jQuery EasyUI 插件-macmenu源码js


/**
 * jQuery EasyUI 1.4
 *
 * Copyright (c) 2009-2014 www.jeasyui.com. All rights reserved.
 *
 * Licensed under the GPL license: http://www.gnu.org/licenses/gpl.txt
 * To use it on other terms please contact us at [email protected]
 *
 */
/**
 * macmenu - jQuery EasyUI
 *
 */
(function($, window, document){
	//dom原生属性,例如id, disabled和onclick事件等与data-options属性冲突时以data-options属性
	var xtype = baseMenuCls = 'macmenu', baseItemCls = 'menuitem';
	function onItemEvent(item){
		var itemOpts = item.data(baseItemCls).options;
		if (itemOpts.disabled || item.hasClass('menudisabled')) return item;
		return item.data(baseItemCls).subMenu ? onItemHover(item) : onItemClick(item);

		function onItemHover(item){
			return item.hover(function() {
				if (itemOpts.disabled || item.hasClass('menudisabled')) return;
				// item.data(baseItemCls) = {options:{...}, subMenu: jquery对象包含一个ul}
				//返回subMenu
				var subMenu = item.data(baseItemCls).subMenu;
				// 如果没有baseMenuCls的class,说明subMenu没render
				if (!subMenu.hasClass(baseMenuCls)) {
					subMenu = renderMenu(subMenu.appendTo(item));
				}
				//不是最顶级菜单, topmacmenu没有任何样式
				if (!subMenu.hasClass('topmenu')) {
					var parentItem = subMenu.parent('li.' + baseItemCls),//subMenu对应的父节点:li.menuitem
						left = parentItem.offset().left + parentItem.outerWidth(),//父节点:li.menuitem的相对文档的X坐标和父节点:li.menuitem的宽度之和
						top = parentItem.offset().top + parentItem.outerHeight(),
						pos = {};
					if (left + subMenu.outerWidth() > $(window)._outerWidth() + $(document)._scrollLeft()) {
						pos.right = '100%';
						pos.left = 'auto'
					} else {
						pos.left = '100%';
						pos.right = 'auto'
					}
					if (top + subMenu.outerHeight() > $(window)._outerHeight() + $(document).scrollTop()) {
						pos.bottom = '5px';
						pos.top = 'auto'
					} else {
						pos.top = '-5px';
						pos.bottom = 'auto'
					}
					subMenu.css(pos).show();
				}
			}, function() {
				if (itemOpts.disabled || item.hasClass('menudisabled')) return;
				item.data(baseItemCls).subMenu.hide()
			})
		}
		function onItemClick(item){
			//触发onclick事件,dom的onclick被覆盖
			// 
  • New
  • 只执行fn2 if (itemOpts.onClick){ item[0].onclick = null; //在纯js模式下itemOpts.onClick或itemOpts.onClick.fn是经过$.parser.splitOptions处理过的string if (typeof itemOpts.onClick === 'string') itemOpts.onClick = eval('(' + itemOpts.onClick + ')'); if (itemOpts.onClick.fn && typeof itemOpts.onClick.fn === 'string') itemOpts.onClick.fn = eval('(' + itemOpts.onClick.fn + ')'); } return item.off('click').on('click', function(e) { if (itemOpts.disabled || item.hasClass('menudisabled')) return item; //触发onclick事件,dom的onclick被覆盖 //
  • New
  • 只执行fn2 if (itemOpts.onClick){ if (typeof itemOpts.onClick === 'function'){ itemOpts.onClick.apply($(this)); }else if (typeof itemOpts.onClick === 'object' && typeof itemOpts.onClick.fn === 'function'){ var scope = $($.trim(itemOpts.onClick.scope).indexOf('#') === 0 ? $.trim(itemOpts.onClick.scope) : '#' + $.trim(itemOpts.onClick.scope)) || $(this), fn = itemOpts.onClick.fn, args = itemOpts.onClick.args || [], single = !!itemOpts.onClick.single || false; fn.apply(scope, args); if (single){ delete itemOpts.onClick; } } } // 隐藏topmenu $(this).parents('ul.topmenu').hide(); //若果item有href属性,再跳转页面 var href = itemOpts.href; if (href && typeof href === 'string'){ //href是否以http:开头 if (/^http\:/i.test(href)){ location.href = href; }else{ location.href = location.href.substring(0, location.href.indexOf('\/')) + href; } } }); } }; function setDisabled(item, disabled){ if (!item.hasClass(baseItemCls)){return} var itemEl = item[0], itemOpts = item.data(baseItemCls).options; if (disabled){ item.addClass('menudisabled'); itemOpts.disabled = disabled; if (itemEl.onclick){ itemEl.onclick1 = itemEl.onclick; itemEl.onclick = null; } }else{ item.removeClass('menudisabled'); delete itemOpts.disabled; if (itemEl.onclick1){ itemEl.onclick = itemEl.onclick1; itemEl.onclick1 = null; } } return item; }; function setHidden(item, hidden){ if (!item.hasClass(baseItemCls)){return} var itemOpts = item.data(baseItemCls).options; if (hidden){ item.hide(); itemOpts.hidden = hidden; }else{ item.show(); delete itemOpts.hidden; } return item; }; function getItems(theMenu, subMenu){ return subMenu ? theMenu.find('li.' + baseItemCls) : theMenu.children('li.' + baseItemCls); }; function len(theMenu, subMenu){ return getItems(theMenu, subMenu).length; }; function getItemByIndex(theMenu, index){ var itemCount = len(theMenu); return $(theMenu.children('li.' + baseItemCls).eq((Math.abs(index || 0) < itemCount) ? index : itemCount - 1)); }; function onMenuEvent(theMenu){ if (!theMenu.hasClass('topmenu')) return theMenu; var state = theMenu.data(baseMenuCls), options = state.options; return theMenu.off('mouseenter').on('mouseenter', function(){ if (state.timer){ clearTimeout(state.timer); state.timer = null; } }).off('mouseleave').on('mouseleave', function(){ if (options.hideOnUnhover){ theMenu.data('timer', setTimeout(function(){ theMenu.hide(); }, options.duration)); } }); }; function setIcon(item, iconCls){ if (!iconCls || typeof iconCls !== 'string') return item; item.children('span.itemicon').remove(); return item.prepend($('').addClass(iconCls)); }; function setHtml(item, html){ if (!html || typeof html !== 'string') return item; var itemText = item.children('span.itemtext').eq(0); if (itemText.length){ itemText.html(html); }else{ $('').html(html).appendTo(item); } return item; }; function renderItem(item){ var subMenu = null, state = item.data(baseItemCls) || {}, itemOpts = $.extend({}, $.parser.parseOptions(item[0], ['name', 'iconCls', 'href', { separator: 'boolean' }]), { disabled: (item.attr('disabled') ? true : undefined) }); //用于动态添加item //renderItem($('
  • ').data(baseItemCls, {options: args})) if (state && state.options){ itemOpts = $.extend(state.options, itemOpts); }else{ $.extend(state, {options: itemOpts}); item.data(baseItemCls, state); } if (itemOpts.separator) { item.addClass('divider'); } if (!item.hasClass('divider')){ if (itemOpts.id && typeof itemOpts.id === 'string'){ item.attr('id', itemOpts.id); }else{ if (item.attr('id')) itemOpts.id = item.attr('id'); } if (itemOpts.name && typeof itemOpts.name === 'string'){ item.attr('name', itemOpts.name); }else{ if (item.attr('name')) itemOpts.name = item.attr('name'); } if (itemOpts.href && typeof itemOpts.href === 'string'){ item.attr('href', itemOpts.href); }else{ if (item.attr('href')) itemOpts.href = item.attr('href'); } item.children('ul').each(function(index) { if (index === 0){ subMenu = $(this); $.extend(state, {subMenu: subMenu}); } $(this).remove(); }); itemOpts.html = $.trim(itemOpts.html || itemOpts.text || item.html()); item.empty().addClass(baseItemCls).append(setHtml(item, itemOpts.html)); setIcon(item, itemOpts.iconCls); if (itemOpts.disabled) { setDisabled(item, true); } if (subMenu) { $('').appendTo(item); renderMenu(subMenu.appendTo(item)); } onItemEvent(item); } return item; }; function renderMenu(theMenu) { if (!theMenu.hasClass('topmenu')) { theMenu.data(baseMenuCls, { options: $.extend({}, $.fn[xtype].defaults, $.fn[xtype].parseOptions(theMenu[0])) }); } var options = theMenu.data(baseMenuCls).options; if (options.content){ theMenu.addClass('contentmenu'); } if (!theMenu.hasClass('contentmenu')){ theMenu.addClass(baseMenuCls).children('li').each(function(index) { renderItem($(this)); }); } if (options.width){ theMenu.css({'width': typeof options.width == 'string' ? options.width : options.width + 'px'}); } if (options.minWidth){ theMenu.css({'min-width': typeof options.minWidth == 'string' ? options.minWidth : options.minWidth + 'px'}); } if (options.maxWidth){ theMenu.css({'max-width': typeof options.maxWidth == 'string' ? options.maxWidth : options.maxWidth + 'px'}); } return onMenuEvent(theMenu).css({'z-index': $.fn[xtype].defaults.zIndex++}); }; function init(target){ if (!$(target).parents('ul.topmenu').length) $(target).addClass('topmenu'); var options = $(target).data(baseMenuCls).options; $(document).off('.topmenu').on('mousedown.topmenu', function(e){ var m = $(e.target).closest('ul.topmenu,div.combo-p'); if (m.length){return} if ($('ul.topmenu:visible').length) hide($('ul.topmenu:visible')[0]); }); setPosition(renderMenu($(target)),{ left: options.left, top: options.top }); if (options.autoShow) show($(target)); }; function setPosition(theMenu, pos){ var options = theMenu.data(baseMenuCls).options; if (pos) $.extend(options, pos); var left = options.left, top = options.top, at = options.alignTo && options.alignTo.indexOf('#') === 0 ? $(options.alignTo).eq(0) : $('#' + options.alignTo).eq(0), align = options.align.toLowerCase(); if (at.length){ left = at.offset().left; top = at.offset().top + at._outerHeight(); if (align === 'right'){ left += at.outerWidth() - theMenu.outerWidth(); } theMenu.addClass('align'); }else{ theMenu.removeClass('align'); } if (left + theMenu.outerWidth() > $(window)._outerWidth() + $(document)._scrollLeft()){ left = $(window)._outerWidth() + $(document).scrollLeft() - theMenu.outerWidth() - 15; } if (top + theMenu.outerHeight() > $(window)._outerHeight() + $(document).scrollTop()){ if (at.length){ top = $(at).offset().top - theMenu._outerHeight(); }else{ top = $(window)._outerHeight() + $(document).scrollTop() - theMenu.outerHeight() - 10; } } var position = { left: left < 0 ? 0 : left, top: top < 0 ? 0 : top }; $.extend(options, position); return theMenu.css(position); }; function cb(menu, eventName){ var options = menu.data(baseMenuCls).options, cb = options[$.trim(eventName)]; if (!cb && ['onBeforeShow', 'onBeforeHide'].indexOf($.trim(eventName)) > -1) return true; if (typeof cb === 'function'){ return cb.apply(menu, menu); }else if (typeof cb === 'object'){ var scope = cb.scope && cb.scope.indexOf('#') === 0 ? $(cb.scope).eq(0) : $('#' + cb.scope).eq(0) || menu, single = cb.single || false, args = cb.args || [], fn = cb.fn || function(){}, val = fn.apply(scope, args); if (single) delete options[$.trim(eventName)]; return val; } } function show(menuEl, pos){ var menu = $(menuEl); if(pos && typeof pos === 'object') setPosition(menu, pos); if (cb(menu, 'onBeforeShow')){ menu.show(); cb(menu, 'onShow'); } return menu; }; function hide(menuEl){ var menu = $(menuEl); if (cb(menu, 'onBeforeHide')){ menu.hide(); cb(menu, 'onHide'); } return menu; }; function setAlignTo(theMenu, alignTo, align){ if (!theMenu || !alignTo || typeof alignTo !== 'string') return theMenu; var options = theMenu.data(baseMenuCls).options; $.extend(options, { alignTo: alignTo, align: align }); setPosition(theMenu); } $(window).off('.' + baseMenuCls).on('resize.' + baseMenuCls, function() { $('ul.topmenu.' + baseMenuCls).each(function(){ setPosition($(this)); }); }); function createDom(){ return $('
      '); }; $[xtype] = function(options, autoRender){ if (!options || !typeof options === 'object' || $.isEmptyObject(options)) return; var appendTo = typeof options.appendTo === 'string' ? (options.appendTo.indexOf('#') === 0 ? $(options.appendTo) : $('#' + options.appendTo)) : $('body'); target = createDom().attr('id', options.id || '').appendTo(appendTo); $.parser.splitOptions(target, options); function appendItems(items, parent){ if (!items || !Array.isArray(items)) return parent; for(var i = 0; i < items.length; i++){ if (items[i] == '-') items[i] = {separator: true}; var item = $('
    • ').attr('id', items[i].id || '').appendTo(parent); item = $.parser.splitOptions(item, items[i]); if (items[i].menu){ var subMenuOpts = items[i].menu, subMenuItems = subMenuOpts.items, subMenu = $.parser.splitOptions(createDom().appendTo(item), subMenuOpts); appendItems(subMenuItems, subMenu); } } return parent; } var t = appendItems(options.items || null, target); return !autoRender ? t : t[xtype](options); }; $.fn[xtype] = function(options){ if (typeof options == 'string'){ var args = Array.prototype.slice.call(arguments, 1); return $.fn[xtype].methods[options].apply(this, args); } options = options || {}; return this.each(function(){ var state = $.data(this, baseMenuCls); if (state){ $.extend(state.options, options); } else { state = $.data(this, baseMenuCls, { options: $.extend({}, $.fn[xtype].defaults, $.fn[xtype].parseOptions(this), options) }); init(this); } }); }; $.fn[xtype].methods = { options: function(){ return $.data(this[0], baseMenuCls).options; }, show: function(pos){ return this.each(function(){ show(this, pos); }); }, hide: function(){ return this.each(function(){ hide(this); }); }, destroy: function(){ return this.each(function(){ $(this).remove(); }); }, alignTo: function(alignTo, align){ return this.each(function(){ setAlignTo($(this), alignTo, align || 'left'); }); }, //subMenu默认为false直接菜单项 //subMenu为true所有菜单项 getItems: function(subMenu){ return getItems(this, subMenu); }, //subMenu默认为false直接菜单项的数量 //subMenu为true所有菜单项的数量 //$('#mm').macmenu('itemCount') len: function(subMenu){ return len(this, subMenu); }, //根据索引值返回菜单项,从0开始计数,不包括子菜单 //$('#mm').macmenu('getItemByIndex', 3)--返回第4个菜单项 //$('#mm').macmenu('getItemByIndex', -3)--返回倒数第4个菜单项 //如果index超出范围,返回最后1个菜单项 $('#mm').macmenu('getItemByIndex', -99999)--返回最后1个菜单项 getItemByIndex: function(index){ return getItemByIndex(this, index); }, getItemOption: function(item){ return !item[0] ? null : $.extend({}, item.data(baseItemCls).options); }, getSubMenu: function(item){ return !item[0] ? null : item.children('ul.' + baseMenuCls); }, //返回菜单项的索引值,从0开始计数 indexOf: function(item){ return !item[0] ? -1 : this.children('li.' + baseItemCls).index(item); }, //返回包含所有菜单项的DOM元素数组 toArray: function(subMenu){ return subMenu ? this.find('li.' + baseItemCls).toArray() : this.children('li.' + baseItemCls).toArray(); }, findItem: function(text, subMenu){ var items = []; if (!text || !$.trim(text).length) return items; getItems(this, subMenu).each(function(){ var itemText = $.trim($(this).children('span.itemtext').eq(0).text()).toLowerCase(); if (itemText.indexOf($.trim(text).toLowerCase()) >= 0){ items.push($(this)); } }); return items; }, setHtml: function(item, html){ return setHtml(item, html); }, setIcon: function(item, iconCls){ return setIcon(item, iconCls); }, insertItem: function(args, index){ if (index < 0) return this[xtype].methods.prependItem.call(this, args); if (index >= len(this)) return this[xtype].methods.appendItem.call(this, args); var theItem = renderItem($('
    • ').data(baseItemCls, {options: args})); var prevItem = getItemByIndex(this, index); prevItem.length ? theItem.insertBefore(prevItem) : theItem.appendTo(this); return theItem; }, prependItem: function(args){ var theItem = renderItem($('
    • ').data(baseItemCls, {options: args})); theItem.prependTo(this); return theItem; }, appendItem: function(args){ var theItem = renderItem($('
    • ').data(baseItemCls, {options: args})); theItem.appendTo(this); return theItem; }, removeItem: function(item){ return item.remove(); }, enableItem: function(item){ return setDisabled(item, false); }, disableItem: function(item){ return setDisabled(item, true); }, showItem: function(item){ return setHidden(item, false); }, hideItem: function(item){ return setHidden(item, true); } }; $.fn[xtype].parseOptions = function(target){ return $.extend({}, $.parser.parseOptions(target, [{minWidth:'number',duration:'number',hideOnUnhover:'boolean'}])); }; $.fn[xtype].defaults = { zIndex:110000, left: 0, top: 0, alignTo: null, align: 'left', autoShow: false, content: false, minWidth: 100, maxWidth: 400, duration: 100, // Defines duration time in milliseconds to hide when the mouse leaves the macmenu. hideOnUnhover: false, // Automatically hides the macmenu when mouse exits it // 事件定义有两种方法 // 一是简单的定义函数:onBeforeShow: function(){}, // 二是定义一个对象,包含4个属性: // scope指定事件执行的上下文语境 // fn事件的函数体 // args数组包含传递给fn的所有参数 // single布尔值,如为true只执行一次 onBeforeShow: function(){return true;},//只有返回值为true,才会show onShow: function(){}, onBeforeHide: function(){return true;},//只有返回值为true,才会hide onHide: function(){} }; })($ || jQuery || window.jQuery, window, document);




      你可能感兴趣的:(easyui,Jquery,javascript,jquery,menu,源码,easyui)