<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<pre>open context menu on 2nd column, and hit select,<br> you will get it's value in corresponding function</pre>
<div ng-app="HelloWorldApp" class='container'>
<div ng-controller="HelloWorldController">
<div contextmenu="meta.contextmenu" class="dropdown contextmenu">
<ul class="dropdown-menu" role="menu">
<li class="dropdown-header">
{{ meta.contextmenu.item.address }}
</li>
<li>
<a role="menuitem" href
ng-click="delete(meta.contextmenu.item)"
>
<span>Delete</span>
</a>
</li>
</ul>
</div>
<table class='table table-striped' contextmenu-container="meta.contextmenu">
<tr>
<td><b>NAME</b></td>
<td><b>ADDRESS</b></td>
</tr>
<tr ng-repeat="obj in objects" contextmenu-item="obj" >
<td>{{obj.name}}</td>
<td context-menu="menuOptions">{{obj.address}}</td>
</tr>
</table>
Data to delete :
<pre>{{selected.name}}</pre>
<pre>{{selected.address}}</pre>
</div>
</div>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
</body>
</html>
angular.module('HelloWorldApp', ['io.dennis.contextmenu'])
.controller('HelloWorldController', function($scope) {
$scope.greeting = "Hello World";
$scope.objects = [{
name: 'person1',
address: 'India'
},
{
name: 'any name',
address: 'any address'
}];
$scope.delete = function(data){
console.log(data);
$scope.selected = data;
}
});
//contextmenu -angular-contextmenu
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ngContextmenu = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
'use strict';
angular.module('io.dennis.contextmenu')
.directive('contextmenuContainer', Container);
function Container() {
return {
scope: {
contextmenu: '=contextmenuContainer'
},
restrict: 'A',
controller: ['$scope', ContainerCtrl]
};
}
function ContainerCtrl($scope) {
var pub = this;
pub.get = get;
function get() {
return $scope.contextmenu;
}
}
},{}],2:[function(_dereq_,module,exports){
'use strict';
angular.module('io.dennis.contextmenu')
.provider('$contextmenu', ContextmenuProvider)
.directive('contextmenu', Contextmenu);
var config = {
DEBOUNCE_BROADCAST_TIME: 200
};
var contextmenuConfig = new ContextmenuConfig();
function ContextmenuConfig() {
this.set = function(key, value) {
if (config[key]) {
config[key] = value;
}
return config[key];
};
this.get = function(key) {
return config[key];
};
}
function ContextmenuProvider() {
this.$get = function() {
return contextmenuConfig;
};
}
Contextmenu.$inject = [
'$window',
'$rootScope',
'ContextmenuService'
];
var canBroadcast = true;
var broadcastClose;
function Contextmenu($window, $rootScope, $contextmenu) {
broadcastClose = (function($rootScope) {
return function _broadcastClose() {
if (canBroadcast) {
$rootScope.$broadcast('contextmenu.close');
canBroadcast = false;
setTimeout(function() {
canBroadcast = true;
}, config.DEBOUNCE_BROADCAST_TIME);
}
}
})($rootScope);
var $windowElement = angular.element($window);
$windowElement.on('contextmenu scroll click', broadcastClose);
return {
scope: {
contextmenu: '='
},
restrict: 'A',
controller: ['$scope', '$window', '$rootScope', CotextmenuCtrl],
link: link,
priority: 100
};
function link(scope, element, attrs, ctrl) {
scope.contextmenu = $contextmenu.$get();
scope.contextmenu.setMenu(ctrl);
ctrl.setElement(element);
}
}
function CotextmenuCtrl($scope, $window, $rootScope) {
console.log('init contextmenu ctrl');
var pub = this;
var $element;
$scope.$on('contextmenu.close', close);
pub.open = open;
pub.close = close;
pub.setElement = setElement;
function open(item, x, y) {
broadcastClose();
$element.css({top: y, left: x})
.toggleClass('dropup', isDropup(y))
.toggleClass('open', true)
.toggleClass('ng-hide', false);
}
function close() {
$element.toggleClass('ng-hide', true);
}
function setElement(element) {
$element = element;
}
function isDropup(y) {
var mid = $window.innerHeight / 2;
return (y > mid);
}
}
},{}],3:[function(_dereq_,module,exports){
'use strict';
angular.module('io.dennis.contextmenu')
.directive('contextmenuItem', Item);
Item.$inject = [];
function Item() {
/*global DocumentTouch:false */
var isTouch = !!(('ontouchstart' in window) ||
window.DocumentTouch && document instanceof DocumentTouch);
return {
scope: {
item: '=contextmenuItem'
},
require: '^contextmenuContainer',
restrict: 'A',
link: link
};
function link(scope, element, attrs, ctrl) {
var iam = mk(scope.item, element);
return (isTouch) ?
registerTouch(iam, scope, ctrl) :
registerMouse(iam, scope, ctrl);
}
function registerTouch(iam, scope, ctrl) {
iam.element.on('click', function(ev) {
ev.preventDefault();
ev.stopPropagation();
ctrl.get().open(iam, ev.clientX, ev.clientY);
scope.$apply();
return false;
});
}
function registerMouse(iam, scope, ctrl) {
iam.element.on('click', function(ev) {
var multi = ev.ctrlKey || ev.metaKey;
ev.preventDefault();
ev.stopPropagation();
ctrl.get().toggle(iam, multi);
scope.$apply();
});
iam.element.on('contextmenu', function(ev) {
// don't show context menu if user holds down ctrl || cmd key
if (ev.ctrlKey || ev.metaKey) { return; }
ev.preventDefault();
ev.stopPropagation();
ev.stopImmediatePropagation();
ctrl.get().open(iam, ev.clientX, ev.clientY);
scope.$apply();
return false;
});
}
function mk(item, element) {
return {item: item, element: element};
}
}
},{}],4:[function(_dereq_,module,exports){
'use strict';
angular.module('io.dennis.contextmenu', []);
_dereq_('./service/service');
_dereq_('./directive/contextmenu');
_dereq_('./directive/container');
_dereq_('./directive/item');
},{"./directive/container":1,"./directive/contextmenu":2,"./directive/item":3,"./service/service":5}],5:[function(_dereq_,module,exports){
'use strict';
angular.module('io.dennis.contextmenu')
.service('ContextmenuService', ContextmenuProvider);
function ContextmenuProvider() {
var self = this;
self.$get = function() {
return new Contextmenu();
};
}
function Contextmenu() {
var pub = this;
var selected = [];
var menu;
init();
function init() {
pub.menu = menu;
pub.selected = selected;
pub.setMenu = setMenu;
pub.add = add;
pub.remove = remove;
pub.isSelected = isSelected;
pub.get = get;
pub.num = getNumberOf;
pub.open = open;
pub.close = close;
pub.toggle = toggle;
pub.clear = clear;
pub.listOfIds = getListOfIds;
}
function setMenu(ctrl) {
menu = ctrl;
}
function add(entry) {
if (!isSelected(entry)) {
selected.unshift(entry);
toggleSelected(entry.element, true);
}
pub.item = selected[0].item;
}
function remove(entry) {
var index = selected.indexOf(entry);
if (index > -1) {
selected.splice(index, 1);
}
toggleSelected(entry.element, false);
}
function isSelected(entry) {
return (selected.indexOf(entry) > -1);
}
function get() {
return selected[0];
}
function getNumberOf() {
return selected.length || 0;
}
function open(entry, x, y) {
x = x || 0;
y = y || 0;
if (!isSelected(entry)) {
clear();
}
add(entry);
menu.open.apply(null, arguments);
}
function close() {
menu.close.apply(null, arguments);
}
function toggle(entry, multi) {
multi = multi || false;
var isEntrySelected = isSelected(entry);
if (isEntrySelected) {
remove(entry);
} else {
if (!multi) { clear(); }
add(entry);
}
}
function clear() {
angular.forEach(selected, function(entry) {
toggleSelected(entry.element, false);
});
selected = [];
}
function getListOfIds(limit, path) {
path = path || 'item.id';
limit = Math.min(limit || selected.length, selected.length);
var list = selected.slice(0, limit).map(function(entry) {
return safeGet(entry, path, '');
});
var asString = list.join(', ');
return (limit < selected.length) ? asString + '..' : asString;
}
function toggleSelected(element, forceState) {
element.toggleClass('selected', forceState);
}
function safeGet(obj, path, _default) {
if (!obj) {
return _default;
}
if (!path || !String(path).length) {
return obj;
}
var keys = (angular.isArray(path)) ? path : path.split('.');
var next = keys.shift();
return get(obj[next], keys, _default);
}
}
},{}]},{},[4])(4)
});
Output
300px
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |