JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.1
[ckeditor.git] / _source / plugins / tab / 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 (function()\r
7 {\r
8         var blurCommand =\r
9                 {\r
10                         exec : function( editor )\r
11                         {\r
12                                 editor.container.focusNext( true );\r
13                         }\r
14                 };\r
15 \r
16         var blurBackCommand =\r
17                 {\r
18                         exec : function( editor )\r
19                         {\r
20                                 editor.container.focusPrevious( true );\r
21                         }\r
22                 };\r
23 \r
24         CKEDITOR.plugins.add( 'tab',\r
25         {\r
26                 requires : [ 'keystrokes' ],\r
27 \r
28                 init : function( editor )\r
29                 {\r
30                         // Register the keystrokes.\r
31                         var keystrokes = editor.keystrokeHandler.keystrokes;\r
32                         keystrokes[ 9 /* TAB */ ] = 'tab';\r
33                         keystrokes[ CKEDITOR.SHIFT + 9 /* TAB */ ] = 'shiftTab';\r
34 \r
35                         var tabSpaces = editor.config.tabSpaces,\r
36                                 tabText = '';\r
37 \r
38                         while ( tabSpaces-- )\r
39                                 tabText += '\xa0';\r
40 \r
41                         // Register the "tab" and "shiftTab" commands.\r
42                         editor.addCommand( 'tab',\r
43                                 {\r
44                                         exec : function( editor )\r
45                                         {\r
46                                                 // Fire the "tab" event, making it possible to\r
47                                                 // customize the TAB key behavior on specific cases.\r
48                                                 if ( !editor.fire( 'tab' ) )\r
49                                                 {\r
50                                                         if ( tabText.length > 0 )\r
51                                                                 editor.insertHtml( tabText );\r
52                                                         else\r
53                                                         {\r
54                                                                 // All browsers jump to the next field on TAB,\r
55                                                                 // except Safari, so we have to do that manually\r
56                                                                 // here.\r
57                                                                 /// https://bugs.webkit.org/show_bug.cgi?id=20597\r
58                                                                 return editor.execCommand( 'blur' );\r
59                                                         }\r
60                                                 }\r
61 \r
62                                                 return true;\r
63                                         }\r
64                                 });\r
65 \r
66                         editor.addCommand( 'shiftTab',\r
67                                 {\r
68                                         exec : function( editor )\r
69                                         {\r
70                                                 // Fire the "tab" event, making it possible to\r
71                                                 // customize the TAB key behavior on specific cases.\r
72                                                 if ( !editor.fire( 'shiftTab' ) )\r
73                                                         return editor.execCommand( 'blurBack' );\r
74 \r
75                                                 return true;\r
76                                         }\r
77                                 });\r
78 \r
79                         editor.addCommand( 'blur', blurCommand );\r
80                         editor.addCommand( 'blurBack', blurBackCommand );\r
81                 }\r
82         });\r
83 })();\r
84 \r
85 /**\r
86  * Moves the UI focus to the element following this element in the tabindex\r
87  * order.\r
88  * @example\r
89  * var element = CKEDITOR.document.getById( 'example' );\r
90  * element.focusNext();\r
91  */\r
92 CKEDITOR.dom.element.prototype.focusNext = function( ignoreChildren )\r
93 {\r
94         var $ = this.$,\r
95                 curTabIndex = this.getTabIndex(),\r
96                 passedCurrent, enteredCurrent,\r
97                 elected, electedTabIndex,\r
98                 element, elementTabIndex;\r
99 \r
100         if ( curTabIndex <= 0 )\r
101         {\r
102                 // If this element has tabindex <= 0 then we must simply look for any\r
103                 // element following it containing tabindex=0.\r
104 \r
105                 element = this.getNextSourceNode( ignoreChildren, CKEDITOR.NODE_ELEMENT );\r
106 \r
107                 while( element )\r
108                 {\r
109                         if ( element.isVisible() && element.getTabIndex() === 0 )\r
110                         {\r
111                                 elected = element;\r
112                                 break;\r
113                         }\r
114 \r
115                         element = element.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT );\r
116                 }\r
117         }\r
118         else\r
119         {\r
120                 // If this element has tabindex > 0 then we must look for:\r
121                 //              1. An element following this element with the same tabindex.\r
122                 //              2. The first element in source other with the lowest tabindex\r
123                 //                 that is higher than this element tabindex.\r
124                 //              3. The first element with tabindex=0.\r
125 \r
126                 element = this.getDocument().getBody().getFirst();\r
127 \r
128                 while( ( element = element.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT ) ) )\r
129                 {\r
130                         if ( !passedCurrent )\r
131                         {\r
132                                 if ( !enteredCurrent && element.equals( this ) )\r
133                                 {\r
134                                         enteredCurrent = true;\r
135 \r
136                                         // Ignore this element, if required.\r
137                                         if ( ignoreChildren )\r
138                                         {\r
139                                                 if ( !( element = element.getNextSourceNode( true, CKEDITOR.NODE_ELEMENT ) ) )\r
140                                                         break;\r
141                                                 passedCurrent = 1;\r
142                                         }\r
143                                 }\r
144                                 else if ( enteredCurrent && !this.contains( element ) )\r
145                                         passedCurrent = 1;\r
146                         }\r
147 \r
148                         if ( !element.isVisible() || ( elementTabIndex = element.getTabIndex() ) < 0 )\r
149                                 continue;\r
150 \r
151                         if ( passedCurrent && elementTabIndex == curTabIndex )\r
152                         {\r
153                                 elected = element;\r
154                                 break;\r
155                         }\r
156 \r
157                         if ( elementTabIndex > curTabIndex && ( !elected || !electedTabIndex || elementTabIndex < electedTabIndex ) )\r
158                         {\r
159                                 elected = element;\r
160                                 electedTabIndex = elementTabIndex;\r
161                         }\r
162                         else if ( !elected && elementTabIndex === 0 )\r
163                         {\r
164                                 elected = element;\r
165                                 electedTabIndex = elementTabIndex;\r
166                         }\r
167                 }\r
168         }\r
169 \r
170         if ( elected )\r
171                 elected.focus();\r
172 };\r
173 \r
174 /**\r
175  * Moves the UI focus to the element before this element in the tabindex order.\r
176  * @example\r
177  * var element = CKEDITOR.document.getById( 'example' );\r
178  * element.focusPrevious();\r
179  */\r
180 CKEDITOR.dom.element.prototype.focusPrevious = function( ignoreChildren )\r
181 {\r
182         var $ = this.$,\r
183                 curTabIndex = this.getTabIndex(),\r
184                 passedCurrent, enteredCurrent,\r
185                 elected,\r
186                 electedTabIndex = 0,\r
187                 elementTabIndex;\r
188 \r
189         var element = this.getDocument().getBody().getLast();\r
190 \r
191         while( ( element = element.getPreviousSourceNode( false, CKEDITOR.NODE_ELEMENT ) ) )\r
192         {\r
193                 if ( !passedCurrent )\r
194                 {\r
195                         if ( !enteredCurrent && element.equals( this ) )\r
196                         {\r
197                                 enteredCurrent = true;\r
198 \r
199                                 // Ignore this element, if required.\r
200                                 if ( ignoreChildren )\r
201                                 {\r
202                                         if ( !( element = element.getPreviousSourceNode( true, CKEDITOR.NODE_ELEMENT ) ) )\r
203                                                 break;\r
204                                         passedCurrent = 1;\r
205                                 }\r
206                         }\r
207                         else if ( enteredCurrent && !this.contains( element ) )\r
208                                 passedCurrent = 1;\r
209                 }\r
210 \r
211                 if ( !element.isVisible() || ( elementTabIndex = element.getTabIndex() ) < 0 )\r
212                         continue;\r
213 \r
214                 if ( curTabIndex <= 0 )\r
215                 {\r
216                         // If this element has tabindex <= 0 then we must look for:\r
217                         //              1. An element before this one containing tabindex=0.\r
218                         //              2. The last element with the highest tabindex.\r
219 \r
220                         if ( passedCurrent && elementTabIndex === 0 )\r
221                         {\r
222                                 elected = element;\r
223                                 break;\r
224                         }\r
225 \r
226                         if ( elementTabIndex > electedTabIndex )\r
227                         {\r
228                                 elected = element;\r
229                                 electedTabIndex = elementTabIndex;\r
230                         }\r
231                 }\r
232                 else\r
233                 {\r
234                         // If this element has tabindex > 0 we must look for:\r
235                         //              1. An element preceeding this one, with the same tabindex.\r
236                         //              2. The last element in source other with the highest tabindex\r
237                         //                 that is lower than this element tabindex.\r
238 \r
239                         if ( passedCurrent && elementTabIndex == curTabIndex )\r
240                         {\r
241                                 elected = element;\r
242                                 break;\r
243                         }\r
244 \r
245                         if ( elementTabIndex < curTabIndex && ( !elected || elementTabIndex > electedTabIndex ) )\r
246                         {\r
247                                 elected = element;\r
248                                 electedTabIndex = elementTabIndex;\r
249                         }\r
250                 }\r
251         }\r
252 \r
253         if ( elected )\r
254                 elected.focus();\r
255 };\r
256 \r
257 /**\r
258  * Intructs the editor to add a number of spaces (&amp;nbsp;) to the text when\r
259  * hitting the TAB key. If set to zero, the TAB key will be used to move the\r
260  * cursor focus to the next element in the page, out of the editor focus.\r
261  * @type Number\r
262  * @default 0\r
263  * @example\r
264  * config.tabSpaces = 4;\r
265  */\r
266 CKEDITOR.config.tabSpaces = 0 ;\r