|
22 | 22 | delegate: "[data-menu]", // selector |
23 | 23 | hide: { effect: "fadeOut", duration: "fast"}, |
24 | 24 | ignoreParentSelect: true, // Don't trigger 'select' for sub-menu parents |
25 | | - menu: null, // selector or jQuery or a function returning such |
| 25 | + menu: null, // selector or jQuery pointing to <UL>, or a definition hash |
26 | 26 | position: null, // popup positon |
27 | 27 | preventSelect: false, // disable text selection of target |
28 | 28 | show: { effect: "slideDown", duration: "fast"}, |
|
43 | 43 | opts = this.options; |
44 | 44 |
|
45 | 45 | this.$headStyle = null; |
46 | | - this.orgMenu = null; |
| 46 | + this.$menu = null; |
| 47 | + this.menuIsTemp = false; |
47 | 48 | this.currentTarget = null; |
48 | 49 | this.ns = "." + this.widgetName; |
49 | 50 |
|
|
69 | 70 | }); |
70 | 71 | } |
71 | 72 | } |
| 73 | + this._createUiMenu(opts.menu); |
| 74 | + |
| 75 | + eventNames = "contextmenu" + this.ns; |
| 76 | + if(opts.taphold){ |
| 77 | + eventNames += " taphold" + this.ns; |
| 78 | + } |
| 79 | + this.element.delegate(opts.delegate, eventNames, $.proxy(this._openMenu, this)); |
| 80 | + |
| 81 | + this._trigger("init"); |
| 82 | + }, |
| 83 | + /** Destructor, called on $().contextmenu("destroy"). */ |
| 84 | + _destroy: function(key, value){ |
| 85 | + this._createUiMenu(null); |
| 86 | + if(this.$headStyle){ |
| 87 | + this.$headStyle.remove(); |
| 88 | + this.$headStyle = null; |
| 89 | + } |
| 90 | + }, |
| 91 | + /** (Re)Create jQuery UI Menu. */ |
| 92 | + _createUiMenu: function(menuDef){ |
| 93 | + // Remove temporary <ul> if any |
| 94 | + if(this.menuIsTemp){ |
| 95 | + this.$menu.remove(); // this will also destroy ui.menu |
| 96 | + this.menuIsTemp = false; |
| 97 | + } else if(this.$menu){ |
| 98 | + this.$menu.menu("destroy").hide(); |
| 99 | + } |
72 | 100 | // If a menu definition array was passed, create a hidden <ul> |
73 | 101 | // and generate the structure now |
74 | | - if($.isArray(opts.menu)){ |
75 | | - this.orgMenu = opts.menu; |
76 | | - opts.menu = $.moogle.contextmenu.createMenuMarkup(opts.menu); |
| 102 | + if( ! menuDef ){ |
| 103 | + this.$menu = null; |
| 104 | + return; |
| 105 | + } else if($.isArray(menuDef)){ |
| 106 | + this.$menu = $.moogle.contextmenu.createMenuMarkup(menuDef); |
| 107 | + this.menuIsTemp = true; |
| 108 | + }else if ( typeof menuDef === "string" ){ |
| 109 | + this.$menu = $(menuDef); |
| 110 | + }else{ |
| 111 | + this.$menu = menuDef; |
77 | 112 | } |
78 | | - // Create - but hide - the jQuery UI Menu |
79 | | - this._getMenu() |
| 113 | + // Create - but hide - the jQuery UI Menu widget |
| 114 | + this.$menu |
80 | 115 | .hide() |
81 | 116 | .addClass("ui-contextmenu") |
82 | 117 | // Create a menu instance that delegates events to our widget |
|
97 | 132 | } |
98 | 133 | }, this) |
99 | 134 | }); |
100 | | - |
101 | | - eventNames = "contextmenu" + this.ns; |
102 | | - if(opts.taphold){ |
103 | | - eventNames += " taphold" + this.ns; |
104 | | - } |
105 | | - this.element.delegate(opts.delegate, eventNames, $.proxy(this._openMenu, this)); |
106 | | - |
107 | | - this._trigger("init"); |
108 | | - }, |
109 | | - /** Destructor, called on $().contextmenu("destroy"). */ |
110 | | - _destroy: function(key, value){ |
111 | | - if(this.$headStyle){ |
112 | | - this.$headStyle.remove(); |
113 | | - this.$headStyle = null; |
114 | | - } |
115 | | - // Remove temporary <ul> if any |
116 | | - if(this.orgMenu){ |
117 | | - this.options.menu.remove(); |
118 | | - this.options.menu = this.orgMenu; |
119 | | - this.orgMenu = null; |
120 | | - } |
121 | 135 | }, |
122 | 136 | /** Open popup (called on 'contextmenu' event). */ |
123 | 137 | _openMenu: function(event){ |
124 | 138 | var opts = this.options, |
125 | 139 | posOption = opts.position, |
126 | 140 | self = this, |
127 | | - $menu = this._getMenu(), |
128 | | - ui = {menu: $menu, target: $(event.target)}; |
| 141 | + ui = {menu: this.$menu, target: $(event.target)}; |
129 | 142 | this.currentTarget = event.target; |
130 | 143 | // Prevent browser from opening the system context menu |
131 | 144 | event.preventDefault(); |
132 | 145 |
|
133 | 146 | if( this._trigger("beforeOpen", event, ui) === false ){ |
134 | 147 | return false; |
135 | 148 | } |
| 149 | + ui.menu = this.$menu; // Might have changed in beforeOpen |
136 | 150 | // Register global event handlers that close the dropdown-menu |
137 | 151 | $(document).bind("keydown" + this.ns, function(event){ |
138 | 152 | if( event.which === $.ui.keyCode.ESCAPE ){ |
|
158 | 172 | }, posOption); |
159 | 173 |
|
160 | 174 | // Finally display the popup |
161 | | - $menu |
| 175 | + this.$menu |
162 | 176 | .show() // required to fix positioning error |
163 | 177 | .css({ |
164 | 178 | position: "absolute", |
165 | 179 | left: 0, |
166 | 180 | top: 0 |
167 | 181 | }).position(posOption) |
168 | | - .hide(); |
| 182 | + .hide(); // hide again, so we can apply nice effects |
169 | 183 |
|
170 | | - this._show($menu, this.options.show, function(){ |
| 184 | + this._show(this.$menu, this.options.show, function(){ |
171 | 185 | self._trigger.call(self, "open", event, ui); |
172 | 186 | }); |
173 | 187 | }, |
174 | 188 | /** Close popup. */ |
175 | 189 | _closeMenu: function(){ |
176 | | - var self = this, |
177 | | - $menu = this._getMenu(); |
| 190 | + var self = this; |
178 | 191 |
|
179 | | - this._hide($menu, this.options.hide, function() { |
| 192 | + this._hide(this.$menu, this.options.hide, function() { |
180 | 193 | self._trigger("close"); |
181 | 194 | this.currentTarget = null; |
182 | 195 | }); |
|
195 | 208 | } |
196 | 209 | $.Widget.prototype._setOption.apply(this, arguments); |
197 | 210 | }, |
198 | | - /** Return ui-menu root element as jQuery object. */ |
199 | | - _getMenu: function(){ |
200 | | - var $menu = this.options.menu; |
201 | | - return (typeof $menu === "string") ? $($menu) : $menu; |
202 | | - }, |
203 | 211 | /** Return ui-menu entry (<A> or <LI> tag). */ |
204 | 212 | _getMenuEntry: function(cmd, wantLi){ |
205 | | - var $entry = this._getMenu().find("li a[href=#" + normCommand(cmd) + "]"); |
| 213 | + var $entry = this.$menu.find("li a[href=#" + normCommand(cmd) + "]"); |
206 | 214 | return wantLi ? $entry.closest("li") : $entry; |
207 | 215 | }, |
208 | 216 | /** Open context menu on a specific target (must match options.delegate) */ |
|
221 | 229 | }, |
222 | 230 | /** Redefine the whole menu. */ |
223 | 231 | replaceMenu: function(data){ |
224 | | - var opts = this.options, |
225 | | - $menu = this._getMenu(); |
226 | | - |
227 | | - if($.isArray(data)){ |
228 | | - if(this.orgMenu){ |
229 | | - // re-use existing temporary <ul> |
230 | | - $menu.empty(); |
231 | | - $.moogle.contextmenu.createMenuMarkup(data, opts.menu); |
232 | | - $menu.menu("refresh"); |
233 | | - }else{ |
234 | | - $.error("not implemented"); |
235 | | -// this.orgMenu = opts.menu; |
236 | | -// opts.menu = $.ui.contextmenu.createMenuMarkup(data); |
237 | | - } |
238 | | - }else{ |
239 | | -// if(this.orgMenu){ |
240 | | -// // re-use existing temporary <ul> |
241 | | -// }else{ |
242 | | -// } |
243 | | -// $menu.menu("option", "menu", opts.menu); |
244 | | - $.error("not implemented"); |
245 | | - } |
| 232 | + this._createUiMenu(data); |
246 | 233 | }, |
247 | 234 | /** Redefine menu entry (title or all of it). */ |
248 | 235 | setEntry: function(cmd, titleOrData){ |
|
0 commit comments