Changeset 39911
- Timestamp:
- 01/16/2017 12:48:49 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/js/editor.js
r39738 r39911 2 2 ( function( $ ) { 3 3 /** 4 * @summary Creates the tinyMCE editors.4 * @summary Utility functions for the editor. 5 5 * 6 * Creates the tinyMCE editor and binds all events used for switching 7 * from visual to text mode. 8 * 9 * @since 4.3.0 10 * 11 * @class 6 * @since 2.5.0 12 7 */ 13 8 function SwitchEditors() { … … 15 10 exports = {}; 16 11 17 /**18 * @summary Initializes the event binding for switching editors.19 *20 * @since 4.3.021 *22 * @returns {void}23 */24 12 function init() { 25 13 if ( ! tinymce && window.tinymce ) { … … 28 16 29 17 /** 30 * @summary Handles onclick events for the editor buttons.18 * @summary Handles onclick events for the Visual/Text tabs. 31 19 * 32 20 * @since 4.3.0 33 *34 * Handles an onclick event on the document.35 * Switches the editor between visual and text,36 * if the clicked element has the 'wp-switch-editor' class.37 * If the class name is switch-html switches to the HTML editor,38 * if the class name is switch-tmce39 * switches to the TMCE editor.40 21 * 41 22 * @returns {void} … … 55 36 56 37 /** 57 * @summary Retrieves the height of the toolbar based on the container the 58 * editor is placed in. 38 * @summary Returns the height of the editor toolbar(s) in px. 59 39 * 60 40 * @since 3.9.0 61 41 * 62 * @param {Object} editor The tinyMCE editor.42 * @param {Object} editor The TinyMCE editor. 63 43 * @returns {number} If the height is between 10 and 200 return the height, 64 44 * else return 30. … … 76 56 77 57 /** 78 * @summary Switches the editor between visual and text.79 * 80 * @since 4.3.058 * @summary Switches the editor between Visual and Text mode. 59 * 60 * @since 2.5.0 81 61 * 82 62 * @memberof switchEditors 83 63 * 84 * @param {string} id The id of the editor you want to change the editor mode for. 85 * If no id is given, it defaults to content. 86 * @param {string} mode The mode you want to switch to. 87 * If an undefined mode is given, it defaults to toggle. 88 * 64 * @param {string} id The id of the editor you want to change the editor mode for. Default: `content`. 65 * @param {string} mode The mode you want to switch to. Default: `toggle`. 89 66 * @returns {void} 90 67 */ … … 99 76 textarea = $textarea[0]; 100 77 101 // Toggle the mode between visual and textual representation.102 78 if ( 'toggle' === mode ) { 103 79 if ( editor && ! editor.isHidden() ) { … … 108 84 } 109 85 110 111 // If the mode is tmce or tinymce, show the editor.112 86 if ( 'tmce' === mode || 'tinymce' === mode ) { 113 114 /* 115 * If the editor isn't hidden we are already in tmce mode 116 * and we don't need to switch. 117 * Return false to stop event bubbling. 118 */ 87 // If the editor is visible we are already in `tinymce` mode. 119 88 if ( editor && ! editor.isHidden() ) { 120 89 return false; 121 90 } 122 91 123 // Close the QuickTags toolbars if they are visible.92 // Insert closing tags for any open tags in QuickTags. 124 93 if ( typeof( window.QTags ) !== 'undefined' ) { 125 94 window.QTags.closeAllTags( id ); … … 131 100 editor.show(); 132 101 133 // Don'tresize the iframe in iOS.102 // No point to resize the iframe in iOS. 134 103 if ( ! tinymce.Env.iOS && editorHeight ) { 135 104 toolbarHeight = getToolbarHeight( editor ); 136 105 editorHeight = editorHeight - toolbarHeight + 14; 137 106 138 // Height must be between 50 and 5000.107 // Sane limit for the editor height. 139 108 if ( editorHeight > 50 && editorHeight < 5000 ) { 140 109 editor.theme.resizeTo( null, editorHeight ); … … 149 118 window.setUserSetting( 'editor', 'tinymce' ); 150 119 151 // Hide the editor if mode is html.152 120 } else if ( 'html' === mode ) { 153 154 /* 155 * If the editor is hidden we are already in html mode and 156 * we don't need to switch. 157 * Return false to stop event bubbling. 158 */ 121 // If the editor is hidden (Quicktags is shown) we don't need to switch. 159 122 if ( editor && editor.isHidden() ) { 160 123 return false; … … 162 125 163 126 if ( editor ) { 164 165 // Don't resize the iframe in iOS. 127 // Don't resize the textarea in iOS. The iframe is forced to 100% height there, we shouldn't match it. 166 128 if ( ! tinymce.Env.iOS ) { 167 129 iframe = editor.iframeElement; … … 172 134 editorHeight = editorHeight + toolbarHeight - 14; 173 135 174 // Height must be between 50 and 5000.136 // Sane limit for the textarea height. 175 137 if ( editorHeight > 50 && editorHeight < 5000 ) { 176 138 textarea.style.height = editorHeight + 'px'; … … 181 143 editor.hide(); 182 144 } else { 183 // The TinyMCE instance doesn't exist, show the textarea.145 // There is probably a JS error on the page. The TinyMCE editor instance doesn't exist. Show the textarea. 184 146 $textarea.css({ 'display': '', 'visibility': '' }); 185 147 } … … 192 154 193 155 /** 194 * @summary Replaces all paragraphs with double line breaks. 195 * 196 * Replaces all paragraphs with double line breaks. Taking into account 197 * the elements where the <p> should be preserved. 198 * Unifies all whitespaces. 199 * Adds indenting with tabs to li, dt and dd elements. 200 * Trims whitespaces from beginning and end of the html input. 201 * 202 * @since 4.3.0 156 * @summary Replaces <p> tags with two line breaks. "Opposite" of wpautop(). 157 * 158 * Replaces <p> tags with two line breaks except where the <p> has attributes. 159 * Unifies whitespace. 160 * Indents <li>, <dt> and <dd> for better readability. 161 * 162 * @since 2.5.0 203 163 * 204 164 * @memberof switchEditors 205 165 * 206 166 * @param {string} html The content from the editor. 207 * @return {string} The formatted html string.167 * @return {string} The content with stripped paragraph tags. 208 168 */ 209 169 function removep( html ) { … … 219 179 } 220 180 221 /* 222 * Protect script and style tags by replacing them with <wp-preserve>. 223 * Push matches into the preserve array. 224 */ 181 // Protect script and style tags. 225 182 if ( html.indexOf( '<script' ) !== -1 || html.indexOf( '<style' ) !== -1 ) { 226 183 html = html.replace( /<(script|style)[^>]*>[\s\S]*?<\/\1>/g, function( match ) { … … 230 187 } 231 188 232 /* 233 * Protect pre tags by replacing all newlines and 234 * <br> tags with <wp-line-break>. 235 */ 189 // Protect pre tags. 236 190 if ( html.indexOf( '<pre' ) !== -1 ) { 237 191 preserve_linebreaks = true; … … 243 197 } 244 198 245 /* 246 * Keep <br> tags inside captions and remove line breaks by replacing 247 * them with <wp-temp-br>. 248 */ 199 // Remove line breaks but keep <br> tags inside image captions. 249 200 if ( html.indexOf( '[caption' ) !== -1 ) { 250 201 preserve_br = true; … … 254 205 } 255 206 256 // Format the text to be readable in the source editor.207 // Normalize white space characters before and after block tags. 257 208 html = html.replace( new RegExp( '\\s*</(' + blocklist1 + ')>\\s*', 'g' ), '</$1>\n' ); 258 209 html = html.replace( new RegExp( '\\s*<((?:' + blocklist1 + ')(?: [^>]*)?)>', 'g' ), '\n<$1>' ); … … 261 212 html = html.replace( /(<p [^>]+>.*?)<\/p>/g, '$1</p#>' ); 262 213 263 // If the content of a container starts with a paragraph, replace the <p> tag with 2 newlines.214 // Preserve the first <p> inside a <div>. 264 215 html = html.replace( /<div( [^>]*)?>\s*<p>/gi, '<div$1>\n\n' ); 265 216 266 // Remove <p> and </p>tags.217 // Remove paragraph tags. 267 218 html = html.replace( /\s*<p>/gi, '' ); 268 219 html = html.replace( /\s*<\/p>\s*/gi, '\n\n' ); 269 220 270 // Remove white spaces between newlines. u00a0 is a no breaking space.221 // Normalize white space chars and remove multiple line breaks. 271 222 html = html.replace( /\n[\s\u00a0]+\n/g, '\n\n' ); 272 223 273 // R emove <br> tags.224 // Rrplace <br> tags with a line break. 274 225 html = html.replace( /\s*<br ?\/?>\s*/gi, '\n' ); 275 226 276 /* 277 * Fix some block element newline issues. 278 * Replace white spaces with newlines in combination with <div> tags. 279 */ 227 // Fix line breaks around <div>. 280 228 html = html.replace( /\s*<div/g, '\n<div' ); 281 229 html = html.replace( /<\/div>\s*/g, '</div>\n' ); 282 230 283 // Replace white spaces with newlines in combination with [caption]shortcodes.231 // Fix line breaks around caption shortcodes. 284 232 html = html.replace( /\s*\[caption([^\[]+)\[\/caption\]\s*/gi, '\n\n[caption$1[/caption]\n\n' ); 285 286 /*287 * Limit the newlines in combination with [caption]'s to a maximum of288 * two consecutive occurrences.289 * .290 */291 233 html = html.replace( /caption\]\n\n+\[caption/g, 'caption]\n\n[caption' ); 292 234 293 /* 294 * Replace white spaces with newlines in combination with 295 * all elements listed in blocklist2. 296 */ 235 // Pad block elements tags with a line break. 297 236 html = html.replace( new RegExp('\\s*<((?:' + blocklist2 + ')(?: [^>]*)?)\\s*>', 'g' ), '\n<$1>' ); 298 237 html = html.replace( new RegExp('\\s*</(' + blocklist2 + ')>\\s*', 'g' ), '</$1>\n' ); 299 238 300 // Add indentation by adding a tab in front of<li>, <dt> and <dd> tags.239 // Indent <li>, <dt> and <dd> tags. 301 240 html = html.replace( /<((li|dt|dd)[^>]*)>/g, ' \t<$1>' ); 302 241 303 // Replace white spaces with newlines in combination with <select> and <option> tags.242 // Fix line breaks around <select> and <option>. 304 243 if ( html.indexOf( '<option' ) !== -1 ) { 305 244 html = html.replace( /\s*<option/g, '\n<option' ); … … 307 246 } 308 247 309 // Replace white spaces with 2 newlines in combination with <hr> tags.248 // Pad <hr> with two line breaks. 310 249 if ( html.indexOf( '<hr' ) !== -1 ) { 311 250 html = html.replace( /\s*<hr( [^>]*)?>\s*/g, '\n\n<hr$1>\n\n' ); 312 251 } 313 252 314 // Remove newlines in <object> tags.253 // Remove line breaks in <object> tags. 315 254 if ( html.indexOf( '<object' ) !== -1 ) { 316 255 html = html.replace( /<object[\s\S]+?<\/object>/g, function( a ) { … … 322 261 html = html.replace( /<\/p#>/g, '</p>\n' ); 323 262 324 325 // Add a new line before <p> tags when there is content inside the paragraph 263 // Pad remaining <p> tags whit a line break. 326 264 html = html.replace( /\s*(<p [^>]+>[\s\S]*?<\/p>)/g, '\n$1' ); 327 265 328 /* 329 * Remove whitespaces at the start and end of a string. 330 * u00a0 is a no breaking space. 331 */ 266 // Trim. 332 267 html = html.replace( /^\s+/, '' ); 333 268 html = html.replace( /[\s\u00a0]+$/, '' ); 334 269 335 // Replace <wp-line-break> tags with a newline.336 270 if ( preserve_linebreaks ) { 337 271 html = html.replace( /<wp-line-break>/g, '\n' ); 338 272 } 339 273 340 // Restore the <wp-temp-br> with <br> tags.341 274 if ( preserve_br ) { 342 275 html = html.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' ); … … 354 287 355 288 /** 356 * @summary Adds paragraph tags to the text. 357 * 358 * Adds paragraph tags to the text taking into account block level elements. 359 * Normalizes the whitespaces and newlines. 289 * @summary Replaces two line breaks with a paragraph tag and one line break with a <br>. 360 290 * 361 291 * Similar to `wpautop()` in formatting.php. 362 292 * 363 * @since 4.3.0293 * @since 2.5.0 364 294 * 365 295 * @memberof switchEditors … … 371 301 var preserve_linebreaks = false, 372 302 preserve_br = false, 373 374 // A list containing all block level elements.375 303 blocklist = 'table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre' + 376 304 '|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section' + … … 380 308 text = text.replace( /\r\n|\r/g, '\n' ); 381 309 382 // If there are no newlines, return the text.383 310 if ( text.indexOf( '\n' ) === -1 ) { 384 311 return text; 385 312 } 386 313 314 // Remove line breaks from <object>. 387 315 if ( text.indexOf( '<object' ) !== -1 ) { 388 389 // If there are multiple newlines in an <object>, remove them.390 316 text = text.replace( /<object[\s\S]+?<\/object>/g, function( a ) { 391 317 return a.replace( /\n+/g, '' ); … … 393 319 } 394 320 395 // Re place all new lines and tabs with spaces insidetags.321 // Remove line breaks from tags. 396 322 text = text.replace( /<[^<>]+>/g, function( a ) { 397 323 return a.replace( /[\n\t ]+/g, ' ' ); 398 324 }); 399 325 400 // Pr otect <pre> and <script> tags by replacing them with <wp-line-break>.326 // Preserve line breaks in <pre> and <script> tags. 401 327 if ( text.indexOf( '<pre' ) !== -1 || text.indexOf( '<script' ) !== -1 ) { 402 328 preserve_linebreaks = true; … … 410 336 preserve_br = true; 411 337 412 // Replace all white spaces and <br> tags with <wp-temp-br>.413 338 text = text.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) { 414 415 // Protect <br> tags by converting them to <wp-temp-br> tags.416 339 a = a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' ); 417 340 418 // Replace all new lines and tabs with spaces inside HTML tags.419 341 a = a.replace( /<[^<>]+>/g, function( b ) { 420 421 // Replace newlines and tabs with a space.422 342 return b.replace( /[\n\t ]+/, ' ' ); 423 343 }); 424 344 425 // Convert remaining line breaks to <wp-temp-br />.426 345 return a.replace( /\s*\n\s*/g, '<wp-temp-br />' ); 427 346 }); 428 347 } 429 348 430 // Append 2 newlines at the end of the text.431 349 text = text + '\n\n'; 432 433 /*434 * Replace a <br> tag followed by 1 or more spaces435 * and another <br> tag with 2 newlines.436 */437 350 text = text.replace( /<br \/>\s*<br \/>/gi, '\n\n' ); 438 351 439 /* 440 * Replace a block level element open tag with 2 newlines 441 * followed by the captured block level element. 442 */ 352 // Pad block tags with two line breaks. 443 353 text = text.replace( new RegExp( '(<(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '\n\n$1' ); 444 445 /*446 * Replace a block level element closing tag with the captured447 * block level element followed by 2 newlines.448 */449 354 text = text.replace( new RegExp( '(</(?:' + blocklist + ')>)', 'gi' ), '$1\n\n' ); 450 451 // Add 2 newlines to a <hr> tag. <hr> is a self closing block element.452 355 text = text.replace( /<hr( [^>]*)?>/gi, '<hr$1>\n\n' ); 453 356 454 // Remove the spaces before an <option> tag.357 // Remove white space chars around <option>. 455 358 text = text.replace( /\s*<option/gi, '<option' ); 456 457 // Remove the spaces after an <option> closing tag.458 359 text = text.replace( /<\/option>\s*/gi, '</option>' ); 459 360 460 // Remove the spaces between two newlines.361 // Normalize multiple line breaks and white space chars. 461 362 text = text.replace( /\n\s*\n+/g, '\n\n' ); 462 363 463 // Convert 2 newlines to a paragraph and a single newline.364 // Convert two line breaks to a paragraph. 464 365 text = text.replace( /([\s\S]+?)\n\n/g, '<p>$1</p>\n' ); 465 366 … … 467 368 text = text.replace( /<p>\s*?<\/p>/gi, ''); 468 369 469 // Remove spaces and <p> tags around block level elements.370 // Remove <p> tags that are around block tags. 470 371 text = text.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' ); 471 472 // Remove <p> tags around li elements.473 372 text = text.replace( /<p>(<li.+?)<\/p>/gi, '$1'); 474 373 475 // Remove spaces and <p> tags fromblockquotes.374 // Fix <p> in blockquotes. 476 375 text = text.replace( /<p>\s*<blockquote([^>]*)>/gi, '<blockquote$1><p>'); 477 478 // Place the <blockquote> outside of the paragraph.479 376 text = text.replace( /<\/blockquote>\s*<\/p>/gi, '</p></blockquote>'); 480 377 481 // Remove spaces at the start and <p> tags from block level elements.378 // Remove <p> tags that are wrapped around block tags. 482 379 text = text.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '$1' ); 483 484 // Remove spaces at the end and <p> tags from block level elements.485 380 text = text.replace( new RegExp( '(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' ); 486 381 487 // Remove spaces and newlines after a <br> tag.488 382 text = text.replace( /(<br[^>]*>)\s*\n/gi, '$1' ); 489 383 490 // Replace spaces followed by a newline with a <br> tag followed by a new line.384 // Add <br> tags. 491 385 text = text.replace( /\s*\n/g, '<br />\n'); 492 386 493 // Remove <br> tag that follows a block element directly, ignoring spaces.387 // Remove <br> tags that are around block tags. 494 388 text = text.replace( new RegExp( '(</?(?:' + blocklist + ')[^>]*>)\\s*<br />', 'gi' ), '$1' ); 495 496 /*497 * Remove a br tag preceding white spaces followed by a498 * <p>, <li>, <div>, <dl>, <dd>, <dt>, <th>, <pre>, <td>, <ul>, or <ol> tag.499 */500 389 text = text.replace( /<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)/gi, '$1' ); 501 390 502 // Remove white spaces, <p> and <br> tags incaptions.391 // Remove <p> and <br> around captions. 503 392 text = text.replace( /(?:<p>|<br ?\/?>)*\s*\[caption([^\[]+)\[\/caption\]\s*(?:<\/p>|<br ?\/?>)*/gi, '[caption$1[/caption]' ); 504 393 505 /** 506 * @summary Makes sure there is a paragraph open tag for a close tag. 507 * 508 * @since 2.9.0 509 * 510 * Makes sure there is a paragraph open tag when there is a paragraph close tag 511 * in a div, th, td, form, fieldset or dd element. 512 * @param {string} a The complete match. 513 * @param {string} b The first capture group. 514 * @param {string} c The second capture group. 515 * @returns {string} The string in paragraph tags. 516 */ 394 // Make sure there is <p> when there is </p> inside block tags that can contain other blocks. 517 395 text = text.replace( /(<(?:div|th|td|form|fieldset|dd)[^>]*>)(.*?)<\/p>/g, function( a, b, c ) { 518 519 /*520 * Check if the matched group has a p open tag in it. If so, we don't need to521 * enclose it with a paragraph.522 */523 396 if ( c.match( /<p( [^>]*)?>/ ) ) { 524 397 return a; 525 398 } 526 399 527 /*528 * If there is no p open tag in the matched string,529 * add it and return the string including p tags.530 */531 400 return b + '<p>' + c + '</p>'; 532 401 }); … … 546 415 547 416 /** 548 * @summary Modifies the data when a switch is made from HTML to text. 549 * 550 * Modifies the data when a switch is made. 551 * Remove the <p> tags from text. 552 * Returns the modified text. 553 * Adds a trigger on beforePreWpautop and afterPreWpautop. 554 * 555 * @since 2.5.0 417 * @summary Fires custom jQuery events `beforePreWpautop` and `afterPreWpautop` when jQuery is available. 418 * 419 * @since 2.9.0 556 420 * 557 421 * @memberof switchEditors 558 422 * 559 423 * @param {String} html The content from the visual editor. 560 * @returns {String} the modified text.424 * @returns {String} the filtered content. 561 425 */ 562 426 function pre_wpautop( html ) { … … 577 441 578 442 /** 579 * @summary Modifies the data when a switch is made from text to HTML. 580 * 581 * Modifies the data when a switch is made. Runs autop to add p tags from text. 582 * Returns the modified text. Adds a trigger on beforeWpautop and afterWpautop. 583 * 584 * @since 2.5.0 443 * @summary Fires custom jQuery events `beforeWpautop` and `afterWpautop` when jQuery is available. 444 * 445 * @since 2.9.0 585 446 * 586 447 * @memberof switchEditors 587 448 * 588 449 * @param {String} text The content from the text editor. 589 * @returns {String} the modified text.450 * @returns {String} filtered content. 590 451 */ 591 452 function wpautop( text ) { … … 605 466 } 606 467 607 // Bind the init function to be run when the document is loaded.608 468 if ( $ ) { 609 469 $( document ).ready( init ); 610 470 } else if ( document.addEventListener ) { 611 612 // Use the addEventListener to bind the init event on document load.613 471 document.addEventListener( 'DOMContentLoaded', init, false ); 614 472 window.addEventListener( 'load', init, false ); 615 616 473 } else if ( window.attachEvent ) { 617 618 // Use the addEvent to bind the init event on document load.619 474 window.attachEvent( 'onload', init ); 620 475 document.attachEvent( 'onreadystatechange', function() { … … 625 480 } 626 481 627 /*628 * Make sure the window.wp object exists so autop and removep629 * can be bound to it.630 */631 482 window.wp = window.wp || {}; 632 483 window.wp.editor = window.wp.editor || {};
Note: See TracChangeset
for help on using the changeset viewer.