diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2016-02-19 23:38:52 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2016-02-19 23:38:52 +0100 |
commit | 3332bebe4da6dfa0fe3e4b2abddc84b1cc62f8f5 (patch) | |
tree | a4f77655fe55b79606e7d3416504686a1ab8b058 /sources/plugins/tab | |
download | piedsjaloux-ckeditor-component-3332bebe4da6dfa0fe3e4b2abddc84b1cc62f8f5.tar.gz piedsjaloux-ckeditor-component-3332bebe4da6dfa0fe3e4b2abddc84b1cc62f8f5.tar.zst piedsjaloux-ckeditor-component-3332bebe4da6dfa0fe3e4b2abddc84b1cc62f8f5.zip |
Initial commit4.5.7
Diffstat (limited to 'sources/plugins/tab')
-rw-r--r-- | sources/plugins/tab/plugin.js | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/sources/plugins/tab/plugin.js b/sources/plugins/tab/plugin.js new file mode 100644 index 0000000..cd61b97 --- /dev/null +++ b/sources/plugins/tab/plugin.js | |||
@@ -0,0 +1,302 @@ | |||
1 | /** | ||
2 | * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. | ||
3 | * For licensing, see LICENSE.md or http://ckeditor.com/license | ||
4 | */ | ||
5 | |||
6 | ( function() { | ||
7 | var meta = { | ||
8 | editorFocus: false, | ||
9 | modes: { wysiwyg: 1, source: 1 } | ||
10 | }; | ||
11 | |||
12 | var blurCommand = { | ||
13 | exec: function( editor ) { | ||
14 | editor.container.focusNext( true, editor.tabIndex ); | ||
15 | } | ||
16 | }; | ||
17 | |||
18 | var blurBackCommand = { | ||
19 | exec: function( editor ) { | ||
20 | editor.container.focusPrevious( true, editor.tabIndex ); | ||
21 | } | ||
22 | }; | ||
23 | |||
24 | function selectNextCellCommand( backward ) { | ||
25 | return { | ||
26 | editorFocus: false, | ||
27 | canUndo: false, | ||
28 | modes: { wysiwyg: 1 }, | ||
29 | exec: function( editor ) { | ||
30 | if ( editor.editable().hasFocus ) { | ||
31 | var sel = editor.getSelection(), | ||
32 | path = new CKEDITOR.dom.elementPath( sel.getCommonAncestor(), sel.root ), | ||
33 | cell; | ||
34 | |||
35 | if ( ( cell = path.contains( { td: 1, th: 1 }, 1 ) ) ) { | ||
36 | var resultRange = editor.createRange(), | ||
37 | next = CKEDITOR.tools.tryThese( function() { | ||
38 | var row = cell.getParent(), | ||
39 | next = row.$.cells[ cell.$.cellIndex + ( backward ? -1 : 1 ) ]; | ||
40 | |||
41 | // Invalid any empty value. | ||
42 | next.parentNode.parentNode; | ||
43 | return next; | ||
44 | }, function() { | ||
45 | var row = cell.getParent(), | ||
46 | table = row.getAscendant( 'table' ), | ||
47 | nextRow = table.$.rows[ row.$.rowIndex + ( backward ? -1 : 1 ) ]; | ||
48 | |||
49 | return nextRow.cells[ backward ? nextRow.cells.length - 1 : 0 ]; | ||
50 | } ); | ||
51 | |||
52 | // Clone one more row at the end of table and select the first newly established cell. | ||
53 | if ( !( next || backward ) ) { | ||
54 | var table = cell.getAscendant( 'table' ).$, | ||
55 | cells = cell.getParent().$.cells; | ||
56 | |||
57 | var newRow = new CKEDITOR.dom.element( table.insertRow( -1 ), editor.document ); | ||
58 | |||
59 | for ( var i = 0, count = cells.length; i < count; i++ ) { | ||
60 | var newCell = newRow.append( new CKEDITOR.dom.element( cells[ i ], editor.document ).clone( false, false ) ); | ||
61 | newCell.appendBogus(); | ||
62 | } | ||
63 | |||
64 | resultRange.moveToElementEditStart( newRow ); | ||
65 | } else if ( next ) { | ||
66 | next = new CKEDITOR.dom.element( next ); | ||
67 | resultRange.moveToElementEditStart( next ); | ||
68 | // Avoid selecting empty block makes the cursor blind. | ||
69 | if ( !( resultRange.checkStartOfBlock() && resultRange.checkEndOfBlock() ) ) | ||
70 | resultRange.selectNodeContents( next ); | ||
71 | } else { | ||
72 | return true; | ||
73 | } | ||
74 | |||
75 | resultRange.select( true ); | ||
76 | return true; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | return false; | ||
81 | } | ||
82 | }; | ||
83 | } | ||
84 | |||
85 | CKEDITOR.plugins.add( 'tab', { | ||
86 | init: function( editor ) { | ||
87 | var tabTools = editor.config.enableTabKeyTools !== false, | ||
88 | tabSpaces = editor.config.tabSpaces || 0, | ||
89 | tabText = ''; | ||
90 | |||
91 | while ( tabSpaces-- ) | ||
92 | tabText += '\xa0'; | ||
93 | |||
94 | if ( tabText ) { | ||
95 | editor.on( 'key', function( ev ) { | ||
96 | // TAB. | ||
97 | if ( ev.data.keyCode == 9 ) { | ||
98 | editor.insertText( tabText ); | ||
99 | ev.cancel(); | ||
100 | } | ||
101 | } ); | ||
102 | } | ||
103 | |||
104 | if ( tabTools ) { | ||
105 | editor.on( 'key', function( ev ) { | ||
106 | if ( ev.data.keyCode == 9 && editor.execCommand( 'selectNextCell' ) || // TAB | ||
107 | ev.data.keyCode == ( CKEDITOR.SHIFT + 9 ) && editor.execCommand( 'selectPreviousCell' ) ) // SHIFT+TAB | ||
108 | ev.cancel(); | ||
109 | } ); | ||
110 | } | ||
111 | |||
112 | editor.addCommand( 'blur', CKEDITOR.tools.extend( blurCommand, meta ) ); | ||
113 | editor.addCommand( 'blurBack', CKEDITOR.tools.extend( blurBackCommand, meta ) ); | ||
114 | editor.addCommand( 'selectNextCell', selectNextCellCommand() ); | ||
115 | editor.addCommand( 'selectPreviousCell', selectNextCellCommand( true ) ); | ||
116 | } | ||
117 | } ); | ||
118 | } )(); | ||
119 | |||
120 | /** | ||
121 | * Moves the UI focus to the element following this element in the tabindex order. | ||
122 | * | ||
123 | * var element = CKEDITOR.document.getById( 'example' ); | ||
124 | * element.focusNext(); | ||
125 | * | ||
126 | * @param {Boolean} [ignoreChildren=false] | ||
127 | * @param {Number} [indexToUse] | ||
128 | * @member CKEDITOR.dom.element | ||
129 | */ | ||
130 | CKEDITOR.dom.element.prototype.focusNext = function( ignoreChildren, indexToUse ) { | ||
131 | var curTabIndex = ( indexToUse === undefined ? this.getTabIndex() : indexToUse ), | ||
132 | passedCurrent, enteredCurrent, elected, electedTabIndex, element, elementTabIndex; | ||
133 | |||
134 | if ( curTabIndex <= 0 ) { | ||
135 | // If this element has tabindex <= 0 then we must simply look for any | ||
136 | // element following it containing tabindex=0. | ||
137 | |||
138 | element = this.getNextSourceNode( ignoreChildren, CKEDITOR.NODE_ELEMENT ); | ||
139 | |||
140 | while ( element ) { | ||
141 | if ( element.isVisible() && element.getTabIndex() === 0 ) { | ||
142 | elected = element; | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | element = element.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT ); | ||
147 | } | ||
148 | } else { | ||
149 | // If this element has tabindex > 0 then we must look for: | ||
150 | // 1. An element following this element with the same tabindex. | ||
151 | // 2. The first element in source other with the lowest tabindex | ||
152 | // that is higher than this element tabindex. | ||
153 | // 3. The first element with tabindex=0. | ||
154 | |||
155 | element = this.getDocument().getBody().getFirst(); | ||
156 | |||
157 | while ( ( element = element.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT ) ) ) { | ||
158 | if ( !passedCurrent ) { | ||
159 | if ( !enteredCurrent && element.equals( this ) ) { | ||
160 | enteredCurrent = true; | ||
161 | |||
162 | // Ignore this element, if required. | ||
163 | if ( ignoreChildren ) { | ||
164 | if ( !( element = element.getNextSourceNode( true, CKEDITOR.NODE_ELEMENT ) ) ) | ||
165 | break; | ||
166 | passedCurrent = 1; | ||
167 | } | ||
168 | } else if ( enteredCurrent && !this.contains( element ) ) { | ||
169 | passedCurrent = 1; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | if ( !element.isVisible() || ( elementTabIndex = element.getTabIndex() ) < 0 ) | ||
174 | continue; | ||
175 | |||
176 | if ( passedCurrent && elementTabIndex == curTabIndex ) { | ||
177 | elected = element; | ||
178 | break; | ||
179 | } | ||
180 | |||
181 | if ( elementTabIndex > curTabIndex && ( !elected || !electedTabIndex || elementTabIndex < electedTabIndex ) ) { | ||
182 | elected = element; | ||
183 | electedTabIndex = elementTabIndex; | ||
184 | } else if ( !elected && elementTabIndex === 0 ) { | ||
185 | elected = element; | ||
186 | electedTabIndex = elementTabIndex; | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | |||
191 | if ( elected ) | ||
192 | elected.focus(); | ||
193 | }; | ||
194 | |||
195 | /** | ||
196 | * Moves the UI focus to the element before this element in the tabindex order. | ||
197 | * | ||
198 | * var element = CKEDITOR.document.getById( 'example' ); | ||
199 | * element.focusPrevious(); | ||
200 | * | ||
201 | * @param {Boolean} [ignoreChildren=false] | ||
202 | * @param {Number} [indexToUse] | ||
203 | * @member CKEDITOR.dom.element | ||
204 | */ | ||
205 | CKEDITOR.dom.element.prototype.focusPrevious = function( ignoreChildren, indexToUse ) { | ||
206 | var curTabIndex = ( indexToUse === undefined ? this.getTabIndex() : indexToUse ), | ||
207 | passedCurrent, enteredCurrent, elected, | ||
208 | electedTabIndex = 0, | ||
209 | elementTabIndex; | ||
210 | |||
211 | var element = this.getDocument().getBody().getLast(); | ||
212 | |||
213 | while ( ( element = element.getPreviousSourceNode( false, CKEDITOR.NODE_ELEMENT ) ) ) { | ||
214 | if ( !passedCurrent ) { | ||
215 | if ( !enteredCurrent && element.equals( this ) ) { | ||
216 | enteredCurrent = true; | ||
217 | |||
218 | // Ignore this element, if required. | ||
219 | if ( ignoreChildren ) { | ||
220 | if ( !( element = element.getPreviousSourceNode( true, CKEDITOR.NODE_ELEMENT ) ) ) | ||
221 | break; | ||
222 | passedCurrent = 1; | ||
223 | } | ||
224 | } else if ( enteredCurrent && !this.contains( element ) ) { | ||
225 | passedCurrent = 1; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | if ( !element.isVisible() || ( elementTabIndex = element.getTabIndex() ) < 0 ) | ||
230 | continue; | ||
231 | |||
232 | if ( curTabIndex <= 0 ) { | ||
233 | // If this element has tabindex <= 0 then we must look for: | ||
234 | // 1. An element before this one containing tabindex=0. | ||
235 | // 2. The last element with the highest tabindex. | ||
236 | |||
237 | if ( passedCurrent && elementTabIndex === 0 ) { | ||
238 | elected = element; | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | if ( elementTabIndex > electedTabIndex ) { | ||
243 | elected = element; | ||
244 | electedTabIndex = elementTabIndex; | ||
245 | } | ||
246 | } else { | ||
247 | // If this element has tabindex > 0 we must look for: | ||
248 | // 1. An element preceeding this one, with the same tabindex. | ||
249 | // 2. The last element in source other with the highest tabindex | ||
250 | // that is lower than this element tabindex. | ||
251 | |||
252 | if ( passedCurrent && elementTabIndex == curTabIndex ) { | ||
253 | elected = element; | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | if ( elementTabIndex < curTabIndex && ( !elected || elementTabIndex > electedTabIndex ) ) { | ||
258 | elected = element; | ||
259 | electedTabIndex = elementTabIndex; | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | |||
264 | if ( elected ) | ||
265 | elected.focus(); | ||
266 | }; | ||
267 | |||
268 | /** | ||
269 | * Intructs the editor to add a number of spaces (` `) to the text when | ||
270 | * hitting the <kbd>Tab</kbd> key. If set to zero, the <kbd>Tab</kbd> key will be used to move the | ||
271 | * cursor focus to the next element in the page, out of the editor focus. | ||
272 | * | ||
273 | * config.tabSpaces = 4; | ||
274 | * | ||
275 | * @cfg {Number} [tabSpaces=0] | ||
276 | * @member CKEDITOR.config | ||
277 | */ | ||
278 | |||
279 | /** | ||
280 | * Allow context-sensitive <kbd>Tab</kbd> key behaviors, including the following scenarios: | ||
281 | * | ||
282 | * When selection is anchored inside **table cells**: | ||
283 | * | ||
284 | * * If <kbd>Tab</kbd> is pressed, select the content of the "next" cell. If in the last | ||
285 | * cell in the table, add a new row to it and focus its first cell. | ||
286 | * * If <kbd>Shift+Tab</kbd> is pressed, select the content of the "previous" cell. | ||
287 | * Do nothing when it is in the first cell. | ||
288 | * | ||
289 | * Example: | ||
290 | * | ||
291 | * config.enableTabKeyTools = false; | ||
292 | * | ||
293 | * @cfg {Boolean} [enableTabKeyTools=true] | ||
294 | * @member CKEDITOR.config | ||
295 | */ | ||
296 | |||
297 | // If the <kbd>Tab</kbd> key is not supposed to be enabled for navigation, the following | ||
298 | // settings could be used alternatively: | ||
299 | // config.keystrokes.push( | ||
300 | // [ CKEDITOR.ALT + 38 /*Arrow Up*/, 'selectPreviousCell' ], | ||
301 | // [ CKEDITOR.ALT + 40 /*Arrow Down*/, 'selectNextCell' ] | ||
302 | // ); | ||