<!DOCTYPE html>
<html ng-app="myApp">
<head lang="en">
<meta charset="utf-8">
<title>Bootstrap Table Directive</title>
<link
rel="stylesheet"
href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap-combined.min.css"
>
<link rel="stylesheet" href="style.css">
</head>
<body ng-controller="Ctrl">
<h1>Bootstrap Context Menu</h1>
<p>
The following table contains the <b>context menu</b> directive,
which offers the ability to open up a dropdown menu in case of a
click on the table row. The directive is bound via <b>context="targetUL"</b>
and references the <b>ul</b> defined in the document. All click events are
catched, in case on a document click, the context menu is closed.
</p>
<p>
The scope is applied to the context menu, and the model
is passed through via scope : '@&', so all click events are passed
through to the parent controller. That makes the context menu really
easy to use and the events easy to catch.
</p>
<table class="table table-bordered table-striped cell-highlight" style="margin-top: 20px">
<thead>
<tr>
<th>Header One</th>
<th>Header Two</th>
</tr>
</thead>
<tbody>
<tr context="context1">
<td>Item three</td>
<td>Item four</td>
</tr>
<tr context="context2">
<td>Item five</td>
<td>Item six</td>
</tr>
</tbody>
</table>
<ul id="context1" class="dropdown-menu">
<li><a ng-click="edit()">Edit</a></li>
<li><a ng-click="link()">Link</a></li>
<li><a ng-click="delete()">Delete</a></li>
<li class="divider"></li>
<li><a ng-click="properties()">Properties</a></li>
</ul>
<ul id="context2" class="dropdown-menu">
<li><a ng-click="edit()">Edit</a></li>
<li class="divider"></li>
<li><a ng-click="properties()">Properties</a></li>
</ul>
<pre>clicked = {{clicked || json }}</pre>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<script src="app.js"></script>
<script src="controller.js"></script>
</body>
</html>
var app = angular.module('myApp', ['directive.contextMenu']);
app.controller('Ctrl', ["$scope", function($scope){
$scope.clicked = '';
$scope.edit = function(){
$scope.clicked = 'edit was clicked';
console.log($scope.clicked);
};
$scope.properties = function(){
$scope.clicked = 'properties was clicked';
console.log($scope.clicked);
};
$scope.link = function(){
$scope.clicked = 'link was clicked';
console.log($scope.clicked);
};
$scope.delete = function(){
$scope.clicked = 'delete was clicked';
console.log($scope.clicked);
};
}]);
(function(angular) {
var directiveContextMenu = angular.module('directive.contextMenu', []);
directiveContextMenu.directive('cellHighlight', function(){
var postLink = function(scope, iElement, iAttrs) {
var td = iElement.find('td');
td.mouseover(function() {
$(this).parent('tr').css('opacity', '0.7');
});
td.mouseout(function() {
$(this).parent('tr').css('opacity', '1.0');
});
};
return {
restrict: 'C',
postLink: postLink
};
});
directiveContextMenu.directive('context', function() {
return {
restrict : 'A',
scope : '@&',
compile: function compile(tElement, tAttrs, transclude) {
return {
post: function postLink(scope, iElement, iAttrs, controller) {
var ul = $('#' + iAttrs.context);
var last = null;
ul.css({ 'display' : 'none'});
$(iElement).click(function(event) {
var X = event.clientX;
var Y = event.clientY;
ul.css({
display: "block",
position: "fixed",
top: Y + 'px',
left: X + 'px'
});
last = event.timeStamp;
});
$(document).click(function(event) {
var target = $(event.target);
if(!target.is(".popover") && !target.parents().is(".popover")) {
if(last === event.timeStamp)
return;
ul.css({
'display' : 'none'
});
}
});
}
};
}
};
});
})(window.angular);
.cell-highlight > tbody > tr:hover {
-webkit-transition: opacity 0.15s linear;
-moz-transition: opacity 0.15s linear;
-o-transition: opacity 0.15s linear;
transition: opacity 0.15s linear;
opacity: 0.5;
}