contextMenu.js 3.95 KB
define('contextMenu', ['vue', 'vue-ext', 'jquery'], function (Vue) {
	var template = '\
<div class="context-menu" v-show="isshow" :style="position">\
	<context-menu-items :items="items"></context-menu-items>\
</div>';

	var cssText = '\
.context-menu{ position: absolute; top: -200px; left: -200px; padding: 5px 0; background: #fff; width: 180px; font: 12px/1 Microsoft YaHei, Arial, Helvetica,sans-serif; z-index: 100; border: 1px solid #bbb; box-shadow: 5px 5px 5px -3px rgba(0, 0, 0, 0.15) }\
	.context-menu .context-menu-item { line-height: 2; padding: 0px 36px; cursor: default; text-transform: capitalize; }\
	.context-menu .context-menu-item:hover { background-color: #ebebeb; }\
	.context-menu-item.line { border-bottom: 1px solid #eee; margin: 5px 0; }\
		.context-menu-item i { position: absolute; left: 10px; padding: 0 2px; font-size: 13px; color: #555; }\
		.context-menu-item .menu-name { color: #000 }\
		.context-menu-item .menu-shortcut { position: absolute; right: 10px; color: #999; }\
';

	var ContextMenuItems = {
		template: '\
<div><div class="context-menu-item" v-if="item.isshow!==false" v-for="item in items" @click="item.handler&&item.handler(item)" :class="{line: !item.name}">\
	<template v-if="!!item.name">\
		<i :class="\'iconfont \' + (item.icon||\'\')" ></i>\
		<span class="menu-name" v-text="item.name"></span>\
		<span class="menu-shortcut" v-text="item.shortcut"></span>\
	</template>\
</div></div>',
		props: ['items']
	};

	// 引入context menu css
	Vue.importCssText("contextMenu", cssText);

	var ContextMenu = {
		index: 0,
		init: function (options) {
			var defaults = {
				container: 'body',
				items: []
			};
			var ops = $.extend(defaults, options),
				$temp = $(template),
				menuId = 'context-menu' + ContextMenu.index++,
				$container = $(ops.container), contextMenu, $menu;

			$temp.attr('id', menuId);
			$container.find(".context-menu").remove();
			$container.append($temp);

			contextMenu = new Vue({
				el: '#' + menuId,
				components: {
					"context-menu-items": ContextMenuItems
				},
				data: {
					items: ops.items.filter(function (item) { return item; }),
					isshow: false, // 控制显示隐藏
					position: {}, // menu定位
				},
				methods: {
					toggle: function (isshow) {
						if (isshow != "undefined") return this.isshow = isshow;

						this.isshow = !this.isshow;
					}
				}
			});

			$menu = $container.find("#" + menuId);
			$menu[0].contextmenu = contextMenu;

			// init event
			$container.off("mousedown.contextMenu").on('mousedown.contextMenu', function (e) {
				if (e.buttons != 2) return; // 非右击鼠标
				if ($(e.target).parents('.context-menu').length > 0) return;
				
				var x = e.pageX, y = e.pageY,
					cWidth = $container.outerWidth(),
					cHeight = $container.outerHeight() - 15,
					cOffset = $container.offset(),
					mWidth = $menu.outerWidth(),
					mHeight = $menu.outerHeight(),
					cTop = cOffset.top,
					cLeft = cOffset.left, top, left;
				
				top = y > cTop && y < cTop + cHeight - mHeight ? y : cTop + cHeight - mHeight;
				left = x > cLeft && x < cLeft + cWidth - mWidth? x : cLeft + cWidth - mWidth;

				if($container.css('position') == 'fixed') {
					top = top - cTop;
					left = left - cLeft;
				}

				contextMenu.position = {
					top: top + 'px',
					left: left + 'px'
				};
				contextMenu.toggle(true);

				e.stopPropagation();
			}).off("click.closeMenu").on('click.closeMenu', function (e) {
				contextMenu.toggle(false);
				e.stopPropagation();
			}).off("contextmenu").on("contextmenu", function() { // 禁用浏览器的右键菜单
				return false;
			}).off("mousedown.contextMenu", ".layui-layer").on("mousedown.contextMenu", ".layui-layer", function(e) {
				e.stopPropagation();
			});
		}
	};

	// 初始化全局context menu事件
	// $('body').on('contextmenu', function () { // 禁用浏览器的右键菜单
	// 	return false;
	// }).on('mousedown.contextMenu', '.layui-layer', function(e) {
	// 	e.stopPropagation();
	// });

	return {
		init: ContextMenu.init
	};
});