You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
475 lines
11 KiB
Plaintext
475 lines
11 KiB
Plaintext
11 months ago
|
/**
|
||
|
* menu - jQuery EasyUI
|
||
|
*
|
||
|
* Licensed under the GPL terms
|
||
|
* To use it on other terms please contact us
|
||
|
*
|
||
|
* Copyright(c) 2009-2012 stworthy [ stworthy@gmail.com ]
|
||
|
*/
|
||
|
(function($){
|
||
|
|
||
|
/**
|
||
|
* initialize the target menu, the function can be invoked only once
|
||
|
*/
|
||
|
function init(target){
|
||
|
$(target).appendTo('body');
|
||
|
$(target).addClass('menu-top'); // the top menu
|
||
|
|
||
|
var menus = [];
|
||
|
adjust($(target));
|
||
|
|
||
|
var time = null;
|
||
|
for(var i=0; i<menus.length; i++){
|
||
|
var menu = menus[i];
|
||
|
wrapMenu(menu);
|
||
|
menu.children('div.menu-item').each(function(){
|
||
|
bindMenuItemEvent(target, $(this));
|
||
|
});
|
||
|
|
||
|
menu.bind('mouseenter', function(){
|
||
|
if (time){
|
||
|
clearTimeout(time);
|
||
|
time = null;
|
||
|
}
|
||
|
}).bind('mouseleave', function(){
|
||
|
time = setTimeout(function(){
|
||
|
hideAll(target);
|
||
|
}, 100);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
|
||
|
function adjust(menu){
|
||
|
menus.push(menu);
|
||
|
menu.find('>div').each(function(){
|
||
|
var item = $(this);
|
||
|
var submenu = item.find('>div');
|
||
|
if (submenu.length){
|
||
|
submenu.insertAfter(target);
|
||
|
item[0].submenu = submenu;
|
||
|
adjust(submenu);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* wrap a menu and set it's status to hidden
|
||
|
* the menu not include sub menus
|
||
|
*/
|
||
|
function wrapMenu(menu){
|
||
|
menu.addClass('menu').find('>div').each(function(){
|
||
|
var item = $(this);
|
||
|
if (item.hasClass('menu-sep')){
|
||
|
item.html(' ');
|
||
|
} else {
|
||
|
// the menu item options
|
||
|
var itemOpts = $.extend({}, $.parser.parseOptions(this,['name','iconCls','href']), {
|
||
|
disabled: (item.attr('disabled') ? true : undefined)
|
||
|
});
|
||
|
item.attr('name',itemOpts.name || '').attr('href',itemOpts.href || '');
|
||
|
|
||
|
var text = item.addClass('menu-item').html();
|
||
|
item.empty().append($('<div class="menu-text"></div>').html(text));
|
||
|
|
||
|
if (itemOpts.iconCls){
|
||
|
$('<div class="menu-icon"></div>').addClass(itemOpts.iconCls).appendTo(item);
|
||
|
}
|
||
|
if (itemOpts.disabled){
|
||
|
setDisabled(target, item[0], true);
|
||
|
}
|
||
|
if (item[0].submenu){
|
||
|
$('<div class="menu-rightarrow"></div>').appendTo(item); // has sub menu
|
||
|
}
|
||
|
|
||
|
item._outerHeight(22);
|
||
|
}
|
||
|
});
|
||
|
menu.hide();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* bind menu item event
|
||
|
*/
|
||
|
function bindMenuItemEvent(target, item){
|
||
|
item.unbind('.menu');
|
||
|
item.bind('mousedown.menu', function(){
|
||
|
return false; // skip the mousedown event that has been used for document to hide the menu
|
||
|
}).bind('click.menu', function(){
|
||
|
if ($(this).hasClass('menu-item-disabled')){
|
||
|
return;
|
||
|
}
|
||
|
// only the sub menu clicked can hide all menus
|
||
|
if (!this.submenu){
|
||
|
hideAll(target);
|
||
|
var href = $(this).attr('href');
|
||
|
if (href){
|
||
|
location.href = href;
|
||
|
}
|
||
|
}
|
||
|
var item = $(target).menu('getItem', this);
|
||
|
$.data(target, 'menu').options.onClick.call(target, item);
|
||
|
}).bind('mouseenter.menu', function(e){
|
||
|
// hide other menu
|
||
|
item.siblings().each(function(){
|
||
|
if (this.submenu){
|
||
|
hideMenu(this.submenu);
|
||
|
}
|
||
|
$(this).removeClass('menu-active');
|
||
|
});
|
||
|
// show this menu
|
||
|
item.addClass('menu-active');
|
||
|
|
||
|
if ($(this).hasClass('menu-item-disabled')){
|
||
|
item.addClass('menu-active-disabled');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var submenu = item[0].submenu;
|
||
|
if (submenu){
|
||
|
var left = item.offset().left + item.outerWidth() - 2;
|
||
|
if (left + submenu.outerWidth() + 5 > $(window)._outerWidth() + $(document).scrollLeft()){
|
||
|
left = item.offset().left - submenu.outerWidth() + 2;
|
||
|
}
|
||
|
var top = item.offset().top - 3;
|
||
|
if (top + submenu.outerHeight() > $(window)._outerHeight() + $(document).scrollTop()){
|
||
|
top = $(window)._outerHeight() + $(document).scrollTop() - submenu.outerHeight() - 5;
|
||
|
}
|
||
|
showMenu(submenu, {
|
||
|
left: left,
|
||
|
top: top
|
||
|
});
|
||
|
}
|
||
|
}).bind('mouseleave.menu', function(e){
|
||
|
item.removeClass('menu-active menu-active-disabled');
|
||
|
var submenu = item[0].submenu;
|
||
|
if (submenu){
|
||
|
if (e.pageX>=parseInt(submenu.css('left'))){
|
||
|
item.addClass('menu-active');
|
||
|
} else {
|
||
|
hideMenu(submenu);
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
item.removeClass('menu-active');
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* hide top menu and it's all sub menus
|
||
|
*/
|
||
|
function hideAll(target){
|
||
|
var opts = $.data(target, 'menu').options;
|
||
|
hideMenu($(target));
|
||
|
$(document).unbind('.menu');
|
||
|
opts.onHide.call(target);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* show the top menu
|
||
|
*/
|
||
|
function showTopMenu(target, pos){
|
||
|
var opts = $.data(target, 'menu').options;
|
||
|
if (pos){
|
||
|
opts.left = pos.left;
|
||
|
opts.top = pos.top;
|
||
|
if (opts.left + $(target).outerWidth() > $(window)._outerWidth() + $(document).scrollLeft()){
|
||
|
opts.left = $(window)._outerWidth() + $(document).scrollLeft() - $(target).outerWidth() - 5;
|
||
|
}
|
||
|
if (opts.top + $(target).outerHeight() > $(window)._outerHeight() + $(document).scrollTop()){
|
||
|
opts.top -= $(target).outerHeight();
|
||
|
}
|
||
|
}
|
||
|
showMenu($(target), {left:opts.left,top:opts.top}, function(){
|
||
|
$(document).unbind('.menu').bind('mousedown.menu', function(){
|
||
|
hideAll(target);
|
||
|
$(document).unbind('.menu');
|
||
|
return false;
|
||
|
});
|
||
|
opts.onShow.call(target);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function showMenu(menu, pos, callback){
|
||
|
if (!menu) return;
|
||
|
|
||
|
if (pos){
|
||
|
menu.css(pos);
|
||
|
}
|
||
|
menu.show(0, function(){
|
||
|
if (!menu[0].shadow){
|
||
|
menu[0].shadow = $('<div class="menu-shadow"></div>').insertAfter(menu);
|
||
|
}
|
||
|
menu[0].shadow.css({
|
||
|
display:'block',
|
||
|
zIndex:$.fn.menu.defaults.zIndex++,
|
||
|
left:menu.css('left'),
|
||
|
top:menu.css('top'),
|
||
|
width:menu.outerWidth(),
|
||
|
height:menu.outerHeight()
|
||
|
});
|
||
|
menu.css('z-index', $.fn.menu.defaults.zIndex++);
|
||
|
|
||
|
if (callback){
|
||
|
callback();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function hideMenu(menu){
|
||
|
if (!menu) return;
|
||
|
|
||
|
hideit(menu);
|
||
|
menu.find('div.menu-item').each(function(){
|
||
|
if (this.submenu){
|
||
|
hideMenu(this.submenu);
|
||
|
}
|
||
|
$(this).removeClass('menu-active');
|
||
|
});
|
||
|
|
||
|
function hideit(m){
|
||
|
m.stop(true,true);
|
||
|
if (m[0].shadow){
|
||
|
m[0].shadow.hide();
|
||
|
}
|
||
|
m.hide();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function findItem(target, text){
|
||
|
var result = null;
|
||
|
var tmp = $('<div></div>');
|
||
|
function find(menu){
|
||
|
menu.children('div.menu-item').each(function(){
|
||
|
var item = $(target).menu('getItem', this);
|
||
|
var s = tmp.empty().html(item.text).text();
|
||
|
if (text == $.trim(s)) {
|
||
|
result = item;
|
||
|
} else if (this.submenu && !result){
|
||
|
find(this.submenu);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
find($(target));
|
||
|
tmp.remove();
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
function setDisabled(target, itemEl, disabled){
|
||
|
var t = $(itemEl);
|
||
|
|
||
|
if (disabled){
|
||
|
t.addClass('menu-item-disabled');
|
||
|
if (itemEl.onclick){
|
||
|
itemEl.onclick1 = itemEl.onclick;
|
||
|
itemEl.onclick = null;
|
||
|
}
|
||
|
} else {
|
||
|
t.removeClass('menu-item-disabled');
|
||
|
if (itemEl.onclick1){
|
||
|
itemEl.onclick = itemEl.onclick1;
|
||
|
itemEl.onclick1 = null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function appendItem(target, param){
|
||
|
var menu = $(target);
|
||
|
if (param.parent){
|
||
|
menu = param.parent.submenu;
|
||
|
}
|
||
|
var item = $('<div class="menu-item"></div>').appendTo(menu);
|
||
|
$('<div class="menu-text"></div>').html(param.text).appendTo(item);
|
||
|
if (param.iconCls) $('<div class="menu-icon"></div>').addClass(param.iconCls).appendTo(item);
|
||
|
if (param.id) item.attr('id', param.id);
|
||
|
if (param.href) item.attr('href', param.href);
|
||
|
if (param.name) item.attr('name', param.name);
|
||
|
if (param.onclick){
|
||
|
if (typeof param.onclick == 'string'){
|
||
|
item.attr('onclick', param.onclick);
|
||
|
} else {
|
||
|
item[0].onclick = eval(param.onclick);
|
||
|
}
|
||
|
}
|
||
|
if (param.handler) item[0].onclick = eval(param.handler);
|
||
|
|
||
|
bindMenuItemEvent(target, item);
|
||
|
|
||
|
if (param.disabled){
|
||
|
setDisabled(target, item[0], true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function removeItem(target, itemEl){
|
||
|
function removeit(el){
|
||
|
if (el.submenu){
|
||
|
el.submenu.children('div.menu-item').each(function(){
|
||
|
removeit(this);
|
||
|
});
|
||
|
var shadow = el.submenu[0].shadow;
|
||
|
if (shadow) shadow.remove();
|
||
|
el.submenu.remove();
|
||
|
}
|
||
|
$(el).remove();
|
||
|
}
|
||
|
removeit(itemEl);
|
||
|
}
|
||
|
|
||
|
function destroyMenu(target){
|
||
|
$(target).children('div.menu-item').each(function(){
|
||
|
removeItem(target, this);
|
||
|
});
|
||
|
if (target.shadow) target.shadow.remove();
|
||
|
$(target).remove();
|
||
|
}
|
||
|
|
||
|
$.fn.menu = function(options, param){
|
||
|
if (typeof options == 'string'){
|
||
|
return $.fn.menu.methods[options](this, param);
|
||
|
}
|
||
|
|
||
|
options = options || {};
|
||
|
return this.each(function(){
|
||
|
var state = $.data(this, 'menu');
|
||
|
if (state){
|
||
|
$.extend(state.options, options);
|
||
|
} else {
|
||
|
state = $.data(this, 'menu', {
|
||
|
options: $.extend({}, $.fn.menu.defaults, $.fn.menu.parseOptions(this), options)
|
||
|
});
|
||
|
init(this);
|
||
|
}
|
||
|
$(this).css({
|
||
|
left: state.options.left,
|
||
|
top: state.options.top
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
|
||
|
$.fn.menu.methods = {
|
||
|
show: function(jq, pos){
|
||
|
return jq.each(function(){
|
||
|
showTopMenu(this, pos);
|
||
|
});
|
||
|
},
|
||
|
hide: function(jq){
|
||
|
return jq.each(function(){
|
||
|
hideAll(this);
|
||
|
});
|
||
|
},
|
||
|
destroy: function(jq){
|
||
|
return jq.each(function(){
|
||
|
destroyMenu(this);
|
||
|
});
|
||
|
},
|
||
|
/**
|
||
|
* set the menu item text
|
||
|
* param: {
|
||
|
* target: DOM object, indicate the menu item
|
||
|
* text: string, the new text
|
||
|
* }
|
||
|
*/
|
||
|
setText: function(jq, param){
|
||
|
return jq.each(function(){
|
||
|
$(param.target).children('div.menu-text').html(param.text);
|
||
|
});
|
||
|
},
|
||
|
/**
|
||
|
* set the menu icon class
|
||
|
* param: {
|
||
|
* target: DOM object, indicate the menu item
|
||
|
* iconCls: the menu item icon class
|
||
|
* }
|
||
|
*/
|
||
|
setIcon: function(jq, param){
|
||
|
return jq.each(function(){
|
||
|
var item = $(this).menu('getItem', param.target);
|
||
|
if (item.iconCls){
|
||
|
$(item.target).children('div.menu-icon').removeClass(item.iconCls).addClass(param.iconCls);
|
||
|
} else {
|
||
|
$('<div class="menu-icon"></div>').addClass(param.iconCls).appendTo(param.target);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
/**
|
||
|
* get the menu item data that contains the following property:
|
||
|
* {
|
||
|
* target: DOM object, the menu item
|
||
|
* id: the menu id
|
||
|
* text: the menu item text
|
||
|
* iconCls: the icon class
|
||
|
* href: a remote address to redirect to
|
||
|
* onclick: a function to be called when the item is clicked
|
||
|
* }
|
||
|
*/
|
||
|
getItem: function(jq, itemEl){
|
||
|
var t = $(itemEl);
|
||
|
var item = {
|
||
|
target: itemEl,
|
||
|
id: t.attr('id'),
|
||
|
text: $.trim(t.children('div.menu-text').html()),
|
||
|
disabled: t.hasClass('menu-item-disabled'),
|
||
|
href: t.attr('href'),
|
||
|
name: t.attr('name'),
|
||
|
onclick: itemEl.onclick
|
||
|
}
|
||
|
var icon = t.children('div.menu-icon');
|
||
|
if (icon.length){
|
||
|
var cc = [];
|
||
|
var aa = icon.attr('class').split(' ');
|
||
|
for(var i=0; i<aa.length; i++){
|
||
|
if (aa[i] != 'menu-icon'){
|
||
|
cc.push(aa[i]);
|
||
|
}
|
||
|
}
|
||
|
item.iconCls = cc.join(' ');
|
||
|
}
|
||
|
return item;
|
||
|
},
|
||
|
findItem: function(jq, text){
|
||
|
return findItem(jq[0], text);
|
||
|
},
|
||
|
/**
|
||
|
* append menu item, the param contains following properties:
|
||
|
* parent,id,text,iconCls,href,onclick
|
||
|
* when parent property is assigned, append menu item to it
|
||
|
*/
|
||
|
appendItem: function(jq, param){
|
||
|
return jq.each(function(){
|
||
|
appendItem(this, param);
|
||
|
});
|
||
|
},
|
||
|
removeItem: function(jq, itemEl){
|
||
|
return jq.each(function(){
|
||
|
removeItem(this, itemEl);
|
||
|
});
|
||
|
},
|
||
|
enableItem: function(jq, itemEl){
|
||
|
return jq.each(function(){
|
||
|
setDisabled(this, itemEl, false);
|
||
|
});
|
||
|
},
|
||
|
disableItem: function(jq, itemEl){
|
||
|
return jq.each(function(){
|
||
|
setDisabled(this, itemEl, true);
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$.fn.menu.parseOptions = function(target){
|
||
|
return $.extend({}, $.parser.parseOptions(target, ['left','top']));
|
||
|
};
|
||
|
|
||
|
$.fn.menu.defaults = {
|
||
|
zIndex:110000,
|
||
|
left: 0,
|
||
|
top: 0,
|
||
|
onShow: function(){},
|
||
|
onHide: function(){},
|
||
|
onClick: function(item){}
|
||
|
};
|
||
|
})(jQuery);
|