Implemented URL query parsing for initial token /opa/?token=abcde
[src/app-framework-demo.git] / afb-client / bower_components / angular-ui-router / src / viewDirective.js
1 var ngMajorVer = angular.version.major;
2 var ngMinorVer = angular.version.minor;
3 /**
4  * @ngdoc directive
5  * @name ui.router.state.directive:ui-view
6  *
7  * @requires ui.router.state.$state
8  * @requires $compile
9  * @requires $controller
10  * @requires $injector
11  * @requires ui.router.state.$uiViewScroll
12  * @requires $document
13  *
14  * @restrict ECA
15  *
16  * @description
17  * The ui-view directive tells $state where to place your templates.
18  *
19  * @param {string=} name A view name. The name should be unique amongst the other views in the
20  * same state. You can have views of the same name that live in different states.
21  *
22  * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window
23  * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll
24  * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you
25  * scroll ui-view elements into view when they are populated during a state activation.
26  *
27  * @param {string=} noanimation If truthy, the non-animated renderer will be selected (no animations
28  * will be applied to the ui-view)
29  *
30  * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll)
31  * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.*
32  *
33  * @param {string=} onload Expression to evaluate whenever the view updates.
34  * 
35  * @example
36  * A view can be unnamed or named. 
37  * <pre>
38  * <!-- Unnamed -->
39  * <div ui-view></div> 
40  * 
41  * <!-- Named -->
42  * <div ui-view="viewName"></div>
43  * </pre>
44  *
45  * You can only have one unnamed view within any template (or root html). If you are only using a 
46  * single view and it is unnamed then you can populate it like so:
47  * <pre>
48  * <div ui-view></div> 
49  * $stateProvider.state("home", {
50  *   template: "<h1>HELLO!</h1>"
51  * })
52  * </pre>
53  * 
54  * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`}
55  * config property, by name, in this case an empty name:
56  * <pre>
57  * $stateProvider.state("home", {
58  *   views: {
59  *     "": {
60  *       template: "<h1>HELLO!</h1>"
61  *     }
62  *   }    
63  * })
64  * </pre>
65  * 
66  * But typically you'll only use the views property if you name your view or have more than one view 
67  * in the same template. There's not really a compelling reason to name a view if its the only one, 
68  * but you could if you wanted, like so:
69  * <pre>
70  * <div ui-view="main"></div>
71  * </pre> 
72  * <pre>
73  * $stateProvider.state("home", {
74  *   views: {
75  *     "main": {
76  *       template: "<h1>HELLO!</h1>"
77  *     }
78  *   }    
79  * })
80  * </pre>
81  * 
82  * Really though, you'll use views to set up multiple views:
83  * <pre>
84  * <div ui-view></div>
85  * <div ui-view="chart"></div> 
86  * <div ui-view="data"></div> 
87  * </pre>
88  * 
89  * <pre>
90  * $stateProvider.state("home", {
91  *   views: {
92  *     "": {
93  *       template: "<h1>HELLO!</h1>"
94  *     },
95  *     "chart": {
96  *       template: "<chart_thing/>"
97  *     },
98  *     "data": {
99  *       template: "<data_thing/>"
100  *     }
101  *   }    
102  * })
103  * </pre>
104  *
105  * Examples for `autoscroll`:
106  *
107  * <pre>
108  * <!-- If autoscroll present with no expression,
109  *      then scroll ui-view into view -->
110  * <ui-view autoscroll/>
111  *
112  * <!-- If autoscroll present with valid expression,
113  *      then scroll ui-view into view if expression evaluates to true -->
114  * <ui-view autoscroll='true'/>
115  * <ui-view autoscroll='false'/>
116  * <ui-view autoscroll='scopeVariable'/>
117  * </pre>
118  */
119 $ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate'];
120 function $ViewDirective(   $state,   $injector,   $uiViewScroll,   $interpolate) {
121
122   function getService() {
123     return ($injector.has) ? function(service) {
124       return $injector.has(service) ? $injector.get(service) : null;
125     } : function(service) {
126       try {
127         return $injector.get(service);
128       } catch (e) {
129         return null;
130       }
131     };
132   }
133
134   var service = getService(),
135       $animator = service('$animator'),
136       $animate = service('$animate');
137
138   // Returns a set of DOM manipulation functions based on which Angular version
139   // it should use
140   function getRenderer(attrs, scope) {
141     var statics = {
142       enter: function (element, target, cb) { target.after(element); cb(); },
143       leave: function (element, cb) { element.remove(); cb(); }
144     };
145
146     if (!!attrs.noanimation) return statics;
147
148     function animEnabled(element) {
149       if (ngMajorVer === 1 && ngMinorVer >= 4) return !!$animate.enabled(element);
150       if (ngMajorVer === 1 && ngMinorVer >= 2) return !!$animate.enabled();
151       return (!!$animator);
152     }
153
154     // ng 1.2+
155     if ($animate) {
156       return {
157         enter: function(element, target, cb) {
158           if (!animEnabled(element)) {
159             statics.enter(element, target, cb);
160           } else if (angular.version.minor > 2) {
161             $animate.enter(element, null, target).then(cb);
162           } else {
163             $animate.enter(element, null, target, cb);
164           }
165         },
166         leave: function(element, cb) {
167           if (!animEnabled(element)) {
168             statics.leave(element, cb);
169           } else if (angular.version.minor > 2) {
170             $animate.leave(element).then(cb);
171           } else {
172             $animate.leave(element, cb);
173           }
174         }
175       };
176     }
177
178     // ng 1.1.5
179     if ($animator) {
180       var animate = $animator && $animator(scope, attrs);
181
182       return {
183         enter: function(element, target, cb) {animate.enter(element, null, target); cb(); },
184         leave: function(element, cb) { animate.leave(element); cb(); }
185       };
186     }
187
188     return statics;
189   }
190
191   var directive = {
192     restrict: 'ECA',
193     terminal: true,
194     priority: 400,
195     transclude: 'element',
196     compile: function (tElement, tAttrs, $transclude) {
197       return function (scope, $element, attrs) {
198         var previousEl, currentEl, currentScope, latestLocals,
199             onloadExp     = attrs.onload || '',
200             autoScrollExp = attrs.autoscroll,
201             renderer      = getRenderer(attrs, scope);
202
203         scope.$on('$stateChangeSuccess', function() {
204           updateView(false);
205         });
206
207         updateView(true);
208
209         function cleanupLastView() {
210           var _previousEl = previousEl;
211           var _currentScope = currentScope;
212
213           if (_currentScope) {
214             _currentScope._willBeDestroyed = true;
215           }
216
217           function cleanOld() {
218             if (_previousEl) {
219               _previousEl.remove();
220             }
221
222             if (_currentScope) {
223               _currentScope.$destroy();
224             }
225           }
226
227           if (currentEl) {
228             renderer.leave(currentEl, function() {
229               cleanOld();
230               previousEl = null;
231             });
232
233             previousEl = currentEl;
234           } else {
235             cleanOld();
236             previousEl = null;
237           }
238
239           currentEl = null;
240           currentScope = null;
241         }
242
243         function updateView(firstTime) {
244           var newScope,
245               name            = getUiViewName(scope, attrs, $element, $interpolate),
246               previousLocals  = name && $state.$current && $state.$current.locals[name];
247
248           if (!firstTime && previousLocals === latestLocals || scope._willBeDestroyed) return; // nothing to do
249           newScope = scope.$new();
250           latestLocals = $state.$current.locals[name];
251
252           /**
253            * @ngdoc event
254            * @name ui.router.state.directive:ui-view#$viewContentLoading
255            * @eventOf ui.router.state.directive:ui-view
256            * @eventType emits on ui-view directive scope
257            * @description
258            *
259            * Fired once the view **begins loading**, *before* the DOM is rendered.
260            *
261            * @param {Object} event Event object.
262            * @param {string} viewName Name of the view.
263            */
264           newScope.$emit('$viewContentLoading', name);
265
266           var clone = $transclude(newScope, function(clone) {
267             renderer.enter(clone, $element, function onUiViewEnter() {
268               if(currentScope) {
269                 currentScope.$emit('$viewContentAnimationEnded');
270               }
271
272               if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) {
273                 $uiViewScroll(clone);
274               }
275             });
276             cleanupLastView();
277           });
278
279           currentEl = clone;
280           currentScope = newScope;
281           /**
282            * @ngdoc event
283            * @name ui.router.state.directive:ui-view#$viewContentLoaded
284            * @eventOf ui.router.state.directive:ui-view
285            * @eventType emits on ui-view directive scope
286            * @description
287            * Fired once the view is **loaded**, *after* the DOM is rendered.
288            *
289            * @param {Object} event Event object.
290            * @param {string} viewName Name of the view.
291            */
292           currentScope.$emit('$viewContentLoaded', name);
293           currentScope.$eval(onloadExp);
294         }
295       };
296     }
297   };
298
299   return directive;
300 }
301
302 $ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate'];
303 function $ViewDirectiveFill (  $compile,   $controller,   $state,   $interpolate) {
304   return {
305     restrict: 'ECA',
306     priority: -400,
307     compile: function (tElement) {
308       var initial = tElement.html();
309       return function (scope, $element, attrs) {
310         var current = $state.$current,
311             name = getUiViewName(scope, attrs, $element, $interpolate),
312             locals  = current && current.locals[name];
313
314         if (! locals) {
315           return;
316         }
317
318         $element.data('$uiView', { name: name, state: locals.$$state });
319         $element.html(locals.$template ? locals.$template : initial);
320
321         var link = $compile($element.contents());
322
323         if (locals.$$controller) {
324           locals.$scope = scope;
325           locals.$element = $element;
326           var controller = $controller(locals.$$controller, locals);
327           if (locals.$$controllerAs) {
328             scope[locals.$$controllerAs] = controller;
329           }
330           $element.data('$ngControllerController', controller);
331           $element.children().data('$ngControllerController', controller);
332         }
333
334         link(scope);
335       };
336     }
337   };
338 }
339
340 /**
341  * Shared ui-view code for both directives:
342  * Given scope, element, and its attributes, return the view's name
343  */
344 function getUiViewName(scope, attrs, element, $interpolate) {
345   var name = $interpolate(attrs.uiView || attrs.name || '')(scope);
346   var inherited = element.inheritedData('$uiView');
347   return name.indexOf('@') >= 0 ?  name :  (name + '@' + (inherited ? inherited.state.name : ''));
348 }
349
350 angular.module('ui.router.state').directive('uiView', $ViewDirective);
351 angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill);