Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/js/phuix/PHUIXDropdownMenu.js
| Show All 15 Lines | |||||
| * when an item is selected. Callers must make a call to @{method:close} after | * when an item is selected. Callers must make a call to @{method:close} after | ||||
| * an item is chosen in order to close the menu. | * an item is chosen in order to close the menu. | ||||
| */ | */ | ||||
| JX.install('PHUIXDropdownMenu', { | JX.install('PHUIXDropdownMenu', { | ||||
| construct : function(node) { | construct : function(node) { | ||||
| this._node = node; | this._node = node; | ||||
| if (node) { | |||||
| JX.DOM.listen( | JX.DOM.listen( | ||||
| this._node, | this._node, | ||||
| 'click', | 'click', | ||||
| null, | null, | ||||
| JX.bind(this, this._onclick)); | JX.bind(this, this._onclick)); | ||||
| } | |||||
| JX.Stratcom.listen( | JX.Stratcom.listen( | ||||
| 'mousedown', | 'mousedown', | ||||
| null, | null, | ||||
| JX.bind(this, this._onanyclick)); | JX.bind(this, this._onanyclick)); | ||||
| JX.Stratcom.listen( | JX.Stratcom.listen( | ||||
| 'resize', | 'resize', | ||||
| Show All 12 Lines | JX.install('PHUIXDropdownMenu', { | ||||
| }, | }, | ||||
| events: ['open', 'close'], | events: ['open', 'close'], | ||||
| properties: { | properties: { | ||||
| width: null, | width: null, | ||||
| align: 'right', | align: 'right', | ||||
| offsetX: 0, | offsetX: 0, | ||||
| offsetY: 0 | offsetY: 0, | ||||
| disableAutofocus: false | |||||
| }, | }, | ||||
| members: { | members: { | ||||
| _node: null, | _node: null, | ||||
| _menu: null, | _menu: null, | ||||
| _open: false, | _open: false, | ||||
| _content: null, | _content: null, | ||||
| _position: null, | |||||
| _visible: false, | |||||
| setContent: function(content) { | setContent: function(content) { | ||||
| JX.DOM.setContent(this._getMenuNode(), content); | JX.DOM.setContent(this._getMenuNode(), content); | ||||
| return this; | return this; | ||||
| }, | }, | ||||
| open: function() { | open: function() { | ||||
| if (this._open) { | if (this._open) { | ||||
| Show All 16 Lines | close: function() { | ||||
| this._open = false; | this._open = false; | ||||
| this._hide(); | this._hide(); | ||||
| this.invoke('close'); | this.invoke('close'); | ||||
| return this; | return this; | ||||
| }, | }, | ||||
| setPosition: function(pos) { | |||||
| this._position = pos; | |||||
| this._setMenuNodePosition(pos); | |||||
| return this; | |||||
| }, | |||||
| _getMenuNode: function() { | _getMenuNode: function() { | ||||
| if (!this._menu) { | if (!this._menu) { | ||||
| var attrs = { | var attrs = { | ||||
| className: 'phuix-dropdown-menu', | className: 'phuix-dropdown-menu', | ||||
| role: 'button' | role: 'button' | ||||
| }; | }; | ||||
| var menu = JX.$N('div', attrs); | var menu = JX.$N('div', attrs); | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | _onanyclick : function(e) { | ||||
| } | } | ||||
| t = t.parentNode; | t = t.parentNode; | ||||
| } | } | ||||
| this.close(); | this.close(); | ||||
| }, | }, | ||||
| _show : function() { | _show : function() { | ||||
| if (!this._visible) { | |||||
| this._visible = true; | |||||
| document.body.appendChild(this._menu); | document.body.appendChild(this._menu); | ||||
| } | |||||
| if (this.getWidth()) { | if (this.getWidth()) { | ||||
| new JX.Vector(this.getWidth(), null).setDim(this._menu); | new JX.Vector(this.getWidth(), null).setDim(this._menu); | ||||
| } | } | ||||
| this._adjustposition(); | this._adjustposition(); | ||||
| if (this._node) { | |||||
| JX.DOM.alterClass(this._node, 'phuix-dropdown-open', true); | JX.DOM.alterClass(this._node, 'phuix-dropdown-open', true); | ||||
| this._node.setAttribute('aria-expanded', 'true'); | this._node.setAttribute('aria-expanded', 'true'); | ||||
| } | |||||
| // Try to highlight the first link in the menu for assistive technologies. | // Try to highlight the first link in the menu for assistive technologies. | ||||
| if (!this.getDisableAutofocus()) { | |||||
| var links = JX.DOM.scry(this._menu, 'a'); | var links = JX.DOM.scry(this._menu, 'a'); | ||||
| if (links[0]) { | if (links[0]) { | ||||
| JX.DOM.focus(links[0]); | JX.DOM.focus(links[0]); | ||||
| } | } | ||||
| } | |||||
| }, | }, | ||||
| _hide : function() { | _hide : function() { | ||||
| this._visible = false; | |||||
| JX.DOM.remove(this._menu); | JX.DOM.remove(this._menu); | ||||
| if (this._node) { | |||||
| JX.DOM.alterClass(this._node, 'phuix-dropdown-open', false); | JX.DOM.alterClass(this._node, 'phuix-dropdown-open', false); | ||||
| this._node.setAttribute('aria-expanded', 'false'); | this._node.setAttribute('aria-expanded', 'false'); | ||||
| } | |||||
| }, | }, | ||||
| _adjustposition : function() { | _adjustposition : function() { | ||||
| if (!this._open) { | if (!this._open) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (this._position) { | |||||
| this._setMenuNodePosition(this._position); | |||||
| return; | |||||
| } | |||||
| if (!this._node) { | |||||
| return; | |||||
| } | |||||
| var m = JX.Vector.getDim(this._menu); | var m = JX.Vector.getDim(this._menu); | ||||
| var v = JX.$V(this._node); | var v = JX.$V(this._node); | ||||
| var d = JX.Vector.getDim(this._node); | var d = JX.Vector.getDim(this._node); | ||||
| var alignments = ['right', 'left']; | var alignments = ['right', 'left']; | ||||
| var disallow = {}; | var disallow = {}; | ||||
| var margin = 8; | var margin = 8; | ||||
| Show All 27 Lines | _adjustposition : function() { | ||||
| v = v.add(d) | v = v.add(d) | ||||
| .add(JX.$V(-m.x, 0)); | .add(JX.$V(-m.x, 0)); | ||||
| break; | break; | ||||
| default: | default: | ||||
| v = v.add(0, d.y); | v = v.add(0, d.y); | ||||
| break; | break; | ||||
| } | } | ||||
| v = v.add(this.getOffsetX(), this.getOffsetY()); | this._setMenuNodePosition(v); | ||||
| }, | |||||
| _setMenuNodePosition: function(v) { | |||||
| v = v.add(this.getOffsetX(), this.getOffsetY()); | |||||
| v.setPos(this._menu); | v.setPos(this._menu); | ||||
| }, | }, | ||||
| getMenuNodeDimensions: function() { | |||||
| if (!this._visible) { | |||||
| document.body.appendChild(this._menu); | |||||
| } | |||||
| var dim = JX.Vector.getDim(this._menu); | |||||
| if (!this._visible) { | |||||
| JX.DOM.remove(this._menu); | |||||
| } | |||||
| return dim; | |||||
| }, | |||||
| _onkey: function(e) { | _onkey: function(e) { | ||||
| // When the user presses escape with a menu open, close the menu and | // When the user presses escape with a menu open, close the menu and | ||||
| // refocus the button which activates the menu. In particular, this makes | // refocus the button which activates the menu. In particular, this makes | ||||
| // popups more usable with assistive technologies. | // popups more usable with assistive technologies. | ||||
| if (!this._open) { | if (!this._open) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (e.getSpecialKey() != 'esc') { | if (e.getSpecialKey() != 'esc') { | ||||
| return; | return; | ||||
| } | } | ||||
| this.close(); | this.close(); | ||||
| if (this._node) { | |||||
| JX.DOM.focus(this._node); | JX.DOM.focus(this._node); | ||||
| } | |||||
| e.prevent(); | e.prevent(); | ||||
| } | } | ||||
| } | } | ||||
| }); | }); | ||||