+<html>\r
+<head>\r
+ <title>The source code</title>\r
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
+</head>\r
+<body onload="prettyPrint();">\r
+ <pre class="prettyprint lang-js">(function(){\r
+Ext.ns('Ext.a11y');\r
+\r
+Ext.a11y.Frame = Ext.extend(Object, {\r
+ initialized: false,\r
+ \r
+ constructor: function(size, color){\r
+ this.setSize(size || 1);\r
+ this.setColor(color || '15428B');\r
+ },\r
+ \r
+ init: function(){\r
+ if (!this.initialized) {\r
+ this.sides = [];\r
+ \r
+ var s, i;\r
+ \r
+ this.ct = Ext.DomHelper.append(document.body, {\r
+ cls: 'x-a11y-focusframe'\r
+ }, true);\r
+ \r
+ for (i = 0; i < 4; i++) {\r
+ s = Ext.DomHelper.append(this.ct, {\r
+ cls: 'x-a11y-focusframe-side',\r
+ style: 'background-color: #' + this.color\r
+ }, true);\r
+ s.visibilityMode = Ext.Element.DISPLAY;\r
+ this.sides.push(s);\r
+ }\r
+ \r
+ this.frameTask = new Ext.util.DelayedTask(function(el){\r
+ var newEl = Ext.get(el);\r
+ if (newEl != this.curEl) {\r
+ var w = newEl.getWidth();\r
+ var h = newEl.getHeight();\r
+ this.sides[0].show().setSize(w, this.size).anchorTo(el, 'tl', [0, -1]);\r
+ this.sides[2].show().setSize(w, this.size).anchorTo(el, 'bl', [0, -1]);\r
+ this.sides[1].show().setSize(this.size, h).anchorTo(el, 'tr', [-1, 0]);\r
+ this.sides[3].show().setSize(this.size, h).anchorTo(el, 'tl', [-1, 0]);\r
+ this.curEl = newEl;\r
+ }\r
+ }, this);\r
+ \r
+ this.unframeTask = new Ext.util.DelayedTask(function(){\r
+ if (this.initialized) {\r
+ this.sides[0].hide();\r
+ this.sides[1].hide();\r
+ this.sides[2].hide();\r
+ this.sides[3].hide();\r
+ this.curEl = null;\r
+ }\r
+ }, this);\r
+ this.initialized = true;\r
+ }\r
+ },\r
+ \r
+ frame: function(el){\r
+ this.init();\r
+ this.unframeTask.cancel();\r
+ this.frameTask.delay(2, false, false, [el]);\r
+ },\r
+ \r
+ unframe: function(){\r
+ this.init();\r
+ this.unframeTask.delay(2);\r
+ },\r
+ \r
+ setSize: function(size){\r
+ this.size = size;\r
+ },\r
+ \r
+ setColor: function(color){\r
+ this.color = color;\r
+ }\r
+});\r
+\r
+Ext.a11y.FocusFrame = new Ext.a11y.Frame(2, '15428B');\r
+Ext.a11y.RelayFrame = new Ext.a11y.Frame(1, '6B8CBF');\r
+\r
+Ext.a11y.Focusable = Ext.extend(Ext.util.Observable, {\r
+ constructor: function(el, relayTo, noFrame, frameEl){\r
+ Ext.a11y.Focusable.superclass.constructor.call(this);\r
+ \r
+ this.addEvents('focus', 'blur', 'left', 'right', 'up', 'down', 'esc', 'enter', 'space');\r
+ \r
+ if (el instanceof Ext.Component) {\r
+ this.el = el.el;\r
+ this.setComponent(el);\r
+ }\r
+ else {\r
+ this.el = Ext.get(el);\r
+ this.setComponent(null);\r
+ }\r
+ \r
+ this.setRelayTo(relayTo)\r
+ this.setNoFrame(noFrame);\r
+ this.setFrameEl(frameEl);\r
+ \r
+ this.init();\r
+ \r
+ Ext.a11y.FocusMgr.register(this);\r
+ },\r
+ \r
+ init: function(){\r
+ this.el.dom.tabIndex = '1';\r
+ this.el.addClass('x-a11y-focusable');\r
+ this.el.on({\r
+ focus: this.onFocus,\r
+ blur: this.onBlur,\r
+ keydown: this.onKeyDown,\r
+ scope: this\r
+ });\r
+ },\r
+ \r
+ setRelayTo: function(relayTo){\r
+ this.relayTo = relayTo ? Ext.a11y.FocusMgr.get(relayTo) : null;\r
+ },\r
+ \r
+ setNoFrame: function(noFrame){\r
+ this.noFrame = (noFrame === true) ? true : false;\r
+ },\r
+ \r
+ setFrameEl: function(frameEl){\r
+ this.frameEl = frameEl && Ext.get(frameEl) || this.el;\r
+ },\r
+ \r
+ setComponent: function(cmp){\r
+ this.component = cmp || null;\r
+ },\r
+ \r
+ onKeyDown: function(e, t){\r
+ var k = e.getKey(), SK = Ext.a11y.Focusable.SpecialKeys, ret, tf;\r
+ \r
+ tf = (t !== this.el.dom) ? Ext.a11y.FocusMgr.get(t, true) : this;\r
+ if (!tf) {\r
+ // this can happen when you are on a focused item within a panel body\r
+ // that is not a Ext.a11y.Focusable\r
+ tf = Ext.a11y.FocusMgr.get(Ext.fly(t).parent('.x-a11y-focusable'));\r
+ }\r
+ \r
+ if (SK[k] !== undefined) {\r
+ ret = this.fireEvent(SK[k], e, t, tf, this);\r
+ }\r
+ if (ret === false || this.fireEvent('keydown', e, t, tf, this) === false) {\r
+ e.stopEvent();\r
+ }\r
+ },\r
+ \r
+ focus: function(){\r
+ this.el.dom.focus();\r
+ },\r
+ \r
+ blur: function(){\r
+ this.el.dom.blur();\r
+ },\r
+ \r
+ onFocus: function(e, t){\r
+ this.el.addClass('x-a11y-focused');\r
+ if (this.relayTo) {\r
+ this.relayTo.el.addClass('x-a11y-focused-relay');\r
+ if (!this.relayTo.noFrame) {\r
+ Ext.a11y.FocusFrame.frame(this.relayTo.frameEl);\r
+ }\r
+ if (!this.noFrame) {\r
+ Ext.a11y.RelayFrame.frame(this.frameEl);\r
+ }\r
+ }\r
+ else {\r
+ if (!this.noFrame) {\r
+ Ext.a11y.FocusFrame.frame(this.frameEl);\r
+ }\r
+ }\r
+ \r
+ this.fireEvent('focus', e, t, this);\r
+ },\r
+ \r
+ onBlur: function(e, t){\r
+ if (this.relayTo) {\r
+ this.relayTo.el.removeClass('x-a11y-focused-relay');\r
+ Ext.a11y.RelayFrame.unframe();\r
+ }\r
+ this.el.removeClass('x-a11y-focused');\r
+ Ext.a11y.FocusFrame.unframe();\r
+ this.fireEvent('blur', e, t, this);\r
+ },\r
+ \r
+ destroy: function(){\r
+ this.el.un('keydown', this.onKeyDown);\r
+ this.el.un('focus', this.onFocus);\r
+ this.el.un('blur', this.onBlur);\r
+ this.el.removeClass('x-a11y-focusable');\r
+ this.el.removeClass('x-a11y-focused');\r
+ if (this.relayTo) {\r
+ this.relayTo.el.removeClass('x-a11y-focused-relay');\r
+ }\r
+ }\r
+});\r
+\r
+Ext.a11y.FocusItem = Ext.extend(Object, {\r
+ constructor: function(el, enableTabbing){\r
+ Ext.a11y.FocusItem.superclass.constructor.call(this);\r
+ \r
+ this.el = Ext.get(el);\r
+ this.fi = new Ext.a11y.Focusable(el);\r
+ this.fi.setComponent(this);\r
+ \r
+ this.fi.on('tab', this.onTab, this);\r
+ \r
+ this.enableTabbing = enableTabbing === true ? true : false;\r
+ },\r
+ \r
+ getEnterItem: function(){\r
+ if (this.enableTabbing) {\r
+ var items = this.getFocusItems();\r
+ if (items && items.length) {\r
+ return items[0];\r
+ }\r
+ }\r
+ },\r
+ \r
+ getFocusItems: function(){\r
+ if (this.enableTabbing) {\r
+ return this.el.query('a, button, input, select');\r
+ }\r
+ return null;\r
+ },\r
+ \r
+ onTab: function(e, t){\r
+ var items = this.getFocusItems(), i;\r
+ \r
+ if (items && items.length && (i = items.indexOf(t)) !== -1) {\r
+ if (e.shiftKey && i > 0) {\r
+ e.stopEvent();\r
+ items[i - 1].focus();\r
+ Ext.a11y.FocusFrame.frame.defer(20, Ext.a11y.FocusFrame, [this.el]);\r
+ return;\r
+ }\r
+ else \r
+ if (!e.shiftKey && i < items.length - 1) {\r
+ e.stopEvent();\r
+ items[i + 1].focus();\r
+ Ext.a11y.FocusFrame.frame.defer(20, Ext.a11y.FocusFrame, [this.el]);\r
+ return;\r
+ }\r
+ }\r
+ },\r
+ \r
+ focus: function(){\r
+ if (this.enableTabbing) {\r
+ var items = this.getFocusItems();\r
+ if (items && items.length) {\r
+ items[0].focus();\r
+ Ext.a11y.FocusFrame.frame.defer(20, Ext.a11y.FocusFrame, [this.el]);\r
+ return;\r
+ }\r
+ }\r
+ this.fi.focus();\r
+ },\r
+ \r
+ blur: function(){\r
+ this.fi.blur();\r
+ }\r
+});\r
+\r
+Ext.a11y.FocusMgr = function(){\r
+ var all = new Ext.util.MixedCollection();\r
+ \r
+ return {\r
+ register: function(f){\r
+ all.add(f.el && Ext.id(f.el), f);\r
+ },\r
+ \r
+ unregister: function(f){\r
+ all.remove(f);\r
+ },\r
+ \r
+ get: function(el, noCreate){\r
+ return all.get(Ext.id(el)) || (noCreate ? false : new Ext.a11y.Focusable(el));\r
+ },\r
+ \r
+ all: all\r
+ }\r
+}();\r
+\r
+Ext.a11y.Focusable.SpecialKeys = {};\r
+Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.LEFT] = 'left';\r
+Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.RIGHT] = 'right';\r
+Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.DOWN] = 'down';\r
+Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.UP] = 'up';\r
+Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.ESC] = 'esc';\r
+Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.ENTER] = 'enter';\r
+Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.SPACE] = 'space';\r
+Ext.a11y.Focusable.SpecialKeys[Ext.EventObjectImpl.prototype.TAB] = 'tab';\r
+\r
+// we use the new observeClass method to fire our new initFocus method on components\r
+Ext.util.Observable.observeClass(Ext.Component);\r
+Ext.Component.on('render', function(cmp){\r
+ cmp.initFocus();\r
+ cmp.initARIA();\r
+});\r
+Ext.override(Ext.Component, {\r
+ initFocus: Ext.emptyFn,\r
+ initARIA: Ext.emptyFn\r
+});\r
+\r
+Ext.override(Ext.Container, {\r
+ isFocusable: true,\r
+ noFocus: false,\r
+ \r
+ // private\r
+ initFocus: function(){\r
+ if (!this.fi && !this.noFocus) {\r
+ this.fi = new Ext.a11y.Focusable(this);\r
+ }\r
+ this.mon(this.fi, {\r
+ focus: this.onFocus,\r
+ blur: this.onBlur,\r
+ tab: this.onTab,\r
+ enter: this.onEnter,\r
+ esc: this.onEsc,\r
+ scope: this\r
+ });\r
+ \r
+ if (this.hidden) {\r
+ this.isFocusable = false;\r
+ }\r
+ \r
+ this.on('show', function(){\r
+ this.isFocusable = true;\r
+ }, this);\r
+ this.on('hide', function(){\r
+ this.isFocusable = false;\r
+ }, this);\r
+ },\r
+ \r
+ focus: function(){\r
+ this.fi.focus();\r
+ },\r
+ \r
+ blur: function(){\r
+ this.fi.blur();\r
+ },\r
+ \r
+ enter: function(){\r
+ var eitem = this.getEnterItem();\r
+ if (eitem) {\r
+ eitem.focus();\r
+ }\r
+ },\r
+ \r
+ onFocus: Ext.emptyFn,\r
+ onBlur: Ext.emptyFn,\r
+ \r
+ onTab: function(e, t, tf){\r
+ var rf = tf.relayTo || tf;\r
+ if (rf.component && rf.component !== this) {\r
+ e.stopEvent();\r
+ var item = e.shiftKey ? this.getPreviousFocus(rf.component) : this.getNextFocus(rf.component);\r
+ item.focus();\r
+ }\r
+ },\r
+ \r
+ onEnter: function(e, t, tf){\r
+ // check to see if enter is pressed while "on" the panel\r
+ if (tf.component && tf.component === this) {\r
+ e.stopEvent();\r
+ this.enter();\r
+ }\r
+ e.stopPropagation();\r
+ },\r
+ \r
+ onEsc: function(e, t){\r
+ e.preventDefault();\r
+ \r
+ // check to see if esc is pressed while "inside" the panel\r
+ // or while "on" the panel\r
+ if (t === this.el.dom) {\r
+ // "on" the panel, check if this panel has an owner panel and focus that\r
+ // we dont stop the event in this case so that this same check will be\r
+ // done for this ownerCt\r
+ if (this.ownerCt) {\r
+ this.ownerCt.focus();\r
+ }\r
+ }\r
+ else {\r
+ // we were inside the panel when esc was pressed,\r
+ // so go back "on" the panel\r
+ if (this.ownerCt && this.ownerCt.isFocusable) {\r
+ var si = this.ownerCt.getFocusItems();\r
+ \r
+ if (si && si.getCount() > 1) {\r
+ e.stopEvent();\r
+ }\r
+ }\r
+ this.focus();\r
+ }\r
+ },\r
+ \r
+ getFocusItems: function(){\r
+ return this.items &&\r
+ this.items.filterBy(function(o){\r
+ return o.isFocusable;\r
+ }) ||\r
+ null;\r
+ },\r
+ \r
+ getEnterItem: function(){\r
+ var ci = this.getFocusItems(), length = ci ? ci.getCount() : 0;\r
+ \r
+ if (length === 1) {\r
+ return ci.first().getEnterItem && ci.first().getEnterItem() || ci.first();\r
+ }\r
+ else \r
+ if (length > 1) {\r
+ return ci.first();\r
+ }\r
+ },\r
+ \r
+ getNextFocus: function(current){\r
+ var items = this.getFocusItems(), next = current, i = items.indexOf(current), length = items.getCount();\r
+ \r
+ if (i === length - 1) {\r
+ next = items.first();\r
+ }\r
+ else {\r
+ next = items.get(i + 1);\r
+ }\r
+ return next;\r
+ },\r
+ \r
+ getPreviousFocus: function(current){\r
+ var items = this.getFocusItems(), prev = current, i = items.indexOf(current), length = items.getCount();\r
+ \r
+ if (i === 0) {\r
+ prev = items.last();\r
+ }\r
+ else {\r
+ prev = items.get(i - 1);\r
+ }\r
+ return prev;\r
+ },\r
+ \r
+ getFocusable : function() {\r
+ return this.fi;\r
+ }\r
+});\r
+\r
+Ext.override(Ext.Panel, {\r
+ <div id="cfg-Ext.ux.layout.RowLayout-enableTabbing"></div>/**\r
+ * @cfg {Boolean} enableTabbing <tt>true</tt> to enable tabbing. Default is <tt>false</tt>.\r
+ */ \r
+ getFocusItems: function(){\r
+ // items gets all the items inside the body\r
+ var items = Ext.Panel.superclass.getFocusItems.call(this), bodyFocus = null;\r
+ \r
+ if (!items) {\r
+ items = new Ext.util.MixedCollection();\r
+ this.bodyFocus = this.bodyFocus || new Ext.a11y.FocusItem(this.body, this.enableTabbing);\r
+ items.add('body', this.bodyFocus);\r
+ }\r
+ // but panels can also have tbar, bbar, fbar\r
+ if (this.tbar && this.topToolbar) {\r
+ items.insert(0, this.topToolbar);\r
+ }\r
+ if (this.bbar && this.bottomToolbar) {\r
+ items.add(this.bottomToolbar);\r
+ }\r
+ if (this.fbar) {\r
+ items.add(this.fbar);\r
+ }\r
+ \r
+ return items;\r
+ }\r
+});\r
+\r
+Ext.override(Ext.TabPanel, {\r
+ // private\r
+ initFocus: function(){\r
+ Ext.TabPanel.superclass.initFocus.call(this);\r
+ this.mon(this.fi, {\r
+ left: this.onLeft,\r
+ right: this.onRight,\r
+ scope: this\r
+ });\r
+ },\r
+ \r
+ onLeft: function(e){\r
+ if (!this.activeTab) {\r
+ return;\r
+ }\r
+ e.stopEvent();\r
+ var prev = this.items.itemAt(this.items.indexOf(this.activeTab) - 1);\r
+ if (prev) {\r
+ this.setActiveTab(prev);\r
+ }\r
+ return false;\r
+ },\r
+ \r
+ onRight: function(e){\r
+ if (!this.activeTab) {\r
+ return;\r
+ }\r
+ e.stopEvent();\r
+ var next = this.items.itemAt(this.items.indexOf(this.activeTab) + 1);\r
+ if (next) {\r
+ this.setActiveTab(next);\r
+ }\r
+ return false;\r
+ }\r
+});\r
+\r
+Ext.override(Ext.tree.TreeNodeUI, {\r
+ // private\r
+ focus: function(){\r
+ this.node.getOwnerTree().bodyFocus.focus();\r
+ }\r
+});\r
+\r
+Ext.override(Ext.tree.TreePanel, {\r
+ // private\r
+ afterRender : function(){\r
+ Ext.tree.TreePanel.superclass.afterRender.call(this);\r
+ this.root.render();\r
+ if(!this.rootVisible){\r
+ this.root.renderChildren();\r
+ }\r
+ this.bodyFocus = new Ext.a11y.FocusItem(this.body.down('.x-tree-root-ct'));\r
+ this.bodyFocus.fi.setFrameEl(this.body);\r
+ } \r
+});\r
+\r
+Ext.override(Ext.grid.GridPanel, {\r
+ initFocus: function(){\r
+ Ext.grid.GridPanel.superclass.initFocus.call(this);\r
+ this.bodyFocus = new Ext.a11y.FocusItem(this.view.focusEl);\r
+ this.bodyFocus.fi.setFrameEl(this.body);\r
+ }\r
+});\r
+\r
+Ext.override(Ext.Button, {\r
+ isFocusable: true,\r
+ noFocus: false,\r
+ \r
+ initFocus: function(){\r
+ Ext.Button.superclass.initFocus.call(this);\r
+ this.fi = this.fi || new Ext.a11y.Focusable(this.btnEl, null, null, this.el);\r
+ this.fi.setComponent(this);\r
+ \r
+ this.mon(this.fi, {\r
+ focus: this.onFocus,\r
+ blur: this.onBlur,\r
+ scope: this\r
+ });\r
+ \r
+ if (this.menu) {\r
+ this.mon(this.fi, 'down', this.showMenu, this);\r
+ this.on('menuhide', this.focus, this);\r
+ }\r
+ \r
+ if (this.hidden) {\r
+ this.isFocusable = false;\r
+ }\r
+ \r
+ this.on('show', function(){\r
+ this.isFocusable = true;\r
+ }, this);\r
+ this.on('hide', function(){\r
+ this.isFocusable = false;\r
+ }, this);\r
+ },\r
+ \r
+ focus: function(){\r
+ this.fi.focus();\r
+ },\r
+ \r
+ blur: function(){\r
+ this.fi.blur();\r
+ },\r
+ \r
+ onFocus: function(){\r
+ if (!this.disabled) {\r
+ this.el.addClass("x-btn-focus");\r
+ }\r
+ },\r
+ \r
+ onBlur: function(){\r
+ this.el.removeClass("x-btn-focus");\r
+ }\r
+});\r
+\r
+Ext.override(Ext.Toolbar, {\r
+ initFocus: function(){\r
+ Ext.Toolbar.superclass.initFocus.call(this);\r
+ this.mon(this.fi, {\r
+ left: this.onLeft,\r
+ right: this.onRight,\r
+ scope: this\r
+ });\r
+ \r
+ this.on('focus', this.onButtonFocus, this, {\r
+ stopEvent: true\r
+ });\r
+ },\r
+ \r
+ addItem: function(item){\r
+ Ext.Toolbar.superclass.add.apply(this, arguments);\r
+ if (item.rendered && item.fi !== undefined) {\r
+ item.fi.setRelayTo(this.el);\r
+ this.relayEvents(item.fi, ['focus']);\r
+ }\r
+ else {\r
+ item.on('render', function(){\r
+ if (item.fi !== undefined) {\r
+ item.fi.setRelayTo(this.el);\r
+ this.relayEvents(item.fi, ['focus']);\r
+ }\r
+ }, this, {\r
+ single: true\r
+ });\r
+ }\r
+ return item;\r
+ },\r
+ \r
+ onFocus: function(){\r
+ var items = this.getFocusItems();\r
+ if (items && items.getCount() > 0) {\r
+ if (this.lastFocus && items.indexOf(this.lastFocus) !== -1) {\r
+ this.lastFocus.focus();\r
+ }\r
+ else {\r
+ items.first().focus();\r
+ }\r
+ }\r
+ },\r
+ \r
+ onButtonFocus: function(e, t, tf){\r
+ this.lastFocus = tf.component || null;\r
+ },\r
+ \r
+ onLeft: function(e, t, tf){\r
+ e.stopEvent();\r
+ this.getPreviousFocus(tf.component).focus();\r
+ },\r
+ \r
+ onRight: function(e, t, tf){\r
+ e.stopEvent();\r
+ this.getNextFocus(tf.component).focus();\r
+ },\r
+ \r
+ getEnterItem: Ext.emptyFn,\r
+ onTab: Ext.emptyFn,\r
+ onEsc: Ext.emptyFn\r
+});\r
+\r
+Ext.override(Ext.menu.BaseItem, {\r
+ initFocus: function(){\r
+ this.fi = new Ext.a11y.Focusable(this, this.parentMenu && this.parentMenu.el || null, true);\r
+ }\r
+});\r
+\r
+Ext.override(Ext.menu.Menu, {\r
+ initFocus: function(){\r
+ this.fi = new Ext.a11y.Focusable(this);\r
+ this.focusEl = this.fi;\r
+ }\r
+});\r
+\r
+Ext.a11y.WindowMgr = new Ext.WindowGroup();\r
+\r
+Ext.apply(Ext.WindowMgr, {\r
+ bringToFront: function(win){\r
+ Ext.a11y.WindowMgr.bringToFront.call(this, win);\r
+ if (win.modal) {\r
+ win.enter();\r
+ }\r
+ else {\r
+ win.focus();\r
+ }\r
+ }\r
+});\r
+\r
+Ext.override(Ext.Window, {\r
+ initFocus: function(){\r
+ Ext.Window.superclass.initFocus.call(this);\r
+ this.on('beforehide', function(){\r
+ Ext.a11y.RelayFrame.unframe();\r
+ Ext.a11y.FocusFrame.unframe();\r
+ });\r
+ }\r
+});\r
+\r
+Ext.override(Ext.form.Field, {\r
+ isFocusable: true,\r
+ noFocus: false,\r
+ \r
+ initFocus: function(){\r
+ this.fi = this.fi || new Ext.a11y.Focusable(this, null, true);\r
+ \r
+ Ext.form.Field.superclass.initFocus.call(this);\r
+ \r
+ if (this.hidden) {\r
+ this.isFocusable = false;\r
+ }\r
+ \r
+ this.on('show', function(){\r
+ this.isFocusable = true;\r
+ }, this);\r
+ this.on('hide', function(){\r
+ this.isFocusable = false;\r
+ }, this);\r
+ }\r
+});\r
+\r
+Ext.override(Ext.FormPanel, {\r
+ initFocus: function(){\r
+ Ext.FormPanel.superclass.initFocus.call(this);\r
+ this.on('focus', this.onFieldFocus, this, {\r
+ stopEvent: true\r
+ });\r
+ },\r
+ \r
+ // private\r
+ createForm: function(){\r
+ delete this.initialConfig.listeners;\r
+ var form = new Ext.form.BasicForm(null, this.initialConfig);\r
+ form.afterMethod('add', this.formItemAdd, this);\r
+ return form;\r
+ },\r
+ \r
+ formItemAdd: function(item){\r
+ item.on('render', function(field){\r
+ field.fi.setRelayTo(this.el);\r
+ this.relayEvents(field.fi, ['focus']);\r
+ }, this, {\r
+ single: true\r
+ });\r
+ },\r
+ \r
+ onFocus: function(){\r
+ var items = this.getFocusItems();\r
+ if (items && items.getCount() > 0) {\r
+ if (this.lastFocus && items.indexOf(this.lastFocus) !== -1) {\r
+ this.lastFocus.focus();\r
+ }\r
+ else {\r
+ items.first().focus();\r
+ }\r
+ }\r
+ },\r
+ \r
+ onFieldFocus: function(e, t, tf){\r
+ this.lastFocus = tf.component || null;\r
+ },\r
+ \r
+ onTab: function(e, t, tf){\r
+ if (tf.relayTo.component === this) {\r
+ var item = e.shiftKey ? this.getPreviousFocus(tf.component) : this.getNextFocus(tf.component);\r
+ \r
+ if (item) {\r
+ ev.stopEvent();\r
+ item.focus();\r
+ return;\r
+ }\r
+ }\r
+ Ext.FormPanel.superclass.onTab.apply(this, arguments);\r
+ },\r
+ \r
+ getNextFocus: function(current){\r
+ var items = this.getFocusItems(), i = items.indexOf(current), length = items.getCount();\r
+ \r
+ return (i < length - 1) ? items.get(i + 1) : false;\r
+ },\r
+ \r
+ getPreviousFocus: function(current){\r
+ var items = this.getFocusItems(), i = items.indexOf(current), length = items.getCount();\r
+ \r
+ return (i > 0) ? items.get(i - 1) : false;\r
+ }\r
+});\r
+\r
+Ext.override(Ext.Viewport, {\r
+ initFocus: function(){\r
+ Ext.Viewport.superclass.initFocus.apply(this);\r
+ this.mon(Ext.get(document), 'focus', this.focus, this);\r
+ this.mon(Ext.get(document), 'blur', this.blur, this);\r
+ this.fi.setNoFrame(true);\r
+ },\r
+ \r
+ onTab: function(e, t, tf, f){\r
+ e.stopEvent();\r
+ \r
+ if (tf === f) {\r
+ items = this.getFocusItems();\r
+ if (items && items.getCount() > 0) {\r
+ items.first().focus();\r
+ }\r
+ }\r
+ else {\r
+ var rf = tf.relayTo || tf;\r
+ var item = e.shiftKey ? this.getPreviousFocus(rf.component) : this.getNextFocus(rf.component);\r
+ item.focus();\r
+ }\r
+ }\r
+});\r
+ \r
+})();</pre> \r
+</body>\r
+</html>
\ No newline at end of file