]> git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blob - sources/plugins/link/dialogs/link.js
Update to 4.7.3
[perso/Immae/Projets/packagist/ludivine-ckeditor-component.git] / sources / plugins / link / dialogs / link.js
1 /**
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
4 */
5
6 'use strict';
7
8 ( function() {
9 CKEDITOR.dialog.add( 'link', function( editor ) {
10 var plugin = CKEDITOR.plugins.link,
11 initialLinkText;
12
13 function createRangeForLink( editor, link ) {
14 var range = editor.createRange();
15
16 range.setStartBefore( link );
17 range.setEndAfter( link );
18
19 return range;
20 }
21
22 function insertLinksIntoSelection( editor, data ) {
23 var attributes = plugin.getLinkAttributes( editor, data ),
24 ranges = editor.getSelection().getRanges(),
25 style = new CKEDITOR.style( {
26 element: 'a',
27 attributes: attributes.set
28 } ),
29 rangesToSelect = [],
30 range,
31 text,
32 nestedLinks,
33 i,
34 j;
35
36 style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why.
37
38 for ( i = 0; i < ranges.length; i++ ) {
39 range = ranges[ i ];
40
41 // Use link URL as text with a collapsed cursor.
42 if ( range.collapsed ) {
43 // Short mailto link text view (http://dev.ckeditor.com/ticket/5736).
44 text = new CKEDITOR.dom.text( data.linkText || ( data.type == 'email' ?
45 data.email.address : attributes.set[ 'data-cke-saved-href' ] ), editor.document );
46 range.insertNode( text );
47 range.selectNodeContents( text );
48 } else if ( initialLinkText !== data.linkText ) {
49 text = new CKEDITOR.dom.text( data.linkText, editor.document );
50
51 // Shrink range to preserve block element.
52 range.shrink( CKEDITOR.SHRINK_TEXT );
53
54 // Use extractHtmlFromRange to remove markup within the selection. Also this method is a little
55 // smarter than range#deleteContents as it plays better e.g. with table cells.
56 editor.editable().extractHtmlFromRange( range );
57
58 range.insertNode( text );
59 }
60
61 // Editable links nested within current range should be removed, so that the link is applied to whole selection.
62 nestedLinks = range._find( 'a' );
63
64 for ( j = 0; j < nestedLinks.length; j++ ) {
65 nestedLinks[ j ].remove( true );
66 }
67
68
69 // Apply style.
70 style.applyToRange( range, editor );
71
72 rangesToSelect.push( range );
73 }
74
75 editor.getSelection().selectRanges( rangesToSelect );
76 }
77
78 function editLinksInSelection( editor, selectedElements, data ) {
79 var attributes = plugin.getLinkAttributes( editor, data ),
80 ranges = [],
81 element,
82 href,
83 textView,
84 newText,
85 i;
86
87 for ( i = 0; i < selectedElements.length; i++ ) {
88 // We're only editing an existing link, so just overwrite the attributes.
89 element = selectedElements[ i ];
90 href = element.data( 'cke-saved-href' );
91 textView = element.getHtml();
92
93 element.setAttributes( attributes.set );
94 element.removeAttributes( attributes.removed );
95
96
97 if ( data.linkText && initialLinkText != data.linkText ) {
98 // Display text has been changed.
99 newText = data.linkText;
100 } else if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) {
101 // Update text view when user changes protocol (http://dev.ckeditor.com/ticket/4612).
102 // Short mailto link text view (http://dev.ckeditor.com/ticket/5736).
103 newText = data.type == 'email' ? data.email.address : attributes.set[ 'data-cke-saved-href' ];
104 }
105
106 if ( newText ) {
107 element.setText( newText );
108 }
109
110 ranges.push( createRangeForLink( editor, element ) );
111 }
112
113 // We changed the content, so need to select it again.
114 editor.getSelection().selectRanges( ranges );
115 }
116
117 // Handles the event when the "Target" selection box is changed.
118 var targetChanged = function() {
119 var dialog = this.getDialog(),
120 popupFeatures = dialog.getContentElement( 'target', 'popupFeatures' ),
121 targetName = dialog.getContentElement( 'target', 'linkTargetName' ),
122 value = this.getValue();
123
124 if ( !popupFeatures || !targetName )
125 return;
126
127 popupFeatures = popupFeatures.getElement();
128 popupFeatures.hide();
129 targetName.setValue( '' );
130
131 switch ( value ) {
132 case 'frame':
133 targetName.setLabel( editor.lang.link.targetFrameName );
134 targetName.getElement().show();
135 break;
136 case 'popup':
137 popupFeatures.show();
138 targetName.setLabel( editor.lang.link.targetPopupName );
139 targetName.getElement().show();
140 break;
141 default:
142 targetName.setValue( value );
143 targetName.getElement().hide();
144 break;
145 }
146
147 };
148
149 // Handles the event when the "Type" selection box is changed.
150 var linkTypeChanged = function() {
151 var dialog = this.getDialog(),
152 partIds = [ 'urlOptions', 'anchorOptions', 'emailOptions' ],
153 typeValue = this.getValue(),
154 uploadTab = dialog.definition.getContents( 'upload' ),
155 uploadInitiallyHidden = uploadTab && uploadTab.hidden;
156
157 if ( typeValue == 'url' ) {
158 if ( editor.config.linkShowTargetTab )
159 dialog.showPage( 'target' );
160 if ( !uploadInitiallyHidden )
161 dialog.showPage( 'upload' );
162 } else {
163 dialog.hidePage( 'target' );
164 if ( !uploadInitiallyHidden )
165 dialog.hidePage( 'upload' );
166 }
167
168 for ( var i = 0; i < partIds.length; i++ ) {
169 var element = dialog.getContentElement( 'info', partIds[ i ] );
170 if ( !element )
171 continue;
172
173 element = element.getElement().getParent().getParent();
174 if ( partIds[ i ] == typeValue + 'Options' )
175 element.show();
176 else
177 element.hide();
178 }
179
180 dialog.layout();
181 };
182
183 var setupParams = function( page, data ) {
184 if ( data[ page ] )
185 this.setValue( data[ page ][ this.id ] || '' );
186 };
187
188 var setupPopupParams = function( data ) {
189 return setupParams.call( this, 'target', data );
190 };
191
192 var setupAdvParams = function( data ) {
193 return setupParams.call( this, 'advanced', data );
194 };
195
196 var commitParams = function( page, data ) {
197 if ( !data[ page ] )
198 data[ page ] = {};
199
200 data[ page ][ this.id ] = this.getValue() || '';
201 };
202
203 var commitPopupParams = function( data ) {
204 return commitParams.call( this, 'target', data );
205 };
206
207 var commitAdvParams = function( data ) {
208 return commitParams.call( this, 'advanced', data );
209 };
210
211 var commonLang = editor.lang.common,
212 linkLang = editor.lang.link,
213 anchors;
214
215 return {
216 title: linkLang.title,
217 minWidth: ( CKEDITOR.skinName || editor.config.skin ) == 'moono-lisa' ? 450 : 350,
218 minHeight: 240,
219 contents: [ {
220 id: 'info',
221 label: linkLang.info,
222 title: linkLang.info,
223 elements: [ {
224 type: 'text',
225 id: 'linkDisplayText',
226 label: linkLang.displayText,
227 setup: function() {
228 this.enable();
229
230 this.setValue( editor.getSelection().getSelectedText() );
231
232 // Keep inner text so that it can be compared in commit function. By obtaining value from getData()
233 // we get value stripped from new line chars which is important when comparing the value later on.
234 initialLinkText = this.getValue();
235 },
236 commit: function( data ) {
237 data.linkText = this.isEnabled() ? this.getValue() : '';
238 }
239 },
240 {
241 id: 'linkType',
242 type: 'select',
243 label: linkLang.type,
244 'default': 'url',
245 items: [
246 [ linkLang.toUrl, 'url' ],
247 [ linkLang.toAnchor, 'anchor' ],
248 [ linkLang.toEmail, 'email' ]
249 ],
250 onChange: linkTypeChanged,
251 setup: function( data ) {
252 this.setValue( data.type || 'url' );
253 },
254 commit: function( data ) {
255 data.type = this.getValue();
256 }
257 },
258 {
259 type: 'vbox',
260 id: 'urlOptions',
261 children: [ {
262 type: 'hbox',
263 widths: [ '25%', '75%' ],
264 children: [ {
265 id: 'protocol',
266 type: 'select',
267 label: commonLang.protocol,
268 'default': 'http://',
269 items: [
270 // Force 'ltr' for protocol names in BIDI. (http://dev.ckeditor.com/ticket/5433)
271 [ 'http://\u200E', 'http://' ],
272 [ 'https://\u200E', 'https://' ],
273 [ 'ftp://\u200E', 'ftp://' ],
274 [ 'news://\u200E', 'news://' ],
275 [ linkLang.other, '' ]
276 ],
277 setup: function( data ) {
278 if ( data.url )
279 this.setValue( data.url.protocol || '' );
280 },
281 commit: function( data ) {
282 if ( !data.url )
283 data.url = {};
284
285 data.url.protocol = this.getValue();
286 }
287 },
288 {
289 type: 'text',
290 id: 'url',
291 label: commonLang.url,
292 required: true,
293 onLoad: function() {
294 this.allowOnChange = true;
295 },
296 onKeyUp: function() {
297 this.allowOnChange = false;
298 var protocolCmb = this.getDialog().getContentElement( 'info', 'protocol' ),
299 url = this.getValue(),
300 urlOnChangeProtocol = /^(http|https|ftp|news):\/\/(?=.)/i,
301 urlOnChangeTestOther = /^((javascript:)|[#\/\.\?])/i;
302
303 var protocol = urlOnChangeProtocol.exec( url );
304 if ( protocol ) {
305 this.setValue( url.substr( protocol[ 0 ].length ) );
306 protocolCmb.setValue( protocol[ 0 ].toLowerCase() );
307 } else if ( urlOnChangeTestOther.test( url ) ) {
308 protocolCmb.setValue( '' );
309 }
310
311 this.allowOnChange = true;
312 },
313 onChange: function() {
314 if ( this.allowOnChange ) // Dont't call on dialog load.
315 this.onKeyUp();
316 },
317 validate: function() {
318 var dialog = this.getDialog();
319
320 if ( dialog.getContentElement( 'info', 'linkType' ) && dialog.getValueOf( 'info', 'linkType' ) != 'url' )
321 return true;
322
323 if ( !editor.config.linkJavaScriptLinksAllowed && ( /javascript\:/ ).test( this.getValue() ) ) {
324 alert( commonLang.invalidValue ); // jshint ignore:line
325 return false;
326 }
327
328 if ( this.getDialog().fakeObj ) // Edit Anchor.
329 return true;
330
331 var func = CKEDITOR.dialog.validate.notEmpty( linkLang.noUrl );
332 return func.apply( this );
333 },
334 setup: function( data ) {
335 this.allowOnChange = false;
336 if ( data.url )
337 this.setValue( data.url.url );
338 this.allowOnChange = true;
339
340 },
341 commit: function( data ) {
342 // IE will not trigger the onChange event if the mouse has been used
343 // to carry all the operations http://dev.ckeditor.com/ticket/4724
344 this.onChange();
345
346 if ( !data.url )
347 data.url = {};
348
349 data.url.url = this.getValue();
350 this.allowOnChange = false;
351 }
352 } ],
353 setup: function() {
354 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) )
355 this.getElement().show();
356 }
357 },
358 {
359 type: 'button',
360 id: 'browse',
361 hidden: 'true',
362 filebrowser: 'info:url',
363 label: commonLang.browseServer
364 } ]
365 },
366 {
367 type: 'vbox',
368 id: 'anchorOptions',
369 width: 260,
370 align: 'center',
371 padding: 0,
372 children: [ {
373 type: 'fieldset',
374 id: 'selectAnchorText',
375 label: linkLang.selectAnchor,
376 setup: function() {
377 anchors = plugin.getEditorAnchors( editor );
378
379 this.getElement()[ anchors && anchors.length ? 'show' : 'hide' ]();
380 },
381 children: [ {
382 type: 'hbox',
383 id: 'selectAnchor',
384 children: [ {
385 type: 'select',
386 id: 'anchorName',
387 'default': '',
388 label: linkLang.anchorName,
389 style: 'width: 100%;',
390 items: [
391 [ '' ]
392 ],
393 setup: function( data ) {
394 this.clear();
395 this.add( '' );
396
397 if ( anchors ) {
398 for ( var i = 0; i < anchors.length; i++ ) {
399 if ( anchors[ i ].name )
400 this.add( anchors[ i ].name );
401 }
402 }
403
404 if ( data.anchor )
405 this.setValue( data.anchor.name );
406
407 var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
408 if ( linkType && linkType.getValue() == 'email' )
409 this.focus();
410 },
411 commit: function( data ) {
412 if ( !data.anchor )
413 data.anchor = {};
414
415 data.anchor.name = this.getValue();
416 }
417 },
418 {
419 type: 'select',
420 id: 'anchorId',
421 'default': '',
422 label: linkLang.anchorId,
423 style: 'width: 100%;',
424 items: [
425 [ '' ]
426 ],
427 setup: function( data ) {
428 this.clear();
429 this.add( '' );
430
431 if ( anchors ) {
432 for ( var i = 0; i < anchors.length; i++ ) {
433 if ( anchors[ i ].id )
434 this.add( anchors[ i ].id );
435 }
436 }
437
438 if ( data.anchor )
439 this.setValue( data.anchor.id );
440 },
441 commit: function( data ) {
442 if ( !data.anchor )
443 data.anchor = {};
444
445 data.anchor.id = this.getValue();
446 }
447 } ],
448 setup: function() {
449 this.getElement()[ anchors && anchors.length ? 'show' : 'hide' ]();
450 }
451 } ]
452 },
453 {
454 type: 'html',
455 id: 'noAnchors',
456 style: 'text-align: center;',
457 html: '<div role="note" tabIndex="-1">' + CKEDITOR.tools.htmlEncode( linkLang.noAnchors ) + '</div>',
458 // Focus the first element defined in above html.
459 focus: true,
460 setup: function() {
461 this.getElement()[ anchors && anchors.length ? 'hide' : 'show' ]();
462 }
463 } ],
464 setup: function() {
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 type: 'text',
475 id: 'emailAddress',
476 label: linkLang.emailAddress,
477 required: true,
478 validate: function() {
479 var dialog = this.getDialog();
480
481 if ( !dialog.getContentElement( 'info', 'linkType' ) || dialog.getValueOf( 'info', 'linkType' ) != 'email' )
482 return true;
483
484 var func = CKEDITOR.dialog.validate.notEmpty( linkLang.noEmail );
485 return func.apply( this );
486 },
487 setup: function( data ) {
488 if ( data.email )
489 this.setValue( data.email.address );
490
491 var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
492 if ( linkType && linkType.getValue() == 'email' )
493 this.select();
494 },
495 commit: function( data ) {
496 if ( !data.email )
497 data.email = {};
498
499 data.email.address = this.getValue();
500 }
501 },
502 {
503 type: 'text',
504 id: 'emailSubject',
505 label: linkLang.emailSubject,
506 setup: function( data ) {
507 if ( data.email )
508 this.setValue( data.email.subject );
509 },
510 commit: function( data ) {
511 if ( !data.email )
512 data.email = {};
513
514 data.email.subject = this.getValue();
515 }
516 },
517 {
518 type: 'textarea',
519 id: 'emailBody',
520 label: linkLang.emailBody,
521 rows: 3,
522 'default': '',
523 setup: function( data ) {
524 if ( data.email )
525 this.setValue( data.email.body );
526 },
527 commit: function( data ) {
528 if ( !data.email )
529 data.email = {};
530
531 data.email.body = this.getValue();
532 }
533 } ],
534 setup: function() {
535 if ( !this.getDialog().getContentElement( 'info', 'linkType' ) )
536 this.getElement().hide();
537 }
538 } ]
539 },
540 {
541 id: 'target',
542 requiredContent: 'a[target]', // This is not fully correct, because some target option requires JS.
543 label: linkLang.target,
544 title: linkLang.target,
545 elements: [ {
546 type: 'hbox',
547 widths: [ '50%', '50%' ],
548 children: [ {
549 type: 'select',
550 id: 'linkTargetType',
551 label: commonLang.target,
552 'default': 'notSet',
553 style: 'width : 100%;',
554 'items': [
555 [ commonLang.notSet, 'notSet' ],
556 [ linkLang.targetFrame, 'frame' ],
557 [ linkLang.targetPopup, 'popup' ],
558 [ commonLang.targetNew, '_blank' ],
559 [ commonLang.targetTop, '_top' ],
560 [ commonLang.targetSelf, '_self' ],
561 [ commonLang.targetParent, '_parent' ]
562 ],
563 onChange: targetChanged,
564 setup: function( data ) {
565 if ( data.target )
566 this.setValue( data.target.type || 'notSet' );
567 targetChanged.call( this );
568 },
569 commit: function( data ) {
570 if ( !data.target )
571 data.target = {};
572
573 data.target.type = this.getValue();
574 }
575 },
576 {
577 type: 'text',
578 id: 'linkTargetName',
579 label: linkLang.targetFrameName,
580 'default': '',
581 setup: function( data ) {
582 if ( data.target )
583 this.setValue( data.target.name );
584 },
585 commit: function( data ) {
586 if ( !data.target )
587 data.target = {};
588
589 data.target.name = this.getValue().replace( /([^\x00-\x7F]|\s)/gi, '' );
590 }
591 } ]
592 },
593 {
594 type: 'vbox',
595 width: '100%',
596 align: 'center',
597 padding: 2,
598 id: 'popupFeatures',
599 children: [ {
600 type: 'fieldset',
601 label: linkLang.popupFeatures,
602 children: [ {
603 type: 'hbox',
604 children: [ {
605 type: 'checkbox',
606 id: 'resizable',
607 label: linkLang.popupResizable,
608 setup: setupPopupParams,
609 commit: commitPopupParams
610 },
611 {
612 type: 'checkbox',
613 id: 'status',
614 label: linkLang.popupStatusBar,
615 setup: setupPopupParams,
616 commit: commitPopupParams
617
618 } ]
619 },
620 {
621 type: 'hbox',
622 children: [ {
623 type: 'checkbox',
624 id: 'location',
625 label: linkLang.popupLocationBar,
626 setup: setupPopupParams,
627 commit: commitPopupParams
628
629 },
630 {
631 type: 'checkbox',
632 id: 'toolbar',
633 label: linkLang.popupToolbar,
634 setup: setupPopupParams,
635 commit: commitPopupParams
636
637 } ]
638 },
639 {
640 type: 'hbox',
641 children: [ {
642 type: 'checkbox',
643 id: 'menubar',
644 label: linkLang.popupMenuBar,
645 setup: setupPopupParams,
646 commit: commitPopupParams
647
648 },
649 {
650 type: 'checkbox',
651 id: 'fullscreen',
652 label: linkLang.popupFullScreen,
653 setup: setupPopupParams,
654 commit: commitPopupParams
655
656 } ]
657 },
658 {
659 type: 'hbox',
660 children: [ {
661 type: 'checkbox',
662 id: 'scrollbars',
663 label: linkLang.popupScrollBars,
664 setup: setupPopupParams,
665 commit: commitPopupParams
666
667 },
668 {
669 type: 'checkbox',
670 id: 'dependent',
671 label: linkLang.popupDependent,
672 setup: setupPopupParams,
673 commit: commitPopupParams
674
675 } ]
676 },
677 {
678 type: 'hbox',
679 children: [ {
680 type: 'text',
681 widths: [ '50%', '50%' ],
682 labelLayout: 'horizontal',
683 label: commonLang.width,
684 id: 'width',
685 setup: setupPopupParams,
686 commit: commitPopupParams
687
688 },
689 {
690 type: 'text',
691 labelLayout: 'horizontal',
692 widths: [ '50%', '50%' ],
693 label: linkLang.popupLeft,
694 id: 'left',
695 setup: setupPopupParams,
696 commit: commitPopupParams
697
698 } ]
699 },
700 {
701 type: 'hbox',
702 children: [ {
703 type: 'text',
704 labelLayout: 'horizontal',
705 widths: [ '50%', '50%' ],
706 label: commonLang.height,
707 id: 'height',
708 setup: setupPopupParams,
709 commit: commitPopupParams
710
711 },
712 {
713 type: 'text',
714 labelLayout: 'horizontal',
715 label: linkLang.popupTop,
716 widths: [ '50%', '50%' ],
717 id: 'top',
718 setup: setupPopupParams,
719 commit: commitPopupParams
720
721 } ]
722 } ]
723 } ]
724 } ]
725 },
726 {
727 id: 'upload',
728 label: linkLang.upload,
729 title: linkLang.upload,
730 hidden: true,
731 filebrowser: 'uploadButton',
732 elements: [ {
733 type: 'file',
734 id: 'upload',
735 label: commonLang.upload,
736 style: 'height:40px',
737 size: 29
738 },
739 {
740 type: 'fileButton',
741 id: 'uploadButton',
742 label: commonLang.uploadSubmit,
743 filebrowser: 'info:url',
744 'for': [ 'upload', 'upload' ]
745 } ]
746 },
747 {
748 id: 'advanced',
749 label: linkLang.advanced,
750 title: linkLang.advanced,
751 elements: [ {
752 type: 'vbox',
753 padding: 1,
754 children: [ {
755 type: 'hbox',
756 widths: [ '45%', '35%', '20%' ],
757 children: [ {
758 type: 'text',
759 id: 'advId',
760 requiredContent: 'a[id]',
761 label: linkLang.id,
762 setup: setupAdvParams,
763 commit: commitAdvParams
764 },
765 {
766 type: 'select',
767 id: 'advLangDir',
768 requiredContent: 'a[dir]',
769 label: linkLang.langDir,
770 'default': '',
771 style: 'width:110px',
772 items: [
773 [ commonLang.notSet, '' ],
774 [ linkLang.langDirLTR, 'ltr' ],
775 [ linkLang.langDirRTL, 'rtl' ]
776 ],
777 setup: setupAdvParams,
778 commit: commitAdvParams
779 },
780 {
781 type: 'text',
782 id: 'advAccessKey',
783 requiredContent: 'a[accesskey]',
784 width: '80px',
785 label: linkLang.acccessKey,
786 maxLength: 1,
787 setup: setupAdvParams,
788 commit: commitAdvParams
789
790 } ]
791 },
792 {
793 type: 'hbox',
794 widths: [ '45%', '35%', '20%' ],
795 children: [ {
796 type: 'text',
797 label: linkLang.name,
798 id: 'advName',
799 requiredContent: 'a[name]',
800 setup: setupAdvParams,
801 commit: commitAdvParams
802
803 },
804 {
805 type: 'text',
806 label: linkLang.langCode,
807 id: 'advLangCode',
808 requiredContent: 'a[lang]',
809 width: '110px',
810 'default': '',
811 setup: setupAdvParams,
812 commit: commitAdvParams
813
814 },
815 {
816 type: 'text',
817 label: linkLang.tabIndex,
818 id: 'advTabIndex',
819 requiredContent: 'a[tabindex]',
820 width: '80px',
821 maxLength: 5,
822 setup: setupAdvParams,
823 commit: commitAdvParams
824
825 } ]
826 } ]
827 },
828 {
829 type: 'vbox',
830 padding: 1,
831 children: [ {
832 type: 'hbox',
833 widths: [ '45%', '55%' ],
834 children: [ {
835 type: 'text',
836 label: linkLang.advisoryTitle,
837 requiredContent: 'a[title]',
838 'default': '',
839 id: 'advTitle',
840 setup: setupAdvParams,
841 commit: commitAdvParams
842
843 },
844 {
845 type: 'text',
846 label: linkLang.advisoryContentType,
847 requiredContent: 'a[type]',
848 'default': '',
849 id: 'advContentType',
850 setup: setupAdvParams,
851 commit: commitAdvParams
852
853 } ]
854 },
855 {
856 type: 'hbox',
857 widths: [ '45%', '55%' ],
858 children: [ {
859 type: 'text',
860 label: linkLang.cssClasses,
861 requiredContent: 'a(cke-xyz)', // Random text like 'xyz' will check if all are allowed.
862 'default': '',
863 id: 'advCSSClasses',
864 setup: setupAdvParams,
865 commit: commitAdvParams
866
867 },
868 {
869 type: 'text',
870 label: linkLang.charset,
871 requiredContent: 'a[charset]',
872 'default': '',
873 id: 'advCharset',
874 setup: setupAdvParams,
875 commit: commitAdvParams
876
877 } ]
878 },
879 {
880 type: 'hbox',
881 widths: [ '45%', '55%' ],
882 children: [ {
883 type: 'text',
884 label: linkLang.rel,
885 requiredContent: 'a[rel]',
886 'default': '',
887 id: 'advRel',
888 setup: setupAdvParams,
889 commit: commitAdvParams
890 },
891 {
892 type: 'text',
893 label: linkLang.styles,
894 requiredContent: 'a{cke-xyz}', // Random text like 'xyz' will check if all are allowed.
895 'default': '',
896 id: 'advStyles',
897 validate: CKEDITOR.dialog.validate.inlineStyle( editor.lang.common.invalidInlineStyle ),
898 setup: setupAdvParams,
899 commit: commitAdvParams
900 } ]
901 },
902 {
903 type: 'hbox',
904 widths: [ '45%', '55%' ],
905 children: [ {
906 type: 'checkbox',
907 id: 'download',
908 requiredContent: 'a[download]',
909 label: linkLang.download,
910 setup: function( data ) {
911 if ( data.download !== undefined )
912 this.setValue( 'checked', 'checked' );
913 },
914 commit: function( data ) {
915 if ( this.getValue() ) {
916 data.download = this.getValue();
917 }
918 }
919 } ]
920 } ]
921 } ]
922 } ],
923 onShow: function() {
924 var editor = this.getParentEditor(),
925 selection = editor.getSelection(),
926 displayTextField = this.getContentElement( 'info', 'linkDisplayText' ).getElement().getParent().getParent(),
927 elements = plugin.getSelectedLink( editor, true ),
928 firstLink = elements[ 0 ] || null;
929
930 // Fill in all the relevant fields if there's already one link selected.
931 if ( firstLink && firstLink.hasAttribute( 'href' ) ) {
932 // Don't change selection if some element is already selected.
933 // For example - don't destroy fake selection.
934 if ( !selection.getSelectedElement() && !selection.isInTable() ) {
935 selection.selectElement( firstLink );
936 }
937 }
938
939 var data = plugin.parseLinkAttributes( editor, firstLink );
940
941 // Here we'll decide whether or not we want to show Display Text field.
942 if ( elements.length <= 1 && plugin.showDisplayTextForElement( firstLink, editor ) ) {
943 displayTextField.show();
944 } else {
945 displayTextField.hide();
946 }
947
948 // Record down the selected element in the dialog.
949 this._.selectedElements = elements;
950
951 this.setupContent( data );
952 },
953 onOk: function() {
954 var data = {};
955
956 // Collect data from fields.
957 this.commitContent( data );
958
959 if ( !this._.selectedElements.length ) {
960 insertLinksIntoSelection( editor, data );
961 } else {
962 editLinksInSelection( editor, this._.selectedElements, data );
963
964 delete this._.selectedElements;
965 }
966 },
967 onLoad: function() {
968 if ( !editor.config.linkShowAdvancedTab )
969 this.hidePage( 'advanced' ); //Hide Advanded tab.
970
971 if ( !editor.config.linkShowTargetTab )
972 this.hidePage( 'target' ); //Hide Target tab.
973 },
974 // Inital focus on 'url' field if link is of type URL.
975 onFocus: function() {
976 var linkType = this.getContentElement( 'info', 'linkType' ),
977 urlField;
978
979 if ( linkType && linkType.getValue() == 'url' ) {
980 urlField = this.getContentElement( 'info', 'url' );
981 urlField.select();
982 }
983 }
984 };
985 } );
986 } )();
987 // jscs:disable maximumLineLength
988 /**
989 * The e-mail address anti-spam protection option. The protection will be
990 * applied when creating or modifying e-mail links through the editor interface.
991 *
992 * Two methods of protection can be chosen:
993 *
994 * 1. The e-mail parts (name, domain, and any other query string) are
995 * assembled into a function call pattern. Such function must be
996 * provided by the developer in the pages that will use the contents.
997 * 2. Only the e-mail address is obfuscated into a special string that
998 * has no meaning for humans or spam bots, but which is properly
999 * rendered and accepted by the browser.
1000 *
1001 * Both approaches require JavaScript to be enabled.
1002 *
1003 * // href="mailto:tester@ckeditor.com?subject=subject&body=body"
1004 * config.emailProtection = '';
1005 *
1006 * // 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>"
1007 * config.emailProtection = 'encode';
1008 *
1009 * // href="javascript:mt('tester','ckeditor.com','subject','body')"
1010 * config.emailProtection = 'mt(NAME,DOMAIN,SUBJECT,BODY)';
1011 *
1012 * @since 3.1
1013 * @cfg {String} [emailProtection='' (empty string = disabled)]
1014 * @member CKEDITOR.config
1015 */