├── .circleci
└── config.yml
├── .codacy.yml
├── .github
└── FUNDING.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── bower.json
├── dst
├── angular-modal-service.js
├── angular-modal-service.js.map
├── angular-modal-service.min.js
└── angular-modal-service.min.js.map
├── index.js
├── karma.conf.js
├── package-lock.json
├── package.json
├── samples
├── complex
│ ├── complex.html
│ └── complexcontroller.js
├── custom
│ ├── custom.css
│ ├── custom.html
│ └── customcontroller.js
├── index.html
├── sampleapp.js
├── vendor
│ ├── bootstrap
│ │ ├── css
│ │ │ ├── bootstrap-theme.css
│ │ │ ├── bootstrap-theme.css.map
│ │ │ ├── bootstrap-theme.min.css
│ │ │ ├── bootstrap-theme.min.css.map
│ │ │ ├── bootstrap.css
│ │ │ ├── bootstrap.css.map
│ │ │ ├── bootstrap.min.css
│ │ │ └── bootstrap.min.css.map
│ │ └── js
│ │ │ ├── bootstrap.js
│ │ │ └── bootstrap.min.js
│ └── jquery
│ │ ├── jquery.js
│ │ ├── jquery.min.js
│ │ └── jquery.min.map
└── yesno
│ ├── yesno.html
│ └── yesnocontroller.js
├── src
└── angular-modal-service.js
├── test
├── basics.spec.js
├── bodyClass.spec.js
├── close.spec.js
├── closeModals.spec.js
├── component.spec.js
├── configOptions.spec.js
├── controller.spec.js
├── dom.spec.js
├── index.js
├── parameters.spec.js
└── template.spec.js
└── webpack.config.js
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | build:
4 | working_directory: ~/project
5 | docker:
6 | - image: circleci/node:8-browsers
7 | environment:
8 | CHROME_BIN: "/usr/bin/google-chrome"
9 | steps:
10 | - checkout
11 | - run:
12 | name: update-npm
13 | command: 'sudo npm install -g npm@latest'
14 | - restore_cache:
15 | key: dependency-cache-{{ checksum "package.json" }}
16 | - run:
17 | name: install-npm
18 | command: npm install
19 | - save_cache:
20 | key: dependency-cache-{{ checksum "package.json" }}
21 | paths:
22 | - ./node_modules
23 | - run:
24 | name: test
25 | command: npm test
26 | - run:
27 | name: upload coverage
28 | command: bash <(curl -s https://codecov.io/bash)
29 | - store_artifacts:
30 | path: dst
31 | destination: dst
32 | - store_artifacts:
33 | path: test-results.xml
34 | destination: tests
35 | - store_artifacts:
36 | path: coverage
37 | destination: coverage
38 | - store_test_results:
39 | path: ./build/test-results.xml
40 | workflows:
41 | version: 2
42 | build:
43 | jobs:
44 | - build:
45 | # All branches, all tags.
46 | filters:
47 | tags:
48 | only: /.*/
49 |
--------------------------------------------------------------------------------
/.codacy.yml:
--------------------------------------------------------------------------------
1 | exclude_paths:
2 | - ./dst/.
3 | - '*.min.js'
4 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # Support 'GitHub Sponsors' funding.
2 | github: dwmkerr
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bower_components
2 | node_modules
3 | build
4 | .DS_Store
5 | .idea
6 |
7 | artifacts/
8 |
9 |
10 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ### [0.15.6](https://github.com/dwmkerr/angular-modal-service/compare/v0.15.5...v0.15.6) (2020-04-28)
6 |
7 | ### [0.15.5](https://github.com/dwmkerr/angular-modal-service/compare/v0.15.4...v0.15.5) (2020-04-28)
8 |
9 | ### [0.15.4](https://github.com/dwmkerr/angular-modal-service/compare/v0.15.3...v0.15.4) (2020-04-28)
10 |
11 | ## v0.15.0
12 |
13 | * Support for a globally configurable close timeout. Thanks [decherneyge](https://github.com/decherneyge).
14 | * Support for selector for `appendElement`. Thanks [decherneyge](https://github.com/decherneyge).
15 | * Tooling version updates.
16 |
17 | ## v0.7.12
18 |
19 | * Support for configuration of the `$locationChangeSuccess` event. Thanks [smalbs](https://github.com/smalbs).
20 |
21 | ## v0.6.12
22 |
23 | * When a model is opened, we blur any active element. Thanks [samx](https://github.com/samwx)!
24 |
25 | ## v0.6.11
26 |
27 | * Robustness for 'locationChangeEvent'.
28 | * Robustness if the body element changs.
29 | * Addded `bower` as a dev dependency. Run `bower install` as an `npm` `postinstall` step, which makes initial setup on a clean machine slightly easier.
30 |
31 | ## v0.6.10
32 |
33 | * Added support for using a custom parent scope for the controller scope, via the `scope` option.
34 | * Fixed a bug with controllerAs vs `controller as`.
35 |
36 | ## v0.6.6
37 |
38 | * Removed calls to $q `catch` and replaced with `then(null, f)` so that the code works in
39 | IE8 (ECMAScript 3).
40 |
41 | ## v0.6.5
42 |
43 | * Reverted changes below as they led to a bug with injected `$element` in modal controller.
44 | Added a test to protect against this case in the future.
45 |
46 | ## v0.6.4
47 |
48 | * Merged `scope` option field. Updated readme.
49 |
50 | ## v0.6.3
51 |
52 | * Fixed memory leak.
53 |
54 | ## v0.6.2
55 |
56 | * Tidied up logic for cleanup.
57 | * Fixed issue with vendor files.
58 |
59 | ## v0.6.1
60 |
61 | * Moved from grunt to gulp.
62 |
63 | ## v0.6
64 |
65 | ## v0.5
66 |
67 | * Updated the dependencies to use AngularJS 1.3 and upwards.
68 |
69 | ## v0.4
70 |
71 | ### Features
72 |
73 | * The modal can now be added to any specific element in the DOM. If
74 | unspecified, the modal is added to the `body`, as before.
75 | Thanks [cointilt](https://github.com/cointilt)!
76 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Dave Kerr
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular-modal-service
2 |
3 | [](https://circleci.com/gh/dwmkerr/angular-modal-service)
4 | [](https://codecov.io/gh/dwmkerr/angular-modal-service)
5 | [](https://david-dm.org/dwmkerr/angular-modal-service)
6 | [](https://david-dm.org/dwmkerr/angular-modal-service#info=devDependencies)
7 | [](https://greenkeeper.io/) [](https://www.guardrails.io)
8 |
9 | Modal service for AngularJS - supports creating popups and modals via a service. Full support for Angular 1.5+ components. See [a quick fiddle](http://jsfiddle.net/dwmkerr/8MVLJ/) or a full set of samples at [dwmkerr.github.io/angular-modal-service](http://dwmkerr.github.io/angular-modal-service).
10 |
11 |
12 |
13 | * [Usage](#usage)
14 | * [Support for AngularJS 1.5.x Components](#support-for-angularjs-15x-components)
15 | * [ShowModal Options](#showmodal-options)
16 | * [The Modal Object](#the-modal-object)
17 | * [The Modal Controller](#the-modal-controller)
18 | * [Closing All Modals](#closing-all-modals)
19 | * [Animation](#animation)
20 | * [Error Handing](#error-handing)
21 | * [Global Options Configuration](#global-options-configuration)
22 | * [Developing](#developing)
23 | * [Tests](#tests)
24 | * [Releasing](#releasing)
25 | * [FAQ](#faq)
26 | * [Thanks](#thanks)
27 |
28 |
29 |
30 | ## Usage
31 |
32 | Install with Bower (or NPM):
33 |
34 | ```bash
35 | bower install angular-modal-service
36 | # or...
37 | npm install angular-modal-service
38 | ```
39 |
40 | Then reference the minified script:
41 |
42 | ```html
43 |
44 | ```
45 |
46 | Specify the modal service as a dependency of your application:
47 |
48 | ```js
49 | var app = angular.module('sampleapp', ['angularModalService']);
50 | ```
51 |
52 | Now just inject the modal service into any controller, service or directive where you need it.
53 |
54 | ```js
55 | app.controller('SampleController', ["$scope", "ModalService", function($scope, ModalService) {
56 |
57 | $scope.showAModal = function() {
58 |
59 | // Just provide a template url, a controller and call 'showModal'.
60 | ModalService.showModal({
61 | templateUrl: "yesno/yesno.html",
62 | controller: "YesNoController"
63 | }).then(function(modal) {
64 | // The modal object has the element built, if this is a bootstrap modal
65 | // you can call 'modal' to show it, if it's a custom modal just show or hide
66 | // it as you need to.
67 | modal.element.modal();
68 | modal.close.then(function(result) {
69 | $scope.message = result ? "You said Yes" : "You said No";
70 | });
71 | });
72 |
73 | };
74 |
75 | }]);
76 | ```
77 |
78 | Calling `showModal` returns a promise which is resolved when the modal DOM element is created
79 | and the controller for it is created. The promise returns a `modal` object which contains the
80 | element created, the controller, the scope and two promises: `close` and `closed`. Both are
81 | resolved to the result of the modal close function, but `close` is resolved as soon as the
82 | modal close function is called, while `closed` is only resolved once the modal has finished
83 | animating and has been completely removed from the DOM.
84 |
85 | The modal controller can be any controller that you like, just remember that it is always
86 | provided with one extra parameter - the `close` function. Here's an example controller
87 | for a bootstrap modal:
88 |
89 | ```js
90 | app.controller('SampleModalController', function($scope, close) {
91 |
92 | $scope.dismissModal = function(result) {
93 | close(result, 200); // close, but give 200ms for bootstrap to animate
94 | };
95 |
96 | });
97 | ```
98 |
99 | The `close` function is automatically injected to the modal controller and takes the result
100 | object (which is passed to the `close` and `closed` promises used by the caller). It can
101 | take an optional second parameter, the number of milliseconds to wait before destroying the
102 | DOM element. This is so that you can have a delay before destroying the DOM element if you
103 | are animating the closure. See [Global Config](#global-options-configuration) for setting a default delay.
104 |
105 | Now just make sure the `close` function is called by your modal controller when the modal
106 | should be closed and that's it. Quick hint - if you are using Bootstrap for your modals,
107 | then make sure the modal template only contains one root level element, see the [FAQ](#faq)
108 | for the gritty details of why.
109 |
110 | To pass data into the modal controller, use the `inputs` field of the modal options. For example:
111 |
112 | ```js
113 | ModalService.showModal({
114 | templateUrl: "exampletemplate.html",
115 | controller: "ExampleController",
116 | inputs: {
117 | name: "Fry",
118 | year: 3001
119 | }
120 | })
121 | ```
122 |
123 | injects the `name` and `year` values into the controller:
124 |
125 | ```js
126 | app.controller('ExampleController', function($scope, name, year, close) {
127 | });
128 | ```
129 |
130 | You can also provide a controller function directly to the modal, with or without the `controllerAs` attribute.
131 | But if you provide `controller` attribute with `as` syntax and `controllerAs` attribute together, `controllerAs`
132 | will have high priority.
133 |
134 | ```js
135 | ModalService.showModal({
136 | template: "
383 | ```
384 |
385 | To do this programatically, use:
386 |
387 | ```js
388 | ModalService.showModal({
389 | templateUrl: "whatever.html",
390 | controller: "WhateverController"
391 | }).then(function(modal) {
392 | modal.element.modal({
393 | backdrop: 'static',
394 | keyboard: false
395 | });
396 | modal.close.then(function(result) {
397 | // ...etc
398 | });
399 | });
400 | ```
401 |
402 | Thanks [lindamarieb](https://github.com/lindamarieb) and [ledgeJumper](https://github.com/ledgeJumper)!
403 |
404 | **Problems with Nested Modals**
405 |
406 | If you are trying to nest Bootstrap modals, you will run into issues. From Bootstrap:
407 |
408 | > Bootstrap only supports one modal window at a time. Nested modals aren’t supported as we believe them to be poor user experiences.
409 |
410 | See: https://v4-alpha.getbootstrap.com/components/modal/#how-it-works
411 |
412 | Some people have been able to get them working (see https://github.com/dwmkerr/angular-modal-service/issues/176). Unfortunately, due to the lack of support in Bootstrap is has proven troublesome to support this in angular-modal-service.
413 |
414 | ## Thanks
415 |
416 | Thanks go the the following contributors:
417 |
418 | * [DougKeller](https://github.com/DougKeller) - Adding support for Angular 1.5 components.
419 | * [joshvillbrandt](https://github.com/joshvillbrandt) - Adding support for `$templateCache`.
420 | * [cointilt](https://github.com/cointilt) - Allowing the modal to be added to a custom element, not just the body.
421 | * [kernowjoe](https://github.com/kernowjoe) - controllerAs
422 | * [poporul](https://github.com/poporul) - Improving the core logic around compilation and inputs.
423 | * [jonasnas](https://github.com/jonasnas) - Fixing template cache logic.
424 | * [maxdow](https://github.com/maxdow) - Added support for controller inlining.
425 | * [kernowjoe](https://github.com/kernowjoe) - Robustness around locationChange
426 | * [arthur-xavier](https://github.com/arthur-xavier) - Robustness when `body` element changes.
427 | * [stormpooper](https://github.com/StormPooper) - The new `bodyClass` feature.
428 | * [decherneyge](https://github.com/decherneyge) - Provider features, global configuration, `appendElement` improvements.
429 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-modal-service",
3 | "version": "0.15.6",
4 | "homepage": "https://github.com/dwmkerr/angular-modal-service",
5 | "authors": [
6 | "Dave Kerr (github.com/dwmkerr)"
7 | ],
8 | "description": "AngularJS Service for showing Modals and Popups",
9 | "main": "dst/angular-modal-service.js",
10 | "keywords": [
11 | "angular",
12 | "angularjs",
13 | "modal",
14 | "popup",
15 | "service"
16 | ],
17 | "license": "MIT",
18 | "ignore": [
19 | "**/.*",
20 | "node_modules",
21 | "bower_components",
22 | "test",
23 | "samples",
24 | "src",
25 | ".gitignore",
26 | "*.json",
27 | "gulpfile.js",
28 | "CHANGELOG.md",
29 | "*.yml"
30 | ],
31 | "dependencies": {
32 | "angular": "1.5.0 - 1.7.x"
33 | },
34 | "devDependencies": {
35 | "angular-mocks": "1.5.0 - 1.7.x"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/dst/angular-modal-service.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/angular-modal-service.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","angular","factory","$animate","$document","$compile","$controller","$http","$rootScope","$q","$templateRequest","$timeout","self","this","openModals","appendChild","parent","child","children","length","enter","closeModals","result","delay","close","splice","showModal","options","body","element","deferred","defer","controller","template","templateUrl","resolve","then","error","reject","promise","getTemplate","modal","modalScope","scope","$new","rootScopeOnClose","locationChangeSuccess","noop","isNumber","$on","cleanUpClose","closeDeferred","closedDeferred","hasAlreadyBeenClosed","inputs","$scope","preClose","undefined","extend","modalElement","linkFn","$element","controllerObjBefore","controllerAs","modalController","bodyClass","classList","remove","leave","$destroy","appendElement","add","closed","document","activeElement","blur","push"],"mappings":"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","file":"angular-modal-service.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","'use strict';\n\nvar module = angular.module('angularModalService', []);\n\nmodule.factory('ModalService', ['$animate', '$document', '$compile', '$controller', '$http', '$rootScope', '$q', '$templateRequest', '$timeout',\n function($animate, $document, $compile, $controller, $http, $rootScope, $q, $templateRequest, $timeout) {\n\n function ModalService() {\n\n var self = this;\n\n // Track open modals.\n self.openModals = [];\n\n // Returns a promise which gets the template, either\n // from the template parameter or via a request to the\n // template url parameter.\n var getTemplate = function(template, templateUrl) {\n var deferred = $q.defer();\n if (template) {\n deferred.resolve(template);\n } else if (templateUrl) {\n $templateRequest(templateUrl, true)\n .then(function(template) {\n deferred.resolve(template);\n }, function(error) {\n deferred.reject(error);\n });\n } else {\n deferred.reject(\"No template or templateUrl has been specified.\");\n }\n return deferred.promise;\n };\n\n // Adds an element to the DOM as the last child of its container\n // like append, but uses $animate to handle animations. Returns a\n // promise that is resolved once all animation is complete.\n var appendChild = function(parent, child) {\n var children = parent.children();\n if (children.length > 0) {\n return $animate.enter(child, parent, children[children.length - 1]);\n }\n return $animate.enter(child, parent);\n };\n\n // Close all modals, providing the given result to the close promise.\n self.closeModals = function(result, delay) {\n while (self.openModals.length) {\n self.openModals[0].close(result, delay);\n self.openModals.splice(0, 1);\n }\n };\n\n self.showModal = function(options) {\n\n // Get the body of the document, we'll add the modal to this.\n var body = angular.element($document[0].body);\n\n // Create a deferred we'll resolve when the modal is ready.\n var deferred = $q.defer();\n\n // Validate the input parameters.\n var controllerName = options.controller;\n if (!controllerName) {\n deferred.reject(\"No controller has been specified.\");\n return deferred.promise;\n }\n\n // Get the actual html of the template.\n getTemplate(options.template, options.templateUrl)\n .then(function(template) {\n\n // The main modal object we will build.\n var modal = {};\n\n // Create a new scope for the modal.\n var modalScope = (options.scope || $rootScope).$new(),\n rootScopeOnClose = null,\n locationChangeSuccess = options.locationChangeSuccess;\n\n // Allow locationChangeSuccess event registration to be configurable.\n // True (default) = event registered immediately\n // # (greater than 0) = event registered with delay\n // False = disabled\n if (locationChangeSuccess === false){\n rootScopeOnClose = angular.noop;\n }\n else if (angular.isNumber(locationChangeSuccess) && locationChangeSuccess >= 0) {\n $timeout(function() {\n rootScopeOnClose = $rootScope.$on('$locationChangeSuccess', cleanUpClose);\n }, locationChangeSuccess);\n }\n else {\n rootScopeOnClose = $rootScope.$on('$locationChangeSuccess', cleanUpClose);\n }\n\n\n\n\n // Create the inputs object to the controller - this will include\n // the scope, as well as all inputs provided.\n // We will also create a deferred that is resolved with a provided\n // close function. The controller can then call 'close(result)'.\n // The controller can also provide a delay for closing - this is\n // helpful if there are closing animations which must finish first.\n var closeDeferred = $q.defer();\n var closedDeferred = $q.defer();\n var hasAlreadyBeenClosed = false;\n\n var inputs = {\n $scope: modalScope,\n close: function(result, delay) {\n // If we have a pre-close function, call it.\n if (typeof options.preClose === 'function') options.preClose(modal, result, delay);\n\n if (delay === undefined || delay === null) delay = 0;\n if (hasAlreadyBeenClosed) {\n return;\n }\n hasAlreadyBeenClosed = true;\n\n $timeout(function() {\n\n cleanUpClose(result);\n\n }, delay);\n }\n };\n\n // If we have provided any inputs, pass them to the controller.\n if (options.inputs) angular.extend(inputs, options.inputs);\n\n // Compile then link the template element, building the actual element.\n // Set the $element on the inputs so that it can be injected if required.\n var linkFn = $compile(template);\n var modalElement = linkFn(modalScope);\n inputs.$element = modalElement;\n\n // Create the controller, explicitly specifying the scope to use.\n var controllerObjBefore = modalScope[options.controllerAs];\n var modalController = $controller(options.controller, inputs, false, options.controllerAs);\n\n if (options.controllerAs && controllerObjBefore) {\n angular.extend(modalController, controllerObjBefore);\n }\n\n // Then, append the modal to the dom.\n if (options.appendElement) {\n // append to custom append element\n appendChild(options.appendElement, modalElement);\n } else {\n // append to body when no custom append element is specified\n appendChild(body, modalElement);\n }\n\n // Finally, append any custom classes to the body\n if(options.bodyClass) {\n body[0].classList.add(options.bodyClass);\n }\n\n // Populate the modal object...\n modal.controller = modalController;\n modal.scope = modalScope;\n modal.element = modalElement;\n modal.close = closeDeferred.promise;\n modal.closed = closedDeferred.promise;\n\n // ...which is passed to the caller via the promise.\n deferred.resolve(modal);\n\n // Clear previous input focus to avoid open multiple modals on enter\n document.activeElement.blur();\n\n // We can track this modal in our open modals.\n self.openModals.push({ modal: modal, close: inputs.close });\n\n function cleanUpClose(result) {\n\n // Resolve the 'close' promise.\n closeDeferred.resolve(result);\n\n // Remove the custom class from the body\n if(options.bodyClass) {\n body[0].classList.remove(options.bodyClass);\n }\n\n // Let angular remove the element and wait for animations to finish.\n $animate.leave(modalElement)\n .then(function () {\n // prevent error if modal is already destroyed\n if (!modalElement) {\n return;\n }\n\n // Resolve the 'closed' promise.\n closedDeferred.resolve(result);\n\n // We can now clean up the scope\n modalScope.$destroy();\n\n // Remove the modal from the set of open modals.\n for (var i=0; i
"+t+">"));var s,a,i,b=angular.element(M[0].body),y=C.defer();return v.controller?(s=v.template,a=v.templateUrl,i=C.defer(),s?i.resolve(s):a?u(a,!0).then(function(e){i.resolve(e)},function(e){i.reject(e)}):i.reject("No template or templateUrl has been specified."),i.promise).then(function(e){var o={},t=(v.scope||S).$new(),l=null,n=v.locationChangeSuccess;!1===n?l=angular.noop:angular.isNumber(n)&&0<=n?x(function(){l=S.$on("$locationChangeSuccess",a.close)},n):x(function(){l=S.$on("$locationChangeSuccess",a.close)},h.configOptions.closeDelay);var r=C.defer(),c=C.defer(),s=!1,a={$scope:t,close:function(e,n){s||(s=!0,n=n||h.configOptions.closeDelay,"function"==typeof v.preClose&&v.preClose(o,e,n),null==n&&(n=0),x(function(){var n;n=e,r.resolve(n),v.bodyClass&&b[0].classList.remove(v.bodyClass),$.leave(i).then(function(){if(i){c.resolve(n),t.$destroy();for(var e=0;e
2 |
3 |
4 |
8 |
9 |
Here's a more complex modal, it contains a form, data is passed to the controller
10 | and data is returned from the modal.
11 |
12 |
26 |
27 |
28 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/samples/complex/complexcontroller.js:
--------------------------------------------------------------------------------
1 | var app = angular.module('sampleapp');
2 |
3 | app.controller('ComplexController', [
4 | '$scope', '$element', 'title', 'close',
5 | function ($scope, $element, title, close) {
6 |
7 | $scope.name = null;
8 | $scope.age = null;
9 | $scope.title = title;
10 |
11 | $scope.wasClosed = false;
12 |
13 | // This close function doesn't need to use jQuery or bootstrap, because
14 | // the button has the 'data-dismiss' attribute.
15 | $scope.close = function () {
16 |
17 | //mark the modal as handled
18 | $scope.wasClosed = true;
19 |
20 | close({
21 | name: $scope.name,
22 | age: $scope.age,
23 | source: 'Ok\'ed'
24 | }, 500); // close, but give 500ms for bootstrap to animate
25 | };
26 |
27 | // This cancel function must use the bootstrap, 'modal' function because
28 | // the doesn't have the 'data-dismiss' attribute.
29 | $scope.cancel = function () {
30 |
31 | //mark the modal as handled
32 | $scope.wasClosed = true;
33 |
34 | // Manually hide the modal.
35 | $element.modal('hide');
36 |
37 | // Now call close, returning control to the caller.
38 | close({
39 | name: $scope.name,
40 | age: $scope.age,
41 | source: 'Cancelled'
42 | }, 500); // close, but give 500ms for bootstrap to animate
43 | };
44 |
45 | // The abort function doesn't need to use jQuery or bootstrap, because
46 | // the backdrop click already dismisses the modal and the X has the 'data-dismiss' attribute.
47 | $scope.abort = function () {
48 | //mark the modal as handled
49 | $scope.wasClosed = true;
50 |
51 | close({
52 | name: $scope.name,
53 | age: $scope.age,
54 | source: 'Aborted'
55 | }, 500); // close, but give 500ms for bootstrap to animate
56 | };
57 |
58 | var backgroundClickHandler = function (e) {
59 |
60 | //if the modal was already closed short circuit
61 | if ($scope.wasClosed) return;
62 |
63 | //call the close functionality
64 | $scope.abort();
65 |
66 | //remove the listener
67 | $element.off('hidden.bs.modal', backgroundClickHandler);
68 | };
69 |
70 | //listen for when the modal is dismissed and close it
71 | $element.on('hidden.bs.modal', backgroundClickHandler);
72 |
73 | }]);
--------------------------------------------------------------------------------
/samples/custom/custom.css:
--------------------------------------------------------------------------------
1 |
2 | #overlay {
3 | position: fixed;
4 | left: 25%;
5 | top: 25%;
6 | padding: 25px;
7 | border: 2px solid black;
8 | background-color: #ffffff;
9 | width: 50%;
10 | height: 50%;
11 | z-index: 100;
12 | }
13 | #fade {
14 | position: fixed;
15 | left: 0%;
16 | top: 0%;
17 | background-color: black;
18 | -moz-opacity: 0.7;
19 | opacity: .70;
20 | filter: alpha(opacity=70);
21 | width: 100%;
22 | height: 100%;
23 | z-index: 90;
24 | }
25 |
26 | body.custom-modal-open #fade {
27 | background-color: darkred;
28 | -moz-opacity: 0.9;
29 | opacity: .90;
30 | filter: alpha(opacity=90);
31 | }
32 |
33 | #custom-modal.ng-enter {
34 | transition: opacity .5s ease-out;
35 | opacity: 0;
36 | }
37 | #custom-modal.ng-enter.ng-enter-active {
38 | opacity: 1;
39 | }
40 | #custom-modal.ng-leave {
41 | transition: opacity .5s ease-out;
42 | opacity: 1;
43 | }
44 | #custom-modal.ng-leave.ng-leave-active {
45 | opacity: 0;
46 | }
47 |
--------------------------------------------------------------------------------
/samples/custom/custom.html:
--------------------------------------------------------------------------------
1 |