Make WordPress Core

Ticket #28206: 28206.2.patch

File 28206.2.patch, 11.5 KB (added by iseulde, 9 years ago)
  • src/wp-includes/class-wp-editor.php

     
    14491449                        <div id="link-options">
    14501450                                <p class="howto"><?php _e( 'Enter the destination URL' ); ?></p>
    14511451                                <div>
    1452                                         <label><span><?php _e( 'URL' ); ?></span><input id="url-field" type="text" name="href" /></label>
     1452                                        <label><span><?php _e( 'Text' ); ?></span><input id="wp-link-text" type="text" /></label>
    14531453                                </div>
    14541454                                <div>
    1455                                         <label><span><?php _e( 'Title' ); ?></span><input id="link-title-field" type="text" name="linktitle" /></label>
     1455                                        <label><span><?php _e( 'Link' ); ?></span><input id="wp-link-url" type="text" /></label>
    14561456                                </div>
    14571457                                <div class="link-target">
    1458                                         <label><span>&nbsp;</span><input type="checkbox" id="link-target-checkbox" /> <?php _e( 'Open link in a new window/tab' ); ?></label>
     1458                                        <label><span>&nbsp;</span><input type="checkbox" id="wp-link-target" /> <?php _e( 'Open link in a new window/tab' ); ?></label>
    14591459                                </div>
    14601460                        </div>
    14611461                        <p class="howto"><a href="#" id="wp-link-search-toggle"><?php _e( 'Or link to existing content' ); ?></a></p>
     
    14631463                                <div class="link-search-wrapper">
    14641464                                        <label>
    14651465                                                <span class="search-label"><?php _e( 'Search' ); ?></span>
    1466                                                 <input type="search" id="search-field" class="link-search-field" autocomplete="off" />
     1466                                                <input type="search" id="wp-link-search" class="link-search-field" autocomplete="off" />
    14671467                                                <span class="spinner"></span>
    14681468                                        </label>
    14691469                                </div>
  • src/wp-includes/js/tinymce/plugins/wplink/plugin.js

     
    11/* global tinymce */
    22tinymce.PluginManager.add( 'wplink', function( editor ) {
    3         var linkButton;
    4 
    5         // Register a command so that it can be invoked by using tinyMCE.activeEditor.execCommand( 'WP_Link' );
    63        editor.addCommand( 'WP_Link', function() {
    7                 if ( ( ! linkButton || ! linkButton.disabled() ) && typeof window.wpLink !== 'undefined' ) {
    8                         window.wpLink.open( editor.id );
    9                 }
     4                window.wpLink && window.wpLink.open( editor.id );
    105        });
    116
    127        // WP default shortcut
     
    149        // The "de-facto standard" shortcut, see #27305
    1510        editor.addShortcut( 'ctrl+k', '', 'WP_Link' );
    1611
    17         function setState( button, node ) {
    18                 var parent = editor.dom.getParent( node, 'a' ),
    19                         getView = editor.plugins.wpview ? editor.plugins.wpview.getView : function() { return false; };
    20 
    21                 button.disabled( ( editor.selection.isCollapsed() && ! parent ) || ( parent && ! parent.href ) || getView( node ) );
    22                 button.active( parent && parent.href );
    23         }
    24 
    2512        editor.addButton( 'link', {
    2613                icon: 'link',
    2714                tooltip: 'Insert/edit link',
    2815                shortcut: 'Alt+Shift+A',
    2916                cmd: 'WP_Link',
    30 
    31                 onPostRender: function() {
    32                         linkButton = this;
    33 
    34                         editor.on( 'nodechange', function( event ) {
    35                                 setState( linkButton, event.element );
    36                         });
    37                 }
     17                stateSelector: 'a[href]'
    3818        });
    3919
    4020        editor.addButton( 'unlink', {
    4121                icon: 'unlink',
    4222                tooltip: 'Remove link',
    43                 cmd: 'unlink',
    44 
    45                 onPostRender: function() {
    46                         var unlinkButton = this;
    47 
    48                         editor.on( 'nodechange', function( event ) {
    49                                 setState( unlinkButton, event.element );
    50                         });
    51                 }
     23                cmd: 'unlink'
    5224        });
    5325
    5426        editor.addMenuItem( 'link', {
  • src/wp-includes/js/wplink.js

     
    77                rivers = {},
    88                isTouch = ( 'ontouchend' in document );
    99
     10        function getLink() {
     11                return editor.dom.getParent( editor.selection.getNode(), 'a' );
     12        }
     13
    1014        wpLink = {
    1115                timeToTriggerRiver: 150,
    1216                minRiverAJAXDuration: 200,
     
    2125                        inputs.backdrop = $( '#wp-link-backdrop' );
    2226                        inputs.submit = $( '#wp-link-submit' );
    2327                        inputs.close = $( '#wp-link-close' );
    24                         // URL
    25                         inputs.url = $( '#url-field' );
     28
     29                        // Input
     30                        inputs.text = $( '#wp-link-text' );
     31                        inputs.url = $( '#wp-link-url' );
    2632                        inputs.nonce = $( '#_ajax_linking_nonce' );
    27                         // Secondary options
    28                         inputs.title = $( '#link-title-field' );
    29                         // Advanced Options
    30                         inputs.openInNewTab = $( '#link-target-checkbox' );
    31                         inputs.search = $( '#search-field' );
     33                        inputs.openInNewTab = $( '#wp-link-target' );
     34                        inputs.search = $( '#wp-link-search' );
     35
    3236                        // Build Rivers
    3337                        rivers.search = new River( $( '#search-results' ) );
    3438                        rivers.recent = new River( $( '#most-recent-results' ) );
     
    129133                        inputs.backdrop.show();
    130134
    131135                        wpLink.refresh();
     136
    132137                        $( document ).trigger( 'wplink-open', inputs.wrap );
    133138                },
    134139
     
    165170                        correctedURL = inputs.url.val().replace( /^http:\/\//, '' );
    166171                },
    167172
     173                selectedText: function( object ) {
     174                        var childNodes,
     175                                i;
     176
     177                        if ( typeof object === 'string' ) {
     178                                return /</.test( object ) ? '' : object;
     179                        } else {
     180                                childNodes = object.childNodes;
     181                                i = childNodes.length;
     182
     183                                if ( ! i ) {
     184                                        return '';
     185                                }
     186
     187                                while ( i-- ) {
     188                                        if ( childNodes[ i ].nodeType !== 3 ) {
     189                                                return '';
     190                                        }
     191                                }
     192
     193                                return object.textContent || object.innerText;
     194                        }
     195                },
     196
    168197                mceRefresh: function() {
    169                         var e;
     198                        var node = getLink(),
     199                                text;
    170200
    171                         // If link exists, select proper values.
    172                         if ( e = editor.dom.getParent( editor.selection.getNode(), 'A' ) ) {
    173                                 // Set URL and description.
    174                                 inputs.url.val( editor.dom.getAttrib( e, 'href' ) );
    175                                 inputs.title.val( editor.dom.getAttrib( e, 'title' ) );
    176                                 // Set open in new tab.
    177                                 inputs.openInNewTab.prop( 'checked', ( '_blank' === editor.dom.getAttrib( e, 'target' ) ) );
    178                                 // Update save prompt.
     201                        if ( ! node && editor.selection.isCollapsed() ) {
     202                                editor.undoManager.transact( function() {
     203                                        editor.execCommand( 'mceInsertLink', false, { href: '#' } );
     204                                        editor.selection.select( getLink() );
     205                                        editor.execCommand( 'unlink' );
     206                                } );
     207                        }
     208
     209                        if ( node ) {
     210                                text = this.selectedText( node );
     211
     212                                inputs.text.val( text ).prop( 'disabled', ! text );
     213                                inputs.url.val( editor.dom.getAttrib( node, 'href' ) );
     214                                inputs.openInNewTab.prop( 'checked', '_blank' === editor.dom.getAttrib( node, 'target' ) );
    179215                                inputs.submit.val( wpLinkL10n.update );
    180 
    181                         // If there's no link, set the default values.
    182216                        } else {
    183                                 wpLink.setDefaultValues();
     217                                this.setDefaultValues();
    184218                        }
    185219                },
    186220
     
    209243                getAttrs: function() {
    210244                        return {
    211245                                href: $.trim( inputs.url.val() ),
    212                                 title: $.trim( inputs.title.val() ),
    213246                                target: inputs.openInNewTab.prop( 'checked' ) ? '_blank' : ''
    214247                        };
    215248                },
    216249
    217250                update: function() {
    218                         if ( wpLink.isMCE() )
     251                        if ( wpLink.isMCE() ) {
    219252                                wpLink.mceUpdate();
    220                         else
     253                        } else {
    221254                                wpLink.htmlUpdate();
     255                        }
    222256                },
    223257
    224258                htmlUpdate: function() {
    225                         var attrs, html, begin, end, cursor, title, selection,
     259                        var attrs, text, html, begin, end, cursor, selection,
    226260                                textarea = wpLink.textarea;
    227261
    228                         if ( ! textarea )
     262                        if ( ! textarea ) {
    229263                                return;
     264                        }
    230265
    231266                        attrs = wpLink.getAttrs();
     267                        text = $.trim( inputs.text.val() );
    232268
    233269                        // If there's no href, return.
    234                         if ( ! attrs.href )
     270                        if ( ! attrs.href ) {
    235271                                return;
     272                        }
    236273
    237274                        // Build HTML
    238275                        html = '<a href="' + attrs.href + '"';
    239276
    240                         if ( attrs.title ) {
    241                                 title = attrs.title.replace( /</g, '&lt;' ).replace( />/g, '&gt;' ).replace( /"/g, '&quot;' );
    242                                 html += ' title="' + title + '"';
    243                         }
    244 
    245277                        if ( attrs.target ) {
    246278                                html += ' target="' + attrs.target + '"';
    247279                        }
     
    254286                                // Note: If no text is selected, IE will not place the cursor
    255287                                //       inside the closing tag.
    256288                                textarea.focus();
    257                                 wpLink.range.text = html + wpLink.range.text + '</a>';
     289                                wpLink.range.text = html + ( text || wpLink.range.text ) + '</a>';
    258290                                wpLink.range.moveToBookmark( wpLink.range.getBookmark() );
    259291                                wpLink.range.select();
    260292
    261293                                wpLink.range = null;
    262294                        } else if ( typeof textarea.selectionStart !== 'undefined' ) {
    263295                                // W3C
    264                                 begin       = textarea.selectionStart;
    265                                 end         = textarea.selectionEnd;
    266                                 selection   = textarea.value.substring( begin, end );
    267                                 html        = html + selection + '</a>';
    268                                 cursor      = begin + html.length;
     296                                begin = textarea.selectionStart;
     297                                end = textarea.selectionEnd;
     298                                selection = text || textarea.value.substring( begin, end );
     299                                html = html + selection + '</a>';
     300                                cursor = begin + html.length;
    269301
    270302                                // If no text is selected, place the cursor inside the closing tag.
    271                                 if ( begin == end )
    272                                         cursor -= '</a>'.length;
     303                                if ( begin === end && ! selection ) {
     304                                        cursor -= 4;
     305                                }
    273306
    274                                 textarea.value = textarea.value.substring( 0, begin ) + html +
    275                                         textarea.value.substring( end, textarea.value.length );
     307                                textarea.value = (
     308                                        textarea.value.substring( 0, begin ) +
     309                                        html +
     310                                        textarea.value.substring( end, textarea.value.length )
     311                                );
    276312
    277313                                // Update cursor position
    278314                                textarea.selectionStart = textarea.selectionEnd = cursor;
     
    283319                },
    284320
    285321                mceUpdate: function() {
    286                         var link,
    287                                 attrs = wpLink.getAttrs();
     322                        var attrs = wpLink.getAttrs(),
     323                                link,
     324                                text;
    288325
    289326                        wpLink.close();
    290327                        editor.focus();
     
    293330                                editor.selection.moveToBookmark( editor.windowManager.bookmark );
    294331                        }
    295332
    296                         link = editor.dom.getParent( editor.selection.getNode(), 'a[href]' );
    297 
    298                         // If the values are empty, unlink and return
    299                         if ( ! attrs.href || attrs.href == 'http://' ) {
     333                        if ( ! attrs.href ) {
    300334                                editor.execCommand( 'unlink' );
    301335                                return;
    302336                        }
    303337
     338                        link = getLink();
     339                        text = $.trim( inputs.text.val() );
     340
    304341                        if ( link ) {
     342                                if ( text ) {
     343                                        if ( 'innerText' in link ) {
     344                                                link.innerText = text;
     345                                        } else {
     346                                                link.textContent = text;
     347                                        }
     348                                }
     349
    305350                                editor.dom.setAttribs( link, attrs );
    306351                        } else {
    307                                 editor.execCommand( 'mceInsertLink', false, attrs );
     352                                if ( text ) {
     353                                        editor.selection.setNode( editor.dom.create( 'a', attrs, text ) );
     354                                } else {
     355                                        editor.execCommand( 'mceInsertLink', false, attrs );
     356                                }
    308357                        }
    309 
    310                         // Move the cursor to the end of the selection
    311                         editor.selection.collapse();
    312358                },
    313359
    314360                updateFields: function( e, li ) {
    315361                        inputs.url.val( li.children( '.item-permalink' ).val() );
    316                         inputs.title.val( li.hasClass( 'no-title' ) ? '' : li.children( '.item-title' ).text() );
    317362                },
    318363
    319364                setDefaultValues: function() {
    320                         var selection = editor && editor.selection.getContent(),
     365                        var selection,
    321366                                emailRegexp = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
    322                                 urlRegexp = /^(https?|ftp):\/\/[A-Z0-9.-]+\.[A-Z]{2,4}[^ "]*$/i;
     367                                urlRegexp = /^(https?|ftp):\/\/[A-Z0-9.-]+\.[A-Z]{2,4}[^ "]*$/i,
     368                                text;
     369
     370                        if ( this.isMCE() ) {
     371                                selection = editor.selection.getContent();
     372                        } else if ( document.selection && wpLink.range ) {
     373                                selection = wpLink.range.text;
     374                        } else if ( typeof this.textarea.selectionStart !== 'undefined' ) {
     375                                selection = this.textarea.value.substring( this.textarea.selectionStart, this.textarea.selectionEnd );
     376                        }
    323377
    324378                        if ( selection && emailRegexp.test( selection ) ) {
    325379                                // Selection is email address
     
    332386                                inputs.url.val( '' );
    333387                        }
    334388
    335                         // Set description to default.
    336                         inputs.title.val( '' );
     389                        text = this.selectedText( selection );
     390                        inputs.text.val( text ).prop( 'disabled', ! text );
    337391
    338392                        // Update save prompt.
    339393                        inputs.submit.val( wpLinkL10n.save );