3 <title>The source code</title>
4 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
5 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
7 <body onload="prettyPrint();">
8 <pre class="prettyprint lang-js">(function(){
\r
11 Ext.a11y.Frame = Ext.extend(Object, {
\r
14 constructor: function(size, color){
\r
15 this.setSize(size || 1);
\r
16 this.setColor(color || '15428B');
\r
20 if (!this.initialized) {
\r
25 this.ct = Ext.DomHelper.append(document.body, {
\r
26 cls: 'x-a11y-focusframe'
\r
29 for (i = 0; i < 4; i++) {
\r
30 s = Ext.DomHelper.append(this.ct, {
\r
31 cls: 'x-a11y-focusframe-side',
\r
32 style: 'background-color: #' + this.color
\r
34 s.visibilityMode = Ext.Element.DISPLAY;
\r
38 this.frameTask = new Ext.util.DelayedTask(function(el){
\r
39 var newEl = Ext.get(el);
\r
40 if (newEl != this.curEl) {
\r
41 var w = newEl.getWidth();
\r
42 var h = newEl.getHeight();
\r
43 this.sides[0].show().setSize(w, this.size).anchorTo(el, 'tl', [0, -1]);
\r
44 this.sides[2].show().setSize(w, this.size).anchorTo(el, 'bl', [0, -1]);
\r
45 this.sides[1].show().setSize(this.size, h).anchorTo(el, 'tr', [-1, 0]);
\r
46 this.sides[3].show().setSize(this.size, h).anchorTo(el, 'tl', [-1, 0]);
\r
51 this.unframeTask = new Ext.util.DelayedTask(function(){
\r
52 if (this.initialized) {
\r
53 this.sides[0].hide();
\r
54 this.sides[1].hide();
\r
55 this.sides[2].hide();
\r
56 this.sides[3].hide();
\r
60 this.initialized = true;
\r
64 frame: function(el){
\r
66 this.unframeTask.cancel();
\r
67 this.frameTask.delay(2, false, false, [el]);
\r
70 unframe: function(){
\r
72 this.unframeTask.delay(2);
\r
75 setSize: function(size){
\r
79 setColor: function(color){
\r
84 Ext.a11y.FocusFrame = new Ext.a11y.Frame(2, '15428B');
\r
85 Ext.a11y.RelayFrame = new Ext.a11y.Frame(1, '6B8CBF');
\r
87 Ext.a11y.Focusable = Ext.extend(Ext.util.Observable, {
\r
88 constructor: function(el, relayTo, noFrame, frameEl){
\r
89 Ext.a11y.Focusable.superclass.constructor.call(this);
\r
91 this.addEvents('focus', 'blur', 'left', 'right', 'up', 'down', 'esc', 'enter', 'space');
\r
93 if (el instanceof Ext.Component) {
\r
95 this.setComponent(el);
\r
98 this.el = Ext.get(el);
\r
99 this.setComponent(null);
\r
102 this.setRelayTo(relayTo)
\r
103 this.setNoFrame(noFrame);
\r
104 this.setFrameEl(frameEl);
\r
108 Ext.a11y.FocusMgr.register(this);
\r
112 this.el.dom.tabIndex = '1';
\r
113 this.el.addClass('x-a11y-focusable');
\r
115 focus: this.onFocus,
\r
117 keydown: this.onKeyDown,
\r
122 setRelayTo: function(relayTo){
\r
123 this.relayTo = relayTo ? Ext.a11y.FocusMgr.get(relayTo) : null;
\r
126 setNoFrame: function(noFrame){
\r
127 this.noFrame = (noFrame === true) ? true : false;
\r
130 setFrameEl: function(frameEl){
\r
131 this.frameEl = frameEl && Ext.get(frameEl) || this.el;
\r
134 setComponent: function(cmp){
\r
135 this.component = cmp || null;
\r
138 onKeyDown: function(e, t){
\r
139 var k = e.getKey(), SK = Ext.a11y.Focusable.SpecialKeys, ret, tf;
\r
141 tf = (t !== this.el.dom) ? Ext.a11y.FocusMgr.get(t, true) : this;
\r
143 // this can happen when you are on a focused item within a panel body
\r
144 // that is not a Ext.a11y.Focusable
\r
145 tf = Ext.a11y.FocusMgr.get(Ext.fly(t).parent('.x-a11y-focusable'));
\r
148 if (SK[k] !== undefined) {
\r
149 ret = this.fireEvent(SK[k], e, t, tf, this);
\r
151 if (ret === false || this.fireEvent('keydown', e, t, tf, this) === false) {
\r
157 this.el.dom.focus();
\r
161 this.el.dom.blur();
\r
164 onFocus: function(e, t){
\r
165 this.el.addClass('x-a11y-focused');
\r
166 if (this.relayTo) {
\r
167 this.relayTo.el.addClass('x-a11y-focused-relay');
\r
168 if (!this.relayTo.noFrame) {
\r
169 Ext.a11y.FocusFrame.frame(this.relayTo.frameEl);
\r
171 if (!this.noFrame) {
\r
172 Ext.a11y.RelayFrame.frame(this.frameEl);
\r
176 if (!this.noFrame) {
\r
177 Ext.a11y.FocusFrame.frame(this.frameEl);
\r
181 this.fireEvent('focus', e, t, this);
\r
184 onBlur: function(e, t){
\r
185 if (this.relayTo) {
\r
186 this.relayTo.el.removeClass('x-a11y-focused-relay');
\r
187 Ext.a11y.RelayFrame.unframe();
\r
189 this.el.removeClass('x-a11y-focused');
\r
190 Ext.a11y.FocusFrame.unframe();
\r
191 this.fireEvent('blur', e, t, this);
\r
194 destroy: function(){
\r
195 this.el.un('keydown', this.onKeyDown);
\r
196 this.el.un('focus', this.onFocus);
\r
197 this.el.un('blur', this.onBlur);
\r
198 this.el.removeClass('x-a11y-focusable');
\r
199 this.el.removeClass('x-a11y-focused');
\r
200 if (this.relayTo) {
\r
201 this.relayTo.el.removeClass('x-a11y-focused-relay');
\r
206 Ext.a11y.FocusItem = Ext.extend(Object, {
\r
207 constructor: function(el, enableTabbing){
\r
208 Ext.a11y.FocusItem.superclass.constructor.call(this);
\r
210 this.el = Ext.get(el);
\r
211 this.fi = new Ext.a11y.Focusable(el);
\r
212 this.fi.setComponent(this);
\r
214 this.fi.on('tab', this.onTab, this);
\r
216 this.enableTabbing = enableTabbing === true ? true : false;
\r
219 getEnterItem: function(){
\r
220 if (this.enableTabbing) {
\r
221 var items = this.getFocusItems();
\r
222 if (items && items.length) {
\r
228 getFocusItems: function(){
\r
229 if (this.enableTabbing) {
\r
230 return this.el.query('a, button, input, select');
\r
235 onTab: function(e, t){
\r
236 var items = this.getFocusItems(), i;
\r
238 if (items && items.length && (i = items.indexOf(t)) !== -1) {
\r
239 if (e.shiftKey && i > 0) {
\r
241 items[i - 1].focus();
\r
242 Ext.a11y.FocusFrame.frame.defer(20, Ext.a11y.FocusFrame, [this.el]);
\r
246 if (!e.shiftKey && i < items.length - 1) {
\r
248 items[i + 1].focus();
\r
249 Ext.a11y.FocusFrame.frame.defer(20, Ext.a11y.FocusFrame, [this.el]);
\r
256 if (this.enableTabbing) {
\r
257 var items = this.getFocusItems();
\r
258 if (items && items.length) {
\r
260 Ext.a11y.FocusFrame.frame.defer(20, Ext.a11y.FocusFrame, [this.el]);
\r
272 Ext.a11y.FocusMgr = function(){
\r
273 var all = new Ext.util.MixedCollection();
\r
276 register: function(f){
\r
277 all.add(f.el && Ext.id(f.el), f);
\r
280 unregister: function(f){
\r
284 get: function(el, noCreate){
\r
285 return all.get(Ext.id(el)) || (noCreate ? false : new Ext.a11y.Focusable(el));
\r
292 Ext.a11y.Focusable.SpecialKeys = {};
\r
293 Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.LEFT] = 'left';
\r
294 Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.RIGHT] = 'right';
\r
295 Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.DOWN] = 'down';
\r
296 Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.UP] = 'up';
\r
297 Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.ESC] = 'esc';
\r
298 Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.ENTER] = 'enter';
\r
299 Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.SPACE] = 'space';
\r
300 Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.TAB] = 'tab';
\r
302 // we use the new observeClass method to fire our new initFocus method on components
\r
303 Ext.util.Observable.observeClass(Ext.Component);
\r
304 Ext.Component.on('render', function(cmp){
\r
308 Ext.override(Ext.Component, {
\r
309 initFocus: Ext.emptyFn,
\r
310 initARIA: Ext.emptyFn
\r
313 Ext.override(Ext.Container, {
\r
318 initFocus: function(){
\r
319 if (!this.fi && !this.noFocus) {
\r
320 this.fi = new Ext.a11y.Focusable(this);
\r
322 this.mon(this.fi, {
\r
323 focus: this.onFocus,
\r
326 enter: this.onEnter,
\r
332 this.isFocusable = false;
\r
335 this.on('show', function(){
\r
336 this.isFocusable = true;
\r
338 this.on('hide', function(){
\r
339 this.isFocusable = false;
\r
352 var eitem = this.getEnterItem();
\r
358 onFocus: Ext.emptyFn,
\r
359 onBlur: Ext.emptyFn,
\r
361 onTab: function(e, t, tf){
\r
362 var rf = tf.relayTo || tf;
\r
363 if (rf.component && rf.component !== this) {
\r
365 var item = e.shiftKey ? this.getPreviousFocus(rf.component) : this.getNextFocus(rf.component);
\r
370 onEnter: function(e, t, tf){
\r
371 // check to see if enter is pressed while "on" the panel
\r
372 if (tf.component && tf.component === this) {
\r
376 e.stopPropagation();
\r
379 onEsc: function(e, t){
\r
380 e.preventDefault();
\r
382 // check to see if esc is pressed while "inside" the panel
\r
383 // or while "on" the panel
\r
384 if (t === this.el.dom) {
\r
385 // "on" the panel, check if this panel has an owner panel and focus that
\r
386 // we dont stop the event in this case so that this same check will be
\r
387 // done for this ownerCt
\r
388 if (this.ownerCt) {
\r
389 this.ownerCt.focus();
\r
393 // we were inside the panel when esc was pressed,
\r
394 // so go back "on" the panel
\r
395 if (this.ownerCt && this.ownerCt.isFocusable) {
\r
396 var si = this.ownerCt.getFocusItems();
\r
398 if (si && si.getCount() > 1) {
\r
406 getFocusItems: function(){
\r
407 return this.items &&
\r
408 this.items.filterBy(function(o){
\r
409 return o.isFocusable;
\r
414 getEnterItem: function(){
\r
415 var ci = this.getFocusItems(), length = ci ? ci.getCount() : 0;
\r
417 if (length === 1) {
\r
418 return ci.first().getEnterItem && ci.first().getEnterItem() || ci.first();
\r
420 else if (length > 1) {
\r
425 getNextFocus: function(current){
\r
426 var items = this.getFocusItems(), next = current, i = items.indexOf(current), length = items.getCount();
\r
428 if (i === length - 1) {
\r
429 next = items.first();
\r
432 next = items.get(i + 1);
\r
437 getPreviousFocus: function(current){
\r
438 var items = this.getFocusItems(), prev = current, i = items.indexOf(current), length = items.getCount();
\r
441 prev = items.last();
\r
444 prev = items.get(i - 1);
\r
449 getFocusable : function() {
\r
454 Ext.override(Ext.Panel, {
\r
455 <div id="cfg-Ext.ux.form.FileUploadField-enableTabbing"></div>/**
\r
456 * @cfg {Boolean} enableTabbing <tt>true</tt> to enable tabbing. Default is <tt>false</tt>.
\r
458 getFocusItems: function(){
\r
459 // items gets all the items inside the body
\r
460 var items = Ext.Panel.superclass.getFocusItems.call(this), bodyFocus = null;
\r
463 items = new Ext.util.MixedCollection();
\r
464 this.bodyFocus = this.bodyFocus || new Ext.a11y.FocusItem(this.body, this.enableTabbing);
\r
465 items.add('body', this.bodyFocus);
\r
467 // but panels can also have tbar, bbar, fbar
\r
468 if (this.tbar && this.topToolbar) {
\r
469 items.insert(0, this.topToolbar);
\r
471 if (this.bbar && this.bottomToolbar) {
\r
472 items.add(this.bottomToolbar);
\r
475 items.add(this.fbar);
\r
482 Ext.override(Ext.TabPanel, {
\r
484 initFocus: function(){
\r
485 Ext.TabPanel.superclass.initFocus.call(this);
\r
486 this.mon(this.fi, {
\r
488 right: this.onRight,
\r
493 onLeft: function(e){
\r
494 if (!this.activeTab) {
\r
498 var prev = this.items.itemAt(this.items.indexOf(this.activeTab) - 1);
\r
500 this.setActiveTab(prev);
\r
505 onRight: function(e){
\r
506 if (!this.activeTab) {
\r
510 var next = this.items.itemAt(this.items.indexOf(this.activeTab) + 1);
\r
512 this.setActiveTab(next);
\r
518 Ext.override(Ext.tree.TreeNodeUI, {
\r
521 this.node.getOwnerTree().bodyFocus.focus();
\r
525 Ext.override(Ext.tree.TreePanel, {
\r
527 afterRender : function(){
\r
528 Ext.tree.TreePanel.superclass.afterRender.call(this);
\r
529 this.root.render();
\r
530 if(!this.rootVisible){
\r
531 this.root.renderChildren();
\r
533 this.bodyFocus = new Ext.a11y.FocusItem(this.body.down('.x-tree-root-ct'));
\r
534 this.bodyFocus.fi.setFrameEl(this.body);
\r
538 Ext.override(Ext.grid.GridPanel, {
\r
539 initFocus: function(){
\r
540 Ext.grid.GridPanel.superclass.initFocus.call(this);
\r
541 this.bodyFocus = new Ext.a11y.FocusItem(this.view.focusEl);
\r
542 this.bodyFocus.fi.setFrameEl(this.body);
\r
546 Ext.override(Ext.Button, {
\r
550 initFocus: function(){
\r
551 Ext.Button.superclass.initFocus.call(this);
\r
552 this.fi = this.fi || new Ext.a11y.Focusable(this.btnEl, null, null, this.el);
\r
553 this.fi.setComponent(this);
\r
555 this.mon(this.fi, {
\r
556 focus: this.onFocus,
\r
562 this.mon(this.fi, 'down', this.showMenu, this);
\r
563 this.on('menuhide', this.focus, this);
\r
567 this.isFocusable = false;
\r
570 this.on('show', function(){
\r
571 this.isFocusable = true;
\r
573 this.on('hide', function(){
\r
574 this.isFocusable = false;
\r
586 onFocus: function(){
\r
587 if (!this.disabled) {
\r
588 this.el.addClass("x-btn-focus");
\r
592 onBlur: function(){
\r
593 this.el.removeClass("x-btn-focus");
\r
597 Ext.override(Ext.Toolbar, {
\r
598 initFocus: function(){
\r
599 Ext.Toolbar.superclass.initFocus.call(this);
\r
600 this.mon(this.fi, {
\r
602 right: this.onRight,
\r
606 this.on('focus', this.onButtonFocus, this, {
\r
612 var item = Ext.Toolbar.superclass.add.apply(this, arguments);
\r
613 if(!item || !item.events) {
\r
616 if (item.rendered && item.fi !== undefined) {
\r
617 item.fi.setRelayTo(this.el);
\r
618 this.relayEvents(item.fi, ['focus']);
\r
621 item.on('render', function(){
\r
622 if (item.fi !== undefined) {
\r
623 item.fi.setRelayTo(this.el);
\r
624 this.relayEvents(item.fi, ['focus']);
\r
633 onFocus: function(){
\r
634 var items = this.getFocusItems();
\r
635 if (items && items.getCount() > 0) {
\r
636 if (this.lastFocus && items.indexOf(this.lastFocus) !== -1) {
\r
637 this.lastFocus.focus();
\r
640 items.first().focus();
\r
645 onButtonFocus: function(e, t, tf){
\r
646 this.lastFocus = tf.component || null;
\r
649 onLeft: function(e, t, tf){
\r
651 this.getPreviousFocus(tf.component).focus();
\r
654 onRight: function(e, t, tf){
\r
656 this.getNextFocus(tf.component).focus();
\r
659 getEnterItem: Ext.emptyFn,
\r
660 onTab: Ext.emptyFn,
\r
664 Ext.override(Ext.menu.BaseItem, {
\r
665 initFocus: function(){
\r
666 this.fi = new Ext.a11y.Focusable(this, this.parentMenu && this.parentMenu.el || null, true);
\r
670 Ext.override(Ext.menu.Menu, {
\r
671 initFocus: function(){
\r
672 this.fi = new Ext.a11y.Focusable(this);
\r
673 this.focusEl = this.fi;
\r
677 Ext.a11y.WindowMgr = new Ext.WindowGroup();
\r
679 Ext.apply(Ext.WindowMgr, {
\r
680 bringToFront: function(win){
\r
681 Ext.a11y.WindowMgr.bringToFront.call(this, win);
\r
691 Ext.override(Ext.Window, {
\r
692 initFocus: function(){
\r
693 Ext.Window.superclass.initFocus.call(this);
\r
694 this.on('beforehide', function(){
\r
695 Ext.a11y.RelayFrame.unframe();
\r
696 Ext.a11y.FocusFrame.unframe();
\r
701 Ext.override(Ext.form.Field, {
\r
705 initFocus: function(){
\r
706 this.fi = this.fi || new Ext.a11y.Focusable(this, null, true);
\r
708 Ext.form.Field.superclass.initFocus.call(this);
\r
711 this.isFocusable = false;
\r
714 this.on('show', function(){
\r
715 this.isFocusable = true;
\r
717 this.on('hide', function(){
\r
718 this.isFocusable = false;
\r
723 Ext.override(Ext.FormPanel, {
\r
724 initFocus: function(){
\r
725 Ext.FormPanel.superclass.initFocus.call(this);
\r
726 this.on('focus', this.onFieldFocus, this, {
\r
732 createForm: function(){
\r
733 delete this.initialConfig.listeners;
\r
734 var form = new Ext.form.BasicForm(null, this.initialConfig);
\r
735 form.afterMethod('add', this.formItemAdd, this);
\r
739 formItemAdd: function(item){
\r
740 item.on('render', function(field){
\r
741 field.fi.setRelayTo(this.el);
\r
742 this.relayEvents(field.fi, ['focus']);
\r
748 onFocus: function(){
\r
749 var items = this.getFocusItems();
\r
750 if (items && items.getCount() > 0) {
\r
751 if (this.lastFocus && items.indexOf(this.lastFocus) !== -1) {
\r
752 this.lastFocus.focus();
\r
755 items.first().focus();
\r
760 onFieldFocus: function(e, t, tf){
\r
761 this.lastFocus = tf.component || null;
\r
764 onTab: function(e, t, tf){
\r
765 if (tf.relayTo.component === this) {
\r
766 var item = e.shiftKey ? this.getPreviousFocus(tf.component) : this.getNextFocus(tf.component);
\r
774 Ext.FormPanel.superclass.onTab.apply(this, arguments);
\r
777 getNextFocus: function(current){
\r
778 var items = this.getFocusItems(), i = items.indexOf(current), length = items.getCount();
\r
780 return (i < length - 1) ? items.get(i + 1) : false;
\r
783 getPreviousFocus: function(current){
\r
784 var items = this.getFocusItems(), i = items.indexOf(current), length = items.getCount();
\r
786 return (i > 0) ? items.get(i - 1) : false;
\r
790 Ext.override(Ext.Viewport, {
\r
791 initFocus: function(){
\r
792 Ext.Viewport.superclass.initFocus.apply(this);
\r
793 this.mon(Ext.get(document), 'focus', this.focus, this);
\r
794 this.mon(Ext.get(document), 'blur', this.blur, this);
\r
795 this.fi.setNoFrame(true);
\r
798 onTab: function(e, t, tf, f){
\r
802 items = this.getFocusItems();
\r
803 if (items && items.getCount() > 0) {
\r
804 items.first().focus();
\r
808 var rf = tf.relayTo || tf;
\r
809 var item = e.shiftKey ? this.getPreviousFocus(rf.component) : this.getNextFocus(rf.component);
\r