1/*!
2 * jquery.fancytree.menu.js
3 *
4 * Enable jQuery UI Menu as context menu for tree nodes.
5 * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
6 *
7 * @see http://api.jqueryui.com/menu/
8 *
9 * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
10 *
11 * Released under the MIT license
12 * https://github.com/mar10/fancytree/wiki/LicenseInfo
13 *
14 * @version 2.38.3
15 * @date 2023-02-01T20:52:50Z
16 */
17
18(function (factory) {
19	if (typeof define === "function" && define.amd) {
20		// AMD. Register as an anonymous module.
21		define(["jquery", "./jquery.fancytree"], factory);
22	} else if (typeof module === "object" && module.exports) {
23		// Node/CommonJS
24		require("./jquery.fancytree");
25		module.exports = factory(require("jquery"));
26	} else {
27		// Browser globals
28		factory(jQuery);
29	}
30})(function ($) {
31	"use strict";
32
33	$.ui.fancytree.registerExtension({
34		name: "menu",
35		version: "2.38.3",
36		// Default options for this extension.
37		options: {
38			enable: true,
39			selector: null, //
40			position: {}, //
41			// Events:
42			create: $.noop, //
43			beforeOpen: $.noop, //
44			open: $.noop, //
45			focus: $.noop, //
46			select: $.noop, //
47			close: $.noop, //
48		},
49		// Override virtual methods for this extension.
50		// `this`       : is this extension object
51		// `this._base` : the Fancytree instance
52		// `this._super`: the virtual function that was overridden (member of prev. extension or Fancytree)
53		treeInit: function (ctx) {
54			var opts = ctx.options,
55				tree = ctx.tree;
56
57			this._superApply(arguments);
58
59			// Prepare an object that will be passed with menu events
60			tree.ext.menu.data = {
61				tree: tree,
62				node: null,
63				$menu: null,
64				menuId: null,
65			};
66
67			//        tree.$container[0].oncontextmenu = function() {return false;};
68			// Replace the standard browser context menu with out own
69			tree.$container.on(
70				"contextmenu",
71				"span.fancytree-node",
72				function (event) {
73					var node = $.ui.fancytree.getNode(event),
74						ctx = {
75							node: node,
76							tree: node.tree,
77							originalEvent: event,
78							options: tree.options,
79						};
80					tree.ext.menu._openMenu(ctx);
81					return false;
82				}
83			);
84
85			// Use jquery.ui.menu
86			$(opts.menu.selector)
87				.menu({
88					create: function (event, ui) {
89						tree.ext.menu.data.$menu = $(this).menu("widget");
90						var data = $.extend({}, tree.ext.menu.data);
91						opts.menu.create.call(tree, event, data);
92					},
93					focus: function (event, ui) {
94						var data = $.extend({}, tree.ext.menu.data, {
95							menuItem: ui.item,
96							menuId: ui.item.find(">a").attr("href"),
97						});
98						opts.menu.focus.call(tree, event, data);
99					},
100					select: function (event, ui) {
101						var data = $.extend({}, tree.ext.menu.data, {
102							menuItem: ui.item,
103							menuId: ui.item.find(">a").attr("href"),
104						});
105						if (
106							opts.menu.select.call(tree, event, data) !== false
107						) {
108							tree.ext.menu._closeMenu(ctx);
109						}
110					},
111				})
112				.hide();
113		},
114		treeDestroy: function (ctx) {
115			this._superApply(arguments);
116		},
117		_openMenu: function (ctx) {
118			var data,
119				tree = ctx.tree,
120				opts = ctx.options,
121				$menu = $(opts.menu.selector);
122
123			tree.ext.menu.data.node = ctx.node;
124			data = $.extend({}, tree.ext.menu.data);
125
126			if (
127				opts.menu.beforeOpen.call(tree, ctx.originalEvent, data) ===
128				false
129			) {
130				return;
131			}
132
133			$(document)
134				.on("keydown.fancytree", function (event) {
135					if (event.which === $.ui.keyCode.ESCAPE) {
136						tree.ext.menu._closeMenu(ctx);
137					}
138				})
139				.on("mousedown.fancytree", function (event) {
140					// Close menu when clicked outside menu
141					if ($(event.target).closest(".ui-menu-item").length === 0) {
142						tree.ext.menu._closeMenu(ctx);
143					}
144				});
145			//        $menu.position($.extend({my: "left top", at: "left bottom", of: event}, opts.menu.position));
146			$menu
147				.css("position", "absolute")
148				.show()
149				.position({
150					my: "left top",
151					at: "right top",
152					of: ctx.originalEvent,
153					collision: "fit",
154				})
155				.focus();
156
157			opts.menu.open.call(tree, ctx.originalEvent, data);
158		},
159		_closeMenu: function (ctx) {
160			var $menu,
161				tree = ctx.tree,
162				opts = ctx.options,
163				data = $.extend({}, tree.ext.menu.data);
164			if (opts.menu.close.call(tree, ctx.originalEvent, data) === false) {
165				return;
166			}
167			$menu = $(opts.menu.selector);
168			$(document).off("keydown.fancytree, mousedown.fancytree");
169			$menu.hide();
170			tree.ext.menu.data.node = null;
171		},
172		//	,
173		//	nodeClick: function(ctx) {
174		//		var event = ctx.originalEvent;
175		//		if(event.which === 2 || (event.which === 1 && event.ctrlKey)){
176		//			event.preventDefault();
177		//			ctx.tree.ext.menu._openMenu(ctx);
178		//			return false;
179		//		}
180		//		this._superApply(arguments);
181		//	}
182	});
183	// Value returned by `require('jquery.fancytree..')`
184	return $.ui.fancytree;
185}); // End of closure
186