Upgraded the jQuery-contextMenu to v2.1.0 (latest stable version) in

order to fix the issue rendering the context menu for longer text.

Needs to do some modification in the existing pgAdmin4 CSS theme to make
it looks like/near the existing look and feel.
pull/3/head
Ashesh Vashi 2016-03-30 19:08:25 +05:30
parent 067c269fc8
commit d70535385b
14 changed files with 335 additions and 152 deletions

View File

@ -10,7 +10,7 @@ Modernizr 2.6.2 MIT/BSD http://modernizr.com/
AlertifyJS 1.1.0 MIT http://alertifyjs.com/
CodeMirror 4.12 MIT http://codemirror.net/
aciTree 4.5.0-rc.7 MIT/GPL http://acoderinsights.ro/en/aciTree-tree-view-with-jQuery
contextMenu 1.9.2 MIT https://github.com/swisnl/jQuery-contextMenu
contextMenu 2.1.0 MIT https://github.com/swisnl/jQuery-contextMenu
wcDocker 0f5690318c MIT/GPL https://github.com/WebCabin/wcDocker
Require.js 2.1.18 BSD/MIT http://requirejs.org/
Underscore.js 1.8.3 MIT http://underscorejs.org/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 620 B

View File

@ -1,48 +1,113 @@
@charset "UTF-8";
/*!
* jQuery contextMenu - Plugin for simple contextMenu handling
*
* Version: v1.9.2
* Version: v2.1.0
*
* Authors: Björn Brala (SWIS.nl), Rodney Rehm, Addy Osmani (patches for FF)
* Web: http://swisnl.github.io/jQuery-contextMenu/
*
* Copyright (c) 2011-2015 SWIS BV and contributors
* Copyright (c) 2011-2016 SWIS BV and contributors
*
* Licensed under
* MIT License http://www.opensource.org/licenses/mit-license
* Date: 2015-10-25T14:36:11.963Z
*
* Date: 2016-02-28T09:41:28.803Z
*/
@font-face {
font-family: "context-menu-icons";
font-style: normal;
font-weight: normal;
src: url("font/context-menu-icons.eot?2qmzf");
src: url("font/context-menu-icons.eot?2qmzf#iefix") format("embedded-opentype"), url("font/context-menu-icons.woff2?2qmzf") format("woff2"), url("font/context-menu-icons.woff?2qmzf") format("woff"), url("font/context-menu-icons.ttf?2qmzf") format("truetype");
}
.context-menu-icon:before {
position: absolute;
top: 50%;
left: 0;
width: 28px;
font-family: "context-menu-icons";
font-size: 16px;
font-style: normal;
font-weight: normal;
line-height: 1;
color: #2980b9;
text-align: center;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.context-menu-icon-add:before {
content: "";
}
.context-menu-icon-copy:before {
content: "";
}
.context-menu-icon-cut:before {
content: "";
}
.context-menu-icon-delete:before {
content: "";
}
.context-menu-icon-edit:before {
content: "";
}
.context-menu-icon-paste:before {
content: "";
}
.context-menu-icon-quit:before {
content: "";
}
.context-menu-icon.context-menu-hover:before {
color: #fff;
}
.context-menu-list {
position: absolute;
display: inline-block;
min-width: 120px;
max-width: 250px;
padding: 0;
margin: 0;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
min-width: 180px;
max-width: 360px;
padding: 4px 0;
margin: 5px;
font-family: inherit;
font-size: inherit;
list-style-type: none;
background: #eee;
border: 1px solid #ddd;
background: #fff;
border: 1px solid #bebebe;
border-radius: 3px;
-webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, .5);
box-shadow: 0 2px 5px rgba(0, 0, 0, .5);
}
.context-menu-item {
position: relative;
padding: 2px 2px 2px 24px;
padding: 3px 28px;
color: #2f2f2f;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #eee;
background-color: #fff;
}
.context-menu-separator {
padding-bottom: 0;
border-bottom: 1px solid #ddd;
padding: 0;
margin: 5px 0;
border-bottom: 1px solid #e6e6e6;
}
.context-menu-item > label > input,
@ -53,62 +118,49 @@
user-select: text;
}
.context-menu-item.hover {
.context-menu-item.context-menu-hover {
color: #fff;
cursor: pointer;
background-color: #39f;
background-color: #2980b9;
}
.context-menu-item.disabled {
color: #666;
.context-menu-item.context-menu-disabled {
color: #626262;
background-color: #fff;
}
.context-menu-input.hover,
.context-menu-item.disabled.hover {
.context-menu-item.context-menu-disabled {
color: #626262;
}
.context-menu-input.context-menu-hover,
.context-menu-item.context-menu-disabled.context-menu-hover {
cursor: default;
background-color: #eee;
}
.context-menu-submenu:after {
position: absolute;
top: 0;
right: 3px;
top: 50%;
right: 8px;
z-index: 1;
color: #666;
content: ">";
width: 0;
height: 0;
content: '';
border-color: transparent transparent transparent #2f2f2f;
border-style: solid;
border-width: 4px 0 4px 4px;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
}
/* icons
#protip:
In case you want to use sprites for icons (which I would suggest you do) have a look at
http://css-tricks.com/13224-pseudo-spriting/ to get an idea of how to implement
.context-menu-item.icon:before {}
/**
* Inputs
*/
.context-menu-item.icon {
min-height: 18px;
list-style-type: none;
background-repeat: no-repeat;
background-position: 4px 2px;
}
.context-menu-item.icon-edit {
background-image: url(images/page_white_edit.png);
}
.context-menu-item.icon-cut {
background-image: url(images/cut.png);
}
.context-menu-item.icon-copy {
background-image: url(images/page_white_copy.png);
}
.context-menu-item.icon-paste {
background-image: url(images/page_white_paste.png);
}
.context-menu-item.icon-delete {
background-image: url(images/page_white_delete.png);
}
.context-menu-item.icon-add {
background-image: url(images/page_white_add.png);
}
.context-menu-item.icon-quit {
background-image: url(images/door.png);
.context-menu-item.context-menu-input {
padding: 5px 10px;
}
/* vertically align inside labels */
@ -119,10 +171,8 @@
/* position checkboxes and radios as icons */
.context-menu-input > label > input[type="checkbox"],
.context-menu-input > label > input[type="radio"] {
margin-left: -17px;
}
.context-menu-input > label > span {
margin-left: 5px;
position: relative;
top: 3px;
}
.context-menu-input > label,
@ -139,6 +189,7 @@
.context-menu-input > label > textarea {
height: 100px;
}
.context-menu-item > .context-menu-list {
top: 5px;
/* re-positioned by js */
@ -146,7 +197,7 @@
display: none;
}
.context-menu-item.visible > .context-menu-list {
.context-menu-item.context-menu-visible > .context-menu-list {
display: block;
}

12
web/pgadmin/static/css/jQuery-contextMenu/jquery.contextMenu.min.css vendored Executable file → Normal file
View File

@ -1,16 +1,16 @@
/*!
@charset "UTF-8";/*!
* jQuery contextMenu - Plugin for simple contextMenu handling
*
* Version: v1.9.2
* Version: v2.1.0
*
* Authors: Björn Brala (SWIS.nl), Rodney Rehm, Addy Osmani (patches for FF)
* Web: http://swisnl.github.io/jQuery-contextMenu/
*
* Copyright (c) 2011-2015 SWIS BV and contributors
* Copyright (c) 2011-2016 SWIS BV and contributors
*
* Licensed under
* MIT License http://www.opensource.org/licenses/mit-license
* Date: 2015-10-25T14:36:11.963Z
*/.context-menu-list{position:absolute;display:inline-block;min-width:120px;max-width:250px;padding:0;margin:0;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;list-style-type:none;background:#eee;border:1px solid #ddd;-webkit-box-shadow:0 2px 5px rgba(0,0,0,.5);box-shadow:0 2px 5px rgba(0,0,0,.5)}.context-menu-item{position:relative;padding:2px 2px 2px 24px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#eee}.context-menu-separator{padding-bottom:0;border-bottom:1px solid #ddd}.context-menu-item>label>input,.context-menu-item>label>textarea{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.context-menu-item.hover{cursor:pointer;background-color:#39f}.context-menu-item.disabled{color:#666}.context-menu-input.hover,.context-menu-item.disabled.hover{cursor:default;background-color:#eee}.context-menu-submenu:after{position:absolute;top:0;right:3px;z-index:1;color:#666;content:">"}.context-menu-item.icon{min-height:18px;list-style-type:none;background-repeat:no-repeat;background-position:4px 2px}.context-menu-item.icon-edit{background-image:url(images/page_white_edit.png)}.context-menu-item.icon-cut{background-image:url(images/cut.png)}.context-menu-item.icon-copy{background-image:url(images/page_white_copy.png)}.context-menu-item.icon-paste{background-image:url(images/page_white_paste.png)}.context-menu-item.icon-delete{background-image:url(images/page_white_delete.png)}.context-menu-item.icon-add{background-image:url(images/page_white_add.png)}.context-menu-item.icon-quit{background-image:url(images/door.png)}.context-menu-input>label>*{vertical-align:top}.context-menu-input>label>input[type=checkbox],.context-menu-input>label>input[type=radio]{margin-left:-17px}.context-menu-input>label>span{margin-left:5px}.context-menu-input>label,.context-menu-input>label>input[type=text],.context-menu-input>label>select,.context-menu-input>label>textarea{display:block;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.context-menu-input>label>textarea{height:100px}.context-menu-item>.context-menu-list{top:5px;right:-5px;display:none}.context-menu-item.visible>.context-menu-list{display:block}.context-menu-accesskey{text-decoration:underline}
*
* Date: 2016-02-28T09:41:28.803Z
*/@font-face{font-family:context-menu-icons;font-style:normal;font-weight:400;src:url(font/context-menu-icons.eot?2qmzf);src:url(font/context-menu-icons.eot?2qmzf#iefix) format("embedded-opentype"),url(font/context-menu-icons.woff2?2qmzf) format("woff2"),url(font/context-menu-icons.woff?2qmzf) format("woff"),url(font/context-menu-icons.ttf?2qmzf) format("truetype")}.context-menu-icon:before{position:absolute;top:50%;left:0;width:28px;font-family:context-menu-icons;font-size:16px;font-style:normal;font-weight:400;line-height:1;color:#2980b9;text-align:center;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.context-menu-icon-add:before{content:""}.context-menu-icon-copy:before{content:""}.context-menu-icon-cut:before{content:""}.context-menu-icon-delete:before{content:""}.context-menu-icon-edit:before{content:""}.context-menu-icon-paste:before{content:""}.context-menu-icon-quit:before{content:""}.context-menu-icon.context-menu-hover:before{color:#fff}.context-menu-list{position:absolute;display:inline-block;min-width:180px;max-width:360px;padding:4px 0;margin:5px;font-family:inherit;font-size:inherit;list-style-type:none;background:#fff;border:1px solid #bebebe;border-radius:3px;-webkit-box-shadow:0 2px 5px rgba(0,0,0,.5);box-shadow:0 2px 5px rgba(0,0,0,.5)}.context-menu-item{position:relative;padding:3px 28px;color:#2f2f2f;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#fff}.context-menu-separator{padding:0;margin:5px 0;border-bottom:1px solid #e6e6e6}.context-menu-item>label>input,.context-menu-item>label>textarea{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.context-menu-item.context-menu-hover{color:#fff;cursor:pointer;background-color:#2980b9}.context-menu-item.context-menu-disabled{background-color:#fff;color:#626262}.context-menu-input.context-menu-hover,.context-menu-item.context-menu-disabled.context-menu-hover{cursor:default;background-color:#eee}.context-menu-submenu:after{position:absolute;top:50%;right:8px;z-index:1;width:0;height:0;content:'';border-color:transparent transparent transparent #2f2f2f;border-style:solid;border-width:4px 0 4px 4px;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%)}.context-menu-item.context-menu-input{padding:5px 10px}.context-menu-input>label>*{vertical-align:top}.context-menu-input>label>input[type=checkbox],.context-menu-input>label>input[type=radio]{position:relative;top:3px}.context-menu-input>label,.context-menu-input>label>input[type=text],.context-menu-input>label>select,.context-menu-input>label>textarea{display:block;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.context-menu-input>label>textarea{height:100px}.context-menu-item>.context-menu-list{top:5px;right:-5px;display:none}.context-menu-item.context-menu-visible>.context-menu-list{display:block}.context-menu-accesskey{text-decoration:underline}
/*# sourceMappingURL=jquery.contextMenu.min.css.map */

File diff suppressed because one or more lines are too long

View File

@ -182,6 +182,7 @@
.wcMenuList, .context-menu-list {
border: 1px solid #dddddd;
z-index: 999 !important;
background: #dddddd;
}
.wcMenuItem, .context-menu-item {
@ -240,11 +241,7 @@
vertical-align: top;
}
.context-menu-submenu:after {
content: '>' !important;
}
.wcTabIcon {
.wcPanelTab > div > .wcTabIcon {
display: inline-block;
text-align: center;
padding-left: 20px;
@ -270,3 +267,49 @@
right: 5px;
color: white;
}
.context-menu-list {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
}
.context-menu-icon:before {
color: #222;
font-size: 14px;
}
.context-menu-icon-fa:before {
font-family: 'FontAwesome'
}
.context-menu-item {
display:block;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
font-weight: normal;
}
.context-menu-list {
padding: 2px 0;
}
.context-menu-list > .context-menu-item {
display:block !important;
}
.context-menu-list > .context-menu-separator {
margin: 0;
border: 1px solid #fff;
}
.context-menu-icon-wcTabIcon {
text-align: left;
padding: 3px 28px;
background-position-x: 5px;
height: auto;
background-position-y: 4px
}
ul.dropdown-menu > li.menu-item > a > i.wcTabIcon {
width: 15px;
}

View File

@ -1,18 +1,18 @@
/*!
* jQuery contextMenu v1.9.2 - Plugin for simple contextMenu handling
* jQuery contextMenu v2.1.0 - Plugin for simple contextMenu handling
*
* Version: v1.9.2
* Version: v2.1.0
*
* Authors: Björn Brala (SWIS.nl), Rodney Rehm, Addy Osmani (patches for FF)
* Web: http://swisnl.github.io/jQuery-contextMenu/
*
* Copyright (c) 2011-2015 SWIS BV and contributors
* Copyright (c) 2011-2016 SWIS BV and contributors
*
* Licensed under
* MIT License http://www.opensource.org/licenses/mit-license
* GPL v3 http://opensource.org/licenses/GPL-3.0
*
* Date: 2015-10-25T14:36:12.905Z
* Date: 2016-02-28T09:41:24.636Z
*/
(function (factory) {
@ -60,12 +60,14 @@
})();
*/
/* jshint ignore:start */
if (!$.ui || !$.widget) {
// duck punch $.cleanData like jQueryUI does to get that remove event
$.cleanData = (function (orig) {
return function (elems) {
var events, elem, i;
for (i = 0; (elem = elems[i]) != null; i++) {
for (i = 0; elems[i] != null; i++) {
elem = elems[i];
try {
// Only trigger remove when necessary to save time
events = $._data(elem, 'events');
@ -80,6 +82,7 @@
};
})($.cleanData);
}
/* jshint ignore:end */
var // currently active contextMenu trigger
$currentTrigger = null,
@ -114,19 +117,19 @@
// Default classname configuration to be able avoid conflicts in frameworks
classNames : {
hover: 'hover', // Item hover
disabled: 'disabled', // Item disabled
visible: 'visible', // Item visible
notSelectable: 'not-selectable', // Item not selectable
hover: 'context-menu-hover', // Item hover
disabled: 'context-menu-disabled', // Item disabled
visible: 'context-menu-visible', // Item visible
notSelectable: 'context-menu-not-selectable', // Item not selectable
icon: 'icon',
iconEdit: 'icon-edit',
iconCut: 'icon-cut',
iconCopy: 'icon-copy',
iconPaste: 'icon-paste',
iconDelete: 'icon-delete',
iconAdd: 'icon-add',
iconQuit: 'icon-quit'
icon: 'context-menu-icon',
iconEdit: 'context-menu-icon-edit',
iconCut: 'context-menu-icon-cut',
iconCopy: 'context-menu-icon-copy',
iconPaste: 'context-menu-icon-paste',
iconDelete: 'context-menu-icon-delete',
iconAdd: 'context-menu-icon-add',
iconQuit: 'context-menu-icon-quit'
},
// determine position to show menu at
@ -269,6 +272,14 @@
return;
}
// Let the current contextmenu decide if it should show or not based on its own trigger settings
if (e.mouseButton !== undefined && e.data) {
if (!(e.data.trigger === 'left' && e.mouseButton === 0) && !(e.data.trigger === 'right' && e.mouseButton === 2)) {
// Mouse click is not valid.
return;
}
}
// abort event if menu is visible for this trigger
if ($this.hasClass('context-menu-active')) {
return;
@ -324,7 +335,15 @@
}
if (showMenu) {
// show menu
op.show.call($this, e.data, e.pageX, e.pageY);
var menuContainer = (e.data.appendTo === null ? $('body') : $(e.data.appendTo));
var srcElement = e.target || e.srcElement || e.originalTarget;
if (e.offsetX !== undefined && e.offsetY !== undefined) {
op.show.call($this, e.data,
$(srcElement).offset().left - menuContainer.offset().left + e.offsetX,
$(srcElement).offset().top - menuContainer.offset().top + e.offsetY);
} else {
op.show.call($this, e.data, e.pageX, e.pageY);
}
}
}
},
@ -431,7 +450,7 @@
var triggerAction = ((root.trigger === 'left' && button === 0) || (root.trigger === 'right' && button === 2));
// find the element that would've been clicked, wasn't the layer in the way
if (document.elementFromPoint) {
if (document.elementFromPoint && root.$layer) {
root.$layer.hide();
target = document.elementFromPoint(x - $win.scrollLeft(), y - $win.scrollTop());
root.$layer.show();
@ -468,7 +487,7 @@
if (target && triggerAction) {
root.$trigger.one('contextmenu:hidden', function () {
$(target).contextMenu({x: x, y: y});
$(target).contextMenu({ x: x, y: y, button: button });
});
}
@ -491,7 +510,30 @@
if ($currentTrigger) {
opt = $currentTrigger.data('contextMenu') || {};
}
// If the trigger happen on a element that are above the contextmenu do this
if (opt.zIndex === undefined) {
opt.zIndex = 0;
}
var targetZIndex = 0;
var getZIndexOfTriggerTarget = function (target) {
if (target.style.zIndex !== '') {
targetZIndex = target.style.zIndex;
} else {
if (target.offsetParent !== null && target.offsetParent !== undefined) {
getZIndexOfTriggerTarget(target.offsetParent);
}
else if (target.parentElement !== null && target.parentElement !== undefined) {
getZIndexOfTriggerTarget(target.parentElement);
}
}
};
getZIndexOfTriggerTarget(e.target);
// If targetZIndex is heigher then opt.zIndex dont progress any futher.
// This is used to make sure that if you are using a dialog with a input / textarea / contenteditable div
// and its above the contextmenu it wont steal keys events
if (targetZIndex > opt.zIndex) {
return;
}
switch (e.keyCode) {
case 9:
case 38: // up
@ -500,7 +542,9 @@
if (opt.isInput) {
if (e.keyCode === 9 && e.shiftKey) {
e.preventDefault();
opt.$selected && opt.$selected.find('input, textarea, select').blur();
if(opt.$selected) {
opt.$selected.find('input, textarea, select').blur();
}
opt.$menu.trigger('prevcommand');
return;
} else if (e.keyCode === 38 && opt.$selected.find('input, textarea, select').prop('type') === 'checkbox') {
@ -512,6 +556,7 @@
opt.$menu.trigger('prevcommand');
return;
}
break;
// omitting break;
// case 9: // tab - reached through omitted break;
case 40: // down
@ -519,7 +564,9 @@
if (opt.isInput) {
if (e.keyCode === 9) {
e.preventDefault();
opt.$selected && opt.$selected.find('input, textarea, select').blur();
if(opt.$selected) {
opt.$selected.find('input, textarea, select').blur();
}
opt.$menu.trigger('nextcommand');
return;
} else if (e.keyCode === 40 && opt.$selected.find('input, textarea, select').prop('type') === 'checkbox') {
@ -584,7 +631,7 @@
}
break;
}
if (typeof opt.$selected !== 'undefined') {
if (typeof opt.$selected !== 'undefined' && opt.$selected !== null) {
opt.$selected.trigger('mouseup');
}
return;
@ -613,7 +660,7 @@
// pass event to selected item,
// stop propagation to avoid endless recursion
e.stopPropagation();
if (typeof opt.$selected !== 'undefined') {
if (typeof opt.$selected !== 'undefined' && opt.$selected !== null) {
opt.$selected.trigger(e);
}
},
@ -634,8 +681,8 @@
$prev = !opt.$selected || !opt.$selected.prev().length ? $children.last() : opt.$selected.prev(),
$round = $prev;
// skip disabled
while ($prev.hasClass(root.classNames.disabled) || $prev.hasClass(root.classNames.notSelectable)) {
// skip disabled or hidden elements
while ($prev.hasClass(root.classNames.disabled) || $prev.hasClass(root.classNames.notSelectable) || $prev.is(':hidden')) {
if ($prev.prev().length) {
$prev = $prev.prev();
} else {
@ -679,7 +726,7 @@
$round = $next;
// skip disabled
while ($next.hasClass(root.classNames.disabled) || $next.hasClass(root.classNames.notSelectable)) {
while ($next.hasClass(root.classNames.disabled) || $next.hasClass(root.classNames.notSelectable) || $next.is(':hidden')) {
if ($next.next().length) {
$next = $next.next();
} else {
@ -753,6 +800,7 @@
// make sure only one item is selected
(opt.$menu ? opt : root).$menu
.children('.' + root.classNames.hover).trigger('contextmenu:blur')
.children('.hover').trigger('contextmenu:blur');
if ($this.hasClass(root.classNames.disabled) || $this.hasClass(root.classNames.notSelectable)) {
@ -770,7 +818,7 @@
root = data.contextMenuRoot;
if (root !== opt && root.$layer && root.$layer.is(e.relatedTarget)) {
if (typeof root.$selected !== 'undefined') {
if (typeof root.$selected !== 'undefined' && root.$selected !== null) {
root.$selected.trigger('contextmenu:blur');
}
e.preventDefault();
@ -835,9 +883,10 @@
$this
.addClass([root.classNames.hover, root.classNames.visible].join(' '))
.siblings()
// select other items and included items
.parent().find('.context-menu-item').not($this)
.removeClass(root.classNames.visible)
.filter(root.classNames.hover)
.filter('.' + root.classNames.hover)
.trigger('contextmenu:blur');
// remember selected
@ -889,7 +938,12 @@
// make sure we're in front
if (opt.zIndex) {
css.zIndex = zindex($trigger) + opt.zIndex;
var additionalZValue = opt.zIndex;
// If opt.zIndex is a function, call the function to get the right zIndex.
if (typeof opt.zIndex === 'function') {
additionalZValue = opt.zIndex.call($trigger, opt);
}
css.zIndex = zindex($trigger) + additionalZValue;
}
// add layer
@ -920,8 +974,10 @@
pos.bottom = pos.top + $trigger.outerHeight();
if (opt.$layer && !opt.hovering && (!(e.pageX >= pos.left && e.pageX <= pos.right) || !(e.pageY >= pos.top && e.pageY <= pos.bottom))) {
// if mouse in menu...
opt.$menu.trigger('contextmenu:hide');
/* Additional hover check after short time, you might just miss the edge of the menu */
setTimeout(function () {
if (!opt.hovering) { opt.$menu.trigger('contextmenu:hide'); }
}, 50);
}
});
}
@ -962,37 +1018,41 @@
// remove selected
opt.$menu.find('.' + opt.classNames.hover).trigger('contextmenu:blur');
opt.$selected = null;
// collapse all submenus
opt.$menu.find('.' + opt.classNames.visible).removeClass(opt.classNames.visible);
// unregister key and mouse handlers
// $(document).off('.contextMenuAutoHide keydown.contextMenu'); // http://bugs.jquery.com/ticket/10705
$(document).off('.contextMenuAutoHide').off('keydown.contextMenu');
// hide menu
opt.$menu && opt.$menu[opt.animation.hide](opt.animation.duration, function () {
// tear down dynamically built menu after animation is completed.
if (opt.build) {
opt.$menu.remove();
$.each(opt, function (key) {
switch (key) {
case 'ns':
case 'selector':
case 'build':
case 'trigger':
return true;
if(opt.$menu){
opt.$menu[opt.animation.hide](opt.animation.duration, function () {
// tear down dynamically built menu after animation is completed.
if (opt.build) {
opt.$menu.remove();
$.each(opt, function (key) {
switch (key) {
case 'ns':
case 'selector':
case 'build':
case 'trigger':
return true;
default:
opt[key] = undefined;
try {
delete opt[key];
} catch (e) {
}
return true;
}
});
}
default:
opt[key] = undefined;
try {
delete opt[key];
} catch (e) {
}
return true;
}
});
}
setTimeout(function () {
$trigger.trigger('contextmenu:hidden');
}, 10);
});
setTimeout(function () {
$trigger.trigger('contextmenu:hidden');
}, 10);
});
}
},
create: function (opt, root) {
if (root === undefined) {
@ -1011,7 +1071,28 @@
}
});
root.accesskeys || (root.accesskeys = {});
if(!root.accesskeys){
root.accesskeys = {};
}
function createNameNode(item) {
var $name = $('<span></span>');
if (item._accesskey) {
if (item._beforeAccesskey) {
$name.append(document.createTextNode(item._beforeAccesskey));
}
$('<span></span>')
.addClass('context-menu-accesskey')
.text(item._accesskey)
.appendTo($name);
if (item._afterAccesskey) {
$name.append(document.createTextNode(item._afterAccesskey));
}
} else {
$name.text(item.name);
}
return $name;
}
// create contextMenu items
$.each(opt.items, function (key, item) {
@ -1042,7 +1123,12 @@
for (var i = 0, ak; ak = aks[i]; i++) {
if (!root.accesskeys[ak]) {
root.accesskeys[ak] = item;
item._name = item.name.replace(new RegExp('(' + ak + ')', 'i'), '<span class="context-menu-accesskey">$1</span>');
var matched = item.name.match(new RegExp('^(.*?)(' + ak + ')(.*)$', 'i'));
if (matched) {
item._beforeAccesskey = matched[1];
item._accesskey = matched[2];
item._afterAccesskey = matched[3];
}
break;
}
}
@ -1066,7 +1152,8 @@
$t.addClass('context-menu-html ' + root.classNames.notSelectable);
} else if (item.type) {
$label = $('<label></label>').appendTo($t);
$('<span></span>').html(item._name || item.name).appendTo($label);
createNameNode(item).appendTo($label);
$t.addClass('context-menu-input');
opt.hasTypes = true;
$.each([opt, root], function (i, k) {
@ -1078,7 +1165,7 @@
}
switch (item.type) {
case 'seperator':
case 'cm_seperator':
break;
case 'text':
@ -1128,7 +1215,8 @@
break;
case 'sub':
$('<span></span>').html(item._name || item.name).appendTo($t);
createNameNode(item).appendTo($t);
item.appendTo = item.$node;
op.create(item, root);
$t.data('contextMenu', item).addClass('context-menu-submenu');
@ -1146,7 +1234,7 @@
k.callbacks[key] = item.callback;
}
});
$('<span></span>').html(item._name || item.name || '').appendTo($t);
createNameNode(item).appendTo($t);
break;
}
@ -1164,10 +1252,9 @@
// add icons
if (item.icon) {
if ($.isFunction(item.icon)) {
item._icon = item.icon.call(this, $t, key, item);
item._icon = item.icon.call(this, this, $t, key, item);
} else {
item._icon = root.classNames.icon + ' ' + root.classNames.icon + '-' + item.icon;
}
$t.addClass(item._icon);
}
@ -1202,7 +1289,7 @@
// determine width of absolutely positioned element
$menu.css({position: 'absolute', display: 'block'});
// don't apply yet, because that would break nested elements' widths
$menu.data('width', Math.ceil($menu.width()));
$menu.data('width', Math.ceil($menu.outerWidth()));
// reset styles so they allow nested elements to grow/shrink naturally
$menu.css({
position: 'static',
@ -1221,7 +1308,7 @@
display: '',
minWidth: '',
maxWidth: ''
}).width(function () {
}).outerWidth(function () {
return $(this).data('width');
});
}
@ -1253,7 +1340,7 @@
if ($.isFunction(item.icon)) {
$item.removeClass(item._icon);
item._icon = item.icon.call(this, $trigger, key, item);
item._icon = item.icon.call(this, $trigger, $item, key, item);
$item.addClass(item._icon);
}
@ -1329,10 +1416,12 @@
if (operation === undefined) {
this.first().trigger('contextmenu');
} else if (operation.x !== undefined && operation.y !== undefined) {
this.first().trigger($.Event('contextmenu', {pageX: operation.x, pageY: operation.y}));
this.first().trigger($.Event('contextmenu', { pageX: operation.x, pageY: operation.y, mouseButton: operation.button }));
} else if (operation === 'hide') {
var $menu = this.first().data('contextMenu') ? this.first().data('contextMenu').$menu : null;
$menu && $menu.trigger('contextmenu:hide');
if($menu){
$menu.trigger('contextmenu:hide');
}
} else if (operation === 'destroy') {
$.contextMenu('destroy', {context: this});
} else if ($.isPlainObject(operation)) {

File diff suppressed because one or more lines are too long