Subversion Repositories bacoAlunos

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2068 es 1
 
2
(function (root, factory) {
3
    if (typeof define === 'function' && define.amd) {
4
        define(['angular'], factory);
5
    } else if (typeof module === 'object' && module.exports) {
6
        module.exports = factory(require('angular'));
7
    } else {
8
        factory(root.angular);
9
    }
10
}(this, function (angular) {
11
 
12
    angular
13
        .module('pageslide-directive', [])
14
        .directive('pageslide', ['$document', '$timeout', function ($document, $timeout) {
15
            var defaults = {};
16
 
17
 
18
            return {
19
                restrict: 'EA',
20
                transclude: false,
21
                scope: {
22
                    psOpen: '=?',
23
                    psAutoClose: '@',
24
                    psSide: '@',
25
                    psSpeed: '@',
26
                    psClass: '@',
27
                    psSize: '@',
28
                    psZindex: '@',
29
                    psPush: '@',
30
                    psContainer: '@',
31
                    psKeyListener: '@',
32
                    psBodyClass: '@',
33
                    psClickOutside: '@',
34
                    onopen: '&?',
35
                    onclose: '&?'
36
                },
37
                link: function (scope, el, attrs) {
38
 
39
                    var param = {};
40
 
41
                    param.side = scope.psSide || 'right';
42
                    param.speed = scope.psSpeed || '0.5';
43
                    param.size = scope.psSize || '300px';
44
                    param.zindex = scope.psZindex || 1000;
45
                    param.className = scope.psClass || 'ng-pageslide';
46
                    param.push = scope.psPush === 'true';
47
                    param.container = scope.psContainer || false;
48
                    param.keyListener = scope.psKeyListener === 'true';
49
                    param.bodyClass = scope.psBodyClass || false;
50
                    param.clickOutside = scope.psClickOutside !== 'false';
51
                    param.autoClose = scope.psAutoClose || false;
52
 
53
                    param.push = param.push && !param.container;
54
 
55
                    el.addClass(param.className);
56
 
57
                    /* DOM manipulation */
58
 
59
                    var content, slider, body, isOpen = false;
60
 
61
                    if (param.container) {
62
                        body = document.getElementById(param.container);
63
                    } else {
64
                        body = document.body;
65
                    }
66
 
67
                    function onBodyClick(e) {
68
                        var target = e.touches && e.touches[0] || e.target;
69
                        if(
70
                            isOpen &&
71
                            body.contains(target) &&
72
                            !slider.contains(target)
73
                        ) {
74
                            isOpen = false;
75
                            scope.psOpen = false;
76
                            scope.$apply();
77
                        }
78
 
79
                        if(scope.psOpen) {
80
                            isOpen = true;
81
                        }
82
                    }
83
 
84
                    function setBodyClass(value){
85
                        if (param.bodyClass) {
86
                            var bodyClass = param.className + '-body';
87
                            var bodyClassRe = new RegExp(bodyClass + '-closed|' + bodyClass + '-open');
88
                            body.className = body.className.replace(bodyClassRe, '');
89
                            var newBodyClassName = bodyClass + '-' + value;
90
                            if (body.className[body.className.length -1] !== ' ') {
91
                                body.className += ' ' + newBodyClassName;
92
                            } else {
93
                                body.className += newBodyClassName;
94
                            }
95
                        }
96
                    }
97
 
98
                    setBodyClass('closed');
99
 
100
                    slider = el[0];
101
 
102
                    if (slider.tagName.toLowerCase() !== 'div' &&
103
                        slider.tagName.toLowerCase() !== 'pageslide') {
104
                        throw new Error('Pageslide can only be applied to <div> or <pageslide> elements');
105
                    }
106
 
107
                    if (slider.children.length === 0) {
108
                        throw new Error('You need to have content inside the <pageslide>');
109
                    }
110
 
111
                    content = angular.element(slider.children);
112
 
113
                    body.appendChild(slider);
114
 
115
                    slider.style.zIndex = param.zindex;
116
                    slider.style.position = 'fixed';
117
                    slider.style.transitionDuration = param.speed + 's';
118
                    slider.style.webkitTransitionDuration = param.speed + 's';
119
                    slider.style.height = param.size;
120
                    slider.style.transitionProperty = 'top, bottom, left, right';
121
 
122
                    if (param.push) {
123
                        body.style.position = 'absolute';
124
                        body.style.transitionDuration = param.speed + 's';
125
                        body.style.webkitTransitionDuration = param.speed + 's';
126
                        body.style.transitionProperty = 'top, bottom, left, right';
127
                    }
128
 
129
                    if (param.container) {
130
                        slider.style.position = 'absolute';
131
                        body.style.position = 'relative';
132
                        body.style.overflow = 'hidden';
133
                    }
134
 
135
                    function onTransitionEnd() {
136
                        if (scope.psOpen) {
137
                            if (typeof scope.onopen === 'function') {
138
                                scope.onopen()();
139
                            }
140
                        } else {
141
                            if (typeof scope.onclose === 'function') {
142
                                scope.onclose()();
143
                            }
144
                        }
145
                    }
146
 
147
                    slider.addEventListener('transitionend', onTransitionEnd);
148
 
149
                    initSlider();
150
 
151
                    function initSlider() {
152
                        switch (param.side) {
153
                            case 'right':
154
                                slider.style.width = param.size;
155
                                slider.style.height = '100%';
156
                                slider.style.top = '0px';
157
                                slider.style.bottom = '0px';
158
                                slider.style.right = '0px';
159
                                break;
160
                            case 'left':
161
                                slider.style.width = param.size;
162
                                slider.style.height = '100%';
163
                                slider.style.top = '0px';
164
                                slider.style.bottom = '0px';
165
                                slider.style.left = '0px';
166
                                break;
167
                            case 'top':
168
                                slider.style.height = param.size;
169
                                slider.style.width = '100%';
170
                                slider.style.left = '0px';
171
                                slider.style.top = '0px';
172
                                slider.style.right = '0px';
173
                                break;
174
                            case 'bottom':
175
                                slider.style.height = param.size;
176
                                slider.style.width = '100%';
177
                                slider.style.bottom = '0px';
178
                                slider.style.left = '0px';
179
                                slider.style.right = '0px';
180
                                break;
181
                        }
182
                    }
183
 
184
                    function psClose(slider, param) {
185
                        switch (param.side) {
186
                            case 'right':
187
                                slider.style.right = "-" + param.size;
188
                                if (param.push) {
189
                                    body.style.right = '0px';
190
                                    body.style.left = '0px';
191
                                }
192
                                break;
193
                            case 'left':
194
                                slider.style.left = "-" + param.size;
195
                                if (param.push) {
196
                                    body.style.left = '0px';
197
                                    body.style.right = '0px';
198
                                }
199
                                break;
200
                            case 'top':
201
                                slider.style.top = "-" + param.size;
202
                                if (param.push) {
203
                                    body.style.top = '0px';
204
                                    body.style.bottom = '0px';
205
                                }
206
                                break;
207
                            case 'bottom':
208
                                slider.style.bottom = "-" + param.size;
209
                                if (param.push) {
210
                                    body.style.bottom = '0px';
211
                                    body.style.top = '0px';
212
                                }
213
                                break;
214
                        }
215
 
216
                        if (param.keyListener) {
217
                            $document.off('keydown', handleKeyDown);
218
                        }
219
 
220
                        if (param.clickOutside) {
221
                            $document.off('touchend click', onBodyClick);
222
                        }
223
                        isOpen = false;
224
                        setBodyClass('closed');
225
                        scope.psOpen = false;
226
                    }
227
 
228
                    function psOpen(slider, param) {
229
                        switch (param.side) {
230
                            case 'right':
231
                                slider.style.right = "0px";
232
                                if (param.push) {
233
                                    body.style.right = param.size;
234
                                    body.style.left = '-' + param.size;
235
                                }
236
                                break;
237
                            case 'left':
238
                                slider.style.left = "0px";
239
                                if (param.push) {
240
                                    body.style.left = param.size;
241
                                    body.style.right = '-' + param.size;
242
                                }
243
                                break;
244
                            case 'top':
245
                                slider.style.top = "0px";
246
                                if (param.push) {
247
                                    body.style.top = param.size;
248
                                    body.style.bottom = '-' + param.size;
249
                                }
250
                                break;
251
                            case 'bottom':
252
                                slider.style.bottom = "0px";
253
                                if (param.push) {
254
                                    body.style.bottom = param.size;
255
                                    body.style.top = '-' + param.size;
256
                                }
257
                                break;
258
                        }
259
 
260
                        scope.psOpen = true;
261
 
262
                        if (param.keyListener) {
263
                            $document.on('keydown', handleKeyDown);
264
                        }
265
 
266
                        if (param.clickOutside) {
267
                            $document.on('touchend click', onBodyClick);
268
                        }
269
                        setBodyClass('open');
270
                    }
271
 
272
                    function handleKeyDown(e) {
273
                        var ESC_KEY = 27;
274
                        var key = e.keyCode || e.which;
275
 
276
                        if (key === ESC_KEY) {
277
                            psClose(slider, param);
278
 
279
                            // FIXME check with tests
280
                            // http://stackoverflow.com/questions/12729122/angularjs-prevent-error-digest-already-in-progress-when-calling-scope-apply
281
 
282
                            $timeout(function () {
283
                                scope.$apply();
284
                            });
285
                        }
286
                    }
287
 
288
 
289
                    // Watchers
290
 
291
                    scope.$watch('psOpen', function(value) {
292
                        if (!!value) {
293
                            psOpen(slider, param);
294
                        } else {
295
                            psClose(slider, param);
296
                        }
297
                    });
298
 
299
                    scope.$watch('psSize', function(newValue, oldValue) {
300
                        if (oldValue !== newValue) {
301
                            param.size = newValue;
302
                            initSlider();
303
                        }
304
                    });
305
 
306
 
307
                    // Events
308
 
309
                    scope.$on('$destroy', function () {
310
                        if (slider.parentNode === body) {
311
                            if (param.clickOutside) {
312
                                $document.off('touchend click', onBodyClick);
313
                            }
314
                            body.removeChild(slider);
315
                        }
316
 
317
                        slider.removeEventListener('transitionend', onTransitionEnd);
318
                    });
319
 
320
                    if (param.autoClose) {
321
                        scope.$on('$locationChangeStart', function() {
322
                            psClose(slider, param);
323
                        });
324
                        scope.$on('$stateChangeStart', function() {
325
                            psClose(slider, param);
326
                        });
327
                    }
328
 
329
                }
330
            };
331
        }]);
332
}));