--- /dev/null
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>The source code</title>
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
+</head>
+<body onload="prettyPrint();">
+ <pre class="prettyprint lang-js">/*!
+ * Ext JS Library 3.2.0
+ * Copyright(c) 2006-2010 Ext JS, Inc.
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/*
+ * Ext Core Library Examples 3.0 Beta
+ * http://extjs.com/
+ * Copyright(c) 2006-2009, Ext JS, LLC.
+ *
+ * The MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+Ext.ns('Ext.ux');
+
+Ext.ux.Menu = Ext.extend(Ext.util.Observable, {
+ direction: 'horizontal',
+ delay: 0.2,
+ autoWidth: true,
+ transitionType: 'fade',
+ transitionDuration: 0.3,
+ animate: true,
+ currentClass: 'current',
+
+ constructor: function(elId, config) {
+ config = config || {};
+ Ext.apply(this, config);
+
+ Ext.ux.Menu.superclass.constructor.call(this, config);
+
+ this.addEvents(
+ 'show',
+ 'hide',
+ 'click'
+ );
+
+ this.el = Ext.get(elId);
+
+ this.initMarkup();
+ this.initEvents();
+
+ this.setCurrent();
+ },
+
+ initMarkup: function(){
+ this.container = this.el.wrap({cls: 'ux-menu-container', style: 'z-index: ' + --Ext.ux.Menu.zSeed});
+ this.items = this.el.select('li');
+
+ this.el.addClass('ux-menu ux-menu-' + this.direction);
+ this.el.select('>li').addClass('ux-menu-item-main');
+
+ this.el.select('li:has(>ul)').addClass('ux-menu-item-parent').each(function(item) {
+ item.down('a')
+ .addClass('ux-menu-link-parent')
+ .createChild({tag: 'span', cls: 'ux-menu-arrow'});
+ });
+
+ this.el.select('li:first-child>a').addClass('ux-menu-link-first');
+ this.el.select('li:last-child>a').addClass('ux-menu-link-last');
+
+ // create clear fixes for the floating stuff
+ this.container.addClass('ux-menu-clearfix');
+
+ // if autoWidth make every submenu as wide as its biggest child;
+ if(this.autoWidth) {
+ this.doAutoWidth();
+ }
+
+ var subs = this.el.select('ul');
+ subs.addClass('ux-menu-sub');
+
+ //ie6 and ie7/ie8 quirksmode need iframes behind the submenus
+ if(Ext.isBorderBox || Ext.isIE7) {
+ subs.each(function(item) {
+ item.parent().createChild({tag: 'iframe', cls: 'ux-menu-ie-iframe'})
+ .setWidth(item.getWidth())
+ .setHeight(item.getHeight());
+ });
+ }
+
+ subs.addClass('ux-menu-hidden');
+ },
+
+ initEvents: function() {
+ this.showTask = new Ext.util.DelayedTask(this.showMenu, this);
+ this.hideTask = new Ext.util.DelayedTask(function() {
+ this.showTask.cancel();
+ this.hideAll();
+ this.fireEvent('hide');
+ }, this);
+
+ this.el.hover(function() {
+ this.hideTask.cancel();
+ }, function() {
+ this.hideTask.delay(this.delay*1000);
+ }, this);
+
+ // for each item that has a submenu, create a mouseenter function that shows its submenu
+ // delay 5 to make sure enter is fired after mouseover
+ this.el.select('li.ux-menu-item-parent').on('mouseenter', this.onParentEnter, false, {me: this, delay: 5});
+
+ // listen for mouseover events on items to hide other items submenus and remove hovers
+ this.el.on('mouseover', function(ev, t) {
+ this.manageSiblings(t);
+ // if this item does not have a submenu, the showMenu task for a sibling could potentially still be fired, so cancel it
+ if(!Ext.fly(t).hasClass('ux-menu-item-parent')) {
+ this.showTask.cancel();
+ }
+ }, this, {delegate: 'li'});
+
+ this.el.on('click', function(ev, t) {
+ return this.fireEvent('click', ev, t, this);
+ }, this, {delegate: 'a'})
+ },
+
+ onParentEnter: function(ev, link, o) {
+ var item = Ext.get(this),
+ me = o.me;
+
+ // if this item is in a submenu and contains a submenu, check if the submenu is not still animating
+ if(!item.hasClass('ux-menu-item-main') && item.parent('ul').hasActiveFx()) {
+ item.parent('ul').stopFx(true);
+ }
+
+ // if submenu is already shown dont do anything
+ if(!item.child('ul').hasClass('ux-menu-hidden')) {
+ return;
+ }
+
+ me.showTask.delay(me.delay*1000, false, false, [item]);
+ },
+
+ showMenu : function(item) {
+ var menu = item.child('ul'),
+ x = y = 0;
+
+ item.select('>a').addClass('ux-menu-link-hover');
+
+ // some different configurations require different positioning
+ if(this.direction == 'horizontal' && item.hasClass('ux-menu-item-main')) {
+ y = item.getHeight()+1;
+ }
+ else {
+ x = item.getWidth()+1;
+ }
+
+ // if its ie, force a repaint of the submenu
+ if(Ext.isIE) {
+ menu.select('ul').addClass('ux-menu-hidden');
+ // ie bugs...
+ if(Ext.isBorderBox || Ext.isIE7) {
+ item.down('iframe').setStyle({left: x + 'px', top: y + 'px', display: 'block'});
+ }
+ }
+
+ menu.setStyle({left: x + 'px', top: y + 'px'}).removeClass('ux-menu-hidden');
+
+ if(this.animate) {
+ switch(this.transitionType) {
+ case 'slide':
+ if(this.direction == 'horizontal' && item.hasClass('ux-menu-item-main')) {
+ menu.slideIn('t', {
+ duration: this.transitionDuration
+ });
+ }
+ else {
+ menu.slideIn('l', {
+ duration: this.transitionDuration
+ });
+ }
+ break;
+
+ default:
+ menu.setOpacity(0.001).fadeIn({
+ duration: this.transitionDuration
+ });
+ break
+ }
+ }
+
+ this.fireEvent('show', item, menu, this);
+ },
+
+ manageSiblings: function(item) {
+ var item = Ext.get(item);
+ item.parent().select('li.ux-menu-item-parent').each(function(child) {
+ if(child.dom.id !== item.dom.id) {
+ child.select('>a').removeClass('ux-menu-link-hover');
+ child.select('ul').stopFx(false).addClass('ux-menu-hidden');
+ if (Ext.isBorderBox || Ext.isIE7) {
+ child.select('iframe').setStyle('display', 'none');
+ }
+ }
+ });
+ },
+
+ hideAll: function() {
+ this.manageSiblings(this.el);
+ },
+
+ setCurrent: function() {
+ var els = this.el.query('.' + this.currentClass);
+ if(!els.length) {
+ return;
+ }
+ var item = Ext.get(els[els.length-1]).removeClass(this.currentClass).findParent('li', null, true);
+ while(item && item.parent('.ux-menu')) {
+ item.down('a').addClass(this.currentClass);
+ item = item.parent('li');
+ }
+ },
+
+ doAutoWidth: function() {
+ var fixWidth = function(sub) {
+ var widest = 0;
+ var items = sub.select('>li');
+
+ sub.setStyle({width: 3000 + 'px'});
+ items.each(function(item) {
+ widest = Math.max(widest, item.getWidth());
+ });
+
+ widest = Ext.isIE ? widest + 1 : widest;
+ items.setWidth(widest + 'px');
+ sub.setWidth(widest + 'px');
+ }
+
+ if(this.direction == 'vertical') {
+ this.container.select('ul').each(fixWidth);
+ }
+ else {
+ this.el.select('ul').each(fixWidth);
+ }
+
+ }
+});
+
+Ext.ux.Menu.zSeed = 10000;</pre>
+</body>
+</html>
\ No newline at end of file