[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 /** 2 * PressThis App 3 * 4 */ 5 ( function( $, window ) { 6 var PressThis = function() { 7 var editor, $mediaList, $mediaThumbWrap, 8 $window = $( window ), 9 $document = $( document ), 10 saveAlert = false, 11 sidebarIsOpen = false, 12 settings = window.wpPressThisConfig || {}, 13 data = window.wpPressThisData || {}, 14 smallestWidth = 128, 15 hasSetFocus = false, 16 catsCache = [], 17 isOffScreen = 'is-off-screen', 18 isHidden = 'is-hidden', 19 offscreenHidden = isOffScreen + ' ' + isHidden, 20 iOS = /iPad|iPod|iPhone/.test( window.navigator.userAgent ), 21 $textEditor = $( '#pressthis' ), 22 textEditor = $textEditor[0], 23 textEditorMinHeight = 600, 24 textLength = 0, 25 transitionEndEvent = ( function() { 26 var style = document.documentElement.style; 27 28 if ( typeof style.transition !== 'undefined' ) { 29 return 'transitionend'; 30 } 31 32 if ( typeof style.WebkitTransition !== 'undefined' ) { 33 return 'webkitTransitionEnd'; 34 } 35 36 return false; 37 }() ); 38 39 /* *************************************************************** 40 * HELPER FUNCTIONS 41 *************************************************************** */ 42 43 /** 44 * Emulates our PHP __() gettext function, powered by the strings exported in pressThisL10n. 45 * 46 * @param key string Key of the string to be translated, as found in pressThisL10n. 47 * @returns string Original or translated string, or empty string if no key. 48 */ 49 function __( key ) { 50 if ( key && window.pressThisL10n ) { 51 return window.pressThisL10n[key] || key; 52 } 53 54 return key || ''; 55 } 56 57 /** 58 * Allow only HTTP or protocol relative URLs. 59 * 60 * @param url string The URL. 61 * @returns string Processed URL. 62 */ 63 function checkUrl( url ) { 64 url = $.trim( url || '' ); 65 66 if ( /^(?:https?:)?\/\//.test( url ) ) { 67 url = wp.sanitize.stripTags( url ); 68 return url.replace( /["\\]+/g, '' ); 69 } 70 71 return ''; 72 } 73 74 /** 75 * Show UX spinner 76 */ 77 function showSpinner() { 78 $( '.spinner' ).addClass( 'is-active' ); 79 $( '.post-actions button' ).attr( 'disabled', 'disabled' ); 80 } 81 82 /** 83 * Hide UX spinner 84 */ 85 function hideSpinner() { 86 $( '.spinner' ).removeClass( 'is-active' ); 87 $( '.post-actions button' ).removeAttr( 'disabled' ); 88 } 89 90 function textEditorResize( reset ) { 91 var pageYOffset, height; 92 93 if ( editor && ! editor.isHidden() ) { 94 return; 95 } 96 97 reset = ( reset === 'reset' ) || ( textLength && textLength > textEditor.value.length ); 98 height = textEditor.style.height; 99 100 if ( reset ) { 101 pageYOffset = window.pageYOffset; 102 103 textEditor.style.height = 'auto'; 104 textEditor.style.height = Math.max( textEditor.scrollHeight, textEditorMinHeight ) + 'px'; 105 window.scrollTo( window.pageXOffset, pageYOffset ); 106 } else if ( parseInt( textEditor.style.height, 10 ) < textEditor.scrollHeight ) { 107 textEditor.style.height = textEditor.scrollHeight + 'px'; 108 } 109 110 textLength = textEditor.value.length; 111 } 112 113 function mceGetCursorOffset() { 114 if ( ! editor ) { 115 return false; 116 } 117 118 var node = editor.selection.getNode(), 119 range, view, offset; 120 121 if ( editor.wp && editor.wp.getView && ( view = editor.wp.getView( node ) ) ) { 122 offset = view.getBoundingClientRect(); 123 } else { 124 range = editor.selection.getRng(); 125 126 try { 127 offset = range.getClientRects()[0]; 128 } catch( er ) {} 129 130 if ( ! offset ) { 131 offset = node.getBoundingClientRect(); 132 } 133 } 134 135 return offset.height ? offset : false; 136 } 137 138 // Make sure the caret is always visible. 139 function mceKeyup( event ) { 140 var VK = window.tinymce.util.VK, 141 key = event.keyCode; 142 143 // Bail on special keys. 144 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 ) ) { 145 return; 146 // OS keys, function keys, num lock, scroll lock 147 } else if ( ( key >= 91 && key <= 93 ) || ( key >= 112 && key <= 123 ) || key === 144 || key === 145 ) { 148 return; 149 } 150 151 mceScroll( key ); 152 } 153 154 function mceScroll( key ) { 155 var cursorTop, cursorBottom, editorBottom, 156 offset = mceGetCursorOffset(), 157 bufferTop = 50, 158 bufferBottom = 65, 159 VK = window.tinymce.util.VK; 160 161 if ( ! offset ) { 162 return; 163 } 164 165 cursorTop = offset.top + editor.iframeElement.getBoundingClientRect().top; 166 cursorBottom = cursorTop + offset.height; 167 cursorTop = cursorTop - bufferTop; 168 cursorBottom = cursorBottom + bufferBottom; 169 editorBottom = $window.height(); 170 171 // Don't scroll if the node is taller than the visible part of the editor 172 if ( editorBottom < offset.height ) { 173 return; 174 } 175 176 if ( cursorTop < 0 && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) { 177 window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset ); 178 } else if ( cursorBottom > editorBottom ) { 179 window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom ); 180 } 181 } 182 183 /** 184 * Replace emoji images with chars and sanitize the text content. 185 */ 186 function getTitleText() { 187 var $element = $( '#title-container' ); 188 189 $element.find( 'img.emoji' ).each( function() { 190 var $image = $( this ); 191 $image.replaceWith( $( '<span>' ).text( $image.attr( 'alt' ) ) ); 192 }); 193 194 return wp.sanitize.sanitizeText( $element.text() ); 195 } 196 197 /** 198 * Prepare the form data for saving. 199 */ 200 function prepareFormData() { 201 var $form = $( '#pressthis-form' ), 202 $input = $( '<input type="hidden" name="post_category[]" value="">' ); 203 204 editor && editor.save(); 205 206 $( '#post_title' ).val( getTitleText() ); 207 208 // Make sure to flush out the tags with tagBox before saving 209 if ( window.tagBox ) { 210 $( 'div.tagsdiv' ).each( function() { 211 window.tagBox.flushTags( this, false, 1 ); 212 } ); 213 } 214 215 // Get selected categories 216 $( '.categories-select .category' ).each( function( i, element ) { 217 var $cat = $( element ); 218 219 if ( $cat.hasClass( 'selected' ) ) { 220 // Have to append a node as we submit the actual form on preview 221 $form.append( $input.clone().val( $cat.attr( 'data-term-id' ) || '' ) ); 222 } 223 }); 224 } 225 226 /** 227 * Submit the post form via AJAX, and redirect to the proper screen if published vs saved as a draft. 228 * 229 * @param action string publish|draft 230 */ 231 function submitPost( action ) { 232 var data; 233 234 saveAlert = false; 235 showSpinner(); 236 237 if ( 'publish' === action ) { 238 $( '#post_status' ).val( 'publish' ); 239 } 240 241 prepareFormData(); 242 data = $( '#pressthis-form' ).serialize(); 243 244 $.ajax( { 245 type: 'post', 246 url: window.ajaxurl, 247 data: data 248 }).always( function() { 249 hideSpinner(); 250 clearNotices(); 251 $( '.publish-button' ).removeClass( 'is-saving' ); 252 }).done( function( response ) { 253 if ( ! response.success ) { 254 renderError( response.data.errorMessage ); 255 } else if ( response.data.redirect ) { 256 if ( window.opener && ( settings.redirInParent || response.data.force ) ) { 257 try { 258 window.opener.location.href = response.data.redirect; 259 260 window.setTimeout( function() { 261 window.self.close(); 262 }, 200 ); 263 } catch( er ) { 264 window.location.href = response.data.redirect; 265 } 266 } else { 267 window.location.href = response.data.redirect; 268 } 269 } 270 }).fail( function() { 271 renderError( __( 'serverError' ) ); 272 }); 273 } 274 275 /** 276 * Inserts the media a user has selected from the presented list inside the editor, as an image or embed, based on type 277 * 278 * @param type string img|embed 279 * @param src string Source URL 280 * @param link string Optional destination link, for images (defaults to src) 281 */ 282 function insertSelectedMedia( $element ) { 283 var src, link, newContent = ''; 284 285 src = checkUrl( $element.attr( 'data-wp-src' ) || '' ); 286 link = checkUrl( data.u ); 287 288 if ( $element.hasClass( 'is-image' ) ) { 289 if ( ! link ) { 290 link = src; 291 } 292 293 newContent = '<a href="' + link + '"><img class="alignnone size-full" src="' + src + '" alt="" /></a>'; 294 } else { 295 newContent = '[embed]' + src + '[/embed]'; 296 } 297 298 if ( editor && ! editor.isHidden() ) { 299 if ( ! hasSetFocus ) { 300 editor.setContent( '<p>' + newContent + '</p>' + editor.getContent() ); 301 } else { 302 editor.execCommand( 'mceInsertContent', false, newContent ); 303 } 304 } else if ( window.QTags ) { 305 window.QTags.insertContent( newContent ); 306 } 307 } 308 309 /** 310 * Save a new user-generated category via AJAX 311 */ 312 function saveNewCategory() { 313 var data, 314 name = $( '#new-category' ).val(); 315 316 if ( ! name ) { 317 return; 318 } 319 320 data = { 321 action: 'press-this-add-category', 322 post_id: $( '#post_ID' ).val() || 0, 323 name: name, 324 new_cat_nonce: $( '#_ajax_nonce-add-category' ).val() || '', 325 parent: $( '#new-category-parent' ).val() || 0 326 }; 327 328 $.post( window.ajaxurl, data, function( response ) { 329 if ( ! response.success ) { 330 renderError( response.data.errorMessage ); 331 } else { 332 var $parent, $ul, 333 $wrap = $( 'ul.categories-select' ); 334 335 $.each( response.data, function( i, newCat ) { 336 var $node = $( '<li>' ).append( $( '<div class="category selected" tabindex="0" role="checkbox" aria-checked="true">' ) 337 .attr( 'data-term-id', newCat.term_id ) 338 .text( newCat.name ) ); 339 340 if ( newCat.parent ) { 341 if ( ! $ul || ! $ul.length ) { 342 $parent = $wrap.find( 'div[data-term-id="' + newCat.parent + '"]' ).parent(); 343 $ul = $parent.find( 'ul.children:first' ); 344 345 if ( ! $ul.length ) { 346 $ul = $( '<ul class="children">' ).appendTo( $parent ); 347 } 348 } 349 350 $ul.prepend( $node ); 351 } else { 352 $wrap.prepend( $node ); 353 } 354 355 $node.focus(); 356 } ); 357 358 refreshCatsCache(); 359 } 360 } ); 361 } 362 363 /* *************************************************************** 364 * RENDERING FUNCTIONS 365 *************************************************************** */ 366 367 /** 368 * Hide the form letting users enter a URL to be scanned, if a URL was already passed. 369 */ 370 function renderToolsVisibility() { 371 if ( data.hasData ) { 372 $( '#scanbar' ).hide(); 373 } 374 } 375 376 /** 377 * Render error notice 378 * 379 * @param msg string Notice/error message 380 * @param error string error|notice CSS class for display 381 */ 382 function renderNotice( msg, error ) { 383 var $alerts = $( '.editor-wrapper div.alerts' ), 384 className = error ? 'is-error' : 'is-notice'; 385 386 $alerts.append( $( '<p class="alert ' + className + '">' ).text( msg ) ); 387 } 388 389 /** 390 * Render error notice 391 * 392 * @param msg string Error message 393 */ 394 function renderError( msg ) { 395 renderNotice( msg, true ); 396 } 397 398 function clearNotices() { 399 $( 'div.alerts' ).empty(); 400 } 401 402 /** 403 * Render notices on page load, if any already 404 */ 405 function renderStartupNotices() { 406 // Render errors sent in the data, if any 407 if ( data.errors ) { 408 $.each( data.errors, function( i, msg ) { 409 renderError( msg ); 410 } ); 411 } 412 } 413 414 /** 415 * Add an image to the list of found images. 416 */ 417 function addImg( src, displaySrc, i ) { 418 var $element = $mediaThumbWrap.clone().addClass( 'is-image' ); 419 420 $element.attr( 'data-wp-src', src ).css( 'background-image', 'url(' + displaySrc + ')' ) 421 .find( 'span' ).text( __( 'suggestedImgAlt' ).replace( '%d', i + 1 ) ); 422 423 $mediaList.append( $element ); 424 } 425 426 /** 427 * Render the detected images and embed for selection, if any 428 */ 429 function renderDetectedMedia() { 430 var found = 0; 431 432 $mediaList = $( 'ul.media-list' ); 433 $mediaThumbWrap = $( '<li class="suggested-media-thumbnail" tabindex="0"><span class="screen-reader-text"></span></li>' ); 434 435 if ( data._embeds ) { 436 $.each( data._embeds, function ( i, src ) { 437 var displaySrc = '', 438 cssClass = '', 439 $element = $mediaThumbWrap.clone().addClass( 'is-embed' ); 440 441 src = checkUrl( src ); 442 443 if ( src.indexOf( 'youtube.com/' ) > -1 ) { 444 displaySrc = 'https://i.ytimg.com/vi/' + src.replace( /.+v=([^&]+).*/, '$1' ) + '/hqdefault.jpg'; 445 cssClass += ' is-video'; 446 } else if ( src.indexOf( 'youtu.be/' ) > -1 ) { 447 displaySrc = 'https://i.ytimg.com/vi/' + src.replace( /\/([^\/])$/, '$1' ) + '/hqdefault.jpg'; 448 cssClass += ' is-video'; 449 } else if ( src.indexOf( 'dailymotion.com' ) > -1 ) { 450 displaySrc = src.replace( '/video/', '/thumbnail/video/' ); 451 cssClass += ' is-video'; 452 } else if ( src.indexOf( 'soundcloud.com' ) > -1 ) { 453 cssClass += ' is-audio'; 454 } else if ( src.indexOf( 'twitter.com' ) > -1 ) { 455 cssClass += ' is-tweet'; 456 } else { 457 cssClass += ' is-video'; 458 } 459 460 $element.attr( 'data-wp-src', src ).find( 'span' ).text( __( 'suggestedEmbedAlt' ).replace( '%d', i + 1 ) ); 461 462 if ( displaySrc ) { 463 $element.css( 'background-image', 'url(' + displaySrc + ')' ); 464 } 465 466 $mediaList.append( $element ); 467 found++; 468 } ); 469 } 470 471 if ( data._images ) { 472 $.each( data._images, function( i, src ) { 473 var displaySrc, img = new Image(); 474 475 src = checkUrl( src ); 476 displaySrc = src.replace( /^(http[^\?]+)(\?.*)?$/, '$1' ); 477 478 if ( src.indexOf( 'files.wordpress.com/' ) > -1 ) { 479 displaySrc = displaySrc.replace( /\?.*$/, '' ) + '?w=' + smallestWidth; 480 } else if ( src.indexOf( 'gravatar.com/' ) > -1 ) { 481 displaySrc = displaySrc.replace( /\?.*$/, '' ) + '?s=' + smallestWidth; 482 } else { 483 displaySrc = src; 484 } 485 486 img.onload = function() { 487 if ( ( img.width && img.width < 256 ) || 488 ( img.height && img.height < 128 ) ) { 489 490 return; 491 } 492 493 addImg( src, displaySrc, i ); 494 }; 495 496 img.src = src; 497 found++; 498 } ); 499 } 500 501 if ( found ) { 502 $( '.media-list-container' ).addClass( 'has-media' ); 503 } 504 } 505 506 /* *************************************************************** 507 * MONITORING FUNCTIONS 508 *************************************************************** */ 509 510 /** 511 * Interactive navigation behavior for the options modal (post format, tags, categories) 512 */ 513 function monitorOptionsModal() { 514 var $postOptions = $( '.post-options' ), 515 $postOption = $( '.post-option' ), 516 $settingModal = $( '.setting-modal' ), 517 $modalClose = $( '.modal-close' ); 518 519 $postOption.on( 'click', function() { 520 var index = $( this ).index(), 521 $targetSettingModal = $settingModal.eq( index ); 522 523 $postOptions.addClass( isOffScreen ) 524 .one( transitionEndEvent, function() { 525 $( this ).addClass( isHidden ); 526 } ); 527 528 $targetSettingModal.removeClass( offscreenHidden ) 529 .one( transitionEndEvent, function() { 530 $( this ).find( '.modal-close' ).focus(); 531 } ); 532 } ); 533 534 $modalClose.on( 'click', function() { 535 var $targetSettingModal = $( this ).parent(), 536 index = $targetSettingModal.index(); 537 538 $postOptions.removeClass( offscreenHidden ); 539 $targetSettingModal.addClass( isOffScreen ); 540 541 if ( transitionEndEvent ) { 542 $targetSettingModal.one( transitionEndEvent, function() { 543 $( this ).addClass( isHidden ); 544 $postOption.eq( index - 1 ).focus(); 545 } ); 546 } else { 547 setTimeout( function() { 548 $targetSettingModal.addClass( isHidden ); 549 $postOption.eq( index - 1 ).focus(); 550 }, 350 ); 551 } 552 } ); 553 } 554 555 /** 556 * Interactive behavior for the sidebar toggle, to show the options modals 557 */ 558 function openSidebar() { 559 sidebarIsOpen = true; 560 561 $( '.options' ).removeClass( 'closed' ).addClass( 'open' ); 562 $( '.press-this-actions, #scanbar' ).addClass( isHidden ); 563 $( '.options-panel-back' ).removeClass( isHidden ); 564 565 $( '.options-panel' ).removeClass( offscreenHidden ) 566 .one( transitionEndEvent, function() { 567 $( '.post-option:first' ).focus(); 568 } ); 569 } 570 571 function closeSidebar() { 572 sidebarIsOpen = false; 573 574 $( '.options' ).removeClass( 'open' ).addClass( 'closed' ); 575 $( '.options-panel-back' ).addClass( isHidden ); 576 $( '.press-this-actions, #scanbar' ).removeClass( isHidden ); 577 578 $( '.options-panel' ).addClass( isOffScreen ) 579 .one( transitionEndEvent, function() { 580 $( this ).addClass( isHidden ); 581 // Reset to options list 582 $( '.post-options' ).removeClass( offscreenHidden ); 583 $( '.setting-modal').addClass( offscreenHidden ); 584 }); 585 } 586 587 /** 588 * Interactive behavior for the post title's field placeholder 589 */ 590 function monitorPlaceholder() { 591 var $titleField = $( '#title-container' ), 592 $placeholder = $( '.post-title-placeholder' ); 593 594 $titleField.on( 'focus', function() { 595 $placeholder.addClass( 'is-hidden' ); 596 }).on( 'blur', function() { 597 if ( ! $titleField.text() && ! $titleField.html() ) { 598 $placeholder.removeClass( 'is-hidden' ); 599 } 600 }).on( 'keyup', function() { 601 saveAlert = true; 602 }).on( 'paste', function( event ) { 603 var text, range, 604 clipboard = event.originalEvent.clipboardData || window.clipboardData; 605 606 if ( clipboard ) { 607 try{ 608 text = clipboard.getData( 'Text' ) || clipboard.getData( 'text/plain' ); 609 610 if ( text ) { 611 text = $.trim( text.replace( /\s+/g, ' ' ) ); 612 613 if ( window.getSelection ) { 614 range = window.getSelection().getRangeAt(0); 615 616 if ( range ) { 617 if ( ! range.collapsed ) { 618 range.deleteContents(); 619 } 620 621 range.insertNode( document.createTextNode( text ) ); 622 } 623 } else if ( document.selection ) { 624 range = document.selection.createRange(); 625 626 if ( range ) { 627 range.text = text; 628 } 629 } 630 } 631 } catch ( er ) {} 632 633 event.preventDefault(); 634 } 635 636 saveAlert = true; 637 638 setTimeout( function() { 639 $titleField.text( getTitleText() ); 640 }, 50 ); 641 }); 642 643 if ( $titleField.text() || $titleField.html() ) { 644 $placeholder.addClass('is-hidden'); 645 } 646 } 647 648 function toggleCatItem( $element ) { 649 if ( $element.hasClass( 'selected' ) ) { 650 $element.removeClass( 'selected' ).attr( 'aria-checked', 'false' ); 651 } else { 652 $element.addClass( 'selected' ).attr( 'aria-checked', 'true' ); 653 } 654 } 655 656 function monitorCatList() { 657 $( '.categories-select' ).on( 'click.press-this keydown.press-this', function( event ) { 658 var $element = $( event.target ); 659 660 if ( $element.is( 'div.category' ) ) { 661 if ( event.type === 'keydown' && event.keyCode !== 32 ) { 662 return; 663 } 664 665 toggleCatItem( $element ); 666 event.preventDefault(); 667 } 668 }); 669 } 670 671 function splitButtonClose() { 672 $( '.split-button' ).removeClass( 'is-open' ); 673 $( '.split-button-toggle' ).attr( 'aria-expanded', 'false' ); 674 } 675 676 /* *************************************************************** 677 * PROCESSING FUNCTIONS 678 *************************************************************** */ 679 680 /** 681 * Calls all the rendring related functions to happen on page load 682 */ 683 function render(){ 684 // We're on! 685 renderToolsVisibility(); 686 renderDetectedMedia(); 687 renderStartupNotices(); 688 689 if ( window.tagBox ) { 690 window.tagBox.init(); 691 } 692 693 // iOS doesn't fire click events on "standard" elements without this... 694 if ( iOS ) { 695 $( document.body ).css( 'cursor', 'pointer' ); 696 } 697 } 698 699 /** 700 * Set app events and other state monitoring related code. 701 */ 702 function monitor() { 703 var $splitButton = $( '.split-button' ); 704 705 $document.on( 'tinymce-editor-init', function( event, ed ) { 706 editor = ed; 707 708 editor.on( 'nodechange', function() { 709 hasSetFocus = true; 710 }); 711 712 editor.on( 'focus', function() { 713 splitButtonClose(); 714 }); 715 716 editor.on( 'show', function() { 717 setTimeout( function() { 718 editor.execCommand( 'wpAutoResize' ); 719 }, 300 ); 720 }); 721 722 editor.on( 'hide', function() { 723 setTimeout( function() { 724 textEditorResize( 'reset' ); 725 }, 100 ); 726 }); 727 728 editor.on( 'keyup', mceKeyup ); 729 editor.on( 'undo redo', mceScroll ); 730 731 }).on( 'click.press-this keypress.press-this', '.suggested-media-thumbnail', function( event ) { 732 if ( event.type === 'click' || event.keyCode === 13 ) { 733 insertSelectedMedia( $( this ) ); 734 } 735 }).on( 'click.press-this', function( event ) { 736 if ( ! $( event.target ).closest( 'button' ).hasClass( 'split-button-toggle' ) ) { 737 splitButtonClose(); 738 } 739 }); 740 741 // Publish, Draft and Preview buttons 742 $( '.post-actions' ).on( 'click.press-this', function( event ) { 743 var location, 744 $target = $( event.target ), 745 $button = $target.closest( 'button' ); 746 747 if ( $button.length ) { 748 if ( $button.hasClass( 'draft-button' ) ) { 749 $( '.publish-button' ).addClass( 'is-saving' ); 750 submitPost( 'draft' ); 751 } else if ( $button.hasClass( 'publish-button' ) ) { 752 $button.addClass( 'is-saving' ); 753 754 if ( window.history.replaceState ) { 755 location = window.location.href; 756 location += ( location.indexOf( '?' ) !== -1 ) ? '&' : '?'; 757 location += 'wp-press-this-reload=true'; 758 759 window.history.replaceState( null, null, location ); 760 } 761 762 submitPost( 'publish' ); 763 } else if ( $button.hasClass( 'preview-button' ) ) { 764 prepareFormData(); 765 window.opener && window.opener.focus(); 766 767 $( '#wp-preview' ).val( 'dopreview' ); 768 $( '#pressthis-form' ).attr( 'target', '_blank' ).submit().attr( 'target', '' ); 769 $( '#wp-preview' ).val( '' ); 770 } else if ( $button.hasClass( 'standard-editor-button' ) ) { 771 $( '.publish-button' ).addClass( 'is-saving' ); 772 $( '#pt-force-redirect' ).val( 'true' ); 773 submitPost( 'draft' ); 774 } else if ( $button.hasClass( 'split-button-toggle' ) ) { 775 if ( $splitButton.hasClass( 'is-open' ) ) { 776 $splitButton.removeClass( 'is-open' ); 777 $button.attr( 'aria-expanded', 'false' ); 778 } else { 779 $splitButton.addClass( 'is-open' ); 780 $button.attr( 'aria-expanded', 'true' ); 781 } 782 } 783 } 784 }); 785 786 monitorOptionsModal(); 787 monitorPlaceholder(); 788 monitorCatList(); 789 790 $( '.options' ).on( 'click.press-this', function() { 791 if ( $( this ).hasClass( 'open' ) ) { 792 closeSidebar(); 793 } else { 794 openSidebar(); 795 } 796 }); 797 798 // Close the sidebar when focus moves outside of it. 799 $( '.options-panel, .options-panel-back' ).on( 'focusout.press-this', function() { 800 setTimeout( function() { 801 var node = document.activeElement, 802 $node = $( node ); 803 804 if ( sidebarIsOpen && node && ! $node.hasClass( 'options-panel-back' ) && 805 ( node.nodeName === 'BODY' || 806 ( ! $node.closest( '.options-panel' ).length && 807 ! $node.closest( '.options' ).length ) ) ) { 808 809 closeSidebar(); 810 } 811 }, 50 ); 812 }); 813 814 $( '#post-formats-select input' ).on( 'change', function() { 815 var $this = $( this ); 816 817 if ( $this.is( ':checked' ) ) { 818 $( '#post-option-post-format' ).text( $( 'label[for="' + $this.attr( 'id' ) + '"]' ).text() || '' ); 819 } 820 } ); 821 822 $window.on( 'beforeunload.press-this', function() { 823 if ( saveAlert || ( editor && editor.isDirty() ) ) { 824 return __( 'saveAlert' ); 825 } 826 } ).on( 'resize.press-this', function() { 827 if ( ! editor || editor.isHidden() ) { 828 textEditorResize( 'reset' ); 829 } 830 }); 831 832 $( 'button.add-cat-toggle' ).on( 'click.press-this', function() { 833 var $this = $( this ); 834 835 $this.toggleClass( 'is-toggled' ); 836 $this.attr( 'aria-expanded', 'false' === $this.attr( 'aria-expanded' ) ? 'true' : 'false' ); 837 $( '.setting-modal .add-category, .categories-search-wrapper' ).toggleClass( 'is-hidden' ); 838 } ); 839 840 $( 'button.add-cat-submit' ).on( 'click.press-this', saveNewCategory ); 841 842 $( '.categories-search' ).on( 'keyup.press-this', function() { 843 var search = $( this ).val().toLowerCase() || ''; 844 845 // Don't search when less thasn 3 extended ASCII chars 846 if ( /[\x20-\xFF]+/.test( search ) && search.length < 2 ) { 847 return; 848 } 849 850 $.each( catsCache, function( i, cat ) { 851 cat.node.removeClass( 'is-hidden searched-parent' ); 852 } ); 853 854 if ( search ) { 855 $.each( catsCache, function( i, cat ) { 856 if ( cat.text.indexOf( search ) === -1 ) { 857 cat.node.addClass( 'is-hidden' ); 858 } else { 859 cat.parents.addClass( 'searched-parent' ); 860 } 861 } ); 862 } 863 } ); 864 865 $textEditor.on( 'focus.press-this input.press-this propertychange.press-this', textEditorResize ); 866 867 return true; 868 } 869 870 function refreshCatsCache() { 871 $( '.categories-select' ).find( 'li' ).each( function() { 872 var $this = $( this ); 873 874 catsCache.push( { 875 node: $this, 876 parents: $this.parents( 'li' ), 877 text: $this.children( '.category' ).text().toLowerCase() 878 } ); 879 } ); 880 } 881 882 // Let's go! 883 $document.ready( function() { 884 render(); 885 monitor(); 886 refreshCatsCache(); 887 }); 888 889 // Expose public methods? 890 return { 891 renderNotice: renderNotice, 892 renderError: renderError 893 }; 894 }; 895 896 window.wp = window.wp || {}; 897 window.wp.pressThis = new PressThis(); 898 899 }( jQuery, window ));
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Sep 24 01:00:03 2017 | Cross-referenced by PHPXref 0.7.1 |