/**
* 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);