├── .gitignore
├── CHANGELOG.md
├── README.md
├── bower.json
├── dist
├── css
│ ├── ocModal.animations.css
│ ├── ocModal.animations.min.css
│ ├── ocModal.full.css
│ ├── ocModal.full.min.css
│ ├── ocModal.light.css
│ └── ocModal.light.min.css
├── ocModal.js
├── ocModal.min.js
└── scss
│ ├── _animations.scss
│ ├── _modal.scss
│ ├── _no-bootstrap.scss
│ ├── _variables.scss
│ ├── ocModal.animations.scss
│ ├── ocModal.full.scss
│ └── ocModal.light.scss
├── example
├── app.js
├── bootstrap.min.css
├── index.html
├── ocModal.animations.css
├── ocModal.js
└── ocModal.light.css
├── gulpfile.js
├── package.json
└── src
├── changelog.js
├── ocModal.js
├── scss
├── _animations.scss
├── _modal.scss
├── _no-bootstrap.scss
├── _variables.scss
├── ocModal.animations.scss
├── ocModal.full.scss
└── ocModal.light.scss
└── validate-commit-msg.js
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #############
33 | ## Windows detritus
34 | #############
35 |
36 | # Windows image file caches
37 | Thumbs.db
38 | ehthumbs.db
39 |
40 | # Folder config file
41 | Desktop.ini
42 |
43 | # Recycle Bin used on file shares
44 | $RECYCLE.BIN/
45 |
46 | # Mac crap
47 | .DS_Store
48 |
49 |
50 | #############
51 | ## Intellij
52 | #############
53 |
54 | nbproject
55 | manifest.mf
56 | build.xml
57 |
58 | .project
59 | .settings
60 | .idea/*
61 | *.iml
62 |
63 |
64 | #############
65 | ## Project
66 | #############
67 | public
68 | node_modules/*
69 | npm-debug.log
70 | bower_components
71 |
72 | test/test-results.xml
73 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # 0.1.12 (2015-12-23)
3 |
4 |
5 | ## Bug Fixes
6 |
7 | - make it work for npm
8 | ([70d39ecf](https://github.com/ocombe/ocModal/commit/70d39ecfb4b825a1d139aa84ebed352456606a76))
9 | - vertical center with flexbox in IE10+
10 | ([b0aa3f95](https://github.com/ocombe/ocModal/commit/b0aa3f9529ae9952498907cb15a1cb265e72083e))
11 |
12 |
13 |
14 | # 0.1.11 (2015-11-05)
15 |
16 |
17 | ## Bug Fixes
18 |
19 | - don't prevent click events propagation
20 | ([727c6d25](https://github.com/ocombe/ocModal/commit/727c6d25811f4c2e8607b3909259abc2af585e8d))
21 |
22 |
23 |
24 | # 0.1.10 (2015-01-08)
25 |
26 |
27 | ## Bug Fixes
28 |
29 | - support for the latest versions of bootstrap
30 | ([8e56e21e](https://github.com/ocombe/ocModal/commit/8e56e21e29a9b2dcb58109eff3eb30fc23691866))
31 |
32 |
33 |
34 | # 0.1.9 (2014-10-09)
35 |
36 |
37 | ## Bug Fixes
38 |
39 | - revert "height 100% for vertical align center on ie10+"
40 | ([b8d1dcc4](https://github.com/ocombe/ocModal/commit/b8d1dcc4a22c7516740080b49838c6317806e71e))
41 |
42 |
43 |
44 | # 0.1.8 (2014-10-06)
45 |
46 |
47 | ## Bug Fixes
48 |
49 | - height 100% for vertical align center on ie10+
50 | ([a39b9b40](https://github.com/ocombe/ocModal/commit/a39b9b40cf61e4a852e1987a731953044563cd99))
51 | - padding for bootstrap modals
52 | ([4fcb0653](https://github.com/ocombe/ocModal/commit/4fcb0653dba0a4113d719bc4c9daef4d13758409))
53 |
54 |
55 |
56 | # 0.1.7 (2014-09-18)
57 |
58 |
59 | ## Bug Fixes
60 |
61 | - compatibility with angular 1.3.0
62 | ([ff5c4500](https://github.com/ocombe/ocModal/commit/ff5c45009ad0b5b67b3daf826c128831c54f39fe))
63 |
64 |
65 |
66 | # 0.1.6 (2014-06-23)
67 |
68 |
69 | ## Bug Fixes
70 |
71 | - bug fixed with backdrop overlay on IE
72 | ([e791f698](https://github.com/ocombe/ocModal/commit/e791f698781ed6b58d7a2053a8254dceaccd4714))
73 | - max-height on flexbox browsers
74 | ([15a531d26f](https://github.com/ocombe/ocModal/commit/15a531d26ffcac51b5367e3a8e920b03791b9ec7))
75 |
76 |
77 |
78 | # 0.1.5 (2014-06-17)
79 |
80 |
81 | ## Bug Fixes
82 |
83 | - the slit animation now ends with a nice fade
84 | ([5d27b162](https://github.com/ocombe/ocModal/commit/5d27b1623cc770d6dc6b18ba0f7e66c41d646989))
85 | - no more blurry modal on chrome
86 | ([153d4db3](https://github.com/ocombe/ocModal/commit/153d4db3a35c03ed2237a6d832f251903b6954a5))
87 |
88 |
89 |
90 | # 0.1.4 (2014-06-12)
91 |
92 |
93 | ## Bug Fixes
94 |
95 | - destroy the scope of the modal before removing it
96 | ([12d34a76](https://github.com/ocombe/ocModal/commit/12d34a76134531a6ec5bbf4b8e04392edb6cf84b))
97 |
98 |
99 |
100 | # 0.1.3 (2014-06-11)
101 |
102 |
103 | ## Bug Fixes
104 |
105 | - anim name for fade is fade-in not fade
106 | ([2dc9b931](https://github.com/ocombe/ocModal/commit/2dc9b93119356bad0f19b037e7ec9233fd505c5a))
107 | - let the modal be responsive on small resolutions
108 | ([02cff9f5](https://github.com/ocombe/ocModal/commit/02cff9f54d94aecb165f8a469847bd7e759dc57a))
109 |
110 |
111 | ## Features
112 |
113 | - added scss files to dist for bower distribution
114 | ([35b8181d](https://github.com/ocombe/ocModal/commit/35b8181d042e1562de9d6ca2568451c4191d83e0))
115 |
116 |
117 |
118 | # 0.1.2 (2014-06-05)
119 |
120 |
121 | ## Bug Fixes
122 |
123 | - the close function now returns a promise and resolves after animations
124 | ([3dde4592](https://github.com/ocombe/ocModal/commit/3dde4592bace1b836b2aa4dde8e3ee9a201e31f0))
125 |
126 |
127 |
128 | # 0.1.1 (2014-06-05)
129 |
130 |
131 | ## Bug Fixes
132 |
133 | - style updates to center modal
134 | ([bc3446cd](https://github.com/ocombe/ocModal/commit/bc3446cdac3e9f1bf32705814a189b6755b42da2))
135 |
136 |
137 |
138 | # 0.1.0 (2014-06-04)
139 |
140 |
141 | ## Features
142 |
143 | - added animations
144 | ([f99f4ba6](https://github.com/ocombe/ocModal/commit/f99f4ba66f808e3760ea67120792a5af6eace63d),
145 | [#4](https://github.com/ocombe/ocModal/issues/4))
146 | - adding gulp tasks to build & release
147 | ([d153f425](https://github.com/ocombe/ocModal/commit/d153f425f0e375d9cd8a39ffbf93047c326eb2b0))
148 | - adding an auto changelog generated by a gulp task
149 | ([5978652b](https://github.com/ocombe/ocModal/commit/5978652b883f14255ac63a0c1bda0af32a747bca))
150 |
151 |
152 | ## Breaking Changes
153 |
154 | - due to [d153f425](https://github.com/ocombe/ocModal/commit/d153f425f0e375d9cd8a39ffbf93047c326eb2b0),
155 | the src files have been moved to the src folder and the dist files to the dist folder. Update your paths accordingly.
156 |
157 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ocModal
2 | =======
3 |
4 | An angularJS modal directive & service
5 |
6 | ### Key features
7 | - Easy to use modal
8 | - Dependencies free (well except angular off course)
9 | - Load via the service or the directive
10 | - Style yourself or use the bootstrap's theme
11 |
12 | ### [Demo on Plunker](http://embed.plnkr.co/8QBKgw779g6jT6lmhXS5/)
13 |
14 | ### Usage
15 | - Download the lib (you can use `bower install ocModal`)
16 | - Put ocModal.js into you project
17 | - Add the css file to your project: if you don't have bootstrap 3, include dist/css/ocModal.full.min.css. If you already have bootstrap 3, use dist/css/ocModal.light.min.css
18 | - Add the module ```oc.modal``` to your application
19 | - Load on demand using the service or the directive :
20 |
21 | **Service**:
22 | ```javascript
23 | $ocModal.open('partials/modal.html');
24 | ```
25 | or
26 | ```javascript
27 | $ocModal.open('
My content
');
28 | ```
29 |
30 | **Directive**:
31 | ```html
32 |
33 | ```
34 | or
35 | ```html
36 |
37 | ```
38 |
39 | See the example in the 'example' folder to know how to integrate ocLazyLoad with your router.
40 |
41 | ### Parameters
42 | You can also pass parameters when you open a modal via the service or the directive. The previous examples are equivalent to :
43 |
44 | **Service**:
45 | ```javascript
46 | $ocModal.open({
47 | url: 'partials/modal.html'
48 | });
49 | ```
50 | or
51 | ```javascript
52 | $ocModal.open({
53 | template: 'My content
'
54 | });
55 | ```
56 |
57 | **Directive**:
58 | ```html
59 |
60 | ```
61 | or
62 | ```html
63 |
64 | ```
65 |
66 | The complete list of parameters is :
67 | - **id**: you can specify an id for your modal, it is usefull if you want to open more than one modal at the same time
68 | ```javascript
69 | $ocModal.open({
70 | id: 'modal1',
71 | url: 'partials/modal.html'
72 | });
73 | ```
74 | By default the id is set to ```'_default'```.
75 |
76 | - **url**: a template url loaded via [ng-include](http://docs.angularjs.org/api/ng.directive:ngInclude), so you can use an ng-script template or the url of an external html file
77 |
78 | - **template**: if you prefer to write the template in line, you can use the ```template``` parameter instead of ```url```.
79 |
80 | - **controller**: you can pass a controller for the new content
81 | ```javascript
82 | $ocModal.open({
83 | url: 'partials/modal.html',
84 | controller: 'MyController'
85 | });
86 | ```
87 |
88 | - **cls**: You can specify one or more (space separated) classes to be added to the modal
89 | ```javascript
90 | $ocModal.open({
91 | url: 'partials/modal.html',
92 | cls: 'my-class1 my-class2'
93 | });
94 | ```
95 |
96 | - **onOpen**: you can add a callback that will be called when the modal is opened
97 | ```javascript
98 | $ocModal.open({
99 | url: 'partials/modal.html',
100 | onOpen: function() {
101 | console.log('Just opened !');
102 | }
103 | });
104 | ```
105 |
106 | - **onClose**: you can add a callback that will be called when the modal is closed
107 | ```javascript
108 | $ocModal.open({
109 | url: 'partials/modal.html',
110 | onClose: function() {
111 | console.log('Just closed !');
112 | }
113 | });
114 | ```
115 |
116 | - **init**: use this to populate the modal scope. If you use a controller you will also be able to access this via $init
117 | ```javascript
118 | $ocModal.open({
119 | template: '{{param1}}
',
120 | controller: 'MyController',
121 | init: {
122 | param1: 'test'
123 | }
124 | });
125 | ```
126 |
127 | And in your controller :
128 | ```javascript
129 | angular.module('app').controller('MyController', ['$scope', '$init', function($scope, $init) {
130 | console.log($scope.param1, $init.param1);
131 | }]);
132 | ```
133 |
134 | - **$ocModalParams**: Access the modal params in your controller
135 | ```javascript
136 | angular.module('app').controller('MyController', ['$scope', '$ocModalParams', function($scope, $ocModalParams) {
137 | console.log($ocModalParams);
138 | }]);
139 | ```
140 |
141 | - **isolate**: by default your modal's scope will inherit the variables from the init parameter. If you don't want that and you prefer to access these variables via the $init in your controller, you can use ```isolate=true```
142 | ```javascript
143 | $ocModal.open({
144 | url: 'partials/modal.html',
145 | controller: 'MyController',
146 | isolate: true,
147 | init: {
148 | param1: 'test'
149 | }
150 | });
151 | ```
152 |
153 | And use $init in your controller :
154 | ```javascript
155 | angular.module('app').controller('MyController', ['$scope', '$init', function($scope, $init) {
156 | console.log($init.param1);
157 | }]);
158 | ```
159 |
160 | But ```$scope.param1``` will be ```undefined```.
161 |
162 | - **closeOnEsc**: by default you will be able to close the modal with the "ESC" key. If you want to disable this behaviour, use ```closeOnEsc: false```
163 | ```javascript
164 | $ocModal.open({
165 | url: 'partials/modal.html',
166 | closeOnEsc: false
167 | });
168 | ```
169 |
170 | ### Functions & attributes
171 | - **open(**__url/template/object__**)**: use this to open the modal
172 | ```javascript
173 | $ocModal.open({
174 | url: 'partials/modal.html'
175 | });
176 | ```
177 |
178 | - **close(**__[id][, param1][, param2][, ...]__**)**: use this to close the modal, it will return a promise that resolves at the end of the closing animation (if any)
179 | ```javascript
180 | $ocModal.close();
181 | ```
182 |
183 | With no parameter it will close the last opened modal. If you want to close a specific modal, use the id.
184 | ```javascript
185 | $ocModal.close('modal1');
186 | ```
187 |
188 | You can also pass what you want to the onClose callback (if you have one) :
189 | ```javascript
190 | $ocModal.open({
191 | url: 'partials/modal.html',
192 | onClose: function(a, b, c) {
193 | console.log(a); // arg1
194 | b(); // whatever
195 | console.log(c); // {p1: 'test'}
196 | }
197 | });
198 |
199 | $ocModal.close('arg1', function() { console.log('whatever') }, {p1: 'test'});
200 | ```
201 |
202 | - **$scope.closeModal(**__[id][, param1][, param2][, ...]__**)**: this is an alias for ```$ocModal.close()``` that you can also use in your template
203 | ```html
204 |
205 | ```
206 |
207 | - **getOpenedModals()**: if you need to get the ids of the opened modals
208 |
209 | - **waitingForOpen**: check this property if you need to know if another modal will be opened once this one is closed
210 | ```javascript
211 | $ocModal.open({
212 | url: "partials/login.html",
213 | controller: 'LoginCtrl',
214 | onClose: function() {
215 | if(!$ocModal.waitingForOpen) {
216 | $state.transitionTo('welcome');
217 | }
218 | }
219 | });
220 | ```
221 |
222 | ### Directives
223 | - **oc-modal-open**: this is an alias for ```$ocModal.open()``` that you can also use in your template.
224 | ```html
225 |
226 | ```
227 |
228 | - **oc-modal-close**: this is an alias for ```$ocModal.close()``` that you can also use in your template.
229 | ```html
230 |
231 | ```
232 |
233 | ### Animations
234 | You can use a set of animations by including the file ocModal.animations.css and by adding one of those classes with the cls parameter :
235 | - fade-in
236 | - slide-down
237 | - scale
238 | - fall
239 | - flip-horizontal
240 | - flip-vertical
241 | - super-scaled
242 | - slit
243 |
244 | ```javascript
245 | oc-modal-open="{url: 'partials/modal.html', cls: 'fade-in'}"
246 | ```
247 |
248 | You can add your own animations by adding new styles to `.modal .modal-dialog .modal-content` and `.modal .modal-dialog .modal-content.opened`.
249 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ocModal",
3 | "main": "dist/ocModal.min.js",
4 | "version": "0.1.12",
5 | "homepage": "https://github.com/ocombe/ocModal",
6 | "authors": [
7 | "Olivier Combe "
8 | ],
9 | "description": "An angularJS modal directive / service",
10 | "keywords": [
11 | "modal",
12 | "dialog",
13 | "module",
14 | "angular",
15 | "angularJS"
16 | ],
17 | "license": "MIT",
18 | "ignore": [
19 | "**/.*",
20 | "node_modules",
21 | "bower_components",
22 | "src",
23 | "gulpfile.js",
24 | "package.json"
25 | ]
26 | }
--------------------------------------------------------------------------------
/dist/css/ocModal.animations.css:
--------------------------------------------------------------------------------
1 | .modal .modal-dialog .modal-content.fade-in {
2 | -webkit-transition: opacity 0.5s;
3 | -moz-transition: opacity 0.5s;
4 | transition: opacity 0.5s;
5 | opacity: 0; }
6 | .modal .modal-dialog .modal-content.fade-in.opened {
7 | opacity: 1; }
8 |
9 | .modal .modal-dialog .modal-content.slide-down {
10 | -webkit-transition: opacity, -webkit-transform;
11 | -moz-transition: opacity, -moz-transform;
12 | transition: opacity, transform;
13 | -webkit-transform: translateY(-20%);
14 | -moz-transform: translateY(-20%);
15 | -ms-transform: translateY(-20%);
16 | -o-transform: translateY(-20%);
17 | transform: translateY(-20%);
18 | opacity: 0; }
19 | .modal .modal-dialog .modal-content.slide-down.slide-down.opened {
20 | -webkit-transform: translateY(0%);
21 | -moz-transform: translateY(0%);
22 | -ms-transform: translateY(0%);
23 | -o-transform: translateY(0%);
24 | transform: translateY(0%);
25 | opacity: 1; }
26 |
27 | .modal .modal-dialog .modal-content.scale {
28 | -webkit-transform: scale(0.7);
29 | -moz-transform: scale(0.7);
30 | -ms-transform: scale(0.7);
31 | -o-transform: scale(0.7);
32 | transform: scale(0.7);
33 | -webkit-transition: -webkit-transform, opacity;
34 | -moz-transition: -moz-transform, opacity;
35 | transition: transform, opacity;
36 | opacity: 0; }
37 | .modal .modal-dialog .modal-content.scale.opened {
38 | -webkit-transform: scale(1);
39 | -moz-transform: scale(1);
40 | -ms-transform: scale(1);
41 | -o-transform: scale(1);
42 | transform: scale(1);
43 | opacity: 1; }
44 |
45 | .modal .modal-dialog .modal-content.fall {
46 | -webkit-transform-style: preserve-3d;
47 | -moz-transform-style: preserve-3d;
48 | -ms-transform-style: preserve-3d;
49 | -o-transform-style: preserve-3d;
50 | transform-style: preserve-3d;
51 | -webkit-transform: translateZ(600px) rotateX(20deg);
52 | -moz-transform: translateZ(600px) rotateX(20deg);
53 | -ms-transform: translateZ(600px) rotateX(20deg);
54 | -o-transform: translateZ(600px) rotateX(20deg);
55 | transform: translateZ(600px) rotateX(20deg);
56 | -webkit-transition: -webkit-transform, opacity;
57 | -moz-transition: -moz-transform, opacity;
58 | transition: transform, opacity;
59 | opacity: 0; }
60 | .modal .modal-dialog .modal-content.fall.opened {
61 | -webkit-transform: translateZ(0) rotateX(0deg);
62 | -moz-transform: translateZ(0) rotateX(0deg);
63 | -ms-transform: translateZ(0) rotateX(0deg);
64 | -o-transform: translateZ(0) rotateX(0deg);
65 | transform: translateZ(0) rotateX(0deg);
66 | opacity: 1; }
67 |
68 | .modal .modal-dialog .modal-content.flip-horizontal {
69 | -webkit-transform-style: preserve-3d;
70 | -moz-transform-style: preserve-3d;
71 | -ms-transform-style: preserve-3d;
72 | -o-transform-style: preserve-3d;
73 | transform-style: preserve-3d;
74 | -webkit-transform: rotateY(-70deg);
75 | -moz-transform: rotateY(-70deg);
76 | -ms-transform: rotateY(-70deg);
77 | -o-transform: rotateY(-70deg);
78 | transform: rotateY(-70deg);
79 | -webkit-transition: -webkit-transform, opacity;
80 | -moz-transition: -moz-transform, opacity;
81 | transition: transform, opacity;
82 | opacity: 0; }
83 | .modal .modal-dialog .modal-content.flip-horizontal.opened {
84 | -webkit-transform: rotateY(0deg);
85 | -moz-transform: rotateY(0deg);
86 | -ms-transform: rotateY(0deg);
87 | -o-transform: rotateY(0deg);
88 | transform: rotateY(0deg);
89 | opacity: 1; }
90 |
91 | .modal .modal-dialog .modal-content.flip-vertical {
92 | -webkit-transform-style: preserve-3d;
93 | -moz-transform-style: preserve-3d;
94 | -ms-transform-style: preserve-3d;
95 | -o-transform-style: preserve-3d;
96 | transform-style: preserve-3d;
97 | -webkit-transform: rotateX(-70deg);
98 | -moz-transform: rotateX(-70deg);
99 | -ms-transform: rotateX(-70deg);
100 | -o-transform: rotateX(-70deg);
101 | transform: rotateX(-70deg);
102 | -webkit-transition: -webkit-transform, opacity;
103 | -moz-transition: -moz-transform, opacity;
104 | transition: transform, opacity;
105 | opacity: 0; }
106 | .modal .modal-dialog .modal-content.flip-vertical.opened {
107 | -webkit-transform: rotateX(0deg);
108 | -moz-transform: rotateX(0deg);
109 | -ms-transform: rotateX(0deg);
110 | -o-transform: rotateX(0deg);
111 | transform: rotateX(0deg);
112 | opacity: 1; }
113 |
114 | .modal .modal-dialog .modal-content.super-scaled {
115 | -webkit-transform: scale(2);
116 | -moz-transform: scale(2);
117 | -ms-transform: scale(2);
118 | -o-transform: scale(2);
119 | transform: scale(2);
120 | -webkit-transition: -webkit-transform, opacity;
121 | -moz-transition: -moz-transform, opacity;
122 | transition: transform, opacity;
123 | opacity: 0; }
124 | .modal .modal-dialog .modal-content.super-scaled.opened {
125 | -webkit-transform: scale(1);
126 | -moz-transform: scale(1);
127 | -ms-transform: scale(1);
128 | -o-transform: scale(1);
129 | transform: scale(1);
130 | opacity: 1; }
131 |
132 | .modal .modal-dialog .modal-content.slit {
133 | -webkit-transform-style: preserve-3d;
134 | -moz-transform-style: preserve-3d;
135 | -ms-transform-style: preserve-3d;
136 | -o-transform-style: preserve-3d;
137 | transform-style: preserve-3d;
138 | -webkit-transition: opacity 0.5s;
139 | -moz-transition: opacity 0.5s;
140 | transition: opacity 0.5s;
141 | opacity: 0; }
142 | .modal .modal-dialog .modal-content.slit.opened {
143 | opacity: 1;
144 | -webkit-transform: translateZ(-3000px) rotateY(90deg);
145 | -moz-transform: translateZ(-3000px) rotateY(90deg);
146 | -ms-transform: translateZ(-3000px) rotateY(90deg);
147 | -o-transform: translateZ(-3000px) rotateY(90deg);
148 | transform: translateZ(-3000px) rotateY(90deg);
149 | -webkit-animation: slit 0.7s forwards ease-out;
150 | -moz-animation: slit 0.7s forwards ease-out;
151 | animation: slit 0.7s forwards ease-out; }
152 |
153 | @-webkit-keyframes slit {
154 | 50% {
155 | -webkit-transform: translateZ(-250px) rotateY(89deg);
156 | -webkit-animation-timing-function: ease-out; }
157 | 100% {
158 | -webkit-transform: translateZ(0) rotateY(0deg); } }
159 |
160 | @-moz-keyframes slit {
161 | 50% {
162 | -moz-transform: translateZ(-250px) rotateY(89deg);
163 | opacity: .5;
164 | -moz-animation-timing-function: ease-out; }
165 | 100% {
166 | -moz-transform: translateZ(0) rotateY(0deg); } }
167 |
168 | @keyframes slit {
169 | 50% {
170 | transform: translateZ(-250px) rotateY(89deg);
171 | animation-timing-function: ease-in; }
172 | 100% {
173 | transform: translateZ(0) rotateY(0deg); } }
174 |
--------------------------------------------------------------------------------
/dist/css/ocModal.animations.min.css:
--------------------------------------------------------------------------------
1 | .modal .modal-dialog .modal-content.fade-in{-webkit-transition:opacity .5s;-moz-transition:opacity .5s;transition:opacity .5s;opacity:0}.modal .modal-dialog .modal-content.fade-in.opened{opacity:1}.modal .modal-dialog .modal-content.slide-down{-webkit-transition:opacity,-webkit-transform;-moz-transition:opacity,-moz-transform;transition:opacity,transform;-webkit-transform:translateY(-20%);-moz-transform:translateY(-20%);-ms-transform:translateY(-20%);-o-transform:translateY(-20%);transform:translateY(-20%);opacity:0}.modal .modal-dialog .modal-content.fall,.modal .modal-dialog .modal-content.scale{-webkit-transition:-webkit-transform,opacity;-moz-transition:-moz-transform,opacity}.modal .modal-dialog .modal-content.slide-down.slide-down.opened{-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0);opacity:1}.modal .modal-dialog .modal-content.scale{-webkit-transform:scale(.7);-moz-transform:scale(.7);-ms-transform:scale(.7);-o-transform:scale(.7);transform:scale(.7);transition:transform,opacity;opacity:0}.modal .modal-dialog .modal-content.scale.opened{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1);opacity:1}.modal .modal-dialog .modal-content.fall{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;-o-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-transform:translateZ(600px) rotateX(20deg);-moz-transform:translateZ(600px) rotateX(20deg);-ms-transform:translateZ(600px) rotateX(20deg);-o-transform:translateZ(600px) rotateX(20deg);transform:translateZ(600px) rotateX(20deg);transition:transform,opacity;opacity:0}.modal .modal-dialog .modal-content.fall.opened{-webkit-transform:translateZ(0) rotateX(0);-moz-transform:translateZ(0) rotateX(0);-ms-transform:translateZ(0) rotateX(0);-o-transform:translateZ(0) rotateX(0);transform:translateZ(0) rotateX(0);opacity:1}.modal .modal-dialog .modal-content.flip-horizontal{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;-o-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-transform:rotateY(-70deg);-moz-transform:rotateY(-70deg);-ms-transform:rotateY(-70deg);-o-transform:rotateY(-70deg);transform:rotateY(-70deg);-webkit-transition:-webkit-transform,opacity;-moz-transition:-moz-transform,opacity;transition:transform,opacity;opacity:0}.modal .modal-dialog .modal-content.flip-horizontal.opened{-webkit-transform:rotateY(0);-moz-transform:rotateY(0);-ms-transform:rotateY(0);-o-transform:rotateY(0);transform:rotateY(0);opacity:1}.modal .modal-dialog .modal-content.flip-vertical{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;-o-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-transform:rotateX(-70deg);-moz-transform:rotateX(-70deg);-ms-transform:rotateX(-70deg);-o-transform:rotateX(-70deg);transform:rotateX(-70deg);-webkit-transition:-webkit-transform,opacity;-moz-transition:-moz-transform,opacity;transition:transform,opacity;opacity:0}.modal .modal-dialog .modal-content.flip-vertical.opened{-webkit-transform:rotateX(0);-moz-transform:rotateX(0);-ms-transform:rotateX(0);-o-transform:rotateX(0);transform:rotateX(0);opacity:1}.modal .modal-dialog .modal-content.super-scaled{-webkit-transform:scale(2);-moz-transform:scale(2);-ms-transform:scale(2);-o-transform:scale(2);transform:scale(2);-webkit-transition:-webkit-transform,opacity;-moz-transition:-moz-transform,opacity;transition:transform,opacity;opacity:0}.modal .modal-dialog .modal-content.super-scaled.opened{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1);opacity:1}.modal .modal-dialog .modal-content.slit{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;-o-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-transition:opacity .5s;-moz-transition:opacity .5s;transition:opacity .5s;opacity:0}.modal .modal-dialog .modal-content.slit.opened{opacity:1;-webkit-transform:translateZ(-3000px) rotateY(90deg);-moz-transform:translateZ(-3000px) rotateY(90deg);-ms-transform:translateZ(-3000px) rotateY(90deg);-o-transform:translateZ(-3000px) rotateY(90deg);transform:translateZ(-3000px) rotateY(90deg);-webkit-animation:slit .7s forwards ease-out;-moz-animation:slit .7s forwards ease-out;animation:slit .7s forwards ease-out}@-webkit-keyframes slit{50%{-webkit-transform:translateZ(-250px) rotateY(89deg);-webkit-animation-timing-function:ease-out}100%{-webkit-transform:translateZ(0) rotateY(0)}}@-moz-keyframes slit{50%{-moz-transform:translateZ(-250px) rotateY(89deg);opacity:.5;-moz-animation-timing-function:ease-out}100%{-moz-transform:translateZ(0) rotateY(0)}}@keyframes slit{50%{transform:translateZ(-250px) rotateY(89deg);animation-timing-function:ease-in}100%{transform:translateZ(0) rotateY(0)}}
--------------------------------------------------------------------------------
/dist/css/ocModal.full.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | *,
3 | *:before,
4 | *:after {
5 | -webkit-box-sizing: border-box;
6 | -moz-box-sizing: border-box;
7 | box-sizing: border-box; }
8 |
9 | .modal-open {
10 | overflow: hidden; }
11 |
12 | .modal {
13 | display: none;
14 | overflow: auto;
15 | overflow-y: scroll;
16 | position: fixed;
17 | top: 0;
18 | right: 0;
19 | bottom: 0;
20 | left: 0;
21 | z-index: 1040; }
22 | .modal.fade .modal-dialog {
23 | -webkit-transform: translate(0, -25%);
24 | -ms-transform: translate(0, -25%);
25 | transform: translate(0, -25%);
26 | -webkit-transition: -webkit-transform 0.3s ease-out;
27 | -moz-transition: -moz-transform 0.3s ease-out;
28 | -o-transition: -o-transform 0.3s ease-out;
29 | transition: transform 0.3s ease-out; }
30 | .modal.in .modal-dialog {
31 | -webkit-transform: translate(0, 0);
32 | -ms-transform: translate(0, 0);
33 | transform: translate(0, 0); }
34 |
35 | .modal-dialog {
36 | position: relative;
37 | margin-left: auto;
38 | margin-right: auto;
39 | width: auto;
40 | padding: 10px;
41 | z-index: 1050; }
42 |
43 | .modal-content {
44 | position: relative;
45 | background-color: #fff;
46 | border: 1px solid #999;
47 | border: 1px solid rgba(0, 0, 0, 0.2);
48 | border-radius: 6px;
49 | -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
50 | box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
51 | background-clip: padding-box;
52 | outline: none; }
53 |
54 | .modal-backdrop {
55 | position: fixed;
56 | top: 0;
57 | right: 0;
58 | bottom: 0;
59 | left: 0;
60 | z-index: 1030;
61 | background-color: #CCCCCC; }
62 | .modal-backdrop.fade {
63 | opacity: 0;
64 | filter: alpha(opacity=0); }
65 | .modal-backdrop.in {
66 | opacity: 0.5;
67 | filter: alpha(opacity=50); }
68 |
69 | .modal-header {
70 | padding: 15px;
71 | border-bottom: 1px solid transparent;
72 | min-height: 16.42857px; }
73 |
74 | .modal-header .close {
75 | margin-top: -2px; }
76 |
77 | .modal-title {
78 | margin: 0;
79 | line-height: 1.42857; }
80 |
81 | .modal-body {
82 | position: relative;
83 | padding: 20px; }
84 |
85 | .modal-footer {
86 | margin-top: 15px;
87 | padding: 19px 20px 20px;
88 | text-align: right;
89 | border-top: 1px solid transparent; }
90 | .modal-footer:before, .modal-footer:after {
91 | content: " ";
92 | /* 1 */
93 | display: table;
94 | /* 2 */ }
95 | .modal-footer:after {
96 | clear: both; }
97 | .modal-footer .btn + .btn {
98 | margin-left: 5px;
99 | margin-bottom: 0; }
100 | .modal-footer .btn-group .btn + .btn {
101 | margin-left: -1px; }
102 | .modal-footer .btn-block + .btn-block {
103 | margin-left: 0; }
104 |
105 | @media screen and (min-width: 768px) {
106 | .modal-dialog {
107 | width: 600px;
108 | padding-top: 30px;
109 | padding-bottom: 30px; }
110 | .modal-content {
111 | -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
112 | box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); } }
113 |
114 | .noOverflow {
115 | overflow: hidden; }
116 |
117 | .modal-wrapper {
118 | z-index: 1050;
119 | position: fixed; }
120 | .modal-wrapper .modal-backdrop {
121 | width: 100%;
122 | height: 100%;
123 | opacity: 0.8;
124 | filter: alpha(opacity=80); }
125 |
126 | .modal {
127 | display: block;
128 | overflow: auto;
129 | text-align: center; }
130 | .modal .modal-dialog {
131 | z-index: 1060;
132 | width: auto;
133 | text-align: left;
134 | /* on rétablit l'alignement du texte */
135 | -webkit-perspective: 1300px;
136 | -moz-perspective: 1300px;
137 | perspective: 1300px;
138 | max-width: 100%; }
139 | .modal .modal-dialog.no-backdrop .modal-backdrop {
140 | display: none; }
141 | .modal .modal-dialog .modal-content {
142 | z-index: 1050;
143 | border-radius: 2px;
144 | width: 600px;
145 | padding: 10px;
146 | max-width: 100%;
147 | margin: 0; }
148 |
149 | .flexbox .modal > .modal-backdrop {
150 | display: none; }
151 |
152 | .flexbox .modal .modal-dialog {
153 | display: -webkit-box;
154 | display: -moz-box;
155 | display: box;
156 | display: -webkit-flex;
157 | display: -moz-flex;
158 | display: -ms-flexbox;
159 | display: flex;
160 | -webkit-box-align: center;
161 | -moz-box-align: center;
162 | box-align: center;
163 | -webkit-align-items: center;
164 | -moz-align-items: center;
165 | -ms-align-items: center;
166 | -o-align-items: center;
167 | align-items: center;
168 | -ms-flex-align: center;
169 | -webkit-box-pack: center;
170 | -moz-box-pack: center;
171 | box-pack: center;
172 | -webkit-justify-content: center;
173 | -moz-justify-content: center;
174 | -ms-justify-content: center;
175 | -o-justify-content: center;
176 | justify-content: center;
177 | -ms-flex-pack: center;
178 | position: absolute;
179 | width: 100%;
180 | min-height: 100%;
181 | height: 100%;
182 | margin: 0;
183 | padding: 10px;
184 | max-height: initial; }
185 |
186 | .no-flexbox .modal-dialog {
187 | -webkit-transform: translate(-50%, -50%);
188 | -moz-transform: translate(-50%, -50%);
189 | -ms-transform: translate(-50%, -50%);
190 | -o-transform: translate(-50%, -50%);
191 | transform: translate(-50%, -50%);
192 | position: absolute;
193 | left: 50%;
194 | top: 50%;
195 | margin: 0;
196 | padding: 10px;
197 | max-height: 100%; }
198 | .no-flexbox .modal-dialog .modal-backdrop {
199 | display: none; }
200 |
201 | .no-flexbox.no-csstransforms .modal-dialog {
202 | left: auto;
203 | top: auto;
204 | margin: auto; }
205 |
206 | .lt-ie8 .modal-content {
207 | display: inline;
208 | zoom: 1; }
209 |
--------------------------------------------------------------------------------
/dist/css/ocModal.full.min.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";.modal,.modal-backdrop{top:0;right:0;bottom:0;left:0}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.modal-open{overflow:hidden}.modal{overflow-y:scroll;position:fixed;z-index:1040}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;margin-left:auto;margin-right:auto;width:auto;padding:10px;z-index:1050}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;z-index:1030;background-color:#CCC}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid transparent;min-height:16.43px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid transparent}.modal-footer:after,.modal-footer:before{content:" ";display:table}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}}.noOverflow{overflow:hidden}.modal-wrapper{z-index:1050;position:fixed}.modal-wrapper .modal-backdrop{width:100%;height:100%;opacity:.8;filter:alpha(opacity=80)}.modal{display:block;overflow:auto;text-align:center}.flexbox .modal>.modal-backdrop,.modal .modal-dialog.no-backdrop .modal-backdrop{display:none}.modal .modal-dialog{z-index:1060;width:auto;text-align:left;-webkit-perspective:1300px;-moz-perspective:1300px;perspective:1300px;max-width:100%}.modal .modal-dialog .modal-content{z-index:1050;border-radius:2px;width:600px;padding:10px;max-width:100%;margin:0}.flexbox .modal .modal-dialog{display:-webkit-box;display:-moz-box;display:box;display:-webkit-flex;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-moz-box-align:center;box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;-ms-flex-align:center;-webkit-box-pack:center;-moz-box-pack:center;box-pack:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;-o-justify-content:center;justify-content:center;-ms-flex-pack:center;position:absolute;width:100%;min-height:100%;height:100%;margin:0;padding:10px;max-height:initial}.no-flexbox .modal-dialog{-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;margin:0;padding:10px;max-height:100%}.no-flexbox .modal-dialog .modal-backdrop{display:none}.no-flexbox.no-csstransforms .modal-dialog{left:auto;top:auto;margin:auto}.lt-ie8 .modal-content{display:inline;zoom:1}
--------------------------------------------------------------------------------
/dist/css/ocModal.light.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | .noOverflow {
3 | overflow: hidden; }
4 |
5 | .modal-wrapper {
6 | z-index: 1050;
7 | position: fixed; }
8 | .modal-wrapper .modal-backdrop {
9 | width: 100%;
10 | height: 100%;
11 | opacity: 0.8;
12 | filter: alpha(opacity=80); }
13 |
14 | .modal {
15 | display: block;
16 | overflow: auto;
17 | text-align: center; }
18 | .modal .modal-dialog {
19 | z-index: 1060;
20 | width: auto;
21 | text-align: left;
22 | /* on rétablit l'alignement du texte */
23 | -webkit-perspective: 1300px;
24 | -moz-perspective: 1300px;
25 | perspective: 1300px;
26 | max-width: 100%; }
27 | .modal .modal-dialog.no-backdrop .modal-backdrop {
28 | display: none; }
29 | .modal .modal-dialog .modal-content {
30 | z-index: 1050;
31 | border-radius: 2px;
32 | width: 600px;
33 | padding: 10px;
34 | max-width: 100%;
35 | margin: 0; }
36 |
37 | .flexbox .modal > .modal-backdrop {
38 | display: none; }
39 |
40 | .flexbox .modal .modal-dialog {
41 | display: -webkit-box;
42 | display: -moz-box;
43 | display: box;
44 | display: -webkit-flex;
45 | display: -moz-flex;
46 | display: -ms-flexbox;
47 | display: flex;
48 | -webkit-box-align: center;
49 | -moz-box-align: center;
50 | box-align: center;
51 | -webkit-align-items: center;
52 | -moz-align-items: center;
53 | -ms-align-items: center;
54 | -o-align-items: center;
55 | align-items: center;
56 | -ms-flex-align: center;
57 | -webkit-box-pack: center;
58 | -moz-box-pack: center;
59 | box-pack: center;
60 | -webkit-justify-content: center;
61 | -moz-justify-content: center;
62 | -ms-justify-content: center;
63 | -o-justify-content: center;
64 | justify-content: center;
65 | -ms-flex-pack: center;
66 | position: absolute;
67 | width: 100%;
68 | min-height: 100%;
69 | height: 100%;
70 | margin: 0;
71 | padding: 10px;
72 | max-height: initial; }
73 |
74 | .no-flexbox .modal-dialog {
75 | -webkit-transform: translate(-50%, -50%);
76 | -moz-transform: translate(-50%, -50%);
77 | -ms-transform: translate(-50%, -50%);
78 | -o-transform: translate(-50%, -50%);
79 | transform: translate(-50%, -50%);
80 | position: absolute;
81 | left: 50%;
82 | top: 50%;
83 | margin: 0;
84 | padding: 10px;
85 | max-height: 100%; }
86 | .no-flexbox .modal-dialog .modal-backdrop {
87 | display: none; }
88 |
89 | .no-flexbox.no-csstransforms .modal-dialog {
90 | left: auto;
91 | top: auto;
92 | margin: auto; }
93 |
94 | .lt-ie8 .modal-content {
95 | display: inline;
96 | zoom: 1; }
97 |
--------------------------------------------------------------------------------
/dist/css/ocModal.light.min.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";.noOverflow{overflow:hidden}.modal-wrapper{z-index:1050;position:fixed}.modal-wrapper .modal-backdrop{width:100%;height:100%;opacity:.8;filter:alpha(opacity=80)}.modal{display:block;overflow:auto;text-align:center}.flexbox .modal>.modal-backdrop,.modal .modal-dialog.no-backdrop .modal-backdrop{display:none}.modal .modal-dialog{z-index:1060;width:auto;text-align:left;-webkit-perspective:1300px;-moz-perspective:1300px;perspective:1300px;max-width:100%}.modal .modal-dialog .modal-content{z-index:1050;border-radius:2px;width:600px;padding:10px;max-width:100%;margin:0}.flexbox .modal .modal-dialog{display:-webkit-box;display:-moz-box;display:box;display:-webkit-flex;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-moz-box-align:center;box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;-ms-flex-align:center;-webkit-box-pack:center;-moz-box-pack:center;box-pack:center;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;-o-justify-content:center;justify-content:center;-ms-flex-pack:center;position:absolute;width:100%;min-height:100%;height:100%;margin:0;padding:10px;max-height:initial}.no-flexbox .modal-dialog{-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;margin:0;padding:10px;max-height:100%}.no-flexbox .modal-dialog .modal-backdrop{display:none}.no-flexbox.no-csstransforms .modal-dialog{left:auto;top:auto;margin:auto}.lt-ie8 .modal-content{display:inline;zoom:1}
--------------------------------------------------------------------------------
/dist/ocModal.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ocmodal - An angularJS modal directive / service
3 | * @version v0.1.12
4 | * @link https://github.com/ocombe/ocModal
5 | * @license MIT
6 | * @author Olivier Combe
7 | */
8 | (function() {
9 | 'use strict';
10 |
11 | var ocModal = angular.module('oc.modal', []);
12 |
13 | ocModal.factory('$ocModal', ['$rootScope', '$controller', '$location', '$timeout', '$compile', '$sniffer', '$q', function($rootScope, $controller, $location, $timeout, $compile, $sniffer, $q) {
14 | var $body = angular.element(document.body),
15 | $dialogsWrapper = angular.element(''),
16 | $modalWrapper = angular.element(
17 | '
'
18 | ),
19 | modals = {},
20 | openedModals = [],
21 | baseOverflow;
22 |
23 | // include the modal in DOM at start for animations
24 | $modalWrapper.css('display', 'none');
25 | $modalWrapper.append($dialogsWrapper);
26 | $body.append($modalWrapper);
27 | $dialogsWrapper.on('click', function(e) {
28 | if(angular.element(e.target).hasClass('modal-backdrop')) { // only if clicked on backdrop
29 | $rootScope.$apply(function() {
30 | self.closeOnEsc();
31 | });
32 | }
33 | });
34 |
35 | var parseMaxTime = function parseMaxTime(str) {
36 | var total = 0, values = angular.isString(str) ? str.split(/\s*,\s*/) : [];
37 | angular.forEach(values, function(value) {
38 | total = Math.max(parseFloat(value) || 0, total);
39 | });
40 | return total;
41 | };
42 |
43 | var getAnimDuration = function getDuration($element) {
44 | var duration = 0;
45 | if(($sniffer.transitions || $sniffer.animations)) {
46 | //one day all browsers will have these properties
47 | var w3cAnimationProp = 'animation';
48 | var w3cTransitionProp = 'transition';
49 |
50 | //but some still use vendor-prefixed styles
51 | var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation';
52 | var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
53 |
54 | var durationKey = 'Duration',
55 | delayKey = 'Delay',
56 | animationIterationCountKey = 'IterationCount';
57 |
58 | //we want all the styles defined before and after
59 | var ELEMENT_NODE = 1;
60 | angular.forEach($element, function(element) {
61 | if(element.nodeType == ELEMENT_NODE) {
62 | var elementStyles = window.getComputedStyle(element) || {};
63 |
64 | var transitionDelay = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + delayKey]),
65 | parseMaxTime(elementStyles[vendorTransitionProp + delayKey]));
66 |
67 | var animationDelay = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + delayKey]),
68 | parseMaxTime(elementStyles[vendorAnimationProp + delayKey]));
69 |
70 | var transitionDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]),
71 | parseMaxTime(elementStyles[vendorTransitionProp + durationKey]));
72 |
73 | var animationDuration = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + durationKey]),
74 | parseMaxTime(elementStyles[vendorAnimationProp + durationKey]));
75 |
76 | if(animationDuration > 0) {
77 | animationDuration *= Math.max(parseInt(elementStyles[w3cAnimationProp + animationIterationCountKey]) || 0,
78 | parseInt(elementStyles[vendorAnimationProp + animationIterationCountKey]) || 0, 1);
79 | }
80 |
81 | duration = Math.max(animationDelay + animationDuration, transitionDelay + transitionDuration, duration);
82 | }
83 | });
84 | }
85 |
86 | return duration * 1000;
87 | };
88 |
89 | angular.element(document).on('keyup', function(e) {
90 | if (e.keyCode == 27 && openedModals.length > 0) {
91 | e.stopPropagation();
92 | $rootScope.$apply(function() {
93 | self.closeOnEsc(openedModals[openedModals.length - 1]);
94 | });
95 | }
96 | });
97 |
98 | var self = {
99 | waitingForOpen: false,
100 |
101 | getOpenedModals: function() {
102 | return openedModals;
103 | },
104 |
105 | register: function(params) {
106 | modals[params.id || '_default'] = params;
107 | },
108 |
109 | remove: function(id) {
110 | delete modals[id || '_default'];
111 | },
112 |
113 | open: function(opt) {
114 | if(typeof opt === 'string') {
115 | if(opt.match('<')) { // if html code
116 | opt = {
117 | template: opt
118 | }
119 | } else {
120 | opt = {
121 | url: opt
122 | }
123 | }
124 | }
125 | var modal = modals[opt.id || '_default'];
126 | if(!modal) {
127 | $dialogsWrapper.append($compile('
')($rootScope));
128 | $timeout(function() { // let the ng-include detect that it's now empty
129 | self.open(opt);
130 | });
131 | return;
132 | } else if(modal && openedModals.indexOf(opt.id || '_default') !== -1) { // if modal already opened
133 | if(self.waitingForOpen) {
134 | return;
135 | }
136 | self.waitingForOpen = true;
137 | self.close(opt.id).then(function() {
138 | self.open(opt);
139 | });
140 | return;
141 | }
142 | // ok let's open the modal
143 | if(!self.waitingForOpen) {
144 | if(openedModals.length === 0) { // if no modal opened
145 | baseOverflow = document.body.style.overflow;
146 | document.body.style.overflow = 'hidden';
147 | $modalWrapper.css('display', 'block');
148 | } else {
149 | for(var i = 0, len = openedModals.length; i < len; i++) {
150 | var $e = modals[openedModals[i]].$element;
151 | modals[openedModals[i]].baseZIndex = $e.css('z-index');
152 | $e.css('z-index', '-1');
153 | $e.addClass('no-backdrop');
154 | }
155 | }
156 | }
157 | self.waitingForOpen = false;
158 | openedModals.push(opt.id || '_default');
159 | modal.params = opt;
160 | modal.$scope.customClass = modal.params.cls;
161 |
162 | // timeout for animations (if any)
163 | $rootScope.$digest();
164 | $body[0].offsetWidth; // force paint to be sure the element is in the page
165 | $timeout(function() {
166 | modal.$scope.modalShow = true;
167 | }, 100);
168 |
169 | if(typeof modal.params.onOpen === 'function') {
170 | modal.params.onOpen();
171 | }
172 |
173 | var off = modal.$scope.$on('$includeContentLoaded', function(event) { // on view load
174 | if(modal.params.init && !modal.params.isolate) {
175 | angular.extend(event.targetScope, modal.params.init);
176 | }
177 | if(typeof modal.params.controller === 'string') {
178 | $controller(modal.params.controller, {$scope: event.targetScope, $init: modal.params.init, $ocModalParams: modal.params}); // inject controller
179 | }
180 | off();
181 | });
182 |
183 | if(modal.params.template) {
184 | modal.$scope.modalTemplate = modal.params.template; // load the view
185 | } else if(modal.params.url) {
186 | modal.$scope.modalUrl = modal.params.url; // load the view
187 | } else {
188 | throw "You need to define a template or an url";
189 | return;
190 | }
191 |
192 | if(typeof callback === 'function') {
193 | modal.$scope.callbacksList.push(callback);
194 | }
195 | },
196 |
197 | closeOnEsc: function(id) {
198 | if(modals[id || openedModals[openedModals.length -1]].params.closeOnEsc !== false) {
199 | return self.close(id);
200 | }
201 | },
202 |
203 | close: function(id) {
204 | var args,
205 | deferred = $q.defer();
206 | if(typeof id === 'string' && openedModals.indexOf(id) !== -1) {
207 | args = Array.prototype.slice.call(arguments, 1);
208 | } else {
209 | args = arguments;
210 | }
211 | if(typeof id === 'undefined' || openedModals.indexOf(id) === -1) {
212 | id = openedModals[openedModals.length -1];
213 | }
214 | var modal = modals[id || openedModals[openedModals.length -1]];
215 | if(modal && modal.$scope.modalShow === true) { // if the modal is opened
216 | var animDuration = getAnimDuration(angular.element(modal.$element[0].querySelector('.modal-content')));
217 | $timeout(function() {
218 | modal.$scope.modalShow = false;
219 |
220 | $timeout(function() {
221 | modal.$scope.$destroy();
222 | modal.$element.remove(); // destroy the modal
223 |
224 | modal.callbacksList = []; // forget all callbacks
225 | openedModals.splice(openedModals.indexOf(id || openedModals[openedModals.length -1]), 1);
226 | if(openedModals.length === 0) { // if no modal left opened
227 | if(!self.waitingForOpen) { // in case the current modal is closed because another opened with the same id (avoid backdrop flickering in firefox)
228 | document.body.style.overflow = baseOverflow; // restore the body overflow
229 | $modalWrapper.css('display', 'none');
230 | }
231 | } else {
232 | var topModal = modals[openedModals[openedModals.length - 1]];
233 | topModal.$element.css('z-index', topModal.baseZIndex);
234 | topModal.$element.removeClass('no-backdrop');
235 | }
236 | if(typeof modal.params.onClose === 'function') {
237 | modal.params.onClose.apply(undefined, args);
238 | }
239 |
240 | deferred.resolve();
241 | }, animDuration);
242 | });
243 | } else {
244 | deferred.resolve();
245 | }
246 | return deferred.promise;
247 | }
248 | };
249 |
250 | return self;
251 | }]);
252 |
253 | ocModal.directive('ocModal', ['$ocModal', '$compile', '$timeout', function($ocModal, $compile, $timeout) {
254 | return {
255 | restrict: 'AE',
256 | replace: true,
257 | scope: true,
258 | template:
259 | '' +
260 | '
' +
261 | '
' +
262 | '
' +
263 | '
',
264 |
265 | link: function link($scope, $element, $attrs) {
266 | var id = $attrs.ocModal,
267 | $templateWrapper;
268 |
269 | $scope.closeModal = function() {
270 | var args = Array.prototype.slice.call(arguments);
271 | args.unshift(id);
272 | $ocModal.close.apply(undefined, args);
273 | };
274 |
275 | $ocModal.register({
276 | id: id,
277 | $scope: $scope,
278 | $element: $element
279 | });
280 |
281 | $element.on('$destroy', function() {
282 | $ocModal.remove(id);
283 | });
284 |
285 | $scope.$watch('modalTemplate', function(newVal, oldVal) {
286 | if(typeof newVal !== 'undefined') {
287 | if(!$templateWrapper) {
288 | $templateWrapper = angular.element($element.children()[1]);
289 | }
290 | $templateWrapper.append($compile(newVal)($scope));
291 | $scope.$emit('$includeContentLoaded');
292 | }
293 | });
294 | }
295 | }
296 | }]);
297 |
298 | ocModal.directive('ocModalOpen', ['$ocModal', function($ocModal) {
299 | return {
300 | restrict: 'A',
301 | require: '?modal',
302 | link: function($scope, $element, $attrs) {
303 | $element.on('click touchstart', function(e) {
304 | e.preventDefault();
305 | e.stopPropagation();
306 | var newScope = $scope.$new();
307 | var params = newScope.$eval($attrs.ocModalOpen);
308 | if(params) {
309 | if(typeof params === "number") {
310 | params = { url: $attrs.ocModalOpen };
311 | } else if(typeof params === "string") {
312 | params = { url: params };
313 | }
314 | if(!params.url) {
315 | throw "You need to set the modal url";
316 | }
317 | $scope.$apply(function() {
318 | $ocModal.open(params);
319 | });
320 | }
321 | });
322 | }
323 | };
324 | }]);
325 |
326 | ocModal.directive('ocModalClose', ['$ocModal', function($ocModal) {
327 | return {
328 | restrict: 'A',
329 | require: '?modal',
330 | link: function($scope, $element, $attrs) {
331 | $element.on('click touchstart', function(e) {
332 | e.preventDefault();
333 | e.stopPropagation();
334 | $scope.$apply(function() {
335 | if($attrs.ocModalClose) {
336 | var params = $scope.$new().$eval($attrs.ocModalClose);
337 | }
338 | $ocModal.close(params);
339 | });
340 | });
341 | }
342 | };
343 | }]);
344 |
345 |
346 |
347 | })();
348 |
349 | /* Modernizr 2.8.2 (Custom Build) | MIT & BSD
350 | * Build: http://modernizr.com/download/#-flexbox-flexboxlegacy-cssclasses-testprop-testallprops-domprefixes
351 | */
352 | (function(e,t,n){function x(e){f.cssText=e}function T(e,t){return x(prefixes.join(e+";")+(t||""))}function N(e,t){return typeof e===t}function C(e,t){return!!~(""+e).indexOf(t)}function k(e,t){for(var r in e){var i=e[r];if(!C(i,"-")&&f[i]!==n){return t=="pfx"?i:true}}return false}function L(e,t,r){for(var i in e){var s=t[e[i]];if(s!==n){if(r===false)return e[i];if(N(s,"function")){return s.bind(r||t)}return s}}return false}function A(e,t,n){var r=e.charAt(0).toUpperCase()+e.slice(1),i=(e+" "+p.join(r+" ")+r).split(" ");if(N(t,"string")||N(t,"undefined")){return k(i,t)}else{i=(e+" "+d.join(r+" ")+r).split(" ");return L(i,t,n)}}var r="2.8.2",i={},s=true,o=t.documentElement,u="modernizr",a=t.createElement(u),f=a.style,l,c={}.toString,h="Webkit Moz O ms",p=h.split(" "),d=h.toLowerCase().split(" "),v={},m={},g={},y=[],b=y.slice,w,E={}.hasOwnProperty,S;if(!N(E,"undefined")&&!N(E.call,"undefined")){S=function(e,t){return E.call(e,t)}}else{S=function(e,t){return t in e&&N(e.constructor.prototype[t],"undefined")}}if(!Function.prototype.bind){Function.prototype.bind=function(t){var n=this;if(typeof n!="function"){throw new TypeError}var r=b.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e;var o=n.apply(s,r.concat(b.call(arguments)));if(Object(o)===o){return o}return s}else{return n.apply(t,r.concat(b.call(arguments)))}};return i}}v["flexbox"]=function(){return A("flexWrap")};v["csstransforms"]=function(){return!!A("transform")};for(var O in v){if(S(v,O)){w=O.toLowerCase();i[w]=v[O]();y.push((i[w]?"":"no-")+w)}}i.addTest=function(e,t){if(typeof e=="object"){for(var r in e){if(S(e,r)){i.addTest(r,e[r])}}}else{e=e.toLowerCase();if(i[e]!==n){return i}t=typeof t=="function"?t():t;if(typeof s!=="undefined"&&s){o.className+=" "+(t?"":"no-")+e}i[e]=t}return i};x("");a=l=null;(function(e,t){function c(e,t){var n=e.createElement("p"),r=e.getElementsByTagName("head")[0]||e.documentElement;n.innerHTML="x";return r.insertBefore(n.lastChild,r.firstChild)}function h(){var e=y.elements;return typeof e=="string"?e.split(" "):e}function p(e){var t=f[e[u]];if(!t){t={};a++;e[u]=a;f[a]=t}return t}function d(e,n,r){if(!n){n=t}if(l){return n.createElement(e)}if(!r){r=p(n)}var o;if(r.cache[e]){o=r.cache[e].cloneNode()}else if(s.test(e)){o=(r.cache[e]=r.createElem(e)).cloneNode()}else{o=r.createElem(e)}return o.canHaveChildren&&!i.test(e)&&!o.tagUrn?r.frag.appendChild(o):o}function v(e,n){if(!e){e=t}if(l){return e.createDocumentFragment()}n=n||p(e);var r=n.frag.cloneNode(),i=0,s=h(),o=s.length;for(;i";o="hidden"in e;l=e.childNodes.length==1||function(){t.createElement("a");var e=t.createDocumentFragment();return typeof e.cloneNode=="undefined"||typeof e.createDocumentFragment=="undefined"||typeof e.createElement=="undefined"}()}catch(n){o=true;l=true}})();var y={elements:r.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:n,shivCSS:r.shivCSS!==false,supportsUnknownElements:l,shivMethods:r.shivMethods!==false,type:"default",shivDocument:g,createElement:d,createDocumentFragment:v};e.html5=y;g(t)})(this,t);i._version=r;i._domPrefixes=d;i._cssomPrefixes=p;i.testProp=function(e){return k([e])};i.testAllProps=A;o.className=o.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(s?" js "+y.join(" "):"");return i})(this,this.document)
--------------------------------------------------------------------------------
/dist/ocModal.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ocmodal - An angularJS modal directive / service
3 | * @version v0.1.12
4 | * @link https://github.com/ocombe/ocModal
5 | * @license MIT
6 | * @author Olivier Combe
7 | */
8 | !function(){"use strict";var e=angular.module("oc.modal",[]);e.factory("$ocModal",["$rootScope","$controller","$location","$timeout","$compile","$sniffer","$q",function(e,n,t,o,a,r,i){var l,c=angular.element(document.body),s=angular.element(''),u=angular.element('
'),d={},p=[];u.css("display","none"),u.append(s),c.append(u),s.on("click",function(n){angular.element(n.target).hasClass("modal-backdrop")&&e.$apply(function(){v.closeOnEsc()})});var f=function(e){var n=0,t=angular.isString(e)?e.split(/\s*,\s*/):[];return angular.forEach(t,function(e){n=Math.max(parseFloat(e)||0,n)}),n},m=function(e){var n=0;if(r.transitions||r.animations){var t="animation",o="transition",a=r.vendorPrefix+"Animation",i=r.vendorPrefix+"Transition",l="Duration",c="Delay",s="IterationCount",u=1;angular.forEach(e,function(e){if(e.nodeType==u){var r=window.getComputedStyle(e)||{},d=Math.max(f(r[o+c]),f(r[i+c])),p=Math.max(f(r[t+c]),f(r[a+c])),m=Math.max(f(r[o+l]),f(r[i+l])),v=Math.max(f(r[t+l]),f(r[a+l]));v>0&&(v*=Math.max(parseInt(r[t+s])||0,parseInt(r[a+s])||0,1)),n=Math.max(p+v,d+m,n)}})}return 1e3*n};angular.element(document).on("keyup",function(n){27==n.keyCode&&p.length>0&&(n.stopPropagation(),e.$apply(function(){v.closeOnEsc(p[p.length-1])}))});var v={waitingForOpen:!1,getOpenedModals:function(){return p},register:function(e){d[e.id||"_default"]=e},remove:function(e){delete d[e||"_default"]},open:function(t){"string"==typeof t&&(t=t.match("<")?{template:t}:{url:t});var r=d[t.id||"_default"];if(!r)return s.append(a('
')(e)),void o(function(){v.open(t)});if(r&&-1!==p.indexOf(t.id||"_default")){if(v.waitingForOpen)return;return v.waitingForOpen=!0,void v.close(t.id).then(function(){v.open(t)})}if(!v.waitingForOpen)if(0===p.length)l=document.body.style.overflow,document.body.style.overflow="hidden",u.css("display","block");else for(var i=0,f=p.length;f>i;i++){var m=d[p[i]].$element;d[p[i]].baseZIndex=m.css("z-index"),m.css("z-index","-1"),m.addClass("no-backdrop")}v.waitingForOpen=!1,p.push(t.id||"_default"),r.params=t,r.$scope.customClass=r.params.cls,e.$digest(),c[0].offsetWidth,o(function(){r.$scope.modalShow=!0},100),"function"==typeof r.params.onOpen&&r.params.onOpen();var h=r.$scope.$on("$includeContentLoaded",function(e){r.params.init&&!r.params.isolate&&angular.extend(e.targetScope,r.params.init),"string"==typeof r.params.controller&&n(r.params.controller,{$scope:e.targetScope,$init:r.params.init,$ocModalParams:r.params}),h()});if(r.params.template)r.$scope.modalTemplate=r.params.template;else{if(!r.params.url)throw"You need to define a template or an url";r.$scope.modalUrl=r.params.url}"function"==typeof callback&&r.$scope.callbacksList.push(callback)},closeOnEsc:function(e){return d[e||p[p.length-1]].params.closeOnEsc!==!1?v.close(e):void 0},close:function(e){var n,t=i.defer();n="string"==typeof e&&-1!==p.indexOf(e)?Array.prototype.slice.call(arguments,1):arguments,("undefined"==typeof e||-1===p.indexOf(e))&&(e=p[p.length-1]);var a=d[e||p[p.length-1]];if(a&&a.$scope.modalShow===!0){var r=m(angular.element(a.$element[0].querySelector(".modal-content")));o(function(){a.$scope.modalShow=!1,o(function(){if(a.$scope.$destroy(),a.$element.remove(),a.callbacksList=[],p.splice(p.indexOf(e||p[p.length-1]),1),0===p.length)v.waitingForOpen||(document.body.style.overflow=l,u.css("display","none"));else{var o=d[p[p.length-1]];o.$element.css("z-index",o.baseZIndex),o.$element.removeClass("no-backdrop")}"function"==typeof a.params.onClose&&a.params.onClose.apply(void 0,n),t.resolve()},r)})}else t.resolve();return t.promise}};return v}]),e.directive("ocModal",["$ocModal","$compile","$timeout",function(e,n,t){return{restrict:"AE",replace:!0,scope:!0,template:'',link:function(t,o,a){var r,i=a.ocModal;t.closeModal=function(){var n=Array.prototype.slice.call(arguments);n.unshift(i),e.close.apply(void 0,n)},e.register({id:i,$scope:t,$element:o}),o.on("$destroy",function(){e.remove(i)}),t.$watch("modalTemplate",function(e,a){"undefined"!=typeof e&&(r||(r=angular.element(o.children()[1])),r.append(n(e)(t)),t.$emit("$includeContentLoaded"))})}}}]),e.directive("ocModalOpen",["$ocModal",function(e){return{restrict:"A",require:"?modal",link:function(n,t,o){t.on("click touchstart",function(t){t.preventDefault(),t.stopPropagation();var a=n.$new(),r=a.$eval(o.ocModalOpen);if(r){if("number"==typeof r?r={url:o.ocModalOpen}:"string"==typeof r&&(r={url:r}),!r.url)throw"You need to set the modal url";n.$apply(function(){e.open(r)})}})}}}]),e.directive("ocModalClose",["$ocModal",function(e){return{restrict:"A",require:"?modal",link:function(n,t,o){t.on("click touchstart",function(t){t.preventDefault(),t.stopPropagation(),n.$apply(function(){if(o.ocModalClose)var t=n.$new().$eval(o.ocModalClose);e.close(t)})})}}}])}(),function(e,n,t){function o(e){y.cssText=e}function a(e,n){return typeof e===n}function r(e,n){return!!~(""+e).indexOf(n)}function i(e,n){for(var o in e){var a=e[o];if(!r(a,"-")&&y[a]!==t)return"pfx"==n?a:!0}return!1}function l(e,n,o){for(var r in e){var i=n[e[r]];if(i!==t)return o===!1?e[r]:a(i,"function")?i.bind(o||n):i}return!1}function c(e,n,t){var o=e.charAt(0).toUpperCase()+e.slice(1),r=(e+" "+b.join(o+" ")+o).split(" ");return a(n,"string")||a(n,"undefined")?i(r,n):(r=(e+" "+x.join(o+" ")+o).split(" "),l(r,n,t))}var s,u,d,p="2.8.2",f={},m=!0,v=n.documentElement,h="modernizr",g=n.createElement(h),y=g.style,$=({}.toString,"Webkit Moz O ms"),b=$.split(" "),x=$.toLowerCase().split(" "),w={},C=[],E=C.slice,M={}.hasOwnProperty;d=a(M,"undefined")||a(M.call,"undefined")?function(e,n){return n in e&&a(e.constructor.prototype[n],"undefined")}:function(e,n){return M.call(e,n)},Function.prototype.bind||(Function.prototype.bind=function(e){var n=this;if("function"!=typeof n)throw new TypeError;var t=E.call(arguments,1),o=function(){if(this instanceof o){var a=function(){};a.prototype=n.prototype;var r=new a,i=n.apply(r,t.concat(E.call(arguments)));return Object(i)===i?i:r}return n.apply(e,t.concat(E.call(arguments)))};return o}),w.flexbox=function(){return c("flexWrap")},w.csstransforms=function(){return!!c("transform")};for(var k in w)d(w,k)&&(u=k.toLowerCase(),f[u]=w[k](),C.push((f[u]?"":"no-")+u));return f.addTest=function(e,n){if("object"==typeof e)for(var o in e)d(e,o)&&f.addTest(o,e[o]);else{if(e=e.toLowerCase(),f[e]!==t)return f;n="function"==typeof n?n():n,"undefined"!=typeof m&&m&&(v.className+=" "+(n?"":"no-")+e),f[e]=n}return f},o(""),g=s=null,function(e,n){function t(e,n){var t=e.createElement("p"),o=e.getElementsByTagName("head")[0]||e.documentElement;return t.innerHTML="x",o.insertBefore(t.lastChild,o.firstChild)}function o(){var e=y.elements;return"string"==typeof e?e.split(" "):e}function a(e){var n=g[e[v]];return n||(n={},h++,e[v]=h,g[h]=n),n}function r(e,t,o){if(t||(t=n),u)return t.createElement(e);o||(o=a(t));var r;return r=o.cache[e]?o.cache[e].cloneNode():m.test(e)?(o.cache[e]=o.createElem(e)).cloneNode():o.createElem(e),!r.canHaveChildren||f.test(e)||r.tagUrn?r:o.frag.appendChild(r)}function i(e,t){if(e||(e=n),u)return e.createDocumentFragment();t=t||a(e);for(var r=t.frag.cloneNode(),i=0,l=o(),c=l.length;c>i;i++)r.createElement(l[i]);return r}function l(e,n){n.cache||(n.cache={},n.createElem=e.createElement,n.createFrag=e.createDocumentFragment,n.frag=n.createFrag()),e.createElement=function(t){return y.shivMethods?r(t,e,n):n.createElem(t)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+o().join().replace(/[\w\-]+/g,function(e){return n.createElem(e),n.frag.createElement(e),'c("'+e+'")'})+");return n}")(y,n.frag)}function c(e){e||(e=n);var o=a(e);return!y.shivCSS||s||o.hasCSS||(o.hasCSS=!!t(e,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),u||l(e,o),e}var s,u,d="3.7.0",p=e.html5||{},f=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,m=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",h=0,g={};!function(){try{var e=n.createElement("a");e.innerHTML=" ",s="hidden"in e,u=1==e.childNodes.length||function(){n.createElement("a");var e=n.createDocumentFragment();return"undefined"==typeof e.cloneNode||"undefined"==typeof e.createDocumentFragment||"undefined"==typeof e.createElement}()}catch(t){s=!0,u=!0}}();var y={elements:p.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:d,shivCSS:p.shivCSS!==!1,supportsUnknownElements:u,shivMethods:p.shivMethods!==!1,type:"default",shivDocument:c,createElement:r,createDocumentFragment:i};e.html5=y,c(n)}(this,n),f._version=p,f._domPrefixes=x,f._cssomPrefixes=b,f.testProp=function(e){return i([e])},f.testAllProps=c,v.className=v.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(m?" js "+C.join(" "):""),f}(this,this.document);
--------------------------------------------------------------------------------
/dist/scss/_animations.scss:
--------------------------------------------------------------------------------
1 | .modal .modal-dialog .modal-content {
2 | &.fade-in {
3 | @include transition(opacity 0.5s);
4 | opacity: 0;
5 |
6 | &.opened {
7 | opacity: 1;
8 | }
9 | }
10 | &.slide-down {
11 | @include transition(opacity 0.5s, transform 0.5s);
12 | @include transform(translateY(-20%));
13 | opacity: 0;
14 |
15 | &.slide-down.opened {
16 | @include transform(translateY(0%));
17 | opacity: 1;
18 | }
19 | }
20 |
21 | &.scale {
22 | @include transform(scale(0.7));
23 | @include transition(transform 0.5s, opacity 0.5s);
24 | opacity: 0;
25 |
26 | &.opened {
27 | @include transform(scale(1));
28 | opacity: 1;
29 | }
30 | }
31 |
32 | &.fall {
33 | @include transform-style(preserve-3d);
34 | @include transform(translateZ(600px) rotateX(20deg));
35 | @include transition(transform 0.3s ease-in, opacity 0.3s ease-in);
36 | opacity: 0;
37 |
38 | &.opened {
39 | @include transform(translateZ(0) rotateX(0deg));
40 | opacity: 1;
41 | }
42 | }
43 |
44 | &.flip-horizontal {
45 | @include transform-style(preserve-3d);
46 | @include transform(rotateY(-70deg));
47 | @include transition(transform 0.3s ease-in, opacity 0.3s ease-in);
48 | opacity: 0;
49 |
50 | &.opened {
51 | @include transform(rotateY(0deg));
52 | opacity: 1;
53 | }
54 | }
55 |
56 | &.flip-vertical {
57 | @include transform-style(preserve-3d);
58 | @include transform(rotateX(-70deg));
59 | @include transition(transform 0.3s, opacity 0.3s);
60 | opacity: 0;
61 |
62 | &.opened {
63 | @include transform(rotateX(0deg));
64 | opacity: 1;
65 | }
66 | }
67 |
68 | &.super-scaled {
69 | @include transform(scale(2));
70 | @include transition(transform 0.5s, opacity 0.5s);
71 | opacity: 0;
72 |
73 | &.opened {
74 | @include transform(scale(1));
75 | opacity: 1;
76 | }
77 | }
78 |
79 | &.slit {
80 | @include transform-style(preserve-3d);
81 | @include transition(opacity 0.5s);
82 | opacity: 0;
83 |
84 | &.opened {
85 | opacity: 1;
86 | @include transform(translateZ(-3000px) rotateY(90deg));
87 | @include animation(slit .7s forwards ease-out);
88 | }
89 | }
90 | }
91 |
92 | @-webkit-keyframes slit {
93 | 50% { -webkit-transform: translateZ(-250px) rotateY(89deg); -webkit-animation-timing-function: ease-out;}
94 | 100% { -webkit-transform: translateZ(0) rotateY(0deg); }
95 | }
96 |
97 | @-moz-keyframes slit {
98 | 50% { -moz-transform: translateZ(-250px) rotateY(89deg); opacity: .5; -moz-animation-timing-function: ease-out;}
99 | 100% { -moz-transform: translateZ(0) rotateY(0deg); }
100 | }
101 |
102 | @keyframes slit {
103 | 50% { transform: translateZ(-250px) rotateY(89deg); animation-timing-function: ease-in;}
104 | 100% { transform: translateZ(0) rotateY(0deg); }
105 | }
--------------------------------------------------------------------------------
/dist/scss/_modal.scss:
--------------------------------------------------------------------------------
1 | @mixin opacity($opacity) {
2 | opacity: $opacity;
3 | // IE8 filter
4 | $opacity-ie: ($opacity * 100);
5 | filter: #{alpha(opacity=$opacity-ie)};
6 | }
7 |
8 | .noOverflow {
9 | overflow: hidden;
10 | }
11 |
12 | .modal-wrapper {
13 | z-index: $zindex-modal;
14 | position: fixed;
15 |
16 | .modal-backdrop {
17 | width: 100%;
18 | height: 100%;
19 | @include opacity($modal-backdrop-opacity);
20 | }
21 | }
22 |
23 | .modal {
24 | display: block;
25 | overflow: auto;
26 | text-align: center;
27 |
28 | .modal-dialog {
29 | z-index: $zindex-modal + 10;
30 | width: auto;
31 | text-align: left; /* on rétablit l'alignement du texte */
32 | @include perspective(1300px);
33 | max-width: 100%;
34 |
35 | &.no-backdrop .modal-backdrop {
36 | display: none;
37 | }
38 |
39 | .modal-content {
40 | z-index: $zindex-modal;
41 | border-radius: $modal-border-radius;
42 | width: 600px;
43 | padding: 10px;
44 | max-width: 100%;
45 | margin: 0;
46 | }
47 | }
48 | }
49 |
50 | .flexbox {
51 | .modal {
52 | & > .modal-backdrop {
53 | display: none;
54 | }
55 | .modal-dialog {
56 | @include display(flex);
57 | @include align-items(center);
58 | @include justify-content(center);
59 | position: absolute;
60 | width: 100%;
61 | min-height: 100%;
62 | height: 100%; // required by IE10+ to center vertically
63 | margin: 0;
64 | padding: 10px;
65 | max-height: initial;
66 | }
67 | }
68 | }
69 |
70 | .no-flexbox {
71 | .modal-dialog {
72 | @include transform(translate(-50%, -50%));
73 | position: absolute;
74 | left: 50%;
75 | top: 50%;
76 | margin: 0;
77 | padding: 10px;
78 | max-height: 100%;
79 |
80 | .modal-backdrop {
81 | display: none;
82 | }
83 | }
84 | &.no-csstransforms {
85 | .modal-dialog {
86 | left: auto;
87 | top: auto;
88 | margin: auto;
89 | }
90 | }
91 | }
92 |
93 | // IE7 support
94 | // Styles that make popup look nicer in old IE
95 | .lt-ie8 {
96 | .modal-content {
97 | display: inline;
98 | zoom: 1;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/dist/scss/_no-bootstrap.scss:
--------------------------------------------------------------------------------
1 | // Bootstrap variables & mixins
2 | @mixin transition-transform($transition...) {
3 | -webkit-transition: -webkit-transform $transition;
4 | -moz-transition: -moz-transform $transition;
5 | -o-transition: -o-transform $transition;
6 | transition: transform $transition;
7 | }
8 |
9 | // Box sizing
10 | @mixin box-sizing($boxmodel) {
11 | -webkit-box-sizing: $boxmodel;
12 | -moz-box-sizing: $boxmodel;
13 | box-sizing: $boxmodel;
14 | }
15 |
16 | // Translate
17 | @mixin translate($x, $y) {
18 | -webkit-transform: translate($x, $y);
19 | -ms-transform: translate($x, $y); // IE9+
20 | transform: translate($x, $y);
21 | }
22 |
23 | // Box shadow
24 | @mixin box-shadow($shadow...) {
25 | -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1
26 | box-shadow: $shadow;
27 | }
28 |
29 | // Opacity
30 | @mixin opacity($opacity) {
31 | opacity: $opacity;
32 | // IE8 filter
33 | $opacity-ie: ($opacity * 100);
34 | filter: #{alpha(opacity=$opacity-ie)};
35 | }
36 |
37 | // Clearfix
38 | // Source: http://nicolasgallagher.com/micro-clearfix-hack/
39 | //
40 | // For modern browsers
41 | // 1. The space content is one way to avoid an Opera bug when the
42 | // contenteditable attribute is included anywhere else in the document.
43 | // Otherwise it causes space to appear at the top and bottom of elements
44 | // that are clearfixed.
45 | // 2. The use of `table` rather than `block` is only necessary if using
46 | // `:before` to contain the top-margins of child elements.
47 | @mixin clearfix() {
48 | &:before,
49 | &:after {
50 | content: " "; /* 1 */
51 | display: table; /* 2 */
52 | }
53 | &:after {
54 | clear: both;
55 | }
56 | }
57 |
58 | $screen-sm: 768px !default;
59 | $screen-sm-min: $screen-sm !default;
60 | $border-radius-base: 4px !default;
61 | $border-radius-large: 6px !default;
62 | $border-radius-small: 3px !default;
63 | $line-height-base: 1.428571429 !default; // 20/14
64 | $modal-title-line-height: $line-height-base !default;
65 |
66 | // Others
67 | *,
68 | *:before,
69 | *:after {
70 | @include box-sizing(border-box);
71 | }
72 |
73 | //
74 | // Modals
75 | // --------------------------------------------------
76 |
77 | // .modal-open - body class for killing the scroll
78 | // .modal - container to scroll within
79 | // .modal-dialog - positioning shell for the actual modal
80 | // .modal-content - actual modal w/ bg and corners and shit
81 |
82 | // Kill the scroll on the body
83 | .modal-open {
84 | overflow: hidden;
85 | }
86 |
87 | // Container that the modal scrolls within
88 | .modal {
89 | display: none;
90 | overflow: auto;
91 | overflow-y: scroll;
92 | position: fixed;
93 | top: 0;
94 | right: 0;
95 | bottom: 0;
96 | left: 0;
97 | z-index: $zindex-modal-background;
98 |
99 | // When fading in the modal, animate it to slide down
100 | &.fade .modal-dialog {
101 | @include translate(0, -25%);
102 | @include transition-transform(0.3s ease-out);
103 | }
104 | &.in .modal-dialog { @include translate(0, 0)}
105 | }
106 |
107 | // Shell div to position the modal with bottom padding
108 | .modal-dialog {
109 | position: relative;
110 | margin-left: auto;
111 | margin-right: auto;
112 | width: auto;
113 | padding: 10px;
114 | z-index: ($zindex-modal-background + 10);
115 | }
116 |
117 | // Actual modal
118 | .modal-content {
119 | position: relative;
120 | background-color: $modal-content-bg;
121 | border: 1px solid $modal-content-fallback-border-color; //old browsers fallback (ie8 etc)
122 | border: 1px solid $modal-content-border-color;
123 | border-radius: $border-radius-large;
124 | @include box-shadow(0 3px 9px rgba(0,0,0,.5));
125 | background-clip: padding-box;
126 | // Remove focus outline from opened modal
127 | outline: none;
128 | }
129 |
130 | // Modal background
131 | .modal-backdrop {
132 | position: fixed;
133 | top: 0;
134 | right: 0;
135 | bottom: 0;
136 | left: 0;
137 | z-index: ($zindex-modal-background - 10);
138 | background-color: $modal-backdrop-bg;
139 | // Fade for backdrop
140 | &.fade { @include opacity(0); }
141 | &.in { @include opacity(.5); }
142 | }
143 |
144 | // Modal header
145 | // Top section of the modal w/ title and dismiss
146 | .modal-header {
147 | padding: $modal-title-padding;
148 | border-bottom: 1px solid $modal-header-border-color;
149 | min-height: ($modal-title-padding + $modal-title-line-height);
150 | }
151 | // Close icon
152 | .modal-header .close {
153 | margin-top: -2px;
154 | }
155 |
156 | // Title text within header
157 | .modal-title {
158 | margin: 0;
159 | line-height: $modal-title-line-height;
160 | }
161 |
162 | // Modal body
163 | // Where all modal content resides (sibling of .modal-header and .modal-footer)
164 | .modal-body {
165 | position: relative;
166 | padding: $modal-inner-padding;
167 | }
168 |
169 | // Footer (for actions)
170 | .modal-footer {
171 | margin-top: 15px;
172 | padding: ($modal-inner-padding - 1) $modal-inner-padding $modal-inner-padding;
173 | text-align: right; // right align buttons
174 | border-top: 1px solid $modal-footer-border-color;
175 | @include clearfix(); // clear it in case folks use .pull-* classes on buttons
176 |
177 | // Properly space out buttons
178 | .btn + .btn {
179 | margin-left: 5px;
180 | margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs
181 | }
182 | // but override that for button groups
183 | .btn-group .btn + .btn {
184 | margin-left: -1px;
185 | }
186 | // and override it for block buttons as well
187 | .btn-block + .btn-block {
188 | margin-left: 0;
189 | }
190 | }
191 |
192 | // Scale up the modal
193 | @media screen and (min-width: $screen-sm-min) {
194 | .modal-dialog {
195 | width: 600px;
196 | padding-top: 30px;
197 | padding-bottom: 30px;
198 | }
199 | .modal-content {
200 | @include box-shadow(0 5px 15px rgba(0,0,0,.5));
201 | }
202 | }
--------------------------------------------------------------------------------
/dist/scss/_variables.scss:
--------------------------------------------------------------------------------
1 | $modal-backdrop-bg: #CCCCCC !default; // Color of overlay
2 | $modal-backdrop-opacity: 0.8 !default; // opacity of overlay
3 | $modal-border-radius: 2px;
4 | $modal-header-border-color: transparent !default;
5 | $close-button-color: #000;
6 | $zindex-modal-background: 1040 !default;
7 | $zindex-modal: 1050 !default;
8 | $modal-inner-padding: 20px !default;
9 | $modal-title-padding: 15px !default;
10 | $modal-content-bg: #fff !default;
11 | $modal-content-border-color: rgba(0, 0, 0, .2) !default;
12 | $modal-content-fallback-border-color: #999 !default;
13 | $modal-backdrop-bg: #000 !default;
14 | $modal-header-border-color: #e5e5e5 !default;
15 | $modal-footer-border-color: $modal-header-border-color !default;
--------------------------------------------------------------------------------
/dist/scss/ocModal.animations.scss:
--------------------------------------------------------------------------------
1 | @import "../../node_modules/bourbon/app/assets/stylesheets/_bourbon.scss";
2 |
3 | @import "animations";
--------------------------------------------------------------------------------
/dist/scss/ocModal.full.scss:
--------------------------------------------------------------------------------
1 | @import "../../node_modules/bourbon/app/assets/stylesheets/_bourbon.scss";
2 |
3 | @import "variables";
4 | @import "no-bootstrap";
5 | @import "modal";
--------------------------------------------------------------------------------
/dist/scss/ocModal.light.scss:
--------------------------------------------------------------------------------
1 | @import "../../node_modules/bourbon/app/assets/stylesheets/_bourbon.scss";
2 |
3 | @import "variables";
4 | @import "modal";
--------------------------------------------------------------------------------
/example/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var App = angular.module('app', ['oc.modal']);
4 |
5 | App.controller('AppCtrl', ['$scope', '$ocModal', function($scope, $ocModal) {
6 | $ocModal.open({
7 | url: 'partials/modal.html',
8 | cls: 'test fade-in',
9 | onOpen: function() {
10 | console.log('modal1 opened from url');
11 | }
12 | })
13 |
14 |
15 | $ocModal.open({
16 | id: 'tempModal',
17 | template: '{{ testVar }}
',
18 | controller: 'TestCtrl',
19 | cls: 'slide-down',
20 | onClose: function(a, b) {
21 | console.log('on close callback:', a, b);
22 | },
23 | init: {
24 | testVar: 'Close this or wait 5s'
25 | }
26 | })
27 | }]);
28 |
29 | App.controller('TestCtrl', ['$scope', '$ocModal', '$timeout', function($scope, $ocModal, $timeout) {
30 | $timeout(function() {
31 | if($ocModal.getOpenedModals().indexOf('tempModal') !== -1) {
32 | $ocModal.close('tempModal', 'var a', 'var b');
33 | }
34 | }, 5000);
35 | }]);
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Default
11 | Test open
12 |
13 | Transitions :
14 | fade-in
15 | slide-down
16 | scale
17 | fall
18 | flip horizontal
19 | flip vertical
20 | super-scaled
21 | slit
22 |
23 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/example/ocModal.animations.css:
--------------------------------------------------------------------------------
1 | .modal .modal-dialog .modal-content.fade-in {
2 | -webkit-transition: opacity 0.5s;
3 | -moz-transition: opacity 0.5s;
4 | transition: opacity 0.5s;
5 | opacity: 0; }
6 | .modal .modal-dialog .modal-content.fade-in.opened {
7 | opacity: 1; }
8 |
9 | .modal .modal-dialog .modal-content.slide-down {
10 | -webkit-transition: opacity, -webkit-transform;
11 | -moz-transition: opacity, -moz-transform;
12 | transition: opacity, transform;
13 | -webkit-transform: translateY(-20%);
14 | -moz-transform: translateY(-20%);
15 | -ms-transform: translateY(-20%);
16 | -o-transform: translateY(-20%);
17 | transform: translateY(-20%);
18 | opacity: 0; }
19 | .modal .modal-dialog .modal-content.slide-down.slide-down.opened {
20 | -webkit-transform: translateY(0%);
21 | -moz-transform: translateY(0%);
22 | -ms-transform: translateY(0%);
23 | -o-transform: translateY(0%);
24 | transform: translateY(0%);
25 | opacity: 1; }
26 |
27 | .modal .modal-dialog .modal-content.scale {
28 | -webkit-transform: scale(0.7);
29 | -moz-transform: scale(0.7);
30 | -ms-transform: scale(0.7);
31 | -o-transform: scale(0.7);
32 | transform: scale(0.7);
33 | -webkit-transition: -webkit-transform, opacity;
34 | -moz-transition: -moz-transform, opacity;
35 | transition: transform, opacity;
36 | opacity: 0; }
37 | .modal .modal-dialog .modal-content.scale.opened {
38 | -webkit-transform: scale(1);
39 | -moz-transform: scale(1);
40 | -ms-transform: scale(1);
41 | -o-transform: scale(1);
42 | transform: scale(1);
43 | opacity: 1; }
44 |
45 | .modal .modal-dialog .modal-content.fall {
46 | -webkit-transform-style: preserve-3d;
47 | -moz-transform-style: preserve-3d;
48 | -ms-transform-style: preserve-3d;
49 | -o-transform-style: preserve-3d;
50 | transform-style: preserve-3d;
51 | -webkit-transform: translateZ(600px) rotateX(20deg);
52 | -moz-transform: translateZ(600px) rotateX(20deg);
53 | -ms-transform: translateZ(600px) rotateX(20deg);
54 | -o-transform: translateZ(600px) rotateX(20deg);
55 | transform: translateZ(600px) rotateX(20deg);
56 | -webkit-transition: -webkit-transform, opacity;
57 | -moz-transition: -moz-transform, opacity;
58 | transition: transform, opacity;
59 | opacity: 0; }
60 | .modal .modal-dialog .modal-content.fall.opened {
61 | -webkit-transform: translateZ(0) rotateX(0deg);
62 | -moz-transform: translateZ(0) rotateX(0deg);
63 | -ms-transform: translateZ(0) rotateX(0deg);
64 | -o-transform: translateZ(0) rotateX(0deg);
65 | transform: translateZ(0) rotateX(0deg);
66 | opacity: 1; }
67 |
68 | .modal .modal-dialog .modal-content.flip-horizontal {
69 | -webkit-transform-style: preserve-3d;
70 | -moz-transform-style: preserve-3d;
71 | -ms-transform-style: preserve-3d;
72 | -o-transform-style: preserve-3d;
73 | transform-style: preserve-3d;
74 | -webkit-transform: rotateY(-70deg);
75 | -moz-transform: rotateY(-70deg);
76 | -ms-transform: rotateY(-70deg);
77 | -o-transform: rotateY(-70deg);
78 | transform: rotateY(-70deg);
79 | -webkit-transition: -webkit-transform, opacity;
80 | -moz-transition: -moz-transform, opacity;
81 | transition: transform, opacity;
82 | opacity: 0; }
83 | .modal .modal-dialog .modal-content.flip-horizontal.opened {
84 | -webkit-transform: rotateY(0deg);
85 | -moz-transform: rotateY(0deg);
86 | -ms-transform: rotateY(0deg);
87 | -o-transform: rotateY(0deg);
88 | transform: rotateY(0deg);
89 | opacity: 1; }
90 |
91 | .modal .modal-dialog .modal-content.flip-vertical {
92 | -webkit-transform-style: preserve-3d;
93 | -moz-transform-style: preserve-3d;
94 | -ms-transform-style: preserve-3d;
95 | -o-transform-style: preserve-3d;
96 | transform-style: preserve-3d;
97 | -webkit-transform: rotateX(-70deg);
98 | -moz-transform: rotateX(-70deg);
99 | -ms-transform: rotateX(-70deg);
100 | -o-transform: rotateX(-70deg);
101 | transform: rotateX(-70deg);
102 | -webkit-transition: -webkit-transform, opacity;
103 | -moz-transition: -moz-transform, opacity;
104 | transition: transform, opacity;
105 | opacity: 0; }
106 | .modal .modal-dialog .modal-content.flip-vertical.opened {
107 | -webkit-transform: rotateX(0deg);
108 | -moz-transform: rotateX(0deg);
109 | -ms-transform: rotateX(0deg);
110 | -o-transform: rotateX(0deg);
111 | transform: rotateX(0deg);
112 | opacity: 1; }
113 |
114 | .modal .modal-dialog .modal-content.super-scaled {
115 | -webkit-transform: scale(2);
116 | -moz-transform: scale(2);
117 | -ms-transform: scale(2);
118 | -o-transform: scale(2);
119 | transform: scale(2);
120 | -webkit-transition: -webkit-transform, opacity;
121 | -moz-transition: -moz-transform, opacity;
122 | transition: transform, opacity;
123 | opacity: 0; }
124 | .modal .modal-dialog .modal-content.super-scaled.opened {
125 | -webkit-transform: scale(1);
126 | -moz-transform: scale(1);
127 | -ms-transform: scale(1);
128 | -o-transform: scale(1);
129 | transform: scale(1);
130 | opacity: 1; }
131 |
132 | .modal .modal-dialog .modal-content.slit {
133 | -webkit-transform-style: preserve-3d;
134 | -moz-transform-style: preserve-3d;
135 | -ms-transform-style: preserve-3d;
136 | -o-transform-style: preserve-3d;
137 | transform-style: preserve-3d;
138 | -webkit-transition: opacity 0.5s;
139 | -moz-transition: opacity 0.5s;
140 | transition: opacity 0.5s;
141 | opacity: 0; }
142 | .modal .modal-dialog .modal-content.slit.opened {
143 | opacity: 1;
144 | -webkit-transform: translateZ(-3000px) rotateY(90deg);
145 | -moz-transform: translateZ(-3000px) rotateY(90deg);
146 | -ms-transform: translateZ(-3000px) rotateY(90deg);
147 | -o-transform: translateZ(-3000px) rotateY(90deg);
148 | transform: translateZ(-3000px) rotateY(90deg);
149 | -webkit-animation: slit 0.7s forwards ease-out;
150 | -moz-animation: slit 0.7s forwards ease-out;
151 | animation: slit 0.7s forwards ease-out; }
152 |
153 | @-webkit-keyframes slit {
154 | 50% {
155 | -webkit-transform: translateZ(-250px) rotateY(89deg);
156 | -webkit-animation-timing-function: ease-out; }
157 | 100% {
158 | -webkit-transform: translateZ(0) rotateY(0deg); } }
159 |
160 | @-moz-keyframes slit {
161 | 50% {
162 | -moz-transform: translateZ(-250px) rotateY(89deg);
163 | opacity: .5;
164 | -moz-animation-timing-function: ease-out; }
165 | 100% {
166 | -moz-transform: translateZ(0) rotateY(0deg); } }
167 |
168 | @keyframes slit {
169 | 50% {
170 | transform: translateZ(-250px) rotateY(89deg);
171 | animation-timing-function: ease-in; }
172 | 100% {
173 | transform: translateZ(0) rotateY(0deg); } }
174 |
--------------------------------------------------------------------------------
/example/ocModal.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ocmodal - An angularJS modal directive / service
3 | * @version v0.1.12
4 | * @link https://github.com/ocombe/ocModal
5 | * @license MIT
6 | * @author Olivier Combe
7 | */
8 | (function() {
9 | 'use strict';
10 |
11 | var ocModal = angular.module('oc.modal', []);
12 |
13 | ocModal.factory('$ocModal', ['$rootScope', '$controller', '$location', '$timeout', '$compile', '$sniffer', '$q', function($rootScope, $controller, $location, $timeout, $compile, $sniffer, $q) {
14 | var $body = angular.element(document.body),
15 | $dialogsWrapper = angular.element(''),
16 | $modalWrapper = angular.element(
17 | '
'
18 | ),
19 | modals = {},
20 | openedModals = [],
21 | baseOverflow;
22 |
23 | // include the modal in DOM at start for animations
24 | $modalWrapper.css('display', 'none');
25 | $modalWrapper.append($dialogsWrapper);
26 | $body.append($modalWrapper);
27 | $dialogsWrapper.on('click', function(e) {
28 | if(angular.element(e.target).hasClass('modal-backdrop')) { // only if clicked on backdrop
29 | $rootScope.$apply(function() {
30 | self.closeOnEsc();
31 | });
32 | }
33 | });
34 |
35 | var parseMaxTime = function parseMaxTime(str) {
36 | var total = 0, values = angular.isString(str) ? str.split(/\s*,\s*/) : [];
37 | angular.forEach(values, function(value) {
38 | total = Math.max(parseFloat(value) || 0, total);
39 | });
40 | return total;
41 | };
42 |
43 | var getAnimDuration = function getDuration($element) {
44 | var duration = 0;
45 | if(($sniffer.transitions || $sniffer.animations)) {
46 | //one day all browsers will have these properties
47 | var w3cAnimationProp = 'animation';
48 | var w3cTransitionProp = 'transition';
49 |
50 | //but some still use vendor-prefixed styles
51 | var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation';
52 | var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
53 |
54 | var durationKey = 'Duration',
55 | delayKey = 'Delay',
56 | animationIterationCountKey = 'IterationCount';
57 |
58 | //we want all the styles defined before and after
59 | var ELEMENT_NODE = 1;
60 | angular.forEach($element, function(element) {
61 | if(element.nodeType == ELEMENT_NODE) {
62 | var elementStyles = window.getComputedStyle(element) || {};
63 |
64 | var transitionDelay = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + delayKey]),
65 | parseMaxTime(elementStyles[vendorTransitionProp + delayKey]));
66 |
67 | var animationDelay = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + delayKey]),
68 | parseMaxTime(elementStyles[vendorAnimationProp + delayKey]));
69 |
70 | var transitionDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]),
71 | parseMaxTime(elementStyles[vendorTransitionProp + durationKey]));
72 |
73 | var animationDuration = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + durationKey]),
74 | parseMaxTime(elementStyles[vendorAnimationProp + durationKey]));
75 |
76 | if(animationDuration > 0) {
77 | animationDuration *= Math.max(parseInt(elementStyles[w3cAnimationProp + animationIterationCountKey]) || 0,
78 | parseInt(elementStyles[vendorAnimationProp + animationIterationCountKey]) || 0, 1);
79 | }
80 |
81 | duration = Math.max(animationDelay + animationDuration, transitionDelay + transitionDuration, duration);
82 | }
83 | });
84 | }
85 |
86 | return duration * 1000;
87 | };
88 |
89 | angular.element(document).on('keyup', function(e) {
90 | if (e.keyCode == 27 && openedModals.length > 0) {
91 | e.stopPropagation();
92 | $rootScope.$apply(function() {
93 | self.closeOnEsc(openedModals[openedModals.length - 1]);
94 | });
95 | }
96 | });
97 |
98 | var self = {
99 | waitingForOpen: false,
100 |
101 | getOpenedModals: function() {
102 | return openedModals;
103 | },
104 |
105 | register: function(params) {
106 | modals[params.id || '_default'] = params;
107 | },
108 |
109 | remove: function(id) {
110 | delete modals[id || '_default'];
111 | },
112 |
113 | open: function(opt) {
114 | if(typeof opt === 'string') {
115 | if(opt.match('<')) { // if html code
116 | opt = {
117 | template: opt
118 | }
119 | } else {
120 | opt = {
121 | url: opt
122 | }
123 | }
124 | }
125 | var modal = modals[opt.id || '_default'];
126 | if(!modal) {
127 | $dialogsWrapper.append($compile('
')($rootScope));
128 | $timeout(function() { // let the ng-include detect that it's now empty
129 | self.open(opt);
130 | });
131 | return;
132 | } else if(modal && openedModals.indexOf(opt.id || '_default') !== -1) { // if modal already opened
133 | if(self.waitingForOpen) {
134 | return;
135 | }
136 | self.waitingForOpen = true;
137 | self.close(opt.id).then(function() {
138 | self.open(opt);
139 | });
140 | return;
141 | }
142 | // ok let's open the modal
143 | if(!self.waitingForOpen) {
144 | if(openedModals.length === 0) { // if no modal opened
145 | baseOverflow = document.body.style.overflow;
146 | document.body.style.overflow = 'hidden';
147 | $modalWrapper.css('display', 'block');
148 | } else {
149 | for(var i = 0, len = openedModals.length; i < len; i++) {
150 | var $e = modals[openedModals[i]].$element;
151 | modals[openedModals[i]].baseZIndex = $e.css('z-index');
152 | $e.css('z-index', '-1');
153 | $e.addClass('no-backdrop');
154 | }
155 | }
156 | }
157 | self.waitingForOpen = false;
158 | openedModals.push(opt.id || '_default');
159 | modal.params = opt;
160 | modal.$scope.customClass = modal.params.cls;
161 |
162 | // timeout for animations (if any)
163 | $rootScope.$digest();
164 | $body[0].offsetWidth; // force paint to be sure the element is in the page
165 | $timeout(function() {
166 | modal.$scope.modalShow = true;
167 | }, 100);
168 |
169 | if(typeof modal.params.onOpen === 'function') {
170 | modal.params.onOpen();
171 | }
172 |
173 | var off = modal.$scope.$on('$includeContentLoaded', function(event) { // on view load
174 | if(modal.params.init && !modal.params.isolate) {
175 | angular.extend(event.targetScope, modal.params.init);
176 | }
177 | if(typeof modal.params.controller === 'string') {
178 | $controller(modal.params.controller, {$scope: event.targetScope, $init: modal.params.init, $ocModalParams: modal.params}); // inject controller
179 | }
180 | off();
181 | });
182 |
183 | if(modal.params.template) {
184 | modal.$scope.modalTemplate = modal.params.template; // load the view
185 | } else if(modal.params.url) {
186 | modal.$scope.modalUrl = modal.params.url; // load the view
187 | } else {
188 | throw "You need to define a template or an url";
189 | return;
190 | }
191 |
192 | if(typeof callback === 'function') {
193 | modal.$scope.callbacksList.push(callback);
194 | }
195 | },
196 |
197 | closeOnEsc: function(id) {
198 | if(modals[id || openedModals[openedModals.length -1]].params.closeOnEsc !== false) {
199 | return self.close(id);
200 | }
201 | },
202 |
203 | close: function(id) {
204 | var args,
205 | deferred = $q.defer();
206 | if(typeof id === 'string' && openedModals.indexOf(id) !== -1) {
207 | args = Array.prototype.slice.call(arguments, 1);
208 | } else {
209 | args = arguments;
210 | }
211 | if(typeof id === 'undefined' || openedModals.indexOf(id) === -1) {
212 | id = openedModals[openedModals.length -1];
213 | }
214 | var modal = modals[id || openedModals[openedModals.length -1]];
215 | if(modal && modal.$scope.modalShow === true) { // if the modal is opened
216 | var animDuration = getAnimDuration(angular.element(modal.$element[0].querySelector('.modal-content')));
217 | $timeout(function() {
218 | modal.$scope.modalShow = false;
219 |
220 | $timeout(function() {
221 | modal.$scope.$destroy();
222 | modal.$element.remove(); // destroy the modal
223 |
224 | modal.callbacksList = []; // forget all callbacks
225 | openedModals.splice(openedModals.indexOf(id || openedModals[openedModals.length -1]), 1);
226 | if(openedModals.length === 0) { // if no modal left opened
227 | if(!self.waitingForOpen) { // in case the current modal is closed because another opened with the same id (avoid backdrop flickering in firefox)
228 | document.body.style.overflow = baseOverflow; // restore the body overflow
229 | $modalWrapper.css('display', 'none');
230 | }
231 | } else {
232 | var topModal = modals[openedModals[openedModals.length - 1]];
233 | topModal.$element.css('z-index', topModal.baseZIndex);
234 | topModal.$element.removeClass('no-backdrop');
235 | }
236 | if(typeof modal.params.onClose === 'function') {
237 | modal.params.onClose.apply(undefined, args);
238 | }
239 |
240 | deferred.resolve();
241 | }, animDuration);
242 | });
243 | } else {
244 | deferred.resolve();
245 | }
246 | return deferred.promise;
247 | }
248 | };
249 |
250 | return self;
251 | }]);
252 |
253 | ocModal.directive('ocModal', ['$ocModal', '$compile', '$timeout', function($ocModal, $compile, $timeout) {
254 | return {
255 | restrict: 'AE',
256 | replace: true,
257 | scope: true,
258 | template:
259 | '' +
260 | '
' +
261 | '
' +
262 | '
' +
263 | '
',
264 |
265 | link: function link($scope, $element, $attrs) {
266 | var id = $attrs.ocModal,
267 | $templateWrapper;
268 |
269 | $scope.closeModal = function() {
270 | var args = Array.prototype.slice.call(arguments);
271 | args.unshift(id);
272 | $ocModal.close.apply(undefined, args);
273 | };
274 |
275 | $ocModal.register({
276 | id: id,
277 | $scope: $scope,
278 | $element: $element
279 | });
280 |
281 | $element.on('$destroy', function() {
282 | $ocModal.remove(id);
283 | });
284 |
285 | $scope.$watch('modalTemplate', function(newVal, oldVal) {
286 | if(typeof newVal !== 'undefined') {
287 | if(!$templateWrapper) {
288 | $templateWrapper = angular.element($element.children()[1]);
289 | }
290 | $templateWrapper.append($compile(newVal)($scope));
291 | $scope.$emit('$includeContentLoaded');
292 | }
293 | });
294 | }
295 | }
296 | }]);
297 |
298 | ocModal.directive('ocModalOpen', ['$ocModal', function($ocModal) {
299 | return {
300 | restrict: 'A',
301 | require: '?modal',
302 | link: function($scope, $element, $attrs) {
303 | $element.on('click touchstart', function(e) {
304 | e.preventDefault();
305 | e.stopPropagation();
306 | var newScope = $scope.$new();
307 | var params = newScope.$eval($attrs.ocModalOpen);
308 | if(params) {
309 | if(typeof params === "number") {
310 | params = { url: $attrs.ocModalOpen };
311 | } else if(typeof params === "string") {
312 | params = { url: params };
313 | }
314 | if(!params.url) {
315 | throw "You need to set the modal url";
316 | }
317 | $scope.$apply(function() {
318 | $ocModal.open(params);
319 | });
320 | }
321 | });
322 | }
323 | };
324 | }]);
325 |
326 | ocModal.directive('ocModalClose', ['$ocModal', function($ocModal) {
327 | return {
328 | restrict: 'A',
329 | require: '?modal',
330 | link: function($scope, $element, $attrs) {
331 | $element.on('click touchstart', function(e) {
332 | e.preventDefault();
333 | e.stopPropagation();
334 | $scope.$apply(function() {
335 | if($attrs.ocModalClose) {
336 | var params = $scope.$new().$eval($attrs.ocModalClose);
337 | }
338 | $ocModal.close(params);
339 | });
340 | });
341 | }
342 | };
343 | }]);
344 |
345 |
346 |
347 | })();
348 |
349 | /* Modernizr 2.8.2 (Custom Build) | MIT & BSD
350 | * Build: http://modernizr.com/download/#-flexbox-flexboxlegacy-cssclasses-testprop-testallprops-domprefixes
351 | */
352 | (function(e,t,n){function x(e){f.cssText=e}function T(e,t){return x(prefixes.join(e+";")+(t||""))}function N(e,t){return typeof e===t}function C(e,t){return!!~(""+e).indexOf(t)}function k(e,t){for(var r in e){var i=e[r];if(!C(i,"-")&&f[i]!==n){return t=="pfx"?i:true}}return false}function L(e,t,r){for(var i in e){var s=t[e[i]];if(s!==n){if(r===false)return e[i];if(N(s,"function")){return s.bind(r||t)}return s}}return false}function A(e,t,n){var r=e.charAt(0).toUpperCase()+e.slice(1),i=(e+" "+p.join(r+" ")+r).split(" ");if(N(t,"string")||N(t,"undefined")){return k(i,t)}else{i=(e+" "+d.join(r+" ")+r).split(" ");return L(i,t,n)}}var r="2.8.2",i={},s=true,o=t.documentElement,u="modernizr",a=t.createElement(u),f=a.style,l,c={}.toString,h="Webkit Moz O ms",p=h.split(" "),d=h.toLowerCase().split(" "),v={},m={},g={},y=[],b=y.slice,w,E={}.hasOwnProperty,S;if(!N(E,"undefined")&&!N(E.call,"undefined")){S=function(e,t){return E.call(e,t)}}else{S=function(e,t){return t in e&&N(e.constructor.prototype[t],"undefined")}}if(!Function.prototype.bind){Function.prototype.bind=function(t){var n=this;if(typeof n!="function"){throw new TypeError}var r=b.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e;var o=n.apply(s,r.concat(b.call(arguments)));if(Object(o)===o){return o}return s}else{return n.apply(t,r.concat(b.call(arguments)))}};return i}}v["flexbox"]=function(){return A("flexWrap")};v["csstransforms"]=function(){return!!A("transform")};for(var O in v){if(S(v,O)){w=O.toLowerCase();i[w]=v[O]();y.push((i[w]?"":"no-")+w)}}i.addTest=function(e,t){if(typeof e=="object"){for(var r in e){if(S(e,r)){i.addTest(r,e[r])}}}else{e=e.toLowerCase();if(i[e]!==n){return i}t=typeof t=="function"?t():t;if(typeof s!=="undefined"&&s){o.className+=" "+(t?"":"no-")+e}i[e]=t}return i};x("");a=l=null;(function(e,t){function c(e,t){var n=e.createElement("p"),r=e.getElementsByTagName("head")[0]||e.documentElement;n.innerHTML="x";return r.insertBefore(n.lastChild,r.firstChild)}function h(){var e=y.elements;return typeof e=="string"?e.split(" "):e}function p(e){var t=f[e[u]];if(!t){t={};a++;e[u]=a;f[a]=t}return t}function d(e,n,r){if(!n){n=t}if(l){return n.createElement(e)}if(!r){r=p(n)}var o;if(r.cache[e]){o=r.cache[e].cloneNode()}else if(s.test(e)){o=(r.cache[e]=r.createElem(e)).cloneNode()}else{o=r.createElem(e)}return o.canHaveChildren&&!i.test(e)&&!o.tagUrn?r.frag.appendChild(o):o}function v(e,n){if(!e){e=t}if(l){return e.createDocumentFragment()}n=n||p(e);var r=n.frag.cloneNode(),i=0,s=h(),o=s.length;for(;i";o="hidden"in e;l=e.childNodes.length==1||function(){t.createElement("a");var e=t.createDocumentFragment();return typeof e.cloneNode=="undefined"||typeof e.createDocumentFragment=="undefined"||typeof e.createElement=="undefined"}()}catch(n){o=true;l=true}})();var y={elements:r.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:n,shivCSS:r.shivCSS!==false,supportsUnknownElements:l,shivMethods:r.shivMethods!==false,type:"default",shivDocument:g,createElement:d,createDocumentFragment:v};e.html5=y;g(t)})(this,t);i._version=r;i._domPrefixes=d;i._cssomPrefixes=p;i.testProp=function(e){return k([e])};i.testAllProps=A;o.className=o.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(s?" js "+y.join(" "):"");return i})(this,this.document)
--------------------------------------------------------------------------------
/example/ocModal.light.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | .noOverflow {
3 | overflow: hidden; }
4 |
5 | .modal-wrapper {
6 | z-index: 1050;
7 | position: fixed; }
8 | .modal-wrapper .modal-backdrop {
9 | width: 100%;
10 | height: 100%;
11 | opacity: 0.8;
12 | filter: alpha(opacity=80); }
13 |
14 | .modal {
15 | display: block;
16 | overflow: auto;
17 | text-align: center; }
18 | .modal .modal-dialog {
19 | z-index: 1060;
20 | width: auto;
21 | text-align: left;
22 | /* on rétablit l'alignement du texte */
23 | -webkit-perspective: 1300px;
24 | -moz-perspective: 1300px;
25 | perspective: 1300px;
26 | max-width: 100%; }
27 | .modal .modal-dialog.no-backdrop .modal-backdrop {
28 | display: none; }
29 | .modal .modal-dialog .modal-content {
30 | z-index: 1050;
31 | border-radius: 2px;
32 | width: 600px;
33 | padding: 10px;
34 | max-width: 100%;
35 | margin: 0; }
36 |
37 | .flexbox .modal > .modal-backdrop {
38 | display: none; }
39 |
40 | .flexbox .modal .modal-dialog {
41 | display: -webkit-box;
42 | display: -moz-box;
43 | display: box;
44 | display: -webkit-flex;
45 | display: -moz-flex;
46 | display: -ms-flexbox;
47 | display: flex;
48 | -webkit-box-align: center;
49 | -moz-box-align: center;
50 | box-align: center;
51 | -webkit-align-items: center;
52 | -moz-align-items: center;
53 | -ms-align-items: center;
54 | -o-align-items: center;
55 | align-items: center;
56 | -ms-flex-align: center;
57 | -webkit-box-pack: center;
58 | -moz-box-pack: center;
59 | box-pack: center;
60 | -webkit-justify-content: center;
61 | -moz-justify-content: center;
62 | -ms-justify-content: center;
63 | -o-justify-content: center;
64 | justify-content: center;
65 | -ms-flex-pack: center;
66 | position: absolute;
67 | width: 100%;
68 | min-height: 100%;
69 | height: 100%;
70 | margin: 0;
71 | padding: 10px;
72 | max-height: initial; }
73 |
74 | .no-flexbox .modal-dialog {
75 | -webkit-transform: translate(-50%, -50%);
76 | -moz-transform: translate(-50%, -50%);
77 | -ms-transform: translate(-50%, -50%);
78 | -o-transform: translate(-50%, -50%);
79 | transform: translate(-50%, -50%);
80 | position: absolute;
81 | left: 50%;
82 | top: 50%;
83 | margin: 0;
84 | padding: 10px;
85 | max-height: 100%; }
86 | .no-flexbox .modal-dialog .modal-backdrop {
87 | display: none; }
88 |
89 | .no-flexbox.no-csstransforms .modal-dialog {
90 | left: auto;
91 | top: auto;
92 | margin: auto; }
93 |
94 | .lt-ie8 .modal-content {
95 | display: inline;
96 | zoom: 1; }
97 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 |
3 | gulp.task('sass', function() {
4 | var sass = require('gulp-sass'),
5 | minifyCSS = require('gulp-minify-css'),
6 | rename = require('gulp-rename');
7 |
8 | gulp.src('./src/scss/*.scss')
9 | .pipe(gulp.dest('./dist/scss'));
10 |
11 | // light
12 | gulp.src('./src/scss/ocModal.light.scss')
13 | .pipe(sass({
14 | includePaths: [
15 | 'node_modules/bourbon/app/assets/stylesheets/'
16 | ]
17 | }))
18 | .pipe(gulp.dest('./dist/css'))
19 | .pipe(gulp.dest('./example'))
20 | .pipe(minifyCSS())
21 | .pipe(rename({suffix: '.min'}))
22 | .pipe(gulp.dest('./dist/css'));
23 |
24 | // full (bootstrap included)
25 | gulp.src('./src/scss/ocModal.full.scss')
26 | .pipe(sass())
27 | .pipe(gulp.dest('./dist/css'))
28 | .pipe(minifyCSS())
29 | .pipe(rename({suffix: '.min'}))
30 | .pipe(gulp.dest('./dist/css'));
31 |
32 | // full (bootstrap included)
33 | gulp.src('./src/scss/ocModal.animations.scss')
34 | .pipe(sass())
35 | .pipe(gulp.dest('./dist/css'))
36 | .pipe(gulp.dest('./example'))
37 | .pipe(minifyCSS())
38 | .pipe(rename({suffix: '.min'}))
39 | .pipe(gulp.dest('./dist/css'));
40 | });
41 |
42 | var build = function(newVer) {
43 | var rename = require('gulp-rename'),
44 | uglify = require('gulp-uglify'),
45 | header = require('gulp-header'),
46 | pkg = require('./package.json'),
47 | banner = ['/**',
48 | ' * <%= pkg.name %> - <%= pkg.description %>',
49 | ' * @version v<%= version %>',
50 | ' * @link <%= pkg.homepage %>',
51 | ' * @license <%= pkg.license %>',
52 | ' * @author <%= pkg.author %>',
53 | ' */',
54 | ''].join('\n');
55 |
56 | return gulp.src('src/ocModal.js')
57 | .pipe(header(banner, {pkg: pkg, version: newVer || pkg.version}))
58 | .pipe(gulp.dest('dist'))
59 | .pipe(gulp.dest('example'))
60 | .pipe(uglify())
61 | .pipe(header(banner, {pkg: pkg, version: newVer || pkg.version}))
62 | .pipe(rename({suffix: '.min'}))
63 | .pipe(gulp.dest('dist'));
64 | };
65 |
66 | gulp.task('build', ['sass'], function() {
67 | return build();
68 | });
69 |
70 | var promptBump = function(callback) {
71 | var prompt = require('gulp-prompt'),
72 | semver = require('semver'),
73 | pkg = require('./package.json');
74 |
75 | return gulp.src('')
76 | .pipe(prompt.prompt({
77 | type: 'list',
78 | name: 'bump',
79 | message: 'What type of version bump would you like to do ? (current version is ' + pkg.version + ')',
80 | choices: [
81 | 'patch (' + pkg.version + ' --> ' + semver.inc(pkg.version, 'patch') + ')',
82 | 'minor (' + pkg.version + ' --> ' + semver.inc(pkg.version, 'minor') + ')',
83 | 'major (' + pkg.version + ' --> ' + semver.inc(pkg.version, 'major') + ')',
84 | 'none (exit)'
85 | ]
86 | }, function(res) {
87 | var newVer;
88 | if(res.bump.match(/^patch/)) {
89 | newVer = semver.inc(pkg.version, 'patch');
90 | } else if(res.bump.match(/^minor/)) {
91 | newVer = semver.inc(pkg.version, 'minor');
92 | } else if(res.bump.match(/^major/)) {
93 | newVer = semver.inc(pkg.version, 'major');
94 | }
95 | if(newVer && typeof callback === 'function') {
96 | return callback(newVer);
97 | } else {
98 | return;
99 | }
100 | }));
101 | };
102 |
103 | var makeChangelog = function(newVer) {
104 | var streamqueue = require('streamqueue'),
105 | stream = streamqueue({objectMode: true}),
106 | exec = require('gulp-exec'),
107 | concat = require('gulp-concat'),
108 | clean = require('gulp-clean');
109 |
110 | stream.queue(gulp.src('').pipe(exec('node ./src/changelog.js ' + newVer, {pipeStdout: true})));
111 | stream.queue(gulp.src('CHANGELOG.md').pipe(clean()));
112 |
113 | return stream.done()
114 | .pipe(concat('CHANGELOG.md'))
115 | .pipe(gulp.dest('./'));
116 | };
117 |
118 | // Make changelog
119 | gulp.task('changelog', function(event) {
120 | var prompt = require('gulp-prompt');
121 | var semver = require('semver');
122 |
123 | return promptBump(makeChangelog);
124 | });
125 |
126 | gulp.task('release', ['sass'], function() {
127 | var jeditor = require("gulp-json-editor");
128 |
129 | return promptBump(function(newVer) {
130 | var streamqueue = require('streamqueue');
131 | var stream = streamqueue({objectMode: true});
132 |
133 | // make the changelog
134 | stream.queue(makeChangelog(newVer));
135 |
136 | // update the main project version number
137 | stream.queue(
138 | gulp.src('package.json')
139 | .pipe(jeditor({
140 | 'version': newVer
141 | }))
142 | .pipe(gulp.dest("./"))
143 | );
144 |
145 | stream.queue(
146 | gulp.src('bower.json')
147 | .pipe(jeditor({
148 | 'version': newVer
149 | }))
150 | .pipe(gulp.dest("./"))
151 | );
152 |
153 | stream.queue(build(newVer));
154 |
155 | return stream.done();
156 | });
157 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ocmodal",
3 | "version": "0.1.12",
4 | "description": "An angularJS modal directive / service",
5 | "author": "Olivier Combe ",
6 | "license": "MIT",
7 | "main": "dist/ocModal.js",
8 | "homepage": "https://github.com/ocombe/ocModal",
9 | "bugs": {
10 | "url": "https://github.com/ocombe/ocModal/issues"
11 | },
12 | "scripts": {
13 | "start": "static ./example/ -p 3000",
14 | "build": "gulp build"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "git://github.com/ocombe/ocModal.git"
19 | },
20 | "keywords": [
21 | "modal",
22 | "dialog",
23 | "module",
24 | "angular",
25 | "angularJS"
26 | ],
27 | "devDependencies": {
28 | "bourbon": "^4.2.6",
29 | "bower": "~1.6.5",
30 | "gulp": "~3.9.0",
31 | "gulp-clean": "^0.3.0",
32 | "gulp-concat": "~2.6.0",
33 | "gulp-exec": "~2.1.2",
34 | "gulp-header": "~1.7.1",
35 | "gulp-json-editor": "~2.2.1",
36 | "gulp-minify-css": "^1.2.1",
37 | "gulp-prompt": "~0.1.1",
38 | "gulp-rename": "^1.2.0",
39 | "gulp-sass": "^2.1.0",
40 | "gulp-uglify": "~1.4.2",
41 | "node-static": "^0.7.3",
42 | "qq": "~0.3.5",
43 | "semver": "~5.0.3",
44 | "streamqueue": "~1.1.1"
45 | }
46 | }
--------------------------------------------------------------------------------
/src/changelog.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var child = require('child_process');
4 | var fs = require('fs');
5 | var util = require('util');
6 | var q = require('qq');
7 |
8 | var GIT_LOG_CMD = 'git log --grep="%s" -E --format=%s %s..HEAD';
9 | var GIT_TAG_CMD = 'git describe --tags --abbrev=0';
10 |
11 | var HEADER_TPL = ' \n# %s (%s)\n\n';
12 | var LINK_ISSUE = '[#%s](https://github.com/ocombe/ocModal/issues/%s)';
13 | var LINK_COMMIT = '[%s](https://github.com/ocombe/ocModal/commit/%s)';
14 |
15 | var EMPTY_COMPONENT = '$$';
16 |
17 |
18 | var warn = function() {
19 | console.error('WARNING:', util.format.apply(null, arguments));
20 | };
21 |
22 |
23 | var parseRawCommit = function(raw) {
24 | if (!raw) return null;
25 |
26 | var lines = raw.split('\n');
27 | var msg = {}, match;
28 |
29 | msg.hash = lines.shift();
30 | msg.subject = lines.shift();
31 | msg.closes = [];
32 | msg.breaks = [];
33 |
34 | lines.forEach(function(line) {
35 | match = line.match(/(?:Closes|Fixes)\s#(\d+)/);
36 | if (match) msg.closes.push(parseInt(match[1]));
37 | });
38 |
39 | match = raw.match(/BREAKING CHANGE:([\s\S]*)/);
40 | if (match) {
41 | msg.breaking = match[1];
42 | }
43 |
44 | msg.body = lines.join('\n');
45 | match = msg.subject.match(/^(\w*)\s?\:\s?(.*)$/);
46 |
47 | if (!match || !match[1] || !match[2]) {
48 | warn('Incorrect message: %s %s', msg.hash, msg.subject);
49 | return null;
50 | }
51 |
52 | msg.type = match[1];
53 | // msg.component = match[2];
54 | msg.subject = match[2];
55 |
56 | return msg;
57 | };
58 |
59 |
60 | var linkToIssue = function(issue) {
61 | return util.format(LINK_ISSUE, issue, issue);
62 | };
63 |
64 |
65 | var linkToCommit = function(hash) {
66 | return util.format(LINK_COMMIT, hash.substr(0, 8), hash);
67 | };
68 |
69 |
70 | var currentDate = function() {
71 | var now = new Date();
72 | var pad = function(i) {
73 | return ('0' + i).substr(-2);
74 | };
75 |
76 | return util.format('%d-%s-%s', now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate()));
77 | };
78 |
79 |
80 | var printSection = function(stream, title, section, printCommitLinks) {
81 | printCommitLinks = printCommitLinks === undefined ? true : printCommitLinks;
82 | var components = Object.getOwnPropertyNames(section).sort();
83 |
84 | if (!components.length || section['$$'].length <= 0) return;
85 |
86 | stream.write(util.format('\n## %s\n\n', title));
87 |
88 | components.forEach(function(name) {
89 | var prefix = '-';
90 | var nested = section[name].length > 1;
91 |
92 | if (name !== EMPTY_COMPONENT) {
93 | if (nested) {
94 | stream.write(util.format('- **%s:**\n', name));
95 | prefix = ' -';
96 | } else {
97 | prefix = util.format('- **%s:**', name);
98 | }
99 | }
100 |
101 | section[name].forEach(function(commit) {
102 | if (printCommitLinks) {
103 | stream.write(util.format('%s %s\n (%s', prefix, commit.subject, linkToCommit(commit.hash)));
104 | if (commit.closes.length) {
105 | stream.write(',\n ' + commit.closes.map(linkToIssue).join(', '));
106 | }
107 | stream.write(')\n');
108 | } else {
109 | stream.write(util.format('%s %s', prefix, commit.subject));
110 | }
111 | });
112 | });
113 |
114 | stream.write('\n');
115 | };
116 |
117 |
118 | var readGitLog = function(grep, from) {
119 | var deferred = q.defer();
120 |
121 | // TODO(vojta): if it's slow, use spawn and stream it instead
122 | child.exec(util.format(GIT_LOG_CMD, grep, '%H%n%s%n%b%n==END==', from), function(code, stdout, stderr) {
123 | var commits = [];
124 |
125 | stdout.split('\n==END==\n').forEach(function(rawCommit) {
126 | var commit = parseRawCommit(rawCommit);
127 | if (commit) commits.push(commit);
128 | });
129 |
130 | deferred.resolve(commits);
131 | });
132 |
133 | return deferred.promise;
134 | };
135 |
136 |
137 | var writeChangelog = function(stream, commits, version) {
138 | var sections = {
139 | fix: {},
140 | feat: {},
141 | perf: {},
142 | docs: {},
143 | breaks: {}
144 | };
145 |
146 | sections.breaks[EMPTY_COMPONENT] = [];
147 |
148 | commits.forEach(function(commit) {
149 | var section = sections[commit.type];
150 | var component = commit.component || EMPTY_COMPONENT;
151 |
152 | if (section) {
153 | section[component] = section[component] || [];
154 | section[component].push(commit);
155 | }
156 |
157 | if (commit.breaking) {
158 | sections.breaks[component] = sections.breaks[component] || [];
159 | sections.breaks[component].push({
160 | subject: util.format("due to %s,\n %s", linkToCommit(commit.hash), commit.breaking),
161 | hash: commit.hash,
162 | closes: []
163 | });
164 | };
165 | });
166 |
167 | stream.write(util.format(HEADER_TPL, version, version, currentDate()));
168 | printSection(stream, 'Bug Fixes', sections.fix);
169 | printSection(stream, 'Features', sections.feat);
170 | printSection(stream, 'Performance Improvements', sections.perf);
171 | printSection(stream, 'Documentation', sections.docs);
172 | printSection(stream, 'Breaking Changes', sections.breaks, false);
173 | }
174 |
175 |
176 | var getPreviousTag = function() {
177 | var deferred = q.defer();
178 | child.exec(GIT_TAG_CMD, function(code, stdout, stderr) {
179 | if (code) deferred.reject('Cannot get the previous tag.');
180 | else deferred.resolve(stdout.replace('\n', ''));
181 | });
182 | return deferred.promise;
183 | };
184 |
185 |
186 | var generate = function(version, file) {
187 | getPreviousTag().then(function(tag) {
188 | // console.log('Reading git log since', tag);
189 | readGitLog('^fix|^feat|^perf|^docs|BREAKING', tag).then(function(commits) {
190 | // console.log('Parsed', commits.length, 'commits');
191 | // console.log('Generating changelog to', file || 'stdout', '(', version, ')');
192 | writeChangelog(file ? fs.createWriteStream(file) : process.stdout, commits, version);
193 | });
194 | });
195 | };
196 |
197 |
198 | // publish for testing
199 | exports.parseRawCommit = parseRawCommit;
200 |
201 | // hacky start if not run by jasmine :-D
202 | if (process.argv.join('').indexOf('jasmine-node') === -1) {
203 | generate(process.argv[2], process.argv[3]);
204 | }
--------------------------------------------------------------------------------
/src/ocModal.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | var ocModal = angular.module('oc.modal', []);
5 |
6 | ocModal.factory('$ocModal', ['$rootScope', '$controller', '$location', '$timeout', '$compile', '$sniffer', '$q', function($rootScope, $controller, $location, $timeout, $compile, $sniffer, $q) {
7 | var $body = angular.element(document.body),
8 | $dialogsWrapper = angular.element(''),
9 | $modalWrapper = angular.element(
10 | '
'
11 | ),
12 | modals = {},
13 | openedModals = [],
14 | baseOverflow;
15 |
16 | // include the modal in DOM at start for animations
17 | $modalWrapper.css('display', 'none');
18 | $modalWrapper.append($dialogsWrapper);
19 | $body.append($modalWrapper);
20 | $dialogsWrapper.on('click', function(e) {
21 | if(angular.element(e.target).hasClass('modal-backdrop')) { // only if clicked on backdrop
22 | $rootScope.$apply(function() {
23 | self.closeOnEsc();
24 | });
25 | }
26 | });
27 |
28 | var parseMaxTime = function parseMaxTime(str) {
29 | var total = 0, values = angular.isString(str) ? str.split(/\s*,\s*/) : [];
30 | angular.forEach(values, function(value) {
31 | total = Math.max(parseFloat(value) || 0, total);
32 | });
33 | return total;
34 | };
35 |
36 | var getAnimDuration = function getDuration($element) {
37 | var duration = 0;
38 | if(($sniffer.transitions || $sniffer.animations)) {
39 | //one day all browsers will have these properties
40 | var w3cAnimationProp = 'animation';
41 | var w3cTransitionProp = 'transition';
42 |
43 | //but some still use vendor-prefixed styles
44 | var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation';
45 | var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition';
46 |
47 | var durationKey = 'Duration',
48 | delayKey = 'Delay',
49 | animationIterationCountKey = 'IterationCount';
50 |
51 | //we want all the styles defined before and after
52 | var ELEMENT_NODE = 1;
53 | angular.forEach($element, function(element) {
54 | if(element.nodeType == ELEMENT_NODE) {
55 | var elementStyles = window.getComputedStyle(element) || {};
56 |
57 | var transitionDelay = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + delayKey]),
58 | parseMaxTime(elementStyles[vendorTransitionProp + delayKey]));
59 |
60 | var animationDelay = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + delayKey]),
61 | parseMaxTime(elementStyles[vendorAnimationProp + delayKey]));
62 |
63 | var transitionDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]),
64 | parseMaxTime(elementStyles[vendorTransitionProp + durationKey]));
65 |
66 | var animationDuration = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + durationKey]),
67 | parseMaxTime(elementStyles[vendorAnimationProp + durationKey]));
68 |
69 | if(animationDuration > 0) {
70 | animationDuration *= Math.max(parseInt(elementStyles[w3cAnimationProp + animationIterationCountKey]) || 0,
71 | parseInt(elementStyles[vendorAnimationProp + animationIterationCountKey]) || 0, 1);
72 | }
73 |
74 | duration = Math.max(animationDelay + animationDuration, transitionDelay + transitionDuration, duration);
75 | }
76 | });
77 | }
78 |
79 | return duration * 1000;
80 | };
81 |
82 | angular.element(document).on('keyup', function(e) {
83 | if (e.keyCode == 27 && openedModals.length > 0) {
84 | e.stopPropagation();
85 | $rootScope.$apply(function() {
86 | self.closeOnEsc(openedModals[openedModals.length - 1]);
87 | });
88 | }
89 | });
90 |
91 | var self = {
92 | waitingForOpen: false,
93 |
94 | getOpenedModals: function() {
95 | return openedModals;
96 | },
97 |
98 | register: function(params) {
99 | modals[params.id || '_default'] = params;
100 | },
101 |
102 | remove: function(id) {
103 | delete modals[id || '_default'];
104 | },
105 |
106 | open: function(opt) {
107 | if(typeof opt === 'string') {
108 | if(opt.match('<')) { // if html code
109 | opt = {
110 | template: opt
111 | }
112 | } else {
113 | opt = {
114 | url: opt
115 | }
116 | }
117 | }
118 | var modal = modals[opt.id || '_default'];
119 | if(!modal) {
120 | $dialogsWrapper.append($compile('
')($rootScope));
121 | $timeout(function() { // let the ng-include detect that it's now empty
122 | self.open(opt);
123 | });
124 | return;
125 | } else if(modal && openedModals.indexOf(opt.id || '_default') !== -1) { // if modal already opened
126 | if(self.waitingForOpen) {
127 | return;
128 | }
129 | self.waitingForOpen = true;
130 | self.close(opt.id).then(function() {
131 | self.open(opt);
132 | });
133 | return;
134 | }
135 | // ok let's open the modal
136 | if(!self.waitingForOpen) {
137 | if(openedModals.length === 0) { // if no modal opened
138 | baseOverflow = document.body.style.overflow;
139 | document.body.style.overflow = 'hidden';
140 | $modalWrapper.css('display', 'block');
141 | } else {
142 | for(var i = 0, len = openedModals.length; i < len; i++) {
143 | var $e = modals[openedModals[i]].$element;
144 | modals[openedModals[i]].baseZIndex = $e.css('z-index');
145 | $e.css('z-index', '-1');
146 | $e.addClass('no-backdrop');
147 | }
148 | }
149 | }
150 | self.waitingForOpen = false;
151 | openedModals.push(opt.id || '_default');
152 | modal.params = opt;
153 | modal.$scope.customClass = modal.params.cls;
154 |
155 | // timeout for animations (if any)
156 | $rootScope.$digest();
157 | $body[0].offsetWidth; // force paint to be sure the element is in the page
158 | $timeout(function() {
159 | modal.$scope.modalShow = true;
160 | }, 100);
161 |
162 | if(typeof modal.params.onOpen === 'function') {
163 | modal.params.onOpen();
164 | }
165 |
166 | var off = modal.$scope.$on('$includeContentLoaded', function(event) { // on view load
167 | if(modal.params.init && !modal.params.isolate) {
168 | angular.extend(event.targetScope, modal.params.init);
169 | }
170 | if(typeof modal.params.controller === 'string') {
171 | $controller(modal.params.controller, {$scope: event.targetScope, $init: modal.params.init, $ocModalParams: modal.params}); // inject controller
172 | }
173 | off();
174 | });
175 |
176 | if(modal.params.template) {
177 | modal.$scope.modalTemplate = modal.params.template; // load the view
178 | } else if(modal.params.url) {
179 | modal.$scope.modalUrl = modal.params.url; // load the view
180 | } else {
181 | throw "You need to define a template or an url";
182 | return;
183 | }
184 |
185 | if(typeof callback === 'function') {
186 | modal.$scope.callbacksList.push(callback);
187 | }
188 | },
189 |
190 | closeOnEsc: function(id) {
191 | if(modals[id || openedModals[openedModals.length -1]].params.closeOnEsc !== false) {
192 | return self.close(id);
193 | }
194 | },
195 |
196 | close: function(id) {
197 | var args,
198 | deferred = $q.defer();
199 | if(typeof id === 'string' && openedModals.indexOf(id) !== -1) {
200 | args = Array.prototype.slice.call(arguments, 1);
201 | } else {
202 | args = arguments;
203 | }
204 | if(typeof id === 'undefined' || openedModals.indexOf(id) === -1) {
205 | id = openedModals[openedModals.length -1];
206 | }
207 | var modal = modals[id || openedModals[openedModals.length -1]];
208 | if(modal && modal.$scope.modalShow === true) { // if the modal is opened
209 | var animDuration = getAnimDuration(angular.element(modal.$element[0].querySelector('.modal-content')));
210 | $timeout(function() {
211 | modal.$scope.modalShow = false;
212 |
213 | $timeout(function() {
214 | modal.$scope.$destroy();
215 | modal.$element.remove(); // destroy the modal
216 |
217 | modal.callbacksList = []; // forget all callbacks
218 | openedModals.splice(openedModals.indexOf(id || openedModals[openedModals.length -1]), 1);
219 | if(openedModals.length === 0) { // if no modal left opened
220 | if(!self.waitingForOpen) { // in case the current modal is closed because another opened with the same id (avoid backdrop flickering in firefox)
221 | document.body.style.overflow = baseOverflow; // restore the body overflow
222 | $modalWrapper.css('display', 'none');
223 | }
224 | } else {
225 | var topModal = modals[openedModals[openedModals.length - 1]];
226 | topModal.$element.css('z-index', topModal.baseZIndex);
227 | topModal.$element.removeClass('no-backdrop');
228 | }
229 | if(typeof modal.params.onClose === 'function') {
230 | modal.params.onClose.apply(undefined, args);
231 | }
232 |
233 | deferred.resolve();
234 | }, animDuration);
235 | });
236 | } else {
237 | deferred.resolve();
238 | }
239 | return deferred.promise;
240 | }
241 | };
242 |
243 | return self;
244 | }]);
245 |
246 | ocModal.directive('ocModal', ['$ocModal', '$compile', '$timeout', function($ocModal, $compile, $timeout) {
247 | return {
248 | restrict: 'AE',
249 | replace: true,
250 | scope: true,
251 | template:
252 | '' +
253 | '
' +
254 | '
' +
255 | '
' +
256 | '
',
257 |
258 | link: function link($scope, $element, $attrs) {
259 | var id = $attrs.ocModal,
260 | $templateWrapper;
261 |
262 | $scope.closeModal = function() {
263 | var args = Array.prototype.slice.call(arguments);
264 | args.unshift(id);
265 | $ocModal.close.apply(undefined, args);
266 | };
267 |
268 | $ocModal.register({
269 | id: id,
270 | $scope: $scope,
271 | $element: $element
272 | });
273 |
274 | $element.on('$destroy', function() {
275 | $ocModal.remove(id);
276 | });
277 |
278 | $scope.$watch('modalTemplate', function(newVal, oldVal) {
279 | if(typeof newVal !== 'undefined') {
280 | if(!$templateWrapper) {
281 | $templateWrapper = angular.element($element.children()[1]);
282 | }
283 | $templateWrapper.append($compile(newVal)($scope));
284 | $scope.$emit('$includeContentLoaded');
285 | }
286 | });
287 | }
288 | }
289 | }]);
290 |
291 | ocModal.directive('ocModalOpen', ['$ocModal', function($ocModal) {
292 | return {
293 | restrict: 'A',
294 | require: '?modal',
295 | link: function($scope, $element, $attrs) {
296 | $element.on('click touchstart', function(e) {
297 | e.preventDefault();
298 | e.stopPropagation();
299 | var newScope = $scope.$new();
300 | var params = newScope.$eval($attrs.ocModalOpen);
301 | if(params) {
302 | if(typeof params === "number") {
303 | params = { url: $attrs.ocModalOpen };
304 | } else if(typeof params === "string") {
305 | params = { url: params };
306 | }
307 | if(!params.url) {
308 | throw "You need to set the modal url";
309 | }
310 | $scope.$apply(function() {
311 | $ocModal.open(params);
312 | });
313 | }
314 | });
315 | }
316 | };
317 | }]);
318 |
319 | ocModal.directive('ocModalClose', ['$ocModal', function($ocModal) {
320 | return {
321 | restrict: 'A',
322 | require: '?modal',
323 | link: function($scope, $element, $attrs) {
324 | $element.on('click touchstart', function(e) {
325 | e.preventDefault();
326 | e.stopPropagation();
327 | $scope.$apply(function() {
328 | if($attrs.ocModalClose) {
329 | var params = $scope.$new().$eval($attrs.ocModalClose);
330 | }
331 | $ocModal.close(params);
332 | });
333 | });
334 | }
335 | };
336 | }]);
337 |
338 |
339 |
340 | })();
341 |
342 | /* Modernizr 2.8.2 (Custom Build) | MIT & BSD
343 | * Build: http://modernizr.com/download/#-flexbox-flexboxlegacy-cssclasses-testprop-testallprops-domprefixes
344 | */
345 | (function(e,t,n){function x(e){f.cssText=e}function T(e,t){return x(prefixes.join(e+";")+(t||""))}function N(e,t){return typeof e===t}function C(e,t){return!!~(""+e).indexOf(t)}function k(e,t){for(var r in e){var i=e[r];if(!C(i,"-")&&f[i]!==n){return t=="pfx"?i:true}}return false}function L(e,t,r){for(var i in e){var s=t[e[i]];if(s!==n){if(r===false)return e[i];if(N(s,"function")){return s.bind(r||t)}return s}}return false}function A(e,t,n){var r=e.charAt(0).toUpperCase()+e.slice(1),i=(e+" "+p.join(r+" ")+r).split(" ");if(N(t,"string")||N(t,"undefined")){return k(i,t)}else{i=(e+" "+d.join(r+" ")+r).split(" ");return L(i,t,n)}}var r="2.8.2",i={},s=true,o=t.documentElement,u="modernizr",a=t.createElement(u),f=a.style,l,c={}.toString,h="Webkit Moz O ms",p=h.split(" "),d=h.toLowerCase().split(" "),v={},m={},g={},y=[],b=y.slice,w,E={}.hasOwnProperty,S;if(!N(E,"undefined")&&!N(E.call,"undefined")){S=function(e,t){return E.call(e,t)}}else{S=function(e,t){return t in e&&N(e.constructor.prototype[t],"undefined")}}if(!Function.prototype.bind){Function.prototype.bind=function(t){var n=this;if(typeof n!="function"){throw new TypeError}var r=b.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e;var o=n.apply(s,r.concat(b.call(arguments)));if(Object(o)===o){return o}return s}else{return n.apply(t,r.concat(b.call(arguments)))}};return i}}v["flexbox"]=function(){return A("flexWrap")};v["csstransforms"]=function(){return!!A("transform")};for(var O in v){if(S(v,O)){w=O.toLowerCase();i[w]=v[O]();y.push((i[w]?"":"no-")+w)}}i.addTest=function(e,t){if(typeof e=="object"){for(var r in e){if(S(e,r)){i.addTest(r,e[r])}}}else{e=e.toLowerCase();if(i[e]!==n){return i}t=typeof t=="function"?t():t;if(typeof s!=="undefined"&&s){o.className+=" "+(t?"":"no-")+e}i[e]=t}return i};x("");a=l=null;(function(e,t){function c(e,t){var n=e.createElement("p"),r=e.getElementsByTagName("head")[0]||e.documentElement;n.innerHTML="x";return r.insertBefore(n.lastChild,r.firstChild)}function h(){var e=y.elements;return typeof e=="string"?e.split(" "):e}function p(e){var t=f[e[u]];if(!t){t={};a++;e[u]=a;f[a]=t}return t}function d(e,n,r){if(!n){n=t}if(l){return n.createElement(e)}if(!r){r=p(n)}var o;if(r.cache[e]){o=r.cache[e].cloneNode()}else if(s.test(e)){o=(r.cache[e]=r.createElem(e)).cloneNode()}else{o=r.createElem(e)}return o.canHaveChildren&&!i.test(e)&&!o.tagUrn?r.frag.appendChild(o):o}function v(e,n){if(!e){e=t}if(l){return e.createDocumentFragment()}n=n||p(e);var r=n.frag.cloneNode(),i=0,s=h(),o=s.length;for(;i";o="hidden"in e;l=e.childNodes.length==1||function(){t.createElement("a");var e=t.createDocumentFragment();return typeof e.cloneNode=="undefined"||typeof e.createDocumentFragment=="undefined"||typeof e.createElement=="undefined"}()}catch(n){o=true;l=true}})();var y={elements:r.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:n,shivCSS:r.shivCSS!==false,supportsUnknownElements:l,shivMethods:r.shivMethods!==false,type:"default",shivDocument:g,createElement:d,createDocumentFragment:v};e.html5=y;g(t)})(this,t);i._version=r;i._domPrefixes=d;i._cssomPrefixes=p;i.testProp=function(e){return k([e])};i.testAllProps=A;o.className=o.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(s?" js "+y.join(" "):"");return i})(this,this.document)
--------------------------------------------------------------------------------
/src/scss/_animations.scss:
--------------------------------------------------------------------------------
1 | .modal .modal-dialog .modal-content {
2 | &.fade-in {
3 | @include transition(opacity 0.5s);
4 | opacity: 0;
5 |
6 | &.opened {
7 | opacity: 1;
8 | }
9 | }
10 | &.slide-down {
11 | @include transition(opacity 0.5s, transform 0.5s);
12 | @include transform(translateY(-20%));
13 | opacity: 0;
14 |
15 | &.slide-down.opened {
16 | @include transform(translateY(0%));
17 | opacity: 1;
18 | }
19 | }
20 |
21 | &.scale {
22 | @include transform(scale(0.7));
23 | @include transition(transform 0.5s, opacity 0.5s);
24 | opacity: 0;
25 |
26 | &.opened {
27 | @include transform(scale(1));
28 | opacity: 1;
29 | }
30 | }
31 |
32 | &.fall {
33 | @include transform-style(preserve-3d);
34 | @include transform(translateZ(600px) rotateX(20deg));
35 | @include transition(transform 0.3s ease-in, opacity 0.3s ease-in);
36 | opacity: 0;
37 |
38 | &.opened {
39 | @include transform(translateZ(0) rotateX(0deg));
40 | opacity: 1;
41 | }
42 | }
43 |
44 | &.flip-horizontal {
45 | @include transform-style(preserve-3d);
46 | @include transform(rotateY(-70deg));
47 | @include transition(transform 0.3s ease-in, opacity 0.3s ease-in);
48 | opacity: 0;
49 |
50 | &.opened {
51 | @include transform(rotateY(0deg));
52 | opacity: 1;
53 | }
54 | }
55 |
56 | &.flip-vertical {
57 | @include transform-style(preserve-3d);
58 | @include transform(rotateX(-70deg));
59 | @include transition(transform 0.3s, opacity 0.3s);
60 | opacity: 0;
61 |
62 | &.opened {
63 | @include transform(rotateX(0deg));
64 | opacity: 1;
65 | }
66 | }
67 |
68 | &.super-scaled {
69 | @include transform(scale(2));
70 | @include transition(transform 0.5s, opacity 0.5s);
71 | opacity: 0;
72 |
73 | &.opened {
74 | @include transform(scale(1));
75 | opacity: 1;
76 | }
77 | }
78 |
79 | &.slit {
80 | @include transform-style(preserve-3d);
81 | @include transition(opacity 0.5s);
82 | opacity: 0;
83 |
84 | &.opened {
85 | opacity: 1;
86 | @include transform(translateZ(-3000px) rotateY(90deg));
87 | @include animation(slit .7s forwards ease-out);
88 | }
89 | }
90 | }
91 |
92 | @-webkit-keyframes slit {
93 | 50% { -webkit-transform: translateZ(-250px) rotateY(89deg); -webkit-animation-timing-function: ease-out;}
94 | 100% { -webkit-transform: translateZ(0) rotateY(0deg); }
95 | }
96 |
97 | @-moz-keyframes slit {
98 | 50% { -moz-transform: translateZ(-250px) rotateY(89deg); opacity: .5; -moz-animation-timing-function: ease-out;}
99 | 100% { -moz-transform: translateZ(0) rotateY(0deg); }
100 | }
101 |
102 | @keyframes slit {
103 | 50% { transform: translateZ(-250px) rotateY(89deg); animation-timing-function: ease-in;}
104 | 100% { transform: translateZ(0) rotateY(0deg); }
105 | }
--------------------------------------------------------------------------------
/src/scss/_modal.scss:
--------------------------------------------------------------------------------
1 | @mixin opacity($opacity) {
2 | opacity: $opacity;
3 | // IE8 filter
4 | $opacity-ie: ($opacity * 100);
5 | filter: #{alpha(opacity=$opacity-ie)};
6 | }
7 |
8 | .noOverflow {
9 | overflow: hidden;
10 | }
11 |
12 | .modal-wrapper {
13 | z-index: $zindex-modal;
14 | position: fixed;
15 |
16 | .modal-backdrop {
17 | width: 100%;
18 | height: 100%;
19 | @include opacity($modal-backdrop-opacity);
20 | }
21 | }
22 |
23 | .modal {
24 | display: block;
25 | overflow: auto;
26 | text-align: center;
27 |
28 | .modal-dialog {
29 | z-index: $zindex-modal + 10;
30 | width: auto;
31 | text-align: left; /* on rétablit l'alignement du texte */
32 | @include perspective(1300px);
33 | max-width: 100%;
34 |
35 | &.no-backdrop .modal-backdrop {
36 | display: none;
37 | }
38 |
39 | .modal-content {
40 | z-index: $zindex-modal;
41 | border-radius: $modal-border-radius;
42 | width: 600px;
43 | padding: 10px;
44 | max-width: 100%;
45 | margin: 0;
46 | }
47 | }
48 | }
49 |
50 | .flexbox {
51 | .modal {
52 | & > .modal-backdrop {
53 | display: none;
54 | }
55 | .modal-dialog {
56 | @include display(flex);
57 | @include align-items(center);
58 | @include justify-content(center);
59 | position: absolute;
60 | width: 100%;
61 | min-height: 100%;
62 | height: 100%; // required by IE10+ to center vertically
63 | margin: 0;
64 | padding: 10px;
65 | max-height: initial;
66 | }
67 | }
68 | }
69 |
70 | .no-flexbox {
71 | .modal-dialog {
72 | @include transform(translate(-50%, -50%));
73 | position: absolute;
74 | left: 50%;
75 | top: 50%;
76 | margin: 0;
77 | padding: 10px;
78 | max-height: 100%;
79 |
80 | .modal-backdrop {
81 | display: none;
82 | }
83 | }
84 | &.no-csstransforms {
85 | .modal-dialog {
86 | left: auto;
87 | top: auto;
88 | margin: auto;
89 | }
90 | }
91 | }
92 |
93 | // IE7 support
94 | // Styles that make popup look nicer in old IE
95 | .lt-ie8 {
96 | .modal-content {
97 | display: inline;
98 | zoom: 1;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/scss/_no-bootstrap.scss:
--------------------------------------------------------------------------------
1 | // Bootstrap variables & mixins
2 | @mixin transition-transform($transition...) {
3 | -webkit-transition: -webkit-transform $transition;
4 | -moz-transition: -moz-transform $transition;
5 | -o-transition: -o-transform $transition;
6 | transition: transform $transition;
7 | }
8 |
9 | // Box sizing
10 | @mixin box-sizing($boxmodel) {
11 | -webkit-box-sizing: $boxmodel;
12 | -moz-box-sizing: $boxmodel;
13 | box-sizing: $boxmodel;
14 | }
15 |
16 | // Translate
17 | @mixin translate($x, $y) {
18 | -webkit-transform: translate($x, $y);
19 | -ms-transform: translate($x, $y); // IE9+
20 | transform: translate($x, $y);
21 | }
22 |
23 | // Box shadow
24 | @mixin box-shadow($shadow...) {
25 | -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1
26 | box-shadow: $shadow;
27 | }
28 |
29 | // Opacity
30 | @mixin opacity($opacity) {
31 | opacity: $opacity;
32 | // IE8 filter
33 | $opacity-ie: ($opacity * 100);
34 | filter: #{alpha(opacity=$opacity-ie)};
35 | }
36 |
37 | // Clearfix
38 | // Source: http://nicolasgallagher.com/micro-clearfix-hack/
39 | //
40 | // For modern browsers
41 | // 1. The space content is one way to avoid an Opera bug when the
42 | // contenteditable attribute is included anywhere else in the document.
43 | // Otherwise it causes space to appear at the top and bottom of elements
44 | // that are clearfixed.
45 | // 2. The use of `table` rather than `block` is only necessary if using
46 | // `:before` to contain the top-margins of child elements.
47 | @mixin clearfix() {
48 | &:before,
49 | &:after {
50 | content: " "; /* 1 */
51 | display: table; /* 2 */
52 | }
53 | &:after {
54 | clear: both;
55 | }
56 | }
57 |
58 | $screen-sm: 768px !default;
59 | $screen-sm-min: $screen-sm !default;
60 | $border-radius-base: 4px !default;
61 | $border-radius-large: 6px !default;
62 | $border-radius-small: 3px !default;
63 | $line-height-base: 1.428571429 !default; // 20/14
64 | $modal-title-line-height: $line-height-base !default;
65 |
66 | // Others
67 | *,
68 | *:before,
69 | *:after {
70 | @include box-sizing(border-box);
71 | }
72 |
73 | //
74 | // Modals
75 | // --------------------------------------------------
76 |
77 | // .modal-open - body class for killing the scroll
78 | // .modal - container to scroll within
79 | // .modal-dialog - positioning shell for the actual modal
80 | // .modal-content - actual modal w/ bg and corners and shit
81 |
82 | // Kill the scroll on the body
83 | .modal-open {
84 | overflow: hidden;
85 | }
86 |
87 | // Container that the modal scrolls within
88 | .modal {
89 | display: none;
90 | overflow: auto;
91 | overflow-y: scroll;
92 | position: fixed;
93 | top: 0;
94 | right: 0;
95 | bottom: 0;
96 | left: 0;
97 | z-index: $zindex-modal-background;
98 |
99 | // When fading in the modal, animate it to slide down
100 | &.fade .modal-dialog {
101 | @include translate(0, -25%);
102 | @include transition-transform(0.3s ease-out);
103 | }
104 | &.in .modal-dialog { @include translate(0, 0)}
105 | }
106 |
107 | // Shell div to position the modal with bottom padding
108 | .modal-dialog {
109 | position: relative;
110 | margin-left: auto;
111 | margin-right: auto;
112 | width: auto;
113 | padding: 10px;
114 | z-index: ($zindex-modal-background + 10);
115 | }
116 |
117 | // Actual modal
118 | .modal-content {
119 | position: relative;
120 | background-color: $modal-content-bg;
121 | border: 1px solid $modal-content-fallback-border-color; //old browsers fallback (ie8 etc)
122 | border: 1px solid $modal-content-border-color;
123 | border-radius: $border-radius-large;
124 | @include box-shadow(0 3px 9px rgba(0,0,0,.5));
125 | background-clip: padding-box;
126 | // Remove focus outline from opened modal
127 | outline: none;
128 | }
129 |
130 | // Modal background
131 | .modal-backdrop {
132 | position: fixed;
133 | top: 0;
134 | right: 0;
135 | bottom: 0;
136 | left: 0;
137 | z-index: ($zindex-modal-background - 10);
138 | background-color: $modal-backdrop-bg;
139 | // Fade for backdrop
140 | &.fade { @include opacity(0); }
141 | &.in { @include opacity(.5); }
142 | }
143 |
144 | // Modal header
145 | // Top section of the modal w/ title and dismiss
146 | .modal-header {
147 | padding: $modal-title-padding;
148 | border-bottom: 1px solid $modal-header-border-color;
149 | min-height: ($modal-title-padding + $modal-title-line-height);
150 | }
151 | // Close icon
152 | .modal-header .close {
153 | margin-top: -2px;
154 | }
155 |
156 | // Title text within header
157 | .modal-title {
158 | margin: 0;
159 | line-height: $modal-title-line-height;
160 | }
161 |
162 | // Modal body
163 | // Where all modal content resides (sibling of .modal-header and .modal-footer)
164 | .modal-body {
165 | position: relative;
166 | padding: $modal-inner-padding;
167 | }
168 |
169 | // Footer (for actions)
170 | .modal-footer {
171 | margin-top: 15px;
172 | padding: ($modal-inner-padding - 1) $modal-inner-padding $modal-inner-padding;
173 | text-align: right; // right align buttons
174 | border-top: 1px solid $modal-footer-border-color;
175 | @include clearfix(); // clear it in case folks use .pull-* classes on buttons
176 |
177 | // Properly space out buttons
178 | .btn + .btn {
179 | margin-left: 5px;
180 | margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs
181 | }
182 | // but override that for button groups
183 | .btn-group .btn + .btn {
184 | margin-left: -1px;
185 | }
186 | // and override it for block buttons as well
187 | .btn-block + .btn-block {
188 | margin-left: 0;
189 | }
190 | }
191 |
192 | // Scale up the modal
193 | @media screen and (min-width: $screen-sm-min) {
194 | .modal-dialog {
195 | width: 600px;
196 | padding-top: 30px;
197 | padding-bottom: 30px;
198 | }
199 | .modal-content {
200 | @include box-shadow(0 5px 15px rgba(0,0,0,.5));
201 | }
202 | }
--------------------------------------------------------------------------------
/src/scss/_variables.scss:
--------------------------------------------------------------------------------
1 | $modal-backdrop-bg: #CCCCCC !default; // Color of overlay
2 | $modal-backdrop-opacity: 0.8 !default; // opacity of overlay
3 | $modal-border-radius: 2px;
4 | $modal-header-border-color: transparent !default;
5 | $close-button-color: #000;
6 | $zindex-modal-background: 1040 !default;
7 | $zindex-modal: 1050 !default;
8 | $modal-inner-padding: 20px !default;
9 | $modal-title-padding: 15px !default;
10 | $modal-content-bg: #fff !default;
11 | $modal-content-border-color: rgba(0, 0, 0, .2) !default;
12 | $modal-content-fallback-border-color: #999 !default;
13 | $modal-backdrop-bg: #000 !default;
14 | $modal-header-border-color: #e5e5e5 !default;
15 | $modal-footer-border-color: $modal-header-border-color !default;
--------------------------------------------------------------------------------
/src/scss/ocModal.animations.scss:
--------------------------------------------------------------------------------
1 | @import "../../node_modules/bourbon/app/assets/stylesheets/_bourbon.scss";
2 |
3 | @import "animations";
--------------------------------------------------------------------------------
/src/scss/ocModal.full.scss:
--------------------------------------------------------------------------------
1 | @import "../../node_modules/bourbon/app/assets/stylesheets/_bourbon.scss";
2 |
3 | @import "variables";
4 | @import "no-bootstrap";
5 | @import "modal";
--------------------------------------------------------------------------------
/src/scss/ocModal.light.scss:
--------------------------------------------------------------------------------
1 | @import "../../node_modules/bourbon/app/assets/stylesheets/_bourbon.scss";
2 |
3 | @import "variables";
4 | @import "modal";
--------------------------------------------------------------------------------
/src/validate-commit-msg.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * Git COMMIT-MSG hook for validating commit message
5 | * See https://docs.google.com/document/d/1rk04jEuGfk9kYzfqCuOlPTSJw3hEDZJTBN5E5f1SALo/edit
6 | *
7 | * Installation:
8 | * >> cd
9 | * >> ln -s ../../src/validate-commit-msg.js .git/hooks/commit-msg
10 | */
11 | var fs = require('fs');
12 | var util = require('util');
13 |
14 |
15 | var MAX_LENGTH = 100;
16 | var PATTERN = /^(?:fixup!\s*)?(\w*)(\(([\w\$\.\-\*/]*)\))?\: (.*)$/;
17 | var IGNORED = /^WIP\:/;
18 | var TYPES = {
19 | feat: true,
20 | fix: true,
21 | docs: true,
22 | style: true,
23 | refactor: true,
24 | perf: true,
25 | test: true,
26 | chore: true,
27 | revert: true
28 | };
29 |
30 |
31 | var error = function() {
32 | // gitx does not display it
33 | // http://gitx.lighthouseapp.com/projects/17830/tickets/294-feature-display-hook-error-message-when-hook-fails
34 | // https://groups.google.com/group/gitx/browse_thread/thread/a03bcab60844b812
35 | console.error('INVALID COMMIT MSG: ' + util.format.apply(null, arguments));
36 | };
37 |
38 |
39 | var validateMessage = function(message) {
40 | var isValid = true;
41 |
42 | if (IGNORED.test(message)) {
43 | console.log('Commit message validation ignored.');
44 | return true;
45 | }
46 |
47 | if (message.length > MAX_LENGTH) {
48 | error('is longer than %d characters !', MAX_LENGTH);
49 | isValid = false;
50 | }
51 |
52 | var match = PATTERN.exec(message);
53 |
54 | if (!match) {
55 | error('does not match "(): " ! was: ' + message);
56 | return false;
57 | }
58 |
59 | var type = match[1];
60 | var scope = match[3];
61 | var subject = match[4];
62 |
63 | if (!TYPES.hasOwnProperty(type)) {
64 | error('"%s" is not allowed type !', type);
65 | return false;
66 | }
67 |
68 | // Some more ideas, do want anything like this ?
69 | // - allow only specific scopes (eg. fix(docs) should not be allowed ?
70 | // - auto correct the type to lower case ?
71 | // - auto correct first letter of the subject to lower case ?
72 | // - auto add empty line after subject ?
73 | // - auto remove empty () ?
74 | // - auto correct typos in type ?
75 | // - store incorrect messages, so that we can learn
76 |
77 | return isValid;
78 | };
79 |
80 |
81 | var firstLineFromBuffer = function(buffer) {
82 | return buffer.toString().split('\n').shift();
83 | };
84 |
85 |
86 |
87 | // publish for testing
88 | exports.validateMessage = validateMessage;
89 |
90 | // hacky start if not run by jasmine :-D
91 | if (process.argv.join('').indexOf('jasmine-node') === -1) {
92 | var commitMsgFile = process.argv[2];
93 | var incorrectLogFile = commitMsgFile.replace('COMMIT_EDITMSG', 'logs/incorrect-commit-msgs');
94 |
95 | fs.readFile(commitMsgFile, function(err, buffer) {
96 | var msg = firstLineFromBuffer(buffer);
97 |
98 | if (!validateMessage(msg)) {
99 | fs.appendFile(incorrectLogFile, msg + '\n', function() {
100 | process.exit(1);
101 | });
102 | } else {
103 | process.exit(0);
104 | }
105 | });
106 | }
--------------------------------------------------------------------------------