Ticket #2852: 2852.patch
File 2852.patch, 79.6 KB (added by , 16 years ago) |
---|
-
_samples/api_dialog.html
56 56 57 57 // Remove the "Link Type" combo and the "Browser 58 58 // Server" button from the "info" tab. 59 infoTab.remove( ' protocol' );59 infoTab.remove( 'linkType' ); 60 60 infoTab.remove( 'browse' ); 61 61 62 62 // Set the default value for the URL field. -
_source/core/config.js
146 146 * @example 147 147 * config.plugins = 'basicstyles,button,htmldataprocessor,toolbar,wysiwygarea'; 148 148 */ 149 plugins : 'basicstyles,button,elementspath,horizontalrule,htmldataprocessor,keystrokes,newpage,removeformat,smiley, sourcearea,specialchar,tab,toolbar,wysiwygarea',149 plugins : 'basicstyles,button,elementspath,horizontalrule,htmldataprocessor,keystrokes,newpage,removeformat,smiley,link,sourcearea,specialchar,tab,toolbar,wysiwygarea', 150 150 151 151 /** 152 152 * The theme to be used to build the UI. -
_source/plugins/dialogui/plugin.js
884 884 accessKeyUp : function() 885 885 { 886 886 this.select(); 887 }, 888 889 /** 890 * Sets the value of this text input object. 891 * @param {Object} value The new value. 892 * @returns {CKEDITOR.ui.dialog.textInput} The current UI element. 893 * @example 894 * uiElement.setValue( 'Blamo' ); 895 */ 896 setValue : function( value ) 897 { 898 value = value || ''; 899 return CKEDITOR.ui.dialog.uiElement.prototype.setValue.call( this, value ); 887 900 } 888 901 }, commonPrototype, true ); 889 902 -
_source/plugins/link/plugin.js
1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 CKEDITOR.plugins.add( 'link', 7 { 8 init : function( editor, pluginPath ) 9 { 10 // Add the link and unlink buttons. 11 editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link' ) ); 12 editor.addCommand( 'anchor', new CKEDITOR.dialogCommand( 'anchor' ) ); 13 editor.addCommand( 'unlink', new CKEDITOR.unlinkCommand() ); 14 editor.ui.addButton( 'Link', 15 { 16 label : editor.lang.link.toolbar, 17 command : 'link' 18 } ); 19 editor.ui.addButton( 'Unlink', 20 { 21 label : editor.lang.unlink, 22 command : 'unlink' 23 } ); 24 editor.ui.addButton( 'Anchor', 25 { 26 label : editor.lang.anchor.toolbar, 27 command : 'anchor' 28 } ); 29 CKEDITOR.dialog.add( 'link', this.path + 'dialogs/link.js' ); 30 CKEDITOR.dialog.add( 'anchor', this.path + 'dialogs/anchor.js' ); 31 // Register selection change handler for the unlink button. 32 editor.on( 'selectionChange', function( evt ) 33 { 34 /* 35 * Despite our initial hope, document.queryCommandEnabled() does not work 36 * for this in Firefox. So we must detect the state by element paths. 37 */ 38 var command = editor.getCommand( 'unlink' ), 39 element = evt.data.path.lastElement.getAscendant( 'a', true ); 40 if ( element && element.getName() == 'a' && element.getAttribute( 'href' ) ) 41 command.state = CKEDITOR.TRISTATE_OFF; 42 else 43 command.state = CKEDITOR.TRISTATE_DISABLED; 44 command.fire( 'state' ); 45 } ); 46 }, 47 48 requires : [ 'fakeobjects' ] 49 } ); 50 51 CKEDITOR.unlinkCommand = function(){}; 52 CKEDITOR.unlinkCommand.prototype = 53 { 54 /** @ignore */ 55 exec : function( editor ) 56 { 57 /* 58 * execCommand( 'unlink', ... ) in Firefox leaves behind <span> tags at where 59 * the <a> was, so again we have to remove the link ourselves. (See #430) 60 * 61 * TODO: Use the style system when it's complete. Let's use execCommand() 62 * as a stopgap solution for now. 63 */ 64 var selection = editor.getSelection(), 65 bookmarks = selection.createBookmarks(), 66 ranges = selection.getRanges(), 67 rangeRoot, 68 element; 69 70 for ( var i = 0 ; i < ranges.length ; i++ ) 71 { 72 rangeRoot = ranges[i].getCommonAncestor( true ); 73 element = rangeRoot.getAscendant( 'a', true ); 74 if ( !element ) 75 continue; 76 ranges[i].selectNodeContents( element ); 77 } 78 79 selection.selectRanges( ranges ); 80 editor.document.$.execCommand( 'unlink', false, null ); 81 selection.selectBookmarks( bookmarks ); 82 } 83 }; 84 85 CKEDITOR.config.link = 86 { 87 uploadTab : true, 88 browseServer : true, 89 uploadAction : 'nowhere.php', 90 showAdvancedTab : true, 91 showTargetTab : true, 92 defaultValues : 93 { 94 /** 95 * Startup values 96 * @type Text 97 * @default '' 98 */ 99 linkType : 'url', 100 protocol : 'http://', 101 target : 'notSet', 102 targetFrameName : '', 103 title : '', 104 type : '', 105 classes : '', 106 langDir : '', 107 langCode : '', 108 charset : '', 109 style : '' 110 } 111 }; -
_source/plugins/link/dialogs/anchor.js
1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 CKEDITOR.dialog.add( 'anchor', function( editor ) 7 { 8 // Function called in onShow to load selected element. 9 var loadElements = function( editor, selection, ranges, element ) 10 { 11 this.saveSelection(); 12 this.editMode = true; 13 this.editObj = element; 14 15 var attributeValue = this.editObj.getAttribute( 'name' ); 16 if ( attributeValue == null ) 17 this.setValueOf( 'info','txtName', "" ); 18 else 19 this.setValueOf( 'info','txtName', attributeValue ); 20 }; 21 22 return { 23 title : editor.lang.anchor.title, 24 minWidth : 350, 25 minHeight : 150, 26 onOk : function() 27 { 28 // Create a new anchor. 29 if ( !this.editMode ) 30 this.editObj = editor.document.createElement( 'a' ); 31 32 // Set name. 33 var name = this.getContentElement( 'info', 'txtName' ).getValue(); 34 this.editObj.setAttribute( 'name', name ); 35 36 // Insert a new anchor. 37 if ( !this.editMode ) 38 { 39 // It doesn't work with IE. 40 this.restoreSelection(); 41 this.clearSavedSelection(); 42 43 var fakeElement = editor.fakeobjects.protectElement( this.editObj ); 44 editor.insertElement( fakeElement ); 45 } 46 else 47 editor.fakeobjects.updateFakeElement( this.fakeObj, this.editObj ); 48 return true; 49 }, 50 onShow : function() 51 { 52 this.editObj = false; 53 this.fakeObj = false; 54 this.editMode = false; 55 56 // IE BUG: Selection must be in the editor for getSelection() to work. 57 this.restoreSelection(); 58 59 var editor = this.getParentEditor(), 60 selection = editor.getSelection(), 61 ranges = selection.getRanges(); 62 63 if ( ranges.length == 1 ) 64 { 65 ranges[0].enlarge( CKEDITOR.ENLARGE_ELEMENT ); 66 rangeRoot = ranges[0].getCommonAncestor( true ); 67 var element = rangeRoot.getAscendant( 'img', true ); 68 if ( element && element.getAttribute( '_cke_real_element_type' ) && element.getAttribute( '_cke_real_element_type' ) == 'anchor' ) 69 { 70 this.fakeObj = element; 71 element = editor.fakeobjects.restoreElement( this.fakeObj ); 72 loadElements.apply( this, [ editor, selection, ranges, element ] ); 73 selection.selectElement( this.fakeObj ); 74 this.saveSelection(); 75 } 76 } 77 this.pushDefault(); 78 this.getContentElement( 'info', 'txtName' ).focus(); 79 }, 80 onHide : function() 81 { 82 // Pop the default values from default value set that are pushed in onShow(). 83 this.popDefault(); 84 }, 85 contents : [ 86 { 87 id : 'info', 88 label : editor.lang.anchor.title, 89 accessKey : 'I', 90 elements : 91 [ 92 { 93 type : 'text', 94 id : 'txtName', 95 label : editor.lang.anchor.name, 96 validate : function() 97 { 98 if ( this.getValue() == '' ) 99 { 100 alert( editor.lang.anchor.errorName ); 101 return false; 102 } 103 return true; 104 } 105 }, 106 ] 107 } 108 ] 109 }; 110 } ); -
_source/plugins/link/dialogs/link.js
1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 CKEDITOR.dialog.add( 'link', function( editor ) 7 { 8 // Handles the event when the "Target" selection box is changed. 9 var targetChanged = function() 10 { 11 var dialog = this.getDialog(), 12 popupFeatures = dialog.getContentElement( 'target', 'popupFeatures' ), 13 targetName = dialog.getContentElement( 'target', 'linkTargetName' ), 14 value = this.getValue(); 15 16 if ( !popupFeatures || !targetName ) 17 return; 18 19 popupFeatures = popupFeatures.getElement(); 20 21 if ( value == 'popup' ) 22 { 23 popupFeatures.show(); 24 targetName.setLabel( editor.lang.link.targetPopupName ); 25 } 26 else 27 { 28 popupFeatures.hide(); 29 targetName.setLabel( editor.lang.link.targetFrameName ); 30 this.getDialog().setValueOf( 'target', 'linkTargetName', value.charAt( 0 ) == '_' ? value : '' ); 31 } 32 }, 33 // Handles the event when the "Type" selection box is changed. 34 linkTypeChanged = function() 35 { 36 var dialog = this.getDialog(), 37 partIds = [ 'urlOptions', 'anchorOptions', 'emailOptions' ], 38 typeValue = this.getValue(); 39 if ( typeValue == 'url' ) 40 { 41 if ( editor.config.link.showTargetTab ) 42 dialog.showPage( 'target' ); 43 if ( editor.config.link.uploadTab ) 44 dialog.showPage( 'upload' ); 45 } 46 else 47 { 48 dialog.hidePage( 'target' ); 49 dialog.hidePage( 'upload' ); 50 } 51 52 for ( var i = 0 ; i < partIds.length ; i++ ) 53 { 54 var element = dialog.getContentElement( 'info', partIds[i] ); 55 if ( !element ) 56 continue; 57 58 element = element.getElement().getParent().getParent(); 59 if ( partIds[i] == typeValue + 'Options' ) 60 element.show(); 61 else 62 element.hide(); 63 } 64 }, 65 // Loads the parameters in a selected link to the link dialog fields. 66 emailRegex = /^mailto:([^?]+)(?:\?(.+))?$/, 67 emailSubjectRegex = /subject=([^;?:@&=$,\/]*)/, 68 emailBodyRegex = /body=([^;?:@&=$,\/]*)/, 69 anchorRegex = /^#(.*)$/, 70 urlRegex = /^((?:http|https|ftp|news):\/\/)?(.*)$/, 71 selectableTargets = /^(_(?:self|top|parent|blank))$/, 72 popupRegex = 73 /\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*/, 74 popupFeaturesRegex = /(?:^|,)([^=]+)=(\d+|yes|no)/gi, 75 parseLink = function( editor, element ) 76 { 77 var href = element ? ( element.getAttribute( '_cke_saved_href' ) || element.getAttribute( 'href' ) ) : '', 78 emailMatch = '', 79 anchorMatch = '', 80 urlMatch = false, 81 retval = {}; 82 83 if ( href != null ) 84 { 85 emailMatch = href.match( emailRegex ); 86 anchorMatch = href.match( anchorRegex ); 87 urlMatch = href.match( urlRegex ); 88 } 89 90 // Load the link type and URL. 91 if ( emailMatch ) 92 { 93 var subjectMatch = href.match( emailSubjectRegex ), 94 bodyMatch = href.match( emailBodyRegex ); 95 retval.type = 'email'; 96 retval.email = {}; 97 retval.email.address = emailMatch[1]; 98 subjectMatch && ( retval.email.subject = decodeURIComponent( subjectMatch[1] ) ); 99 bodyMatch && ( retval.email.body = decodeURIComponent( bodyMatch[1] ) ); 100 } 101 else if ( anchorMatch ) 102 { 103 retval.type = 'anchor'; 104 retval.anchor = {}; 105 retval.anchor.name = retval.anchor.id = anchorMatch[1]; 106 } 107 else if ( urlMatch ) 108 { 109 retval.type = 'url'; 110 retval.url = {}; 111 retval.url.protocol = urlMatch[1]; 112 retval.url.url = urlMatch[2]; 113 } 114 else 115 retval.type = 'url'; 116 117 // Load target and popup settings. 118 if ( element ) 119 { 120 var target = element.getAttribute( 'target' ); 121 retval.target = {}; 122 retval.adv = {}; 123 124 if ( target == null ) 125 { 126 var onclick = element.getAttribute( '_cke_saved_onclick' ) || element.getAttribute( 'onclick' ), 127 onclickMatch = onclick && onclick.match( popupRegex ); 128 if ( onclickMatch ) 129 { 130 retval.target.type = 'popup'; 131 retval.target.name = onclickMatch[1]; 132 133 var featureMatch; 134 while ( ( featureMatch = popupFeaturesRegex.exec( onclickMatch[2] ) ) ) 135 { 136 if ( featureMatch[2] == 'yes' || featureMatch[2] == '1' ) 137 retval.target[ featureMatch[1] ] = true; 138 else if ( isFinite( featureMatch[2] ) ) 139 retval.target[ featureMatch[1] ] = featureMatch[2]; 140 } 141 } 142 } 143 else 144 { 145 var targetMatch = target.match( selectableTargets ); 146 if ( targetMatch ) 147 retval.target.type = retval.target.name = target; 148 else 149 { 150 retval.target.type = 'frame'; 151 retval.target.name = target; 152 } 153 } 154 155 var me = this, 156 advAttr = function( inputName, attrName ) 157 { 158 var value = element.getAttribute( attrName ); 159 if ( value != null ) 160 retval.adv[ inputName ] = value || ''; 161 }; 162 advAttr( 'advId', 'id' ); 163 advAttr( 'advLangDir', 'dir' ); 164 advAttr( 'advAccessKey', 'accessKey' ); 165 advAttr( 'advName', 'name' ); 166 advAttr( 'advLangCode', 'lang' ); 167 advAttr( 'advTabIndex', 'tabindex' ); 168 advAttr( 'advTitle', 'title' ); 169 advAttr( 'advContentType', 'type' ); 170 advAttr( 'advCSSClasses', 'class' ); 171 advAttr( 'advCharset', 'charset' ); 172 advAttr( 'advStyles', 'style' ); 173 } 174 175 // Find out whether we have any anchors in the editor. 176 // Get all IMG elements in CK document. 177 var elements = editor.document.$.getElementsByTagName( 'img' ), 178 anchors = retval.anchors = []; 179 for( var i = 0; i < elements.length; i++ ) 180 { 181 var item = elements.item( i ); 182 if ( item.getAttribute( '_cke_protected_html' ) && item.getAttribute( '_cke_real_element_type' ) == "anchor" ) 183 { 184 var domElement = new CKEDITOR.dom.element( item ); 185 domElement = editor.fakeobjects.restoreElement( domElement ); 186 anchors.push( domElement ); 187 } 188 } 189 for ( var i = 0, name, id ; i < anchors.length ; i++ ) 190 { 191 name = anchors[i].getAttribute( 'name' ); 192 id = anchors[i].getAttribute( 'id' ); 193 anchors.push( { name : name, id : id } ); 194 } 195 196 // Record down the selected element in the dialog. 197 this._.selectedElement = element; 198 199 return retval; 200 }, 201 setupParams = function( page, data ) 202 { 203 if ( data[page] ) 204 this.setValue( data[page][this.id] || '' ); 205 }, 206 setupPopupParams = function( data ) 207 { 208 return setupParams.call( this, 'target', data ); 209 }, 210 setupAdvParams = function( data ) 211 { 212 return setupParams.call( this, 'adv', data ); 213 }, 214 commitParams = function( page, data ) 215 { 216 if ( !data[page] ) 217 data[page] = {}; 218 219 data[page][this.id] = this.getValue() || ''; 220 }, 221 commitPopupParams = function( data ) 222 { 223 return commitParams.call( this, 'target', data ); 224 }, 225 commitAdvParams = function( data ) 226 { 227 return commitParams.call( this, 'adv', data ); 228 }; 229 230 return { 231 title : editor.lang.link.title, 232 minWidth : 400, 233 minHeight : 320, 234 contents : [ 235 { 236 id : 'info', 237 label : editor.lang.link.info, 238 title : editor.lang.link.info, 239 elements : 240 [ 241 { 242 id : 'linkType', 243 type : 'select', 244 label : editor.lang.link.type, 245 'default' : editor.config.link.defaultValues.linkType, 246 items : 247 [ 248 [ editor.lang.common.url, 'url' ], 249 [ editor.lang.link.toAnchor, 'anchor' ], 250 [ editor.lang.link.toEmail, 'email' ] 251 ], 252 onChange : linkTypeChanged, 253 setup : function( data ) 254 { 255 if ( data.type ) 256 this.setValue( data.type ); 257 }, 258 commit : function( data ) 259 { 260 data.type = this.getValue(); 261 } 262 }, 263 { 264 type : 'vbox', 265 id : 'urlOptions', 266 children : 267 [ 268 { 269 type : 'hbox', 270 widths : [ '25%', '75%' ], 271 children : 272 [ 273 { 274 id : 'protocol', 275 type : 'select', 276 label : editor.lang.common.protocol, 277 'default' : editor.config.link.defaultValues.protocol, 278 style : 'width : 100%;', 279 items : 280 [ 281 [ 'http://' ], 282 [ 'https//' ], 283 [ 'ftp://' ], 284 [ 'news://' ], 285 [ '<other>', '' ] 286 ], 287 setup : function( data ) 288 { 289 if ( data.url ) 290 this.setValue( data.url.protocol ); 291 }, 292 commit : function( data ) 293 { 294 if ( !data.url ) 295 data.url = {}; 296 297 data.url.protocol = this.getValue(); 298 } 299 }, 300 { 301 type : 'text', 302 id : 'url', 303 label : editor.lang.common.url, 304 validate : function() 305 { 306 var dialog = this.getDialog(); 307 308 if ( dialog.getContentElement( 'info', 'linkType' ) && 309 dialog.getValueOf( 'info', 'linkType' ) != 'url' ) 310 return true; 311 312 if ( this.getDialog().fakeObj != false ) // Edit Anchor. 313 return true; 314 315 var func = CKEDITOR.dialog.validate.notEmpty( editor.lang.link.noUrl ); 316 return func.apply( this ); 317 }, 318 setup : function( data ) 319 { 320 if ( data.url ) 321 this.setValue( data.url.url ); 322 323 var linkType = this.getDialog().getContentElement( 'info', 'linkType' ); 324 if ( linkType && linkType.getValue() == 'url' ) 325 this.select(); 326 }, 327 commit : function( data ) 328 { 329 if ( !data.url ) 330 data.url = {}; 331 332 data.url.url = this.getValue(); 333 } 334 } 335 ], 336 setup : function( data ) 337 { 338 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) 339 this.getElement().show(); 340 } 341 }, 342 { 343 type : 'button', 344 id : 'browse', 345 label : editor.lang.common.browseServer 346 } 347 ] 348 }, 349 { 350 type : 'vbox', 351 id : 'anchorOptions', 352 width : 260, 353 align : 'center', 354 padding : 0, 355 children : 356 [ 357 { 358 type : 'html', 359 id : 'selectAnchorText', 360 html : CKEDITOR.tools.htmlEncode( editor.lang.link.selectAnchor ), 361 setup : function( data ) 362 { 363 if ( data.anchors.length > 0 ) 364 this.getElement().show(); 365 else 366 this.getElement().hide(); 367 } 368 }, 369 { 370 type : 'html', 371 id : 'noAnchors', 372 style : 'text-align: center;', 373 html : '<div>' + CKEDITOR.tools.htmlEncode( editor.lang.link.noAnchors ) + '</div>', 374 setup : function( data ) 375 { 376 if ( data.anchors.length < 1 ) 377 this.getElement().show(); 378 else 379 this.getElement().hide(); 380 } 381 }, 382 { 383 type : 'hbox', 384 id : 'selectAnchor', 385 children : 386 [ 387 { 388 type : 'select', 389 id : 'anchorName', 390 'default' : '', 391 label : editor.lang.link.anchorName, 392 style : 'width: 100%;', 393 items : 394 [ 395 [ '' ] 396 ], 397 setup : function( data ) 398 { 399 this.clear(); 400 this.add( '' ); 401 for ( var i = 0 ; i < data.anchors.length ; i++ ) 402 { 403 if ( data.anchors[i].name ) 404 this.add( data.anchors[i].name ); 405 } 406 407 if ( data.anchor ) 408 this.setValue( data.anchor.name ); 409 410 var linkType = this.getDialog().getContentElement( 'info', 'linkType' ); 411 if ( linkType && linkType.getValue() == 'email' ) 412 this.focus(); 413 }, 414 commit : function( data ) 415 { 416 if ( !data.anchor ) 417 data.anchor = {}; 418 419 data.anchor.name = this.getValue(); 420 } 421 }, 422 { 423 type : 'select', 424 id : 'anchorId', 425 'default' : '', 426 label : editor.lang.link.anchorId, 427 style : 'width: 100%;', 428 items : 429 [ 430 [ '' ] 431 ], 432 setup : function( data ) 433 { 434 this.clear(); 435 this.add( '' ); 436 for ( var i = 0 ; i < data.anchors.length ; i++ ) 437 { 438 if ( data.anchors[i].id ) 439 this.add( data.anchors[i].id ); 440 } 441 442 if ( data.anchor ) 443 this.setValue( data.anchor.id ); 444 }, 445 commit : function( data ) 446 { 447 if ( !data.anchor ) 448 data.anchor = {}; 449 450 data.anchor.id = this.getValue(); 451 } 452 } 453 ], 454 setup : function( data ) 455 { 456 if ( data.anchors.length > 0 ) 457 this.getElement().show(); 458 else 459 this.getElement().hide(); 460 } 461 } 462 ], 463 setup : function( data ) 464 { 465 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) 466 this.getElement().hide(); 467 } 468 }, 469 { 470 type : 'vbox', 471 id : 'emailOptions', 472 padding : 1, 473 children : 474 [ 475 { 476 type : 'text', 477 id : 'emailAddress', 478 label : editor.lang.link.emailAddress, 479 validate : function() 480 { 481 var dialog = this.getDialog(); 482 483 if ( !dialog.getContentElement( 'info', 'linkType' ) || 484 dialog.getValueOf( 'info', 'linkType' ) != 'email' ) 485 return true; 486 487 var func = CKEDITOR.dialog.validate.notEmpty( editor.lang.link.noEmail ); 488 return func.apply( this ); 489 }, 490 setup : function( data ) 491 { 492 if ( data.email ) 493 this.setValue( data.email.address ); 494 495 var linkType = this.getDialog().getContentElement( 'info', 'linkType' ); 496 if ( linkType && linkType.getValue() == 'email' ) 497 this.select(); 498 }, 499 commit : function( data ) 500 { 501 if ( !data.email ) 502 data.email = {}; 503 504 data.email.address = this.getValue(); 505 } 506 }, 507 { 508 type : 'text', 509 id : 'emailSubject', 510 label : editor.lang.link.emailSubject, 511 setup : function( data ) 512 { 513 if ( data.email ) 514 this.setValue( data.email.subject ); 515 }, 516 commit : function( data ) 517 { 518 if ( !data.email ) 519 data.email = {}; 520 521 data.email.subject = this.getValue(); 522 } 523 }, 524 { 525 type : 'textarea', 526 id : 'emailBody', 527 label : editor.lang.link.emailBody, 528 rows : 3, 529 'default' : '', 530 setup : function( data ) 531 { 532 if ( data.email ) 533 this.setValue( data.email.body ); 534 }, 535 commit : function( data ) 536 { 537 if ( !data.email ) 538 data.email = {}; 539 540 data.email.body = this.getValue(); 541 } 542 } 543 ], 544 setup : function( data ) 545 { 546 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) 547 this.getElement().hide(); 548 } 549 } 550 ] 551 }, 552 { 553 id : 'target', 554 label : editor.lang.link.target, 555 title : editor.lang.link.target, 556 elements : 557 [ 558 { 559 type : 'hbox', 560 widths : [ '50%', '50%' ], 561 children : 562 [ 563 { 564 type : 'select', 565 id : 'linkTargetType', 566 label : editor.lang.link.target, 567 'default' : editor.config.link.defaultValues.target, 568 style : 'width : 100%;', 569 'items' : 570 [ 571 [ editor.lang.link.targetNotSet, 'notSet' ], 572 [ editor.lang.link.targetFrame, 'frame' ], 573 [ editor.lang.link.targetPopup, 'popup' ], 574 [ editor.lang.link.targetNew, '_blank' ], 575 [ editor.lang.link.targetTop, '_top' ], 576 [ editor.lang.link.targetSelf, '_self' ], 577 [ editor.lang.link.targetParent, '_parent' ] 578 ], 579 onChange : targetChanged, 580 setup : function( data ) 581 { 582 if ( data.target ) 583 this.setValue( data.target.type ); 584 }, 585 commit : function( data ) 586 { 587 if ( !data.target ) 588 data.target = {}; 589 590 data.target.type = this.getValue(); 591 } 592 }, 593 { 594 type : 'text', 595 id : 'linkTargetName', 596 label : editor.lang.link.targetFrameName, 597 'default' : editor.config.link.defaultValues.targetFrameName, 598 setup : function( data ) 599 { 600 if ( data.target ) 601 this.setValue( data.target.name ); 602 }, 603 commit : function( data ) 604 { 605 if ( !data.target ) 606 data.target = {}; 607 608 data.target.name = this.getValue(); 609 } 610 } 611 ] 612 }, 613 { 614 type : 'vbox', 615 width : 260, 616 align : 'center', 617 padding : 2, 618 id : 'popupFeatures', 619 children : 620 [ 621 { 622 type : 'html', 623 html : CKEDITOR.tools.htmlEncode( editor.lang.link.popupFeatures ) 624 }, 625 { 626 type : 'hbox', 627 children : 628 [ 629 { 630 type : 'checkbox', 631 id : 'resizable', 632 label : editor.lang.link.popupResizable, 633 setup : setupPopupParams, 634 commit : commitPopupParams 635 }, 636 { 637 type : 'checkbox', 638 id : 'status', 639 label : editor.lang.link.popupStatusBar, 640 setup : setupPopupParams, 641 commit : commitPopupParams 642 643 } 644 ] 645 }, 646 { 647 type : 'hbox', 648 children : 649 [ 650 { 651 type : 'checkbox', 652 id : 'location', 653 label : editor.lang.link.popupLocationBar, 654 setup : setupPopupParams, 655 commit : commitPopupParams 656 657 }, 658 { 659 type : 'checkbox', 660 id : 'toolbar', 661 label : editor.lang.link.popupToolbar, 662 setup : setupPopupParams, 663 commit : commitPopupParams 664 665 } 666 ] 667 }, 668 { 669 type : 'hbox', 670 children : 671 [ 672 { 673 type : 'checkbox', 674 id : 'menubar', 675 label : editor.lang.link.popupMenuBar, 676 setup : setupPopupParams, 677 commit : commitPopupParams 678 679 }, 680 { 681 type : 'checkbox', 682 id : 'fullscreen', 683 label : editor.lang.link.popupFullScreen, 684 setup : setupPopupParams, 685 commit : commitPopupParams 686 687 } 688 ] 689 }, 690 { 691 type : 'hbox', 692 children : 693 [ 694 { 695 type : 'checkbox', 696 id : 'scrollbars', 697 label : editor.lang.link.popupScrollBars, 698 setup : setupPopupParams, 699 commit : commitPopupParams 700 701 }, 702 { 703 type : 'checkbox', 704 id : 'dependent', 705 label : editor.lang.link.popupDependent, 706 setup : setupPopupParams, 707 commit : commitPopupParams 708 709 } 710 ] 711 }, 712 { 713 type : 'hbox', 714 children : 715 [ 716 { 717 type : 'text', 718 widths : [ '30%', '70%' ], 719 labelLayout : 'horizontal', 720 label : editor.lang.link.popupWidth, 721 id : 'width', 722 setup : setupPopupParams, 723 commit : commitPopupParams 724 725 }, 726 { 727 type : 'text', 728 labelLayout : 'horizontal', 729 widths : [ '55%', '45%' ], 730 label : editor.lang.link.popupLeft, 731 id : 'left', 732 setup : setupPopupParams, 733 commit : commitPopupParams 734 735 } 736 ] 737 }, 738 { 739 type : 'hbox', 740 children : 741 [ 742 { 743 type : 'text', 744 labelLayout : 'horizontal', 745 widths : [ '30%', '70%' ], 746 label : editor.lang.link.popupHeight, 747 id : 'height', 748 setup : setupPopupParams, 749 commit : commitPopupParams 750 751 }, 752 { 753 type : 'text', 754 labelLayout : 'horizontal', 755 label : editor.lang.link.popupTop, 756 widths : [ '55%', '45%' ], 757 id : 'top', 758 setup : setupPopupParams, 759 commit : commitPopupParams 760 761 } 762 ] 763 } 764 ] 765 } 766 ] 767 }, 768 { 769 id : 'upload', 770 label : editor.lang.link.upload, 771 title : editor.lang.link.upload, 772 elements : 773 [ 774 { 775 type : 'file', 776 id : 'upload', 777 label : editor.lang.common.upload, 778 action : editor.config.link.uploadAction, 779 size : 38 780 }, 781 { 782 type : 'fileButton', 783 id : 'uploadButton', 784 label : editor.lang.common.uploadSubmit, 785 'for' : [ 'upload', 'upload' ] 786 } 787 ] 788 }, 789 { 790 id : 'advanced', 791 label : editor.lang.link.advanced, 792 title : editor.lang.link.advanced, 793 elements : 794 [ 795 { 796 type : 'vbox', 797 padding : 1, 798 children : 799 [ 800 { 801 type : 'hbox', 802 widths : [ '45%', '35%', '20%' ], 803 children : 804 [ 805 { 806 type : 'text', 807 id : 'advId', 808 label : editor.lang.link.id, 809 setup : setupAdvParams, 810 commit : commitAdvParams 811 }, 812 { 813 type : 'select', 814 id : 'advLangDir', 815 label : editor.lang.link.langDir, 816 'default' : editor.config.link.defaultValues.langDir, 817 style : 'width: 100%;', 818 items : 819 [ 820 [ editor.lang.link.langDirNotSet, '' ], 821 [ editor.lang.link.langDirLTR, 'ltr' ], 822 [ editor.lang.link.langDirRTL, 'rtl' ] 823 ], 824 setup : setupAdvParams, 825 commit : commitAdvParams 826 }, 827 { 828 type : 'text', 829 id : 'advAccessKey', 830 label : editor.lang.link.acccessKey, 831 maxLength : 1, 832 setup : setupAdvParams, 833 commit : commitAdvParams 834 835 } 836 ] 837 }, 838 { 839 type : 'hbox', 840 widths : [ '45%', '35%', '20%' ], 841 children : 842 [ 843 { 844 type : 'text', 845 label : editor.lang.link.name, 846 id : 'advName', 847 setup : setupAdvParams, 848 commit : commitAdvParams 849 850 }, 851 { 852 type : 'text', 853 label : editor.lang.link.langCode, 854 id : 'advLangCode', 855 'default' : editor.config.link.defaultValues.langCode, 856 setup : setupAdvParams, 857 commit : commitAdvParams 858 859 }, 860 { 861 type : 'text', 862 label : editor.lang.link.tabIndex, 863 id : 'advTabIndex', 864 maxLength : 5, 865 setup : setupAdvParams, 866 commit : commitAdvParams 867 868 } 869 ] 870 } 871 ] 872 }, 873 { 874 type : 'vbox', 875 padding : 1, 876 children : 877 [ 878 { 879 type : 'hbox', 880 widths : [ '45%', '55%' ], 881 children : 882 [ 883 { 884 type : 'text', 885 label : editor.lang.link.advisoryTitle, 886 'default' : editor.config.link.defaultValues.title, 887 id : 'advTitle', 888 setup : setupAdvParams, 889 commit : commitAdvParams 890 891 }, 892 { 893 type : 'text', 894 label : editor.lang.link.advisoryContentType, 895 'default' : editor.config.link.defaultValues.type, 896 id : 'advContentType', 897 setup : setupAdvParams, 898 commit : commitAdvParams 899 900 } 901 ] 902 }, 903 { 904 type : 'hbox', 905 widths : [ '45%', '55%' ], 906 children : 907 [ 908 { 909 type : 'text', 910 label : editor.lang.link.cssClasses, 911 'default' : editor.config.link.defaultValues.classes, 912 id : 'advCSSClasses', 913 setup : setupAdvParams, 914 commit : commitAdvParams 915 916 }, 917 { 918 type : 'text', 919 label : editor.lang.link.charset, 920 'default' : editor.config.link.defaultValues.charset, 921 id : 'advCharset', 922 setup : setupAdvParams, 923 commit : commitAdvParams 924 925 } 926 ] 927 }, 928 { 929 type : 'hbox', 930 children : 931 [ 932 { 933 type : 'text', 934 label : editor.lang.link.styles, 935 'default' : editor.config.link.defaultValues.style, 936 id : 'advStyles', 937 setup : setupAdvParams, 938 commit : commitAdvParams 939 940 } 941 ] 942 } 943 ] 944 } 945 ] 946 } 947 ], 948 onShow : function() 949 { 950 this.fakeObj = false; 951 // IE BUG: Selection must be in the editor for getSelection() to work. 952 this.restoreSelection(); 953 var editor = this.getParentEditor(), 954 selection = editor.getSelection(), 955 ranges = selection.getRanges(), 956 element = null, 957 me = this; 958 959 // Fill in all the relevant fields if there's already one link selected. 960 if ( ranges.length == 1 ) 961 { 962 ranges[0].enlarge( CKEDITOR.ENLARGE_ELEMENT ); 963 964 var rangeRoot = ranges[0].getCommonAncestor( true ); 965 element = rangeRoot.getAscendant( 'a', true ); 966 if ( element && element.getAttribute( 'href' ) ) 967 { 968 selection.selectElement( element ); 969 this.saveSelection(); 970 } 971 else 972 { 973 element = rangeRoot.getAscendant( 'img', true ); 974 if ( element && element.getAttribute( '_cke_real_element_type' ) && element.getAttribute( '_cke_real_element_type' ) == 'anchor' ) 975 { 976 this.fakeObj = element; 977 element = editor.fakeobjects.restoreElement( this.fakeObj ); 978 selection.selectElement( this.fakeObj ); 979 this.saveSelection(); 980 } 981 } 982 } 983 984 this.setupContent( parseLink.apply( this, [ editor, element ] ) ); 985 986 // Push the current values into the dialog default value stack. 987 this.pushDefault(); 988 }, 989 onOk : function() 990 { 991 var attributes = { href : 'javascript:void(0)/*' + CKEDITOR.tools.getNextNumber() + '*/' }, 992 removeAttributes = [], 993 data = { href : attributes.href }, 994 me = this, editor = this.getParentEditor(); 995 996 this.commitContent( data ); 997 998 // Compose the URL. 999 switch ( data.type || 'url' ) 1000 { 1001 case 'url': 1002 var protocol = ( data.url && data.url.protocol ) || 'http://', 1003 url = ( data.url && data.url.url ) || ''; 1004 attributes._cke_saved_href = protocol + url; 1005 break; 1006 case 'anchor': 1007 var name = ( data.anchor && data.anchor.name ), 1008 id = ( data.anchor && data.anchor.id ); 1009 attributes._cke_saved_href = '#' + ( name || id || '' ); 1010 break; 1011 case 'email': 1012 var address = ( data.email && data.email.address ), 1013 subject = ( data.email && encodeURIComponent( data.email.subject || '' ) ), 1014 body = ( data.email && encodeURIComponent( data.email.body || '' ) ), 1015 linkList = [ 'mailto:', address ]; 1016 if ( subject || body ) 1017 { 1018 var argList = []; 1019 linkList.push( '?' ); 1020 subject && argList.push( 'subject=' + subject ); 1021 body && argList.push( 'body=' + body ); 1022 linkList.push( argList.join( '&' ) ); 1023 } 1024 attributes._cke_saved_href = linkList.join( '' ); 1025 break; 1026 default: 1027 } 1028 1029 // Popups and target. 1030 if ( data.target ) 1031 { 1032 if ( data.target.type == 'popup' ) 1033 { 1034 var onclickList = [ 'window.open(this.href, \'', 1035 data.target.name || '', '\', \'' ], 1036 featureList = [ 'resizable', 'status', 'location', 'toolbar', 'menubar', 'fullscreen', 1037 'scrollbars', 'dependent' ], 1038 featureLength = featureList.length, 1039 addFeature = function( featureName ) 1040 { 1041 if ( data.target[ featureName ] ) 1042 featureList.push( featureName + '=' + data.target[ featureName ] ); 1043 }; 1044 1045 for ( var i = 0 ; i < featureLength ; i++ ) 1046 featureList[i] = featureList[i] + ( data.target[ featureList[i] ] ? '=yes' : '=no' ) ; 1047 addFeature( 'width' ); 1048 addFeature( 'left' ); 1049 addFeature( 'height' ); 1050 addFeature( 'top' ); 1051 1052 onclickList.push( featureList.join( ',' ), '\'); return false;' ); 1053 attributes._cke_saved_onclick = onclickList.join( '' ); 1054 } 1055 else 1056 { 1057 if ( data.target.type != 'notSet' ) 1058 attributes.target = data.target.name; 1059 removeAttributes.push( '_cke_saved_onclick', 'onclick' ); 1060 } 1061 } 1062 1063 // Advanced attributes. 1064 if ( data.adv ) 1065 { 1066 var advAttr = function( inputName, attrName ) 1067 { 1068 var value = data.adv[ inputName ]; 1069 if ( value ) 1070 attributes[attrName] = value; 1071 }; 1072 1073 if ( this._.selectedElement ) 1074 advAttr( 'advId', 'id' ); 1075 advAttr( 'advLangDir', 'dir' ); 1076 advAttr( 'advAccessKey', 'accessKey' ); 1077 advAttr( 'advName', 'name' ); 1078 advAttr( 'advLangCode', 'lang' ); 1079 advAttr( 'advTabIndex', 'tabindex' ); 1080 advAttr( 'advTitle', 'title' ); 1081 advAttr( 'advContentType', 'type' ); 1082 advAttr( 'advCSSClasses', 'class' ); 1083 advAttr( 'advCharset', 'charset' ); 1084 advAttr( 'advStyles', 'style' ); 1085 } 1086 1087 if ( !this._.selectedElement ) 1088 { 1089 // IE BUG: Selection must be in the editor for getSelection() to work. 1090 this.restoreSelection(); 1091 this.clearSavedSelection(); 1092 1093 // Create element if current selection is collapsed. 1094 var selection = editor.getSelection(), 1095 ranges = selection.getRanges(); 1096 if ( ranges.length == 1 && ranges[0].collapsed ) 1097 { 1098 ranges[0].insertNode( new CKEDITOR.dom.text( attributes._cke_saved_href, editor.document ) ); 1099 selection.selectRanges( ranges ); 1100 } 1101 1102 // Apply style. 1103 var style = new CKEDITOR.style( { element : 'a', attributes : attributes } ); 1104 style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why. 1105 style.apply( editor.document ); 1106 1107 // Id. Apply only to the first link. 1108 if ( data.adv && data.adv.advId != '' ) 1109 { 1110 var links = this.getParentEditor().document.$.getElementsByTagName( 'a' ); 1111 for ( var i = 0 ; i < links.length ; i++ ) 1112 { 1113 if ( links[i].href == attributes.href ) 1114 { 1115 links[i].id = data.adv.advId; 1116 break; 1117 } 1118 } 1119 } 1120 } 1121 else 1122 { 1123 // We're only editing an existing link, so just overwrite the attributes. 1124 var element = this._.selectedElement; 1125 element.setAttributes( attributes ); 1126 element.removeAttributes( removeAttributes ); 1127 if ( this.fakeObj ) 1128 editor.fakeobjects.updateFakeElement( this.fakeObj, element ); 1129 1130 delete this._.selectedElement; 1131 } 1132 }, 1133 onLoad : function() 1134 { 1135 if ( editor.config.link.uploadTab == false ) 1136 this.hidePage( 'upload' ); //Hide Upload tab. 1137 1138 if ( editor.config.link.showAdvancedTab == false ) 1139 this.hidePage( 'advanced' ); //Hide Advanded tab. 1140 1141 if ( editor.config.link.browseServer == false ) 1142 this.getContentElement( 'info', 'browse' ).getElement().hide(); 1143 1144 if ( editor.config.link.showTargetTab == false ) 1145 this.hidePage( 'target' ); //Hide Target tab. 1146 1147 }, 1148 onHide : function() 1149 { 1150 // Pop the default values from default value set that are pushed in onShow(). 1151 this.popDefault(); 1152 } 1153 }; 1154 } ); -
_source/plugins/link/dialogs/anchor.js
1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 CKEDITOR.dialog.add( 'anchor', function( editor ) 7 { 8 // Function called in onShow to load selected element. 9 var loadElements = function( editor, selection, ranges, element ) 10 { 11 this.saveSelection(); 12 this.editMode = true; 13 this.editObj = element; 14 15 var attributeValue = this.editObj.getAttribute( 'name' ); 16 if ( attributeValue == null ) 17 this.setValueOf( 'info','txtName', "" ); 18 else 19 this.setValueOf( 'info','txtName', attributeValue ); 20 }; 21 22 return { 23 title : editor.lang.anchor.title, 24 minWidth : 350, 25 minHeight : 150, 26 onOk : function() 27 { 28 // Create a new anchor. 29 if ( !this.editMode ) 30 this.editObj = editor.document.createElement( 'a' ); 31 32 // Set name. 33 var name = this.getContentElement( 'info', 'txtName' ).getValue(); 34 this.editObj.setAttribute( 'name', name ); 35 36 // Insert a new anchor. 37 if ( !this.editMode ) 38 { 39 // It doesn't work with IE. 40 this.restoreSelection(); 41 this.clearSavedSelection(); 42 43 var fakeElement = editor.fakeobjects.protectElement( this.editObj ); 44 editor.insertElement( fakeElement ); 45 } 46 else 47 editor.fakeobjects.updateFakeElement( this.fakeObj, this.editObj ); 48 return true; 49 }, 50 onShow : function() 51 { 52 this.editObj = false; 53 this.fakeObj = false; 54 this.editMode = false; 55 56 // IE BUG: Selection must be in the editor for getSelection() to work. 57 this.restoreSelection(); 58 59 var editor = this.getParentEditor(), 60 selection = editor.getSelection(), 61 ranges = selection.getRanges(); 62 63 if ( ranges.length == 1 ) 64 { 65 ranges[0].enlarge( CKEDITOR.ENLARGE_ELEMENT ); 66 rangeRoot = ranges[0].getCommonAncestor( true ); 67 var element = rangeRoot.getAscendant( 'img', true ); 68 if ( element && element.getAttribute( '_cke_real_element_type' ) && element.getAttribute( '_cke_real_element_type' ) == 'anchor' ) 69 { 70 this.fakeObj = element; 71 element = editor.fakeobjects.restoreElement( this.fakeObj ); 72 loadElements.apply( this, [ editor, selection, ranges, element ] ); 73 selection.selectElement( this.fakeObj ); 74 this.saveSelection(); 75 } 76 } 77 this.pushDefault(); 78 this.getContentElement( 'info', 'txtName' ).focus(); 79 }, 80 onHide : function() 81 { 82 // Pop the default values from default value set that are pushed in onShow(). 83 this.popDefault(); 84 }, 85 contents : [ 86 { 87 id : 'info', 88 label : editor.lang.anchor.title, 89 accessKey : 'I', 90 elements : 91 [ 92 { 93 type : 'text', 94 id : 'txtName', 95 label : editor.lang.anchor.name, 96 validate : function() 97 { 98 if ( this.getValue() == '' ) 99 { 100 alert( editor.lang.anchor.errorName ); 101 return false; 102 } 103 return true; 104 } 105 }, 106 ] 107 } 108 ] 109 }; 110 } ); -
_source/plugins/link/dialogs/link.js
1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 CKEDITOR.dialog.add( 'link', function( editor ) 7 { 8 // Handles the event when the "Target" selection box is changed. 9 var targetChanged = function() 10 { 11 var dialog = this.getDialog(), 12 popupFeatures = dialog.getContentElement( 'target', 'popupFeatures' ), 13 targetName = dialog.getContentElement( 'target', 'linkTargetName' ), 14 value = this.getValue(); 15 16 if ( !popupFeatures || !targetName ) 17 return; 18 19 popupFeatures = popupFeatures.getElement(); 20 21 if ( value == 'popup' ) 22 { 23 popupFeatures.show(); 24 targetName.setLabel( editor.lang.link.targetPopupName ); 25 } 26 else 27 { 28 popupFeatures.hide(); 29 targetName.setLabel( editor.lang.link.targetFrameName ); 30 this.getDialog().setValueOf( 'target', 'linkTargetName', value.charAt( 0 ) == '_' ? value : '' ); 31 } 32 }, 33 // Handles the event when the "Type" selection box is changed. 34 linkTypeChanged = function() 35 { 36 var dialog = this.getDialog(), 37 partIds = [ 'urlOptions', 'anchorOptions', 'emailOptions' ], 38 typeValue = this.getValue(); 39 if ( typeValue == 'url' ) 40 { 41 if ( editor.config.link.showTargetTab ) 42 dialog.showPage( 'target' ); 43 if ( editor.config.link.uploadTab ) 44 dialog.showPage( 'upload' ); 45 } 46 else 47 { 48 dialog.hidePage( 'target' ); 49 dialog.hidePage( 'upload' ); 50 } 51 52 for ( var i = 0 ; i < partIds.length ; i++ ) 53 { 54 var element = dialog.getContentElement( 'info', partIds[i] ); 55 if ( !element ) 56 continue; 57 58 element = element.getElement().getParent().getParent(); 59 if ( partIds[i] == typeValue + 'Options' ) 60 element.show(); 61 else 62 element.hide(); 63 } 64 }, 65 // Loads the parameters in a selected link to the link dialog fields. 66 emailRegex = /^mailto:([^?]+)(?:\?(.+))?$/, 67 emailSubjectRegex = /subject=([^;?:@&=$,\/]*)/, 68 emailBodyRegex = /body=([^;?:@&=$,\/]*)/, 69 anchorRegex = /^#(.*)$/, 70 urlRegex = /^((?:http|https|ftp|news):\/\/)?(.*)$/, 71 selectableTargets = /^(_(?:self|top|parent|blank))$/, 72 popupRegex = 73 /\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*/, 74 popupFeaturesRegex = /(?:^|,)([^=]+)=(\d+|yes|no)/gi, 75 parseLink = function( editor, element ) 76 { 77 var href = element ? ( element.getAttribute( '_cke_saved_href' ) || element.getAttribute( 'href' ) ) : '', 78 emailMatch = '', 79 anchorMatch = '', 80 urlMatch = false, 81 retval = {}; 82 83 if ( href != null ) 84 { 85 emailMatch = href.match( emailRegex ); 86 anchorMatch = href.match( anchorRegex ); 87 urlMatch = href.match( urlRegex ); 88 } 89 90 // Load the link type and URL. 91 if ( emailMatch ) 92 { 93 var subjectMatch = href.match( emailSubjectRegex ), 94 bodyMatch = href.match( emailBodyRegex ); 95 retval.type = 'email'; 96 retval.email = {}; 97 retval.email.address = emailMatch[1]; 98 subjectMatch && ( retval.email.subject = decodeURIComponent( subjectMatch[1] ) ); 99 bodyMatch && ( retval.email.body = decodeURIComponent( bodyMatch[1] ) ); 100 } 101 else if ( anchorMatch ) 102 { 103 retval.type = 'anchor'; 104 retval.anchor = {}; 105 retval.anchor.name = retval.anchor.id = anchorMatch[1]; 106 } 107 else if ( urlMatch ) 108 { 109 retval.type = 'url'; 110 retval.url = {}; 111 retval.url.protocol = urlMatch[1]; 112 retval.url.url = urlMatch[2]; 113 } 114 else 115 retval.type = 'url'; 116 117 // Load target and popup settings. 118 if ( element ) 119 { 120 var target = element.getAttribute( 'target' ); 121 retval.target = {}; 122 retval.adv = {}; 123 124 if ( target == null ) 125 { 126 var onclick = element.getAttribute( '_cke_saved_onclick' ) || element.getAttribute( 'onclick' ), 127 onclickMatch = onclick && onclick.match( popupRegex ); 128 if ( onclickMatch ) 129 { 130 retval.target.type = 'popup'; 131 retval.target.name = onclickMatch[1]; 132 133 var featureMatch; 134 while ( ( featureMatch = popupFeaturesRegex.exec( onclickMatch[2] ) ) ) 135 { 136 if ( featureMatch[2] == 'yes' || featureMatch[2] == '1' ) 137 retval.target[ featureMatch[1] ] = true; 138 else if ( isFinite( featureMatch[2] ) ) 139 retval.target[ featureMatch[1] ] = featureMatch[2]; 140 } 141 } 142 } 143 else 144 { 145 var targetMatch = target.match( selectableTargets ); 146 if ( targetMatch ) 147 retval.target.type = retval.target.name = target; 148 else 149 { 150 retval.target.type = 'frame'; 151 retval.target.name = target; 152 } 153 } 154 155 var me = this, 156 advAttr = function( inputName, attrName ) 157 { 158 var value = element.getAttribute( attrName ); 159 if ( value != null ) 160 retval.adv[ inputName ] = value || ''; 161 }; 162 advAttr( 'advId', 'id' ); 163 advAttr( 'advLangDir', 'dir' ); 164 advAttr( 'advAccessKey', 'accessKey' ); 165 advAttr( 'advName', 'name' ); 166 advAttr( 'advLangCode', 'lang' ); 167 advAttr( 'advTabIndex', 'tabindex' ); 168 advAttr( 'advTitle', 'title' ); 169 advAttr( 'advContentType', 'type' ); 170 advAttr( 'advCSSClasses', 'class' ); 171 advAttr( 'advCharset', 'charset' ); 172 advAttr( 'advStyles', 'style' ); 173 } 174 175 // Find out whether we have any anchors in the editor. 176 // Get all IMG elements in CK document. 177 var elements = editor.document.$.getElementsByTagName( 'img' ), 178 anchors = retval.anchors = []; 179 for( var i = 0; i < elements.length; i++ ) 180 { 181 var item = elements.item( i ); 182 if ( item.getAttribute( '_cke_protected_html' ) && item.getAttribute( '_cke_real_element_type' ) == "anchor" ) 183 { 184 var domElement = new CKEDITOR.dom.element( item ); 185 domElement = editor.fakeobjects.restoreElement( domElement ); 186 anchors.push( domElement ); 187 } 188 } 189 for ( var i = 0, name, id ; i < anchors.length ; i++ ) 190 { 191 name = anchors[i].getAttribute( 'name' ); 192 id = anchors[i].getAttribute( 'id' ); 193 anchors.push( { name : name, id : id } ); 194 } 195 196 // Record down the selected element in the dialog. 197 this._.selectedElement = element; 198 199 return retval; 200 }, 201 setupParams = function( page, data ) 202 { 203 if ( data[page] ) 204 this.setValue( data[page][this.id] || '' ); 205 }, 206 setupPopupParams = function( data ) 207 { 208 return setupParams.call( this, 'target', data ); 209 }, 210 setupAdvParams = function( data ) 211 { 212 return setupParams.call( this, 'adv', data ); 213 }, 214 commitParams = function( page, data ) 215 { 216 if ( !data[page] ) 217 data[page] = {}; 218 219 data[page][this.id] = this.getValue() || ''; 220 }, 221 commitPopupParams = function( data ) 222 { 223 return commitParams.call( this, 'target', data ); 224 }, 225 commitAdvParams = function( data ) 226 { 227 return commitParams.call( this, 'adv', data ); 228 }; 229 230 return { 231 title : editor.lang.link.title, 232 minWidth : 400, 233 minHeight : 320, 234 contents : [ 235 { 236 id : 'info', 237 label : editor.lang.link.info, 238 title : editor.lang.link.info, 239 elements : 240 [ 241 { 242 id : 'linkType', 243 type : 'select', 244 label : editor.lang.link.type, 245 'default' : editor.config.link.defaultValues.linkType, 246 items : 247 [ 248 [ editor.lang.common.url, 'url' ], 249 [ editor.lang.link.toAnchor, 'anchor' ], 250 [ editor.lang.link.toEmail, 'email' ] 251 ], 252 onChange : linkTypeChanged, 253 setup : function( data ) 254 { 255 if ( data.type ) 256 this.setValue( data.type ); 257 }, 258 commit : function( data ) 259 { 260 data.type = this.getValue(); 261 } 262 }, 263 { 264 type : 'vbox', 265 id : 'urlOptions', 266 children : 267 [ 268 { 269 type : 'hbox', 270 widths : [ '25%', '75%' ], 271 children : 272 [ 273 { 274 id : 'protocol', 275 type : 'select', 276 label : editor.lang.common.protocol, 277 'default' : editor.config.link.defaultValues.protocol, 278 style : 'width : 100%;', 279 items : 280 [ 281 [ 'http://' ], 282 [ 'https//' ], 283 [ 'ftp://' ], 284 [ 'news://' ], 285 [ '<other>', '' ] 286 ], 287 setup : function( data ) 288 { 289 if ( data.url ) 290 this.setValue( data.url.protocol ); 291 }, 292 commit : function( data ) 293 { 294 if ( !data.url ) 295 data.url = {}; 296 297 data.url.protocol = this.getValue(); 298 } 299 }, 300 { 301 type : 'text', 302 id : 'url', 303 label : editor.lang.common.url, 304 validate : function() 305 { 306 var dialog = this.getDialog(); 307 308 if ( dialog.getContentElement( 'info', 'linkType' ) && 309 dialog.getValueOf( 'info', 'linkType' ) != 'url' ) 310 return true; 311 312 if ( this.getDialog().fakeObj != false ) // Edit Anchor. 313 return true; 314 315 var func = CKEDITOR.dialog.validate.notEmpty( editor.lang.link.noUrl ); 316 return func.apply( this ); 317 }, 318 setup : function( data ) 319 { 320 if ( data.url ) 321 this.setValue( data.url.url ); 322 323 var linkType = this.getDialog().getContentElement( 'info', 'linkType' ); 324 if ( linkType && linkType.getValue() == 'url' ) 325 this.select(); 326 }, 327 commit : function( data ) 328 { 329 if ( !data.url ) 330 data.url = {}; 331 332 data.url.url = this.getValue(); 333 } 334 } 335 ], 336 setup : function( data ) 337 { 338 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) 339 this.getElement().show(); 340 } 341 }, 342 { 343 type : 'button', 344 id : 'browse', 345 label : editor.lang.common.browseServer 346 } 347 ] 348 }, 349 { 350 type : 'vbox', 351 id : 'anchorOptions', 352 width : 260, 353 align : 'center', 354 padding : 0, 355 children : 356 [ 357 { 358 type : 'html', 359 id : 'selectAnchorText', 360 html : CKEDITOR.tools.htmlEncode( editor.lang.link.selectAnchor ), 361 setup : function( data ) 362 { 363 if ( data.anchors.length > 0 ) 364 this.getElement().show(); 365 else 366 this.getElement().hide(); 367 } 368 }, 369 { 370 type : 'html', 371 id : 'noAnchors', 372 style : 'text-align: center;', 373 html : '<div>' + CKEDITOR.tools.htmlEncode( editor.lang.link.noAnchors ) + '</div>', 374 setup : function( data ) 375 { 376 if ( data.anchors.length < 1 ) 377 this.getElement().show(); 378 else 379 this.getElement().hide(); 380 } 381 }, 382 { 383 type : 'hbox', 384 id : 'selectAnchor', 385 children : 386 [ 387 { 388 type : 'select', 389 id : 'anchorName', 390 'default' : '', 391 label : editor.lang.link.anchorName, 392 style : 'width: 100%;', 393 items : 394 [ 395 [ '' ] 396 ], 397 setup : function( data ) 398 { 399 this.clear(); 400 this.add( '' ); 401 for ( var i = 0 ; i < data.anchors.length ; i++ ) 402 { 403 if ( data.anchors[i].name ) 404 this.add( data.anchors[i].name ); 405 } 406 407 if ( data.anchor ) 408 this.setValue( data.anchor.name ); 409 410 var linkType = this.getDialog().getContentElement( 'info', 'linkType' ); 411 if ( linkType && linkType.getValue() == 'email' ) 412 this.focus(); 413 }, 414 commit : function( data ) 415 { 416 if ( !data.anchor ) 417 data.anchor = {}; 418 419 data.anchor.name = this.getValue(); 420 } 421 }, 422 { 423 type : 'select', 424 id : 'anchorId', 425 'default' : '', 426 label : editor.lang.link.anchorId, 427 style : 'width: 100%;', 428 items : 429 [ 430 [ '' ] 431 ], 432 setup : function( data ) 433 { 434 this.clear(); 435 this.add( '' ); 436 for ( var i = 0 ; i < data.anchors.length ; i++ ) 437 { 438 if ( data.anchors[i].id ) 439 this.add( data.anchors[i].id ); 440 } 441 442 if ( data.anchor ) 443 this.setValue( data.anchor.id ); 444 }, 445 commit : function( data ) 446 { 447 if ( !data.anchor ) 448 data.anchor = {}; 449 450 data.anchor.id = this.getValue(); 451 } 452 } 453 ], 454 setup : function( data ) 455 { 456 if ( data.anchors.length > 0 ) 457 this.getElement().show(); 458 else 459 this.getElement().hide(); 460 } 461 } 462 ], 463 setup : function( data ) 464 { 465 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) 466 this.getElement().hide(); 467 } 468 }, 469 { 470 type : 'vbox', 471 id : 'emailOptions', 472 padding : 1, 473 children : 474 [ 475 { 476 type : 'text', 477 id : 'emailAddress', 478 label : editor.lang.link.emailAddress, 479 validate : function() 480 { 481 var dialog = this.getDialog(); 482 483 if ( !dialog.getContentElement( 'info', 'linkType' ) || 484 dialog.getValueOf( 'info', 'linkType' ) != 'email' ) 485 return true; 486 487 var func = CKEDITOR.dialog.validate.notEmpty( editor.lang.link.noEmail ); 488 return func.apply( this ); 489 }, 490 setup : function( data ) 491 { 492 if ( data.email ) 493 this.setValue( data.email.address ); 494 495 var linkType = this.getDialog().getContentElement( 'info', 'linkType' ); 496 if ( linkType && linkType.getValue() == 'email' ) 497 this.select(); 498 }, 499 commit : function( data ) 500 { 501 if ( !data.email ) 502 data.email = {}; 503 504 data.email.address = this.getValue(); 505 } 506 }, 507 { 508 type : 'text', 509 id : 'emailSubject', 510 label : editor.lang.link.emailSubject, 511 setup : function( data ) 512 { 513 if ( data.email ) 514 this.setValue( data.email.subject ); 515 }, 516 commit : function( data ) 517 { 518 if ( !data.email ) 519 data.email = {}; 520 521 data.email.subject = this.getValue(); 522 } 523 }, 524 { 525 type : 'textarea', 526 id : 'emailBody', 527 label : editor.lang.link.emailBody, 528 rows : 3, 529 'default' : '', 530 setup : function( data ) 531 { 532 if ( data.email ) 533 this.setValue( data.email.body ); 534 }, 535 commit : function( data ) 536 { 537 if ( !data.email ) 538 data.email = {}; 539 540 data.email.body = this.getValue(); 541 } 542 } 543 ], 544 setup : function( data ) 545 { 546 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) 547 this.getElement().hide(); 548 } 549 } 550 ] 551 }, 552 { 553 id : 'target', 554 label : editor.lang.link.target, 555 title : editor.lang.link.target, 556 elements : 557 [ 558 { 559 type : 'hbox', 560 widths : [ '50%', '50%' ], 561 children : 562 [ 563 { 564 type : 'select', 565 id : 'linkTargetType', 566 label : editor.lang.link.target, 567 'default' : editor.config.link.defaultValues.target, 568 style : 'width : 100%;', 569 'items' : 570 [ 571 [ editor.lang.link.targetNotSet, 'notSet' ], 572 [ editor.lang.link.targetFrame, 'frame' ], 573 [ editor.lang.link.targetPopup, 'popup' ], 574 [ editor.lang.link.targetNew, '_blank' ], 575 [ editor.lang.link.targetTop, '_top' ], 576 [ editor.lang.link.targetSelf, '_self' ], 577 [ editor.lang.link.targetParent, '_parent' ] 578 ], 579 onChange : targetChanged, 580 setup : function( data ) 581 { 582 if ( data.target ) 583 this.setValue( data.target.type ); 584 }, 585 commit : function( data ) 586 { 587 if ( !data.target ) 588 data.target = {}; 589 590 data.target.type = this.getValue(); 591 } 592 }, 593 { 594 type : 'text', 595 id : 'linkTargetName', 596 label : editor.lang.link.targetFrameName, 597 'default' : editor.config.link.defaultValues.targetFrameName, 598 setup : function( data ) 599 { 600 if ( data.target ) 601 this.setValue( data.target.name ); 602 }, 603 commit : function( data ) 604 { 605 if ( !data.target ) 606 data.target = {}; 607 608 data.target.name = this.getValue(); 609 } 610 } 611 ] 612 }, 613 { 614 type : 'vbox', 615 width : 260, 616 align : 'center', 617 padding : 2, 618 id : 'popupFeatures', 619 children : 620 [ 621 { 622 type : 'html', 623 html : CKEDITOR.tools.htmlEncode( editor.lang.link.popupFeatures ) 624 }, 625 { 626 type : 'hbox', 627 children : 628 [ 629 { 630 type : 'checkbox', 631 id : 'resizable', 632 label : editor.lang.link.popupResizable, 633 setup : setupPopupParams, 634 commit : commitPopupParams 635 }, 636 { 637 type : 'checkbox', 638 id : 'status', 639 label : editor.lang.link.popupStatusBar, 640 setup : setupPopupParams, 641 commit : commitPopupParams 642 643 } 644 ] 645 }, 646 { 647 type : 'hbox', 648 children : 649 [ 650 { 651 type : 'checkbox', 652 id : 'location', 653 label : editor.lang.link.popupLocationBar, 654 setup : setupPopupParams, 655 commit : commitPopupParams 656 657 }, 658 { 659 type : 'checkbox', 660 id : 'toolbar', 661 label : editor.lang.link.popupToolbar, 662 setup : setupPopupParams, 663 commit : commitPopupParams 664 665 } 666 ] 667 }, 668 { 669 type : 'hbox', 670 children : 671 [ 672 { 673 type : 'checkbox', 674 id : 'menubar', 675 label : editor.lang.link.popupMenuBar, 676 setup : setupPopupParams, 677 commit : commitPopupParams 678 679 }, 680 { 681 type : 'checkbox', 682 id : 'fullscreen', 683 label : editor.lang.link.popupFullScreen, 684 setup : setupPopupParams, 685 commit : commitPopupParams 686 687 } 688 ] 689 }, 690 { 691 type : 'hbox', 692 children : 693 [ 694 { 695 type : 'checkbox', 696 id : 'scrollbars', 697 label : editor.lang.link.popupScrollBars, 698 setup : setupPopupParams, 699 commit : commitPopupParams 700 701 }, 702 { 703 type : 'checkbox', 704 id : 'dependent', 705 label : editor.lang.link.popupDependent, 706 setup : setupPopupParams, 707 commit : commitPopupParams 708 709 } 710 ] 711 }, 712 { 713 type : 'hbox', 714 children : 715 [ 716 { 717 type : 'text', 718 widths : [ '30%', '70%' ], 719 labelLayout : 'horizontal', 720 label : editor.lang.link.popupWidth, 721 id : 'width', 722 setup : setupPopupParams, 723 commit : commitPopupParams 724 725 }, 726 { 727 type : 'text', 728 labelLayout : 'horizontal', 729 widths : [ '55%', '45%' ], 730 label : editor.lang.link.popupLeft, 731 id : 'left', 732 setup : setupPopupParams, 733 commit : commitPopupParams 734 735 } 736 ] 737 }, 738 { 739 type : 'hbox', 740 children : 741 [ 742 { 743 type : 'text', 744 labelLayout : 'horizontal', 745 widths : [ '30%', '70%' ], 746 label : editor.lang.link.popupHeight, 747 id : 'height', 748 setup : setupPopupParams, 749 commit : commitPopupParams 750 751 }, 752 { 753 type : 'text', 754 labelLayout : 'horizontal', 755 label : editor.lang.link.popupTop, 756 widths : [ '55%', '45%' ], 757 id : 'top', 758 setup : setupPopupParams, 759 commit : commitPopupParams 760 761 } 762 ] 763 } 764 ] 765 } 766 ] 767 }, 768 { 769 id : 'upload', 770 label : editor.lang.link.upload, 771 title : editor.lang.link.upload, 772 elements : 773 [ 774 { 775 type : 'file', 776 id : 'upload', 777 label : editor.lang.common.upload, 778 action : editor.config.link.uploadAction, 779 size : 38 780 }, 781 { 782 type : 'fileButton', 783 id : 'uploadButton', 784 label : editor.lang.common.uploadSubmit, 785 'for' : [ 'upload', 'upload' ] 786 } 787 ] 788 }, 789 { 790 id : 'advanced', 791 label : editor.lang.link.advanced, 792 title : editor.lang.link.advanced, 793 elements : 794 [ 795 { 796 type : 'vbox', 797 padding : 1, 798 children : 799 [ 800 { 801 type : 'hbox', 802 widths : [ '45%', '35%', '20%' ], 803 children : 804 [ 805 { 806 type : 'text', 807 id : 'advId', 808 label : editor.lang.link.id, 809 setup : setupAdvParams, 810 commit : commitAdvParams 811 }, 812 { 813 type : 'select', 814 id : 'advLangDir', 815 label : editor.lang.link.langDir, 816 'default' : editor.config.link.defaultValues.langDir, 817 style : 'width: 100%;', 818 items : 819 [ 820 [ editor.lang.link.langDirNotSet, '' ], 821 [ editor.lang.link.langDirLTR, 'ltr' ], 822 [ editor.lang.link.langDirRTL, 'rtl' ] 823 ], 824 setup : setupAdvParams, 825 commit : commitAdvParams 826 }, 827 { 828 type : 'text', 829 id : 'advAccessKey', 830 label : editor.lang.link.acccessKey, 831 maxLength : 1, 832 setup : setupAdvParams, 833 commit : commitAdvParams 834 835 } 836 ] 837 }, 838 { 839 type : 'hbox', 840 widths : [ '45%', '35%', '20%' ], 841 children : 842 [ 843 { 844 type : 'text', 845 label : editor.lang.link.name, 846 id : 'advName', 847 setup : setupAdvParams, 848 commit : commitAdvParams 849 850 }, 851 { 852 type : 'text', 853 label : editor.lang.link.langCode, 854 id : 'advLangCode', 855 'default' : editor.config.link.defaultValues.langCode, 856 setup : setupAdvParams, 857 commit : commitAdvParams 858 859 }, 860 { 861 type : 'text', 862 label : editor.lang.link.tabIndex, 863 id : 'advTabIndex', 864 maxLength : 5, 865 setup : setupAdvParams, 866 commit : commitAdvParams 867 868 } 869 ] 870 } 871 ] 872 }, 873 { 874 type : 'vbox', 875 padding : 1, 876 children : 877 [ 878 { 879 type : 'hbox', 880 widths : [ '45%', '55%' ], 881 children : 882 [ 883 { 884 type : 'text', 885 label : editor.lang.link.advisoryTitle, 886 'default' : editor.config.link.defaultValues.title, 887 id : 'advTitle', 888 setup : setupAdvParams, 889 commit : commitAdvParams 890 891 }, 892 { 893 type : 'text', 894 label : editor.lang.link.advisoryContentType, 895 'default' : editor.config.link.defaultValues.type, 896 id : 'advContentType', 897 setup : setupAdvParams, 898 commit : commitAdvParams 899 900 } 901 ] 902 }, 903 { 904 type : 'hbox', 905 widths : [ '45%', '55%' ], 906 children : 907 [ 908 { 909 type : 'text', 910 label : editor.lang.link.cssClasses, 911 'default' : editor.config.link.defaultValues.classes, 912 id : 'advCSSClasses', 913 setup : setupAdvParams, 914 commit : commitAdvParams 915 916 }, 917 { 918 type : 'text', 919 label : editor.lang.link.charset, 920 'default' : editor.config.link.defaultValues.charset, 921 id : 'advCharset', 922 setup : setupAdvParams, 923 commit : commitAdvParams 924 925 } 926 ] 927 }, 928 { 929 type : 'hbox', 930 children : 931 [ 932 { 933 type : 'text', 934 label : editor.lang.link.styles, 935 'default' : editor.config.link.defaultValues.style, 936 id : 'advStyles', 937 setup : setupAdvParams, 938 commit : commitAdvParams 939 940 } 941 ] 942 } 943 ] 944 } 945 ] 946 } 947 ], 948 onShow : function() 949 { 950 this.fakeObj = false; 951 // IE BUG: Selection must be in the editor for getSelection() to work. 952 this.restoreSelection(); 953 var editor = this.getParentEditor(), 954 selection = editor.getSelection(), 955 ranges = selection.getRanges(), 956 element = null, 957 me = this; 958 959 // Fill in all the relevant fields if there's already one link selected. 960 if ( ranges.length == 1 ) 961 { 962 ranges[0].enlarge( CKEDITOR.ENLARGE_ELEMENT ); 963 964 var rangeRoot = ranges[0].getCommonAncestor( true ); 965 element = rangeRoot.getAscendant( 'a', true ); 966 if ( element && element.getAttribute( 'href' ) ) 967 { 968 selection.selectElement( element ); 969 this.saveSelection(); 970 } 971 else 972 { 973 element = rangeRoot.getAscendant( 'img', true ); 974 if ( element && element.getAttribute( '_cke_real_element_type' ) && element.getAttribute( '_cke_real_element_type' ) == 'anchor' ) 975 { 976 this.fakeObj = element; 977 element = editor.fakeobjects.restoreElement( this.fakeObj ); 978 selection.selectElement( this.fakeObj ); 979 this.saveSelection(); 980 } 981 } 982 } 983 984 this.setupContent( parseLink.apply( this, [ editor, element ] ) ); 985 986 // Push the current values into the dialog default value stack. 987 this.pushDefault(); 988 }, 989 onOk : function() 990 { 991 var attributes = { href : 'javascript:void(0)/*' + CKEDITOR.tools.getNextNumber() + '*/' }, 992 removeAttributes = [], 993 data = { href : attributes.href }, 994 me = this, editor = this.getParentEditor(); 995 996 this.commitContent( data ); 997 998 // Compose the URL. 999 switch ( data.type || 'url' ) 1000 { 1001 case 'url': 1002 var protocol = ( data.url && data.url.protocol ) || 'http://', 1003 url = ( data.url && data.url.url ) || ''; 1004 attributes._cke_saved_href = protocol + url; 1005 break; 1006 case 'anchor': 1007 var name = ( data.anchor && data.anchor.name ), 1008 id = ( data.anchor && data.anchor.id ); 1009 attributes._cke_saved_href = '#' + ( name || id || '' ); 1010 break; 1011 case 'email': 1012 var address = ( data.email && data.email.address ), 1013 subject = ( data.email && encodeURIComponent( data.email.subject || '' ) ), 1014 body = ( data.email && encodeURIComponent( data.email.body || '' ) ), 1015 linkList = [ 'mailto:', address ]; 1016 if ( subject || body ) 1017 { 1018 var argList = []; 1019 linkList.push( '?' ); 1020 subject && argList.push( 'subject=' + subject ); 1021 body && argList.push( 'body=' + body ); 1022 linkList.push( argList.join( '&' ) ); 1023 } 1024 attributes._cke_saved_href = linkList.join( '' ); 1025 break; 1026 default: 1027 } 1028 1029 // Popups and target. 1030 if ( data.target ) 1031 { 1032 if ( data.target.type == 'popup' ) 1033 { 1034 var onclickList = [ 'window.open(this.href, \'', 1035 data.target.name || '', '\', \'' ], 1036 featureList = [ 'resizable', 'status', 'location', 'toolbar', 'menubar', 'fullscreen', 1037 'scrollbars', 'dependent' ], 1038 featureLength = featureList.length, 1039 addFeature = function( featureName ) 1040 { 1041 if ( data.target[ featureName ] ) 1042 featureList.push( featureName + '=' + data.target[ featureName ] ); 1043 }; 1044 1045 for ( var i = 0 ; i < featureLength ; i++ ) 1046 featureList[i] = featureList[i] + ( data.target[ featureList[i] ] ? '=yes' : '=no' ) ; 1047 addFeature( 'width' ); 1048 addFeature( 'left' ); 1049 addFeature( 'height' ); 1050 addFeature( 'top' ); 1051 1052 onclickList.push( featureList.join( ',' ), '\'); return false;' ); 1053 attributes._cke_saved_onclick = onclickList.join( '' ); 1054 } 1055 else 1056 { 1057 if ( data.target.type != 'notSet' ) 1058 attributes.target = data.target.name; 1059 removeAttributes.push( '_cke_saved_onclick', 'onclick' ); 1060 } 1061 } 1062 1063 // Advanced attributes. 1064 if ( data.adv ) 1065 { 1066 var advAttr = function( inputName, attrName ) 1067 { 1068 var value = data.adv[ inputName ]; 1069 if ( value ) 1070 attributes[attrName] = value; 1071 }; 1072 1073 if ( this._.selectedElement ) 1074 advAttr( 'advId', 'id' ); 1075 advAttr( 'advLangDir', 'dir' ); 1076 advAttr( 'advAccessKey', 'accessKey' ); 1077 advAttr( 'advName', 'name' ); 1078 advAttr( 'advLangCode', 'lang' ); 1079 advAttr( 'advTabIndex', 'tabindex' ); 1080 advAttr( 'advTitle', 'title' ); 1081 advAttr( 'advContentType', 'type' ); 1082 advAttr( 'advCSSClasses', 'class' ); 1083 advAttr( 'advCharset', 'charset' ); 1084 advAttr( 'advStyles', 'style' ); 1085 } 1086 1087 if ( !this._.selectedElement ) 1088 { 1089 // IE BUG: Selection must be in the editor for getSelection() to work. 1090 this.restoreSelection(); 1091 this.clearSavedSelection(); 1092 1093 // Create element if current selection is collapsed. 1094 var selection = editor.getSelection(), 1095 ranges = selection.getRanges(); 1096 if ( ranges.length == 1 && ranges[0].collapsed ) 1097 { 1098 ranges[0].insertNode( new CKEDITOR.dom.text( attributes._cke_saved_href, editor.document ) ); 1099 selection.selectRanges( ranges ); 1100 } 1101 1102 // Apply style. 1103 var style = new CKEDITOR.style( { element : 'a', attributes : attributes } ); 1104 style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why. 1105 style.apply( editor.document ); 1106 1107 // Id. Apply only to the first link. 1108 if ( data.adv && data.adv.advId != '' ) 1109 { 1110 var links = this.getParentEditor().document.$.getElementsByTagName( 'a' ); 1111 for ( var i = 0 ; i < links.length ; i++ ) 1112 { 1113 if ( links[i].href == attributes.href ) 1114 { 1115 links[i].id = data.adv.advId; 1116 break; 1117 } 1118 } 1119 } 1120 } 1121 else 1122 { 1123 // We're only editing an existing link, so just overwrite the attributes. 1124 var element = this._.selectedElement; 1125 element.setAttributes( attributes ); 1126 element.removeAttributes( removeAttributes ); 1127 if ( this.fakeObj ) 1128 editor.fakeobjects.updateFakeElement( this.fakeObj, element ); 1129 1130 delete this._.selectedElement; 1131 } 1132 }, 1133 onLoad : function() 1134 { 1135 if ( editor.config.link.uploadTab == false ) 1136 this.hidePage( 'upload' ); //Hide Upload tab. 1137 1138 if ( editor.config.link.showAdvancedTab == false ) 1139 this.hidePage( 'advanced' ); //Hide Advanded tab. 1140 1141 if ( editor.config.link.browseServer == false ) 1142 this.getContentElement( 'info', 'browse' ).getElement().hide(); 1143 1144 if ( editor.config.link.showTargetTab == false ) 1145 this.hidePage( 'target' ); //Hide Target tab. 1146 1147 }, 1148 onHide : function() 1149 { 1150 // Pop the default values from default value set that are pushed in onShow(). 1151 this.popDefault(); 1152 } 1153 }; 1154 } ); -
_source/plugins/link/plugin.js
1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 CKEDITOR.plugins.add( 'link', 7 { 8 init : function( editor, pluginPath ) 9 { 10 // Add the link and unlink buttons. 11 editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link' ) ); 12 editor.addCommand( 'anchor', new CKEDITOR.dialogCommand( 'anchor' ) ); 13 editor.addCommand( 'unlink', new CKEDITOR.unlinkCommand() ); 14 editor.ui.addButton( 'Link', 15 { 16 label : editor.lang.link.toolbar, 17 command : 'link' 18 } ); 19 editor.ui.addButton( 'Unlink', 20 { 21 label : editor.lang.unlink, 22 command : 'unlink' 23 } ); 24 editor.ui.addButton( 'Anchor', 25 { 26 label : editor.lang.anchor.toolbar, 27 command : 'anchor' 28 } ); 29 CKEDITOR.dialog.add( 'link', this.path + 'dialogs/link.js' ); 30 CKEDITOR.dialog.add( 'anchor', this.path + 'dialogs/anchor.js' ); 31 // Register selection change handler for the unlink button. 32 editor.on( 'selectionChange', function( evt ) 33 { 34 /* 35 * Despite our initial hope, document.queryCommandEnabled() does not work 36 * for this in Firefox. So we must detect the state by element paths. 37 */ 38 var command = editor.getCommand( 'unlink' ), 39 element = evt.data.path.lastElement.getAscendant( 'a', true ); 40 if ( element && element.getName() == 'a' && element.getAttribute( 'href' ) ) 41 command.state = CKEDITOR.TRISTATE_OFF; 42 else 43 command.state = CKEDITOR.TRISTATE_DISABLED; 44 command.fire( 'state' ); 45 } ); 46 }, 47 48 requires : [ 'fakeobjects' ] 49 } ); 50 51 CKEDITOR.unlinkCommand = function(){}; 52 CKEDITOR.unlinkCommand.prototype = 53 { 54 /** @ignore */ 55 exec : function( editor ) 56 { 57 /* 58 * execCommand( 'unlink', ... ) in Firefox leaves behind <span> tags at where 59 * the <a> was, so again we have to remove the link ourselves. (See #430) 60 * 61 * TODO: Use the style system when it's complete. Let's use execCommand() 62 * as a stopgap solution for now. 63 */ 64 var selection = editor.getSelection(), 65 bookmarks = selection.createBookmarks(), 66 ranges = selection.getRanges(), 67 rangeRoot, 68 element; 69 70 for ( var i = 0 ; i < ranges.length ; i++ ) 71 { 72 rangeRoot = ranges[i].getCommonAncestor( true ); 73 element = rangeRoot.getAscendant( 'a', true ); 74 if ( !element ) 75 continue; 76 ranges[i].selectNodeContents( element ); 77 } 78 79 selection.selectRanges( ranges ); 80 editor.document.$.execCommand( 'unlink', false, null ); 81 selection.selectBookmarks( bookmarks ); 82 } 83 }; 84 85 CKEDITOR.config.link = 86 { 87 uploadTab : true, 88 browseServer : true, 89 uploadAction : 'nowhere.php', 90 showAdvancedTab : true, 91 showTargetTab : true, 92 defaultValues : 93 { 94 /** 95 * Startup values 96 * @type Text 97 * @default '' 98 */ 99 linkType : 'url', 100 protocol : 'http://', 101 target : 'notSet', 102 targetFrameName : '', 103 title : '', 104 type : '', 105 classes : '', 106 langDir : '', 107 langCode : '', 108 charset : '', 109 style : '' 110 } 111 }; -
_source/plugins/toolbar/plugin.js
211 211 'Bold', 'Italic', 'Underline', 'Strike', '-', 212 212 'Subscript', 'Superscript', '-', 213 213 'SelectAll', 'RemoveFormat', '-', 214 'Link', 'Unlink', 'Anchor', '-', 214 215 'Smiley', 'HorizontalRule', 'SpecialChar' 215 216 ] 216 217 ];