diff --git a/.gitignore b/.gitignore index 5b04c74..04c4687 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea node_modules/ +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md index 155dfbe..0d55905 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Add a reference to `contextMenu.js`. In your app config add `ui.bootstrap.contex - `context-menu-class` - A string literal containing a custom class to be added to the context menu (The <ul> elements) - `allow-event-propagation` - (Default: false) A boolean determining whether to allow event propagation. Note that if you set this to true, and don’t catch it with something else the browser’s context menu will be shown on top of this library’s context menu. - `model` - (See Model Attribute below) +- `close-menu-on` - (Default: '') A string literal containing event for triggering menu close action. ### View @@ -94,6 +95,7 @@ Every menu option is represented by an Object containing the following propertie | -------- | ---- | ----------- | | text | Function/String | A function that returns the string or the actual string itself. Either text or html must be specified | | html | Function/String | A function or string that returns the html to be used for this menu option. Either text or html must be specified | +| compile | Boolean | To compile html string to use a custom directive in the html string | | click | Function | The function to be called on click of the option| | enabled | Function/Boolean | A function returning whether the option is enabled or not, or a boolean | | displayed | Function/Boolean | A function returning whether the option is displayed or not, or a boolean. If not displayed, no element is created at all and nothing related to the item will be executed (events, functions returning children, etc.) | diff --git a/bower.json b/bower.json index 49072f5..daf4522 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-bootstrap-contextmenu", - "version": "1.1.0", + "version": "1.2.1", "main": [ "contextMenu.js" ], diff --git a/contextMenu.js b/contextMenu.js index c798590..fe8b000 100644 --- a/contextMenu.js +++ b/contextMenu.js @@ -23,8 +23,8 @@ // Triggers right after any context menu is opened ContextMenuOpened: 'context-menu-opened' }) - .directive('contextMenu', ['$rootScope', 'ContextMenuEvents', '$parse', '$q', 'CustomService', '$sce', '$document', '$window', - function ($rootScope, ContextMenuEvents, $parse, $q, custom, $sce, $document, $window) { + .directive('contextMenu', ['$rootScope', 'ContextMenuEvents', '$parse', '$q', 'CustomService', '$sce', '$document', '$window', '$compile', + function ($rootScope, ContextMenuEvents, $parse, $q, custom, $sce, $document, $window, $compile) { var _contextMenus = []; // Contains the element that was clicked to show the context menu @@ -50,8 +50,13 @@ // runs the function that expects a jQuery/jqLite element optionText = item.html($scope); } else { - // Assumes that the developer already placed a valid jQuery/jqLite element - optionText = item.html; + // Incase we want to compile html string to initialize their custom directive in html string + if (item.compile) { + optionText = $compile(item.html)($scope); + } else { + // Assumes that the developer already placed a valid jQuery/jqLite element + optionText = item.html; + } } } else { @@ -381,7 +386,8 @@ $q.all($promises).then(function () { var topCoordinate = event.pageY; var menuHeight = angular.element($ul[0]).prop('offsetHeight'); - var winHeight = $window.scrollY + event.view.innerHeight; + var winHeight = $window.pageYOffset + event.view.innerHeight; + /// the 20 pixels in second condition are considering the browser status bar that sometimes overrides the element if (topCoordinate > menuHeight && winHeight - topCoordinate < menuHeight + 20) { topCoordinate = event.pageY - menuHeight; @@ -510,7 +516,7 @@ } function removeAllContextMenus(e) { - $document.find('body').off('mousedown', removeOnOutsideClickEvent); + $document.find('body').off('mousedown touchstart', removeOnOutsideClickEvent); $document.off('scroll', removeOnScrollEvent); $(_clickedElement).removeClass('context'); removeContextMenus(); @@ -568,6 +574,10 @@ angular.forEach(openMenuEvents, function (openMenuEvent) { element.on(openMenuEvent.trim(), function (event) { + // Cleanup any leftover contextmenus(there are cases with longpress on touch where we + // still see multiple contextmenus) + removeAllContextMenus(); + if(!attrs.allowEventPropagation) { event.stopPropagation(); event.preventDefault(); @@ -579,7 +589,7 @@ } // Remove if the user clicks outside - $document.find('body').on('mousedown', removeOnOutsideClickEvent); + $document.find('body').on('mousedown touchstart', removeOnOutsideClickEvent); // Remove the menu when the scroll moves $document.on('scroll', removeOnScrollEvent); @@ -617,6 +627,12 @@ }); }); }); + + if (attrs.closeMenuOn) { + $scope.$on(attrs.closeMenuOn, function () { + removeAllContextMenus(); + }); + } }; }]); // eslint-disable-next-line angular/window-service diff --git a/package.json b/package.json index cf7cbf8..acd65df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-bootstrap-contextmenu", - "version": "1.1.0", + "version": "1.2.1", "description": "Angular Bootstrap Context Menu", "main": "contextMenu.js", "scripts": {