123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- (function($) {
- function returnfalse() { return false; };
- $.fn.contextmenu = function(option) {
- option = $.extend({ alias: "cmroot", width: 150 }, option);
- var ruleName = null, target = null,
- groups = {}, mitems = {}, actions = {}, showGroups = [],
- itemTpl = "<div class='b-m-$[type]' unselectable=on><nobr unselectable=on><span unselectable=on>$[text]</span></nobr></div>";
- var gTemplet = $("<div/>").addClass("b-m-mpanel").attr("unselectable", "on").css("display", "none");
- var iTemplet = $("<div/>").addClass("b-m-item").attr("unselectable", "on");
- var sTemplet = $("<div/>").addClass("b-m-split");
- //build group item, which has sub items
- var buildGroup = function(obj) {
- groups[obj.alias] = this;
- this.gidx = obj.alias;
- this.id = obj.alias;
- if (obj.disable) {
- this.disable = obj.disable;
- this.className = "b-m-idisable";
- }
- $(this).width(obj.width).click(returnfalse).mousedown(returnfalse).appendTo($("body"));
- obj = null;
- return this;
- };
- var buildItem = function(obj) {
- var T = this;
- T.idx = obj.alias;
- T.gidx = obj.gidx;
- T.data = obj;
- T.innerHTML = itemTpl.replace(/\$\[([^\]]+)\]/g, function() {
- return obj[arguments[1]];
- });
- if (obj.id)
- T.setAttribute('id', obj.id);
- if (obj.disable) {
- T.disable = obj.disable;
- T.className = "b-m-idisable";
- }
- obj.items && (T.group = true);
- obj.action && (actions[obj.alias] = obj.action);
- mitems[obj.alias] = T;
- T = obj = null;
- return this;
- };
- //add new items
- var addItems = function(gidx, items) {
- var tmp = null;
- for (var i = 0; i < items.length; i++) {
- if (items[i].type == "splitLine") {
- //split line
- tmp = sTemplet.clone()[0];
- } else {
- items[i].gidx = gidx;
- if (items[i].type == "group") {
- //group
- buildGroup.apply(gTemplet.clone()[0], [items[i]]);
- arguments.callee(items[i].alias, items[i].items);
- items[i].type = "arrow";
- tmp = buildItem.apply(iTemplet.clone()[0], [items[i]]);
- } else {
- //normal item
- items[i].type = "ibody";
- tmp = buildItem.apply(iTemplet.clone()[0], [items[i]]);
- $(tmp).click(function(e) {
- if (!this.disable) {
- if ($.isFunction(actions[this.idx])) {
- actions[this.idx].call(this, target);
- }
- hideMenuPane();
- }
- return false;
- });
- } //end if
- $(tmp).bind("contextmenu", returnfalse).hover(overItem, outItem);
- }
- groups[gidx].appendChild(tmp);
- tmp = items[i] = items[i].items = null;
- } //end for
- gidx = items = null;
- };
- var overItem = function(e) {
- //menu item is disabled
- if (this.disable)
- return false;
- hideMenuPane.call(groups[this.gidx]);
- //has sub items
- if (this.group) {
- var pos = $(this).offset();
- var width = $(this).outerWidth();
- showMenuGroup.apply(groups[this.idx], [pos, width]);
- }
- this.className = "b-m-ifocus";
- return false;
- };
- //menu loses focus
- var outItem = function(e) {
- //disabled item
- if (this.disable )
- return false;
- if (!this.group) {
- //normal item
- this.className = "b-m-item";
- } //Endif
- return false;
- };
- //show menu group at specified position
- var reversed = false;
- var showMenuGroup = function(pos, width) {
- var bwidth = $("body").width();
- var bheight = document.documentElement.clientHeight;
- var mwidth = $(this).outerWidth();
- var mheight = $(this).outerHeight();
- var originalPosTop = pos.top;
- pos.left = (pos.left + width + mwidth > bwidth) ? (pos.left - mwidth < 0 ? 0 : pos.left - mwidth) : pos.left + width;
- pos.top = (pos.top + mheight > bheight) ? (pos.top - mheight + (width > 0 ? 25 : 0) < 0 ? 0 : pos.top - mheight + (width > 0 ? 25 : 0)) : pos.top;
- var needsReversed = originalPosTop > pos.top;
- var $this = $(this);
- if (reversed != needsReversed)
- $this.children().each(function(i, child) { $this.prepend(child); });
- reversed = needsReversed;
- $(this).css(pos).show();
- showGroups.push(this.gidx);
- };
- //to hide menu
- var hideMenuPane = function() {
- var alias = null;
- for (var i = showGroups.length - 1; i >= 0; i--) {
- if (showGroups[i] == this.gidx)
- break;
- alias = showGroups.pop();
- groups[alias].style.display = "none";
- mitems[alias] && (mitems[alias].className = "b-m-item");
- } //Endfor
- //CollectGarbage();
- };
- function applyRule(rule) {
- if (ruleName && ruleName == rule.name)
- return false;
- for (var i in mitems)
- disable(i, !rule.disable);
- for (var i = 0; i < rule.items.length; i++)
- disable(rule.items[i], rule.disable);
- ruleName = rule.name;
- };
- function disable(alias, disabled) {
- var item = mitems[alias];
- item.className = (item.disable = item.lastChild.disabled = disabled) ? "b-m-idisable" : "b-m-item";
- };
- /* to show menu */
- function showMenu(e, menutarget) {
- target = menutarget;
- showMenuGroup.call(groups.cmroot, { left: e.pageX, top: e.pageY }, 0);
- $(document).one('mousedown', hideMenuPane);
- }
- var $root = $("#" + option.alias);
- var root = null;
- if ($root.length == 0) {
- root = buildGroup.apply(gTemplet.clone()[0], [option]);
- root.applyrule = applyRule;
- root.showMenu = showMenu;
- addItems(option.alias, option.items);
- }
- else {
- root = $root[0];
- }
- var me = $(this).each(function() {
- return $(this).bind('contextmenu', function(e) {
- var bShowContext = (option.onContextMenu && $.isFunction(option.onContextMenu)) ? option.onContextMenu.call(this, e) : true;
- if (bShowContext) {
- if (option.onShow && $.isFunction(option.onShow)) {
- option.onShow.call(this, root);
- }
- root.showMenu(e, this);
- }
- return false;
- });
- });
- //to apply rule
- if (option.rule) {
- applyRule(option.rule);
- }
- gTemplet = iTemplet = sTemplet = itemTpl = buildGroup = buildItem = null;
- addItems = overItem = outItem = null;
- //CollectGarbage();
- return me;
- }
- })(jQuery);
|