From 2ba684e7e4d5301d1a34890b63d8a14b09ff153c Mon Sep 17 00:00:00 2001 From: Andrew Ozz Date: Sat, 20 Feb 2016 21:35:54 +0000 Subject: [PATCH] TinyMCE, inline link dialog: - Fix passing values to the (old) modal on open when non-linked text is selected and Advanced is clicked before pasting an URL. - When the user has selected text partially including a link and opens the editing dialog, auto-select the link only. Helps when a linked word is selected by double-clicking. - Remove all placeholders on saving. - Do not add undo level on inserting link placeholder. - Remove the placeholder when canceling from the modal. See #33301. git-svn-id: https://develop.svn.wordpress.org/trunk@36602 602fd350-edb4-49c9-b593-d223f7449a82 --- .../js/tinymce/plugins/wplink/plugin.js | 94 +++++++++++++------ src/wp-includes/js/wplink.js | 20 +++- 2 files changed, 81 insertions(+), 33 deletions(-) diff --git a/src/wp-includes/js/tinymce/plugins/wplink/plugin.js b/src/wp-includes/js/tinymce/plugins/wplink/plugin.js index b1769a51c7..4ffd5dc109 100644 --- a/src/wp-includes/js/tinymce/plugins/wplink/plugin.js +++ b/src/wp-includes/js/tinymce/plugins/wplink/plugin.js @@ -41,7 +41,7 @@ if ( url.length > 40 && ( index = url.indexOf( '/' ) ) !== -1 && ( lastIndex = url.lastIndexOf( '/' ) ) !== -1 && lastIndex !== index ) { // If the beginning + ending are shorter that 40 chars, show more of the ending if ( index + url.length - lastIndex < 40 ) { - lastIndex = -( 40 - ( index + 1 ) ); + lastIndex = -( 40 - ( index + 1 ) ); } url = url.slice( 0, index + 1 ) + '\u2026' + url.slice( lastIndex ); @@ -74,26 +74,49 @@ var $ = window.jQuery; function getSelectedLink() { - var href, - selectedNode = editor.selection.getNode(), - selectedText = editor.selection.getContent(), - link = editor.dom.getParent( selectedNode, 'a[href]' ); + var href, html + node = editor.selection.getNode(); + link = editor.dom.getParent( node, 'a[href]' ); - if ( ! link && selectedText.indexOf( '' ) !== -1 ) { - href = selectedText.match( /href="([^">]+)"/ ); + if ( ! link ) { + html = editor.selection.getContent({ format: 'raw' }); - if ( href && href[1] ) { - link = editor.$( 'a[href="' + href[1] + '"]', selectedNode )[0]; - } + if ( html && html.indexOf( '' ) !== -1 ) { + href = html.match( /href="([^">]+)"/ ); - if ( link ) { - editor.selection.select( link ); - editor.nodeChanged(); + if ( href && href[1] ) { + link = editor.$( 'a[href="' + href[1] + '"]', node )[0]; + } + + if ( link ) { + editor.selection.select( link ); + editor.nodeChanged(); + } } } return link; } + + function removePlaceholders() { + editor.$( 'a' ).each( function( i, element ) { + var $element = editor.$( element ); + + if ( $element.attr( 'href' ) === '_wp_link_placeholder' ) { + editor.dom.remove( element, true ); + } else if ( $element.attr( 'data-wp-link-edit' ) ) { + $element.attr( 'data-wp-link-edit', null ); + } + }); + } + + function removePlaceholderStrings( content, dataAttr ) { + if ( dataAttr ) { + content = content.replace( / data-wp-link-edit="true"/g, '' ); + } + + return content.replace( /]*?href="_wp_link_placeholder"[^>]*>([\s\S]+)<\/a>/g, '$1' ); + } editor.on( 'preinit', function() { if ( editor.wp && editor.wp._createToolbar ) { @@ -126,9 +149,12 @@ var link = getSelectedLink(); if ( link ) { - editor.dom.setAttribs( link, { 'data-wp-edit': true } ); + editor.dom.setAttribs( link, { 'data-wp-link-edit': true } ); } else { + removePlaceholders(); + editor.execCommand( 'mceInsertLink', false, { href: '_wp_link_placeholder' } ); + editor.selection.select( editor.$( 'a[href="_wp_link_placeholder"]' )[0] ); editor.nodeChanged(); } } ); @@ -150,7 +176,7 @@ } if ( a ) { - editor.dom.setAttribs( a, { href: href, 'data-wp-edit': null } ); + editor.dom.setAttribs( a, { href: href, 'data-wp-link-edit': null } ); } a = false; @@ -160,16 +186,8 @@ } ); editor.addCommand( 'wp_link_cancel', function() { - if ( a ) { - if ( editor.$( a ).attr( 'href' ) === '_wp_link_placeholder' ) { - editor.dom.remove( a, true ); - } else { - editor.dom.setAttribs( a, { 'data-wp-edit': null } ); - } - } - + removePlaceholders(); a = false; - editor.nodeChanged(); editor.focus(); } ); @@ -218,6 +236,18 @@ } } } ); + + // Remove any remaining placeholders on saving. + editor.on( 'savecontent', function( event ) { + event.content = removePlaceholderStrings( event.content, true ); + }); + + // Prevent adding undo levels on inserting link placeholder. + editor.on( 'BeforeAddUndo', function( event ) { + if ( event.level.content ) { + event.level.content = removePlaceholderStrings( event.level.content ); + } + }); editor.addButton( 'wp_link_preview', { type: 'WPLinkPreview', @@ -235,7 +265,7 @@ inputInstance = this; - if ( $ ) { + if ( $ && $.ui && $.ui.autocomplete ) { $( input ) .on( 'keydown', function() { $( input ).removeAttr( 'aria-activedescendant' ); @@ -311,13 +341,12 @@ editor.on( 'wptoolbar', function( event ) { var anchor = editor.dom.getParent( event.element, 'a' ), - $anchor, - href, edit; + $anchor, href, edit; if ( anchor ) { $anchor = editor.$( anchor ); href = $anchor.attr( 'href' ); - edit = $anchor.attr( 'data-wp-edit' ); + edit = $anchor.attr( 'data-wp-link-edit' ); if ( href === '_wp_link_placeholder' || edit ) { inputInstance.setURL( edit ? href : '' ); @@ -348,8 +377,13 @@ tooltip: 'Advanced', icon: 'dashicon dashicons-admin-generic', onclick: function() { - editor.execCommand( 'wp_link_apply' ); - window.wpLink && window.wpLink.open( editor.id ); + if ( typeof window.wpLink !== 'undefined' ) { + if ( inputInstance.getEl().firstChild.value ) { + editor.execCommand( 'wp_link_apply' ); + } + + window.wpLink.open( editor.id ); + } } } ); diff --git a/src/wp-includes/js/wplink.js b/src/wp-includes/js/wplink.js index b5a84aecb7..eba50fc70d 100644 --- a/src/wp-includes/js/wplink.js +++ b/src/wp-includes/js/wplink.js @@ -219,14 +219,20 @@ var wpLink; }, mceRefresh: function() { - var text, + var text, url, selectedNode = editor.selection.getNode(), linkNode = editor.dom.getParent( selectedNode, 'a[href]' ), onlyText = this.hasSelectedText( linkNode ); if ( linkNode ) { text = linkNode.innerText || linkNode.textContent; - inputs.url.val( editor.dom.getAttrib( linkNode, 'href' ) ); + url = editor.dom.getAttrib( linkNode, 'href' ); + + if ( url === '_wp_link_placeholder' ) { + url = ''; + } + + inputs.url.val( url ); inputs.openInNewTab.prop( 'checked', '_blank' === editor.dom.getAttrib( linkNode, 'target' ) ); inputs.submit.val( wpLinkL10n.update ); } else { @@ -244,6 +250,8 @@ var wpLink; }, close: function() { + var linkNode; + $( document.body ).removeClass( 'modal-open' ); if ( ! wpLink.isMCE() ) { @@ -254,6 +262,12 @@ var wpLink; wpLink.range.select(); } } else { + linkNode = editor.dom.getParent( editor.selection.getNode(), 'a[href]' ); + + if ( linkNode && editor.dom.getAttrib( linkNode, 'href' ) === '_wp_link_placeholder' ) { + editor.dom.remove( linkNode, true ); + } + editor.focus(); } @@ -352,7 +366,6 @@ var wpLink; var attrs = wpLink.getAttrs(), link, text; - wpLink.close(); editor.focus(); if ( tinymce.isIE ) { @@ -388,6 +401,7 @@ var wpLink; } } + wpLink.close(); editor.nodeChanged(); },