New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

cytoscape-cxtmenu

Package Overview
Dependencies
Maintainers
3
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cytoscape-cxtmenu - npm Package Compare versions

Comparing version 2.10.3 to 3.0.0

.babelrc

12

bower.json
{
"name": "cytoscape-cxtmenu",
"description": "A context menu for Cytoscape.js",
"description": "A circular, swipeable context menu extension for Cytoscape.js",
"main": "cytoscape-cxtmenu.js",
"dependencies": {
"cytoscape": "^3.2.0"
},
"repository": {

@@ -9,5 +12,2 @@ "type": "git",

},
"dependencies": {
"cytoscape": "^2.2.0 || ^3.0.0"
},
"ignore": [

@@ -22,7 +22,5 @@ "**/.*",

"cytoscape",
"cytoscape.js",
"cytoscapejs",
"extension"
"cytoscape-extension"
],
"license": "MIT"
}

@@ -1,661 +0,763 @@

/*!
Copyright (c) The Cytoscape Consortium
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["cytoscapeCxtmenu"] = factory();
else
root["cytoscapeCxtmenu"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 4);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the “Software”), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
"use strict";
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
var defaults = __webpack_require__(2);
var assign = __webpack_require__(1);
;(function(){ 'use strict';
var _require = __webpack_require__(3),
removeEles = _require.removeEles,
setStyles = _require.setStyles,
createElement = _require.createElement,
getPixelRatio = _require.getPixelRatio,
getOffset = _require.getOffset;
var defaults = {
menuRadius: 100, // the radius of the circular menu in pixels
selector: 'node', // elements matching this Cytoscape.js selector will trigger cxtmenus
commands: [ // an array of commands to list in the menu or a function that returns the array
/*
{ // example command
fillColor: 'rgba(200, 200, 200, 0.75)', // optional: custom background color for item
content: 'a command name' // html/text content to be displayed in the menu
select: function(ele){ // a function to execute when the command is selected
console.log( ele.id() ) // `ele` holds the reference to the active element
},
enabled: true // whether the command is selectable
}
*/
], // function( ele ){ return [ /*...*/ ] }, // example function for commands
fillColor: 'rgba(0, 0, 0, 0.75)', // the background colour of the menu
activeFillColor: 'rgba(1, 105, 217, 0.75)', // the colour used to indicate the selected command
activePadding: 20, // additional size in pixels for the active command
indicatorSize: 24, // the size in pixels of the pointer to the active command
separatorWidth: 3, // the empty spacing in pixels between successive commands
spotlightPadding: 4, // extra spacing in pixels between the element and the spotlight
minSpotlightRadius: 24, // the minimum radius in pixels of the spotlight
maxSpotlightRadius: 38, // the maximum radius in pixels of the spotlight
openMenuEvents: 'cxttapstart taphold', // space-separated cytoscape events that will open the menu; only `cxttapstart` and/or `taphold` work here
itemColor: 'white', // the colour of text in the command's content
itemTextShadowColor: 'transparent', // the text shadow colour of the command's content
zIndex: 9999, // the z-index of the ui div
atMouse: false // draw menu at mouse position
var cxtmenu = function cxtmenu(params) {
var options = assign({}, defaults, params);
var cy = this;
var container = cy.container();
var target = void 0;
var data = {
options: options,
handlers: [],
container: createElement({ class: 'cxtmenu' })
};
// Object.assign Polyfill for IE
if (typeof Object.assign != 'function') {
(function () {
Object.assign = function (target) {
// We must check against these specific cases.
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var wrapper = data.container;
var parent = createElement();
var canvas = createElement({ tag: 'canvas' });
var commands = [];
var c2d = canvas.getContext('2d');
var r = options.menuRadius;
var containerSize = (r + options.activePadding) * 2;
var activeCommandI = void 0;
var offset = void 0;
var output = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};
})();
}
container.insertBefore(wrapper, container.firstChild);
wrapper.appendChild(parent);
parent.appendChild(canvas);
var removeEles = function(query, ancestor) {
var els = [].slice.call(ancestor.querySelectorAll(query));
setStyles(wrapper, {
position: 'absolute',
zIndex: options.zIndex,
userSelect: 'none'
});
ancestor = ancestor || document;
setStyles(parent, {
display: 'none',
width: containerSize + 'px',
height: containerSize + 'px',
position: 'absolute',
zIndex: 1,
marginLeft: -options.activePadding + 'px',
marginTop: -options.activePadding + 'px',
userSelect: 'none'
});
for (var i = 0, l = els.length; i < l; i++) {
els[i].remove();
}
};
canvas.width = containerSize;
canvas.height = containerSize;
var setStyles = function(el, style) {
var props = Object.keys(style);
function createMenuItems() {
removeEles('.cxtmenu-item', parent);
var dtheta = 2 * Math.PI / commands.length;
var theta1 = Math.PI / 2;
var theta2 = theta1 + dtheta;
for (var i = 0, l = props.length; i < l; i++) {
el.style[props[i]] = style[props[i]];
}
};
for (var i = 0; i < commands.length; i++) {
var command = commands[i];
var createElement = function(options){
options = options || {};
var midtheta = (theta1 + theta2) / 2;
var rx1 = 0.66 * r * Math.cos(midtheta);
var ry1 = 0.66 * r * Math.sin(midtheta);
var el = document.createElement(options.tag || 'div');
var item = createElement({ class: 'cxtmenu-item' });
setStyles(item, {
color: options.itemColor,
cursor: 'default',
display: 'table',
'text-align': 'center',
//background: 'red',
position: 'absolute',
'text-shadow': '-1px -1px 2px ' + options.itemTextShadowColor + ', 1px -1px 2px ' + options.itemTextShadowColor + ', -1px 1px 2px ' + options.itemTextShadowColor + ', 1px 1px 1px ' + options.itemTextShadowColor,
left: '50%',
top: '50%',
'min-height': r * 0.66 + 'px',
width: r * 0.66 + 'px',
height: r * 0.66 + 'px',
marginLeft: rx1 - r * 0.33 + 'px',
marginTop: -ry1 - r * 0.33 + 'px'
});
el.className = options.class || '';
var content = createElement({ class: 'cxtmenu-content' });
if (options.style) {
setStyles(el, options.style);
if (command.content instanceof HTMLElement) {
content.appendChild(command.content);
} else {
content.innerHTML = command.content;
}
setStyles(content, {
'width': r * 0.66 + 'px',
'height': r * 0.66 + 'px',
'vertical-align': 'middle',
'display': 'table-cell'
});
setStyles(content, command.contentStyle || {});
if (command.disabled === true || command.enabled === false) {
content.classList.add('cxtmenu-disabled');
}
parent.appendChild(item);
item.appendChild(content);
theta1 += dtheta;
theta2 += dtheta;
}
}
return el;
};
function queueDrawBg(rspotlight) {
redrawQueue.drawBg = [rspotlight];
}
var getPixelRatio = function(){
return window.devicePixelRatio || 1;
};
function drawBg(rspotlight) {
rspotlight = rspotlight !== undefined ? rspotlight : rs;
// registers the extension on a cytoscape lib ref
var register = function(cytoscape){
if( !cytoscape ){ return; } // can't register if cytoscape unspecified
c2d.globalCompositeOperation = 'source-over';
cytoscape('core', 'cxtmenu', function(params){
var options = Object.assign({}, defaults, params);
var cy = this;
var container = cy.container();
var target;
c2d.clearRect(0, 0, containerSize, containerSize);
function getOffset( el ){
var offset = el.getBoundingClientRect();
// draw background items
c2d.fillStyle = options.fillColor;
var dtheta = 2 * Math.PI / commands.length;
var theta1 = Math.PI / 2;
var theta2 = theta1 + dtheta;
return {
left: offset.left + document.body.scrollLeft +
parseFloat(getComputedStyle(document.body)['padding-left']) +
parseFloat(getComputedStyle(document.body)['border-left-width']),
top: offset.top + document.body.scrollTop +
parseFloat(getComputedStyle(document.body)['padding-top']) +
parseFloat(getComputedStyle(document.body)['border-top-width'])
};
for (var index = 0; index < commands.length; index++) {
var command = commands[index];
if (command.fillColor) {
c2d.fillStyle = command.fillColor;
}
c2d.beginPath();
c2d.moveTo(r + options.activePadding, r + options.activePadding);
c2d.arc(r + options.activePadding, r + options.activePadding, r, 2 * Math.PI - theta1, 2 * Math.PI - theta2, true);
c2d.closePath();
c2d.fill();
var data = {
options: options,
handlers: []
};
var wrapper = createElement({class: 'cxtmenu'});
data.container = wrapper;
var parent = createElement();
var canvas = createElement({tag: 'canvas'});
var commands = [];
var c2d = canvas.getContext('2d');
var r = options.menuRadius;
var containerSize = (r + options.activePadding)*2;
var activeCommandI;
var offset;
theta1 += dtheta;
theta2 += dtheta;
container.insertBefore(wrapper, container.firstChild);
wrapper.appendChild(parent);
parent.appendChild(canvas);
c2d.fillStyle = options.fillColor;
}
setStyles(wrapper, {
position: 'absolute',
zIndex: options.zIndex
});
// draw separators between items
c2d.globalCompositeOperation = 'destination-out';
c2d.strokeStyle = 'white';
c2d.lineWidth = options.separatorWidth;
theta1 = Math.PI / 2;
theta2 = theta1 + dtheta;
setStyles(parent, {
display: 'none',
width: containerSize + 'px',
height: containerSize + 'px',
position: 'absolute',
zIndex: 1,
marginLeft: - options.activePadding + 'px',
marginTop: - options.activePadding + 'px'
});
for (var i = 0; i < commands.length; i++) {
var rx1 = r * Math.cos(theta1);
var ry1 = r * Math.sin(theta1);
c2d.beginPath();
c2d.moveTo(r + options.activePadding, r + options.activePadding);
c2d.lineTo(r + options.activePadding + rx1, r + options.activePadding - ry1);
c2d.closePath();
c2d.stroke();
canvas.width = containerSize;
canvas.height = containerSize;
theta1 += dtheta;
theta2 += dtheta;
}
function createMenuItems() {
removeEles('.cxtmenu-item', parent);
var dtheta = 2 * Math.PI / (commands.length);
var theta1 = Math.PI / 2;
var theta2 = theta1 + dtheta;
c2d.fillStyle = 'white';
c2d.globalCompositeOperation = 'destination-out';
c2d.beginPath();
c2d.arc(r + options.activePadding, r + options.activePadding, rspotlight + options.spotlightPadding, 0, Math.PI * 2, true);
c2d.closePath();
c2d.fill();
for (var i = 0; i < commands.length; i++) {
var command = commands[i];
c2d.globalCompositeOperation = 'source-over';
}
var midtheta = (theta1 + theta2) / 2;
var rx1 = 0.66 * r * Math.cos(midtheta);
var ry1 = 0.66 * r * Math.sin(midtheta);
function queueDrawCommands(rx, ry, theta) {
redrawQueue.drawCommands = [rx, ry, theta];
}
var item = createElement({class: 'cxtmenu-item'});
setStyles(item, {
color: options.itemColor,
cursor: 'default',
display: 'table',
'text-align': 'center',
//background: 'red',
position: 'absolute',
'text-shadow': '-1px -1px 2px ' + options.itemTextShadowColor + ', 1px -1px 2px ' + options.itemTextShadowColor + ', -1px 1px 2px ' + options.itemTextShadowColor + ', 1px 1px 1px ' + options.itemTextShadowColor,
left: '50%',
top: '50%',
'min-height': (r * 0.66) + 'px',
width: (r * 0.66) + 'px',
height: (r * 0.66) + 'px',
marginLeft: (rx1 - r * 0.33) + 'px',
marginTop: (-ry1 - r * 0.33) + 'px'
});
function drawCommands(rx, ry, theta) {
var dtheta = 2 * Math.PI / commands.length;
var theta1 = Math.PI / 2;
var theta2 = theta1 + dtheta;
var content = createElement({class: 'cxtmenu-content'});
content.innerHTML = command.content;
setStyles(content, {
'width': (r * 0.66) + 'px',
'height': (r * 0.66) + 'px',
'vertical-align': 'middle',
'display': 'table-cell'
});
theta1 += dtheta * activeCommandI;
theta2 += dtheta * activeCommandI;
if (command.disabled === true || command.enabled === false) {
content.classList.add('cxtmenu-disabled');
}
c2d.fillStyle = options.activeFillColor;
c2d.strokeStyle = 'black';
c2d.lineWidth = 1;
c2d.beginPath();
c2d.moveTo(r + options.activePadding, r + options.activePadding);
c2d.arc(r + options.activePadding, r + options.activePadding, r + options.activePadding, 2 * Math.PI - theta1, 2 * Math.PI - theta2, true);
c2d.closePath();
c2d.fill();
parent.appendChild(item);
item.appendChild(content);
c2d.fillStyle = 'white';
c2d.globalCompositeOperation = 'destination-out';
theta1 += dtheta;
theta2 += dtheta;
}
}
var tx = r + options.activePadding + rx / r * (rs + options.spotlightPadding - options.indicatorSize / 4);
var ty = r + options.activePadding + ry / r * (rs + options.spotlightPadding - options.indicatorSize / 4);
var rot = Math.PI / 4 - theta;
function queueDrawBg( rspotlight ){
redrawQueue.drawBg = [ rspotlight ];
}
c2d.translate(tx, ty);
c2d.rotate(rot);
function drawBg( rspotlight ){
rspotlight = rspotlight !== undefined ? rspotlight : rs;
// clear the indicator
c2d.beginPath();
c2d.fillRect(-options.indicatorSize / 2, -options.indicatorSize / 2, options.indicatorSize, options.indicatorSize);
c2d.closePath();
c2d.fill();
c2d.globalCompositeOperation = 'source-over';
c2d.rotate(-rot);
c2d.translate(-tx, -ty);
c2d.clearRect(0, 0, containerSize, containerSize);
// c2d.setTransform( 1, 0, 0, 1, 0, 0 );
// draw background items
c2d.fillStyle = options.fillColor;
var dtheta = 2*Math.PI/(commands.length);
var theta1 = Math.PI/2;
var theta2 = theta1 + dtheta;
// clear the spotlight
c2d.beginPath();
c2d.arc(r + options.activePadding, r + options.activePadding, rs + options.spotlightPadding, 0, Math.PI * 2, true);
c2d.closePath();
c2d.fill();
for( var index = 0; index < commands.length; index++ ){
var command = commands[index];
c2d.globalCompositeOperation = 'source-over';
}
if( command.fillColor ){
c2d.fillStyle = command.fillColor;
}
c2d.beginPath();
c2d.moveTo(r + options.activePadding, r + options.activePadding);
c2d.arc(r + options.activePadding, r + options.activePadding, r, 2*Math.PI - theta1, 2*Math.PI - theta2, true);
c2d.closePath();
c2d.fill();
function updatePixelRatio() {
var pxr = getPixelRatio();
var w = container.clientWidth;
var h = container.clientHeight;
theta1 += dtheta;
theta2 += dtheta;
canvas.width = w * pxr;
canvas.height = h * pxr;
c2d.fillStyle = options.fillColor;
}
canvas.style.width = w + 'px';
canvas.style.height = h + 'px';
// draw separators between items
c2d.globalCompositeOperation = 'destination-out';
c2d.strokeStyle = 'white';
c2d.lineWidth = options.separatorWidth;
theta1 = Math.PI/2;
theta2 = theta1 + dtheta;
c2d.setTransform(1, 0, 0, 1, 0, 0);
c2d.scale(pxr, pxr);
}
for( var i = 0; i < commands.length; i++ ){
var rx1 = r * Math.cos(theta1);
var ry1 = r * Math.sin(theta1);
c2d.beginPath();
c2d.moveTo(r + options.activePadding, r + options.activePadding);
c2d.lineTo(r + options.activePadding + rx1, r + options.activePadding - ry1);
c2d.closePath();
c2d.stroke();
var redrawing = true;
var redrawQueue = {};
var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
var redraw = function redraw() {
if (redrawQueue.drawBg) {
drawBg.apply(null, redrawQueue.drawBg);
}
theta1 += dtheta;
theta2 += dtheta;
}
if (redrawQueue.drawCommands) {
drawCommands.apply(null, redrawQueue.drawCommands);
}
redrawQueue = {};
c2d.fillStyle = 'white';
c2d.globalCompositeOperation = 'destination-out';
c2d.beginPath();
c2d.arc(r + options.activePadding, r + options.activePadding, rspotlight + options.spotlightPadding, 0, Math.PI*2, true);
c2d.closePath();
c2d.fill();
if (redrawing) {
raf(redraw);
}
};
c2d.globalCompositeOperation = 'source-over';
// kick off
updatePixelRatio();
redraw();
var ctrx = void 0,
ctry = void 0,
rs = void 0;
var bindings = {
on: function on(events, selector, fn) {
var _fn = fn;
if (selector === 'core') {
_fn = function _fn(e) {
if (e.cyTarget === cy || e.target === cy) {
// only if event target is directly core
return fn.apply(this, [e]);
}
};
}
function queueDrawCommands( rx, ry, theta ){
redrawQueue.drawCommands = [ rx, ry, theta ];
data.handlers.push({
events: events,
selector: selector,
fn: _fn
});
if (selector === 'core') {
cy.on(events, _fn);
} else {
cy.on(events, selector, _fn);
}
function drawCommands( rx, ry, theta ){
var dtheta = 2*Math.PI/(commands.length);
var theta1 = Math.PI/2;
var theta2 = theta1 + dtheta;
return this;
}
};
theta1 += dtheta * activeCommandI;
theta2 += dtheta * activeCommandI;
function addEventListeners() {
var grabbable = void 0;
var inGesture = false;
var dragHandler = void 0;
var zoomEnabled = void 0;
var panEnabled = void 0;
var boxEnabled = void 0;
var gestureStartEvent = void 0;
c2d.fillStyle = options.activeFillColor;
c2d.strokeStyle = 'black';
c2d.lineWidth = 1;
c2d.beginPath();
c2d.moveTo(r + options.activePadding, r + options.activePadding);
c2d.arc(r + options.activePadding, r + options.activePadding, r + options.activePadding, 2*Math.PI - theta1, 2*Math.PI - theta2, true);
c2d.closePath();
c2d.fill();
var restoreZoom = function restoreZoom() {
if (zoomEnabled) {
cy.userZoomingEnabled(true);
}
};
c2d.fillStyle = 'white';
c2d.globalCompositeOperation = 'destination-out';
var restoreGrab = function restoreGrab() {
if (grabbable) {
target.grabify();
}
};
var tx = r + options.activePadding + rx/r*(rs + options.spotlightPadding - options.indicatorSize/4);
var ty = r + options.activePadding + ry/r*(rs + options.spotlightPadding - options.indicatorSize/4);
var rot = Math.PI/4 - theta;
var restorePan = function restorePan() {
if (panEnabled) {
cy.userPanningEnabled(true);
}
};
c2d.translate( tx, ty );
c2d.rotate( rot );
var restoreBoxSeln = function restoreBoxSeln() {
if (boxEnabled) {
cy.boxSelectionEnabled(true);
}
};
// clear the indicator
c2d.beginPath();
c2d.fillRect(-options.indicatorSize/2, -options.indicatorSize/2, options.indicatorSize, options.indicatorSize);
c2d.closePath();
c2d.fill();
var restoreGestures = function restoreGestures() {
restoreGrab();
restoreZoom();
restorePan();
restoreBoxSeln();
};
c2d.rotate( -rot );
c2d.translate( -tx, -ty );
window.addEventListener('resize', updatePixelRatio);
// c2d.setTransform( 1, 0, 0, 1, 0, 0 );
bindings.on('resize', function () {
updatePixelRatio();
}).on(options.openMenuEvents, options.selector, function (e) {
target = this; // Remember which node the context menu is for
var ele = this;
var isCy = this === cy;
// clear the spotlight
c2d.beginPath();
c2d.arc(r + options.activePadding, r + options.activePadding, rs + options.spotlightPadding, 0, Math.PI*2, true);
c2d.closePath();
c2d.fill();
if (inGesture) {
parent.style.display = 'none';
c2d.globalCompositeOperation = 'source-over';
inGesture = false;
restoreGestures();
}
function updatePixelRatio(){
var pxr = getPixelRatio();
var w = container.clientWidth;
var h = container.clientHeight;
if (typeof options.commands === 'function') {
commands = options.commands(target);
} else {
commands = options.commands;
}
canvas.width = w * pxr;
canvas.height = h * pxr;
if (!commands || commands.length === 0) {
return;
}
canvas.style.width = w + 'px';
canvas.style.height = h + 'px';
zoomEnabled = cy.userZoomingEnabled();
cy.userZoomingEnabled(false);
c2d.setTransform( 1, 0, 0, 1, 0, 0 );
c2d.scale( pxr, pxr );
panEnabled = cy.userPanningEnabled();
cy.userPanningEnabled(false);
boxEnabled = cy.boxSelectionEnabled();
cy.boxSelectionEnabled(false);
grabbable = target.grabbable && target.grabbable();
if (grabbable) {
target.ungrabify();
}
var redrawing = true;
var redrawQueue = {};
var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
var redraw = function(){
if( redrawQueue.drawBg ){
drawBg.apply( null, redrawQueue.drawBg );
}
var rp = void 0,
rw = void 0,
rh = void 0;
if (!isCy && ele.isNode() && !ele.isParent() && !options.atMouse) {
rp = ele.renderedPosition();
rw = ele.renderedWidth();
rh = ele.renderedHeight();
} else {
rp = e.renderedPosition || e.cyRenderedPosition;
rw = 1;
rh = 1;
}
if( redrawQueue.drawCommands ){
drawCommands.apply( null, redrawQueue.drawCommands );
}
offset = getOffset(container);
redrawQueue = {};
ctrx = rp.x;
ctry = rp.y;
if( redrawing ){
raf( redraw );
}
};
createMenuItems();
// kick off
updatePixelRatio();
redraw();
setStyles(parent, {
display: 'block',
left: rp.x - r + 'px',
top: rp.y - r + 'px'
});
var ctrx, ctry, rs;
rs = Math.max(rw, rh) / 2;
rs = Math.max(rs, options.minSpotlightRadius);
rs = Math.min(rs, options.maxSpotlightRadius);
var bindings = {
on: function(events, selector, fn){
queueDrawBg();
var _fn = fn;
if( selector === 'core'){
_fn = function( e ){
if( e.cyTarget === cy || e.target === cy ){ // only if event target is directly core
return fn.apply( this, [ e ] );
}
};
}
activeCommandI = undefined;
data.handlers.push({
events: events,
selector: selector,
fn: _fn
});
inGesture = true;
gestureStartEvent = e;
}).on('cxtdrag tapdrag', options.selector, dragHandler = function dragHandler(e) {
if( selector === 'core' ){
cy.on(events, _fn);
} else {
cy.on(events, selector, _fn);
}
if (!inGesture) {
return;
}
return this;
}
};
var origE = e.originalEvent;
var isTouch = origE.touches && origE.touches.length > 0;
function addEventListeners(){
var grabbable;
var inGesture = false;
var dragHandler;
var zoomEnabled;
var panEnabled;
var boxEnabled;
var gestureStartEvent;
var pageX = isTouch ? origE.touches[0].pageX : origE.pageX;
var pageY = isTouch ? origE.touches[0].pageY : origE.pageY;
var restoreZoom = function(){
if( zoomEnabled ){
cy.userZoomingEnabled( true );
}
};
activeCommandI = undefined;
var restoreGrab = function(){
if( grabbable ){
target.grabify();
}
};
var dx = pageX - offset.left - ctrx;
var dy = pageY - offset.top - ctry;
var restorePan = function(){
if( panEnabled ){
cy.userPanningEnabled( true );
}
};
if (dx === 0) {
dx = 0.01;
}
var restoreBoxSeln = function(){
if( boxEnabled ){
cy.boxSelectionEnabled( true );
}
};
var d = Math.sqrt(dx * dx + dy * dy);
var cosTheta = (dy * dy - d * d - dx * dx) / (-2 * d * dx);
var theta = Math.acos(cosTheta);
var restoreGestures = function(){
restoreGrab();
restoreZoom();
restorePan();
restoreBoxSeln();
};
if (d < rs + options.spotlightPadding) {
queueDrawBg();
return;
}
window.addEventListener('resize', updatePixelRatio);
queueDrawBg();
bindings
.on('resize', function(e){
updatePixelRatio();
})
var rx = dx * r / d;
var ry = dy * r / d;
.on(options.openMenuEvents, options.selector, function(e){
target = this; // Remember which node the context menu is for
var ele = this;
var isCy = this === cy;
if (dy > 0) {
theta = Math.PI + Math.abs(theta - Math.PI);
}
if (inGesture) {
parent.style.display = 'none';
var dtheta = 2 * Math.PI / commands.length;
var theta1 = Math.PI / 2;
var theta2 = theta1 + dtheta;
inGesture = false;
for (var i = 0; i < commands.length; i++) {
var command = commands[i];
restoreGestures();
}
var inThisCommand = theta1 <= theta && theta <= theta2 || theta1 <= theta + 2 * Math.PI && theta + 2 * Math.PI <= theta2;
if( typeof options.commands === 'function' ){
commands = options.commands(target);
} else {
commands = options.commands;
}
if (command.disabled) {
inThisCommand = false;
}
if( !commands || commands.length === 0 ){ return; }
if (inThisCommand) {
activeCommandI = i;
break;
}
zoomEnabled = cy.userZoomingEnabled();
cy.userZoomingEnabled( false );
theta1 += dtheta;
theta2 += dtheta;
}
panEnabled = cy.userPanningEnabled();
cy.userPanningEnabled( false );
queueDrawCommands(rx, ry, theta);
}).on('tapdrag', dragHandler).on('cxttapend tapend', function () {
parent.style.display = 'none';
boxEnabled = cy.boxSelectionEnabled();
cy.boxSelectionEnabled( false );
if (activeCommandI !== undefined) {
var select = commands[activeCommandI].select;
grabbable = target.grabbable && target.grabbable();
if( grabbable ){
target.ungrabify();
}
if (select) {
select.apply(target, [target, gestureStartEvent]);
activeCommandI = undefined;
}
}
var rp, rw, rh;
if( !isCy && ele.isNode() && !ele.isParent() && !options.atMouse ){
rp = ele.renderedPosition();
rw = ele.renderedWidth();
rh = ele.renderedHeight();
} else {
rp = e.renderedPosition || e.cyRenderedPosition;
rw = 1;
rh = 1;
}
inGesture = false;
offset = getOffset(container);
restoreGestures();
});
}
ctrx = rp.x;
ctry = rp.y;
function removeEventListeners() {
var handlers = data.handlers;
createMenuItems();
for (var i = 0; i < handlers.length; i++) {
var h = handlers[i];
setStyles(parent, {
display: 'block',
left: (rp.x - r) + 'px',
top: (rp.y - r) + 'px'
});
if (h.selector === 'core') {
cy.off(h.events, h.fn);
} else {
cy.off(h.events, h.selector, h.fn);
}
}
rs = Math.max(rw, rh)/2;
rs = Math.max(rs, options.minSpotlightRadius);
rs = Math.min(rs, options.maxSpotlightRadius);
window.removeEventListener('resize', updatePixelRatio);
}
queueDrawBg();
function destroyInstance() {
redrawing = false;
activeCommandI = undefined;
removeEventListeners();
inGesture = true;
gestureStartEvent = e;
})
wrapper.remove();
}
.on('cxtdrag tapdrag', options.selector, dragHandler = function(e){
addEventListeners();
if( !inGesture ){ return; }
return {
destroy: function destroy() {
destroyInstance();
}
};
};
var origE = e.originalEvent;
var isTouch = origE.touches && origE.touches.length > 0;
module.exports = cxtmenu;
var pageX = isTouch ? origE.touches[0].pageX : origE.pageX;
var pageY = isTouch ? origE.touches[0].pageY : origE.pageY;
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
activeCommandI = undefined;
"use strict";
var dx = pageX - offset.left - ctrx;
var dy = pageY - offset.top - ctry;
if( dx === 0 ){ dx = 0.01; }
// Simple, internal Object.assign() polyfill for options objects etc.
var d = Math.sqrt( dx*dx + dy*dy );
var cosTheta = (dy*dy - d*d - dx*dx)/(-2 * d * dx);
var theta = Math.acos( cosTheta );
module.exports = Object.assign != null ? Object.assign.bind(Object) : function (tgt) {
for (var _len = arguments.length, srcs = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
srcs[_key - 1] = arguments[_key];
}
if( d < rs + options.spotlightPadding ){
queueDrawBg();
return;
}
srcs.forEach(function (src) {
Object.keys(src).forEach(function (k) {
return tgt[k] = src[k];
});
});
queueDrawBg();
return tgt;
};
var rx = dx*r / d;
var ry = dy*r / d;
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
if( dy > 0 ){
theta = Math.PI + Math.abs(theta - Math.PI);
}
"use strict";
var dtheta = 2*Math.PI/(commands.length);
var theta1 = Math.PI/2;
var theta2 = theta1 + dtheta;
for( var i = 0; i < commands.length; i++ ){
var command = commands[i];
var defaults = {
menuRadius: 100, // the radius of the circular menu in pixels
selector: 'node', // elements matching this Cytoscape.js selector will trigger cxtmenus
commands: [// an array of commands to list in the menu or a function that returns the array
/*
{ // example command
fillColor: 'rgba(200, 200, 200, 0.75)', // optional: custom background color for item
content: 'a command name' // html/text content to be displayed in the menu
contentStyle: {}, // css key:value pairs to set the command's css in js if you want
select: function(ele){ // a function to execute when the command is selected
console.log( ele.id() ) // `ele` holds the reference to the active element
},
enabled: true // whether the command is selectable
}
*/
], // function( ele ){ return [ /*...*/ ] }, // example function for commands
fillColor: 'rgba(0, 0, 0, 0.75)', // the background colour of the menu
activeFillColor: 'rgba(1, 105, 217, 0.75)', // the colour used to indicate the selected command
activePadding: 20, // additional size in pixels for the active command
indicatorSize: 24, // the size in pixels of the pointer to the active command
separatorWidth: 3, // the empty spacing in pixels between successive commands
spotlightPadding: 4, // extra spacing in pixels between the element and the spotlight
minSpotlightRadius: 24, // the minimum radius in pixels of the spotlight
maxSpotlightRadius: 38, // the maximum radius in pixels of the spotlight
openMenuEvents: 'cxttapstart taphold', // space-separated cytoscape events that will open the menu; only `cxttapstart` and/or `taphold` work here
itemColor: 'white', // the colour of text in the command's content
itemTextShadowColor: 'transparent', // the text shadow colour of the command's content
zIndex: 9999, // the z-index of the ui div
atMouse: false // draw menu at mouse position
};
var inThisCommand = theta1 <= theta && theta <= theta2
|| theta1 <= theta + 2*Math.PI && theta + 2*Math.PI <= theta2;
module.exports = defaults;
if( command.disabled ){
inThisCommand = false;
}
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
if( inThisCommand ){
activeCommandI = i;
break;
}
"use strict";
theta1 += dtheta;
theta2 += dtheta;
}
queueDrawCommands( rx, ry, theta );
})
var removeEles = function removeEles(query) {
var ancestor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;
.on('tapdrag', dragHandler)
ancestor.querySelectorAll(query).forEach(function (el) {
return el.parentNode.removeChild(el);
});
};
.on('cxttapend tapend', function(e){
parent.style.display = 'none';
var setStyles = function setStyles(el, style) {
var props = Object.keys(style);
if( activeCommandI !== undefined ){
var select = commands[ activeCommandI ].select;
for (var i = 0, l = props.length; i < l; i++) {
el.style[props[i]] = style[props[i]];
}
};
if( select ){
select.apply( target, [target, gestureStartEvent] );
activeCommandI = undefined;
}
}
var createElement = function createElement(options) {
options = options || {};
inGesture = false;
var el = document.createElement(options.tag || 'div');
restoreGestures();
})
;
}
el.className = options.class || '';
function removeEventListeners(){
var handlers = data.handlers;
if (options.style) {
setStyles(el, options.style);
}
for( var i = 0; i < handlers.length; i++ ){
var h = handlers[i];
return el;
};
if( h.selector === 'core' ){
cy.off(h.events, h.fn);
} else {
cy.off(h.events, h.selector, h.fn);
}
}
var getPixelRatio = function getPixelRatio() {
return window.devicePixelRatio || 1;
};
window.removeEventListener('resize', updatePixelRatio);
}
var getOffset = function getOffset(el) {
var offset = el.getBoundingClientRect();
function destroyInstance(){
redrawing = false;
return {
left: offset.left + document.body.scrollLeft + parseFloat(getComputedStyle(document.body)['padding-left']) + parseFloat(getComputedStyle(document.body)['border-left-width']),
top: offset.top + document.body.scrollTop + parseFloat(getComputedStyle(document.body)['padding-top']) + parseFloat(getComputedStyle(document.body)['border-top-width'])
};
};
removeEventListeners();
module.exports = { removeEles: removeEles, setStyles: setStyles, createElement: createElement, getPixelRatio: getPixelRatio, getOffset: getOffset };
wrapper.remove();
}
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
addEventListeners();
"use strict";
return {
destroy: function(){
destroyInstance();
}
};
});
var cxtmenu = __webpack_require__(0);
}; // reg
// registers the extension on a cytoscape lib ref
var register = function register(cytoscape) {
if (!cytoscape) {
return;
} // can't register if cytoscape unspecified
if( typeof module !== 'undefined' && module.exports ){ // expose as a commonjs module
module.exports = register;
} else if( typeof define !== 'undefined' && define.amd ){ // expose as an amd/requirejs module
define('cytoscape-cxtmenu', function(){
return register;
});
}
cytoscape('core', 'cxtmenu', cxtmenu); // register with cytoscape.js
};
if( typeof cytoscape !== typeof undefined ){ // expose to global cytoscape (i.e. window.cytoscape)
register(cytoscape);
}
if (typeof cytoscape !== 'undefined') {
// expose to global cytoscape (i.e. window.cytoscape)
register(cytoscape);
}
})();
module.exports = register;
/***/ })
/******/ ]);
});
{
"name": "cytoscape-cxtmenu",
"version": "2.10.3",
"description": "A context menu for Cytoscape.js",
"version": "3.0.0",
"description": "A circular, swipeable context menu extension for Cytoscape.js",
"main": "cytoscape-cxtmenu.js",
"author": {
"name": "Max Franz",
"email": "maxkfranz@gmail.com"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"postpublish": "run-s gh-pages:demo gh-pages:deploy gh-pages:clean",
"gh-pages:demo": "cpy demo.html . --rename=index.html",
"gh-pages:deploy": "gh-pages -d .",
"gh-pages:clean": "rimraf index.html",
"copyright": "update license",
"lint": "eslint src",
"build": "cross-env NODE_ENV=production webpack",
"build:min": "cross-env NODE_ENV=production MIN=true webpack",
"build:release": "run-s build copyright",
"watch": "webpack --progress --watch",
"dev": "webpack-dev-server --open",
"test": "mocha"
},

@@ -15,4 +30,3 @@ "repository": {

"cytoscape",
"extension",
"cyext"
"cytoscape-extension"
],

@@ -25,13 +39,23 @@ "license": "MIT",

"devDependencies": {
"gulp": "^3.8.8",
"gulp-jshint": "^1.8.5",
"gulp-prompt": "^0.1.1",
"gulp-replace": "^0.4.0",
"gulp-shell": "^0.2.9",
"jshint-stylish": "^1.0.0",
"run-sequence": "^1.0.0"
"babel-core": "^6.24.1",
"babel-loader": "^7.0.0",
"babel-preset-env": "^1.5.1",
"camelcase": "^4.1.0",
"chai": "4.0.2",
"cpy-cli": "^1.0.1",
"cross-env": "^5.0.0",
"eslint": "^3.9.1",
"gh-pages": "^1.0.0",
"mocha": "3.4.2",
"npm-run-all": "^4.1.2",
"rimraf": "^2.6.2",
"update": "^0.7.4",
"updater-license": "^1.0.0",
"webpack": "^2.6.1",
"webpack-dev-server": "^2.4.5"
},
"peerDependencies": {
"cytoscape": "^2.2.0 || ^3.0.0"
}
"cytoscape": "^3.2.0"
},
"dependencies": {}
}
cytoscape-cxtmenu
================================================================================
![Preview](https://raw.githubusercontent.com/cytoscape/cytoscape.js-cxtmenu/master/img/preview.png)
[![DOI](https://zenodo.org/badge/16010906.svg)](https://zenodo.org/badge/latestdoi/16010906)
![Preview](https://raw.githubusercontent.com/cytoscape/cytoscape.js-cxtmenu/master/preview.png)
## Description
A context menu for Cytoscape.js
A circular, swipeable context menu extension for Cytoscape.js ([demo](https://cytoscape.github.io/cytoscape.js-cxtmenu))
This plugin creates a widget that lets the user operate circular context menus on nodes in Cytoscape.js. The user swipes along the circular menu to select a menu item and perform a command on the node of interest.
This extension creates a widget that lets the user operate circular context menus on nodes in Cytoscape.js. The user swipes along the circular menu to select a menu item and perform a command on either a node, a edge, or the graph background.
## Dependencies
* Cytoscape.js ^2.2.0 || ^3.0.0
* Cytoscape.js ^3.2.0

@@ -25,13 +26,24 @@

`require()` the library as appropriate for your project:
Import the library as appropriate for your project:
CommonJS:
ES import:
```js
var cytoscape = require('cytoscape');
var cxtmenu = require('cytoscape-cxtmenu');
import cytoscape from 'cytoscape';
import cxtmenu from 'cytoscape-cxtmenu';
cxtmenu( cytoscape ); // register extension
cytoscape.use( cxtmenu );
```
CommonJS require:
```js
let cytoscape = require('cytoscape');
let cxtmenu = require('cytoscape-cxtmenu');
cytoscape.use( cxtmenu ); // register extension
```
AMD:
```js

@@ -57,3 +69,3 @@ require(['cytoscape', 'cytoscape-cxtmenu'], function( cytoscape, cxtmenu ){

var cy = cytoscape({
let cy = cytoscape({
container: document.getElementById('cy'),

@@ -64,3 +76,3 @@ /* ... */

// the default values of each option are outlined below:
var defaults = {
let defaults = {
menuRadius: 100, // the radius of the circular menu in pixels

@@ -73,2 +85,3 @@ selector: 'node', // elements matching this Cytoscape.js selector will trigger cxtmenus

content: 'a command name' // html/text content to be displayed in the menu
contentStyle: {}, // css key:value pairs to set the command's css in js if you want
select: function(ele){ // a function to execute when the command is selected

@@ -82,3 +95,3 @@ console.log( ele.id() ) // `ele` holds the reference to the active element

fillColor: 'rgba(0, 0, 0, 0.75)', // the background colour of the menu
activeFillColor: 'rgba(92, 194, 237, 0.75)', // the colour used to indicate the selected command
activeFillColor: 'rgba(1, 105, 217, 0.75)', // the colour used to indicate the selected command
activePadding: 20, // additional size in pixels for the active command

@@ -92,3 +105,3 @@ indicatorSize: 24, // the size in pixels of the pointer to the active command

itemColor: 'white', // the colour of text in the command's content
itemTextShadowColor: 'black', // the text shadow colour of the command's content
itemTextShadowColor: 'transparent', // the text shadow colour of the command's content
zIndex: 9999, // the z-index of the ui div

@@ -98,3 +111,3 @@ atMouse: false // draw menu at mouse position

var cxtmenuApi = cy.cxtmenu( defaults );
let menu = cy.cxtmenu( defaults );
```

@@ -105,8 +118,19 @@

```js
var cxtmenuApi = cy.cxtmenu( someOptions );
let menu = cy.cxtmenu( someOptions );
cxtmenuApi.destroy();
menu.destroy();
```
## Build targets
* `npm run test` : Run Mocha tests in `./test`
* `npm run build` : Build `./src/**` into `cytoscape-cxtmenu.js`
* `npm run watch` : Automatically build on changes with live reloading (N.b. you must already have an HTTP server running)
* `npm run dev` : Automatically build on changes with live reloading with webpack dev server
* `npm run lint` : Run eslint on the source
N.b. all builds use babel, so modern ES features can be used in the `src`.
## Publishing instructions

@@ -116,4 +140,8 @@

1. Set the version number environment variable: `export VERSION=1.2.3`
1. Publish: `gulp publish`
1. Build the extension : `npm run build:release`
1. Commit the build : `git commit -am "Build for release"`
1. Bump the version number and tag: `npm version major|minor|patch`
1. Push to origin: `git push && git push --tags`
1. Publish to npm: `npm publish .`
1. If publishing to bower for the first time, you'll need to run `bower register cytoscape-cxtmenu https://github.com/cytoscape/cytoscape.js-cxtmenu.git`
1. [Make a new release](https://github.com/cytoscape/cytoscape.js-cxtmenu/releases/new) for Zenodo.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc