Skip to content

Commit 6e7dced

Browse files
committed
Fixed replaceMenu()
Closed mar10#15
1 parent 0ba4254 commit 6e7dced

File tree

5 files changed

+67
-73
lines changed

5 files changed

+67
-73
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# 0.5.0 / Unreleased
22

33
* [CHANGE] Changed widget namespace from 'ui' to 'moogle'.
4-
* [CHANGE] Default position is now at click event.
4+
* [CHANGE] Default position is now at click event.pageX/Y.
55
* [CHANGE] Show-animation now faster by default.
66
* [FEATURE] `select` event has new parameters `ui.cmd` and `ui.target`.
7+
* [BUGFIX] Fixed replaceMenu() for `<ul>` defined menus.
78

89
# 0.4.0 / 2013-05-28
910

@@ -12,6 +13,6 @@
1213
# 0.3.0 / 2013-05-20
1314

1415
* [CHANGE] Renamed project from "jquery-contextmenu" to "jquery-ui-contextmenu"
15-
* [BUGFIX] Fixed markup for disabled entries
1616
* [FEATURE] Support `taphold` events
1717
* [FEATURE] Show / hide effects configurable
18+
* [BUGFIX] Fixed markup for disabled entries

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,7 @@ structure (see [jQueryUI menu] for details):
186186
<dt>replaceMenu(menu)</dt>
187187
<dd>
188188
Replace the whole menu definition.<br>
189-
Call like <code>$(...).contextmenu("replaceMenu", "#menu2");</code>.<br>
190-
**TODO**: this is currently not implemented for &lt;ul> definition mode.
189+
Call like <code>$(...).contextmenu("replaceMenu", "#menu2");</code>.
191190
</dd>
192191
<dt>setEntry(cmd, data)</dt>
193192
<dd>

demo/index.html

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,20 @@
9090
break
9191
}
9292
alert("select " + ui.cmd + " on " + $target.text());
93+
// Optionally return false, to prevent closing the menu now
9394
},
9495
beforeOpen: function(event, ui) {
9596
var $menu = ui.menu,
9697
$target = ui.target;
9798
$(document)
9899
// .contextmenu("replaceMenu", [{title: "aaa"}, {title: "bbb"}])
100+
// .contextmenu("replaceMenu", "#options2")
99101
// .contextmenu("setEntry", "cut", {title: "Cuty", uiIcon: "ui-icon-heart", disabled: true})
100102
.contextmenu("setEntry", "copy", "Copy '" + $target.text() + "'")
101103
.contextmenu("setEntry", "paste", "Paste" + (CLIPBOARD ? " '" + CLIPBOARD + "'" : ""))
102104
.contextmenu("enableEntry", "paste", (CLIPBOARD !== ""));
103105

104-
// optionally return false, to prevent opening the menu now
106+
// Optionally return false, to prevent opening the menu now
105107
}
106108
});
107109

@@ -116,8 +118,8 @@
116118
},
117119
preventSelect: true,
118120
taphold: true,
119-
hide: { effect: "explode", duration: "slow" },
120121
show: { effect: "fold", duration: "slow"},
122+
hide: { effect: "explode", duration: "slow" },
121123
focus: function(event, ui) {
122124
var menuId = ui.item.find(">a").attr("href");
123125
$("#info").text("focus " + menuId);
@@ -126,8 +128,8 @@
126128
$("#info").text("");
127129
},
128130
beforeOpen: function(event, ui) {
131+
// $("#container").contextmenu("replaceMenu", "#options2");
129132
// $("#container").contextmenu("replaceMenu", [{title: "aaa"}, {title: "bbb"}]);
130-
// alert("beforeopen on " + ui.target.text());
131133
},
132134
open: function(event, ui) {
133135
// alert("open on " + ui.target.text());
@@ -184,7 +186,7 @@ <h3>Sample 2</h3>
184186
<span class="hasmenu2">CCC</span>
185187
</div>
186188

187-
<ul id="options" class="ui-helper-hidden">
189+
<ul id="options" style="display: none;">
188190
<li><a href="#action1"><span class="ui-icon custom-icon-firefox"></span>Action 1</a>
189191
<li><a href="#action2"><span class="ui-icon ui-icon-heart"></span>Action 2</a>
190192
<li class="ui-state-disabled"><a href="#action3">Action 3</a>
@@ -196,6 +198,11 @@ <h3>Sample 2</h3>
196198
</ul>
197199
</ul>
198200

201+
<ul id="options2" class="ui-helper-hidden">
202+
<li><a href="#action2"><span class="ui-icon ui-icon-heart"></span>Action 2</a>
203+
<li class="ui-state-disabled"><a href="#action3">Action 3</a>
204+
</ul>
205+
199206
<h3>Sample 3</h3>
200207
<p>Open context menu using <code>$("#container").contextmenu("open", $(".hasmenu:first"))</code> and close after 2 sec.:</p>
201208
<button id="triggerPopup">Trigger popup</button>

jquery.ui-contextmenu.js

Lines changed: 51 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
delegate: "[data-menu]", // selector
2323
hide: { effect: "fadeOut", duration: "fast"},
2424
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
2626
position: null, // popup positon
2727
preventSelect: false, // disable text selection of target
2828
show: { effect: "slideDown", duration: "fast"},
@@ -43,7 +43,8 @@
4343
opts = this.options;
4444

4545
this.$headStyle = null;
46-
this.orgMenu = null;
46+
this.$menu = null;
47+
this.menuIsTemp = false;
4748
this.currentTarget = null;
4849
this.ns = "." + this.widgetName;
4950

@@ -69,14 +70,48 @@
6970
});
7071
}
7172
}
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+
}
72100
// If a menu definition array was passed, create a hidden <ul>
73101
// 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;
77112
}
78-
// Create - but hide - the jQuery UI Menu
79-
this._getMenu()
113+
// Create - but hide - the jQuery UI Menu widget
114+
this.$menu
80115
.hide()
81116
.addClass("ui-contextmenu")
82117
// Create a menu instance that delegates events to our widget
@@ -97,42 +132,21 @@
97132
}
98133
}, this)
99134
});
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-
}
121135
},
122136
/** Open popup (called on 'contextmenu' event). */
123137
_openMenu: function(event){
124138
var opts = this.options,
125139
posOption = opts.position,
126140
self = this,
127-
$menu = this._getMenu(),
128-
ui = {menu: $menu, target: $(event.target)};
141+
ui = {menu: this.$menu, target: $(event.target)};
129142
this.currentTarget = event.target;
130143
// Prevent browser from opening the system context menu
131144
event.preventDefault();
132145

133146
if( this._trigger("beforeOpen", event, ui) === false ){
134147
return false;
135148
}
149+
ui.menu = this.$menu; // Might have changed in beforeOpen
136150
// Register global event handlers that close the dropdown-menu
137151
$(document).bind("keydown" + this.ns, function(event){
138152
if( event.which === $.ui.keyCode.ESCAPE ){
@@ -158,25 +172,24 @@
158172
}, posOption);
159173

160174
// Finally display the popup
161-
$menu
175+
this.$menu
162176
.show() // required to fix positioning error
163177
.css({
164178
position: "absolute",
165179
left: 0,
166180
top: 0
167181
}).position(posOption)
168-
.hide();
182+
.hide(); // hide again, so we can apply nice effects
169183

170-
this._show($menu, this.options.show, function(){
184+
this._show(this.$menu, this.options.show, function(){
171185
self._trigger.call(self, "open", event, ui);
172186
});
173187
},
174188
/** Close popup. */
175189
_closeMenu: function(){
176-
var self = this,
177-
$menu = this._getMenu();
190+
var self = this;
178191

179-
this._hide($menu, this.options.hide, function() {
192+
this._hide(this.$menu, this.options.hide, function() {
180193
self._trigger("close");
181194
this.currentTarget = null;
182195
});
@@ -195,14 +208,9 @@
195208
}
196209
$.Widget.prototype._setOption.apply(this, arguments);
197210
},
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-
},
203211
/** Return ui-menu entry (<A> or <LI> tag). */
204212
_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) + "]");
206214
return wantLi ? $entry.closest("li") : $entry;
207215
},
208216
/** Open context menu on a specific target (must match options.delegate) */
@@ -221,28 +229,7 @@
221229
},
222230
/** Redefine the whole menu. */
223231
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);
246233
},
247234
/** Redefine menu entry (title or all of it). */
248235
setEntry: function(cmd, titleOrData){

jquery.ui-contextmenu.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)