[76] | 1 | /*! |
---|
| 2 | * Ext JS Library 3.4.0 |
---|
| 3 | * Copyright(c) 2006-2011 Sencha Inc. |
---|
| 4 | * licensing@sencha.com |
---|
| 5 | * http://www.sencha.com/license |
---|
| 6 | */ |
---|
| 7 | /* |
---|
| 8 | * Ext Core Library Examples 3.0 Beta |
---|
| 9 | * http://extjs.com/ |
---|
| 10 | * Copyright(c) 2006-2009, Ext JS, LLC. |
---|
| 11 | * |
---|
| 12 | * The MIT License |
---|
| 13 | * |
---|
| 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
---|
| 15 | * of this software and associated documentation files (the "Software"), to deal |
---|
| 16 | * in the Software without restriction, including without limitation the rights |
---|
| 17 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
---|
| 18 | * copies of the Software, and to permit persons to whom the Software is |
---|
| 19 | * furnished to do so, subject to the following conditions: |
---|
| 20 | * |
---|
| 21 | * The above copyright notice and this permission notice shall be included in |
---|
| 22 | * all copies or substantial portions of the Software. |
---|
| 23 | * |
---|
| 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
| 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
---|
| 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
---|
| 27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
---|
| 28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
---|
| 29 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
---|
| 30 | * THE SOFTWARE. |
---|
| 31 | * |
---|
| 32 | */ |
---|
| 33 | |
---|
| 34 | Ext.ns('Ext.ux'); |
---|
| 35 | |
---|
| 36 | Ext.ux.Menu = Ext.extend(Ext.util.Observable, { |
---|
| 37 | direction: 'horizontal', |
---|
| 38 | delay: 0.2, |
---|
| 39 | autoWidth: true, |
---|
| 40 | transitionType: 'fade', |
---|
| 41 | transitionDuration: 0.3, |
---|
| 42 | animate: true, |
---|
| 43 | currentClass: 'current', |
---|
| 44 | |
---|
| 45 | constructor: function(elId, config) { |
---|
| 46 | config = config || {}; |
---|
| 47 | Ext.apply(this, config); |
---|
| 48 | |
---|
| 49 | Ext.ux.Menu.superclass.constructor.call(this, config); |
---|
| 50 | |
---|
| 51 | this.addEvents( |
---|
| 52 | 'show', |
---|
| 53 | 'hide', |
---|
| 54 | 'click' |
---|
| 55 | ); |
---|
| 56 | |
---|
| 57 | this.el = Ext.get(elId); |
---|
| 58 | |
---|
| 59 | this.initMarkup(); |
---|
| 60 | this.initEvents(); |
---|
| 61 | |
---|
| 62 | this.setCurrent(); |
---|
| 63 | }, |
---|
| 64 | |
---|
| 65 | initMarkup: function(){ |
---|
| 66 | this.container = this.el.wrap({cls: 'ux-menu-container', style: 'z-index: ' + --Ext.ux.Menu.zSeed}); |
---|
| 67 | this.items = this.el.select('li'); |
---|
| 68 | |
---|
| 69 | this.el.addClass('ux-menu ux-menu-' + this.direction); |
---|
| 70 | this.el.select('>li').addClass('ux-menu-item-main'); |
---|
| 71 | |
---|
| 72 | this.el.select('li:has(>ul)').addClass('ux-menu-item-parent').each(function(item) { |
---|
| 73 | item.down('a') |
---|
| 74 | .addClass('ux-menu-link-parent') |
---|
| 75 | .createChild({tag: 'span', cls: 'ux-menu-arrow'}); |
---|
| 76 | }); |
---|
| 77 | |
---|
| 78 | this.el.select('li:first-child>a').addClass('ux-menu-link-first'); |
---|
| 79 | this.el.select('li:last-child>a').addClass('ux-menu-link-last'); |
---|
| 80 | |
---|
| 81 | // create clear fixes for the floating stuff |
---|
| 82 | this.container.addClass('ux-menu-clearfix'); |
---|
| 83 | |
---|
| 84 | // if autoWidth make every submenu as wide as its biggest child; |
---|
| 85 | if(this.autoWidth) { |
---|
| 86 | this.doAutoWidth(); |
---|
| 87 | } |
---|
| 88 | |
---|
| 89 | var subs = this.el.select('ul'); |
---|
| 90 | subs.addClass('ux-menu-sub'); |
---|
| 91 | |
---|
| 92 | //ie6 and ie7/ie8 quirksmode need iframes behind the submenus |
---|
| 93 | if(Ext.isBorderBox || Ext.isIE7) { |
---|
| 94 | subs.each(function(item) { |
---|
| 95 | item.parent().createChild({tag: 'iframe', cls: 'ux-menu-ie-iframe'}) |
---|
| 96 | .setWidth(item.getWidth()) |
---|
| 97 | .setHeight(item.getHeight()); |
---|
| 98 | }); |
---|
| 99 | } |
---|
| 100 | |
---|
| 101 | subs.addClass('ux-menu-hidden'); |
---|
| 102 | }, |
---|
| 103 | |
---|
| 104 | initEvents: function() { |
---|
| 105 | this.showTask = new Ext.util.DelayedTask(this.showMenu, this); |
---|
| 106 | this.hideTask = new Ext.util.DelayedTask(function() { |
---|
| 107 | this.showTask.cancel(); |
---|
| 108 | this.hideAll(); |
---|
| 109 | this.fireEvent('hide'); |
---|
| 110 | }, this); |
---|
| 111 | |
---|
| 112 | this.el.hover(function() { |
---|
| 113 | this.hideTask.cancel(); |
---|
| 114 | }, function() { |
---|
| 115 | this.hideTask.delay(this.delay*1000); |
---|
| 116 | }, this); |
---|
| 117 | |
---|
| 118 | // for each item that has a submenu, create a mouseenter function that shows its submenu |
---|
| 119 | // delay 5 to make sure enter is fired after mouseover |
---|
| 120 | this.el.select('li.ux-menu-item-parent').on('mouseenter', this.onParentEnter, false, {me: this, delay: 5}); |
---|
| 121 | |
---|
| 122 | // listen for mouseover events on items to hide other items submenus and remove hovers |
---|
| 123 | this.el.on('mouseover', function(ev, t) { |
---|
| 124 | this.manageSiblings(t); |
---|
| 125 | // if this item does not have a submenu, the showMenu task for a sibling could potentially still be fired, so cancel it |
---|
| 126 | if(!Ext.fly(t).hasClass('ux-menu-item-parent')) { |
---|
| 127 | this.showTask.cancel(); |
---|
| 128 | } |
---|
| 129 | }, this, {delegate: 'li'}); |
---|
| 130 | |
---|
| 131 | this.el.on('click', function(ev, t) { |
---|
| 132 | return this.fireEvent('click', ev, t, this); |
---|
| 133 | }, this, {delegate: 'a'}) |
---|
| 134 | }, |
---|
| 135 | |
---|
| 136 | onParentEnter: function(ev, link, o) { |
---|
| 137 | var item = Ext.get(this), |
---|
| 138 | me = o.me; |
---|
| 139 | |
---|
| 140 | // if this item is in a submenu and contains a submenu, check if the submenu is not still animating |
---|
| 141 | if(!item.hasClass('ux-menu-item-main') && item.parent('ul').hasActiveFx()) { |
---|
| 142 | item.parent('ul').stopFx(true); |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | // if submenu is already shown dont do anything |
---|
| 146 | if(!item.child('ul').hasClass('ux-menu-hidden')) { |
---|
| 147 | return; |
---|
| 148 | } |
---|
| 149 | |
---|
| 150 | me.showTask.delay(me.delay*1000, false, false, [item]); |
---|
| 151 | }, |
---|
| 152 | |
---|
| 153 | showMenu : function(item) { |
---|
| 154 | var menu = item.child('ul'), |
---|
| 155 | x = y = 0; |
---|
| 156 | |
---|
| 157 | item.select('>a').addClass('ux-menu-link-hover'); |
---|
| 158 | |
---|
| 159 | // some different configurations require different positioning |
---|
| 160 | if(this.direction == 'horizontal' && item.hasClass('ux-menu-item-main')) { |
---|
| 161 | y = item.getHeight()+1; |
---|
| 162 | } |
---|
| 163 | else { |
---|
| 164 | x = item.getWidth()+1; |
---|
| 165 | } |
---|
| 166 | |
---|
| 167 | // if its ie, force a repaint of the submenu |
---|
| 168 | if(Ext.isIE) { |
---|
| 169 | menu.select('ul').addClass('ux-menu-hidden'); |
---|
| 170 | // ie bugs... |
---|
| 171 | if(Ext.isBorderBox || Ext.isIE7) { |
---|
| 172 | item.down('iframe').setStyle({left: x + 'px', top: y + 'px', display: 'block'}); |
---|
| 173 | } |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | menu.setStyle({left: x + 'px', top: y + 'px'}).removeClass('ux-menu-hidden'); |
---|
| 177 | |
---|
| 178 | if(this.animate) { |
---|
| 179 | switch(this.transitionType) { |
---|
| 180 | case 'slide': |
---|
| 181 | if(this.direction == 'horizontal' && item.hasClass('ux-menu-item-main')) { |
---|
| 182 | menu.slideIn('t', { |
---|
| 183 | duration: this.transitionDuration |
---|
| 184 | }); |
---|
| 185 | } |
---|
| 186 | else { |
---|
| 187 | menu.slideIn('l', { |
---|
| 188 | duration: this.transitionDuration |
---|
| 189 | }); |
---|
| 190 | } |
---|
| 191 | break; |
---|
| 192 | |
---|
| 193 | default: |
---|
| 194 | menu.setOpacity(0.001).fadeIn({ |
---|
| 195 | duration: this.transitionDuration |
---|
| 196 | }); |
---|
| 197 | break |
---|
| 198 | } |
---|
| 199 | } |
---|
| 200 | |
---|
| 201 | this.fireEvent('show', item, menu, this); |
---|
| 202 | }, |
---|
| 203 | |
---|
| 204 | manageSiblings: function(item) { |
---|
| 205 | var item = Ext.get(item); |
---|
| 206 | item.parent().select('li.ux-menu-item-parent').each(function(child) { |
---|
| 207 | if(child.dom.id !== item.dom.id) { |
---|
| 208 | child.select('>a').removeClass('ux-menu-link-hover'); |
---|
| 209 | child.select('ul').stopFx(false).addClass('ux-menu-hidden'); |
---|
| 210 | if (Ext.isBorderBox || Ext.isIE7) { |
---|
| 211 | child.select('iframe').setStyle('display', 'none'); |
---|
| 212 | } |
---|
| 213 | } |
---|
| 214 | }); |
---|
| 215 | }, |
---|
| 216 | |
---|
| 217 | hideAll: function() { |
---|
| 218 | this.manageSiblings(this.el); |
---|
| 219 | }, |
---|
| 220 | |
---|
| 221 | setCurrent: function() { |
---|
| 222 | var els = this.el.query('.' + this.currentClass); |
---|
| 223 | if(!els.length) { |
---|
| 224 | return; |
---|
| 225 | } |
---|
| 226 | var item = Ext.get(els[els.length-1]).removeClass(this.currentClass).findParent('li', null, true); |
---|
| 227 | while(item && item.parent('.ux-menu')) { |
---|
| 228 | item.down('a').addClass(this.currentClass); |
---|
| 229 | item = item.parent('li'); |
---|
| 230 | } |
---|
| 231 | }, |
---|
| 232 | |
---|
| 233 | doAutoWidth: function() { |
---|
| 234 | var fixWidth = function(sub) { |
---|
| 235 | var widest = 0; |
---|
| 236 | var items = sub.select('>li'); |
---|
| 237 | |
---|
| 238 | sub.setStyle({width: 3000 + 'px'}); |
---|
| 239 | items.each(function(item) { |
---|
| 240 | widest = Math.max(widest, item.getWidth()); |
---|
| 241 | }); |
---|
| 242 | |
---|
| 243 | widest = Ext.isIE ? widest + 1 : widest; |
---|
| 244 | items.setWidth(widest + 'px'); |
---|
| 245 | sub.setWidth(widest + 'px'); |
---|
| 246 | } |
---|
| 247 | |
---|
| 248 | if(this.direction == 'vertical') { |
---|
| 249 | this.container.select('ul').each(fixWidth); |
---|
| 250 | } |
---|
| 251 | else { |
---|
| 252 | this.el.select('ul').each(fixWidth); |
---|
| 253 | } |
---|
| 254 | |
---|
| 255 | } |
---|
| 256 | }); |
---|
| 257 | |
---|
| 258 | Ext.ux.Menu.zSeed = 10000; |
---|