/** * PressThis App * */ ( function( $, window ) { var PressThis = function() { var editor, $mediaList, $mediaThumbWrap, $window = $( window ), $document = $( document ), saveAlert = false, sidebarIsOpen = false, settings = window.wpPressThisConfig || {}, data = window.wpPressThisData || {}, smallestWidth = 128, hasSetFocus = false, catsCache = [], isOffScreen = 'is-off-screen', isHidden = 'is-hidden', offscreenHidden = isOffScreen + ' ' + isHidden, iOS = /iPad|iPod|iPhone/.test( window.navigator.userAgent ), $textEditor = $( '#pressthis' ), textEditor = $textEditor[0], textEditorMinHeight = 600, textLength = 0, transitionEndEvent = ( function() { var style = document.documentElement.style; if ( typeof style.transition !== 'undefined' ) { return 'transitionend'; } if ( typeof style.WebkitTransition !== 'undefined' ) { return 'webkitTransitionEnd'; } return false; }() ); /* *************************************************************** * HELPER FUNCTIONS *************************************************************** */ /** * Emulates our PHP __() gettext function, powered by the strings exported in pressThisL10n. * * @param key string Key of the string to be translated, as found in pressThisL10n. * @returns string Original or translated string, or empty string if no key. */ function __( key ) { if ( key && window.pressThisL10n ) { return window.pressThisL10n[key] || key; } return key || ''; } /** * Allow only HTTP or protocol relative URLs. * * @param url string The URL. * @returns string Processed URL. */ function checkUrl( url ) { url = $.trim( url || '' ); if ( /^(?:https?:)?\/\//.test( url ) ) { url = wp.sanitize.stripTags( url ); return url.replace( /["\\]+/g, '' ); } return ''; } /** * Show UX spinner */ function showSpinner() { $( '.spinner' ).addClass( 'is-active' ); $( '.post-actions button' ).attr( 'disabled', 'disabled' ); } /** * Hide UX spinner */ function hideSpinner() { $( '.spinner' ).removeClass( 'is-active' ); $( '.post-actions button' ).removeAttr( 'disabled' ); } function textEditorResize( reset ) { var pageYOffset, height; if ( editor && ! editor.isHidden() ) { return; } reset = ( reset === 'reset' ) || ( textLength && textLength > textEditor.value.length ); height = textEditor.style.height; if ( reset ) { pageYOffset = window.pageYOffset; textEditor.style.height = 'auto'; textEditor.style.height = Math.max( textEditor.scrollHeight, textEditorMinHeight ) + 'px'; window.scrollTo( window.pageXOffset, pageYOffset ); } else if ( parseInt( textEditor.style.height, 10 ) < textEditor.scrollHeight ) { textEditor.style.height = textEditor.scrollHeight + 'px'; } textLength = textEditor.value.length; } function mceGetCursorOffset() { if ( ! editor ) { return false; } var node = editor.selection.getNode(), range, view, offset; if ( editor.wp && editor.wp.getView && ( view = editor.wp.getView( node ) ) ) { offset = view.getBoundingClientRect(); } else { range = editor.selection.getRng(); try { offset = range.getClientRects()[0]; } catch( er ) {} if ( ! offset ) { offset = node.getBoundingClientRect(); } } return offset.height ? offset : false; } // Make sure the caret is always visible. function mceKeyup( event ) { var VK = window.tinymce.util.VK, key = event.keyCode; // Bail on special keys. if ( key <= 47 && ! ( key === VK.SPACEBAR || key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE || key === VK.UP || key === VK.LEFT || key === VK.DOWN || key === VK.UP ) ) { return; // OS keys, function keys, num lock, scroll lock } else if ( ( key >= 91 && key <= 93 ) || ( key >= 112 && key <= 123 ) || key === 144 || key === 145 ) { return; } mceScroll( key ); } function mceScroll( key ) { var cursorTop, cursorBottom, editorBottom, offset = mceGetCursorOffset(), bufferTop = 50, bufferBottom = 65, VK = window.tinymce.util.VK; if ( ! offset ) { return; } cursorTop = offset.top + editor.iframeElement.getBoundingClientRect().top; cursorBottom = cursorTop + offset.height; cursorTop = cursorTop - bufferTop; cursorBottom = cursorBottom + bufferBottom; editorBottom = $window.height(); // Don't scroll if the node is taller than the visible part of the editor if ( editorBottom < offset.height ) { return; } if ( cursorTop < 0 && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) { window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset ); } else if ( cursorBottom > editorBottom ) { window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom ); } } /** * Replace emoji images with chars and sanitize the text content. */ function getTitleText() { var $element = $( '#title-container' ); $element.find( 'img.emoji' ).each( function() { var $image = $( this ); $image.replaceWith( $( '' ).text( $image.attr( 'alt' ) ) ); }); return wp.sanitize.sanitizeText( $element.text() ); } /** * Prepare the form data for saving. */ function prepareFormData() { var $form = $( '#pressthis-form' ), $input = $( '' ); editor && editor.save(); $( '#post_title' ).val( getTitleText() ); // Make sure to flush out the tags with tagBox before saving if ( window.tagBox ) { $( 'div.tagsdiv' ).each( function() { window.tagBox.flushTags( this, false, 1 ); } ); } // Get selected categories $( '.categories-select .category' ).each( function( i, element ) { var $cat = $( element ); if ( $cat.hasClass( 'selected' ) ) { // Have to append a node as we submit the actual form on preview $form.append( $input.clone().val( $cat.attr( 'data-term-id' ) || '' ) ); } }); } /** * Submit the post form via AJAX, and redirect to the proper screen if published vs saved as a draft. * * @param action string publish|draft */ function submitPost( action ) { var data; saveAlert = false; showSpinner(); if ( 'publish' === action ) { $( '#post_status' ).val( 'publish' ); } prepareFormData(); data = $( '#pressthis-form' ).serialize(); $.ajax( { type: 'post', url: window.ajaxurl, data: data }).always( function() { hideSpinner(); clearNotices(); $( '.publish-button' ).removeClass( 'is-saving' ); }).done( function( response ) { if ( ! response.success ) { renderError( response.data.errorMessage ); } else if ( response.data.redirect ) { if ( window.opener && ( settings.redirInParent || response.data.force ) ) { try { window.opener.location.href = response.data.redirect; window.setTimeout( function() { window.self.close(); }, 200 ); } catch( er ) { window.location.href = response.data.redirect; } } else { window.location.href = response.data.redirect; } } }).fail( function() { renderError( __( 'serverError' ) ); }); } /** * Inserts the media a user has selected from the presented list inside the editor, as an image or embed, based on type * * @param type string img|embed * @param src string Source URL * @param link string Optional destination link, for images (defaults to src) */ function insertSelectedMedia( $element ) { var src, link, newContent = ''; src = checkUrl( $element.attr( 'data-wp-src' ) || '' ); link = checkUrl( data.u ); if ( $element.hasClass( 'is-image' ) ) { if ( ! link ) { link = src; } newContent = ''; } else { newContent = '[embed]' + src + '[/embed]'; } if ( editor && ! editor.isHidden() ) { if ( ! hasSetFocus ) { editor.setContent( '

' + newContent + '

' + editor.getContent() ); } else { editor.execCommand( 'mceInsertContent', false, newContent ); } } else if ( window.QTags ) { window.QTags.insertContent( newContent ); } } /** * Save a new user-generated category via AJAX */ function saveNewCategory() { var data, name = $( '#new-category' ).val(); if ( ! name ) { return; } data = { action: 'press-this-add-category', post_id: $( '#post_ID' ).val() || 0, name: name, new_cat_nonce: $( '#_ajax_nonce-add-category' ).val() || '', parent: $( '#new-category-parent' ).val() || 0 }; $.post( window.ajaxurl, data, function( response ) { if ( ! response.success ) { renderError( response.data.errorMessage ); } else { var $parent, $ul, $wrap = $( 'ul.categories-select' ); $.each( response.data, function( i, newCat ) { var $node = $( '
  • ' ).append( $( '