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 (function() 7 { 8 var blurInternal = function( editor, previous ) 9 { 10 var hasContainer = editor.container; 11 12 if ( hasContainer ) 13 { 14 // We need an empty element after the container, so the focus don't go to a container child. 15 var tempSpan = new CKEDITOR.dom.element( 'span' ); 16 tempSpan.setAttribute( 'tabindex', editor.container.getTabIndex() ); 17 tempSpan.hide(); 18 19 // Insert the temp element and set the focus. 20 if ( previous ) 21 { 22 tempSpan.insertBefore( editor.container ); 23 tempSpan.focusPrevious(); 24 } 25 else 26 { 27 tempSpan.insertAfter( editor.container ); 28 tempSpan.focusNext(); 29 } 30 31 // Remove the temporary node. 32 tempSpan.remove(); 33 } 34 35 return hasContainer; 36 }; 37 38 var blurCommand = 39 { 40 exec : function( editor ) 41 { 42 return blurInternal( editor ); 43 } 44 }; 45 46 var blurBackCommand = 47 { 48 exec : function( editor ) 49 { 50 return blurInternal( editor, true ); 51 } 52 }; 53 54 CKEDITOR.plugins.add( 'tab', 55 { 56 requires : [ 'keystrokes' ], 57 58 init : function( editor, pluginPath ) 59 { 60 // Register the keystrokes. 61 var keystrokes = editor.keystrokeHandler.keystrokes; 62 keystrokes[ 9 /* TAB */ ] = 'tab'; 63 keystrokes[ CKEDITOR.SHIFT + 9 /* TAB */ ] = 'shiftTab'; 64 65 var tabSpaces = editor.config.tabSpaces, 66 tabText = ''; 67 68 while ( tabSpaces-- ) 69 tabText += '\xa0'; 70 71 // Register the "tab" and "shiftTab" commands. 72 editor.addCommand( 'tab', 73 { 74 exec : function( editor ) 75 { 76 // Fire the "tab" event, making it possible to 77 // customize the TAB key behavior on specific cases. 78 if ( !editor.fire( 'tab' ) ) 79 { 80 if ( tabText.length > 0 ) 81 { 82 // TODO 83 /*jsl:pass*/ 84 } 85 else 86 { 87 // All browsers jump to the next field on TAB, 88 // except Safari, so we have to do that manually 89 // here. 90 /// https://bugs.webkit.org/show_bug.cgi?id=20597 91 return editor.execCommand( 'blur' ); 92 } 93 } 94 95 return true; 96 } 97 }); 98 99 editor.addCommand( 'shiftTab', 100 { 101 exec : function( editor ) 102 { 103 // Fire the "tab" event, making it possible to 104 // customize the TAB key behavior on specific cases. 105 if ( !editor.fire( 'shiftTab' ) ) 106 return editor.execCommand( 'blurBack' ); 107 108 return true; 109 } 110 }); 111 112 editor.addCommand( 'blur', blurCommand ); 113 editor.addCommand( 'blurBack', blurBackCommand ); 114 } 115 }); 116 })(); 117 118 /** 119 * Moves the UI focus to the element following this element in the tabindex 120 * order. 121 * @example 122 * var element = CKEDITOR.document.getById( 'example' ); 123 * element.focusNext(); 124 */ 125 CKEDITOR.dom.element.prototype.focusNext = function() 126 { 127 var $ = this.$, 128 curTabIndex = this.getTabIndex(), 129 passedCurrent = false, 130 elected, 131 electedTabIndex; 132 133 var all = document.body.all || document.body.getElementsByTagName( '*' ); 134 135 if ( curTabIndex <= 0 ) 136 { 137 for ( var i = 0, element ; element = all[ i ] ; i++ ) 138 { 139 if ( !passedCurrent ) 140 { 141 if ( element == $ ) 142 passedCurrent = true; 143 continue; 144 } 145 146 element = new CKEDITOR.dom.element( element ); 147 148 if ( element.getComputedStyle( 'display' ) == 'none' || element.getComputedStyle( 'visibility' ) == 'hidden' ) 149 continue; 150 151 if ( element.getTabIndex() === 0 ) 152 { 153 elected = element; 154 break; 155 } 156 } 157 } 158 else 159 { 160 for ( i = 0, element ; element = all[ i ] ; i++ ) 161 { 162 if ( !passedCurrent && element == $ ) 163 { 164 passedCurrent = true; 165 continue; 166 } 167 168 element = new CKEDITOR.dom.element( element ); 169 170 if ( element.getComputedStyle( 'display' ) == 'none' || element.getComputedStyle( 'visibility' ) == 'hidden' ) 171 continue; 172 173 var elementTabIndex = element.getTabIndex(); 174 175 if ( passedCurrent && elementTabIndex == curTabIndex ) 176 { 177 elected = element; 178 break; 179 } 180 else if ( elementTabIndex > curTabIndex && ( !elected || electedTabIndex > elementTabIndex || electedTabIndex === 0 ) ) 181 { 182 elected = element; 183 electedTabIndex = elementTabIndex; 184 } 185 else if ( !elected && elementTabIndex === 0 ) 186 { 187 elected = element; 188 electedTabIndex = elementTabIndex; 189 } 190 } 191 } 192 193 if ( elected ) 194 elected.focus(); 195 }; 196 197 /** 198 * Moves the UI focus to the element before this element in the tabindex order. 199 * @example 200 * var element = CKEDITOR.document.getById( 'example' ); 201 * element.focusPrevious(); 202 */ 203 CKEDITOR.dom.element.prototype.focusPrevious = function() 204 { 205 var $ = this.$, 206 curTabIndex = this.getTabIndex(), 207 passedCurrent = false, 208 elected, 209 electedTabIndex; 210 211 var all = document.body.all || document.body.getElementsByTagName( '*' ); 212 213 if ( curTabIndex <= 0 ) 214 { 215 for ( var i = 0, element ; element = all[ i ] ; i++ ) 216 { 217 if ( !passedCurrent && element == $ ) 218 { 219 if ( elected && electedTabIndex === 0 ) 220 break; 221 222 passedCurrent = true; 223 continue; 224 } 225 226 element = new CKEDITOR.dom.element( element ); 227 228 if ( element.getComputedStyle( 'display' ) == 'none' || element.getComputedStyle( 'visibility' ) == 'hidden' ) 229 continue; 230 231 var elementTabIndex = element.getTabIndex(); 232 233 if ( ( !passedCurrent && elementTabIndex === 0 ) 234 || ( elementTabIndex > 0 && ( !elected || ( electedTabIndex > 0 && electedTabIndex <= elementTabIndex ) ) ) ) 235 { 236 elected = element; 237 electedTabIndex = elementTabIndex; 238 } 239 } 240 } 241 else 242 { 243 for ( i = 0, element ; element = all[ i ] ; i++ ) 244 { 245 if ( !passedCurrent && element == $ ) 246 { 247 if ( elected && electedTabIndex == curTabIndex ) 248 break; 249 250 passedCurrent = true; 251 continue; 252 } 253 254 element = new CKEDITOR.dom.element( element ); 255 256 elementTabIndex = element.getTabIndex(); 257 258 if ( elementTabIndex > 0 ) 259 { 260 if ( ( !passedCurrent && elementTabIndex == curTabIndex ) 261 || ( elementTabIndex < curTabIndex && ( !elected || electedTabIndex <= elementTabIndex ) ) ) 262 { 263 elected = element; 264 electedTabIndex = elementTabIndex; 265 } 266 } 267 } 268 } 269 270 if ( elected ) 271 elected.focus(); 272 }; 273 274 /** 275 * Intructs the editor to add a number of spaces ( ) to the text when 276 * hitting the TAB key. If set to zero, the TAB key will have its default 277 * behavior instead (like moving out of the editor). 278 * @type {Number} 279 * @default 0 280 * @example 281 * config.tabSpaces = 4; 282 */ 283 CKEDITOR.config.tabSpaces = 0 ; 284