|
21 | 21 | options: {
|
22 | 22 | delegate: "[data-menu]", // selector
|
23 | 23 | hide: { effect: "fadeOut", duration: "fast"},
|
24 |
| - show: { effect: "slideDown", duration: "slow"}, |
25 |
| - position: null, // specify positional preferences (added for issue #18 and #13). |
26 | 24 | ignoreParentSelect: true, // Don't trigger 'select' for sub-menu parents
|
27 | 25 | menu: null, // selector or jQuery or a function returning such
|
| 26 | + position: null, // popup positon |
28 | 27 | preventSelect: false, // disable text selection of target
|
29 |
| - taphold: false, // open menu on taphold events (requires external plugins) |
| 28 | + show: { effect: "slideDown", duration: "fast"}, |
| 29 | + taphold: false, // open menu on taphold events (requires external plugins) |
30 | 30 | // Events:
|
31 | 31 | beforeOpen: $.noop, // menu about to open; return `false` to prevent opening
|
32 | 32 | blur: $.noop, // menu option lost focus
|
|
42 | 42 | var eventNames, targetId,
|
43 | 43 | opts = this.options;
|
44 | 44 |
|
45 |
| -// console.log(this.element) |
46 |
| - |
47 | 45 | this.$headStyle = null;
|
48 | 46 | this.orgMenu = null;
|
49 | 47 | this.currentTarget = null;
|
|
87 | 85 | create: $.proxy(this.options.create, this),
|
88 | 86 | focus: $.proxy(this.options.focus, this),
|
89 | 87 | select: $.proxy(function(event, ui){
|
90 |
| - // Also pass the target that the menu was triggered on: |
91 |
| - event.relatedTarget = this.currentTarget; |
92 |
| - ui.cmd = normCommand(ui.item.find(">a").attr("href")); |
93 |
| - ui.target = $(this.currentTarget); |
94 |
| - // ignore clicks, if they only open a sub-menu |
95 | 88 | var isParent = (ui.item.has(">a[aria-haspopup='true']").length > 0);
|
| 89 | + ui.cmd = normCommand(ui.item.find(">a").attr("href")); |
| 90 | + ui.target = $(this.currentTarget); |
| 91 | + // ignore clicks, if they only open a sub-menu |
96 | 92 | if( !isParent || !this.options.ignoreParentSelect){
|
97 | 93 | if( this._trigger.call(this, "select", event, ui) !== false ){
|
98 | 94 | this._closeMenu.call(this);
|
|
129 | 125 | posOption = opts.position,
|
130 | 126 | self = this,
|
131 | 127 | $menu = this._getMenu(),
|
132 |
| - openEvent = event, |
133 |
| - // if called by 'open' method, 'relatedTarget' is the requested target object |
134 |
| - parentTarget = openEvent.target ? openEvent.target : openEvent, |
135 |
| - ui = {menu: $menu, target: $(openEvent.target)}; |
136 |
| - this.currentTarget = openEvent.target; |
| 128 | + ui = {menu: $menu, target: $(event.target)}; |
| 129 | + this.currentTarget = event.target; |
137 | 130 | // Prevent browser from opening the system context menu
|
138 | 131 | event.preventDefault();
|
139 |
| - // Also pass the target that the menu was triggered on as 'relatedTarget'. |
140 |
| - // This is required because our _trigger() calls will create events |
141 |
| - // that refer to the contextmenu's context (which is the target *container*) |
142 |
| - event.relatedTarget = this.currentTarget; |
143 | 132 |
|
144 | 133 | if( this._trigger("beforeOpen", event, ui) === false ){
|
145 | 134 | return false;
|
|
163 | 152 | posOption = $.extend({
|
164 | 153 | my: "left top",
|
165 | 154 | at: "left bottom",
|
166 |
| - of: parentTarget, |
| 155 | + // if called by 'open' method, event does not have pageX/Y |
| 156 | + of: (event.pageX === undefined) ? event.target : event, |
167 | 157 | collision: "fit"
|
168 | 158 | }, posOption);
|
169 | 159 |
|
170 | 160 | // Finally display the popup
|
171 | 161 | $menu
|
172 |
| - .show() // required to fix positioning error (issue #3) |
| 162 | + .show() // required to fix positioning error |
173 | 163 | .css({
|
174 | 164 | position: "absolute",
|
175 | 165 | left: 0,
|
176 | 166 | top: 0
|
177 |
| - }).position(posOption).hide(); |
| 167 | + }).position(posOption) |
| 168 | + .hide(); |
178 | 169 |
|
179 | 170 | this._show($menu, this.options.show, function(){
|
180 | 171 | self._trigger.call(self, "open", event, ui);
|
|
206 | 197 | },
|
207 | 198 | /** Return ui-menu root element as jQuery object. */
|
208 | 199 | _getMenu: function(){
|
209 |
| - // this.options.menu may be a string, jQuery or a function returning that. |
210 | 200 | var $menu = this.options.menu;
|
211 | 201 | return (typeof $menu === "string") ? $($menu) : $menu;
|
212 | 202 | },
|
| 203 | + /** Return ui-menu entry (<A> or <LI> tag). */ |
| 204 | + _getMenuEntry: function(cmd, wantLi){ |
| 205 | + var $entry = this._getMenu().find("li a[href=#" + normCommand(cmd) + "]"); |
| 206 | + return wantLi ? $entry.closest("li") : $entry; |
| 207 | + }, |
213 | 208 | /** Open context menu on a specific target (must match options.delegate) */
|
214 | 209 | open: function(target){
|
215 | 210 | // Fake a 'contextmenu' event
|
|
222 | 217 | },
|
223 | 218 | /** Enable or disable the menu command. */
|
224 | 219 | enableEntry: function(cmd, flag){
|
225 |
| - // TODO: should be $menu.find(...)! |
226 |
| - var $entry = this.element.find("a[href=#" + normCommand(cmd) + "]"); |
227 |
| - $entry.toggleClass("ui-state-disabled", (flag === false)); |
| 220 | + this._getMenuEntry(cmd, true).toggleClass("ui-state-disabled", (flag === false)); |
228 | 221 | },
|
229 | 222 | /** Redefine the whole menu. */
|
230 | 223 | replaceMenu: function(data){
|
|
254 | 247 | /** Redefine menu entry (title or all of it). */
|
255 | 248 | setEntry: function(cmd, titleOrData){
|
256 | 249 | var $parent,
|
257 |
| - $entry = this.element.find("a[href=#" + normCommand(cmd) + "]"); |
| 250 | + $entry = this._getMenuEntry(cmd, false); |
258 | 251 |
|
259 | 252 | if(typeof titleOrData === "string"){
|
260 | 253 | // Replace <a> text without removing <span> child
|
|
270 | 263 | },
|
271 | 264 | /** Show or hide the menu command. */
|
272 | 265 | showEntry: function(cmd, flag){
|
273 |
| - var $entry = this.element.find("a[href=#" + normCommand(cmd) + "]"); |
274 |
| - $entry.toggle(flag !== false); |
| 266 | + this._getMenuEntry(cmd, true).toggle(flag !== false); |
275 | 267 | }
|
276 | 268 | });
|
277 | 269 |
|
|
0 commit comments