JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
3cdc6fb8e699a428ae224c3d437019068ff49012
[ckeditor.git] / _source / plugins / link / plugin.js
1 /*\r
2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license\r
4 */\r
5 \r
6 CKEDITOR.plugins.add( 'link',\r
7 {\r
8         init : function( editor )\r
9         {\r
10                 // Add the link and unlink buttons.\r
11                 editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link' ) );\r
12                 editor.addCommand( 'anchor', new CKEDITOR.dialogCommand( 'anchor' ) );\r
13                 editor.addCommand( 'unlink', new CKEDITOR.unlinkCommand() );\r
14                 editor.ui.addButton( 'Link',\r
15                         {\r
16                                 label : editor.lang.link.toolbar,\r
17                                 command : 'link'\r
18                         } );\r
19                 editor.ui.addButton( 'Unlink',\r
20                         {\r
21                                 label : editor.lang.unlink,\r
22                                 command : 'unlink'\r
23                         } );\r
24                 editor.ui.addButton( 'Anchor',\r
25                         {\r
26                                 label : editor.lang.anchor.toolbar,\r
27                                 command : 'anchor'\r
28                         } );\r
29                 CKEDITOR.dialog.add( 'link', this.path + 'dialogs/link.js' );\r
30                 CKEDITOR.dialog.add( 'anchor', this.path + 'dialogs/anchor.js' );\r
31 \r
32                 // Add the CSS styles for anchor placeholders.\r
33                 editor.addCss(\r
34                         'img.cke_anchor' +\r
35                         '{' +\r
36                                 'background-image: url(' + CKEDITOR.getUrl( this.path + 'images/anchor.gif' ) + ');' +\r
37                                 'background-position: center center;' +\r
38                                 'background-repeat: no-repeat;' +\r
39                                 'border: 1px solid #a9a9a9;' +\r
40                                 'width: 18px !important;' +\r
41                                 'height: 18px !important;' +\r
42                         '}\n' +\r
43                         'a.cke_anchor' +\r
44                         '{' +\r
45                                 'background-image: url(' + CKEDITOR.getUrl( this.path + 'images/anchor.gif' ) + ');' +\r
46                                 'background-position: 0 center;' +\r
47                                 'background-repeat: no-repeat;' +\r
48                                 'border: 1px solid #a9a9a9;' +\r
49                                 'padding-left: 18px;' +\r
50                         '}'\r
51                         );\r
52 \r
53                 // Register selection change handler for the unlink button.\r
54                  editor.on( 'selectionChange', function( evt )\r
55                         {\r
56                                 /*\r
57                                  * Despite our initial hope, document.queryCommandEnabled() does not work\r
58                                  * for this in Firefox. So we must detect the state by element paths.\r
59                                  */\r
60                                 var command = editor.getCommand( 'unlink' ),\r
61                                         element = evt.data.path.lastElement && evt.data.path.lastElement.getAscendant( 'a', true );\r
62                                 if ( element && element.getName() == 'a' && element.getAttribute( 'href' ) )\r
63                                         command.setState( CKEDITOR.TRISTATE_OFF );\r
64                                 else\r
65                                         command.setState( CKEDITOR.TRISTATE_DISABLED );\r
66                         } );\r
67 \r
68                 editor.on( 'doubleclick', function( evt )\r
69                         {\r
70                                 var element = CKEDITOR.plugins.link.getSelectedLink( editor ) || evt.data.element;\r
71 \r
72                                 if ( element.is( 'a' ) )\r
73                                         evt.data.dialog =  ( element.getAttribute( 'name' ) && !element.getAttribute( 'href' ) ) ? 'anchor' : 'link';\r
74                                 else if ( element.is( 'img' ) && element.getAttribute( '_cke_real_element_type' ) == 'anchor' )\r
75                                         evt.data.dialog = 'anchor';\r
76                         });\r
77 \r
78                 // If the "menu" plugin is loaded, register the menu items.\r
79                 if ( editor.addMenuItems )\r
80                 {\r
81                         editor.addMenuItems(\r
82                                 {\r
83                                         anchor :\r
84                                         {\r
85                                                 label : editor.lang.anchor.menu,\r
86                                                 command : 'anchor',\r
87                                                 group : 'anchor'\r
88                                         },\r
89 \r
90                                         link :\r
91                                         {\r
92                                                 label : editor.lang.link.menu,\r
93                                                 command : 'link',\r
94                                                 group : 'link',\r
95                                                 order : 1\r
96                                         },\r
97 \r
98                                         unlink :\r
99                                         {\r
100                                                 label : editor.lang.unlink,\r
101                                                 command : 'unlink',\r
102                                                 group : 'link',\r
103                                                 order : 5\r
104                                         }\r
105                                 });\r
106                 }\r
107 \r
108                 // If the "contextmenu" plugin is loaded, register the listeners.\r
109                 if ( editor.contextMenu )\r
110                 {\r
111                         editor.contextMenu.addListener( function( element, selection )\r
112                                 {\r
113                                         if ( !element || element.isReadOnly() )\r
114                                                 return null;\r
115 \r
116                                         var isAnchor = ( element.is( 'img' ) && element.getAttribute( '_cke_real_element_type' ) == 'anchor' );\r
117 \r
118                                         if ( !isAnchor )\r
119                                         {\r
120                                                 if ( !( element = CKEDITOR.plugins.link.getSelectedLink( editor ) ) )\r
121                                                         return null;\r
122 \r
123                                                 isAnchor = ( element.getAttribute( 'name' ) && !element.getAttribute( 'href' ) );\r
124                                         }\r
125 \r
126                                         return isAnchor ?\r
127                                                         { anchor : CKEDITOR.TRISTATE_OFF } :\r
128                                                         { link : CKEDITOR.TRISTATE_OFF, unlink : CKEDITOR.TRISTATE_OFF };\r
129                                 });\r
130                 }\r
131         },\r
132 \r
133         afterInit : function( editor )\r
134         {\r
135                 // Register a filter to displaying placeholders after mode change.\r
136 \r
137                 var dataProcessor = editor.dataProcessor,\r
138                         dataFilter = dataProcessor && dataProcessor.dataFilter;\r
139 \r
140                 if ( dataFilter )\r
141                 {\r
142                         dataFilter.addRules(\r
143                                 {\r
144                                         elements :\r
145                                         {\r
146                                                 a : function( element )\r
147                                                 {\r
148                                                         var attributes = element.attributes;\r
149                                                         if ( attributes.name && !attributes.href )\r
150                                                                 return editor.createFakeParserElement( element, 'cke_anchor', 'anchor' );\r
151                                                 }\r
152                                         }\r
153                                 });\r
154                 }\r
155         },\r
156 \r
157         requires : [ 'fakeobjects' ]\r
158 } );\r
159 \r
160 CKEDITOR.plugins.link =\r
161 {\r
162         /**\r
163          *  Get the surrounding link element of current selection.\r
164          * @param editor\r
165          * @example CKEDITOR.plugins.link.getSelectedLink( editor );\r
166          * @since 3.2.1\r
167          * The following selection will all return the link element.\r
168          *       <pre>\r
169          *  <a href="#">li^nk</a>\r
170          *  <a href="#">[link]</a>\r
171          *  text[<a href="#">link]</a>\r
172          *  <a href="#">li[nk</a>]\r
173          *  [<b><a href="#">li]nk</a></b>]\r
174          *  [<a href="#"><b>li]nk</b></a>\r
175          * </pre>\r
176          */\r
177         getSelectedLink : function( editor )\r
178         {\r
179                 try\r
180                 {\r
181                         var selection = editor.getSelection();\r
182                         if ( selection.getType() == CKEDITOR.SELECTION_ELEMENT )\r
183                         {\r
184                                 var selectedElement = selection.getSelectedElement();\r
185                                 if ( selectedElement.is( 'a' ) )\r
186                                         return selectedElement;\r
187                         }\r
188 \r
189                         var range = selection.getRanges( true )[ 0 ];\r
190                         range.shrink( CKEDITOR.SHRINK_TEXT );\r
191                         var root = range.getCommonAncestor();\r
192                         return root.getAscendant( 'a', true );\r
193                 }\r
194                 catch( e ) { return null; }\r
195         }\r
196 };\r
197 \r
198 CKEDITOR.unlinkCommand = function(){};\r
199 CKEDITOR.unlinkCommand.prototype =\r
200 {\r
201         /** @ignore */\r
202         exec : function( editor )\r
203         {\r
204                 /*\r
205                  * execCommand( 'unlink', ... ) in Firefox leaves behind <span> tags at where\r
206                  * the <a> was, so again we have to remove the link ourselves. (See #430)\r
207                  *\r
208                  * TODO: Use the style system when it's complete. Let's use execCommand()\r
209                  * as a stopgap solution for now.\r
210                  */\r
211                 var selection = editor.getSelection(),\r
212                         bookmarks = selection.createBookmarks(),\r
213                         ranges = selection.getRanges(),\r
214                         rangeRoot,\r
215                         element;\r
216 \r
217                 for ( var i = 0 ; i < ranges.length ; i++ )\r
218                 {\r
219                         rangeRoot = ranges[i].getCommonAncestor( true );\r
220                         element = rangeRoot.getAscendant( 'a', true );\r
221                         if ( !element )\r
222                                 continue;\r
223                         ranges[i].selectNodeContents( element );\r
224                 }\r
225 \r
226                 selection.selectRanges( ranges );\r
227                 editor.document.$.execCommand( 'unlink', false, null );\r
228                 selection.selectBookmarks( bookmarks );\r
229         },\r
230 \r
231         startDisabled : true\r
232 };\r
233 \r
234 CKEDITOR.tools.extend( CKEDITOR.config,\r
235 {\r
236         linkShowAdvancedTab : true,\r
237         linkShowTargetTab : true\r
238 } );\r