Skip to content

Commit d28a508

Browse files
committed
Adding taphold and preventSelect options.
Fixed mar10#2 Fixed mar10#12
1 parent 43804b7 commit d28a508

File tree

5 files changed

+148
-69
lines changed

5 files changed

+148
-69
lines changed

README.md

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ A jQuery plugin that provides a context menu (based on the standard [jQueryUI me
66
* Supports delegation (i.e. can be bound to elements that don't exist at the
77
time the context menu is initialized).
88
* Exposes events from [jQueryUI menu]: `blur`, `create`, `focus`, `select`.
9+
* Optional support for touch devices.
910

1011

1112
## Status
@@ -30,10 +31,10 @@ Say we have some HTML elements that we want to attach a popup menu to:
3031
</div>
3132
```
3233

33-
now we can enable a contextmenu like so:
34+
now we can enable a context menu like so:
3435

3536
```js
36-
$(document).contextmenu({
37+
$("#container").contextmenu({
3738
delegate: ".hasmenu",
3839
menu: [
3940
{title: "Copy", cmd: "copy", uiIcon: "ui-icon-copy"},
@@ -51,11 +52,21 @@ $(document).contextmenu({
5152
});
5253
```
5354

55+
To attach menus to *all* elements on the page that have `class="hasmenu"`,
56+
we use `document` as context:
57+
```js
58+
$(document).contextmenu({
59+
delegate: ".hasmenu",
60+
...
61+
});
62+
```
5463

5564
### Initialize menu from an existing `<ul>` element
5665

66+
In this case `menu` must point to the markup:
67+
5768
```js
58-
$("#container").contextmenu({
69+
$(document).contextmenu({
5970
delegate: ".hasmenu",
6071
menu: "#options",
6172
select: function(event, ui) {
@@ -64,19 +75,18 @@ $("#container").contextmenu({
6475
});
6576
```
6677

67-
Of course we also have to provide some HTML markup that defines the context menu
78+
We also have to provide some HTML markup that defines the context menu
6879
structure (see [jQueryUI menu] for details):
6980

7081
```html
7182
<ul id="options" class="ui-helper-hidden">
72-
<li><a href="#action1">Action 1</a>
73-
<li><a href="#action2">Action 2</a>
74-
<li class="ui-state-disabled"><a href="#action3">Action 3</a>
83+
<li><a href="#copy"><span class="ui-icon ui-icon-copy"></span>Copy</a>
84+
<li class="ui-state-disabled"><a href="#paste">Paste</a>
7585
<li>----
76-
<li><a>Extra</a>
86+
<li><a>More</a>
7787
<ul>
78-
<li><a href="#action4">sub4</a>
79-
<li><a href="#action5">sub5</a>
88+
<li><a href="#sub1">Sub 1</a>
89+
<li><a href="#sub2">Sub 2</a>
8090
</ul>
8191
</ul>
8292
```
@@ -93,16 +103,34 @@ structure (see [jQueryUI menu] for details):
93103
<dt>ignoreParentSelect</dt>
94104
<dd>
95105
Type: <code>Boolean</code>, default: <code>true</code><br>
96-
If <code>true</code>, a click on a menu item that contains a sub-menu, will <em>not</em>
97-
trigger the <code>select</code> event.
106+
If <code>true</code>, a click on a menu item that contains a sub-menu, will
107+
<em>not</em> trigger the <code>select</code> event.
98108
</dd>
99109
<dt>menu</dt>
100110
<dd>
101-
Type: <code>String | jQuery | function</code><br>
102-
jQuery object or selector (or function returning such) of HTML markup that defines the context menu
103-
structure (see [jQueryUI menu] for details).
104-
</dd>
111+
Type: <code>Object[] | String | jQuery | function</code><br>
112+
jQuery object or selector (or function returning such) of HTML markup that
113+
defines the context menu structure (see
114+
<a href="http://jqueryui.com/menu/">jQueryUI menu</a> for details).
105115

116+
If an array of objects is passed, it will be interpreted used to generate
117+
such markup on the fly.
118+
119+
If a function is passed, it must return one of the formats described above.
120+
</dd>
121+
<dt>preventSelect</dt>
122+
<dd>
123+
Type: <code>Boolean</code>, default: <code>false</code><br>
124+
Prevent accidental text selection of potential menu targets on doubleclick
125+
or drag.
126+
</dd>
127+
<dt>taphold</dt>
128+
<dd>
129+
Type: <code>Boolean</code>, default: <code>false</code><br>
130+
Open menu on <a href="http://api.jquerymobile.com/taphold/">taphold events</a>,
131+
which is especially useful for touch devices (but may require external
132+
plugins to generate <code>taphold</code> events).
133+
</dd>
106134
</dl>
107135

108136

demo/index.html

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,46 @@
1717
<script src="../jquery.ui-contextmenu.js" type="text/javascript"></script>
1818

1919
<style type="text/css">
20+
21+
/* Some styling */
22+
2023
body{
2124
font-family: "Trebuchet MS", "Helvetica", "Arial", "Verdana", "sans-serif";
2225
font-size: .8em;
2326
}
27+
2428
.hasmenu, .hasmenu2 {
2529
border: 1px solid #008;
2630
margin: 3px;
2731
padding: 2px;
2832
width: 30px;
2933
}
34+
3035
.ui-widget{
3136
font-size: .8em;
3237
}
3338
.ui-menu {
3439
width: 120px;
3540
}
41+
3642
/* Define a custom icon */
43+
3744
.ui-icon.custom-icon-firefox {
3845
background-image: url(application_firefox.gif);
3946
background-position: 0 0;
4047
}
4148
</style>
4249

43-
<!-- Add code to initialize the tree when the document is loaded: -->
50+
4451
<script type="text/javascript">
4552
$(function(){
4653

47-
/* Init menu by passing an array of entries. */
54+
/* Menu 1: init by passing an array of entries. */
4855

4956
$(document).contextmenu({
5057
delegate: ".hasmenu",
58+
preventSelect: true,
59+
taphold: true,
5160
menu: [
5261
{title: "Cut", cmd: "cut", uiIcon: "ui-icon-scissors"},
5362
{title: "Copy", cmd: "copy", uiIcon: "ui-icon-copy"},
@@ -61,15 +70,19 @@
6170
select: function(event, ui) {
6271
var menuId = ui.item.find(">a").attr("href");
6372
alert("select " + menuId + " on " + $(event.relatedTarget).text());
73+
},
74+
beforeOpen: function(event) {
75+
// alert("beforeopen on " + $(event.relatedTarget).text());
6476
}
6577
});
6678

67-
/* Init menu by passing an <ul> element. */
79+
/* Menu 1: init menu by passing an <ul> element. */
6880

6981
$("#container").contextmenu({
7082
delegate: ".hasmenu2",
71-
// ignoreParentSelect: false,
7283
menu: "#options",
84+
preventSelect: true,
85+
taphold: true,
7386
focus: function(event, ui) {
7487
var menuId = ui.item.find(">a").attr("href");
7588
$("#info").text("focus " + menuId);
@@ -89,7 +102,7 @@
89102
}
90103
});
91104

92-
/* Open an existing menu without clicking */
105+
/* Open and close an existing menu without programatically. */
93106

94107
$("#triggerPopup").click(function(){
95108
// Trigger popup menu on the first target element
@@ -106,6 +119,16 @@
106119
<h1>jquery.contextmenu.js</h1>
107120

108121
<p><a href="https://github.com/mar10/jquery-contextmenu">View project on GitHub</a></p>
122+
123+
Not-so-obvious features:
124+
<ul>
125+
<li>`preventSelect: true` prevents accidential selection of the menu
126+
targets (i.e. 'AAA') when double-clicking or dragging the mouse.
127+
<li>`taphold: true` enables long-press to open the menu (useful on
128+
tablet computers).
129+
<li>Ctrl+Click or two-finger-click on the touchpad also works (MacBook).
130+
<li>The menu is modified in the `beforeOpen` event.
131+
</ul>
109132

110133
<p>Right-click in an element to open the context menu (initialized by command-array):</p>
111134
<div>

jquery.ui-contextmenu.js

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,47 +14,74 @@
1414
// $menu = $(menu);
1515
// return $menu.data("ui-menu") || $menu.data("menu");
1616
// }
17-
var NS = ".contextmenu";
17+
var NS = ".contextmenu",
18+
supportSelectstart = "onselectstart" in document.createElement("div");
1819

1920
$.widget("ui.contextmenu", {
2021
version: "0.3.0",
2122
options: {
2223
delegate: "[data-menu]", // selector
2324
ignoreParentSelect: true, // Don't trigger 'select' for sub-menu parents
24-
menu: null, // selector or jQuery or a function returning such
25-
taphold: true, // open menu on taphold events (requires external plugins)
25+
menu: null, // selector or jQuery or a function returning such
26+
preventSelect: false, // disable text selection of target
27+
taphold: false, // open menu on taphold events (requires external plugins)
2628
// Events:
27-
beforeOpen: $.noop, // menu about to open; return `false` to prevent opening
28-
blur: $.noop, // menu option lost focus
29-
close: $.noop, // menu was closed
30-
create: $.noop, // menu was initialized
31-
focus: $.noop, // menu option got focus
32-
init: $.noop, // ui-contextmenu was initialized
33-
open: $.noop, // menu was opened
34-
select: $.noop // menu option was selected; return `false` to prevent closing
29+
beforeOpen: $.noop, // menu about to open; return `false` to prevent opening
30+
blur: $.noop, // menu option lost focus
31+
close: $.noop, // menu was closed
32+
create: $.noop, // menu was initialized
33+
focus: $.noop, // menu option got focus
34+
init: $.noop, // ui-contextmenu was initialized
35+
open: $.noop, // menu was opened
36+
select: $.noop // menu option was selected; return `false` to prevent closing
3537
},
3638
_create: function () {
3739
var opts = this.options,
38-
eventNames = "contextmenu" + NS;
40+
eventNames = "contextmenu" + NS,
41+
targetId = this.element.uniqueId().attr("id");
42+
3943
if(opts.taphold){
4044
eventNames += " taphold" + NS;
4145
}
46+
if(opts.preventSelect){
47+
// Create a global style for all potential menu targets
48+
this.$headStyle = $("<style>")
49+
.prop("type", "text/css")
50+
.html("#" + targetId + " " + opts.delegate + " {" +
51+
"-webkit-user-select: none;" +
52+
"-khtml-user-select: none;" +
53+
"-moz-user-select: none;" +
54+
"-ms-user-select: none;" +
55+
"user-select: none;" +
56+
"}")
57+
.appendTo("head");
58+
// TODO: the selectstart is not supported by FF?
59+
if(supportSelectstart){
60+
this.element.delegate(opts.delegate, "selectstart" + NS, function(event){
61+
event.preventDefault();
62+
});
63+
}
64+
}
4265
if($.isArray(opts.menu)){
4366
this.orgMenu = opts.menu;
4467
opts.menu = $.ui.contextmenu.createMenuMarkup(opts.menu);
4568
}
46-
47-
this.element.delegate(this.options.delegate, eventNames, $.proxy(this._openMenu, this));
69+
this.element.delegate(opts.delegate, eventNames, $.proxy(this._openMenu, this));
4870
// emulate a 'taphold' event
4971
this._trigger("init");
5072
},
5173
/**
5274
*
5375
*/
5476
_destroy: function(key, value){
77+
if(this.$headStyle){
78+
this.$headStyle.remove();
79+
this.$headStyle = null;
80+
}
5581
if(this.orgMenu){
5682
this.options.menu.remove();
5783
this.options.menu = this.orgMenu;
84+
this.orgMenu = null;
5885
}
5986
},
6087
/**
@@ -73,10 +100,10 @@
73100
return (typeof $menu === "string") ? $($menu) : $menu;
74101
},
75102
/** Return ui-menu widget instance (works on pre and post jQueryUI 1.9). */
76-
_getMenuWidget: function(){
77-
var $menu = this._getMenu();
78-
return $menu.data("ui-menu") || $menu.data("menu");
79-
},
103+
// _getMenuWidget: function(){
104+
// var $menu = this._getMenu();
105+
// return $menu.data("ui-menu") || $menu.data("menu");
106+
// },
80107
/** Open dropdown. */
81108
_openMenu: function(event){
82109
var self = this,

jquery.ui-contextmenu.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ui-contextmenu.jquery.json

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,31 @@
11
{
2-
"name": "ui-contextmenu",
3-
"title": "jQuery UI context menu plugin",
4-
"description": "Turns a jQuery UI Menu widget into a context menu.",
5-
"version": "0.3.0",
6-
"homepage": "https://github.com/mar10/jquery-ui-contextmenu",
7-
"author": {
8-
"name": "Martin Wendt",
9-
"email": "jquery@wwwendt.de",
10-
"url": "http://careers.stackoverflow.com/martin-wendt"
11-
},
12-
"repository": {
13-
"type": "git",
14-
"url": "https://github.com/mar10/jquery-ui-contextmenu"
15-
},
16-
"demo": "http://wwwendt.de/tech/demo/jquery-contextmenu/demo/",
17-
"docs": "https://github.com/mar10/jquery-ui-contextmenu/blob/master/README.md",
18-
"bugs": "https://github.com/mar10/jquery-ui-contextmenu/issues",
19-
"licenses": [
20-
{
21-
"type": "MIT",
22-
"url": "https://github.com/mar10/jquery-ui-contextmenu/blob/master/MIT-LICENSE.txt"
23-
}
24-
],
25-
"dependencies": {
26-
"jquery": ">=1.7",
27-
"jqueryui": ">=1.9"
28-
},
29-
"keywords": ["context-menu", "contetxtmenu", "menu", "jquery-ui-menu", "popup", "right-click"]
2+
"name": "ui-contextmenu",
3+
"title": "jQuery UI context menu plugin",
4+
"description": "Turns a jQuery UI Menu widget into a context menu.",
5+
"version": "0.3.0",
6+
"homepage": "https://github.com/mar10/jquery-ui-contextmenu",
7+
"author": {
8+
"name": "Martin Wendt",
9+
"email": "jquery@wwwendt.de",
10+
"url": "http://careers.stackoverflow.com/martin-wendt"
11+
},
12+
"repository": {
13+
"type": "git",
14+
"url": "https://github.com/mar10/jquery-ui-contextmenu"
15+
},
16+
"demo": "http://wwwendt.de/tech/demo/jquery-contextmenu/demo/",
17+
"docs": "https://github.com/mar10/jquery-ui-contextmenu/blob/master/README.md",
18+
"bugs": "https://github.com/mar10/jquery-ui-contextmenu/issues",
19+
"licenses": [
20+
{
21+
"type": "MIT",
22+
"url": "https://github.com/mar10/jquery-ui-contextmenu/blob/master/MIT-LICENSE.txt"
23+
}
24+
],
25+
"dependencies": {
26+
"jquery": ">=1.7",
27+
"jqueryui": ">=1.9"
28+
},
29+
"keywords": ["context-menu", "contetxtmenu", "menu", "delegate",
30+
"jquery-ui-menu", "popup", "right-click"]
3031
}

0 commit comments

Comments
 (0)