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

cytoscape-context-menus

Package Overview
Dependencies
Maintainers
6
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cytoscape-context-menus - npm Package Compare versions

Comparing version 3.1.0 to 4.0.0

.babelrc

0

bower.json

@@ -0,0 +0,0 @@ {

528

cytoscape-context-menus.js

@@ -1,527 +0,1 @@

;(function(){ 'use strict';
var $ = typeof jQuery === typeof undefined ? null : jQuery;
var register = function( cytoscape, $ ){
if( !cytoscape ){ return; } // can't register if cytoscape unspecified
var defaults = {
// Customize event to bring up the context menu
// Possible options https://js.cytoscape.org/#events/user-input-device-events
evtType: 'cxttap',
// List of initial menu items
menuItems: [
/*
{
id: 'remove',
content: 'remove',
tooltipText: 'remove',
selector: 'node, edge',
onClickFunction: function () {
console.log('remove element');
},
hasTrailingDivider: true
},
{
id: 'hide',
content: 'hide',
tooltipText: 'remove',
selector: 'node, edge',
onClickFunction: function () {
console.log('hide element');
},
disabled: true
}*/
],
// css classes that menu items will have
menuItemClasses: [
// add class names to this list
],
// css classes that context menu will have
contextMenuClasses: [
// add class names to this list
]
};
var eventCyTapStart; // The event to be binded on tap start
// To initialize with options.
cytoscape('core', 'contextMenus', function (opts) {
var cy = this;
// Initilize scratch pad
if (!cy.scratch('cycontextmenus')) {
cy.scratch('cycontextmenus', {});
}
var options = getScratchProp('options');
var $cxtMenu = getScratchProp('cxtMenu');
var menuItemCSSClass = 'cy-context-menus-cxt-menuitem';
var dividerCSSClass = 'cy-context-menus-divider';
// Merge default options with the ones coming from parameter
function extend(defaults, options) {
var obj = {};
for (var i in defaults) {
obj[i] = defaults[i];
}
for (var i in options) {
obj[i] = options[i];
}
return obj;
};
function getScratchProp(propname) {
return cy.scratch('cycontextmenus')[propname];
};
function setScratchProp(propname, value) {
cy.scratch('cycontextmenus')[propname] = value;
};
function preventDefaultContextTap() {
$(".cy-context-menus-cxt-menu").contextmenu( function() {
return false;
});
}
// Get string representation of css classes
function getMenuItemClassStr(classes, hasTrailingDivider) {
var str = getClassStr(classes);
str += ' ' + menuItemCSSClass;
if(hasTrailingDivider) {
str += ' ' + dividerCSSClass;
}
return str;
}
// Get string representation of css classes
function getClassStr(classes) {
var str = '';
for( var i = 0; i < classes.length; i++ ) {
var className = classes[i];
str += className;
if(i !== classes.length - 1) {
str += ' ';
}
}
return str;
}
function displayComponent($component) {
$component.css('display', 'block');
}
function hideComponent($component) {
$component.css('display', 'none');
}
function hideMenuItemComponents() {
$cxtMenu.children().css('display', 'none');
}
function bindOnClickFunction($component, onClickFcn) {
var callOnClickFcn;
$component.on('click', callOnClickFcn = function() {
onClickFcn(getScratchProp('currentCyEvent'));
});
$component.data('call-on-click-function', callOnClickFcn);
}
function bindCyCxttap($component, selector, coreAsWell) {
function _cxtfcn(event) {
setScratchProp('currentCyEvent', event);
adjustCxtMenu(event); // adjust the position of context menu
if ($component.data('show')) {
// Now we have a visible element display context menu if it is not visible
if (!$cxtMenu.is(':visible')) {
displayComponent($cxtMenu);
}
// anyVisibleChild indicates if there is any visible child of context menu if not do not show the context menu
setScratchProp('anyVisibleChild', true);// there is visible child
displayComponent($component); // display the component
}
// If there is no visible element hide the context menu as well(If it is visible)
if (!getScratchProp('anyVisibleChild') && $cxtMenu.is(':visible')) {
hideComponent($cxtMenu);
}
}
var cxtfcn;
var cxtCoreFcn;
if(coreAsWell) {
cy.on(options.evtType, cxtCoreFcn = function(event) {
var target = event.target || event.cyTarget;
if( target != cy ) {
return;
}
_cxtfcn(event);
});
}
if(selector) {
cy.on(options.evtType, selector, cxtfcn = function(event) {
_cxtfcn(event);
});
}
// Bind the event to menu item to be able to remove it back
$component.data('cy-context-menus-cxtfcn', cxtfcn);
$component.data('cy-context-menus-cxtcorefcn', cxtCoreFcn);
}
function bindCyEvents() {
cy.on('tapstart', eventCyTapStart = function(){
hideComponent($cxtMenu);
setScratchProp('cxtMenuPosition', undefined);
setScratchProp('currentCyEvent', undefined);
});
}
function performBindings($component, onClickFcn, selector, coreAsWell) {
bindOnClickFunction($component, onClickFcn);
bindCyCxttap($component, selector, coreAsWell);
}
// Adjusts context menu if necessary
function adjustCxtMenu(event) {
var currentCxtMenuPosition = getScratchProp('cxtMenuPosition');
var cyPos = event.position || event.cyPosition;
if( currentCxtMenuPosition != cyPos ) {
hideMenuItemComponents();
setScratchProp('anyVisibleChild', false);// we hide all children there is no visible child remaining
setScratchProp('cxtMenuPosition', cyPos);
var containerPos = $(cy.container()).offset();
var renderedPos = event.renderedPosition || event.cyRenderedPosition;
var borderThickness = parseInt($(cy.container()).css("border-width").replace("px",""));
if(borderThickness > 0){
containerPos.top += borderThickness;
containerPos.left += borderThickness;
}
// var left = containerPos.left + renderedPos.x;
// var top = containerPos.top + renderedPos.y;
//$cxtMenu.css('left', left);
//$cxtMenu.css('top', top);
var containerHeight = $(cy.container()).innerHeight();
var containerWidth = $(cy.container()).innerWidth();
var horizontalSplit = containerHeight/2 ;
var verticalSplit = containerWidth/2 ;
var windowHeight = $(window).height();
var windowWidth = $(window).width();
//When user click on bottom-left part of window
if(renderedPos.y > horizontalSplit && renderedPos.x <= verticalSplit) {
$cxtMenu.css("left", renderedPos.x + containerPos.left);
$cxtMenu.css("bottom", windowHeight - (containerPos.top + renderedPos.y));
$cxtMenu.css("right", "auto");
$cxtMenu.css("top", "auto");
} else if(renderedPos.y > horizontalSplit && renderedPos.x > verticalSplit) {
//When user click on bottom-right part of window
$cxtMenu.css("right", windowWidth - (containerPos.left+ renderedPos.x));
$cxtMenu.css("bottom", windowHeight - (containerPos.top + renderedPos.y));
$cxtMenu.css("left", "auto");
$cxtMenu.css("top", "auto");
} else if(renderedPos.y <= horizontalSplit && renderedPos.x <= verticalSplit) {
//When user click on top-left part of window
$cxtMenu.css("left", renderedPos.x + containerPos.left);
$cxtMenu.css("top", renderedPos.y + containerPos.top);
$cxtMenu.css("right", "auto");
$cxtMenu.css("bottom", "auto");
} else {
//When user click on top-right part of window
$cxtMenu.css("right", windowWidth - (renderedPos.x + containerPos.left));
$cxtMenu.css("top", renderedPos.y + containerPos.top);
$cxtMenu.css("left", "auto");
$cxtMenu.css("bottom", "auto");
}
}
}
function createAndAppendMenuItemComponents(menuItems) {
for (var i = 0; i < menuItems.length; i++) {
createAndAppendMenuItemComponent(menuItems[i]);
}
}
function createAndAppendMenuItemComponent(menuItem) {
// Create and append menu item
var $menuItemComponent = createMenuItemComponent(menuItem);
appendComponentToCxtMenu($menuItemComponent);
performBindings($menuItemComponent, menuItem.onClickFunction, menuItem.selector, menuItem.coreAsWell);
}//insertComponentBeforeExistingItem(component, existingItemID)
function createAndInsertMenuItemComponentBeforeExistingComponent(menuItem, existingComponentID) {
// Create and insert menu item
var $menuItemComponent = createMenuItemComponent(menuItem);
insertComponentBeforeExistingItem($menuItemComponent, existingComponentID);
performBindings($menuItemComponent, menuItem.onClickFunction, menuItem.selector, menuItem.coreAsWell);
}
// create cxtMenu and append it to body
function createAndAppendCxtMenuComponent() {
var classes = getClassStr(options.contextMenuClasses);
// classes += ' cy-context-menus-cxt-menu';
$cxtMenu = $('<div class=' + classes + '></div>');
$cxtMenu.addClass('cy-context-menus-cxt-menu');
setScratchProp('cxtMenu', $cxtMenu);
$('body').append($cxtMenu);
return $cxtMenu;
}
// Creates a menu item as an html component
function createMenuItemComponent(item) {
var classStr = getMenuItemClassStr(options.menuItemClasses, item.hasTrailingDivider);
var itemStr = '<button id="' + item.id + '" class="' + classStr + '"';
if(item.tooltipText) {
itemStr += ' title="' + item.tooltipText + '"';
}
if(item.disabled) {
itemStr += ' disabled';
}
if (!item.image){
itemStr += '>' + item.content + '</button>';
}
else{
itemStr += '>' + '<img src="' + item.image.src + '" width="' + item.image.width + 'px"; height="'
+ item.image.height + 'px"; style="position:absolute; top: ' + item.image.y + 'px; left: '
+ item.image.x + 'px;">' + item.content + '</button>';
};
var $menuItemComponent = $(itemStr);
$menuItemComponent.data('selector', item.selector);
$menuItemComponent.data('on-click-function', item.onClickFunction);
$menuItemComponent.data('show', (typeof(item.show) === 'undefined' || item.show));
return $menuItemComponent;
}
// Appends the given component to cxtMenu
function appendComponentToCxtMenu(component) {
$cxtMenu.append(component);
bindMenuItemClickFunction(component);
}
// Insert the given component to cxtMenu just before the existing item with given ID
function insertComponentBeforeExistingItem(component, existingItemID) {
var $existingItem = $('#' + existingItemID);
component.insertBefore($existingItem);
}
function destroyCxtMenu() {
if(!getScratchProp('active')) {
return;
}
removeAndUnbindMenuItems();
cy.off('tapstart', eventCyTapStart);
$cxtMenu.remove();
$cxtMenu = undefined;
setScratchProp($cxtMenu, undefined);
setScratchProp('active', false);
setScratchProp('anyVisibleChild', false);
}
function removeAndUnbindMenuItems() {
var children = $cxtMenu.children();
$(children).each(function() {
removeAndUnbindMenuItem($(this));
});
}
function removeAndUnbindMenuItem(itemID) {
var $component = typeof itemID === 'string' ? $('#' + itemID) : itemID;
var cxtfcn = $component.data('cy-context-menus-cxtfcn');
var selector = $component.data('selector');
var callOnClickFcn = $component.data('call-on-click-function');
var cxtCoreFcn = $component.data('cy-context-menus-cxtcorefcn');
if(cxtfcn) {
cy.off(options.evtType, selector, cxtfcn);
}
if(cxtCoreFcn) {
cy.off(options.evtType, cxtCoreFcn);
}
if(callOnClickFcn) {
$component.off('click', callOnClickFcn);
}
$component.remove();
}
function moveBeforeOtherMenuItemComponent(componentID, existingComponentID) {
if( componentID === existingComponentID ) {
return;
}
var $component = $('#' + componentID).detach();
var $existingComponent = $('#' + existingComponentID);
$component.insertBefore($existingComponent);
}
function bindMenuItemClickFunction(component) {
component.click( function() {
hideComponent($cxtMenu);
setScratchProp('cxtMenuPosition', undefined);
});
}
function disableComponent(componentID) {
$('#' + componentID).attr('disabled', true);
}
function enableComponent(componentID) {
$('#' + componentID).attr('disabled', false);
}
function setTrailingDivider(componentID, status) {
var $component = $('#' + componentID);
if(status) {
$component.addClass(dividerCSSClass);
}
else {
$component.removeClass(dividerCSSClass);
}
}
// Get an extension instance to enable users to access extension methods
function getInstance(cy) {
var instance = {
// Returns whether the extension is active
isActive: function() {
return getScratchProp('active');
},
// Appends given menu item to the menu items list.
appendMenuItem: function(item) {
createAndAppendMenuItemComponent(item);
return cy;
},
// Appends menu items in the given list to the menu items list.
appendMenuItems: function(items) {
createAndAppendMenuItemComponents(items);
return cy;
},
// Removes the menu item with given ID.
removeMenuItem: function(itemID) {
removeAndUnbindMenuItem(itemID);
return cy;
},
// Sets whether the menuItem with given ID will have a following divider.
setTrailingDivider: function(itemID, status) {
setTrailingDivider(itemID, status);
return cy;
},
// Inserts given item before the existingitem.
insertBeforeMenuItem: function(item, existingItemID) {
createAndInsertMenuItemComponentBeforeExistingComponent(item, existingItemID);
return cy;
},
// Moves the item with given ID before the existingitem.
moveBeforeOtherMenuItem: function(itemID, existingItemID) {
moveBeforeOtherMenuItemComponent(itemID, existingItemID);
return cy;
},
// Disables the menu item with given ID.
disableMenuItem: function(itemID) {
disableComponent(itemID);
return cy;
},
// Enables the menu item with given ID.
enableMenuItem: function(itemID) {
enableComponent(itemID);
return cy;
},
// Disables the menu item with given ID.
hideMenuItem: function(itemID) {
$('#'+itemID).data('show', false);
hideComponent($('#'+itemID));
return cy;
},
// Enables the menu item with given ID.
showMenuItem: function(itemID) {
$('#'+itemID).data('show', true);
displayComponent($('#'+itemID));
return cy;
},
// Destroys the extension instance
destroy: function() {
destroyCxtMenu();
return cy;
}
};
return instance;
}
if ( opts !== 'get' ) {
// merge the options with default ones
options = extend(defaults, opts);
setScratchProp('options', options);
// Clear old context menu if needed
if(getScratchProp('active')) {
destroyCxtMenu();
}
setScratchProp('active', true);
$cxtMenu = createAndAppendCxtMenuComponent();
var menuItems = options.menuItems;
createAndAppendMenuItemComponents(menuItems);
bindCyEvents();
preventDefaultContextTap();
}
return getInstance(this);
});
};
if( typeof module !== 'undefined' && module.exports ){ // expose as a commonjs module
module.exports = register;
}
if( typeof define !== 'undefined' && define.amd ){ // expose as an amd/requirejs module
define('cytoscape-context-menus', function(){
return register;
});
}
if( typeof cytoscape !== 'undefined' && $ ){ // expose to global cytoscape (i.e. window.cytoscape)
register( cytoscape, $ );
}
})();
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.cytoscapeContextMenus=t():e.cytoscapeContextMenus=t()}(window,(function(){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){var i=n(1).contextMenus,o=function(e){e&&e("core","contextMenus",i)};"undefined"!=typeof cytoscape&&o(cytoscape),e.exports=o},function(e,t,n){"use strict";function i(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return o(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return o(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,r=function(){};return{s:r,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,s=!0,a=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return s=e.done,e},e:function(e){a=!0,u=e},f:function(){try{s||null==n.return||n.return()}finally{if(a)throw u}}}}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n<t;n++)i[n]=e[n];return i}function r(e){return!function(e){return e.offsetWidth<=0&&e.offsetHeight<=0||e.style&&e.style.display||getComputedStyle(e).display}(e)}function u(e){for(var t="",n=0;n<e.length;n++){t+=e[n],n!==e.length-1&&(t+=" ")}return t}function s(e,t,n){n?e.setAttribute(t,""):e.removeAttribute(t)}function a(e,t,n){void 0===customElements.get(e)&&customElements.define(e,t,{extends:n})}n.r(t),n.d(t,"contextMenus",(function(){return j}));var c={evtType:"cxttap",menuItems:[],menuItemClasses:["cy-context-menus-cxt-menuitem"],contextMenuClasses:["cy-context-menus-cxt-menu"],submenuIndicator:{src:"assets/submenu-indicator-default.svg",width:12,height:12}};function l(e){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function f(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return d(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return d(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,o=function(){};return{s:o,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,u=!0,s=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return u=e.done,e},e:function(e){s=!0,r=e},f:function(){try{u||null==n.return||n.return()}finally{if(s)throw r}}}}function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n<t;n++)i[n]=e[n];return i}function h(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function m(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function y(e,t,n){return t&&m(e.prototype,t),n&&m(e,n),e}function v(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&I(e,t)}function p(e){var t=C();return function(){var n,i=k(e);if(t){var o=k(this).constructor;n=Reflect.construct(i,arguments,o)}else n=i.apply(this,arguments);return b(this,n)}}function b(e,t){return!t||"object"!==l(t)&&"function"!=typeof t?g(e):t}function g(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function x(e,t,n){return(x="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(e,t,n){var i=function(e,t){for(;!Object.prototype.hasOwnProperty.call(e,t)&&null!==(e=k(e)););return e}(e,t);if(i){var o=Object.getOwnPropertyDescriptor(i,t);return o.get?o.get.call(n):o.value}})(e,t,n||e)}function w(e){var t="function"==typeof Map?new Map:void 0;return(w=function(e){if(null===e||(n=e,-1===Function.toString.call(n).indexOf("[native code]")))return e;var n;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,i)}function i(){return M(e,arguments,k(this).constructor)}return i.prototype=Object.create(e.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),I(i,e)})(e)}function M(e,t,n){return(M=C()?Reflect.construct:function(e,t,n){var i=[null];i.push.apply(i,t);var o=new(Function.bind.apply(e,i));return n&&I(o,n.prototype),o}).apply(null,arguments)}function C(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}function I(e,t){return(I=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function k(e){return(k=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function S(e){e.preventDefault(),e.stopPropagation()}var E=function(e){v(n,e);var t=p(n);function n(e,i,o){var r,u,a,c,l,f,d,m,y,v;h(this,n),x((u=g(v=t.call(this)),k(n.prototype)),"setAttribute",u).call(u,"id",e.id);var p=v._getMenuItemClassStr(o.cxtMenuItemClasses,e.hasTrailingDivider);if(x((a=g(v),k(n.prototype)),"setAttribute",a).call(a,"class",p),x((c=g(v),k(n.prototype)),"setAttribute",c).call(c,"title",null!==(r=e.tooltipText)&&void 0!==r?r:""),e.disabled&&s(g(v),"disabled",!0),e.image){var b=document.createElement("img");b.src=e.image.src,b.width=e.image.width,b.height=e.image.height,b.style.position="absolute",b.style.top=e.image.y+"px",b.style.left=e.image.x+"px",x((l=g(v),k(n.prototype)),"appendChild",l).call(l,b)}if(v.innerHTML+=e.content,v.onMenuItemClick=i,v.data={},v.clickFns=[],v.selector=e.selector,v.show=void 0===e.show||e.show,v.coreAsWell=e.coreAsWell||!1,v.scratchpad=o,void 0===e.onClickFunction&&void 0===e.submenu)throw new Error("A menu item must either have click function or a submenu or both");return v.onClickFunction=e.onClickFunction,e.submenu instanceof Array&&v._createSubmenu(e.submenu),x((f=g(v),k(n.prototype)),"addEventListener",f).call(f,"mousedown",S),x((d=g(v),k(n.prototype)),"addEventListener",d).call(d,"mouseup",S),x((m=g(v),k(n.prototype)),"addEventListener",m).call(m,"touchstart",S),x((y=g(v),k(n.prototype)),"addEventListener",y).call(y,"touchend",S),v}return y(n,[{key:"bindOnClickFunction",value:function(e){this.clickFns.push(e),x(k(n.prototype),"addEventListener",this).call(this,"click",e)}},{key:"unbindOnClickFunctions",value:function(){var e,t=f(this.clickFns);try{for(t.s();!(e=t.n()).done;){var i=e.value;x(k(n.prototype),"removeEventListener",this).call(this,"click",i)}}catch(e){t.e(e)}finally{t.f()}this.clickFns=[]}},{key:"enable",value:function(){s(this,"disabled",!1),this.hasSubmenu()&&this.addEventListener("mouseenter",this.mouseEnterHandler)}},{key:"disable",value:function(){s(this,"disabled",!0),this.hasSubmenu()&&this.removeEventListener("mouseenter",this.mouseEnterHandler)}},{key:"hide",value:function(){this.show=!1,this.style.display="none"}},{key:"hasSubmenu",value:function(){return this.submenu instanceof O}},{key:"appendSubmenuItem",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;this.hasSubmenu()||this._createSubmenu(),this.submenu.appendMenuItem(e,t)}},{key:"isClickable",value:function(){return void 0!==this.onClickFunction}},{key:"display",value:function(){this.show=!0,this.style.display="block"}},{key:"removeSubmenu",value:function(){this.hasSubmenu()&&(this.submenu.removeAllMenuItems(),this.detachSubmenu())}},{key:"detachSubmenu",value:function(){this.hasSubmenu()&&(this.removeChild(this.submenu),this.removeChild(this.indicator),this.removeEventListener("mouseenter",this.mouseEnterHandler),this.removeEventListener("mouseleave",this.mouseLeaveHandler),this.submenu=void 0,this.indicator=void 0)}},{key:"_onMouseEnter",value:function(e){var t=this.getBoundingClientRect(),n=function(e){e.style.opacity="0",e.style.display="block";var t=e.getBoundingClientRect();return e.style.opacity="1",e.style.display="none",t}(this.submenu),i=t.right+n.width>window.innerWidth,o=t.top+n.height>window.innerHeight;i||o?i&&!o?(this.submenu.style.right=this.clientWidth+"px",this.submenu.style.top="0px",this.submenu.style.left="auto",this.submenu.style.bottom="auto"):i&&o?(this.submenu.style.right=this.clientWidth+"px",this.submenu.style.bottom="0px",this.submenu.style.top="auto",this.submenu.style.left="auto"):(this.submenu.style.left=this.clientWidth+"px",this.submenu.style.bottom="0px",this.submenu.style.right="auto",this.submenu.style.top="auto"):(this.submenu.style.left=this.clientWidth+"px",this.submenu.style.top="0px",this.submenu.style.right="auto",this.submenu.style.bottom="auto"),this.submenu.display()}},{key:"_onMouseLeave",value:function(e){var t,n,i,o,r,u={x:e.clientX,y:e.clientY};t=u,n=this.submenu,i=t.x,o=t.y,r=n.getBoundingClientRect(),i>=r.left&&i<=r.right&&o>=r.top&&o<=r.bottom||this.submenu.hide()}},{key:"_createSubmenu",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.indicator=this.scratchpad.submenuIndicatorGen(),this.submenu=new O(this.onMenuItemClick,this.scratchpad),this.appendChild(this.indicator),this.appendChild(this.submenu);var t,i=f(e);try{for(i.s();!(t=i.n()).done;){var o=t.value,r=new n(o,this.onMenuItemClick,this.scratchpad);this.submenu.appendMenuItem(r)}}catch(e){i.e(e)}finally{i.f()}this.mouseEnterHandler=this._onMouseEnter.bind(this),this.mouseLeaveHandler=this._onMouseLeave.bind(this),this.addEventListener("mouseenter",this.mouseEnterHandler),this.addEventListener("mouseleave",this.mouseLeaveHandler)}},{key:"_getMenuItemClassStr",value:function(e,t){return t?e+" cy-context-menus-divider":e}}],[{key:"define",value:function(){a("ctx-menu-item",n,"button")}}]),n}(w(HTMLButtonElement)),O=function(e){v(n,e);var t=p(n);function n(e,i){var o,r;return h(this,n),x((o=g(r=t.call(this)),k(n.prototype)),"setAttribute",o).call(o,"class",i.cxtMenuClasses),r.style.position="absolute",r.onMenuItemClick=e,r.scratchpad=i,r}return y(n,[{key:"hide",value:function(){this.isVisible()&&(this.hideSubmenus(),this.style.display="none")}},{key:"display",value:function(){this.style.display="block"}},{key:"isVisible",value:function(){return"none"!==this.style.display}},{key:"hideMenuItems",value:function(){var e,t=f(this.children);try{for(t.s();!(e=t.n()).done;){var n=e.value;n instanceof HTMLElement?n.style.display="none":console.warn("".concat(n," is not a HTMLElement"))}}catch(e){t.e(e)}finally{t.f()}}},{key:"hideSubmenus",value:function(){var e,t=f(this.children);try{for(t.s();!(e=t.n()).done;){var n=e.value;n instanceof E&&n.submenu&&n.submenu.hide()}}catch(e){t.e(e)}finally{t.f()}}},{key:"appendMenuItem",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;if(void 0!==t){if(t.parentNode!==this)throw new Error("The item with id='".concat(t.id,"' is not a child of the context menu"));this.insertBefore(e,t)}else this.appendChild(e);e.isClickable()&&this._performBindings(e)}},{key:"moveBefore",value:function(e,t){if(e.parentNode!==this)throw new Error("The item with id='".concat(e.id,"' is not a child of context menu"));if(t.parentNode!==this)throw new Error("The item with id='".concat(t.id,"' is not a child of context menu"));this.removeChild(e),this.insertBefore(e,t)}},{key:"removeAllMenuItems",value:function(){for(;this.firstChild;){var e=this.lastChild;e instanceof E?this._removeImmediateMenuItem(e):(console.warn("Found non menu item in the context menu: ",e),this.removeChild(e))}}},{key:"_removeImmediateMenuItem",value:function(e){if(!this._detachImmediateMenuItem(e))throw new Error("menu item(id=".concat(e.id,") is not in the context menu"));e.detachSubmenu(),e.unbindOnClickFunctions()}},{key:"_detachImmediateMenuItem",value:function(e){if(e.parentNode===this){if(this.removeChild(e),this.children.length<=0){var t=this.parentNode;t instanceof E&&t.detachSubmenu()}return!0}return!1}},{key:"_performBindings",value:function(e){var t=this._bindOnClick(e.onClickFunction);e.bindOnClickFunction(t),e.bindOnClickFunction(this.onMenuItemClick)}},{key:"_bindOnClick",value:function(e){var t=this;return function(){var n=t.scratchpad.currentCyEvent;e(n)}}}],[{key:"define",value:function(){a("menu-item-list",n,"div")}}]),n}(w(HTMLDivElement)),A=function(e){v(n,e);var t=p(n);function n(e,i){var o;return h(this,n),(o=t.call(this,e,i)).onMenuItemClick=function(t){S(t),o.hide(),e()},o}return y(n,[{key:"removeMenuItem",value:function(e){var t=e.parentElement;t instanceof O&&this.contains(t)&&t._removeImmediateMenuItem(e)}},{key:"appendMenuItem",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;this.ensureDoesntContain(e.id),x(k(n.prototype),"appendMenuItem",this).call(this,e,t)}},{key:"insertMenuItem",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.before,i=t.parent;if(this.ensureDoesntContain(e.id),void 0!==n){if(!this.contains(n))throw new Error("before(id=".concat(n.id,") is not in the context menu"));var o=n.parentNode;if(!(o instanceof O))throw new Error("Parent of before(id=".concat(n.id,") is not a submenu"));o.appendMenuItem(e,n)}else if(void 0!==i){if(!this.contains(i))throw new Error("parent(id=".concat(i.id,") is not a descendant of the context menu"));i.appendSubmenuItem(e)}else this.appendMenuItem(e)}},{key:"moveBefore",value:function(e,t){var n=e.parentElement;if(!this.contains(n))throw new Error("parent(id=".concat(n.id,") is not in the contex menu"));if(!this.contains(t))throw new Error("before(id=".concat(t.id,") is not in the context menu"));n.removeChild(e),this.insertMenuItem(e,{before:t})}},{key:"moveToSubmenu",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,i=e.parentElement;if(!(i instanceof O))throw new Error("current parent(id=".concat(i.id,") is not a submenu"));if(!this.contains(i))throw new Error("parent of the menu item(id=".concat(i.id,") is not in the context menu"));if(null!==t){if(!this.contains(t))throw new Error("parent(id=".concat(t.id,") is not in the context menu"));i._detachImmediateMenuItem(e),t.appendSubmenuItem(e)}else null!==n&&(e.selector=n.selector,e.coreAsWell=n.coreAsWell),i._detachImmediateMenuItem(e),this.appendMenuItem(e)}},{key:"ensureDoesntContain",value:function(e){var t=document.getElementById(e);if(void 0!==t&&this.contains(t))throw new Error("There is already an element with id=".concat(e," in the context menu"))}}],[{key:"define",value:function(){a("ctx-menu",n,"div")}}]),n}(O);function _(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return T(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return T(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,o=function(){};return{s:o,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,u=!0,s=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return u=e.done,e},e:function(e){s=!0,r=e},f:function(){try{u||null==n.return||n.return()}finally{if(s)throw r}}}}function T(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n<t;n++)i[n]=e[n];return i}function j(e){var t=this;t.scratch("cycontextmenus")||t.scratch("cycontextmenus",{});var n,o,s=function(e){return t.scratch("cycontextmenus")[e]},a=function(e,n){return t.scratch("cycontextmenus")[e]=n},l=s("options"),f=s("cxtMenu"),d=function(e){var n,i=t.container(),o=s("cxtMenuPosition"),r=e.position||e.cyPosition;if(o!=r){f.hideMenuItems(),a("anyVisibleChild",!1),a("cxtMenuPosition",r);var u={top:(n=i.getBoundingClientRect()).top,left:n.left},c=e.renderedPosition||e.cyRenderedPosition,l=getComputedStyle(i)["border-width"],d=parseInt(l.replace("px",""))||0;d>0&&(u.top+=d,u.left+=d);var h=i.clientHeight,m=i.clientWidth,y=h/2,v=m/2;c.y>y&&c.x<=v?(f.style.left=c.x+"px",f.style.bottom=h-c.y+"px",f.style.right="auto",f.style.top="auto"):c.y>y&&c.x>v?(f.style.right=m-c.x+"px",f.style.bottom=h-c.y+"px",f.style.left="auto",f.style.top="auto"):c.y<=y&&c.x<=v?(f.style.left=c.x+"px",f.style.top=c.y+"px",f.style.right="auto",f.style.bottom="auto"):(f.style.right=m-c.x+"px",f.style.top=c.y+"px",f.style.left="auto",f.style.bottom="auto")}},h=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,n=y(e);if(void 0!==t){var i=p(t);f.insertMenuItem(n,{parent:i})}else f.insertMenuItem(n)},m=function(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,n=0;n<e.length;n++)h(e[n],t)},y=function(e){var n=t.scratch("cycontextmenus");return new E(e,f.onMenuItemClick,n)},v=function(){s("active")&&(f.removeAllMenuItems(),t.off("tapstart",s("eventCyTapStart")),t.off(l.evtType,s("onCxttap")),t.off("viewport",s("onViewport")),document.body.removeEventListener("mouseup",s("hideOnNonCyClick")),f.parentNode.removeChild(f),f=void 0,a("cxtMenu",void 0),a("active",!1),a("anyVisibleChild",!1),a("onCxttap",void 0),a("onViewport",void 0),a("hideOnNonCyClick",void 0))},p=function(e){var t=document.getElementById(e);if(t instanceof E)return t;throw new Error("The item with id=".concat(e," is not a menu item"))};if("get"!==e){E.define(),O.define(),A.define(),l=function(e,t){var n={};for(var i in e)n[i]=e[i];for(var o in t)n[o]instanceof Array?n[o]=n[o].concat(t[o]):n[o]=t[o];return n}(c,e),a("options",l),s("active")&&v(),a("active",!0),a("submenuIndicatorGen",function(e){var t=document.createElement("img");return t.src=e.src,t.width=e.width,t.height=e.height,t.classList.add("cy-context-menus-submenu-indicator"),t}.bind(void 0,l.submenuIndicator));var b=u(l.contextMenuClasses);a("cxtMenuClasses",b);var g=t.scratch("cycontextmenus");f=new A((function(){return a("cxtMenuPosition",void 0)}),g),a("cxtMenu",f),t.container().appendChild(f),a("cxtMenuItemClasses",u(l.menuItemClasses));var x=l.menuItems;m(x),o=function(e){a("currentCyEvent",e),d(e);var n,i=e.target||e.cyTarget,o=_(f.children);try{for(o.s();!(n=o.n()).done;){var u=n.value;u instanceof E&&(i===t?u.coreAsWell:i.is(u.selector))&&u.show&&(f.display(),a("anyVisibleChild",!0),u.display())}}catch(e){o.e(e)}finally{o.f()}!s("anyVisibleChild")&&r(f)&&f.hide()},t.on(l.evtType,o),a("onCxttap",o),function(){var e=function(e){if(f.contains(e.originalEvent.target))return!1;f.hide(),a("cxtMenuPosition",void 0),a("currentCyEvent",void 0)};t.on("tapstart",e),a("eventCyTapStart",e);var n=function(){f.hide()};t.on("viewport",n),a("onViewport",n)}(),n=function(e){t.container().contains(e.target)||f.contains(e.target)||(f.hide(),a("cxtMenuPosition",void 0))},document.addEventListener("mouseup",n),a("hideOnNonCyClick",n),function(){var e,t=i(document.getElementsByClassName("cy-context-menus-cxt-menu"));try{for(t.s();!(e=t.n()).done;){e.value.addEventListener("contextmenu",(function(e){return e.preventDefault()}))}}catch(e){t.e(e)}finally{t.f()}}()}return function(e){return{isActive:function(){return s("active")},appendMenuItem:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;return h(t,n),e},appendMenuItems:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;return m(t,n),e},removeMenuItem:function(t){var n=p(t);return f.removeMenuItem(n),e},setTrailingDivider:function(t,n){var i=p(t);return n?i.classList.add("cy-context-menus-divider"):i.classList.remove("cy-context-menus-divider"),e},insertBeforeMenuItem:function(t,n){var i=y(t),o=p(n);return f.insertMenuItem(i,{before:o}),e},moveToSubmenu:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=p(t);if(null===n)f.moveToSubmenu(i);else if("string"==typeof n){var o=p(n.toString());f.moveToSubmenu(i,o)}else void 0!==n.coreAsWell||void 0!==n.selector?f.moveToSubmenu(i,null,n):console.warn("options neither has coreAsWell nor selector property but it is an object. Are you sure that this is what you want to do?");return e},moveBeforeOtherMenuItem:function(t,n){var i=p(t),o=p(n);return f.moveBefore(i,o),e},disableMenuItem:function(t){return p(t).disable(),e},enableMenuItem:function(t){return p(t).enable(),e},hideMenuItem:function(t){return p(t).hide(),e},showMenuItem:function(t){return p(t).display(),e},destroy:function(){return v(),e}}}(this)}}])}));

@@ -0,0 +0,0 @@ MIT License

{
"name": "cytoscape-context-menus",
"version": "3.1.0",
"version": "4.0.0",
"description": "A Cytoscape.js extension to provide context menu around elements and core instance.",

@@ -11,3 +11,5 @@ "main": "cytoscape-context-menus.js",

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"build": "cross-env NODE_ENV=production webpack",
"build:dev": "cross-env NODE_ENV=development webpack"
},

@@ -28,14 +30,12 @@ "repository": {

"devDependencies": {
"gulp": "^3.9.1",
"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": "^7.10.3",
"@babel/preset-env": "^7.10.3",
"babel-loader": "^8.1.0",
"cross-env": "^7.0.2",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
},
"peerDependencies": {
"cytoscape": "^2.7.0 || ^3.0.0",
"jquery": "^1.7.0 || ^2.0.0 || ^3.0.0"
"cytoscape": "^2.7.0 || ^3.0.0"
}
}

@@ -9,3 +9,3 @@ cytoscape-context-menus

![Image of extension](example.png)
![Image of extension](assets/example.png)

@@ -23,3 +23,2 @@ Please cite the following paper when using this extension:

* Cytoscape.js ^2.7.0 || ^3.0.0
* jQuery ^1.7.0 || ^2.0.0 || ^3.0.0

@@ -38,9 +37,10 @@

Note: es import doesn't work for plain javascript applications because webpack doesn't support es module output at the moment.
```js
import cytoscape from 'cytoscape';
import $ from 'jquery';
import contextMenus from 'cytoscape-context-menus';
// register extension
cytoscape.use(contextMenus, $);
cytoscape.use(contextMenus);

@@ -54,6 +54,5 @@ // import CSS as well

var cytoscape = require('cytoscape');
var jquery = require('jquery');
var contextMenus = require('cytoscape-context-menus');
contextMenus( cytoscape, jquery ); // register extension
contextMenus(cytoscape); // register extension
```

@@ -63,4 +62,4 @@

```js
require(['cytoscape', 'cytoscape-context-menus', 'jquery'], function( cytoscape, contextMenus, jquery ){
contextMenus( cytoscape, jquery ); // register extension
require(['cytoscape', 'cytoscape-context-menus'], function(cytoscape, contextMenus) {
contextMenus(cytoscape); // register extension
});

@@ -78,2 +77,3 @@ ```

// List of initial menu items
// A menu item must have either onClickFunction or submenu or both
menuItems: [/*

@@ -95,2 +95,3 @@ {

coreAsWell: false // Whether core instance have this item on cxttap
submenu: [] // Shows the listed menuItems as a submenu for this item. An item must have either submenu or onClickFunction or both.
},

@@ -126,46 +127,73 @@ {

// add class names to this list
]
],
// Indicates that the menu item has a submenu. If not provided default one will be used
submenuIndicator: { src: 'assets/submenu-indicator-default.svg', width: 12, height: 12 }
};
```
**Note:** `selector` and `coreAsWell` options are ignored for the items that are inside a submenu. Their visiblity depends on their root parent's visibility.
## API
### Instance API
```js
var instance = cy.contextMenus( options );
var instance = cy.contextMenus(options);
```
An instance has a number of functions available:
#### `instance.isActive()`
* Returns whether the extension is active.
```js
instance.isActive(); // Returns whether the extension is active.
#### `instance.appendMenuItem(item, parentID = undefined)`
* Appends given menu item to the menu items list.
* If parentID is specified, the item is inserted to the submenu of the item with parentID.
* If the parent has no submenu then it will automatically be created.
* If not specified item will be inserted to the root of the contextmenu
instance.appendMenuItem(item); // Appends given menu item to the menu items list.
#### `instance.appendMenuItems(items, parentID = undefined)`
* Same with above but takes an array of items
instance.appendMenuItems(items); // Appends menu items in the given list to the menu items list.
#### `instance.removeMenuItem(itemID)`
* Removes the menu item with given ID and its submenu along with
instance.removeMenuItem(itemID); // Removes the menu item with given ID.
#### `instance.setTrailingDivider(itemID, status)`
* Sets whether the menuItem with given ID will have a following divider
instance.setTrailingDivider(itemID, status); // Sets whether the menuItem with given ID will have a following divider.
#### `instance.insertBeforeMenuItem(item, existingItemID)`
* Inserts given item before the existingitem
instance.insertBeforeMenuItem(item, existingItemID); // Inserts given item before the existingitem.
#### `instance.moveToSubmenu(itemID, options = null)`
* Moves the item with given ID to the submenu of the parent with the given ID or to root with the specified options
* If `options` is a `string`, then it is the id of the parent
* If `options` is a `{ selector?: string, coreAsWell?: boolean }`, then old properties are overwritten by them and the menu item is moved to the root. If it doesn't have either properties item is **not moved**.
* If `options` is null or not provided, then it is just moved to the root
instance.moveBeforeOtherMenuItem(itemID, existingItemID); // Moves the item with given ID before the existingitem.
#### `instance.moveBeforeOtherMenuItem(itemID, existingItemID)`
* Inserts the `item` before the `existingItem` and moves it to the submenu that contains the `existingItem`
instance.disableMenuItem(itemID); // Disables the menu item with given ID.
#### `instance.disableMenuItem(itemID)`
* Disables the menu item with given ID.
instance.enableMenuItem(itemID); // Enables the menu item with given ID.
#### `instance.enableMenuItem(itemID)`
* Enables the menu item with given ID.
instance.showMenuItem(itemID); // Shows the menu item with given ID.
#### `instance.showMenuItem(itemID)`
* Shows the menu item with given ID.
instance.hideMenuItem(itemID); // Hides the menu item with given ID.
#### `instance.hideMenuItem(itemID)`
* Hides the menu item with given ID.
instance.destroy(); // Destroys the extension instance
```
#### `instance.destroy()`
* Destroys the extension instance
You can also get an existing instance:
### Other API
```js
cy.contextMenus('get');
```
#### `cy.contextMenus('get')`
* Returns the existing instance to the extension
## Build targets
* `npm run build` : Build `./src/**` into `cytoscape-edge-editing.js` in production environment and minimize the file.
* `npm run build:dev` : Build `./src/**` into `cytoscape-edge-editing.js` in development environment without minimizing the file.
## Publishing instructions

@@ -175,4 +203,7 @@

1. Set the version number environment variable: `export VERSION=1.2.3`
1. Publish: `gulp publish`
1. Build the extension : `npm run build`
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-context-menus https://github.com/iVis-at-Bilkent/cytoscape.js-context-menus.git`

@@ -182,2 +213,2 @@

* [Metin Can Siper](https://github.com/metincansiper), [Ugur Dogrusoz](https://github.com/ugurdogrusoz) of [i-Vis at Bilkent University](http://www.cs.bilkent.edu.tr/~ivis)
* [Metin Can Siper](https://github.com/metincansiper), [Onur Şahin](https://github.com/onsah), [Hasan Balcı](https://github.com/hasanbalci) and [Ugur Dogrusoz](https://github.com/ugurdogrusoz) of [i-Vis at Bilkent University](http://www.cs.bilkent.edu.tr/~ivis)

Sorry, the diff of this file is not supported yet

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