3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4 <title>The source code</title>
5 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <body onload="prettyPrint();">
9 <pre class="prettyprint lang-js">/*!
10 * Ext JS Library 3.3.1
11 * Copyright(c) 2006-2010 Sencha Inc.
12 * licensing@sencha.com
13 * http://www.sencha.com/license
16 * Ext Core Library Examples 3.0 Beta
18 * Copyright(c) 2006-2009, Ext JS, LLC.
22 * Permission is hereby granted, free of charge, to any person obtaining a copy
23 * of this software and associated documentation files (the "Software"), to deal
24 * in the Software without restriction, including without limitation the rights
25 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26 * copies of the Software, and to permit persons to whom the Software is
27 * furnished to do so, subject to the following conditions:
29 * The above copyright notice and this permission notice shall be included in
30 * all copies or substantial portions of the Software.
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44 Ext.ux.Menu = Ext.extend(Ext.util.Observable, {
45 direction: 'horizontal',
48 transitionType: 'fade',
49 transitionDuration: 0.3,
51 currentClass: 'current',
53 constructor: function(elId, config) {
54 config = config || {};
55 Ext.apply(this, config);
57 Ext.ux.Menu.superclass.constructor.call(this, config);
65 this.el = Ext.get(elId);
73 initMarkup: function(){
74 this.container = this.el.wrap({cls: 'ux-menu-container', style: 'z-index: ' + --Ext.ux.Menu.zSeed});
75 this.items = this.el.select('li');
77 this.el.addClass('ux-menu ux-menu-' + this.direction);
78 this.el.select('>li').addClass('ux-menu-item-main');
80 this.el.select('li:has(>ul)').addClass('ux-menu-item-parent').each(function(item) {
82 .addClass('ux-menu-link-parent')
83 .createChild({tag: 'span', cls: 'ux-menu-arrow'});
86 this.el.select('li:first-child>a').addClass('ux-menu-link-first');
87 this.el.select('li:last-child>a').addClass('ux-menu-link-last');
89 // create clear fixes for the floating stuff
90 this.container.addClass('ux-menu-clearfix');
92 // if autoWidth make every submenu as wide as its biggest child;
97 var subs = this.el.select('ul');
98 subs.addClass('ux-menu-sub');
100 //ie6 and ie7/ie8 quirksmode need iframes behind the submenus
101 if(Ext.isBorderBox || Ext.isIE7) {
102 subs.each(function(item) {
103 item.parent().createChild({tag: 'iframe', cls: 'ux-menu-ie-iframe'})
104 .setWidth(item.getWidth())
105 .setHeight(item.getHeight());
109 subs.addClass('ux-menu-hidden');
112 initEvents: function() {
113 this.showTask = new Ext.util.DelayedTask(this.showMenu, this);
114 this.hideTask = new Ext.util.DelayedTask(function() {
115 this.showTask.cancel();
117 this.fireEvent('hide');
120 this.el.hover(function() {
121 this.hideTask.cancel();
123 this.hideTask.delay(this.delay*1000);
126 // for each item that has a submenu, create a mouseenter function that shows its submenu
127 // delay 5 to make sure enter is fired after mouseover
128 this.el.select('li.ux-menu-item-parent').on('mouseenter', this.onParentEnter, false, {me: this, delay: 5});
130 // listen for mouseover events on items to hide other items submenus and remove hovers
131 this.el.on('mouseover', function(ev, t) {
132 this.manageSiblings(t);
133 // if this item does not have a submenu, the showMenu task for a sibling could potentially still be fired, so cancel it
134 if(!Ext.fly(t).hasClass('ux-menu-item-parent')) {
135 this.showTask.cancel();
137 }, this, {delegate: 'li'});
139 this.el.on('click', function(ev, t) {
140 return this.fireEvent('click', ev, t, this);
141 }, this, {delegate: 'a'})
144 onParentEnter: function(ev, link, o) {
145 var item = Ext.get(this),
148 // if this item is in a submenu and contains a submenu, check if the submenu is not still animating
149 if(!item.hasClass('ux-menu-item-main') && item.parent('ul').hasActiveFx()) {
150 item.parent('ul').stopFx(true);
153 // if submenu is already shown dont do anything
154 if(!item.child('ul').hasClass('ux-menu-hidden')) {
158 me.showTask.delay(me.delay*1000, false, false, [item]);
161 showMenu : function(item) {
162 var menu = item.child('ul'),
165 item.select('>a').addClass('ux-menu-link-hover');
167 // some different configurations require different positioning
168 if(this.direction == 'horizontal' && item.hasClass('ux-menu-item-main')) {
169 y = item.getHeight()+1;
172 x = item.getWidth()+1;
175 // if its ie, force a repaint of the submenu
177 menu.select('ul').addClass('ux-menu-hidden');
179 if(Ext.isBorderBox || Ext.isIE7) {
180 item.down('iframe').setStyle({left: x + 'px', top: y + 'px', display: 'block'});
184 menu.setStyle({left: x + 'px', top: y + 'px'}).removeClass('ux-menu-hidden');
187 switch(this.transitionType) {
189 if(this.direction == 'horizontal' && item.hasClass('ux-menu-item-main')) {
191 duration: this.transitionDuration
196 duration: this.transitionDuration
202 menu.setOpacity(0.001).fadeIn({
203 duration: this.transitionDuration
209 this.fireEvent('show', item, menu, this);
212 manageSiblings: function(item) {
213 var item = Ext.get(item);
214 item.parent().select('li.ux-menu-item-parent').each(function(child) {
215 if(child.dom.id !== item.dom.id) {
216 child.select('>a').removeClass('ux-menu-link-hover');
217 child.select('ul').stopFx(false).addClass('ux-menu-hidden');
218 if (Ext.isBorderBox || Ext.isIE7) {
219 child.select('iframe').setStyle('display', 'none');
225 hideAll: function() {
226 this.manageSiblings(this.el);
229 setCurrent: function() {
230 var els = this.el.query('.' + this.currentClass);
234 var item = Ext.get(els[els.length-1]).removeClass(this.currentClass).findParent('li', null, true);
235 while(item && item.parent('.ux-menu')) {
236 item.down('a').addClass(this.currentClass);
237 item = item.parent('li');
241 doAutoWidth: function() {
242 var fixWidth = function(sub) {
244 var items = sub.select('>li');
246 sub.setStyle({width: 3000 + 'px'});
247 items.each(function(item) {
248 widest = Math.max(widest, item.getWidth());
251 widest = Ext.isIE ? widest + 1 : widest;
252 items.setWidth(widest + 'px');
253 sub.setWidth(widest + 'px');
256 if(this.direction == 'vertical') {
257 this.container.select('ul').each(fixWidth);
260 this.el.select('ul').each(fixWidth);
266 Ext.ux.Menu.zSeed = 10000;</pre>