86 |
90 |
87 editor.on( 'focus', function() { |
91 editor.on( 'focus', function() { |
88 window.wpActiveEditor = editor.id; |
92 window.wpActiveEditor = editor.id; |
89 }); |
93 }); |
90 |
94 |
91 // Replace Read More/Next Page tags with images |
95 editor.on( 'BeforeSetContent', function( event ) { |
92 editor.on( 'BeforeSetContent', function( e ) { |
|
93 var title; |
96 var title; |
94 |
97 |
95 if ( e.content ) { |
98 if ( event.content ) { |
96 if ( e.content.indexOf( '<!--more' ) !== -1 ) { |
99 if ( event.content.indexOf( '<!--more' ) !== -1 ) { |
97 title = __( 'Read more...' ); |
100 title = __( 'Read more...' ); |
98 |
101 |
99 e.content = e.content.replace( /<!--more(.*?)-->/g, function( match, moretext ) { |
102 event.content = event.content.replace( /<!--more(.*?)-->/g, function( match, moretext ) { |
100 return '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="more" data-wp-more-text="' + moretext + '" ' + |
103 return '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="more" data-wp-more-text="' + moretext + '" ' + |
101 'class="wp-more-tag mce-wp-more" title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />'; |
104 'class="wp-more-tag mce-wp-more" alt="" title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />'; |
102 }); |
105 }); |
103 } |
106 } |
104 |
107 |
105 if ( e.content.indexOf( '<!--nextpage-->' ) !== -1 ) { |
108 if ( event.content.indexOf( '<!--nextpage-->' ) !== -1 ) { |
106 title = __( 'Page break' ); |
109 title = __( 'Page break' ); |
107 |
110 |
108 e.content = e.content.replace( /<!--nextpage-->/g, |
111 event.content = event.content.replace( /<!--nextpage-->/g, |
109 '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="nextpage" class="wp-more-tag mce-wp-nextpage" ' + |
112 '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="nextpage" class="wp-more-tag mce-wp-nextpage" ' + |
110 'title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />' ); |
113 'alt="" title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />' ); |
111 } |
114 } |
112 } |
115 |
113 }); |
116 if ( event.load && event.format !== 'raw' ) { |
114 |
117 if ( hasWpautop ) { |
115 // Replace images with tags |
118 event.content = wp.editor.autop( event.content ); |
116 editor.on( 'PostProcess', function( e ) { |
119 } else { |
117 if ( e.get ) { |
120 // Prevent creation of paragraphs out of multiple HTML comments. |
118 e.content = e.content.replace(/<img[^>]+>/g, function( image ) { |
121 event.content = event.content.replace( /-->\s+<!--/g, '--><!--' ); |
119 var match, moretext = ''; |
122 } |
|
123 } |
|
124 |
|
125 if ( event.content.indexOf( '<script' ) !== -1 || event.content.indexOf( '<style' ) !== -1 ) { |
|
126 event.content = event.content.replace( /<(script|style)[^>]*>[\s\S]*?<\/\1>/g, function( match, tag ) { |
|
127 return '<img ' + |
|
128 'src="' + tinymce.Env.transparentSrc + '" ' + |
|
129 'data-wp-preserve="' + encodeURIComponent( match ) + '" ' + |
|
130 'data-mce-resize="false" ' + |
|
131 'data-mce-placeholder="1" '+ |
|
132 'class="mce-object" ' + |
|
133 'width="20" height="20" '+ |
|
134 'alt="<' + tag + '>" ' + |
|
135 'title="<' + tag + '>" ' + |
|
136 '/>'; |
|
137 } ); |
|
138 } |
|
139 } |
|
140 }); |
|
141 |
|
142 editor.on( 'setcontent', function() { |
|
143 // Remove spaces from empty paragraphs. |
|
144 editor.$( 'p' ).each( function( i, node ) { |
|
145 if ( node.innerHTML && node.innerHTML.length < 10 ) { |
|
146 var html = tinymce.trim( node.innerHTML ); |
|
147 |
|
148 if ( ! html || html === ' ' ) { |
|
149 node.innerHTML = ( tinymce.Env.ie && tinymce.Env.ie < 11 ) ? '' : '<br data-mce-bogus="1">'; |
|
150 } |
|
151 } |
|
152 } ); |
|
153 }); |
|
154 |
|
155 editor.on( 'PostProcess', function( event ) { |
|
156 if ( event.get ) { |
|
157 event.content = event.content.replace(/<img[^>]+>/g, function( image ) { |
|
158 var match, |
|
159 string, |
|
160 moretext = ''; |
120 |
161 |
121 if ( image.indexOf( 'data-wp-more="more"' ) !== -1 ) { |
162 if ( image.indexOf( 'data-wp-more="more"' ) !== -1 ) { |
122 if ( match = image.match( /data-wp-more-text="([^"]+)"/ ) ) { |
163 if ( match = image.match( /data-wp-more-text="([^"]+)"/ ) ) { |
123 moretext = match[1]; |
164 moretext = match[1]; |
124 } |
165 } |
125 |
166 |
126 image = '<!--more' + moretext + '-->'; |
167 string = '<!--more' + moretext + '-->'; |
127 } else if ( image.indexOf( 'data-wp-more="nextpage"' ) !== -1 ) { |
168 } else if ( image.indexOf( 'data-wp-more="nextpage"' ) !== -1 ) { |
128 image = '<!--nextpage-->'; |
169 string = '<!--nextpage-->'; |
129 } |
170 } else if ( image.indexOf( 'data-wp-preserve' ) !== -1 ) { |
130 |
171 if ( match = image.match( / data-wp-preserve="([^"]+)"/ ) ) { |
131 return image; |
172 string = decodeURIComponent( match[1] ); |
|
173 } |
|
174 } |
|
175 |
|
176 return string || image; |
132 }); |
177 }); |
133 } |
178 } |
134 }); |
179 }); |
135 |
180 |
136 // Display the tag name instead of img in element path |
181 // Display the tag name instead of img in element path |
189 editor.addCommand( 'WP_Page', function() { |
235 editor.addCommand( 'WP_Page', function() { |
190 editor.execCommand( 'WP_More', 'nextpage' ); |
236 editor.execCommand( 'WP_More', 'nextpage' ); |
191 }); |
237 }); |
192 |
238 |
193 editor.addCommand( 'WP_Help', function() { |
239 editor.addCommand( 'WP_Help', function() { |
194 editor.windowManager.open({ |
240 var access = tinymce.Env.mac ? __( 'Ctrl + Alt + letter:' ) : __( 'Shift + Alt + letter:' ), |
195 url: tinymce.baseURL + '/wp-mce-help.php', |
241 meta = tinymce.Env.mac ? __( 'Cmd + letter:' ) : __( 'Ctrl + letter:' ), |
|
242 table1 = [], |
|
243 table2 = [], |
|
244 row1 = {}, |
|
245 row2 = {}, |
|
246 i1 = 0, |
|
247 i2 = 0, |
|
248 labels = editor.settings.wp_shortcut_labels, |
|
249 header, html, dialog, $wrap; |
|
250 |
|
251 if ( ! labels ) { |
|
252 return; |
|
253 } |
|
254 |
|
255 function tr( row, columns ) { |
|
256 var out = '<tr>'; |
|
257 var i = 0; |
|
258 |
|
259 columns = columns || 1; |
|
260 |
|
261 each( row, function( text, key ) { |
|
262 out += '<td><kbd>' + key + '</kbd></td><td>' + __( text ) + '</td>'; |
|
263 i++; |
|
264 }); |
|
265 |
|
266 while ( i < columns ) { |
|
267 out += '<td></td><td></td>'; |
|
268 i++; |
|
269 } |
|
270 |
|
271 return out + '</tr>'; |
|
272 } |
|
273 |
|
274 each ( labels, function( label, name ) { |
|
275 var letter; |
|
276 |
|
277 if ( label.indexOf( 'meta' ) !== -1 ) { |
|
278 i1++; |
|
279 letter = label.replace( 'meta', '' ).toLowerCase(); |
|
280 |
|
281 if ( letter ) { |
|
282 row1[ letter ] = name; |
|
283 |
|
284 if ( i1 % 2 === 0 ) { |
|
285 table1.push( tr( row1, 2 ) ); |
|
286 row1 = {}; |
|
287 } |
|
288 } |
|
289 } else if ( label.indexOf( 'access' ) !== -1 ) { |
|
290 i2++; |
|
291 letter = label.replace( 'access', '' ).toLowerCase(); |
|
292 |
|
293 if ( letter ) { |
|
294 row2[ letter ] = name; |
|
295 |
|
296 if ( i2 % 2 === 0 ) { |
|
297 table2.push( tr( row2, 2 ) ); |
|
298 row2 = {}; |
|
299 } |
|
300 } |
|
301 } |
|
302 } ); |
|
303 |
|
304 // Add remaining single entries. |
|
305 if ( i1 % 2 > 0 ) { |
|
306 table1.push( tr( row1, 2 ) ); |
|
307 } |
|
308 |
|
309 if ( i2 % 2 > 0 ) { |
|
310 table2.push( tr( row2, 2 ) ); |
|
311 } |
|
312 |
|
313 header = [ __( 'Letter' ), __( 'Action' ), __( 'Letter' ), __( 'Action' ) ]; |
|
314 header = '<tr><th>' + header.join( '</th><th>' ) + '</th></tr>'; |
|
315 |
|
316 html = '<div class="wp-editor-help">'; |
|
317 |
|
318 // Main section, default and additional shortcuts |
|
319 html = html + |
|
320 '<h2>' + __( 'Default shortcuts,' ) + ' ' + meta + '</h2>' + |
|
321 '<table class="wp-help-th-center fixed">' + |
|
322 header + |
|
323 table1.join('') + |
|
324 '</table>' + |
|
325 '<h2>' + __( 'Additional shortcuts,' ) + ' ' + access + '</h2>' + |
|
326 '<table class="wp-help-th-center fixed">' + |
|
327 header + |
|
328 table2.join('') + |
|
329 '</table>'; |
|
330 |
|
331 if ( editor.plugins.wptextpattern && ( ! tinymce.Env.ie || tinymce.Env.ie > 8 ) ) { |
|
332 // Text pattern section |
|
333 html = html + |
|
334 '<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>' + |
|
335 '<table class="wp-help-th-center fixed">' + |
|
336 tr({ '*': 'Bullet list', '1.': 'Numbered list' }) + |
|
337 tr({ '-': 'Bullet list', '1)': 'Numbered list' }) + |
|
338 '</table>'; |
|
339 |
|
340 html = html + |
|
341 '<h2>' + __( 'The following formatting shortcuts are replaced when pressing Enter. Press Escape or the Undo button to undo.' ) + '</h2>' + |
|
342 '<table class="wp-help-single">' + |
|
343 tr({ '>': 'Blockquote' }) + |
|
344 tr({ '##': 'Heading 2' }) + |
|
345 tr({ '###': 'Heading 3' }) + |
|
346 tr({ '####': 'Heading 4' }) + |
|
347 tr({ '#####': 'Heading 5' }) + |
|
348 tr({ '######': 'Heading 6' }) + |
|
349 tr({ '---': 'Horizontal line' }) + |
|
350 '</table>'; |
|
351 } |
|
352 |
|
353 // Focus management section |
|
354 html = html + |
|
355 '<h2>' + __( 'Focus shortcuts:' ) + '</h2>' + |
|
356 '<table class="wp-help-single">' + |
|
357 tr({ 'Alt + F8': 'Inline toolbar (when an image, link or preview is selected)' }) + |
|
358 tr({ 'Alt + F9': 'Editor menu (when enabled)' }) + |
|
359 tr({ 'Alt + F10': 'Editor toolbar' }) + |
|
360 tr({ 'Alt + F11': 'Elements path' }) + |
|
361 '</table>' + |
|
362 '<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>'; |
|
363 |
|
364 html += '</div>'; |
|
365 |
|
366 dialog = editor.windowManager.open( { |
196 title: 'Keyboard Shortcuts', |
367 title: 'Keyboard Shortcuts', |
197 width: 450, |
368 items: { |
198 height: 420, |
369 type: 'container', |
199 classes: 'wp-help', |
370 classes: 'wp-help', |
200 buttons: { text: 'Close', onclick: 'close' } |
371 html: html |
201 }); |
372 }, |
202 }); |
373 buttons: { |
|
374 text: 'Close', |
|
375 onclick: 'close' |
|
376 } |
|
377 } ); |
|
378 |
|
379 if ( dialog.$el ) { |
|
380 dialog.$el.find( 'div[role="application"]' ).attr( 'role', 'document' ); |
|
381 $wrap = dialog.$el.find( '.mce-wp-help' ); |
|
382 |
|
383 if ( $wrap[0] ) { |
|
384 $wrap.attr( 'tabindex', '0' ); |
|
385 $wrap[0].focus(); |
|
386 $wrap.on( 'keydown', function( event ) { |
|
387 // Prevent use of: page up, page down, end, home, left arrow, up arrow, right arrow, down arrow |
|
388 // in the dialog keydown handler. |
|
389 if ( event.keyCode >= 33 && event.keyCode <= 40 ) { |
|
390 event.stopPropagation(); |
|
391 } |
|
392 }); |
|
393 } |
|
394 } |
|
395 } ); |
203 |
396 |
204 editor.addCommand( 'WP_Medialib', function() { |
397 editor.addCommand( 'WP_Medialib', function() { |
205 if ( typeof wp !== 'undefined' && wp.media && wp.media.editor ) { |
398 if ( wp && wp.media && wp.media.editor ) { |
206 wp.media.editor.open( editor.id ); |
399 wp.media.editor.open( editor.id ); |
207 } |
400 } |
208 }); |
401 }); |
209 |
402 |
210 // Register buttons |
403 // Register buttons |
317 dom.addClass( doc.body, cls ); |
512 dom.addClass( doc.body, cls ); |
318 } |
513 } |
319 }); |
514 }); |
320 |
515 |
321 // Remove invalid parent paragraphs when inserting HTML |
516 // Remove invalid parent paragraphs when inserting HTML |
322 // TODO: still needed? |
517 editor.on( 'BeforeSetContent', function( event ) { |
323 editor.on( 'BeforeSetContent', function( e ) { |
518 if ( event.content ) { |
324 if ( e.content ) { |
519 event.content = event.content.replace( /<p>\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)( [^>]*)?>/gi, '<$1$2>' ) |
325 e.content = e.content.replace(/<p>\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)( [^>]*)?>/gi, '<$1$2>'); |
520 .replace( /<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)>\s*<\/p>/gi, '</$1>' ); |
326 e.content = e.content.replace(/<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)>\s*<\/p>/gi, '</$1>'); |
|
327 } |
521 } |
328 }); |
522 }); |
329 |
523 |
330 if ( typeof window.jQuery !== 'undefined' ) { |
524 if ( $ ) { |
331 window.jQuery( document ).triggerHandler( 'tinymce-editor-init', [editor] ); |
525 $( document ).triggerHandler( 'tinymce-editor-init', [editor] ); |
332 } |
526 } |
333 |
527 |
334 if ( window.tinyMCEPreInit && window.tinyMCEPreInit.dragDropUpload ) { |
528 if ( window.tinyMCEPreInit && window.tinyMCEPreInit.dragDropUpload ) { |
335 dom.bind( doc, 'dragstart dragend dragover drop', function( event ) { |
529 dom.bind( doc, 'dragstart dragend dragover drop', function( event ) { |
336 if ( typeof window.jQuery !== 'undefined' ) { |
530 if ( $ ) { |
337 // Trigger the jQuery handlers. |
531 // Trigger the jQuery handlers. |
338 window.jQuery( document ).trigger( new window.jQuery.Event( event ) ); |
532 $( document ).trigger( new $.Event( event ) ); |
339 } |
533 } |
340 }); |
534 }); |
341 } |
535 } |
342 |
536 |
343 if ( editor.getParam( 'wp_paste_filters', true ) ) { |
537 if ( editor.getParam( 'wp_paste_filters', true ) ) { |
344 if ( ! tinymce.Env.webkit ) { |
538 editor.on( 'PastePreProcess', function( event ) { |
345 // In WebKit handled by removeWebKitStyles() |
539 // Remove trailing <br> added by WebKit browsers to the clipboard |
346 editor.on( 'PastePreProcess', function( event ) { |
540 event.content = event.content.replace( /<br class="?Apple-interchange-newline"?>/gi, '' ); |
|
541 |
|
542 // In WebKit this is handled by removeWebKitStyles() |
|
543 if ( ! tinymce.Env.webkit ) { |
347 // Remove all inline styles |
544 // Remove all inline styles |
348 event.content = event.content.replace( /(<[^>]+) style="[^"]*"([^>]*>)/gi, '$1$2' ); |
545 event.content = event.content.replace( /(<[^>]+) style="[^"]*"([^>]*>)/gi, '$1$2' ); |
349 |
546 |
350 // Put back the internal styles |
547 // Put back the internal styles |
351 event.content = event.content.replace(/(<[^>]+) data-mce-style=([^>]+>)/gi, '$1 style=$2' ); |
548 event.content = event.content.replace(/(<[^>]+) data-mce-style=([^>]+>)/gi, '$1 style=$2' ); |
352 }); |
549 } |
353 } |
550 }); |
354 |
551 |
355 editor.on( 'PastePostProcess', function( event ) { |
552 editor.on( 'PastePostProcess', function( event ) { |
356 // Remove empty paragraphs |
553 // Remove empty paragraphs |
357 each( dom.select( 'p', event.node ), function( node ) { |
554 editor.$( 'p', event.node ).each( function( i, node ) { |
358 if ( dom.isEmpty( node ) ) { |
555 if ( dom.isEmpty( node ) ) { |
359 dom.remove( node ); |
556 dom.remove( node ); |
360 } |
557 } |
361 }); |
558 }); |
|
559 |
|
560 if ( tinymce.isIE ) { |
|
561 editor.$( 'a', event.node ).find( 'font, u' ).each( function( i, node ) { |
|
562 dom.remove( node, true ); |
|
563 }); |
|
564 } |
362 }); |
565 }); |
363 } |
566 } |
364 }); |
567 |
365 |
568 if ( editor.settings.wp_shortcut_labels && editor.theme.panel ) { |
366 // Word count |
569 var labels = {}; |
367 if ( typeof window.jQuery !== 'undefined' ) { |
570 var access = 'Shift+Alt+'; |
368 editor.on( 'keyup', function( e ) { |
571 var meta = 'Ctrl+'; |
369 var key = e.keyCode || e.charCode; |
572 |
370 |
573 // For Mac: ctrl = \u2303, cmd = \u2318, alt = \u2325 |
371 if ( key === last ) { |
574 |
372 return; |
575 if ( tinymce.Env.mac ) { |
373 } |
576 access = '\u2303\u2325'; |
374 |
577 meta = '\u2318'; |
375 if ( 13 === key || 8 === last || 46 === last ) { |
578 } |
376 window.jQuery( document ).triggerHandler( 'wpcountwords', [ editor.getContent({ format : 'raw' }) ] ); |
579 |
377 } |
580 each( editor.settings.wp_shortcut_labels, function( value, name ) { |
378 |
581 labels[ name ] = value.replace( 'access', access ).replace( 'meta', meta ); |
379 last = key; |
582 } ); |
380 }); |
583 |
381 } |
584 each( editor.theme.panel.find('button'), function( button ) { |
382 |
585 if ( button && button.settings.tooltip && labels.hasOwnProperty( button.settings.tooltip ) ) { |
383 editor.on( 'SaveContent', function( e ) { |
586 // Need to translate now. We are changing the string so it won't match and cannot be translated later. |
|
587 button.settings.tooltip = editor.translate( button.settings.tooltip ) + ' (' + labels[ button.settings.tooltip ] + ')'; |
|
588 } |
|
589 } ); |
|
590 |
|
591 // listbox for the "blocks" drop-down |
|
592 each( editor.theme.panel.find('listbox'), function( listbox ) { |
|
593 if ( listbox && listbox.settings.text === 'Paragraph' ) { |
|
594 each( listbox.settings.values, function( item ) { |
|
595 if ( item.text && labels.hasOwnProperty( item.text ) ) { |
|
596 item.shortcut = '(' + labels[ item.text ] + ')'; |
|
597 } |
|
598 } ); |
|
599 } |
|
600 } ); |
|
601 } |
|
602 }); |
|
603 |
|
604 editor.on( 'SaveContent', function( event ) { |
384 // If editor is hidden, we just want the textarea's value to be saved |
605 // If editor is hidden, we just want the textarea's value to be saved |
385 if ( ! editor.inline && editor.isHidden() ) { |
606 if ( ! editor.inline && editor.isHidden() ) { |
386 e.content = e.element.value; |
607 event.content = event.element.value; |
387 return; |
608 return; |
388 } |
609 } |
389 |
610 |
390 // Keep empty paragraphs :( |
611 // Keep empty paragraphs :( |
391 e.content = e.content.replace( /<p>(?:<br ?\/?>|\u00a0|\uFEFF| )*<\/p>/g, '<p> </p>' ); |
612 event.content = event.content.replace( /<p>(?:<br ?\/?>|\u00a0|\uFEFF| )*<\/p>/g, '<p> </p>' ); |
392 |
613 |
393 if ( editor.getParam( 'wpautop', true ) && typeof window.switchEditors !== 'undefined' ) { |
614 if ( hasWpautop ) { |
394 e.content = window.switchEditors.pre_wpautop( e.content ); |
615 event.content = wp.editor.removep( event.content ); |
395 } |
616 } else { |
396 }); |
617 // Restore formatting of block boundaries. |
397 |
618 event.content = event.content.replace( /-->\s*<!-- wp:/g, '-->\n\n<!-- wp:' ); |
398 // Remove spaces from empty paragraphs. |
|
399 editor.on( 'BeforeSetContent', function( event ) { |
|
400 var paragraph = tinymce.Env.webkit ? '<p><br /></p>' : '<p></p>'; |
|
401 |
|
402 if ( event.content ) { |
|
403 event.content = event.content.replace( /<p>(?: |\u00a0|\uFEFF|\s)+<\/p>/gi, paragraph ); |
|
404 } |
619 } |
405 }); |
620 }); |
406 |
621 |
407 editor.on( 'preInit', function() { |
622 editor.on( 'preInit', function() { |
408 // Don't replace <i> with <em> and <b> with <strong> and don't remove them when empty |
623 var validElementsSetting = '@[id|accesskey|class|dir|lang|style|tabindex|' + |
409 editor.schema.addValidElements( '@[id|accesskey|class|dir|lang|style|tabindex|title|contenteditable|draggable|dropzone|hidden|spellcheck|translate],i,b' ); |
624 'title|contenteditable|draggable|dropzone|hidden|spellcheck|translate],' + // Global attributes. |
|
625 'i,' + // Don't replace <i> with <em> and <b> with <strong> and don't remove them when empty. |
|
626 'b,' + |
|
627 'script[src|async|defer|type|charset|crossorigin|integrity]'; // Add support for <script>. |
|
628 |
|
629 editor.schema.addValidElements( validElementsSetting ); |
410 |
630 |
411 if ( tinymce.Env.iOS ) { |
631 if ( tinymce.Env.iOS ) { |
412 editor.settings.height = 300; |
632 editor.settings.height = 300; |
413 } |
633 } |
414 |
634 |
431 }, function( command, key ) { |
650 }, function( command, key ) { |
432 editor.shortcuts.add( 'access+' + key, '', command ); |
651 editor.shortcuts.add( 'access+' + key, '', command ); |
433 } ); |
652 } ); |
434 |
653 |
435 editor.addShortcut( 'meta+s', '', function() { |
654 editor.addShortcut( 'meta+s', '', function() { |
436 if ( typeof wp !== 'undefined' && wp.autosave ) { |
655 if ( wp && wp.autosave ) { |
437 wp.autosave.server.triggerSave(); |
656 wp.autosave.server.triggerSave(); |
438 } |
657 } |
439 } ); |
658 } ); |
|
659 |
|
660 if ( window.getUserSetting( 'editor_plain_text_paste_warning' ) > 1 ) { |
|
661 editor.settings.paste_plaintext_inform = false; |
|
662 } |
|
663 |
|
664 // Change the editor iframe title on MacOS, add the correct help shortcut. |
|
665 if ( tinymce.Env.mac ) { |
|
666 tinymce.$( editor.iframeElement ).attr( 'title', __( 'Rich Text Area. Press Control-Option-H for help.' ) ); |
|
667 } |
440 } ); |
668 } ); |
|
669 |
|
670 editor.on( 'PastePlainTextToggle', function( event ) { |
|
671 // Warn twice, then stop. |
|
672 if ( event.state === true ) { |
|
673 var times = parseInt( window.getUserSetting( 'editor_plain_text_paste_warning' ), 10 ) || 0; |
|
674 |
|
675 if ( times < 2 ) { |
|
676 window.setUserSetting( 'editor_plain_text_paste_warning', ++times ); |
|
677 } |
|
678 } |
|
679 }); |
441 |
680 |
442 /** |
681 /** |
443 * Experimental: create a floating toolbar. |
682 * Experimental: create a floating toolbar. |
444 * This functionality will change in the next releases. Not recommended for use by plugins. |
683 * This functionality will change in the next releases. Not recommended for use by plugins. |
445 */ |
684 */ |
446 ( function() { |
685 editor.on( 'preinit', function() { |
447 var Factory = tinymce.ui.Factory, |
686 var Factory = tinymce.ui.Factory, |
448 settings = editor.settings, |
687 settings = editor.settings, |
449 currentToolbar, |
688 activeToolbar, |
450 currentSelection; |
689 currentSelection, |
451 |
690 timeout, |
452 function create( buttons ) { |
691 container = editor.getContainer(), |
|
692 wpAdminbar = document.getElementById( 'wpadminbar' ), |
|
693 mceIframe = document.getElementById( editor.id + '_ifr' ), |
|
694 mceToolbar, |
|
695 mceStatusbar, |
|
696 wpStatusbar, |
|
697 isChromeRtl = ( editor.rtl && /Chrome/.test( navigator.userAgent ) ); |
|
698 |
|
699 if ( container ) { |
|
700 mceToolbar = tinymce.$( '.mce-toolbar-grp', container )[0]; |
|
701 mceStatusbar = tinymce.$( '.mce-statusbar', container )[0]; |
|
702 } |
|
703 |
|
704 if ( editor.id === 'content' ) { |
|
705 wpStatusbar = document.getElementById( 'post-status-info' ); |
|
706 } |
|
707 |
|
708 function create( buttons, bottom ) { |
453 var toolbar, |
709 var toolbar, |
454 toolbarItems = [], |
710 toolbarItems = [], |
455 buttonGroup; |
711 buttonGroup; |
456 |
712 |
457 each( buttons, function( item ) { |
713 each( buttons, function( item ) { |
571 layout: 'flow', |
827 layout: 'flow', |
572 items: toolbarItems |
828 items: toolbarItems |
573 } ] |
829 } ] |
574 } ); |
830 } ); |
575 |
831 |
576 function hide() { |
832 toolbar.bottom = bottom; |
577 toolbar.hide(); |
|
578 } |
|
579 |
833 |
580 function reposition() { |
834 function reposition() { |
581 var top, left, minTop, className, |
835 if ( ! currentSelection ) { |
582 windowPos, adminbar, mceToolbar, boundary, |
836 return this; |
583 boundaryMiddle, boundaryVerticalMiddle, spaceTop, |
837 } |
584 spaceBottom, windowWidth, toolbarWidth, toolbarHalf, |
838 |
585 iframe, iframePos, iframeWidth, iframeHeigth, |
839 var scrollX = window.pageXOffset || document.documentElement.scrollLeft, |
586 toolbarNodeHeight, verticalSpaceNeeded, |
840 scrollY = window.pageYOffset || document.documentElement.scrollTop, |
587 toolbarNode = this.getEl(), |
841 windowWidth = window.innerWidth, |
|
842 windowHeight = window.innerHeight, |
|
843 iframeRect = mceIframe ? mceIframe.getBoundingClientRect() : { |
|
844 top: 0, |
|
845 right: windowWidth, |
|
846 bottom: windowHeight, |
|
847 left: 0, |
|
848 width: windowWidth, |
|
849 height: windowHeight |
|
850 }, |
|
851 toolbar = this.getEl(), |
|
852 toolbarWidth = toolbar.offsetWidth, |
|
853 toolbarHeight = toolbar.clientHeight, |
|
854 selection = currentSelection.getBoundingClientRect(), |
|
855 selectionMiddle = ( selection.left + selection.right ) / 2, |
588 buffer = 5, |
856 buffer = 5, |
589 margin = 8, |
857 spaceNeeded = toolbarHeight + buffer, |
590 adminbarHeight = 0; |
858 wpAdminbarBottom = wpAdminbar ? wpAdminbar.getBoundingClientRect().bottom : 0, |
591 |
859 mceToolbarBottom = mceToolbar ? mceToolbar.getBoundingClientRect().bottom : 0, |
592 if ( ! currentSelection ) { |
860 mceStatusbarTop = mceStatusbar ? windowHeight - mceStatusbar.getBoundingClientRect().top : 0, |
593 return; |
861 wpStatusbarTop = wpStatusbar ? windowHeight - wpStatusbar.getBoundingClientRect().top : 0, |
594 } |
862 blockedTop = Math.max( 0, wpAdminbarBottom, mceToolbarBottom, iframeRect.top ), |
595 |
863 blockedBottom = Math.max( 0, mceStatusbarTop, wpStatusbarTop, windowHeight - iframeRect.bottom ), |
596 windowPos = window.pageYOffset || document.documentElement.scrollTop; |
864 spaceTop = selection.top + iframeRect.top - blockedTop, |
597 adminbar = tinymce.$( '#wpadminbar' )[0]; |
865 spaceBottom = windowHeight - iframeRect.top - selection.bottom - blockedBottom, |
598 mceToolbar = tinymce.$( '.mce-toolbar-grp', editor.getContainer() )[0]; |
866 editorHeight = windowHeight - blockedTop - blockedBottom, |
599 boundary = currentSelection.getBoundingClientRect(); |
867 className = '', |
600 boundaryMiddle = ( boundary.left + boundary.right ) / 2; |
868 iosOffsetTop = 0, |
601 boundaryVerticalMiddle = ( boundary.top + boundary.bottom ) / 2; |
869 iosOffsetBottom = 0, |
602 spaceTop = boundary.top; |
870 top, left; |
603 spaceBottom = iframeHeigth - boundary.bottom; |
871 |
604 windowWidth = window.innerWidth; |
872 if ( spaceTop >= editorHeight || spaceBottom >= editorHeight ) { |
605 toolbarWidth = toolbarNode.offsetWidth; |
873 this.scrolling = true; |
606 toolbarHalf = toolbarWidth / 2; |
874 this.hide(); |
607 iframe = document.getElementById( editor.id + '_ifr' ); |
875 this.scrolling = false; |
608 iframePos = DOM.getPos( iframe ); |
876 return this; |
609 iframeWidth = iframe.offsetWidth; |
877 } |
610 iframeHeigth = iframe.offsetHeight; |
878 |
611 toolbarNodeHeight = toolbarNode.offsetHeight; |
879 // Add offset in iOS to move the menu over the image, out of the way of the default iOS menu. |
612 verticalSpaceNeeded = toolbarNodeHeight + margin + buffer; |
880 if ( tinymce.Env.iOS && currentSelection.nodeName === 'IMG' ) { |
613 |
881 iosOffsetTop = 54; |
614 if ( spaceTop >= verticalSpaceNeeded ) { |
882 iosOffsetBottom = 46; |
615 className = ' mce-arrow-down'; |
883 } |
616 top = boundary.top + iframePos.y - toolbarNodeHeight - margin; |
884 |
617 } else if ( spaceBottom >= verticalSpaceNeeded ) { |
885 if ( this.bottom ) { |
618 className = ' mce-arrow-up'; |
886 if ( spaceBottom >= spaceNeeded ) { |
619 top = boundary.bottom + iframePos.y; |
887 className = ' mce-arrow-up'; |
|
888 top = selection.bottom + iframeRect.top + scrollY - iosOffsetBottom; |
|
889 } else if ( spaceTop >= spaceNeeded ) { |
|
890 className = ' mce-arrow-down'; |
|
891 top = selection.top + iframeRect.top + scrollY - toolbarHeight + iosOffsetTop; |
|
892 } |
620 } else { |
893 } else { |
621 top = buffer; |
894 if ( spaceTop >= spaceNeeded ) { |
622 |
|
623 if ( boundaryVerticalMiddle >= verticalSpaceNeeded ) { |
|
624 className = ' mce-arrow-down'; |
895 className = ' mce-arrow-down'; |
625 } else { |
896 top = selection.top + iframeRect.top + scrollY - toolbarHeight + iosOffsetTop; |
|
897 } else if ( spaceBottom >= spaceNeeded && editorHeight / 2 > selection.bottom + iframeRect.top - blockedTop ) { |
626 className = ' mce-arrow-up'; |
898 className = ' mce-arrow-up'; |
627 } |
899 top = selection.bottom + iframeRect.top + scrollY - iosOffsetBottom; |
628 } |
900 } |
629 |
901 } |
630 // Make sure the image toolbar is below the main toolbar. |
902 |
631 if ( mceToolbar ) { |
903 if ( typeof top === 'undefined' ) { |
632 minTop = DOM.getPos( mceToolbar ).y + mceToolbar.clientHeight; |
904 top = scrollY + blockedTop + buffer + iosOffsetBottom; |
633 } else { |
905 } |
634 minTop = iframePos.y; |
906 |
635 } |
907 left = selectionMiddle - toolbarWidth / 2 + iframeRect.left + scrollX; |
636 |
908 |
637 // Make sure the image toolbar is below the adminbar (if visible) or below the top of the window. |
909 if ( selection.left < 0 || selection.right > iframeRect.width ) { |
638 if ( windowPos ) { |
910 left = iframeRect.left + scrollX + ( iframeRect.width - toolbarWidth ) / 2; |
639 if ( adminbar && adminbar.getBoundingClientRect().top === 0 ) { |
|
640 adminbarHeight = adminbar.clientHeight; |
|
641 } |
|
642 |
|
643 if ( windowPos + adminbarHeight > minTop ) { |
|
644 minTop = windowPos + adminbarHeight; |
|
645 } |
|
646 } |
|
647 |
|
648 if ( top && minTop && ( minTop + buffer > top ) ) { |
|
649 top = minTop + buffer; |
|
650 className = ''; |
|
651 } |
|
652 |
|
653 left = boundaryMiddle - toolbarHalf; |
|
654 left += iframePos.x; |
|
655 |
|
656 if ( boundary.left < 0 || boundary.right > iframeWidth ) { |
|
657 left = iframePos.x + ( iframeWidth - toolbarWidth ) / 2; |
|
658 } else if ( toolbarWidth >= windowWidth ) { |
911 } else if ( toolbarWidth >= windowWidth ) { |
659 className += ' mce-arrow-full'; |
912 className += ' mce-arrow-full'; |
660 left = 0; |
913 left = 0; |
661 } else if ( ( left < 0 && boundary.left + toolbarWidth > windowWidth ) || |
914 } else if ( ( left < 0 && selection.left + toolbarWidth > windowWidth ) || ( left + toolbarWidth > windowWidth && selection.right - toolbarWidth < 0 ) ) { |
662 ( left + toolbarWidth > windowWidth && boundary.right - toolbarWidth < 0 ) ) { |
|
663 |
|
664 left = ( windowWidth - toolbarWidth ) / 2; |
915 left = ( windowWidth - toolbarWidth ) / 2; |
665 } else if ( left < iframePos.x ) { |
916 } else if ( left < iframeRect.left + scrollX ) { |
666 className += ' mce-arrow-left'; |
917 className += ' mce-arrow-left'; |
667 left = boundary.left + iframePos.x; |
918 left = selection.left + iframeRect.left + scrollX; |
668 } else if ( left + toolbarWidth > iframeWidth + iframePos.x ) { |
919 } else if ( left + toolbarWidth > iframeRect.width + iframeRect.left + scrollX ) { |
669 className += ' mce-arrow-right'; |
920 className += ' mce-arrow-right'; |
670 left = boundary.right - toolbarWidth + iframePos.x; |
921 left = selection.right - toolbarWidth + iframeRect.left + scrollX; |
671 } |
922 } |
672 |
923 |
673 toolbarNode.className = toolbarNode.className.replace( / ?mce-arrow-[\w]+/g, '' ); |
924 // No up/down arrows on the menu over images in iOS. |
674 toolbarNode.className += className; |
925 if ( tinymce.Env.iOS && currentSelection.nodeName === 'IMG' ) { |
675 |
926 className = className.replace( / ?mce-arrow-(up|down)/g, '' ); |
676 DOM.setStyles( toolbarNode, { 'left': left, 'top': top } ); |
927 } |
|
928 |
|
929 toolbar.className = toolbar.className.replace( / ?mce-arrow-[\w]+/g, '' ) + className; |
|
930 |
|
931 DOM.setStyles( toolbar, { |
|
932 'left': left, |
|
933 'top': top |
|
934 } ); |
677 |
935 |
678 return this; |
936 return this; |
679 } |
937 } |
680 |
938 |
681 toolbar.on( 'show', function() { |
939 toolbar.on( 'show', function() { |
682 currentToolbar = this; |
|
683 this.reposition(); |
940 this.reposition(); |
|
941 |
|
942 if ( isChromeRtl ) { |
|
943 tinymce.$( '.mce-widget.mce-tooltip' ).addClass( 'wp-hide-mce-tooltip' ); |
|
944 } |
684 } ); |
945 } ); |
685 |
946 |
686 toolbar.on( 'hide', function() { |
947 toolbar.on( 'hide', function() { |
687 currentToolbar = false; |
948 if ( isChromeRtl ) { |
|
949 tinymce.$( '.mce-widget.mce-tooltip' ).removeClass( 'wp-hide-mce-tooltip' ); |
|
950 } |
688 } ); |
951 } ); |
689 |
952 |
690 toolbar.on( 'keydown', function( event ) { |
953 toolbar.on( 'keydown', function( event ) { |
691 if ( event.keyCode === 27 ) { |
954 if ( event.keyCode === 27 ) { |
692 this.hide(); |
955 this.hide(); |
693 editor.focus(); |
956 editor.focus(); |
694 } |
957 } |
695 } ); |
958 } ); |
696 |
959 |
697 toolbar.on( 'remove', function() { |
960 editor.on( 'remove', function() { |
698 DOM.unbind( window, 'resize scroll', hide ); |
961 toolbar.remove(); |
699 editor.dom.unbind( editor.getWin(), 'resize scroll', hide ); |
|
700 editor.off( 'blur hide', hide ); |
|
701 } ); |
|
702 |
|
703 editor.once( 'init', function() { |
|
704 DOM.bind( window, 'resize scroll', hide ); |
|
705 editor.dom.bind( editor.getWin(), 'resize scroll', hide ); |
|
706 editor.on( 'blur hide', hide ); |
|
707 } ); |
962 } ); |
708 |
963 |
709 toolbar.reposition = reposition; |
964 toolbar.reposition = reposition; |
710 toolbar.hide().renderTo( document.body ); |
965 toolbar.hide().renderTo( document.body ); |
711 |
966 |
732 |
987 |
733 editor.fire( 'wptoolbar', args ); |
988 editor.fire( 'wptoolbar', args ); |
734 |
989 |
735 currentSelection = args.selection || args.element; |
990 currentSelection = args.selection || args.element; |
736 |
991 |
737 currentToolbar && currentToolbar.hide(); |
992 if ( activeToolbar && activeToolbar !== args.toolbar ) { |
738 args.toolbar && args.toolbar.show(); |
993 activeToolbar.hide(); |
|
994 } |
|
995 |
|
996 if ( args.toolbar ) { |
|
997 activeToolbar = args.toolbar; |
|
998 |
|
999 if ( activeToolbar.visible() ) { |
|
1000 activeToolbar.reposition(); |
|
1001 } else { |
|
1002 activeToolbar.show(); |
|
1003 } |
|
1004 } else { |
|
1005 activeToolbar = false; |
|
1006 } |
739 } ); |
1007 } ); |
|
1008 |
|
1009 editor.on( 'focus', function() { |
|
1010 if ( activeToolbar ) { |
|
1011 activeToolbar.show(); |
|
1012 } |
|
1013 } ); |
|
1014 |
|
1015 function hide( event ) { |
|
1016 if ( activeToolbar ) { |
|
1017 if ( activeToolbar.tempHide || event.type === 'hide' || event.type === 'blur' ) { |
|
1018 activeToolbar.hide(); |
|
1019 activeToolbar = false; |
|
1020 } else if ( ( |
|
1021 event.type === 'resizewindow' || |
|
1022 event.type === 'scrollwindow' || |
|
1023 event.type === 'resize' || |
|
1024 event.type === 'scroll' |
|
1025 ) && ! activeToolbar.blockHide ) { |
|
1026 clearTimeout( timeout ); |
|
1027 |
|
1028 timeout = setTimeout( function() { |
|
1029 if ( activeToolbar && typeof activeToolbar.show === 'function' ) { |
|
1030 activeToolbar.scrolling = false; |
|
1031 activeToolbar.show(); |
|
1032 } |
|
1033 }, 250 ); |
|
1034 |
|
1035 activeToolbar.scrolling = true; |
|
1036 activeToolbar.hide(); |
|
1037 } |
|
1038 } |
|
1039 } |
|
1040 |
|
1041 // For full height editor. |
|
1042 editor.on( 'resizewindow scrollwindow', hide ); |
|
1043 // For scrollable editor. |
|
1044 editor.dom.bind( editor.getWin(), 'resize scroll', hide ); |
|
1045 |
|
1046 editor.on( 'remove', function() { |
|
1047 editor.off( 'resizewindow scrollwindow', hide ); |
|
1048 editor.dom.unbind( editor.getWin(), 'resize scroll', hide ); |
|
1049 } ); |
|
1050 |
|
1051 editor.on( 'blur hide', hide ); |
740 |
1052 |
741 editor.wp = editor.wp || {}; |
1053 editor.wp = editor.wp || {}; |
742 editor.wp._createToolbar = create; |
1054 editor.wp._createToolbar = create; |
743 }()); |
1055 }, true ); |
744 |
1056 |
745 function noop() {} |
1057 function noop() {} |
746 |
1058 |
747 // Expose some functions (back-compat) |
1059 // Expose some functions (back-compat) |
748 return { |
1060 return { |