| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 /* 2 Copyright (c) 2003-2010, 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 var plugin = CKEDITOR.plugins.link; 9 // Handles the event when the "Target" selection box is changed. 10 var targetChanged = function() 11 { 12 var dialog = this.getDialog(), 13 popupFeatures = dialog.getContentElement( 'target', 'popupFeatures' ), 14 targetName = dialog.getContentElement( 'target', 'linkTargetName' ), 15 value = this.getValue(); 16 17 if ( !popupFeatures || !targetName ) 18 return; 19 20 popupFeatures = popupFeatures.getElement(); 21 popupFeatures.hide(); 22 targetName.setValue( '' ); 23 24 switch ( value ) 25 { 26 case 'frame' : 27 targetName.setLabel( editor.lang.link.targetFrameName ); 28 targetName.getElement().show(); 29 break; 30 case 'popup' : 31 popupFeatures.show(); 32 targetName.setLabel( editor.lang.link.targetPopupName ); 33 targetName.getElement().show(); 34 break; 35 default : 36 targetName.setValue( value ); 37 targetName.getElement().hide(); 38 break; 39 } 40 41 }; 42 43 // Handles the event when the "Type" selection box is changed. 44 var linkTypeChanged = function() 45 { 46 var dialog = this.getDialog(), 47 partIds = [ 'urlOptions', 'anchorOptions', 'emailOptions' ], 48 typeValue = this.getValue(), 49 uploadTab = dialog.definition.getContents( 'upload' ), 50 uploadInitiallyHidden = uploadTab && uploadTab.hidden; 51 52 if ( typeValue == 'url' ) 53 { 54 if ( editor.config.linkShowTargetTab ) 55 dialog.showPage( 'target' ); 56 if ( !uploadInitiallyHidden ) 57 dialog.showPage( 'upload' ); 58 } 59 else 60 { 61 dialog.hidePage( 'target' ); 62 if ( !uploadInitiallyHidden ) 63 dialog.hidePage( 'upload' ); 64 } 65 66 for ( var i = 0 ; i < partIds.length ; i++ ) 67 { 68 var element = dialog.getContentElement( 'info', partIds[i] ); 69 if ( !element ) 70 continue; 71 72 element = element.getElement().getParent().getParent(); 73 if ( partIds[i] == typeValue + 'Options' ) 74 element.show(); 75 else 76 element.hide(); 77 } 78 }; 79 80 // Loads the parameters in a selected link to the link dialog fields. 81 var javascriptProtocolRegex = /^javascript:/, 82 emailRegex = /^mailto:([^?]+)(?:\?(.+))?$/, 83 emailSubjectRegex = /subject=([^;?:@&=$,\/]*)/, 84 emailBodyRegex = /body=([^;?:@&=$,\/]*)/, 85 anchorRegex = /^#(.*)$/, 86 urlRegex = /^((?:http|https|ftp|news):\/\/)?(.*)$/, 87 selectableTargets = /^(_(?:self|top|parent|blank))$/, 88 encodedEmailLinkRegex = /^javascript:void\(location\.href='mailto:'\+String\.fromCharCode\(([^)]+)\)(?:\+'(.*)')?\)$/, 89 functionCallProtectedEmailLinkRegex = /^javascript:([^(]+)\(([^)]+)\)$/; 90 91 var popupRegex = 92 /\s*window.open\(\s*this\.href\s*,\s*(?:'([^']*)'|null)\s*,\s*'([^']*)'\s*\)\s*;\s*return\s*false;*\s*/; 93 var popupFeaturesRegex = /(?:^|,)([^=]+)=(\d+|yes|no)/gi; 94 95 var parseLink = function( editor, element ) 96 { 97 var href = ( element && ( element.getAttribute( '_cke_saved_href' ) || element.getAttribute( 'href' ) ) ) || '', 98 javascriptMatch, 99 emailMatch, 100 anchorMatch, 101 urlMatch, 102 retval = {}; 103 104 if ( ( javascriptMatch = href.match( javascriptProtocolRegex ) ) ) 105 { 106 if ( emailProtection == 'encode' ) 107 { 108 href = href.replace( encodedEmailLinkRegex, 109 function ( match, protectedAddress, rest ) 110 { 111 return 'mailto:' + 112 String.fromCharCode.apply( String, protectedAddress.split( ',' ) ) + 113 ( rest && unescapeSingleQuote( rest ) ); 114 }); 115 } 116 // Protected email link as function call. 117 else if ( emailProtection ) 118 { 119 href.replace( functionCallProtectedEmailLinkRegex, function( match, funcName, funcArgs ) 120 { 121 if ( funcName == compiledProtectionFunction.name ) 122 { 123 retval.type = 'email'; 124 var email = retval.email = {}; 125 126 var paramRegex = /[^,\s]+/g, 127 paramQuoteRegex = /(^')|('$)/g, 128 paramsMatch = funcArgs.match( paramRegex ), 129 paramsMatchLength = paramsMatch.length, 130 paramName, 131 paramVal; 132 133 for ( var i = 0; i < paramsMatchLength; i++ ) 134 { 135 paramVal = decodeURIComponent( unescapeSingleQuote( paramsMatch[ i ].replace( paramQuoteRegex, '' ) ) ); 136 paramName = compiledProtectionFunction.params[ i ].toLowerCase(); 137 email[ paramName ] = paramVal; 138 } 139 email.address = [ email.name, email.domain ].join( '@' ); 140 } 141 } ); 142 } 143 } 144 145 if ( !retval.type ) 146 { 147 if ( ( anchorMatch = href.match( anchorRegex ) ) ) 148 { 149 retval.type = 'anchor'; 150 retval.anchor = {}; 151 retval.anchor.name = retval.anchor.id = anchorMatch[1]; 152 } 153 // Protected email link as encoded string. 154 else if ( ( emailMatch = href.match( emailRegex ) ) ) 155 { 156 var subjectMatch = href.match( emailSubjectRegex ), 157 bodyMatch = href.match( emailBodyRegex ); 158 159 retval.type = 'email'; 160 var email = ( retval.email = {} ); 161 email.address = emailMatch[ 1 ]; 162 subjectMatch && ( email.subject = decodeURIComponent( subjectMatch[ 1 ] ) ); 163 bodyMatch && ( email.body = decodeURIComponent( bodyMatch[ 1 ] ) ); 164 } 165 // urlRegex matches empty strings, so need to check for href as well. 166 else if ( href && ( urlMatch = href.match( urlRegex ) ) ) 167 { 168 retval.type = 'url'; 169 retval.url = {}; 170 retval.url.protocol = urlMatch[1]; 171 retval.url.url = urlMatch[2]; 172 } 173 else 174 retval.type = 'url'; 175 } 176 177 // Load target and popup settings. 178 if ( element ) 179 { 180 var target = element.getAttribute( 'target' ); 181 retval.target = {}; 182 retval.adv = {}; 183 184 // IE BUG: target attribute is an empty string instead of null in IE if it's not set. 185 if ( !target ) 186 { 187 var onclick = element.getAttribute( '_cke_pa_onclick' ) || element.getAttribute( 'onclick' ), 188 onclickMatch = onclick && onclick.match( popupRegex ); 189 if ( onclickMatch ) 190 { 191 retval.target.type = 'popup'; 192 retval.target.name = onclickMatch[1]; 193 194 var featureMatch; 195 while ( ( featureMatch = popupFeaturesRegex.exec( onclickMatch[2] ) ) ) 196 { 197 if ( featureMatch[2] == 'yes' || featureMatch[2] == '1' ) 198 retval.target[ featureMatch[1] ] = true; 199 else if ( isFinite( featureMatch[2] ) ) 200 retval.target[ featureMatch[1] ] = featureMatch[2]; 201 } 202 } 203 } 204 else 205 { 206 var targetMatch = target.match( selectableTargets ); 207 if ( targetMatch ) 208 retval.target.type = retval.target.name = target; 209 else 210 { 211 retval.target.type = 'frame'; 212 retval.target.name = target; 213 } 214 } 215 216 var me = this; 217 var advAttr = function( inputName, attrName ) 218 { 219 var value = element.getAttribute( attrName ); 220 if ( value !== null ) 221 retval.adv[ inputName ] = value || ''; 222 }; 223 advAttr( 'advId', 'id' ); 224 advAttr( 'advLangDir', 'dir' ); 225 advAttr( 'advAccessKey', 'accessKey' ); 226 advAttr( 'advName', 'name' ); 227 advAttr( 'advLangCode', 'lang' ); 228 advAttr( 'advTabIndex', 'tabindex' ); 229 advAttr( 'advTitle', 'title' ); 230 advAttr( 'advContentType', 'type' ); 231 advAttr( 'advCSSClasses', 'class' ); 232 advAttr( 'advCharset', 'charset' ); 233 advAttr( 'advStyles', 'style' ); 234 } 235 236 // Find out whether we have any anchors in the editor. 237 // Get all IMG elements in CK document. 238 var elements = editor.document.getElementsByTag( 'img' ), 239 realAnchors = new CKEDITOR.dom.nodeList( editor.document.$.anchors ), 240 anchors = retval.anchors = []; 241 242 for ( var i = 0; i < elements.count() ; i++ ) 243 { 244 var item = elements.getItem( i ); 245 if ( item.getAttribute( '_cke_realelement' ) && item.getAttribute( '_cke_real_element_type' ) == 'anchor' ) 246 { 247 anchors.push( editor.restoreRealElement( item ) ); 248 } 249 } 250 251 for ( i = 0 ; i < realAnchors.count() ; i++ ) 252 anchors.push( realAnchors.getItem( i ) ); 253 254 for ( i = 0 ; i < anchors.length ; i++ ) 255 { 256 item = anchors[ i ]; 257 anchors[ i ] = { name : item.getAttribute( 'name' ), id : item.getAttribute( 'id' ) }; 258 } 259 260 // Record down the selected element in the dialog. 261 this._.selectedElement = element; 262 263 return retval; 264 }; 265 266 var setupParams = function( page, data ) 267 { 268 if ( data[page] ) 269 this.setValue( data[page][this.id] || '' ); 270 }; 271 272 var setupPopupParams = function( data ) 273 { 274 return setupParams.call( this, 'target', data ); 275 }; 276 277 var setupAdvParams = function( data ) 278 { 279 return setupParams.call( this, 'adv', data ); 280 }; 281 282 var commitParams = function( page, data ) 283 { 284 if ( !data[page] ) 285 data[page] = {}; 286 287 data[page][this.id] = this.getValue() || ''; 288 }; 289 290 var commitPopupParams = function( data ) 291 { 292 return commitParams.call( this, 'target', data ); 293 }; 294 295 var commitAdvParams = function( data ) 296 { 297 return commitParams.call( this, 'adv', data ); 298 }; 299 300 function unescapeSingleQuote( str ) 301 { 302 return str.replace( /\\'/g, '\'' ); 303 } 304 305 function escapeSingleQuote( str ) 306 { 307 return str.replace( /'/g, '\\$&' ); 308 } 309 310 var emailProtection = editor.config.emailProtection || ''; 311 312 // Compile the protection function pattern. 313 if ( emailProtection && emailProtection != 'encode' ) 314 { 315 var compiledProtectionFunction = {}; 316 317 emailProtection.replace( /^([^(]+)\(([^)]+)\)$/, function( match, funcName, params ) 318 { 319 compiledProtectionFunction.name = funcName; 320 compiledProtectionFunction.params = []; 321 params.replace( /[^,\s]+/g, function( param ) 322 { 323 compiledProtectionFunction.params.push( param ); 324 } ); 325 } ); 326 } 327 328 function protectEmailLinkAsFunction( email ) 329 { 330 var retval, 331 name = compiledProtectionFunction.name, 332 params = compiledProtectionFunction.params, 333 paramName, 334 paramValue; 335 336 retval = [ name, '(' ]; 337 for ( var i = 0; i < params.length; i++ ) 338 { 339 paramName = params[ i ].toLowerCase(); 340 paramValue = email[ paramName ]; 341 342 i > 0 && retval.push( ',' ); 343 retval.push( '\'', 344 paramValue ? 345 escapeSingleQuote( encodeURIComponent( email[ paramName ] ) ) 346 : '', 347 '\''); 348 } 349 retval.push( ')' ); 350 return retval.join( '' ); 351 } 352 353 function protectEmailAddressAsEncodedString( address ) 354 { 355 var charCode, 356 length = address.length, 357 encodedChars = []; 358 for ( var i = 0; i < length; i++ ) 359 { 360 charCode = address.charCodeAt( i ); 361 encodedChars.push( charCode ); 362 } 363 return 'String.fromCharCode(' + encodedChars.join( ',' ) + ')'; 364 } 365 366 return { 367 title : editor.lang.link.title, 368 minWidth : 350, 369 minHeight : 230, 370 contents : [ 371 { 372 id : 'info', 373 label : editor.lang.link.info, 374 title : editor.lang.link.info, 375 elements : 376 [ 377 { 378 id : 'linkType', 379 type : 'select', 380 label : editor.lang.link.type, 381 'default' : 'url', 382 items : 383 [ 384 [ editor.lang.link.toUrl, 'url' ], 385 [ editor.lang.link.toAnchor, 'anchor' ], 386 [ editor.lang.link.toEmail, 'email' ] 387 ], 388 onChange : linkTypeChanged, 389 setup : function( data ) 390 { 391 if ( data.type ) 392 this.setValue( data.type ); 393 }, 394 commit : function( data ) 395 { 396 data.type = this.getValue(); 397 } 398 }, 399 { 400 type : 'vbox', 401 id : 'urlOptions', 402 children : 403 [ 404 { 405 type : 'hbox', 406 widths : [ '25%', '75%' ], 407 children : 408 [ 409 { 410 id : 'protocol', 411 type : 'select', 412 label : editor.lang.common.protocol, 413 'default' : 'http://', 414 items : 415 [ 416 // Force 'ltr' for protocol names in BIDI. (#5433) 417 [ 'http://\u200E', 'http://' ], 418 [ 'https://\u200E', 'https://' ], 419 [ 'ftp://\u200E', 'ftp://' ], 420 [ 'news://\u200E', 'news://' ], 421 [ editor.lang.link.other , '' ] 422 ], 423 setup : function( data ) 424 { 425 if ( data.url ) 426 this.setValue( data.url.protocol || '' ); 427 }, 428 commit : function( data ) 429 { 430 if ( !data.url ) 431 data.url = {}; 432 433 data.url.protocol = this.getValue(); 434 } 435 }, 436 { 437 type : 'text', 438 id : 'url', 439 label : editor.lang.common.url, 440 required: true, 441 onLoad : function () 442 { 443 this.allowOnChange = true; 444 }, 445 onKeyUp : function() 446 { 447 this.allowOnChange = false; 448 var protocolCmb = this.getDialog().getContentElement( 'info', 'protocol' ), 449 url = this.getValue(), 450 urlOnChangeProtocol = /^(http|https|ftp|news):\/\/(?=.)/gi, 451 urlOnChangeTestOther = /^((javascript:)|[#\/\.\?])/gi; 452 453 var protocol = urlOnChangeProtocol.exec( url ); 454 if ( protocol ) 455 { 456 this.setValue( url.substr( protocol[ 0 ].length ) ); 457 protocolCmb.setValue( protocol[ 0 ].toLowerCase() ); 458 } 459 else if ( urlOnChangeTestOther.test( url ) ) 460 protocolCmb.setValue( '' ); 461 462 this.allowOnChange = true; 463 }, 464 onChange : function() 465 { 466 if ( this.allowOnChange ) // Dont't call on dialog load. 467 this.onKeyUp(); 468 }, 469 validate : function() 470 { 471 var dialog = this.getDialog(); 472 473 if ( dialog.getContentElement( 'info', 'linkType' ) && 474 dialog.getValueOf( 'info', 'linkType' ) != 'url' ) 475 return true; 476 477 if ( this.getDialog().fakeObj ) // Edit Anchor. 478 return true; 479 480 var func = CKEDITOR.dialog.validate.notEmpty( editor.lang.link.noUrl ); 481 return func.apply( this ); 482 }, 483 setup : function( data ) 484 { 485 this.allowOnChange = false; 486 if ( data.url ) 487 this.setValue( data.url.url ); 488 this.allowOnChange = true; 489 490 }, 491 commit : function( data ) 492 { 493 // IE will not trigger the onChange event if the mouse has been used 494 // to carry all the operations #4724 495 this.onChange(); 496 497 if ( !data.url ) 498 data.url = {}; 499 500 data.url.url = this.getValue(); 501 this.allowOnChange = false; 502 } 503 } 504 ], 505 setup : function( data ) 506 { 507 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) 508 this.getElement().show(); 509 } 510 }, 511 { 512 type : 'button', 513 id : 'browse', 514 hidden : 'true', 515 filebrowser : 'info:url', 516 label : editor.lang.common.browseServer 517 } 518 ] 519 }, 520 { 521 type : 'vbox', 522 id : 'anchorOptions', 523 width : 260, 524 align : 'center', 525 padding : 0, 526 children : 527 [ 528 { 529 type : 'fieldset', 530 id : 'selectAnchorText', 531 label : editor.lang.link.selectAnchor, 532 setup : function( data ) 533 { 534 if ( data.anchors.length > 0 ) 535 this.getElement().show(); 536 else 537 this.getElement().hide(); 538 }, 539 children : 540 [ 541 { 542 type : 'hbox', 543 id : 'selectAnchor', 544 children : 545 [ 546 { 547 type : 'select', 548 id : 'anchorName', 549 'default' : '', 550 label : editor.lang.link.anchorName, 551 style : 'width: 100%;', 552 items : 553 [ 554 [ '' ] 555 ], 556 setup : function( data ) 557 { 558 this.clear(); 559 this.add( '' ); 560 for ( var i = 0 ; i < data.anchors.length ; i++ ) 561 { 562 if ( data.anchors[i].name ) 563 this.add( data.anchors[i].name ); 564 } 565 566 if ( data.anchor ) 567 this.setValue( data.anchor.name ); 568 569 var linkType = this.getDialog().getContentElement( 'info', 'linkType' ); 570 if ( linkType && linkType.getValue() == 'email' ) 571 this.focus(); 572 }, 573 commit : function( data ) 574 { 575 if ( !data.anchor ) 576 data.anchor = {}; 577 578 data.anchor.name = this.getValue(); 579 } 580 }, 581 { 582 type : 'select', 583 id : 'anchorId', 584 'default' : '', 585 label : editor.lang.link.anchorId, 586 style : 'width: 100%;', 587 items : 588 [ 589 [ '' ] 590 ], 591 setup : function( data ) 592 { 593 this.clear(); 594 this.add( '' ); 595 for ( var i = 0 ; i < data.anchors.length ; i++ ) 596 { 597 if ( data.anchors[i].id ) 598 this.add( data.anchors[i].id ); 599 } 600 601 if ( data.anchor ) 602 this.setValue( data.anchor.id ); 603 }, 604 commit : function( data ) 605 { 606 if ( !data.anchor ) 607 data.anchor = {}; 608 609 data.anchor.id = this.getValue(); 610 } 611 } 612 ], 613 setup : function( data ) 614 { 615 if ( data.anchors.length > 0 ) 616 this.getElement().show(); 617 else 618 this.getElement().hide(); 619 } 620 } 621 ] 622 }, 623 { 624 type : 'html', 625 id : 'noAnchors', 626 style : 'text-align: center;', 627 html : '<div role="label" tabIndex="-1">' + CKEDITOR.tools.htmlEncode( editor.lang.link.noAnchors ) + '</div>', 628 // Focus the first element defined in above html. 629 focus : true, 630 setup : function( data ) 631 { 632 if ( data.anchors.length < 1 ) 633 this.getElement().show(); 634 else 635 this.getElement().hide(); 636 } 637 } 638 ], 639 setup : function( data ) 640 { 641 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) 642 this.getElement().hide(); 643 } 644 }, 645 { 646 type : 'vbox', 647 id : 'emailOptions', 648 padding : 1, 649 children : 650 [ 651 { 652 type : 'text', 653 id : 'emailAddress', 654 label : editor.lang.link.emailAddress, 655 required : true, 656 validate : function() 657 { 658 var dialog = this.getDialog(); 659 660 if ( !dialog.getContentElement( 'info', 'linkType' ) || 661 dialog.getValueOf( 'info', 'linkType' ) != 'email' ) 662 return true; 663 664 var func = CKEDITOR.dialog.validate.notEmpty( editor.lang.link.noEmail ); 665 return func.apply( this ); 666 }, 667 setup : function( data ) 668 { 669 if ( data.email ) 670 this.setValue( data.email.address ); 671 672 var linkType = this.getDialog().getContentElement( 'info', 'linkType' ); 673 if ( linkType && linkType.getValue() == 'email' ) 674 this.select(); 675 }, 676 commit : function( data ) 677 { 678 if ( !data.email ) 679 data.email = {}; 680 681 data.email.address = this.getValue(); 682 } 683 }, 684 { 685 type : 'text', 686 id : 'emailSubject', 687 label : editor.lang.link.emailSubject, 688 setup : function( data ) 689 { 690 if ( data.email ) 691 this.setValue( data.email.subject ); 692 }, 693 commit : function( data ) 694 { 695 if ( !data.email ) 696 data.email = {}; 697 698 data.email.subject = this.getValue(); 699 } 700 }, 701 { 702 type : 'textarea', 703 id : 'emailBody', 704 label : editor.lang.link.emailBody, 705 rows : 3, 706 'default' : '', 707 setup : function( data ) 708 { 709 if ( data.email ) 710 this.setValue( data.email.body ); 711 }, 712 commit : function( data ) 713 { 714 if ( !data.email ) 715 data.email = {}; 716 717 data.email.body = this.getValue(); 718 } 719 } 720 ], 721 setup : function( data ) 722 { 723 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) ) 724 this.getElement().hide(); 725 } 726 } 727 ] 728 }, 729 { 730 id : 'target', 731 label : editor.lang.link.target, 732 title : editor.lang.link.target, 733 elements : 734 [ 735 { 736 type : 'hbox', 737 widths : [ '50%', '50%' ], 738 children : 739 [ 740 { 741 type : 'select', 742 id : 'linkTargetType', 743 label : editor.lang.common.target, 744 'default' : 'notSet', 745 style : 'width : 100%;', 746 'items' : 747 [ 748 [ editor.lang.common.notSet, 'notSet' ], 749 [ editor.lang.link.targetFrame, 'frame' ], 750 [ editor.lang.link.targetPopup, 'popup' ], 751 [ editor.lang.common.targetNew, '_blank' ], 752 [ editor.lang.common.targetTop, '_top' ], 753 [ editor.lang.common.targetSelf, '_self' ], 754 [ editor.lang.common.targetParent, '_parent' ] 755 ], 756 onChange : targetChanged, 757 setup : function( data ) 758 { 759 if ( data.target ) 760 this.setValue( data.target.type ); 761 }, 762 commit : function( data ) 763 { 764 if ( !data.target ) 765 data.target = {}; 766 767 data.target.type = this.getValue(); 768 } 769 }, 770 { 771 type : 'text', 772 id : 'linkTargetName', 773 label : editor.lang.link.targetFrameName, 774 'default' : '', 775 setup : function( data ) 776 { 777 if ( data.target ) 778 this.setValue( data.target.name ); 779 }, 780 commit : function( data ) 781 { 782 if ( !data.target ) 783 data.target = {}; 784 785 data.target.name = this.getValue().replace(/\W/gi, ''); 786 } 787 } 788 ] 789 }, 790 { 791 type : 'vbox', 792 width : 260, 793 align : 'center', 794 padding : 2, 795 id : 'popupFeatures', 796 children : 797 [ 798 { 799 type : 'fieldset', 800 label : editor.lang.link.popupFeatures, 801 children : 802 [ 803 { 804 type : 'hbox', 805 children : 806 [ 807 { 808 type : 'checkbox', 809 id : 'resizable', 810 label : editor.lang.link.popupResizable, 811 setup : setupPopupParams, 812 commit : commitPopupParams 813 }, 814 { 815 type : 'checkbox', 816 id : 'status', 817 label : editor.lang.link.popupStatusBar, 818 setup : setupPopupParams, 819 commit : commitPopupParams 820 821 } 822 ] 823 }, 824 { 825 type : 'hbox', 826 children : 827 [ 828 { 829 type : 'checkbox', 830 id : 'location', 831 label : editor.lang.link.popupLocationBar, 832 setup : setupPopupParams, 833 commit : commitPopupParams 834 835 }, 836 { 837 type : 'checkbox', 838 id : 'toolbar', 839 label : editor.lang.link.popupToolbar, 840 setup : setupPopupParams, 841 commit : commitPopupParams 842 843 } 844 ] 845 }, 846 { 847 type : 'hbox', 848 children : 849 [ 850 { 851 type : 'checkbox', 852 id : 'menubar', 853 label : editor.lang.link.popupMenuBar, 854 setup : setupPopupParams, 855 commit : commitPopupParams 856 857 }, 858 { 859 type : 'checkbox', 860 id : 'fullscreen', 861 label : editor.lang.link.popupFullScreen, 862 setup : setupPopupParams, 863 commit : commitPopupParams 864 865 } 866 ] 867 }, 868 { 869 type : 'hbox', 870 children : 871 [ 872 { 873 type : 'checkbox', 874 id : 'scrollbars', 875 label : editor.lang.link.popupScrollBars, 876 setup : setupPopupParams, 877 commit : commitPopupParams 878 879 }, 880 { 881 type : 'checkbox', 882 id : 'dependent', 883 label : editor.lang.link.popupDependent, 884 setup : setupPopupParams, 885 commit : commitPopupParams 886 887 } 888 ] 889 }, 890 { 891 type : 'hbox', 892 children : 893 [ 894 { 895 type : 'text', 896 widths : [ '30%', '70%' ], 897 labelLayout : 'horizontal', 898 label : editor.lang.link.popupWidth, 899 id : 'width', 900 setup : setupPopupParams, 901 commit : commitPopupParams 902 903 }, 904 { 905 type : 'text', 906 labelLayout : 'horizontal', 907 widths : [ '55%', '45%' ], 908 label : editor.lang.link.popupLeft, 909 id : 'left', 910 setup : setupPopupParams, 911 commit : commitPopupParams 912 913 } 914 ] 915 }, 916 { 917 type : 'hbox', 918 children : 919 [ 920 { 921 type : 'text', 922 labelLayout : 'horizontal', 923 widths : [ '30%', '70%' ], 924 label : editor.lang.link.popupHeight, 925 id : 'height', 926 setup : setupPopupParams, 927 commit : commitPopupParams 928 929 }, 930 { 931 type : 'text', 932 labelLayout : 'horizontal', 933 label : editor.lang.link.popupTop, 934 widths : [ '55%', '45%' ], 935 id : 'top', 936 setup : setupPopupParams, 937 commit : commitPopupParams 938 939 } 940 ] 941 } 942 ] 943 } 944 ] 945 } 946 ] 947 }, 948 { 949 id : 'upload', 950 label : editor.lang.link.upload, 951 title : editor.lang.link.upload, 952 hidden : true, 953 filebrowser : 'uploadButton', 954 elements : 955 [ 956 { 957 type : 'file', 958 id : 'upload', 959 label : editor.lang.common.upload, 960 style: 'height:40px', 961 size : 29 962 }, 963 { 964 type : 'fileButton', 965 id : 'uploadButton', 966 label : editor.lang.common.uploadSubmit, 967 filebrowser : 'info:url', 968 'for' : [ 'upload', 'upload' ] 969 } 970 ] 971 }, 972 { 973 id : 'advanced', 974 label : editor.lang.link.advanced, 975 title : editor.lang.link.advanced, 976 elements : 977 [ 978 { 979 type : 'vbox', 980 padding : 1, 981 children : 982 [ 983 { 984 type : 'hbox', 985 widths : [ '45%', '35%', '20%' ], 986 children : 987 [ 988 { 989 type : 'text', 990 id : 'advId', 991 label : editor.lang.link.id, 992 setup : setupAdvParams, 993 commit : commitAdvParams 994 }, 995 { 996 type : 'select', 997 id : 'advLangDir', 998 label : editor.lang.link.langDir, 999 'default' : '', 1000 style : 'width:110px', 1001 items : 1002 [ 1003 [ editor.lang.common.notSet, '' ], 1004 [ editor.lang.link.langDirLTR, 'ltr' ], 1005 [ editor.lang.link.langDirRTL, 'rtl' ] 1006 ], 1007 setup : setupAdvParams, 1008 commit : commitAdvParams 1009 }, 1010 { 1011 type : 'text', 1012 id : 'advAccessKey', 1013 width : '80px', 1014 label : editor.lang.link.acccessKey, 1015 maxLength : 1, 1016 setup : setupAdvParams, 1017 commit : commitAdvParams 1018 1019 } 1020 ] 1021 }, 1022 { 1023 type : 'hbox', 1024 widths : [ '45%', '35%', '20%' ], 1025 children : 1026 [ 1027 { 1028 type : 'text', 1029 label : editor.lang.link.name, 1030 id : 'advName', 1031 setup : setupAdvParams, 1032 commit : commitAdvParams 1033 1034 }, 1035 { 1036 type : 'text', 1037 label : editor.lang.link.langCode, 1038 id : 'advLangCode', 1039 width : '110px', 1040 'default' : '', 1041 setup : setupAdvParams, 1042 commit : commitAdvParams 1043 1044 }, 1045 { 1046 type : 'text', 1047 label : editor.lang.link.tabIndex, 1048 id : 'advTabIndex', 1049 width : '80px', 1050 maxLength : 5, 1051 setup : setupAdvParams, 1052 commit : commitAdvParams 1053 1054 } 1055 ] 1056 } 1057 ] 1058 }, 1059 { 1060 type : 'vbox', 1061 padding : 1, 1062 children : 1063 [ 1064 { 1065 type : 'hbox', 1066 widths : [ '45%', '55%' ], 1067 children : 1068 [ 1069 { 1070 type : 'text', 1071 label : editor.lang.link.advisoryTitle, 1072 'default' : '', 1073 id : 'advTitle', 1074 setup : setupAdvParams, 1075 commit : commitAdvParams 1076 1077 }, 1078 { 1079 type : 'text', 1080 label : editor.lang.link.advisoryContentType, 1081 'default' : '', 1082 id : 'advContentType', 1083 setup : setupAdvParams, 1084 commit : commitAdvParams 1085 1086 } 1087 ] 1088 }, 1089 { 1090 type : 'hbox', 1091 widths : [ '45%', '55%' ], 1092 children : 1093 [ 1094 { 1095 type : 'text', 1096 label : editor.lang.link.cssClasses, 1097 'default' : '', 1098 id : 'advCSSClasses', 1099 setup : setupAdvParams, 1100 commit : commitAdvParams 1101 1102 }, 1103 { 1104 type : 'text', 1105 label : editor.lang.link.charset, 1106 'default' : '', 1107 id : 'advCharset', 1108 setup : setupAdvParams, 1109 commit : commitAdvParams 1110 1111 } 1112 ] 1113 }, 1114 { 1115 type : 'hbox', 1116 children : 1117 [ 1118 { 1119 type : 'text', 1120 label : editor.lang.link.styles, 1121 'default' : '', 1122 id : 'advStyles', 1123 setup : setupAdvParams, 1124 commit : commitAdvParams 1125 1126 } 1127 ] 1128 } 1129 ] 1130 } 1131 ] 1132 } 1133 ], 1134 onShow : function() 1135 { 1136 this.fakeObj = false; 1137 1138 var editor = this.getParentEditor(), 1139 selection = editor.getSelection(), 1140 element = null; 1141 1142 // Fill in all the relevant fields if there's already one link selected. 1143 if ( ( element = plugin.getSelectedLink( editor ) ) && element.hasAttribute( 'href' ) ) 1144 selection.selectElement( element ); 1145 else if ( ( element = selection.getSelectedElement() ) && element.is( 'img' ) 1146 && element.getAttribute( '_cke_real_element_type' ) 1147 && element.getAttribute( '_cke_real_element_type' ) == 'anchor' ) 1148 { 1149 this.fakeObj = element; 1150 element = editor.restoreRealElement( this.fakeObj ); 1151 selection.selectElement( this.fakeObj ); 1152 } 1153 else 1154 element = null; 1155 1156 this.setupContent( parseLink.apply( this, [ editor, element ] ) ); 1157 }, 1158 onOk : function() 1159 { 1160 var attributes = { href : 'javascript:void(0)/*' + CKEDITOR.tools.getNextNumber() + '*/' }, 1161 removeAttributes = [], 1162 data = { href : attributes.href }, 1163 me = this, 1164 editor = this.getParentEditor(); 1165 1166 this.commitContent( data ); 1167 1168 // Compose the URL. 1169 switch ( data.type || 'url' ) 1170 { 1171 case 'url': 1172 var protocol = ( data.url && data.url.protocol != undefined ) ? data.url.protocol : 'http://', 1173 url = ( data.url && data.url.url ) || ''; 1174 attributes._cke_saved_href = ( url.indexOf( '/' ) === 0 ) ? url : protocol + url; 1175 break; 1176 case 'anchor': 1177 var name = ( data.anchor && data.anchor.name ), 1178 id = ( data.anchor && data.anchor.id ); 1179 attributes._cke_saved_href = '#' + ( name || id || '' ); 1180 break; 1181 case 'email': 1182 1183 var linkHref, 1184 email = data.email, 1185 address = email.address; 1186 1187 switch( emailProtection ) 1188 { 1189 case '' : 1190 case 'encode' : 1191 { 1192 var subject = encodeURIComponent( email.subject || '' ), 1193 body = encodeURIComponent( email.body || '' ); 1194 1195 // Build the e-mail parameters first. 1196 var argList = []; 1197 subject && argList.push( 'subject=' + subject ); 1198 body && argList.push( 'body=' + body ); 1199 argList = argList.length ? '?' + argList.join( '&' ) : ''; 1200 1201 if ( emailProtection == 'encode' ) 1202 { 1203 linkHref = [ 'javascript:void(location.href=\'mailto:\'+', 1204 protectEmailAddressAsEncodedString( address ) ]; 1205 // parameters are optional. 1206 argList && linkHref.push( '+\'', escapeSingleQuote( argList ), '\'' ); 1207 1208 linkHref.push( ')' ); 1209 } 1210 else 1211 linkHref = [ 'mailto:', address, argList ]; 1212 1213 break; 1214 } 1215 default : 1216 { 1217 // Separating name and domain. 1218 var nameAndDomain = address.split( '@', 2 ); 1219 email.name = nameAndDomain[ 0 ]; 1220 email.domain = nameAndDomain[ 1 ]; 1221 1222 linkHref = [ 'javascript:', protectEmailLinkAsFunction( email ) ]; 1223 } 1224 } 1225 1226 attributes._cke_saved_href = linkHref.join( '' ); 1227 break; 1228 } 1229 1230 // Popups and target. 1231 if ( data.target ) 1232 { 1233 if ( data.target.type == 'popup' ) 1234 { 1235 var onclickList = [ 'window.open(this.href, \'', 1236 data.target.name || '', '\', \'' ]; 1237 var featureList = [ 'resizable', 'status', 'location', 'toolbar', 'menubar', 'fullscreen', 1238 'scrollbars', 'dependent' ]; 1239 var featureLength = featureList.length; 1240 var addFeature = function( featureName ) 1241 { 1242 if ( data.target[ featureName ] ) 1243 featureList.push( featureName + '=' + data.target[ featureName ] ); 1244 }; 1245 1246 for ( var i = 0 ; i < featureLength ; i++ ) 1247 featureList[i] = featureList[i] + ( data.target[ featureList[i] ] ? '=yes' : '=no' ) ; 1248 addFeature( 'width' ); 1249 addFeature( 'left' ); 1250 addFeature( 'height' ); 1251 addFeature( 'top' ); 1252 1253 onclickList.push( featureList.join( ',' ), '\'); return false;' ); 1254 attributes[ '_cke_pa_onclick' ] = onclickList.join( '' ); 1255 } 1256 else 1257 { 1258 if ( data.target.type != 'notSet' && data.target.name ) 1259 attributes.target = data.target.name; 1260 else 1261 removeAttributes.push( 'target' ); 1262 1263 removeAttributes.push( '_cke_pa_onclick', 'onclick' ); 1264 } 1265 } 1266 1267 // Advanced attributes. 1268 if ( data.adv ) 1269 { 1270 var advAttr = function( inputName, attrName ) 1271 { 1272 var value = data.adv[ inputName ]; 1273 if ( value ) 1274 attributes[attrName] = value; 1275 else 1276 removeAttributes.push( attrName ); 1277 }; 1278 1279 if ( this._.selectedElement ) 1280 advAttr( 'advId', 'id' ); 1281 advAttr( 'advLangDir', 'dir' ); 1282 advAttr( 'advAccessKey', 'accessKey' ); 1283 advAttr( 'advName', 'name' ); 1284 advAttr( 'advLangCode', 'lang' ); 1285 advAttr( 'advTabIndex', 'tabindex' ); 1286 advAttr( 'advTitle', 'title' ); 1287 advAttr( 'advContentType', 'type' ); 1288 advAttr( 'advCSSClasses', 'class' ); 1289 advAttr( 'advCharset', 'charset' ); 1290 advAttr( 'advStyles', 'style' ); 1291 } 1292 1293 if ( !this._.selectedElement ) 1294 { 1295 // Create element if current selection is collapsed. 1296 var selection = editor.getSelection(), 1297 ranges = selection.getRanges( true ); 1298 if ( ranges.length == 1 && ranges[0].collapsed ) 1299 { 1300 // Short mailto link text view (#5736). 1301 var text = new CKEDITOR.dom.text( data.type == 'email' ? 1302 data.email.address : attributes._cke_saved_href, editor.document ); 1303 ranges[0].insertNode( text ); 1304 ranges[0].selectNodeContents( text ); 1305 selection.selectRanges( ranges ); 1306 } 1307 1308 // Apply style. 1309 var style = new CKEDITOR.style( { element : 'a', attributes : attributes } ); 1310 style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why. 1311 style.apply( editor.document ); 1312 1313 // Id. Apply only to the first link. 1314 if ( data.adv && data.adv.advId ) 1315 { 1316 var links = this.getParentEditor().document.$.getElementsByTagName( 'a' ); 1317 for ( i = 0 ; i < links.length ; i++ ) 1318 { 1319 if ( links[i].href == attributes.href ) 1320 { 1321 links[i].id = data.adv.advId; 1322 break; 1323 } 1324 } 1325 } 1326 } 1327 else 1328 { 1329 // We're only editing an existing link, so just overwrite the attributes. 1330 var element = this._.selectedElement, 1331 href = element.getAttribute( '_cke_saved_href' ), 1332 textView = element.getHtml(); 1333 1334 // IE BUG: Setting the name attribute to an existing link doesn't work. 1335 // Must re-create the link from weired syntax to workaround. 1336 if ( CKEDITOR.env.ie && attributes.name != element.getAttribute( 'name' ) ) 1337 { 1338 var newElement = new CKEDITOR.dom.element( '<a name="' + CKEDITOR.tools.htmlEncode( attributes.name ) + '">', 1339 editor.document ); 1340 1341 selection = editor.getSelection(); 1342 1343 element.moveChildren( newElement ); 1344 element.copyAttributes( newElement, { name : 1 } ); 1345 newElement.replace( element ); 1346 element = newElement; 1347 1348 selection.selectElement( element ); 1349 } 1350 1351 element.setAttributes( attributes ); 1352 element.removeAttributes( removeAttributes ); 1353 // Update text view when user changes protocol (#4612). 1354 if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) 1355 { 1356 // Short mailto link text view (#5736). 1357 element.setHtml( data.type == 'email' ? 1358 data.email.address : attributes._cke_saved_href ); 1359 } 1360 // Make the element display as an anchor if a name has been set. 1361 if ( element.getAttribute( 'name' ) ) 1362 element.addClass( 'cke_anchor' ); 1363 else 1364 element.removeClass( 'cke_anchor' ); 1365 1366 if ( this.fakeObj ) 1367 editor.createFakeElement( element, 'cke_anchor', 'anchor' ).replace( this.fakeObj ); 1368 1369 delete this._.selectedElement; 1370 } 1371 }, 1372 onLoad : function() 1373 { 1374 if ( !editor.config.linkShowAdvancedTab ) 1375 this.hidePage( 'advanced' ); //Hide Advanded tab. 1376 1377 if ( !editor.config.linkShowTargetTab ) 1378 this.hidePage( 'target' ); //Hide Target tab. 1379 1380 }, 1381 // Inital focus on 'url' field if link is of type URL. 1382 onFocus : function() 1383 { 1384 var linkType = this.getContentElement( 'info', 'linkType' ), 1385 urlField; 1386 if ( linkType && linkType.getValue( ) == 'url' ) 1387 { 1388 urlField = this.getContentElement( 'info', 'url' ); 1389 urlField.select(); 1390 } 1391 } 1392 }; 1393 }); 1394 1395 /** 1396 * The e-mail address anti-spam protection option. The protection will be 1397 * applied when creating or modifying e-mail links through the editor interface.<br> 1398 * Two methods of protection can be choosed: 1399 * <ol> <li>The e-mail parts (name, domain and any other query string) are 1400 * assembled into a function call pattern. Such function must be 1401 * provided by the developer in the pages that will use the contents. 1402 * <li>Only the e-mail address is obfuscated into a special string that 1403 * has no meaning for humans or spam bots, but which is properly 1404 * rendered and accepted by the browser.</li></ol> 1405 * Both approaches require JavaScript to be enabled. 1406 * @name CKEDITOR.config.emailProtection 1407 * @since 3.1 1408 * @type String 1409 * @default '' (empty string = disabled) 1410 * @example 1411 * // href="mailto:tester@ckeditor.com?subject=subject&body=body" 1412 * config.emailProtection = ''; 1413 * @example 1414 * // href="<a href=\"javascript:void(location.href=\'mailto:\'+String.fromCharCode(116,101,115,116,101,114,64,99,107,101,100,105,116,111,114,46,99,111,109)+\'?subject=subject&body=body\')\">e-mail</a>" 1415 * config.emailProtection = 'encode'; 1416 * @example 1417 * // href="javascript:mt('tester','ckeditor.com','subject','body')" 1418 * config.emailProtection = 'mt(NAME,DOMAIN,SUBJECT,BODY)'; 1419 */
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |