[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

title

Body

[close]

/wp-includes/js/tinymce/plugins/wordpress/ -> plugin.js (source)

   1  /* global getUserSetting, setUserSetting */
   2  ( function( tinymce ) {
   3  // Set the minimum value for the modals z-index higher than #wpadminbar (100000)
   4  if ( ! tinymce.ui.FloatPanel.zIndex || tinymce.ui.FloatPanel.zIndex < 100100 ) {
   5      tinymce.ui.FloatPanel.zIndex = 100100;
   6  }
   7  
   8  tinymce.PluginManager.add( 'wordpress', function( editor ) {
   9      var wpAdvButton, style,
  10          DOM = tinymce.DOM,
  11          each = tinymce.each,
  12          __ = editor.editorManager.i18n.translate,
  13          $ = window.jQuery,
  14          wp = window.wp,
  15          hasWpautop = ( wp && wp.editor && wp.editor.autop && editor.getParam( 'wpautop', true ) ),
  16          wpTooltips = false;
  17  
  18      if ( $ ) {
  19          $( document ).triggerHandler( 'tinymce-editor-setup', [ editor ] );
  20      }
  21  
  22  	function toggleToolbars( state ) {
  23          var initial, toolbars, iframeHeight,
  24              pixels = 0,
  25              classicBlockToolbar = tinymce.$( '.block-library-classic__toolbar' );
  26  
  27          if ( state === 'hide' ) {
  28              initial = true;
  29          } else if ( classicBlockToolbar.length && ! classicBlockToolbar.hasClass( 'has-advanced-toolbar' ) ) {
  30              // Show the second, third, etc. toolbar rows in the Classic block instance.
  31              classicBlockToolbar.addClass( 'has-advanced-toolbar' );
  32              state = 'show';
  33          }
  34  
  35          if ( editor.theme.panel ) {
  36              toolbars = editor.theme.panel.find('.toolbar:not(.menubar)');
  37          }
  38  
  39          if ( toolbars && toolbars.length > 1 ) {
  40              if ( ! state && toolbars[1].visible() ) {
  41                  state = 'hide';
  42              }
  43  
  44              each( toolbars, function( toolbar, i ) {
  45                  if ( i > 0 ) {
  46                      if ( state === 'hide' ) {
  47                          toolbar.hide();
  48                          pixels += 34;
  49                      } else {
  50                          toolbar.show();
  51                          pixels -= 34;
  52                      }
  53                  }
  54              });
  55          }
  56  
  57          // Resize editor iframe, not needed for iOS and inline instances.
  58          // Don't resize if the editor is in a hidden container.
  59          if ( pixels && ! tinymce.Env.iOS && editor.iframeElement && editor.iframeElement.clientHeight ) {
  60              iframeHeight = editor.iframeElement.clientHeight + pixels;
  61  
  62              // Keep min-height.
  63              if ( iframeHeight > 50  ) {
  64                  DOM.setStyle( editor.iframeElement, 'height', iframeHeight );
  65              }
  66          }
  67  
  68          if ( ! initial ) {
  69              if ( state === 'hide' ) {
  70                  setUserSetting( 'hidetb', '0' );
  71                  wpAdvButton && wpAdvButton.active( false );
  72              } else {
  73                  setUserSetting( 'hidetb', '1' );
  74                  wpAdvButton && wpAdvButton.active( true );
  75              }
  76          }
  77  
  78          editor.fire( 'wp-toolbar-toggle' );
  79      }
  80  
  81      // Add the kitchen sink button :)
  82      editor.addButton( 'wp_adv', {
  83          tooltip: 'Toolbar Toggle',
  84          cmd: 'WP_Adv',
  85          onPostRender: function() {
  86              wpAdvButton = this;
  87              wpAdvButton.active( getUserSetting( 'hidetb' ) === '1' );
  88          }
  89      });
  90  
  91      // Hide the toolbars after loading
  92      editor.on( 'PostRender', function() {
  93          if ( editor.getParam( 'wordpress_adv_hidden', true ) && getUserSetting( 'hidetb', '0' ) === '0' ) {
  94              toggleToolbars( 'hide' );
  95          } else {
  96              tinymce.$( '.block-library-classic__toolbar' ).addClass( 'has-advanced-toolbar' );
  97          }
  98      });
  99  
 100      editor.addCommand( 'WP_Adv', function() {
 101          toggleToolbars();
 102      });
 103  
 104      editor.on( 'focus', function() {
 105          window.wpActiveEditor = editor.id;
 106      });
 107  
 108      editor.on( 'BeforeSetContent', function( event ) {
 109          var title;
 110  
 111          if ( event.content ) {
 112              if ( event.content.indexOf( '<!--more' ) !== -1 ) {
 113                  title = __( 'Read more...' );
 114  
 115                  event.content = event.content.replace( /<!--more(.*?)-->/g, function( match, moretext ) {
 116                      return '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="more" data-wp-more-text="' + moretext + '" ' +
 117                          'class="wp-more-tag mce-wp-more" alt="" title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />';
 118                  });
 119              }
 120  
 121              if ( event.content.indexOf( '<!--nextpage-->' ) !== -1 ) {
 122                  title = __( 'Page break' );
 123  
 124                  event.content = event.content.replace( /<!--nextpage-->/g,
 125                      '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="nextpage" class="wp-more-tag mce-wp-nextpage" ' +
 126                          'alt="" title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />' );
 127              }
 128  
 129              if ( event.load && event.format !== 'raw' ) {
 130                  if ( hasWpautop ) {
 131                      event.content = wp.editor.autop( event.content );
 132                  } else {
 133                      // Prevent creation of paragraphs out of multiple HTML comments.
 134                      event.content = event.content.replace( /-->\s+<!--/g, '--><!--' );
 135                  }
 136              }
 137  
 138              if ( event.content.indexOf( '<script' ) !== -1 || event.content.indexOf( '<style' ) !== -1 ) {
 139                  event.content = event.content.replace( /<(script|style)[^>]*>[\s\S]*?<\/\1>/g, function( match, tag ) {
 140                      return '<img ' +
 141                          'src="' + tinymce.Env.transparentSrc + '" ' +
 142                          'data-wp-preserve="' + encodeURIComponent( match ) + '" ' +
 143                          'data-mce-resize="false" ' +
 144                          'data-mce-placeholder="1" '+
 145                          'class="mce-object" ' +
 146                          'width="20" height="20" '+
 147                          'alt="&lt;' + tag + '&gt;" ' +
 148                          'title="&lt;' + tag + '&gt;" ' +
 149                      '/>';
 150                  } );
 151              }
 152          }
 153      });
 154  
 155      editor.on( 'setcontent', function() {
 156          // Remove spaces from empty paragraphs.
 157          editor.$( 'p' ).each( function( i, node ) {
 158              if ( node.innerHTML && node.innerHTML.length < 10 ) {
 159                  var html = tinymce.trim( node.innerHTML );
 160  
 161                  if ( ! html || html === '&nbsp;' ) {
 162                      node.innerHTML = ( tinymce.Env.ie && tinymce.Env.ie < 11 ) ? '' : '<br data-mce-bogus="1">';
 163                  }
 164              }
 165          } );
 166      });
 167  
 168      editor.on( 'PostProcess', function( event ) {
 169          if ( event.get ) {
 170              event.content = event.content.replace(/<img[^>]+>/g, function( image ) {
 171                  var match,
 172                      string,
 173                      moretext = '';
 174  
 175                  if ( image.indexOf( 'data-wp-more="more"' ) !== -1 ) {
 176                      if ( match = image.match( /data-wp-more-text="([^"]+)"/ ) ) {
 177                          moretext = match[1];
 178                      }
 179  
 180                      string = '<!--more' + moretext + '-->';
 181                  } else if ( image.indexOf( 'data-wp-more="nextpage"' ) !== -1 ) {
 182                      string = '<!--nextpage-->';
 183                  } else if ( image.indexOf( 'data-wp-preserve' ) !== -1 ) {
 184                      if ( match = image.match( / data-wp-preserve="([^"]+)"/ ) ) {
 185                          string = decodeURIComponent( match[1] );
 186                      }
 187                  }
 188  
 189                  return string || image;
 190              });
 191          }
 192      });
 193  
 194      // Display the tag name instead of img in element path
 195      editor.on( 'ResolveName', function( event ) {
 196          var attr;
 197  
 198          if ( event.target.nodeName === 'IMG' && ( attr = editor.dom.getAttrib( event.target, 'data-wp-more' ) ) ) {
 199              event.name = attr;
 200          }
 201      });
 202  
 203      // Register commands
 204      editor.addCommand( 'WP_More', function( tag ) {
 205          var parent, html, title,
 206              classname = 'wp-more-tag',
 207              dom = editor.dom,
 208              node = editor.selection.getNode(),
 209              rootNode = editor.getBody();
 210  
 211          tag = tag || 'more';
 212          classname += ' mce-wp-' + tag;
 213          title = tag === 'more' ? 'Read more...' : 'Next page';
 214          title = __( title );
 215          html = '<img src="' + tinymce.Env.transparentSrc + '" alt="" title="' + title + '" class="' + classname + '" ' +
 216              'data-wp-more="' + tag + '" data-mce-resize="false" data-mce-placeholder="1" />';
 217  
 218          // Most common case
 219          if ( node === rootNode || ( node.nodeName === 'P' && node.parentNode === rootNode ) ) {
 220              editor.insertContent( html );
 221              return;
 222          }
 223  
 224          // Get the top level parent node
 225          parent = dom.getParent( node, function( found ) {
 226              if ( found.parentNode && found.parentNode === rootNode ) {
 227                  return true;
 228              }
 229  
 230              return false;
 231          }, editor.getBody() );
 232  
 233          if ( parent ) {
 234              if ( parent.nodeName === 'P' ) {
 235                  parent.appendChild( dom.create( 'p', null, html ).firstChild );
 236              } else {
 237                  dom.insertAfter( dom.create( 'p', null, html ), parent );
 238              }
 239  
 240              editor.nodeChanged();
 241          }
 242      });
 243  
 244      editor.addCommand( 'WP_Code', function() {
 245          editor.formatter.toggle('code');
 246      });
 247  
 248      editor.addCommand( 'WP_Page', function() {
 249          editor.execCommand( 'WP_More', 'nextpage' );
 250      });
 251  
 252      editor.addCommand( 'WP_Help', function() {
 253          var access = tinymce.Env.mac ? __( 'Ctrl + Alt + letter:' ) : __( 'Shift + Alt + letter:' ),
 254              meta = tinymce.Env.mac ? __( 'Cmd + letter:' ) : __( 'Ctrl + letter:' ),
 255              table1 = [],
 256              table2 = [],
 257              row1 = {},
 258              row2 = {},
 259              i1 = 0,
 260              i2 = 0,
 261              labels = editor.settings.wp_shortcut_labels,
 262              header, html, dialog, $wrap;
 263  
 264          if ( ! labels ) {
 265              return;
 266          }
 267  
 268          function tr( row, columns ) {
 269              var out = '<tr>';
 270              var i = 0;
 271  
 272              columns = columns || 1;
 273  
 274              each( row, function( text, key ) {
 275                  out += '<td><kbd>' + key + '</kbd></td><td>' + __( text ) + '</td>';
 276                  i++;
 277              });
 278  
 279              while ( i < columns ) {
 280                  out += '<td></td><td></td>';
 281                  i++;
 282              }
 283  
 284              return out + '</tr>';
 285          }
 286  
 287          each ( labels, function( label, name ) {
 288              var letter;
 289  
 290              if ( label.indexOf( 'meta' ) !== -1 ) {
 291                  i1++;
 292                  letter = label.replace( 'meta', '' ).toLowerCase();
 293  
 294                  if ( letter ) {
 295                      row1[ letter ] = name;
 296  
 297                      if ( i1 % 2 === 0 ) {
 298                          table1.push( tr( row1, 2 ) );
 299                          row1 = {};
 300                      }
 301                  }
 302              } else if ( label.indexOf( 'access' ) !== -1 ) {
 303                  i2++;
 304                  letter = label.replace( 'access', '' ).toLowerCase();
 305  
 306                  if ( letter ) {
 307                      row2[ letter ] = name;
 308  
 309                      if ( i2 % 2 === 0 ) {
 310                          table2.push( tr( row2, 2 ) );
 311                          row2 = {};
 312                      }
 313                  }
 314              }
 315          } );
 316  
 317          // Add remaining single entries.
 318          if ( i1 % 2 > 0 ) {
 319              table1.push( tr( row1, 2 ) );
 320          }
 321  
 322          if ( i2 % 2 > 0 ) {
 323              table2.push( tr( row2, 2 ) );
 324          }
 325  
 326          header = [ __( 'Letter' ), __( 'Action' ), __( 'Letter' ), __( 'Action' ) ];
 327          header = '<tr><th>' + header.join( '</th><th>' ) + '</th></tr>';
 328  
 329          html = '<div class="wp-editor-help">';
 330  
 331          // Main section, default and additional shortcuts
 332          html = html +
 333              '<h2>' + __( 'Default shortcuts,' ) + ' ' + meta + '</h2>' +
 334              '<table class="wp-help-th-center fixed">' +
 335                  header +
 336                  table1.join('') +
 337              '</table>' +
 338              '<h2>' + __( 'Additional shortcuts,' ) + ' ' + access + '</h2>' +
 339              '<table class="wp-help-th-center fixed">' +
 340                  header +
 341                  table2.join('') +
 342              '</table>';
 343  
 344          if ( editor.plugins.wptextpattern && ( ! tinymce.Env.ie || tinymce.Env.ie > 8 ) ) {
 345              // Text pattern section
 346              html = html +
 347                  '<h2>' + __( 'When starting a new paragraph with one of these formatting shortcuts followed by a space, the formatting will be applied automatically. Press Backspace or Escape to undo.' ) + '</h2>' +
 348                  '<table class="wp-help-th-center fixed">' +
 349                      tr({ '*':  'Bullet list', '1.':  'Numbered list' }) +
 350                      tr({ '-':  'Bullet list', '1)':  'Numbered list' }) +
 351                  '</table>';
 352  
 353              html = html +
 354                  '<h2>' + __( 'The following formatting shortcuts are replaced when pressing Enter. Press Escape or the Undo button to undo.' ) + '</h2>' +
 355                  '<table class="wp-help-single">' +
 356                      tr({ '>': 'Blockquote' }) +
 357                      tr({ '##': 'Heading 2' }) +
 358                      tr({ '###': 'Heading 3' }) +
 359                      tr({ '####': 'Heading 4' }) +
 360                      tr({ '#####': 'Heading 5' }) +
 361                      tr({ '######': 'Heading 6' }) +
 362                      tr({ '---': 'Horizontal line' }) +
 363                  '</table>';
 364          }
 365  
 366          // Focus management section
 367          html = html +
 368              '<h2>' + __( 'Focus shortcuts:' ) + '</h2>' +
 369              '<table class="wp-help-single">' +
 370                  tr({ 'Alt + F8':  'Inline toolbar (when an image, link or preview is selected)' }) +
 371                  tr({ 'Alt + F9':  'Editor menu (when enabled)' }) +
 372                  tr({ 'Alt + F10': 'Editor toolbar' }) +
 373                  tr({ 'Alt + F11': 'Elements path' }) +
 374              '</table>' +
 375              '<p>' + __( 'To move focus to other buttons use Tab or the arrow keys. To return focus to the editor press Escape or use one of the buttons.' ) + '</p>';
 376  
 377          html += '</div>';
 378  
 379          dialog = editor.windowManager.open( {
 380              title: editor.settings.classic_block_editor ? 'Classic Block Keyboard Shortcuts' : 'Keyboard Shortcuts',
 381              items: {
 382                  type: 'container',
 383                  classes: 'wp-help',
 384                  html: html
 385              },
 386              buttons: {
 387                  text: 'Close',
 388                  onclick: 'close'
 389              }
 390          } );
 391  
 392          if ( dialog.$el ) {
 393              dialog.$el.find( 'div[role="application"]' ).attr( 'role', 'document' );
 394              $wrap = dialog.$el.find( '.mce-wp-help' );
 395  
 396              if ( $wrap[0] ) {
 397                  $wrap.attr( 'tabindex', '0' );
 398                  $wrap[0].focus();
 399                  $wrap.on( 'keydown', function( event ) {
 400                      // Prevent use of: page up, page down, end, home, left arrow, up arrow, right arrow, down arrow
 401                      // in the dialog keydown handler.
 402                      if ( event.keyCode >= 33 && event.keyCode <= 40 ) {
 403                          event.stopPropagation();
 404                      }
 405                  });
 406              }
 407          }
 408      } );
 409  
 410      editor.addCommand( 'WP_Medialib', function() {
 411          if ( wp && wp.media && wp.media.editor ) {
 412              wp.media.editor.open( editor.id );
 413          }
 414      });
 415  
 416      // Register buttons
 417      editor.addButton( 'wp_more', {
 418          tooltip: 'Insert Read More tag',
 419          onclick: function() {
 420              editor.execCommand( 'WP_More', 'more' );
 421          }
 422      });
 423  
 424      editor.addButton( 'wp_page', {
 425          tooltip: 'Page break',
 426          onclick: function() {
 427              editor.execCommand( 'WP_More', 'nextpage' );
 428          }
 429      });
 430  
 431      editor.addButton( 'wp_help', {
 432          tooltip: 'Keyboard Shortcuts',
 433          cmd: 'WP_Help'
 434      });
 435  
 436      editor.addButton( 'wp_code', {
 437          tooltip: 'Code',
 438          cmd: 'WP_Code',
 439          stateSelector: 'code'
 440      });
 441  
 442      // Insert->Add Media
 443      if ( wp && wp.media && wp.media.editor ) {
 444          editor.addButton( 'wp_add_media', {
 445              tooltip: 'Add Media',
 446              icon: 'dashicon dashicons-admin-media',
 447              cmd: 'WP_Medialib'
 448          } );
 449  
 450          editor.addMenuItem( 'add_media', {
 451              text: 'Add Media',
 452              icon: 'wp-media-library',
 453              context: 'insert',
 454              cmd: 'WP_Medialib'
 455          });
 456      }
 457  
 458      // Insert "Read More..."
 459      editor.addMenuItem( 'wp_more', {
 460          text: 'Insert Read More tag',
 461          icon: 'wp_more',
 462          context: 'insert',
 463          onclick: function() {
 464              editor.execCommand( 'WP_More', 'more' );
 465          }
 466      });
 467  
 468      // Insert "Next Page"
 469      editor.addMenuItem( 'wp_page', {
 470          text: 'Page break',
 471          icon: 'wp_page',
 472          context: 'insert',
 473          onclick: function() {
 474              editor.execCommand( 'WP_More', 'nextpage' );
 475          }
 476      });
 477  
 478      editor.on( 'BeforeExecCommand', function(e) {
 479          if ( tinymce.Env.webkit && ( e.command === 'InsertUnorderedList' || e.command === 'InsertOrderedList' ) ) {
 480              if ( ! style ) {
 481                  style = editor.dom.create( 'style', {'type': 'text/css'},
 482                      '#tinymce,#tinymce span,#tinymce li,#tinymce li>span,#tinymce p,#tinymce p>span{font:medium sans-serif;color:#000;line-height:normal;}');
 483              }
 484  
 485              editor.getDoc().head.appendChild( style );
 486          }
 487      });
 488  
 489      editor.on( 'ExecCommand', function( e ) {
 490          if ( tinymce.Env.webkit && style &&
 491              ( 'InsertUnorderedList' === e.command || 'InsertOrderedList' === e.command ) ) {
 492  
 493              editor.dom.remove( style );
 494          }
 495      });
 496  
 497      editor.on( 'init', function() {
 498          var env = tinymce.Env,
 499              bodyClass = ['mceContentBody'], // back-compat for themes that use this in editor-style.css...
 500              doc = editor.getDoc(),
 501              dom = editor.dom;
 502  
 503          if ( env.iOS ) {
 504              dom.addClass( doc.documentElement, 'ios' );
 505          }
 506  
 507          if ( editor.getParam( 'directionality' ) === 'rtl' ) {
 508              bodyClass.push('rtl');
 509              dom.setAttrib( doc.documentElement, 'dir', 'rtl' );
 510          }
 511  
 512          dom.setAttrib( doc.documentElement, 'lang', editor.getParam( 'wp_lang_attr' ) );
 513  
 514          if ( env.ie ) {
 515              if ( parseInt( env.ie, 10 ) === 9 ) {
 516                  bodyClass.push('ie9');
 517              } else if ( parseInt( env.ie, 10 ) === 8 ) {
 518                  bodyClass.push('ie8');
 519              } else if ( env.ie < 8 ) {
 520                  bodyClass.push('ie7');
 521              }
 522          } else if ( env.webkit ) {
 523              bodyClass.push('webkit');
 524          }
 525  
 526          bodyClass.push('wp-editor');
 527  
 528          each( bodyClass, function( cls ) {
 529              if ( cls ) {
 530                  dom.addClass( doc.body, cls );
 531              }
 532          });
 533  
 534          // Remove invalid parent paragraphs when inserting HTML
 535          editor.on( 'BeforeSetContent', function( event ) {
 536              if ( event.content ) {
 537                  event.content = event.content.replace( /<p>\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)( [^>]*)?>/gi, '<$1$2>' )
 538                      .replace( /<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)>\s*<\/p>/gi, '</$1>' );
 539              }
 540          });
 541  
 542          if ( $ ) {
 543              $( document ).triggerHandler( 'tinymce-editor-init', [editor] );
 544          }
 545  
 546          if ( window.tinyMCEPreInit && window.tinyMCEPreInit.dragDropUpload ) {
 547              dom.bind( doc, 'dragstart dragend dragover drop', function( event ) {
 548                  if ( $ ) {
 549                      // Trigger the jQuery handlers.
 550                      $( document ).trigger( new $.Event( event ) );
 551                  }
 552              });
 553          }
 554  
 555          if ( editor.getParam( 'wp_paste_filters', true ) ) {
 556              editor.on( 'PastePreProcess', function( event ) {
 557                  // Remove trailing <br> added by WebKit browsers to the clipboard
 558                  event.content = event.content.replace( /<br class="?Apple-interchange-newline"?>/gi, '' );
 559  
 560                  // In WebKit this is handled by removeWebKitStyles()
 561                  if ( ! tinymce.Env.webkit ) {
 562                      // Remove all inline styles
 563                      event.content = event.content.replace( /(<[^>]+) style="[^"]*"([^>]*>)/gi, '$1$2' );
 564  
 565                      // Put back the internal styles
 566                      event.content = event.content.replace(/(<[^>]+) data-mce-style=([^>]+>)/gi, '$1 style=$2' );
 567                  }
 568              });
 569  
 570              editor.on( 'PastePostProcess', function( event ) {
 571                  // Remove empty paragraphs
 572                  editor.$( 'p', event.node ).each( function( i, node ) {
 573                      if ( dom.isEmpty( node ) ) {
 574                          dom.remove( node );
 575                      }
 576                  });
 577  
 578                  if ( tinymce.isIE ) {
 579                      editor.$( 'a', event.node ).find( 'font, u' ).each( function( i, node ) {
 580                          dom.remove( node, true );
 581                      });
 582                  }
 583              });
 584          }
 585      });
 586  
 587      editor.on( 'SaveContent', function( event ) {
 588          // If editor is hidden, we just want the textarea's value to be saved
 589          if ( ! editor.inline && editor.isHidden() ) {
 590              event.content = event.element.value;
 591              return;
 592          }
 593  
 594          // Keep empty paragraphs :(
 595          event.content = event.content.replace( /<p>(?:<br ?\/?>|\u00a0|\uFEFF| )*<\/p>/g, '<p>&nbsp;</p>' );
 596  
 597          if ( hasWpautop ) {
 598              event.content = wp.editor.removep( event.content );
 599          } else {
 600              // Restore formatting of block boundaries.
 601              event.content = event.content.replace( /-->\s*<!-- wp:/g, '-->\n\n<!-- wp:' );
 602          }
 603      });
 604  
 605      editor.on( 'preInit', function() {
 606          var validElementsSetting = '@[id|accesskey|class|dir|lang|style|tabindex|' +
 607              'title|contenteditable|draggable|dropzone|hidden|spellcheck|translate],' + // Global attributes.
 608              'i,' + // Don't replace <i> with <em> and <b> with <strong> and don't remove them when empty.
 609              'b,' +
 610              'script[src|async|defer|type|charset|crossorigin|integrity]'; // Add support for <script>.
 611  
 612          editor.schema.addValidElements( validElementsSetting );
 613  
 614          if ( tinymce.Env.iOS ) {
 615              editor.settings.height = 300;
 616          }
 617  
 618          each( {
 619              c: 'JustifyCenter',
 620              r: 'JustifyRight',
 621              l: 'JustifyLeft',
 622              j: 'JustifyFull',
 623              q: 'mceBlockQuote',
 624              u: 'InsertUnorderedList',
 625              o: 'InsertOrderedList',
 626              m: 'WP_Medialib',
 627              t: 'WP_More',
 628              d: 'Strikethrough',
 629              p: 'WP_Page',
 630              x: 'WP_Code'
 631          }, function( command, key ) {
 632              editor.shortcuts.add( 'access+' + key, '', command );
 633          } );
 634  
 635          editor.addShortcut( 'meta+s', '', function() {
 636              if ( wp && wp.autosave ) {
 637                  wp.autosave.server.triggerSave();
 638              }
 639          } );
 640  
 641          // Alt+Shift+Z removes a block in the block editor, don't add it to the Classic block.
 642          if ( ! editor.settings.classic_block_editor ) {
 643              editor.addShortcut( 'access+z', '', 'WP_Adv' );
 644          }
 645  
 646          // Workaround for not triggering the global help modal in the block editor by the Classic block shortcut.
 647          editor.on( 'keydown', function( event ) {
 648              var match;
 649  
 650              if ( tinymce.Env.mac ) {
 651                  match = event.ctrlKey && event.altKey && event.code === 'KeyH';
 652              } else {
 653                  match = event.shiftKey && event.altKey && event.code === 'KeyH';
 654              }
 655  
 656              if ( match ) {
 657                  editor.execCommand( 'WP_Help' );
 658                  event.stopPropagation();
 659                  event.stopImmediatePropagation();
 660                  return false;
 661              }
 662  
 663              return true;
 664          });
 665  
 666          if ( window.getUserSetting( 'editor_plain_text_paste_warning' ) > 1 ) {
 667              editor.settings.paste_plaintext_inform = false;
 668          }
 669  
 670          // Change the editor iframe title on MacOS, add the correct help shortcut.
 671          if ( tinymce.Env.mac ) {
 672              tinymce.$( editor.iframeElement ).attr( 'title', __( 'Rich Text Area. Press Control-Option-H for help.' ) );
 673          }
 674      } );
 675  
 676      editor.on( 'PastePlainTextToggle', function( event ) {
 677          // Warn twice, then stop.
 678          if ( event.state === true ) {
 679              var times = parseInt( window.getUserSetting( 'editor_plain_text_paste_warning' ), 10 ) || 0;
 680  
 681              if ( times < 2 ) {
 682                  window.setUserSetting( 'editor_plain_text_paste_warning', ++times );
 683              }
 684          }
 685      });
 686  
 687      editor.on( 'beforerenderui', function() {
 688          if ( editor.theme.panel ) {
 689              each( [ 'button', 'colorbutton', 'splitbutton' ], function( buttonType ) {
 690                  replaceButtonsTooltips( editor.theme.panel.find( buttonType ) );
 691              } );
 692  
 693              addShortcutsToListbox();
 694          }
 695      } );
 696  
 697  	function prepareTooltips() {
 698          var access = 'Shift+Alt+';
 699          var meta = 'Ctrl+';
 700  
 701          wpTooltips = {};
 702  
 703          // For MacOS: ctrl = \u2303, cmd = \u2318, alt = \u2325
 704          if ( tinymce.Env.mac ) {
 705              access = '\u2303\u2325';
 706              meta = '\u2318';
 707          }
 708  
 709          // Some tooltips are translated, others are not...
 710          if ( editor.settings.wp_shortcut_labels ) {
 711              each( editor.settings.wp_shortcut_labels, function( value, tooltip ) {
 712                  var translated = editor.translate( tooltip );
 713  
 714                  value = value.replace( 'access', access ).replace( 'meta', meta );
 715                  wpTooltips[ tooltip ] = value;
 716  
 717                  // Add the translated so we can match all of them.
 718                  if ( tooltip !== translated ) {
 719                      wpTooltips[ translated ] = value;
 720                  }
 721              } );
 722          }
 723      }
 724  
 725  	function getTooltip( tooltip ) {
 726          var translated = editor.translate( tooltip );
 727          var label;
 728  
 729          if ( ! wpTooltips ) {
 730              prepareTooltips();
 731          }
 732  
 733          if ( wpTooltips.hasOwnProperty( translated ) ) {
 734              label = wpTooltips[ translated ];
 735          } else if ( wpTooltips.hasOwnProperty( tooltip ) ) {
 736              label = wpTooltips[ tooltip ];
 737          }
 738  
 739          return label ? translated + ' (' + label + ')' : translated;
 740      }
 741  
 742  	function replaceButtonsTooltips( buttons ) {
 743  
 744          if ( ! buttons ) {
 745              return;
 746          }
 747  
 748          each( buttons, function( button ) {
 749              var tooltip;
 750  
 751              if ( button && button.settings.tooltip ) {
 752                  tooltip = getTooltip( button.settings.tooltip );
 753                  button.settings.tooltip = tooltip;
 754  
 755                  // Override the aria label wiht the translated tooltip + shortcut.
 756                  if ( button._aria && button._aria.label ) {
 757                      button._aria.label = tooltip;
 758                  }
 759              }
 760          } );
 761      }
 762  
 763  	function addShortcutsToListbox() {
 764          // listbox for the "blocks" drop-down
 765          each( editor.theme.panel.find( 'listbox' ), function( listbox ) {
 766              if ( listbox && listbox.settings.text === 'Paragraph' ) {
 767                  each( listbox.settings.values, function( item ) {
 768                      if ( item.text && wpTooltips.hasOwnProperty( item.text ) ) {
 769                          item.shortcut = '(' + wpTooltips[ item.text ] + ')';
 770                      }
 771                  } );
 772              }
 773          } );
 774      }
 775  
 776      /**
 777       * Experimental: create a floating toolbar.
 778       * This functionality will change in the next releases. Not recommended for use by plugins.
 779       */
 780      editor.on( 'preinit', function() {
 781          var Factory = tinymce.ui.Factory,
 782              settings = editor.settings,
 783              activeToolbar,
 784              currentSelection,
 785              timeout,
 786              container = editor.getContainer(),
 787              wpAdminbar = document.getElementById( 'wpadminbar' ),
 788              mceIframe = document.getElementById( editor.id + '_ifr' ),
 789              mceToolbar,
 790              mceStatusbar,
 791              wpStatusbar,
 792              cachedWinSize;
 793  
 794              if ( container ) {
 795                  mceToolbar = tinymce.$( '.mce-toolbar-grp', container )[0];
 796                  mceStatusbar = tinymce.$( '.mce-statusbar', container )[0];
 797              }
 798  
 799              if ( editor.id === 'content' ) {
 800                  wpStatusbar = document.getElementById( 'post-status-info' );
 801              }
 802  
 803  		function create( buttons, bottom ) {
 804              var toolbar,
 805                  toolbarItems = [],
 806                  buttonGroup;
 807  
 808              each( buttons, function( item ) {
 809                  var itemName;
 810                  var tooltip;
 811  
 812  				function bindSelectorChanged() {
 813                      var selection = editor.selection;
 814  
 815                      if ( itemName === 'bullist' ) {
 816                          selection.selectorChanged( 'ul > li', function( state, args ) {
 817                              var i = args.parents.length,
 818                                  nodeName;
 819  
 820                              while ( i-- ) {
 821                                  nodeName = args.parents[ i ].nodeName;
 822  
 823                                  if ( nodeName === 'OL' || nodeName == 'UL' ) {
 824                                      break;
 825                                  }
 826                              }
 827  
 828                              item.active( state && nodeName === 'UL' );
 829                          } );
 830                      }
 831  
 832                      if ( itemName === 'numlist' ) {
 833                          selection.selectorChanged( 'ol > li', function( state, args ) {
 834                              var i = args.parents.length,
 835                                  nodeName;
 836  
 837                              while ( i-- ) {
 838                                  nodeName = args.parents[ i ].nodeName;
 839  
 840                                  if ( nodeName === 'OL' || nodeName === 'UL' ) {
 841                                      break;
 842                                  }
 843                              }
 844  
 845                              item.active( state && nodeName === 'OL' );
 846                          } );
 847                      }
 848  
 849                      if ( item.settings.stateSelector ) {
 850                          selection.selectorChanged( item.settings.stateSelector, function( state ) {
 851                              item.active( state );
 852                          }, true );
 853                      }
 854  
 855                      if ( item.settings.disabledStateSelector ) {
 856                          selection.selectorChanged( item.settings.disabledStateSelector, function( state ) {
 857                              item.disabled( state );
 858                          } );
 859                      }
 860                  }
 861  
 862                  if ( item === '|' ) {
 863                      buttonGroup = null;
 864                  } else {
 865                      if ( Factory.has( item ) ) {
 866                          item = {
 867                              type: item
 868                          };
 869  
 870                          if ( settings.toolbar_items_size ) {
 871                              item.size = settings.toolbar_items_size;
 872                          }
 873  
 874                          toolbarItems.push( item );
 875  
 876                          buttonGroup = null;
 877                      } else {
 878                          if ( ! buttonGroup ) {
 879                              buttonGroup = {
 880                                  type: 'buttongroup',
 881                                  items: []
 882                              };
 883  
 884                              toolbarItems.push( buttonGroup );
 885                          }
 886  
 887                          if ( editor.buttons[ item ] ) {
 888                              itemName = item;
 889                              item = editor.buttons[ itemName ];
 890  
 891                              if ( typeof item === 'function' ) {
 892                                  item = item();
 893                              }
 894  
 895                              item.type = item.type || 'button';
 896  
 897                              if ( settings.toolbar_items_size ) {
 898                                  item.size = settings.toolbar_items_size;
 899                              }
 900  
 901                              tooltip = item.tooltip || item.title;
 902  
 903                              if ( tooltip ) {
 904                                  item.tooltip = getTooltip( tooltip );
 905                              }
 906  
 907                              item = Factory.create( item );
 908  
 909                              buttonGroup.items.push( item );
 910  
 911                              if ( editor.initialized ) {
 912                                  bindSelectorChanged();
 913                              } else {
 914                                  editor.on( 'init', bindSelectorChanged );
 915                              }
 916                          }
 917                      }
 918                  }
 919              } );
 920  
 921              toolbar = Factory.create( {
 922                  type: 'panel',
 923                  layout: 'stack',
 924                  classes: 'toolbar-grp inline-toolbar-grp',
 925                  ariaRoot: true,
 926                  ariaRemember: true,
 927                  items: [ {
 928                      type: 'toolbar',
 929                      layout: 'flow',
 930                      items: toolbarItems
 931                  } ]
 932              } );
 933  
 934              toolbar.bottom = bottom;
 935  
 936  			function reposition() {
 937                  if ( ! currentSelection ) {
 938                      return this;
 939                  }
 940  
 941                  var scrollX = window.pageXOffset || document.documentElement.scrollLeft,
 942                      scrollY = window.pageYOffset || document.documentElement.scrollTop,
 943                      windowWidth = window.innerWidth,
 944                      windowHeight = window.innerHeight,
 945                      iframeRect = mceIframe ? mceIframe.getBoundingClientRect() : {
 946                          top: 0,
 947                          right: windowWidth,
 948                          bottom: windowHeight,
 949                          left: 0,
 950                          width: windowWidth,
 951                          height: windowHeight
 952                      },
 953                      toolbar = this.getEl(),
 954                      toolbarWidth = toolbar.offsetWidth,
 955                      toolbarHeight = toolbar.clientHeight,
 956                      selection = currentSelection.getBoundingClientRect(),
 957                      selectionMiddle = ( selection.left + selection.right ) / 2,
 958                      buffer = 5,
 959                      spaceNeeded = toolbarHeight + buffer,
 960                      wpAdminbarBottom = wpAdminbar ? wpAdminbar.getBoundingClientRect().bottom : 0,
 961                      mceToolbarBottom = mceToolbar ? mceToolbar.getBoundingClientRect().bottom : 0,
 962                      mceStatusbarTop = mceStatusbar ? windowHeight - mceStatusbar.getBoundingClientRect().top : 0,
 963                      wpStatusbarTop = wpStatusbar ? windowHeight - wpStatusbar.getBoundingClientRect().top : 0,
 964                      blockedTop = Math.max( 0, wpAdminbarBottom, mceToolbarBottom, iframeRect.top ),
 965                      blockedBottom = Math.max( 0, mceStatusbarTop, wpStatusbarTop, windowHeight - iframeRect.bottom ),
 966                      spaceTop = selection.top + iframeRect.top - blockedTop,
 967                      spaceBottom = windowHeight - iframeRect.top - selection.bottom - blockedBottom,
 968                      editorHeight = windowHeight - blockedTop - blockedBottom,
 969                      className = '',
 970                      iosOffsetTop = 0,
 971                      iosOffsetBottom = 0,
 972                      top, left;
 973  
 974                  if ( spaceTop >= editorHeight || spaceBottom >= editorHeight ) {
 975                      this.scrolling = true;
 976                      this.hide();
 977                      this.scrolling = false;
 978                      return this;
 979                  }
 980  
 981                  // Add offset in iOS to move the menu over the image, out of the way of the default iOS menu.
 982                  if ( tinymce.Env.iOS && currentSelection.nodeName === 'IMG' ) {
 983                      iosOffsetTop = 54;
 984                      iosOffsetBottom = 46;
 985                  }
 986  
 987                  if ( this.bottom ) {
 988                      if ( spaceBottom >= spaceNeeded ) {
 989                          className = ' mce-arrow-up';
 990                          top = selection.bottom + iframeRect.top + scrollY - iosOffsetBottom;
 991                      } else if ( spaceTop >= spaceNeeded ) {
 992                          className = ' mce-arrow-down';
 993                          top = selection.top + iframeRect.top + scrollY - toolbarHeight + iosOffsetTop;
 994                      }
 995                  } else {
 996                      if ( spaceTop >= spaceNeeded ) {
 997                          className = ' mce-arrow-down';
 998                          top = selection.top + iframeRect.top + scrollY - toolbarHeight + iosOffsetTop;
 999                      } else if ( spaceBottom >= spaceNeeded && editorHeight / 2 > selection.bottom + iframeRect.top - blockedTop ) {
1000                          className = ' mce-arrow-up';
1001                          top = selection.bottom + iframeRect.top + scrollY - iosOffsetBottom;
1002                      }
1003                  }
1004  
1005                  if ( typeof top === 'undefined' ) {
1006                      top = scrollY + blockedTop + buffer + iosOffsetBottom;
1007                  }
1008  
1009                  left = selectionMiddle - toolbarWidth / 2 + iframeRect.left + scrollX;
1010  
1011                  if ( selection.left < 0 || selection.right > iframeRect.width ) {
1012                      left = iframeRect.left + scrollX + ( iframeRect.width - toolbarWidth ) / 2;
1013                  } else if ( toolbarWidth >= windowWidth ) {
1014                      className += ' mce-arrow-full';
1015                      left = 0;
1016                  } else if ( ( left < 0 && selection.left + toolbarWidth > windowWidth ) || ( left + toolbarWidth > windowWidth && selection.right - toolbarWidth < 0 ) ) {
1017                      left = ( windowWidth - toolbarWidth ) / 2;
1018                  } else if ( left < iframeRect.left + scrollX ) {
1019                      className += ' mce-arrow-left';
1020                      left = selection.left + iframeRect.left + scrollX;
1021                  } else if ( left + toolbarWidth > iframeRect.width + iframeRect.left + scrollX ) {
1022                      className += ' mce-arrow-right';
1023                      left = selection.right - toolbarWidth + iframeRect.left + scrollX;
1024                  }
1025  
1026                  // No up/down arrows on the menu over images in iOS.
1027                  if ( tinymce.Env.iOS && currentSelection.nodeName === 'IMG' ) {
1028                      className = className.replace( / ?mce-arrow-(up|down)/g, '' );
1029                  }
1030  
1031                  toolbar.className = toolbar.className.replace( / ?mce-arrow-[\w]+/g, '' ) + className;
1032  
1033                  DOM.setStyles( toolbar, {
1034                      'left': left,
1035                      'top': top
1036                  } );
1037  
1038                  return this;
1039              }
1040  
1041              toolbar.on( 'show', function() {
1042                  this.reposition();
1043              } );
1044  
1045              toolbar.on( 'keydown', function( event ) {
1046                  if ( event.keyCode === 27 ) {
1047                      this.hide();
1048                      editor.focus();
1049                  }
1050              } );
1051  
1052              editor.on( 'remove', function() {
1053                  toolbar.remove();
1054              } );
1055  
1056              toolbar.reposition = reposition;
1057              toolbar.hide().renderTo( document.body );
1058  
1059              return toolbar;
1060          }
1061  
1062          editor.shortcuts.add( 'alt+119', '', function() {
1063              var node;
1064  
1065              if ( activeToolbar ) {
1066                  node = activeToolbar.find( 'toolbar' )[0];
1067                  node && node.focus( true );
1068              }
1069          } );
1070  
1071          editor.on( 'nodechange', function( event ) {
1072              var collapsed = editor.selection.isCollapsed();
1073  
1074              var args = {
1075                  element: event.element,
1076                  parents: event.parents,
1077                  collapsed: collapsed
1078              };
1079  
1080              editor.fire( 'wptoolbar', args );
1081  
1082              currentSelection = args.selection || args.element;
1083  
1084              if ( activeToolbar && activeToolbar !== args.toolbar ) {
1085                  activeToolbar.hide();
1086              }
1087  
1088              if ( args.toolbar ) {
1089                  activeToolbar = args.toolbar;
1090  
1091                  if ( activeToolbar.visible() ) {
1092                      activeToolbar.reposition();
1093                  } else {
1094                      activeToolbar.show();
1095                  }
1096              } else {
1097                  activeToolbar = false;
1098              }
1099          } );
1100  
1101          editor.on( 'focus', function() {
1102              if ( activeToolbar ) {
1103                  activeToolbar.show();
1104              }
1105          } );
1106  
1107  		function hide( event ) {
1108              var win;
1109              var size;
1110  
1111              if ( activeToolbar ) {
1112                  if ( activeToolbar.tempHide || event.type === 'hide' || event.type === 'blur' ) {
1113                      activeToolbar.hide();
1114                      activeToolbar = false;
1115                  } else if ( (
1116                      event.type === 'resizewindow' ||
1117                      event.type === 'scrollwindow' ||
1118                      event.type === 'resize' ||
1119                      event.type === 'scroll'
1120                  ) && ! activeToolbar.blockHide ) {
1121                      // Showing a tooltip may trigger a `resize` event in Chromium browsers.
1122                      // That results in a flicketing inline menu; tooltips are shown on hovering over a button,
1123                      // which then hides the toolbar on `resize`, then it repeats as soon as the toolbar is shown again.
1124                      if ( event.type === 'resize' || event.type === 'resizewindow' ) {
1125                          win = editor.getWin();
1126                          size = win.innerHeight + win.innerWidth;
1127  
1128                          // Reset old cached size.
1129                          if ( cachedWinSize && ( new Date() ).getTime() - cachedWinSize.timestamp > 2000 ) {
1130                              cachedWinSize = null;
1131                          }
1132  
1133                          if ( cachedWinSize ) {
1134                              if ( size && Math.abs( size - cachedWinSize.size ) < 2 ) {
1135                                  // `resize` fired but the window hasn't been resized. Bail.
1136                                  return;
1137                              }
1138                          } else {
1139                              // First of a new series of `resize` events. Store the cached size and bail.
1140                              cachedWinSize = {
1141                                  timestamp: ( new Date() ).getTime(),
1142                                  size: size,
1143                              };
1144  
1145                              return;
1146                          }
1147                      }
1148  
1149                      clearTimeout( timeout );
1150  
1151                      timeout = setTimeout( function() {
1152                          if ( activeToolbar && typeof activeToolbar.show === 'function' ) {
1153                              activeToolbar.scrolling = false;
1154                              activeToolbar.show();
1155                          }
1156                      }, 250 );
1157  
1158                      activeToolbar.scrolling = true;
1159                      activeToolbar.hide();
1160                  }
1161              }
1162          }
1163  
1164          if ( editor.inline ) {
1165              editor.on( 'resizewindow', hide );
1166  
1167              // Enable `capture` for the event.
1168              // This will hide/reposition the toolbar on any scrolling in the document.
1169              document.addEventListener( 'scroll', hide, true );
1170          } else {
1171              // Bind to the editor iframe and to the parent window.
1172              editor.dom.bind( editor.getWin(), 'resize scroll', hide );
1173              editor.on( 'resizewindow scrollwindow', hide );
1174          }
1175  
1176          editor.on( 'remove', function() {
1177              document.removeEventListener( 'scroll', hide, true );
1178              editor.off( 'resizewindow scrollwindow', hide );
1179              editor.dom.unbind( editor.getWin(), 'resize scroll', hide );
1180          } );
1181  
1182          editor.on( 'blur hide', hide );
1183  
1184          editor.wp = editor.wp || {};
1185          editor.wp._createToolbar = create;
1186      }, true );
1187  
1188  	function noop() {}
1189  
1190      // Expose some functions (back-compat)
1191      return {
1192          _showButtons: noop,
1193          _hideButtons: noop,
1194          _setEmbed: noop,
1195          _getEmbed: noop
1196      };
1197  });
1198  
1199  }( window.tinymce ));


Generated: Sat Nov 23 20:47:33 2019 Cross-referenced by PHPXref 0.7