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 info@jeasyui.com
 *
 */
/**
 * 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被覆盖
			// <li οnclick="fn1" data-options="iconCls:'icon-save', onclick: fn2">New</li>只执行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被覆盖
				// <li οnclick="fn1" data-options="iconCls:'icon-save', onclick: fn2">New</li>只执行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($('<span class="itemicon"></span>').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{
			$('<span class="itemtext"></span>').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($('<li></li>').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) {
				$('<span class="itemarrow"></span>').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 $('<ul></ul>');
	};
	$[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 = $('<li></li>').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($('<li></li>').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($('<li></li>').data(baseItemCls, {options: args}));
			theItem.prependTo(this);
			return theItem;
		},
		appendItem: function(args){
			var theItem = renderItem($('<li></li>').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);




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值