      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 )
      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
     32 		// Add the CSS styles for anchor placeholders.
     33 		editor.addCss(
     34 			'img.cke_anchor' +
     35 			'{' +
     36 				'background-image: url(' + CKEDITOR.getUrl( this.path + 'images/anchor.gif' ) + ');' +
     37 				'background-position: center center;' +
     38 				'background-repeat: no-repeat;' +
     39 				'border: 1px solid #a9a9a9;' +
     40 				'width: 18px;' +
     41 				'height: 18px;' +
     42 			'}\n' +
     43 			'a.cke_anchor' +
     44 			'{' +
     45 				'background-image: url(' + CKEDITOR.getUrl( this.path + 'images/anchor.gif' ) + ');' +
     46 				'background-position: 0 center;' +
     47 				'background-repeat: no-repeat;' +
     48 				'border: 1px solid #a9a9a9;' +
     49 				'padding-left: 18px;' +
     50 			'}'
     51 		   	);
     52
     53 		// Register selection change handler for the unlink button.
     54 		 editor.on( 'selectionChange', function( evt )
     55 			{
     56 				/*
     57 				 * Despite our initial hope, document.queryCommandEnabled() does not work
     58 				 * for this in Firefox. So we must detect the state by element paths.
     59 				 */
     60 				var command = editor.getCommand( 'unlink' ),
     61 					element = evt.data.path.lastElement.getAscendant( 'a', true );
     62 				if ( element && element.getName() == 'a' && element.getAttribute( 'href' ) )
     63 					command.setState( CKEDITOR.TRISTATE_OFF );
     64 				else
     65 					command.setState( CKEDITOR.TRISTATE_DISABLED );
     66 			} );
     67
     68 		// If the "menu" plugin is loaded, register the menu items.
     69 		if ( editor.addMenuItems )
     70 		{
     71 			editor.addMenuItems(
     72 				{
     73 					anchor :
     74 					{
     75 						label : editor.lang.anchor.menu,
     76 						command : 'anchor',
     77 						group : 'anchor'
     78 					},
     79
     80 					link :
     81 					{
     82 						label : editor.lang.link.menu,
     83 						command : 'link',
     84 						group : 'link',
     85 						order : 1
     86 					},
     87
     88 					unlink :
     89 					{
     90 						label : editor.lang.unlink,
     91 						command : 'unlink',
     92 						group : 'link',
     93 						order : 5
     94 					}
     95 				});
     96 		}
     97
     98 		// If the "contextmenu" plugin is loaded, register the listeners.
     99 		if ( editor.contextMenu )
    100 		{
    101 			editor.contextMenu.addListener( function( element, selection )
    102 				{
    103 					if ( !element )
    104 						return null;
    105
    106 					var isAnchor = ( element.is( 'img' ) && element.getAttribute( '_cke_real_element_type' ) == 'anchor' );
    107
    108 					if ( !isAnchor )
    109 					{
    110 						if ( !( element = element.getAscendant( 'a', true ) ) )
    111 							return null;
    112
    113 						isAnchor = ( element.getAttribute( 'name' ) && !element.getAttribute( 'href' ) );
    114 					}
    115
    116 					return isAnchor ?
    117 							{ anchor : CKEDITOR.TRISTATE_OFF } :
    118 							{ link : CKEDITOR.TRISTATE_OFF, unlink : CKEDITOR.TRISTATE_OFF };
    119 				});
    120 		}
    121 	},
    122
    123 	afterInit : function( editor )
    124 	{
    125 		// Register a filter to displaying placeholders after mode change.
    126
    127 		var dataProcessor = editor.dataProcessor,
    128 			dataFilter = dataProcessor && dataProcessor.dataFilter;
    129
    130 		if ( dataFilter )
    131 		{
    132 			dataFilter.addRules(
    133 				{
    134 					elements :
    135 					{
    136 						a : function( element )
    137 						{
    138 							var attributes = element.attributes;
    139 							if ( attributes.name && !attributes.href )
    140 								return editor.createFakeParserElement( element, 'cke_anchor', 'anchor' );
    141 						}
    142 					}
    143 				});
    144 		}
    145 	},
    146
    147 	requires : [ 'fakeobjects' ]
    148 } );
    149
    150 CKEDITOR.unlinkCommand = function(){};
    151 CKEDITOR.unlinkCommand.prototype =
    152 {
    153 	/** @ignore */
    154 	exec : function( editor )
    155 	{
    156 		/*
    157 		 * execCommand( 'unlink', ... ) in Firefox leaves behind <span> tags at where
    158 		 * the <a> was, so again we have to remove the link ourselves. (See #430)
    159 		 *
    160 		 * TODO: Use the style system when it's complete. Let's use execCommand()
    161 		 * as a stopgap solution for now.
    162 		 */
    163 		var selection = editor.getSelection(),
    164 			bookmarks = selection.createBookmarks(),
    165 			ranges = selection.getRanges(),
    166 			rangeRoot,
    167 			element;
    168
    169 		for ( var i = 0 ; i < ranges.length ; i++ )
    170 		{
    171 			rangeRoot = ranges[i].getCommonAncestor( true );
    172 			element = rangeRoot.getAscendant( 'a', true );
    173 			if ( !element )
    174 				continue;
    175 			ranges[i].selectNodeContents( element );
    176 		}
    177
    178 		selection.selectRanges( ranges );
    179 		editor.document.$.execCommand( 'unlink', false, null );
    180 		selection.selectBookmarks( bookmarks );
    181 	}
    182 };
    183
    184 CKEDITOR.tools.extend( CKEDITOR.config,
    185 {
    186 	linkShowAdvancedTab : true,
    187 	linkShowTargetTab : true
    188 } );
    189