Changeset 30318
- Timestamp:
- 11/13/2014 12:55:22 AM (10 years ago)
- Location:
- trunk/src/wp-includes
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/class-wp-editor.php
r30296 r30318 958 958 'Read more...' => __( 'Read more...' ), // Title on the placeholder inside the editor 959 959 'Distraction Free Writing' => __( 'Distraction Free Writing' ), 960 'Remove Alignment' => __( 'Remove alignment' ), // Tooltip for the 'alignnone' button in the image toolbar 960 961 ); 961 962 -
trunk/src/wp-includes/css/editor.css
r30070 r30318 153 153 padding: 0; 154 154 position: relative; 155 } 156 157 div.mce-inline-toolbar-grp { 158 border: 1px solid #aaa; 159 -webkit-border-radius: 2px; 160 border-radius: 2px; 161 -webkit-box-shadow: 0 1px 4px rgba( 0, 0, 0, 0.2 ) 162 box-shadow: 0 1px 4px rgba( 0, 0, 0, 0.2 ) 163 -webkit-box-sizing: border-box; 164 -moz-box-sizing: border-box; 165 -webkit-box-sizing: border-box; 166 box-sizing: border-box; 167 margin-bottom: 8px; 168 position: absolute; 169 opacity: 0; 170 -moz-user-select: none; 171 -webkit-user-select: none; 172 -ms-user-select: none; 173 user-select: none; 174 } 175 176 div.mce-wp-image-toolbar > div.mce-stack-layout { 177 padding: 1px; 178 } 179 180 div.mce-inline-toolbar-grp.mce-arrow-up { 181 margin-bottom: 0; 182 margin-top: 8px; 183 } 184 185 div.mce-inline-toolbar-grp.mce-inline-toolbar-grp-active { 186 -webkit-transition: 187 top 0.1s ease-out, 188 left 0.1s ease-out, 189 opacity 0.1s ease-in-out; 190 transition: 191 top 0.1s ease-out, 192 left 0.1s ease-out, 193 opacity 0.1s ease-in-out; 194 opacity: 1; 195 } 196 197 div.mce-inline-toolbar-grp:before, 198 div.mce-inline-toolbar-grp:after { 199 position: absolute; 200 left: 50%; 201 display: block; 202 width: 0; 203 height: 0; 204 border-style: solid; 205 border-color: transparent; 206 content: ''; 207 } 208 209 div.mce-inline-toolbar-grp.mce-arrow-up:before { 210 top: -18px; 211 border-bottom-color: #aaa; 212 border-width: 9px; 213 margin-left: -9px; 214 } 215 216 div.mce-inline-toolbar-grp.mce-arrow-down:before { 217 bottom: -18px; 218 border-top-color: #aaa; 219 border-width: 9px; 220 margin-left: -9px; 221 } 222 223 div.mce-inline-toolbar-grp.mce-arrow-up:after { 224 top: -16px; 225 border-bottom-color: #f5f5f5; 226 border-width: 8px; 227 margin-left: -8px; 228 } 229 230 div.mce-inline-toolbar-grp.mce-arrow-down:after { 231 bottom: -16px; 232 border-top-color: #f5f5f5; 233 border-width: 8px; 234 margin-left: -8px; 235 } 236 237 div.mce-inline-toolbar-grp.mce-arrow-left:before, 238 div.mce-inline-toolbar-grp.mce-arrow-left:after { 239 left: 20px; 240 } 241 242 div.mce-inline-toolbar-grp.mce-arrow-right:before, 243 div.mce-inline-toolbar-grp.mce-arrow-right:after { 244 right: 11px; 245 left: auto; 246 } 247 248 div.mce-inline-toolbar-grp.mce-arrow-full { 249 right: 0; 250 } 251 252 div.mce-inline-toolbar-grp.mce-arrow-full > div { 253 width: 100%; 254 overflow-x: auto; 155 255 } 156 256 … … 622 722 i.mce-i-wp_page, 623 723 i.mce-i-hr, 724 i.mce-i-dashicon, 624 725 .mce-close { 625 726 font: normal 20px/1 'dashicons'; -
trunk/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js
r29994 r30318 1 1 /* global tinymce */ 2 2 tinymce.PluginManager.add( 'wpeditimage', function( editor ) { 3 var toolbarActive = false, 4 editingImage = false; 3 var DOM = tinymce.DOM, 4 settings = editor.settings, 5 Factory = tinymce.ui.Factory, 6 each = tinymce.each, 7 iOS = tinymce.Env.iOS, 8 toolbarIsHidden = true, 9 editorWrapParent = tinymce.$( '#postdivrich' ), 10 tb; 11 12 editor.addButton( 'wp_img_remove', { 13 tooltip: 'Remove', 14 icon: 'dashicon dashicons-no', 15 onclick: function() { 16 removeImage( editor.selection.getNode() ); 17 } 18 } ); 19 20 editor.addButton( 'wp_img_edit', { 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: 'Remove alignment' 33 }, function( tooltip, name ) { 34 var direction = name.slice( 5 ); 35 36 editor.addButton( 'wp_img_' + name, { 37 tooltip: tooltip, 38 icon: 'dashicon dashicons-align-' + direction, 39 cmd: 'alignnone' === name ? 'wpAlignNone' : '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( ! /\balign(left|center|right)\b/.test( node.className ) ); 55 } else { 56 self.active( editor.dom.hasClass( node, name ) ); 57 } 58 } ); 59 } 60 } ); 61 } ); 62 63 function toolbarConfig() { 64 var toolbarItems = [], 65 buttonGroup; 66 67 each( [ 'wp_img_alignleft', 'wp_img_aligncenter', 'wp_img_alignright', 'wp_img_alignnone', 'wp_img_edit', 'wp_img_remove' ], function( item ) { 68 var itemName; 69 70 function bindSelectorChanged() { 71 var selection = editor.selection; 72 73 if ( item.settings.stateSelector ) { 74 selection.selectorChanged( item.settings.stateSelector, function( state ) { 75 item.active( state ); 76 }, true ); 77 } 78 79 if ( item.settings.disabledStateSelector ) { 80 selection.selectorChanged( item.settings.disabledStateSelector, function( state ) { 81 item.disabled( state ); 82 } ); 83 } 84 } 85 86 if ( item === '|' ) { 87 buttonGroup = null; 88 } else { 89 if ( Factory.has( item ) ) { 90 item = { 91 type: item 92 }; 93 94 if ( settings.toolbar_items_size ) { 95 item.size = settings.toolbar_items_size; 96 } 97 98 toolbarItems.push( item ); 99 100 buttonGroup = null; 101 } else { 102 if ( ! buttonGroup ) { 103 buttonGroup = { 104 type: 'buttongroup', 105 items: [] 106 }; 107 108 toolbarItems.push( buttonGroup ); 109 } 110 111 if ( editor.buttons[ item ] ) { 112 itemName = item; 113 item = editor.buttons[ itemName ]; 114 115 if ( typeof item === 'function' ) { 116 item = item(); 117 } 118 119 item.type = item.type || 'button'; 120 121 if ( settings.toolbar_items_size ) { 122 item.size = settings.toolbar_items_size; 123 } 124 125 item = Factory.create( item ); 126 buttonGroup.items.push( item ); 127 128 if ( editor.initialized ) { 129 bindSelectorChanged(); 130 } else { 131 editor.on( 'init', bindSelectorChanged ); 132 } 133 } 134 } 135 } 136 } ); 137 138 return { 139 type: 'panel', 140 layout: 'stack', 141 classes: 'toolbar-grp inline-toolbar-grp wp-image-toolbar', 142 ariaRoot: true, 143 ariaRemember: true, 144 items: [ 145 { 146 type: 'toolbar', 147 layout: 'flow', 148 items: toolbarItems 149 } 150 ] 151 }; 152 } 153 154 tb = Factory.create( toolbarConfig() ).renderTo( document.body ).hide(); 155 156 tb.reposition = function() { 157 var top, left, minTop, className, 158 toolbarNode = this.getEl(), 159 buffer = 5, 160 margin = 8, 161 windowPos = window.pageYOffset || document.documentElement.scrollTop, 162 adminbar = tinymce.$( '#wpadminbar' )[0], 163 mceToolbar = tinymce.$( '.mce-tinymce .mce-toolbar-grp' )[0], 164 adminbarHeight = 0, 165 boundary = editor.selection.getRng().getBoundingClientRect(), 166 boundaryMiddle = ( boundary.left + boundary.right ) / 2, 167 boundaryVerticalMiddle = ( boundary.top + boundary.bottom ) / 2, 168 spaceTop = boundary.top, 169 spaceBottom = iframeHeigth - boundary.bottom, 170 windowWidth = window.innerWidth, 171 toolbarWidth = toolbarNode.offsetWidth, 172 toolbarHalf = toolbarWidth / 2, 173 iframe = editor.getContentAreaContainer().firstChild, 174 iframePos = DOM.getPos( iframe ), 175 iframeWidth = iframe.offsetWidth, 176 iframeHeigth = iframe.offsetHeight, 177 toolbarNodeHeight = toolbarNode.offsetHeight, 178 verticalSpaceNeeded = toolbarNodeHeight + margin + buffer; 179 180 if ( iOS ) { 181 top = boundary.top + iframePos.y + margin; 182 } else { 183 if ( spaceTop >= verticalSpaceNeeded ) { 184 className = ' mce-arrow-down'; 185 top = boundary.top + iframePos.y - toolbarNodeHeight - margin; 186 } else if ( spaceBottom >= verticalSpaceNeeded ) { 187 className = ' mce-arrow-up'; 188 top = boundary.bottom + iframePos.y; 189 } else { 190 top = buffer; 191 192 if ( boundaryVerticalMiddle >= verticalSpaceNeeded ) { 193 className = ' mce-arrow-down'; 194 } else { 195 className = ' mce-arrow-up'; 196 } 197 } 198 } 199 200 // Make sure the image toolbar is below the main toolbar. 201 if ( mceToolbar ) { 202 minTop = DOM.getPos( mceToolbar ).y + mceToolbar.clientHeight; 203 } else { 204 minTop = iframePos.y; 205 } 206 207 // Make sure the image toolbar is below the adminbar (if visible) or below the top of the window. 208 if ( windowPos ) { 209 if ( adminbar && adminbar.getBoundingClientRect().top === 0 ) { 210 adminbarHeight = adminbar.clientHeight; 211 } 212 213 if ( windowPos + adminbarHeight > minTop ) { 214 minTop = windowPos + adminbarHeight; 215 } 216 } 217 218 if ( top && minTop && ( minTop + buffer > top ) ) { 219 top = minTop + buffer; 220 className = ''; 221 } 222 223 left = boundaryMiddle - toolbarHalf; 224 left += iframePos.x; 225 226 if ( toolbarWidth >= windowWidth ) { 227 className += ' mce-arrow-full'; 228 left = 0; 229 } else if ( ( left < 0 && boundary.left + toolbarWidth > windowWidth ) || 230 ( left + toolbarWidth > windowWidth && boundary.right - toolbarWidth < 0 ) ) { 231 232 left = ( windowWidth - toolbarWidth ) / 2; 233 } else if ( left < iframePos.x ) { 234 className += ' mce-arrow-left'; 235 left = boundary.left + iframePos.x; 236 } else if ( left + toolbarWidth > iframeWidth + iframePos.x ) { 237 className += ' mce-arrow-right'; 238 left = boundary.right - toolbarWidth + iframePos.x; 239 } 240 241 if ( ! iOS ) { 242 toolbarNode.className = toolbarNode.className.replace( / ?mce-arrow-[\w]+/g, '' ); 243 toolbarNode.className += className; 244 } 245 246 DOM.setStyles( toolbarNode, { 'left': left, 'top': top } ); 247 248 return this; 249 }; 250 251 if ( iOS ) { 252 // Safari on iOS fails to select image nodes in contentEditoble mode on touch/click. 253 // Select them again. 254 editor.on( 'click', function( event ) { 255 if ( event.target.nodeName === 'IMG' ) { 256 var node = event.target; 257 258 window.setTimeout( function() { 259 editor.selection.select( node ); 260 }, 200 ); 261 } else { 262 tb.hide(); 263 } 264 }); 265 } 266 267 editor.on( 'nodechange', function( event ) { 268 var delay = iOS ? 350 : 100; 269 270 if ( event.element.nodeName !== 'IMG' ) { 271 tb.hide(); 272 return; 273 } 274 275 setTimeout( function() { 276 var element = editor.selection.getNode(); 277 278 if ( element.nodeName === 'IMG' ) { 279 if ( tb._visible ) { 280 tb.reposition(); 281 } else { 282 tb.show(); 283 } 284 } else { 285 tb.hide(); 286 } 287 }, delay ); 288 } ); 289 290 tb.on( 'show', function() { 291 var self = this; 292 293 toolbarIsHidden = false; 294 295 setTimeout( function() { 296 if ( self._visible ) { 297 DOM.addClass( self.getEl(), 'mce-inline-toolbar-grp-active' ); 298 self.reposition(); 299 } 300 }, 100 ); 301 } ); 302 303 tb.on( 'hide', function() { 304 toolbarIsHidden = true; 305 DOM.removeClass( this.getEl(), 'mce-inline-toolbar-grp-active' ); 306 } ); 307 308 function hide() { 309 if ( ! toolbarIsHidden ) { 310 tb.hide(); 311 } 312 } 313 314 DOM.bind( window, 'resize scroll', function() { 315 if ( ! toolbarIsHidden && editorWrapParent.hasClass( 'wp-editor-expand' ) ) { 316 hide(); 317 } 318 }); 319 320 editor.on( 'init', function() { 321 DOM.bind( editor.getWin(), 'resize scroll', hide ); 322 } ); 323 324 editor.on( 'blur hide', hide ); 325 326 // 119 = F8 327 editor.shortcuts.add( 'Alt+119', '', function() { 328 var node = tb.find( 'toolbar' )[0]; 329 330 if ( node ) { 331 node.focus( true ); 332 } 333 } ); 5 334 6 335 function parseShortcode( content ) { … … 373 702 374 703 editor.nodeChanged(); 375 // Refresh the toolbar376 addToolbar( imageNode );377 704 } 378 705 … … 415 742 editor.focus(); 416 743 frame.detach(); 417 editingImage = false;418 744 }); 419 745 … … 445 771 } 446 772 447 removeToolbar();448 773 editor.nodeChanged(); 449 774 editor.undoManager.add(); 450 775 } 451 452 function addToolbar( node ) {453 var rectangle, toolbarHtml, toolbar, left,454 dom = editor.dom;455 456 removeToolbar();457 458 // Don't add to placeholders459 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': false473 }, 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: left485 });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-click525 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 776 570 777 editor.on( 'init', function() { … … 804 1011 event.preventDefault(); 805 1012 } 806 807 // Remove toolbar to avoid an orphaned toolbar when dragging an image to a new location808 removeToolbar();809 1013 }); 810 1014 … … 822 1026 } 823 1027 }); 824 825 editor.on( 'click', function( event ) {826 if ( event.target.nodeName === 'IMG' && dom.getAttrib( event.target, 'data-wp-imgselect' ) &&827 dom.getParent( event.target, 'dl.wp-caption' ) ) {828 829 editor.getBody().focus();830 }831 });832 1028 } 833 1029 }); … … 856 1052 } 857 1053 } 858 // refresh toolbar859 addToolbar( node );860 1054 }); 861 1055 } … … 863 1057 864 1058 editor.on( 'BeforeExecCommand', function( event ) { 865 var node, p, DL, align, 1059 var node, p, DL, align, replacement, 866 1060 cmd = event.command, 867 1061 dom = editor.dom; … … 876 1070 editor.nodeChanged(); 877 1071 } 878 } else if ( cmd === 'JustifyLeft' || cmd === 'JustifyRight' || cmd === 'JustifyCenter' ) {1072 } else if ( cmd === 'JustifyLeft' || cmd === 'JustifyRight' || cmd === 'JustifyCenter' || cmd === 'wpAlignNone' ) { 879 1073 node = editor.selection.getNode(); 880 align = cmd.substr(7).toLowerCase(); 881 align = 'align' + align; 882 DL = dom.getParent( node, 'dl.wp-caption' ); 883 884 removeToolbar(); 885 886 if ( DL ) { 887 // When inside an image caption, set the align* class on dl.wp-caption 888 if ( dom.hasClass( DL, align ) ) { 889 dom.removeClass( DL, align ); 890 dom.addClass( DL, 'alignnone' ); 891 } else { 892 DL.className = DL.className.replace( /align[^ ]+/g, '' ); 893 dom.addClass( DL, align ); 894 } 895 896 if ( node.nodeName === 'IMG' ) { 897 // Re-select the image to update resize handles, etc. 898 editor.nodeChanged(); 899 } 900 901 event.preventDefault(); 902 } 903 904 if ( node.nodeName === 'IMG' ) { 905 if ( dom.hasClass( node, align ) ) { 906 // The align class is being removed 907 dom.addClass( node, 'alignnone' ); 908 } else { 909 dom.removeClass( node, 'alignnone' ); 910 } 1074 align = 'align' + cmd.slice( 7 ).toLowerCase(); 1075 DL = editor.dom.getParent( node, '.wp-caption' ); 1076 1077 if ( node.nodeName !== 'IMG' && ! DL ) { 1078 return; 1079 } 1080 1081 node = DL || node; 1082 1083 if ( editor.dom.hasClass( node, align ) ) { 1084 replacement = ' alignnone'; 1085 } else { 1086 replacement = ' ' + align; 1087 } 1088 1089 node.className = node.className.replace( / ?align(left|center|right|none)/g, '' ) + replacement; 1090 1091 editor.nodeChanged(); 1092 event.preventDefault(); 1093 1094 if ( tb ) { 1095 tb.reposition(); 911 1096 } 912 1097 } … … 961 1146 return false; 962 1147 } 963 964 removeToolbar(); 965 } 966 967 // Most key presses will replace the image so we need to remove the toolbar 968 if ( toolbarActive ) { 969 if ( event.ctrlKey || event.metaKey || event.altKey || ( keyCode < 48 && keyCode !== VK.SPACEBAR ) ) { 970 return; 971 } 972 973 removeToolbar(); 974 } 975 }); 976 977 editor.on( 'mousedown', function( event ) { 978 if ( isToolbarButton( event.target ) ) { 979 if ( tinymce.Env.ie ) { 980 // Stop IE > 8 from making the wrapper resizable on mousedown 981 event.preventDefault(); 982 } 983 } else if ( event.target.nodeName !== 'IMG' ) { 984 removeToolbar(); 985 } 986 }); 987 988 // Remove from undo levels 989 editor.on( 'BeforeAddUndo', function( event ) { 990 event.level.content = event.level.content.replace( / data-wp-imgselect="1"/g, '' ); 1148 } 991 1149 }); 992 1150 … … 1002 1160 } 1003 1161 1004 editor.on( 'cut wpview-selected', function() {1005 removeToolbar();1006 });1007 1008 1162 editor.wpSetImgCaption = function( content ) { 1009 1163 return parseShortcode( content ); … … 1023 1177 if ( event.get ) { 1024 1178 event.content = editor.wpGetImgCaption( event.content ); 1025 event.content = event.content.replace( / data-wp-imgselect="1"/g, '' );1026 1179 } 1027 1180 });
Note: See TracChangeset
for help on using the changeset viewer.