From 03d4edc0c5b810b81e8694753ae585f73625b867 Mon Sep 17 00:00:00 2001 From: Rihards Neimanis Date: Wed, 16 Oct 2019 13:04:30 +0300 Subject: [PATCH 1/5] Added logic to be able to specify if: (1) close button 'x' should be visible/hidden; (2) to be able to close the modal on ESC press as configurable option; (3) to disable/enable close on outside click (click on overlay) --- .gitignore | 1 + demo.html | 2 +- dist/ng-modal.js | 51 ++++++++++++++++++++++++++++++++++++++------ dist/ng-modal.min.js | 2 +- src/ng-modal.coffee | 39 ++++++++++++++++++++++++++++++--- 5 files changed, 83 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 2fb31f2..714a037 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ build spec/build ng-modal.zip dist/ng-modal.zip +.idea/ diff --git a/demo.html b/demo.html index 7168aaa..7af0aa1 100644 --- a/demo.html +++ b/demo.html @@ -12,7 +12,7 @@
- +

This is some html content

diff --git a/dist/ng-modal.js b/dist/ng-modal.js index 6879162..c19fb3d 100644 --- a/dist/ng-modal.js +++ b/dist/ng-modal.js @@ -1,12 +1,16 @@ (function() { - var app; + var app, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; app = angular.module("ngModal", []); app.provider("ngModalDefaults", function() { return { options: { - closeButtonHtml: "X" + closeButtonHtml: "X", + hideCloseButton: false, + closeOnEscape: true, + closeOnOutsideClick: true }, $get: function() { return this.options; @@ -28,18 +32,44 @@ }); app.directive('modalDialog', [ - 'ngModalDefaults', '$sce', function(ngModalDefaults, $sce) { + 'ngModalDefaults', '$sce', '$timeout', function(ngModalDefaults, $sce, $timeout) { return { restrict: 'E', scope: { show: '=', dialogTitle: '@', - onClose: '&?' + onClose: '&?', + hideCloseButton: '=', + closeOnEscape: '=', + closeOnOutsideClick: '=' }, replace: true, transclude: true, link: function(scope, element, attrs) { - var setupCloseButton, setupStyle; + var bindEscKeyPress, setupCloseButton, setupStyle, unbindEscKeyPress; + scope.hCB = scope.hideCloseButton === void 0 ? ngModalDefaults.hideCloseButton : scope.hideCloseButton; + scope.cOE = scope.closeOnEscape === void 0 ? ngModalDefaults.closeOnEscape : scope.closeOnEscape; + scope.cOOC = scope.closeOnOutsideClick === void 0 ? ngModalDefaults.closeOnOutsideClick : scope.closeOnOutsideClick; + bindEscKeyPress = function() { + if (scope.cOE) { + return document.onkeydown = function(evt) { + var isEscape; + evt = evt || window.event; + isEscape = false; + if (__indexOf.call(evt, "key") >= 0) { + isEscape = evt.key === "Escape" || evt.key === "Esc"; + } else { + isEscape = evt.keyCode === 27; + } + if (isEscape) { + return scope.hideModal(); + } + }; + } + }; + unbindEscKeyPress = function() { + return document.onkeydown = function() {}; + }; setupCloseButton = function() { return scope.closeButtonHtml = $sce.trustAsHtml(ngModalDefaults.closeButtonHtml); }; @@ -53,22 +83,29 @@ } }; scope.hideModal = function() { - return scope.show = false; + var triggerDigest; + scope.show = false; + return triggerDigest = $timeout(function() { + return $timeout.cancel(triggerDigest); + }); }; scope.$watch('show', function(newVal, oldVal) { if (newVal && !oldVal) { + bindEscKeyPress(); document.getElementsByTagName("body")[0].style.overflow = "hidden"; } else { + unbindEscKeyPress(); document.getElementsByTagName("body")[0].style.overflow = ""; } if ((!newVal && oldVal) && (scope.onClose != null)) { + unbindEscKeyPress(); return scope.onClose(); } }); setupCloseButton(); return setupStyle(); }, - template: "

\n
\n
\n \n
\n
\n
\n
\n
\n
" + template: "
\n
\n
\n \n
\n
\n
\n
\n
\n
" }; } ]); diff --git a/dist/ng-modal.min.js b/dist/ng-modal.min.js index 61a0b6e..015ff44 100644 --- a/dist/ng-modal.min.js +++ b/dist/ng-modal.min.js @@ -1 +1 @@ -(function(){var a;a=angular.module("ngModal",[]),a.provider("ngModalDefaults",function(){return{options:{closeButtonHtml:"X"},$get:function(){return this.options},set:function(a,b){var c,d,e;if("object"==typeof a){e=[];for(c in a)d=a[c],e.push(this.options[c]=d);return e}return this.options[a]=b}}}),a.directive("modalDialog",["ngModalDefaults","$sce",function(a,b){return{restrict:"E",scope:{show:"=",dialogTitle:"@",onClose:"&?"},replace:!0,transclude:!0,link:function(c,d,e){var f,g;return f=function(){return c.closeButtonHtml=b.trustAsHtml(a.closeButtonHtml)},g=function(){return c.dialogStyle={},e.width&&(c.dialogStyle.width=e.width),e.height?c.dialogStyle.height=e.height:void 0},c.hideModal=function(){return c.show=!1},c.$watch("show",function(a,b){return document.getElementsByTagName("body")[0].style.overflow=a&&!b?"hidden":"",!a&&b&&null!=c.onClose?c.onClose():void 0}),f(),g()},template:"
\n
\n
\n \n
\n
\n
\n
\n
\n
"}}])}).call(this); \ No newline at end of file +(function(){var a,b=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};a=angular.module("ngModal",[]),a.provider("ngModalDefaults",function(){return{options:{closeButtonHtml:"X",hideCloseButton:!1,closeOnEscape:!0,closeOnOutsideClick:!0},$get:function(){return this.options},set:function(a,b){var c,d,e;if("object"==typeof a){e=[];for(c in a)d=a[c],e.push(this.options[c]=d);return e}return this.options[a]=b}}}),a.directive("modalDialog",["ngModalDefaults","$sce","$timeout",function(a,c,d){return{restrict:"E",scope:{show:"=",dialogTitle:"@",onClose:"&?",hideCloseButton:"=",closeOnEscape:"=",closeOnOutsideClick:"="},replace:!0,transclude:!0,link:function(e,f,g){var h,i,j,k;return e.hCB=void 0===e.hideCloseButton?a.hideCloseButton:e.hideCloseButton,e.cOE=void 0===e.closeOnEscape?a.closeOnEscape:e.closeOnEscape,e.cOOC=void 0===e.closeOnOutsideClick?a.closeOnOutsideClick:e.closeOnOutsideClick,h=function(){return e.cOE?document.onkeydown=function(a){var c;return a=a||window.event,c=!1,c=b.call(a,"key")>=0?"Escape"===a.key||"Esc"===a.key:27===a.keyCode,c?e.hideModal():void 0}:void 0},k=function(){return document.onkeydown=function(){}},i=function(){return e.closeButtonHtml=c.trustAsHtml(a.closeButtonHtml)},j=function(){return e.dialogStyle={},g.width&&(e.dialogStyle.width=g.width),g.height?e.dialogStyle.height=g.height:void 0},e.hideModal=function(){var a;return e.show=!1,a=d(function(){return d.cancel(a)})},e.$watch("show",function(a,b){return a&&!b?(h(),document.getElementsByTagName("body")[0].style.overflow="hidden"):(k(),document.getElementsByTagName("body")[0].style.overflow=""),!a&&b&&null!=e.onClose?(k(),e.onClose()):void 0}),i(),j()},template:"
\n
\n
\n \n
\n
\n
\n
\n
\n
"}}])}).call(this); \ No newline at end of file diff --git a/src/ng-modal.coffee b/src/ng-modal.coffee index 65da273..f172e25 100644 --- a/src/ng-modal.coffee +++ b/src/ng-modal.coffee @@ -13,6 +13,9 @@ app = angular.module("ngModal", []) app.provider "ngModalDefaults", -> options: { closeButtonHtml: "X" + hideCloseButton: false + closeOnEscape: true + closeOnOutsideClick: true } $get: -> @options @@ -24,15 +27,39 @@ app.provider "ngModalDefaults", -> else @options[keyOrHash] = value -app.directive 'modalDialog', ['ngModalDefaults', '$sce', (ngModalDefaults, $sce) -> +app.directive 'modalDialog', ['ngModalDefaults', '$sce', '$timeout', (ngModalDefaults, $sce, $timeout) -> restrict: 'E' scope: show: '=' dialogTitle: '@' onClose: '&?' + hideCloseButton: '=' + closeOnEscape: '=' + closeOnOutsideClick: '=' replace: true transclude: true link: (scope, element, attrs) -> + scope.hCB = if scope.hideCloseButton == undefined then ngModalDefaults.hideCloseButton else scope.hideCloseButton + scope.cOE = if scope.closeOnEscape == undefined then ngModalDefaults.closeOnEscape else scope.closeOnEscape + scope.cOOC = if scope.closeOnOutsideClick == undefined then ngModalDefaults.closeOnOutsideClick else scope.closeOnOutsideClick + + bindEscKeyPress = -> + if scope.cOE + document.onkeydown = (evt) -> + evt = evt || window.event + isEscape = false + + if "key" in evt + isEscape = evt.key == "Escape" || evt.key == "Esc" + else + isEscape = evt.keyCode == 27 + + if isEscape + scope.hideModal() + + unbindEscKeyPress = -> + document.onkeydown = -> + setupCloseButton = -> scope.closeButtonHtml = $sce.trustAsHtml(ngModalDefaults.closeButtonHtml) @@ -43,13 +70,19 @@ app.directive 'modalDialog', ['ngModalDefaults', '$sce', (ngModalDefaults, $sce) scope.hideModal = -> scope.show = false + triggerDigest = $timeout(() -> + $timeout.cancel(triggerDigest); + ) scope.$watch('show', (newVal, oldVal) -> if newVal && !oldVal + bindEscKeyPress() document.getElementsByTagName("body")[0].style.overflow = "hidden"; else + unbindEscKeyPress() document.getElementsByTagName("body")[0].style.overflow = ""; if (!newVal && oldVal) && scope.onClose? + unbindEscKeyPress() scope.onClose() ) @@ -58,10 +91,10 @@ app.directive 'modalDialog', ['ngModalDefaults', '$sce', (ngModalDefaults, $sce) template: """
-
+
-
+
From 6b0984fb954752efe073a7bbd3e015420a7f07b5 Mon Sep 17 00:00:00 2001 From: Rihards Neimanis Date: Wed, 16 Oct 2019 13:20:33 +0300 Subject: [PATCH 2/5] README.md updated with NEW feature descriptions --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 49083f0..445e126 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The directive itself is called *modal-dialog*. The only required attribute is `s ## Inline Options -There are a few options that be configured inline with attributes. +There are a few options that can be configured inline with attributes. | Option | Default | Description | | -------------- | ------- | ----------------------------------------------------------------- | @@ -49,11 +49,14 @@ There are a few options that be configured inline with attributes. | width | 50% | Width of the dialog. Can be specified in px or %. | | height | 50% | Height of the dialog. Can be specified in px or %. | | on-close | null | Call a function when the dialog is closed. Ex: `on-close='foo()'` | +| hide-close-button | false | Hides the modal close (x) button. | +| close-on-escape | true | Close the modal on ESC key press. | +| close-on-outside-click | true | Close the modal when clicking outside (e.g. click on the overlay). | **Example:** ```html - +

Dialog content goes in here

``` @@ -73,11 +76,14 @@ app.config(function(ngModalDefaultsProvider) { | Option | Default | Description | | ------------------- | ------- | ---------------------------------------------------------------------------------------------------------------- | | closeButtonHtml | 'X' | By default, the close button is just an X character. But you can set it to any HTML. For example, if you're using font-awesome, you could set it to `` | +| hideCloseButton | false | By default, the close button is visible. But you can override this by setting this option to 'true' `` | +| closeOnEscape | true | By default, the ESC button press will close the modal. You can disable this feature by setting this option to 'false' `` | +| closeOnOutsideClick | true | By default, the click outside the modal window will result in modal close action. You can disable this feature by setting this option to 'false' `` | ## Browser Support -So far, it has only been tested in Chrome. There is some CSS that is not compatible with with older browsers, including IE9. +So far, it has only been tested in Chrome. There is some CSS that is not compatible with older browsers, including IE9. ## Contributing @@ -90,6 +96,7 @@ Contributions are welcome. Whenever possible, please include test coverage with 5. Create new Pull Request To get the project running, you'll need [NPM](https://npmjs.org/) and [Bower](http://bower.io/). Run `npm install` and `bower install` to install all dependencies. Then run `grunt` in the project directory to watch and compile changes. And you can run `karma start` to watch for changes and auto-execute unit tests. +If running `grunt` throws an error on Windows (`'grunt' is not recognized as an internal or external command, operable program or batch file.`) try running `npm install -g grunt-cli` - this should fix the issue. ## Potential Features Down the Road From d6feeac61a8164d0586816f4780bb6439c964963 Mon Sep 17 00:00:00 2001 From: Rihards Neimanis Date: Wed, 16 Oct 2019 13:23:57 +0300 Subject: [PATCH 3/5] Version update in the docs --- README.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 445e126..301aeec 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ngModal is very simple [Angular.js](http://angularjs.org/) modal dialog directiv ## Download -* [Version 1.2.2](https://github.com/adamalbrecht/ngModal/archive/1.2.2.zip) - Compatible with Angular 1.2.x. +* [Version 1.2.3](https://github.com/adamalbrecht/ngModal/archive/1.2.3.zip) - Compatible with Angular 1.2.x. You can also install the package using [Bower](http://bower.io). diff --git a/package.json b/package.json index 08e034e..f3e4052 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ngModal", - "version": "1.2.2", + "version": "1.2.3", "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-coffee": "~0.7", From a46f79a311febd9574549deca86a2e3b4e629f30 Mon Sep 17 00:00:00 2001 From: Rihards Neimanis Date: Wed, 16 Oct 2019 13:30:27 +0300 Subject: [PATCH 4/5] Added correct version number to bower --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 88cb927..ebf1855 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "ngModal", - "version": "1.2.2", + "version": "1.2.3", "main": ["dist/ng-modal.js", "dist/ng-modal.css"], "ignore": [ ".gitignore", From 7208e2ca2659a91c6398cdd1603fefeb5b111d6f Mon Sep 17 00:00:00 2001 From: Rihards Neimanis Date: Wed, 16 Oct 2019 13:44:18 +0300 Subject: [PATCH 5/5] Changed name of the project and added homepage to bwer --- bower.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bower.json b/bower.json index ebf1855..a0ab838 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,7 @@ { - "name": "ngModal", + "name": "ngModal-extended", "version": "1.2.3", + "homepage": "https://github.com/Ricco1/ngModal", "main": ["dist/ng-modal.js", "dist/ng-modal.css"], "ignore": [ ".gitignore",