3 | | var toolbarActive = false, |
4 | | editingImage = false; |
| 3 | 'use strict'; |
| 4 | |
| 5 | var DOM = tinymce.DOM, |
| 6 | settings = editor.settings, |
| 7 | Factory = tinymce.ui.Factory, |
| 8 | each = tinymce.each, |
| 9 | postDivRich = DOM.get( 'postdivrich' ), |
| 10 | tb; |
| 11 | |
| 12 | editor.addButton( 'imgremove', { |
| 13 | tooltip: 'Remove', |
| 14 | icon: 'dashicon dashicons-no', |
| 15 | onclick: function() { |
| 16 | removeImage( editor.selection.getNode() ); |
| 17 | } |
| 18 | } ); |
| 19 | |
| 20 | editor.addButton( 'imgedit', { |
| 21 | tooltip: 'Edit', |
| 22 | icon: 'dashicon dashicons-edit', |
| 23 | onclick: function() { |
| 24 | editImage( editor.selection.getNode() ); |
| 25 | } |
| 26 | } ); |
| 27 | |
| 28 | each( { |
| 29 | alignleft: 'Align Left', |
| 30 | aligncenter: 'Align Center', |
| 31 | alignright: 'Align Right', |
| 32 | alignnone: 'Don’t Align' |
| 33 | }, function( tooltip, name ) { |
| 34 | var direction = name.slice( 5 ); |
| 35 | |
| 36 | editor.addButton( 'img' + name, { |
| 37 | tooltip: tooltip, |
| 38 | icon: 'dashicon dashicons-align-' + direction, |
| 39 | cmd: 'alignnone' === name ? name : 'Justify' + direction.slice( 0, 1 ).toUpperCase() + direction.slice( 1 ), |
| 40 | onPostRender: function() { |
| 41 | var self = this; |
| 42 | |
| 43 | editor.on( 'NodeChange', function( event ) { |
| 44 | var node; |
| 45 | |
| 46 | // Don't bother. |
| 47 | if ( event.element.nodeName !== 'IMG' ) { |
| 48 | return; |
| 49 | } |
| 50 | |
| 51 | node = editor.dom.getParent( event.element, '.wp-caption' ) || event.element; |
| 52 | |
| 53 | if ( 'alignnone' === name ) { |
| 54 | self.active( |
| 55 | ! editor.dom.hasClass( node, 'alignleft' ) && |
| 56 | ! editor.dom.hasClass( node, 'aligncenter' ) && |
| 57 | ! editor.dom.hasClass( node, 'alignright' ) |
| 58 | ); |
| 59 | } else { |
| 60 | self.active( editor.dom.hasClass( node, name ) ); |
| 61 | } |
| 62 | } ); |
| 63 | } |
| 64 | } ); |
| 65 | } ); |
| 66 | |
| 67 | function toolbarConfig() { |
| 68 | var toolbarItems = [], |
| 69 | buttonGroup; |
| 70 | |
| 71 | each( [ 'imgalignleft', 'imgaligncenter', 'imgalignright', 'imgalignnone', 'imgedit', 'imgremove' ], function( item ) { |
| 72 | var itemName; |
| 73 | |
| 74 | function bindSelectorChanged() { |
| 75 | var selection = editor.selection; |
| 76 | |
| 77 | if ( item.settings.stateSelector ) { |
| 78 | selection.selectorChanged( item.settings.stateSelector, function( state ) { |
| 79 | item.active( state ); |
| 80 | }, true ); |
| 81 | } |
| 82 | |
| 83 | if ( item.settings.disabledStateSelector ) { |
| 84 | selection.selectorChanged( item.settings.disabledStateSelector, function( state ) { |
| 85 | item.disabled( state ); |
| 86 | } ); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | if ( item === '|' ) { |
| 91 | buttonGroup = null; |
| 92 | } else { |
| 93 | if ( Factory.has( item ) ) { |
| 94 | item = { |
| 95 | type: item |
| 96 | }; |
| 97 | |
| 98 | if ( settings.toolbar_items_size ) { |
| 99 | item.size = settings.toolbar_items_size; |
| 100 | } |
| 101 | |
| 102 | toolbarItems.push( item ); |
| 103 | |
| 104 | buttonGroup = null; |
| 105 | } else { |
| 106 | if ( ! buttonGroup ) { |
| 107 | buttonGroup = { |
| 108 | type: 'buttongroup', |
| 109 | items: [] |
| 110 | }; |
| 111 | |
| 112 | toolbarItems.push( buttonGroup ); |
| 113 | } |
| 114 | |
| 115 | if ( editor.buttons[ item ] ) { |
| 116 | itemName = item; |
| 117 | item = editor.buttons[ itemName ]; |
| 118 | |
| 119 | if ( typeof item === 'function' ) { |
| 120 | item = item(); |
| 121 | } |
| 122 | |
| 123 | item.type = item.type || 'button'; |
| 124 | |
| 125 | if ( settings.toolbar_items_size ) { |
| 126 | item.size = settings.toolbar_items_size; |
| 127 | } |
| 128 | |
| 129 | item = Factory.create( item ); |
| 130 | buttonGroup.items.push( item ); |
| 131 | |
| 132 | if ( editor.initialized ) { |
| 133 | bindSelectorChanged(); |
| 134 | } else { |
| 135 | editor.on( 'init', bindSelectorChanged ); |
| 136 | } |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | } ); |
| 141 | |
| 142 | return { |
| 143 | type: 'panel', |
| 144 | layout: 'stack', |
| 145 | classes: 'toolbar-grp inline-toolbar-grp', |
| 146 | ariaRoot: true, |
| 147 | ariaRemember: true, |
| 148 | items: [ |
| 149 | { |
| 150 | type: 'toolbar', |
| 151 | layout: 'flow', |
| 152 | items: toolbarItems |
| 153 | } |
| 154 | ] |
| 155 | }; |
| 156 | } |
| 157 | |
| 158 | tb = Factory.create( toolbarConfig() ).renderTo( document.body ).hide(); |
| 159 | |
| 160 | tb.reposition = function() { |
| 161 | var toolbarEl = this.getEl(), |
| 162 | buffer = 10, |
| 163 | boundary = editor.selection.getRng().getBoundingClientRect(), |
| 164 | boundaryMiddle = ( boundary.left + boundary.right ) / 2, |
| 165 | boundaryVerticalMiddle = ( boundary.top + boundary.bottom ) / 2, |
| 166 | windowWidth = window.innerWidth, |
| 167 | toolbarWidth, toolbarHalf, |
| 168 | margin = 8, |
| 169 | top, left, className, iframe, iframePos, iframeWidth, iframeHeigth, |
| 170 | spaceTop, spaceBottom, |
| 171 | toolbarElHeight, verticalSpaceNeeded, |
| 172 | expand = DOM.hasClass( postDivRich, 'wp-editor-expand' ) && window.editorExpand, |
| 173 | heights = expand && expand.heights(); |
| 174 | |
| 175 | toolbarEl.className = toolbarEl.className.replace( /\smce-arrow-\S+/g, '' ); |
| 176 | |
| 177 | toolbarWidth = toolbarEl.offsetWidth; |
| 178 | toolbarHalf = toolbarWidth / 2; |
| 179 | |
| 180 | iframe = editor.getContentAreaContainer().firstChild; |
| 181 | iframePos = DOM.getPos( iframe ); |
| 182 | iframeWidth = iframe.offsetWidth; |
| 183 | iframeHeigth = iframe.offsetHeight; |
| 184 | |
| 185 | spaceTop = expand ? |
| 186 | boundary.top + iframePos.y - window.pageYOffset - heights.adminBarHeight - heights.toolsHeight - heights.menuBarHeight - heights.visualTopHeight : |
| 187 | boundary.top; |
| 188 | spaceBottom = expand ? |
| 189 | window.pageYOffset + heights.windowHeight - iframePos.y - boundary.bottom - heights.bottomHeight - heights.statusBarHeight: |
| 190 | iframeHeigth - boundary.bottom; |
| 191 | toolbarElHeight = toolbarEl.offsetHeight; |
| 192 | verticalSpaceNeeded = toolbarElHeight + margin + buffer; |
| 193 | |
| 194 | if ( spaceTop >= verticalSpaceNeeded ) { |
| 195 | className = ' mce-arrow-down'; |
| 196 | top = boundary.top + iframePos.y - toolbarElHeight - margin; |
| 197 | } else if ( spaceBottom >= verticalSpaceNeeded ) { |
| 198 | className = ' mce-arrow-up'; |
| 199 | top = boundary.bottom + iframePos.y; |
| 200 | } else { |
| 201 | top = expand ? |
| 202 | window.pageYOffset + heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight + heights.visualTopHeight + buffer : |
| 203 | buffer; |
| 204 | |
| 205 | if ( boundaryVerticalMiddle >= verticalSpaceNeeded ) { |
| 206 | className = ' mce-arrow-down'; |
| 207 | } else { |
| 208 | className = ' mce-arrow-up'; |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | left = boundaryMiddle - toolbarHalf; |
| 213 | left += iframePos.x; |
| 214 | |
| 215 | if ( toolbarWidth >= windowWidth ) { |
| 216 | className += ' mce-arrow-full'; |
| 217 | left = 0; |
| 218 | } else if ( ( left < 0 && boundary.left + toolbarWidth > windowWidth ) || ( left + toolbarWidth > windowWidth && boundary.right - toolbarWidth < 0 ) ) { |
| 219 | left = ( windowWidth - toolbarWidth ) / 2; |
| 220 | } else if ( left < iframePos.x ) { |
| 221 | className += ' mce-arrow-left'; |
| 222 | left = boundary.left + iframePos.x; |
| 223 | } else if ( left + toolbarWidth > iframeWidth + iframePos.x ) { |
| 224 | className += ' mce-arrow-right'; |
| 225 | left = boundary.right - toolbarWidth + iframePos.x; |
| 226 | } |
| 227 | |
| 228 | toolbarEl.className += className; |
| 229 | |
| 230 | DOM.setStyles( toolbarEl, { 'left': left, 'top': top } ); |
| 231 | |
| 232 | return this; |
| 233 | }; |
| 234 | |
| 235 | editor.on( 'nodechange', function( event ) { |
| 236 | if ( event.element.nodeName !== 'IMG' ) { |
| 237 | tb.hide(); |
| 238 | return; |
| 239 | } |
| 240 | |
| 241 | setTimeout( function() { |
| 242 | var element = editor.selection.getNode(); |
| 243 | |
| 244 | if ( element.nodeName === 'IMG' ) { |
| 245 | if ( tb._visible ) { |
| 246 | tb.reposition(); |
| 247 | } else { |
| 248 | tb.show(); |
| 249 | } |
| 250 | } else { |
| 251 | tb.hide(); |
| 252 | } |
| 253 | }, 50 ); |
| 254 | } ); |
| 255 | |
| 256 | tb.on( 'show', function() { |
| 257 | var self = this; |
| 258 | |
| 259 | setTimeout( function() { |
| 260 | self._visible && DOM.addClass( self.getEl(), 'mce-inline-toolbar-grp-active' ); |
| 261 | }, 100 ); |
| 262 | } ); |
| 263 | |
| 264 | tb.on( 'hide', function() { |
| 265 | DOM.removeClass( this.getEl(), 'mce-inline-toolbar-active' ); |
| 266 | } ); |
| 267 | |
| 268 | function hide() { |
| 269 | tb.hide(); |
| 270 | } |
| 271 | |
| 272 | DOM.bind( window, 'resize scroll', hide ); |
| 273 | |
| 274 | editor.on( 'init', function() { |
| 275 | DOM.bind( editor.getWin(), 'resize scroll', hide ); |
| 276 | } ); |
| 277 | |
| 278 | editor.on( 'blur hide', hide ); |
| 279 | |
| 280 | // 119 = F8 |
| 281 | editor.shortcuts.add( 'Alt+119', '', function() { |
| 282 | var item = tb.find( 'toolbar' )[0]; |
| 283 | |
| 284 | item && item.focus( true ); |
| 285 | } ); |
452 | | function addToolbar( node ) { |
453 | | var rectangle, toolbarHtml, toolbar, left, |
454 | | dom = editor.dom; |
455 | | |
456 | | removeToolbar(); |
457 | | |
458 | | // Don't add to placeholders |
459 | | if ( ! node || node.nodeName !== 'IMG' || isPlaceholder( node ) ) { |
460 | | return; |
461 | | } |
462 | | |
463 | | dom.setAttrib( node, 'data-wp-imgselect', 1 ); |
464 | | rectangle = dom.getRect( node ); |
465 | | |
466 | | toolbarHtml = '<i class="dashicons dashicons-edit edit" data-mce-bogus="all"></i>' + |
467 | | '<i class="dashicons dashicons-no-alt remove" data-mce-bogus="all"></i>'; |
468 | | |
469 | | toolbar = dom.create( 'p', { |
470 | | 'id': 'wp-image-toolbar', |
471 | | 'data-mce-bogus': 'all', |
472 | | 'contenteditable': false |
473 | | }, toolbarHtml ); |
474 | | |
475 | | if ( editor.rtl ) { |
476 | | left = rectangle.x + rectangle.w - 82; |
477 | | } else { |
478 | | left = rectangle.x; |
479 | | } |
480 | | |
481 | | editor.getBody().appendChild( toolbar ); |
482 | | dom.setStyles( toolbar, { |
483 | | top: rectangle.y, |
484 | | left: left |
485 | | }); |
486 | | |
487 | | toolbarActive = true; |
488 | | } |
489 | | |
490 | | function removeToolbar() { |
491 | | var toolbar = editor.dom.get( 'wp-image-toolbar' ); |
492 | | |
493 | | if ( toolbar ) { |
494 | | editor.dom.remove( toolbar ); |
495 | | } |
496 | | |
497 | | editor.dom.setAttrib( editor.dom.select( 'img[data-wp-imgselect]' ), 'data-wp-imgselect', null ); |
498 | | |
499 | | editingImage = false; |
500 | | toolbarActive = false; |
501 | | } |
502 | | |
503 | | function isPlaceholder( node ) { |
504 | | var dom = editor.dom; |
505 | | |
506 | | if ( dom.hasClass( node, 'mceItem' ) || dom.getAttrib( node, 'data-mce-placeholder' ) || |
507 | | dom.getAttrib( node, 'data-mce-object' ) ) { |
508 | | |
509 | | return true; |
510 | | } |
511 | | |
512 | | return false; |
513 | | } |
514 | | |
515 | | function isToolbarButton( node ) { |
516 | | return ( node && node.nodeName === 'I' && node.parentNode.id === 'wp-image-toolbar' ); |
517 | | } |
518 | | |
519 | | function edit( event ) { |
520 | | var image, |
521 | | node = event.target, |
522 | | dom = editor.dom; |
523 | | |
524 | | // Don't trigger on right-click |
525 | | if ( event.button && event.button > 1 ) { |
526 | | return; |
527 | | } |
528 | | |
529 | | if ( isToolbarButton( node ) ) { |
530 | | image = dom.select( 'img[data-wp-imgselect]' )[0]; |
531 | | |
532 | | if ( image ) { |
533 | | editor.selection.select( image ); |
534 | | |
535 | | if ( dom.hasClass( node, 'remove' ) ) { |
536 | | removeImage( image ); |
537 | | } else if ( dom.hasClass( node, 'edit' ) ) { |
538 | | if ( ! editingImage ) { |
539 | | editImage( image ); |
540 | | editingImage = true; |
541 | | } |
542 | | } |
543 | | } |
544 | | |
545 | | event.preventDefault(); |
546 | | } else if ( node.nodeName === 'IMG' && ! editor.dom.getAttrib( node, 'data-wp-imgselect' ) && ! isPlaceholder( node ) ) { |
547 | | addToolbar( node ); |
548 | | } else if ( node.nodeName !== 'IMG' ) { |
549 | | removeToolbar(); |
550 | | } |
551 | | } |
552 | | |
553 | | if ( 'ontouchend' in document ) { |
554 | | editor.on( 'click', function( event ) { |
555 | | var target = event.target; |
556 | | |
557 | | if ( editingImage && target.nodeName === 'IMG' ) { |
558 | | event.preventDefault(); |
559 | | } |
560 | | |
561 | | if ( isToolbarButton( target ) ) { |
562 | | event.preventDefault(); |
563 | | event.stopPropagation(); |
564 | | } |
565 | | }); |
566 | | } |
567 | | |
568 | | editor.on( 'mouseup touchend', edit ); |
569 | | |