Ticket #28206: 28206.2.patch
File 28206.2.patch, 11.5 KB (added by , 10 years ago) |
---|
-
src/wp-includes/class-wp-editor.php
1449 1449 <div id="link-options"> 1450 1450 <p class="howto"><?php _e( 'Enter the destination URL' ); ?></p> 1451 1451 <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> 1453 1453 </div> 1454 1454 <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> 1456 1456 </div> 1457 1457 <div class="link-target"> 1458 <label><span> </span><input type="checkbox" id=" link-target-checkbox" /> <?php _e( 'Open link in a new window/tab' ); ?></label>1458 <label><span> </span><input type="checkbox" id="wp-link-target" /> <?php _e( 'Open link in a new window/tab' ); ?></label> 1459 1459 </div> 1460 1460 </div> 1461 1461 <p class="howto"><a href="#" id="wp-link-search-toggle"><?php _e( 'Or link to existing content' ); ?></a></p> … … 1463 1463 <div class="link-search-wrapper"> 1464 1464 <label> 1465 1465 <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" /> 1467 1467 <span class="spinner"></span> 1468 1468 </label> 1469 1469 </div> -
src/wp-includes/js/tinymce/plugins/wplink/plugin.js
1 1 /* global tinymce */ 2 2 tinymce.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' );6 3 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 ); 10 5 }); 11 6 12 7 // WP default shortcut … … 14 9 // The "de-facto standard" shortcut, see #27305 15 10 editor.addShortcut( 'ctrl+k', '', 'WP_Link' ); 16 11 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 25 12 editor.addButton( 'link', { 26 13 icon: 'link', 27 14 tooltip: 'Insert/edit link', 28 15 shortcut: 'Alt+Shift+A', 29 16 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]' 38 18 }); 39 19 40 20 editor.addButton( 'unlink', { 41 21 icon: 'unlink', 42 22 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' 52 24 }); 53 25 54 26 editor.addMenuItem( 'link', { -
src/wp-includes/js/wplink.js
7 7 rivers = {}, 8 8 isTouch = ( 'ontouchend' in document ); 9 9 10 function getLink() { 11 return editor.dom.getParent( editor.selection.getNode(), 'a' ); 12 } 13 10 14 wpLink = { 11 15 timeToTriggerRiver: 150, 12 16 minRiverAJAXDuration: 200, … … 21 25 inputs.backdrop = $( '#wp-link-backdrop' ); 22 26 inputs.submit = $( '#wp-link-submit' ); 23 27 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' ); 26 32 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 32 36 // Build Rivers 33 37 rivers.search = new River( $( '#search-results' ) ); 34 38 rivers.recent = new River( $( '#most-recent-results' ) ); … … 129 133 inputs.backdrop.show(); 130 134 131 135 wpLink.refresh(); 136 132 137 $( document ).trigger( 'wplink-open', inputs.wrap ); 133 138 }, 134 139 … … 165 170 correctedURL = inputs.url.val().replace( /^http:\/\//, '' ); 166 171 }, 167 172 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 168 197 mceRefresh: function() { 169 var e; 198 var node = getLink(), 199 text; 170 200 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' ) ); 179 215 inputs.submit.val( wpLinkL10n.update ); 180 181 // If there's no link, set the default values.182 216 } else { 183 wpLink.setDefaultValues();217 this.setDefaultValues(); 184 218 } 185 219 }, 186 220 … … 209 243 getAttrs: function() { 210 244 return { 211 245 href: $.trim( inputs.url.val() ), 212 title: $.trim( inputs.title.val() ),213 246 target: inputs.openInNewTab.prop( 'checked' ) ? '_blank' : '' 214 247 }; 215 248 }, 216 249 217 250 update: function() { 218 if ( wpLink.isMCE() ) 251 if ( wpLink.isMCE() ) { 219 252 wpLink.mceUpdate(); 220 else253 } else { 221 254 wpLink.htmlUpdate(); 255 } 222 256 }, 223 257 224 258 htmlUpdate: function() { 225 var attrs, html, begin, end, cursor, title, selection,259 var attrs, text, html, begin, end, cursor, selection, 226 260 textarea = wpLink.textarea; 227 261 228 if ( ! textarea ) 262 if ( ! textarea ) { 229 263 return; 264 } 230 265 231 266 attrs = wpLink.getAttrs(); 267 text = $.trim( inputs.text.val() ); 232 268 233 269 // If there's no href, return. 234 if ( ! attrs.href ) 270 if ( ! attrs.href ) { 235 271 return; 272 } 236 273 237 274 // Build HTML 238 275 html = '<a href="' + attrs.href + '"'; 239 276 240 if ( attrs.title ) {241 title = attrs.title.replace( /</g, '<' ).replace( />/g, '>' ).replace( /"/g, '"' );242 html += ' title="' + title + '"';243 }244 245 277 if ( attrs.target ) { 246 278 html += ' target="' + attrs.target + '"'; 247 279 } … … 254 286 // Note: If no text is selected, IE will not place the cursor 255 287 // inside the closing tag. 256 288 textarea.focus(); 257 wpLink.range.text = html + wpLink.range.text+ '</a>';289 wpLink.range.text = html + ( text || wpLink.range.text ) + '</a>'; 258 290 wpLink.range.moveToBookmark( wpLink.range.getBookmark() ); 259 291 wpLink.range.select(); 260 292 261 293 wpLink.range = null; 262 294 } else if ( typeof textarea.selectionStart !== 'undefined' ) { 263 295 // W3C 264 begin 265 end 266 selection =textarea.value.substring( begin, end );267 html 268 cursor 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; 269 301 270 302 // 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 } 273 306 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 ); 276 312 277 313 // Update cursor position 278 314 textarea.selectionStart = textarea.selectionEnd = cursor; … … 283 319 }, 284 320 285 321 mceUpdate: function() { 286 var link, 287 attrs = wpLink.getAttrs(); 322 var attrs = wpLink.getAttrs(), 323 link, 324 text; 288 325 289 326 wpLink.close(); 290 327 editor.focus(); … … 293 330 editor.selection.moveToBookmark( editor.windowManager.bookmark ); 294 331 } 295 332 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 ) { 300 334 editor.execCommand( 'unlink' ); 301 335 return; 302 336 } 303 337 338 link = getLink(); 339 text = $.trim( inputs.text.val() ); 340 304 341 if ( link ) { 342 if ( text ) { 343 if ( 'innerText' in link ) { 344 link.innerText = text; 345 } else { 346 link.textContent = text; 347 } 348 } 349 305 350 editor.dom.setAttribs( link, attrs ); 306 351 } 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 } 308 357 } 309 310 // Move the cursor to the end of the selection311 editor.selection.collapse();312 358 }, 313 359 314 360 updateFields: function( e, li ) { 315 361 inputs.url.val( li.children( '.item-permalink' ).val() ); 316 inputs.title.val( li.hasClass( 'no-title' ) ? '' : li.children( '.item-title' ).text() );317 362 }, 318 363 319 364 setDefaultValues: function() { 320 var selection = editor && editor.selection.getContent(),365 var selection, 321 366 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 } 323 377 324 378 if ( selection && emailRegexp.test( selection ) ) { 325 379 // Selection is email address … … 332 386 inputs.url.val( '' ); 333 387 } 334 388 335 // Set description to default.336 inputs.t itle.val( '');389 text = this.selectedText( selection ); 390 inputs.text.val( text ).prop( 'disabled', ! text ); 337 391 338 392 // Update save prompt. 339 393 inputs.submit.val( wpLinkL10n.save );