9 |
10 |
11 |
--------------------------------------------------------------------------------
/ngPlaybook/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="NgPlaybook.Global" Language="C#" %>
2 |
--------------------------------------------------------------------------------
/ngPlaybook/Global.asax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Web;
3 | using System.Web.Http;
4 | using NgPlaybook.Server.Startup;
5 |
6 | namespace NgPlaybook
7 | {
8 | public class Global : HttpApplication
9 | {
10 |
11 | protected void Application_Start(object sender, EventArgs e)
12 | {
13 | GlobalConfiguration.Configure(WebApiStartup.Configure);
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/ngPlaybook/Js/angular/angular-aria.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license AngularJS v1.3.5
3 | * (c) 2010-2014 Google, Inc. http://angularjs.org
4 | * License: MIT
5 | */
6 | (function(window, angular, undefined) {'use strict';
7 |
8 | /**
9 | * @ngdoc module
10 | * @name ngAria
11 | * @description
12 | *
13 | * The `ngAria` module provides support for common
14 | * [ARIA](http://www.w3.org/TR/wai-aria/)
15 | * attributes that convey state or semantic information about the application for users
16 | * of assistive technologies, such as screen readers.
17 | *
18 | *
19 | *
20 | * ## Usage
21 | *
22 | * For ngAria to do its magic, simply include the module as a dependency. The directives supported
23 | * by ngAria are:
24 | * `ngModel`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`, `ngDblClick`, and `ngMessages`.
25 | *
26 | * Below is a more detailed breakdown of the attributes handled by ngAria:
27 | *
28 | * | Directive | Supported Attributes |
29 | * |---------------------------------------------|----------------------------------------------------------------------------------------|
30 | * | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required |
31 | * | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled |
32 | * | {@link ng.directive:ngShow ngShow} | aria-hidden |
33 | * | {@link ng.directive:ngHide ngHide} | aria-hidden |
34 | * | {@link ng.directive:ngClick ngClick} | tabindex |
35 | * | {@link ng.directive:ngDblclick ngDblclick} | tabindex |
36 | * | {@link module:ngMessages ngMessages} | aria-live |
37 | *
38 | * Find out more information about each directive by reading the
39 | * {@link guide/accessibility ngAria Developer Guide}.
40 | *
41 | * ##Example
42 | * Using ngDisabled with ngAria:
43 | * ```html
44 | *
45 | * ```
46 | * Becomes:
47 | * ```html
48 | *
49 | * ```
50 | *
51 | * ##Disabling Attributes
52 | * It's possible to disable individual attributes added by ngAria with the
53 | * {@link ngAria.$ariaProvider#config config} method. For more details, see the
54 | * {@link guide/accessibility Developer Guide}.
55 | */
56 | /* global -ngAriaModule */
57 | var ngAriaModule = angular.module('ngAria', ['ng']).
58 | provider('$aria', $AriaProvider);
59 |
60 | /**
61 | * @ngdoc provider
62 | * @name $ariaProvider
63 | *
64 | * @description
65 | *
66 | * Used for configuring the ARIA attributes injected and managed by ngAria.
67 | *
68 | * ```js
69 | * angular.module('myApp', ['ngAria'], function config($ariaProvider) {
70 | * $ariaProvider.config({
71 | * ariaValue: true,
72 | * tabindex: false
73 | * });
74 | * });
75 | *```
76 | *
77 | * ## Dependencies
78 | * Requires the {@link ngAria} module to be installed.
79 | *
80 | */
81 | function $AriaProvider() {
82 | var config = {
83 | ariaHidden: true,
84 | ariaChecked: true,
85 | ariaDisabled: true,
86 | ariaRequired: true,
87 | ariaInvalid: true,
88 | ariaMultiline: true,
89 | ariaValue: true,
90 | tabindex: true
91 | };
92 |
93 | /**
94 | * @ngdoc method
95 | * @name $ariaProvider#config
96 | *
97 | * @param {object} config object to enable/disable specific ARIA attributes
98 | *
99 | * - **ariaHidden** – `{boolean}` – Enables/disables aria-hidden tags
100 | * - **ariaChecked** – `{boolean}` – Enables/disables aria-checked tags
101 | * - **ariaDisabled** – `{boolean}` – Enables/disables aria-disabled tags
102 | * - **ariaRequired** – `{boolean}` – Enables/disables aria-required tags
103 | * - **ariaInvalid** – `{boolean}` – Enables/disables aria-invalid tags
104 | * - **ariaMultiline** – `{boolean}` – Enables/disables aria-multiline tags
105 | * - **ariaValue** – `{boolean}` – Enables/disables aria-valuemin, aria-valuemax and aria-valuenow tags
106 | * - **tabindex** – `{boolean}` – Enables/disables tabindex tags
107 | *
108 | * @description
109 | * Enables/disables various ARIA attributes
110 | */
111 | this.config = function(newConfig) {
112 | config = angular.extend(config, newConfig);
113 | };
114 |
115 | function camelCase(input) {
116 | return input.replace(/-./g, function(letter, pos) {
117 | return letter[1].toUpperCase();
118 | });
119 | }
120 |
121 |
122 | function watchExpr(attrName, ariaAttr, negate) {
123 | var ariaCamelName = camelCase(ariaAttr);
124 | return function(scope, elem, attr) {
125 | if (config[ariaCamelName] && !attr[ariaCamelName]) {
126 | scope.$watch(attr[attrName], function(boolVal) {
127 | if (negate) {
128 | boolVal = !boolVal;
129 | }
130 | elem.attr(ariaAttr, boolVal);
131 | });
132 | }
133 | };
134 | }
135 |
136 | /**
137 | * @ngdoc service
138 | * @name $aria
139 | *
140 | * @description
141 | *
142 | * The $aria service contains helper methods for applying common
143 | * [ARIA](http://www.w3.org/TR/wai-aria/) attributes to HTML directives.
144 | *
145 | * ngAria injects common accessibility attributes that tell assistive technologies when HTML
146 | * elements are enabled, selected, hidden, and more. To see how this is performed with ngAria,
147 | * let's review a code snippet from ngAria itself:
148 | *
149 | *```js
150 | * ngAriaModule.directive('ngDisabled', ['$aria', function($aria) {
151 | * return $aria.$$watchExpr('ngDisabled', 'aria-disabled');
152 | * }])
153 | *```
154 | * Shown above, the ngAria module creates a directive with the same signature as the
155 | * traditional `ng-disabled` directive. But this ngAria version is dedicated to
156 | * solely managing accessibility attributes. The internal `$aria` service is used to watch the
157 | * boolean attribute `ngDisabled`. If it has not been explicitly set by the developer,
158 | * `aria-disabled` is injected as an attribute with its value synchronized to the value in
159 | * `ngDisabled`.
160 | *
161 | * Because ngAria hooks into the `ng-disabled` directive, developers do not have to do
162 | * anything to enable this feature. The `aria-disabled` attribute is automatically managed
163 | * simply as a silent side-effect of using `ng-disabled` with the ngAria module.
164 | *
165 | * The full list of directives that interface with ngAria:
166 | * * **ngModel**
167 | * * **ngShow**
168 | * * **ngHide**
169 | * * **ngClick**
170 | * * **ngDblclick**
171 | * * **ngMessages**
172 | * * **ngDisabled**
173 | *
174 | * Read the {@link guide/accessibility ngAria Developer Guide} for a thorough explanation of each
175 | * directive.
176 | *
177 | *
178 | * ## Dependencies
179 | * Requires the {@link ngAria} module to be installed.
180 | */
181 | this.$get = function() {
182 | return {
183 | config: function(key) {
184 | return config[camelCase(key)];
185 | },
186 | $$watchExpr: watchExpr
187 | };
188 | };
189 | }
190 |
191 | var ngAriaTabindex = ['$aria', function($aria) {
192 | return function(scope, elem, attr) {
193 | if ($aria.config('tabindex') && !elem.attr('tabindex')) {
194 | elem.attr('tabindex', 0);
195 | }
196 | };
197 | }];
198 |
199 | ngAriaModule.directive('ngShow', ['$aria', function($aria) {
200 | return $aria.$$watchExpr('ngShow', 'aria-hidden', true);
201 | }])
202 | .directive('ngHide', ['$aria', function($aria) {
203 | return $aria.$$watchExpr('ngHide', 'aria-hidden', false);
204 | }])
205 | .directive('ngModel', ['$aria', function($aria) {
206 |
207 | function shouldAttachAttr(attr, elem) {
208 | return $aria.config(attr) && !elem.attr(attr);
209 | }
210 |
211 | function getShape(attr, elem) {
212 | var type = attr.type,
213 | role = attr.role;
214 |
215 | return ((type || role) === 'checkbox' || role === 'menuitemcheckbox') ? 'checkbox' :
216 | ((type || role) === 'radio' || role === 'menuitemradio') ? 'radio' :
217 | (type === 'range' || role === 'progressbar' || role === 'slider') ? 'range' :
218 | (type || role) === 'textbox' || elem[0].nodeName === 'TEXTAREA' ? 'multiline' : '';
219 | }
220 |
221 | return {
222 | restrict: 'A',
223 | require: '?ngModel',
224 | link: function(scope, elem, attr, ngModel) {
225 | var shape = getShape(attr, elem);
226 | var needsTabIndex = shouldAttachAttr('tabindex', elem);
227 |
228 | function ngAriaWatchModelValue() {
229 | return ngModel.$modelValue;
230 | }
231 |
232 | function getRadioReaction() {
233 | if (needsTabIndex) {
234 | needsTabIndex = false;
235 | return function ngAriaRadioReaction(newVal) {
236 | var boolVal = newVal === attr.value;
237 | elem.attr('aria-checked', boolVal);
238 | elem.attr('tabindex', 0 - !boolVal);
239 | };
240 | } else {
241 | return function ngAriaRadioReaction(newVal) {
242 | elem.attr('aria-checked', newVal === attr.value);
243 | };
244 | }
245 | }
246 |
247 | function ngAriaCheckboxReaction(newVal) {
248 | elem.attr('aria-checked', !!newVal);
249 | }
250 |
251 | switch (shape) {
252 | case 'radio':
253 | case 'checkbox':
254 | if (shouldAttachAttr('aria-checked', elem)) {
255 | scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
256 | getRadioReaction() : ngAriaCheckboxReaction);
257 | }
258 | break;
259 | case 'range':
260 | if ($aria.config('ariaValue')) {
261 | if (attr.min && !elem.attr('aria-valuemin')) {
262 | elem.attr('aria-valuemin', attr.min);
263 | }
264 | if (attr.max && !elem.attr('aria-valuemax')) {
265 | elem.attr('aria-valuemax', attr.max);
266 | }
267 | if (!elem.attr('aria-valuenow')) {
268 | scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) {
269 | elem.attr('aria-valuenow', newVal);
270 | });
271 | }
272 | }
273 | break;
274 | case 'multiline':
275 | if (shouldAttachAttr('aria-multiline', elem)) {
276 | elem.attr('aria-multiline', true);
277 | }
278 | break;
279 | }
280 |
281 | if (needsTabIndex) {
282 | elem.attr('tabindex', 0);
283 | }
284 |
285 | if (ngModel.$validators.required && shouldAttachAttr('aria-required', elem)) {
286 | scope.$watch(function ngAriaRequiredWatch() {
287 | return ngModel.$error.required;
288 | }, function ngAriaRequiredReaction(newVal) {
289 | elem.attr('aria-required', !!newVal);
290 | });
291 | }
292 |
293 | if (shouldAttachAttr('aria-invalid', elem)) {
294 | scope.$watch(function ngAriaInvalidWatch() {
295 | return ngModel.$invalid;
296 | }, function ngAriaInvalidReaction(newVal) {
297 | elem.attr('aria-invalid', !!newVal);
298 | });
299 | }
300 | }
301 | };
302 | }])
303 | .directive('ngDisabled', ['$aria', function($aria) {
304 | return $aria.$$watchExpr('ngDisabled', 'aria-disabled');
305 | }])
306 | .directive('ngMessages', function() {
307 | return {
308 | restrict: 'A',
309 | require: '?ngMessages',
310 | link: function(scope, elem, attr, ngMessages) {
311 | if (!elem.attr('aria-live')) {
312 | elem.attr('aria-live', 'assertive');
313 | }
314 | }
315 | };
316 | })
317 | .directive('ngClick', ngAriaTabindex)
318 | .directive('ngDblclick', ngAriaTabindex);
319 |
320 |
321 | })(window, window.angular);
322 |
--------------------------------------------------------------------------------
/ngPlaybook/Js/angular/angular-cookies.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license AngularJS v1.3.5
3 | * (c) 2010-2014 Google, Inc. http://angularjs.org
4 | * License: MIT
5 | */
6 | (function(window, angular, undefined) {'use strict';
7 |
8 | /**
9 | * @ngdoc module
10 | * @name ngCookies
11 | * @description
12 | *
13 | * # ngCookies
14 | *
15 | * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
16 | *
17 | *
18 | *
19 | *
20 | * See {@link ngCookies.$cookies `$cookies`} and
21 | * {@link ngCookies.$cookieStore `$cookieStore`} for usage.
22 | */
23 |
24 |
25 | angular.module('ngCookies', ['ng']).
26 | /**
27 | * @ngdoc service
28 | * @name $cookies
29 | *
30 | * @description
31 | * Provides read/write access to browser's cookies.
32 | *
33 | * Only a simple Object is exposed and by adding or removing properties to/from this object, new
34 | * cookies are created/deleted at the end of current $eval.
35 | * The object's properties can only be strings.
36 | *
37 | * Requires the {@link ngCookies `ngCookies`} module to be installed.
38 | *
39 | * @example
40 | *
41 | * ```js
42 | * angular.module('cookiesExample', ['ngCookies'])
43 | * .controller('ExampleController', ['$cookies', function($cookies) {
44 | * // Retrieving a cookie
45 | * var favoriteCookie = $cookies.myFavorite;
46 | * // Setting a cookie
47 | * $cookies.myFavorite = 'oatmeal';
48 | * }]);
49 | * ```
50 | */
51 | factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) {
52 | var cookies = {},
53 | lastCookies = {},
54 | lastBrowserCookies,
55 | runEval = false,
56 | copy = angular.copy,
57 | isUndefined = angular.isUndefined;
58 |
59 | //creates a poller fn that copies all cookies from the $browser to service & inits the service
60 | $browser.addPollFn(function() {
61 | var currentCookies = $browser.cookies();
62 | if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
63 | lastBrowserCookies = currentCookies;
64 | copy(currentCookies, lastCookies);
65 | copy(currentCookies, cookies);
66 | if (runEval) $rootScope.$apply();
67 | }
68 | })();
69 |
70 | runEval = true;
71 |
72 | //at the end of each eval, push cookies
73 | //TODO: this should happen before the "delayed" watches fire, because if some cookies are not
74 | // strings or browser refuses to store some cookies, we update the model in the push fn.
75 | $rootScope.$watch(push);
76 |
77 | return cookies;
78 |
79 |
80 | /**
81 | * Pushes all the cookies from the service to the browser and verifies if all cookies were
82 | * stored.
83 | */
84 | function push() {
85 | var name,
86 | value,
87 | browserCookies,
88 | updated;
89 |
90 | //delete any cookies deleted in $cookies
91 | for (name in lastCookies) {
92 | if (isUndefined(cookies[name])) {
93 | $browser.cookies(name, undefined);
94 | }
95 | }
96 |
97 | //update all cookies updated in $cookies
98 | for (name in cookies) {
99 | value = cookies[name];
100 | if (!angular.isString(value)) {
101 | value = '' + value;
102 | cookies[name] = value;
103 | }
104 | if (value !== lastCookies[name]) {
105 | $browser.cookies(name, value);
106 | updated = true;
107 | }
108 | }
109 |
110 | //verify what was actually stored
111 | if (updated) {
112 | updated = false;
113 | browserCookies = $browser.cookies();
114 |
115 | for (name in cookies) {
116 | if (cookies[name] !== browserCookies[name]) {
117 | //delete or reset all cookies that the browser dropped from $cookies
118 | if (isUndefined(browserCookies[name])) {
119 | delete cookies[name];
120 | } else {
121 | cookies[name] = browserCookies[name];
122 | }
123 | updated = true;
124 | }
125 | }
126 | }
127 | }
128 | }]).
129 |
130 |
131 | /**
132 | * @ngdoc service
133 | * @name $cookieStore
134 | * @requires $cookies
135 | *
136 | * @description
137 | * Provides a key-value (string-object) storage, that is backed by session cookies.
138 | * Objects put or retrieved from this storage are automatically serialized or
139 | * deserialized by angular's toJson/fromJson.
140 | *
141 | * Requires the {@link ngCookies `ngCookies`} module to be installed.
142 | *
143 | * @example
144 | *
145 | * ```js
146 | * angular.module('cookieStoreExample', ['ngCookies'])
147 | * .controller('ExampleController', ['$cookieStore', function($cookieStore) {
148 | * // Put cookie
149 | * $cookieStore.put('myFavorite','oatmeal');
150 | * // Get cookie
151 | * var favoriteCookie = $cookieStore.get('myFavorite');
152 | * // Removing a cookie
153 | * $cookieStore.remove('myFavorite');
154 | * }]);
155 | * ```
156 | */
157 | factory('$cookieStore', ['$cookies', function($cookies) {
158 |
159 | return {
160 | /**
161 | * @ngdoc method
162 | * @name $cookieStore#get
163 | *
164 | * @description
165 | * Returns the value of given cookie key
166 | *
167 | * @param {string} key Id to use for lookup.
168 | * @returns {Object} Deserialized cookie value.
169 | */
170 | get: function(key) {
171 | var value = $cookies[key];
172 | return value ? angular.fromJson(value) : value;
173 | },
174 |
175 | /**
176 | * @ngdoc method
177 | * @name $cookieStore#put
178 | *
179 | * @description
180 | * Sets a value for given cookie key
181 | *
182 | * @param {string} key Id for the `value`.
183 | * @param {Object} value Value to be stored.
184 | */
185 | put: function(key, value) {
186 | $cookies[key] = angular.toJson(value);
187 | },
188 |
189 | /**
190 | * @ngdoc method
191 | * @name $cookieStore#remove
192 | *
193 | * @description
194 | * Remove given cookie
195 | *
196 | * @param {string} key Id of the key-value pair to delete.
197 | */
198 | remove: function(key) {
199 | delete $cookies[key];
200 | }
201 | };
202 |
203 | }]);
204 |
205 |
206 | })(window, window.angular);
207 |
--------------------------------------------------------------------------------
/ngPlaybook/Js/angular/angular-loader.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license AngularJS v1.3.0
3 | * (c) 2010-2014 Google, Inc. http://angularjs.org
4 | * License: MIT
5 | */
6 |
7 | (function() {'use strict';
8 |
9 | /**
10 | * @description
11 | *
12 | * This object provides a utility for producing rich Error messages within
13 | * Angular. It can be called as follows:
14 | *
15 | * var exampleMinErr = minErr('example');
16 | * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
17 | *
18 | * The above creates an instance of minErr in the example namespace. The
19 | * resulting error will have a namespaced error code of example.one. The
20 | * resulting error will replace {0} with the value of foo, and {1} with the
21 | * value of bar. The object is not restricted in the number of arguments it can
22 | * take.
23 | *
24 | * If fewer arguments are specified than necessary for interpolation, the extra
25 | * interpolation markers will be preserved in the final string.
26 | *
27 | * Since data will be parsed statically during a build step, some restrictions
28 | * are applied with respect to how minErr instances are created and called.
29 | * Instances should have names of the form namespaceMinErr for a minErr created
30 | * using minErr('namespace') . Error codes, namespaces and template strings
31 | * should all be static strings, not variables or general expressions.
32 | *
33 | * @param {string} module The namespace to use for the new minErr instance.
34 | * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
35 | * error from returned function, for cases when a particular type of error is useful.
36 | * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
37 | */
38 |
39 | function minErr(module, ErrorConstructor) {
40 | ErrorConstructor = ErrorConstructor || Error;
41 | return function () {
42 | var code = arguments[0],
43 | prefix = '[' + (module ? module + ':' : '') + code + '] ',
44 | template = arguments[1],
45 | templateArgs = arguments,
46 | stringify = function (obj) {
47 | if (typeof obj === 'function') {
48 | return obj.toString().replace(/ \{[\s\S]*$/, '');
49 | } else if (typeof obj === 'undefined') {
50 | return 'undefined';
51 | } else if (typeof obj !== 'string') {
52 | return JSON.stringify(obj);
53 | }
54 | return obj;
55 | },
56 | message, i;
57 |
58 | message = prefix + template.replace(/\{\d+\}/g, function (match) {
59 | var index = +match.slice(1, -1), arg;
60 |
61 | if (index + 2 < templateArgs.length) {
62 | arg = templateArgs[index + 2];
63 | if (typeof arg === 'function') {
64 | return arg.toString().replace(/ ?\{[\s\S]*$/, '');
65 | } else if (typeof arg === 'undefined') {
66 | return 'undefined';
67 | } else if (typeof arg !== 'string') {
68 | return toJson(arg);
69 | }
70 | return arg;
71 | }
72 | return match;
73 | });
74 |
75 | message = message + '\nhttp://errors.angularjs.org/1.3.0/' +
76 | (module ? module + '/' : '') + code;
77 | for (i = 2; i < arguments.length; i++) {
78 | message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
79 | encodeURIComponent(stringify(arguments[i]));
80 | }
81 | return new ErrorConstructor(message);
82 | };
83 | }
84 |
85 | /**
86 | * @ngdoc type
87 | * @name angular.Module
88 | * @module ng
89 | * @description
90 | *
91 | * Interface for configuring angular {@link angular.module modules}.
92 | */
93 |
94 | function setupModuleLoader(window) {
95 |
96 | var $injectorMinErr = minErr('$injector');
97 | var ngMinErr = minErr('ng');
98 |
99 | function ensure(obj, name, factory) {
100 | return obj[name] || (obj[name] = factory());
101 | }
102 |
103 | var angular = ensure(window, 'angular', Object);
104 |
105 | // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
106 | angular.$$minErr = angular.$$minErr || minErr;
107 |
108 | return ensure(angular, 'module', function() {
109 | /** @type {Object.} */
110 | var modules = {};
111 |
112 | /**
113 | * @ngdoc function
114 | * @name angular.module
115 | * @module ng
116 | * @description
117 | *
118 | * The `angular.module` is a global place for creating, registering and retrieving Angular
119 | * modules.
120 | * All modules (angular core or 3rd party) that should be available to an application must be
121 | * registered using this mechanism.
122 | *
123 | * When passed two or more arguments, a new module is created. If passed only one argument, an
124 | * existing module (the name passed as the first argument to `module`) is retrieved.
125 | *
126 | *
127 | * # Module
128 | *
129 | * A module is a collection of services, directives, controllers, filters, and configuration information.
130 | * `angular.module` is used to configure the {@link auto.$injector $injector}.
131 | *
132 | * ```js
133 | * // Create a new module
134 | * var myModule = angular.module('myModule', []);
135 | *
136 | * // register a new service
137 | * myModule.value('appName', 'MyCoolApp');
138 | *
139 | * // configure existing services inside initialization blocks.
140 | * myModule.config(['$locationProvider', function($locationProvider) {
141 | * // Configure existing providers
142 | * $locationProvider.hashPrefix('!');
143 | * }]);
144 | * ```
145 | *
146 | * Then you can create an injector and load your modules like this:
147 | *
148 | * ```js
149 | * var injector = angular.injector(['ng', 'myModule'])
150 | * ```
151 | *
152 | * However it's more likely that you'll just use
153 | * {@link ng.directive:ngApp ngApp} or
154 | * {@link angular.bootstrap} to simplify this process for you.
155 | *
156 | * @param {!string} name The name of the module to create or retrieve.
157 | * @param {!Array.=} requires If specified then new module is being created. If
158 | * unspecified then the module is being retrieved for further configuration.
159 | * @param {Function=} configFn Optional configuration function for the module. Same as
160 | * {@link angular.Module#config Module#config()}.
161 | * @returns {module} new module with the {@link angular.Module} api.
162 | */
163 | return function module(name, requires, configFn) {
164 | var assertNotHasOwnProperty = function(name, context) {
165 | if (name === 'hasOwnProperty') {
166 | throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
167 | }
168 | };
169 |
170 | assertNotHasOwnProperty(name, 'module');
171 | if (requires && modules.hasOwnProperty(name)) {
172 | modules[name] = null;
173 | }
174 | return ensure(modules, name, function() {
175 | if (!requires) {
176 | throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
177 | "the module name or forgot to load it. If registering a module ensure that you " +
178 | "specify the dependencies as the second argument.", name);
179 | }
180 |
181 | /** @type {!Array.>} */
182 | var invokeQueue = [];
183 |
184 | /** @type {!Array.} */
185 | var configBlocks = [];
186 |
187 | /** @type {!Array.} */
188 | var runBlocks = [];
189 |
190 | var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
191 |
192 | /** @type {angular.Module} */
193 | var moduleInstance = {
194 | // Private state
195 | _invokeQueue: invokeQueue,
196 | _configBlocks: configBlocks,
197 | _runBlocks: runBlocks,
198 |
199 | /**
200 | * @ngdoc property
201 | * @name angular.Module#requires
202 | * @module ng
203 | *
204 | * @description
205 | * Holds the list of modules which the injector will load before the current module is
206 | * loaded.
207 | */
208 | requires: requires,
209 |
210 | /**
211 | * @ngdoc property
212 | * @name angular.Module#name
213 | * @module ng
214 | *
215 | * @description
216 | * Name of the module.
217 | */
218 | name: name,
219 |
220 |
221 | /**
222 | * @ngdoc method
223 | * @name angular.Module#provider
224 | * @module ng
225 | * @param {string} name service name
226 | * @param {Function} providerType Construction function for creating new instance of the
227 | * service.
228 | * @description
229 | * See {@link auto.$provide#provider $provide.provider()}.
230 | */
231 | provider: invokeLater('$provide', 'provider'),
232 |
233 | /**
234 | * @ngdoc method
235 | * @name angular.Module#factory
236 | * @module ng
237 | * @param {string} name service name
238 | * @param {Function} providerFunction Function for creating new instance of the service.
239 | * @description
240 | * See {@link auto.$provide#factory $provide.factory()}.
241 | */
242 | factory: invokeLater('$provide', 'factory'),
243 |
244 | /**
245 | * @ngdoc method
246 | * @name angular.Module#service
247 | * @module ng
248 | * @param {string} name service name
249 | * @param {Function} constructor A constructor function that will be instantiated.
250 | * @description
251 | * See {@link auto.$provide#service $provide.service()}.
252 | */
253 | service: invokeLater('$provide', 'service'),
254 |
255 | /**
256 | * @ngdoc method
257 | * @name angular.Module#value
258 | * @module ng
259 | * @param {string} name service name
260 | * @param {*} object Service instance object.
261 | * @description
262 | * See {@link auto.$provide#value $provide.value()}.
263 | */
264 | value: invokeLater('$provide', 'value'),
265 |
266 | /**
267 | * @ngdoc method
268 | * @name angular.Module#constant
269 | * @module ng
270 | * @param {string} name constant name
271 | * @param {*} object Constant value.
272 | * @description
273 | * Because the constant are fixed, they get applied before other provide methods.
274 | * See {@link auto.$provide#constant $provide.constant()}.
275 | */
276 | constant: invokeLater('$provide', 'constant', 'unshift'),
277 |
278 | /**
279 | * @ngdoc method
280 | * @name angular.Module#animation
281 | * @module ng
282 | * @param {string} name animation name
283 | * @param {Function} animationFactory Factory function for creating new instance of an
284 | * animation.
285 | * @description
286 | *
287 | * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
288 | *
289 | *
290 | * Defines an animation hook that can be later used with
291 | * {@link ngAnimate.$animate $animate} service and directives that use this service.
292 | *
293 | * ```js
294 | * module.animation('.animation-name', function($inject1, $inject2) {
295 | * return {
296 | * eventName : function(element, done) {
297 | * //code to run the animation
298 | * //once complete, then run done()
299 | * return function cancellationFunction(element) {
300 | * //code to cancel the animation
301 | * }
302 | * }
303 | * }
304 | * })
305 | * ```
306 | *
307 | * See {@link ng.$animateProvider#register $animateProvider.register()} and
308 | * {@link ngAnimate ngAnimate module} for more information.
309 | */
310 | animation: invokeLater('$animateProvider', 'register'),
311 |
312 | /**
313 | * @ngdoc method
314 | * @name angular.Module#filter
315 | * @module ng
316 | * @param {string} name Filter name.
317 | * @param {Function} filterFactory Factory function for creating new instance of filter.
318 | * @description
319 | * See {@link ng.$filterProvider#register $filterProvider.register()}.
320 | */
321 | filter: invokeLater('$filterProvider', 'register'),
322 |
323 | /**
324 | * @ngdoc method
325 | * @name angular.Module#controller
326 | * @module ng
327 | * @param {string|Object} name Controller name, or an object map of controllers where the
328 | * keys are the names and the values are the constructors.
329 | * @param {Function} constructor Controller constructor function.
330 | * @description
331 | * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
332 | */
333 | controller: invokeLater('$controllerProvider', 'register'),
334 |
335 | /**
336 | * @ngdoc method
337 | * @name angular.Module#directive
338 | * @module ng
339 | * @param {string|Object} name Directive name, or an object map of directives where the
340 | * keys are the names and the values are the factories.
341 | * @param {Function} directiveFactory Factory function for creating new instance of
342 | * directives.
343 | * @description
344 | * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
345 | */
346 | directive: invokeLater('$compileProvider', 'directive'),
347 |
348 | /**
349 | * @ngdoc method
350 | * @name angular.Module#config
351 | * @module ng
352 | * @param {Function} configFn Execute this function on module load. Useful for service
353 | * configuration.
354 | * @description
355 | * Use this method to register work which needs to be performed on module loading.
356 | * For more about how to configure services, see
357 | * {@link providers#provider-recipe Provider Recipe}.
358 | */
359 | config: config,
360 |
361 | /**
362 | * @ngdoc method
363 | * @name angular.Module#run
364 | * @module ng
365 | * @param {Function} initializationFn Execute this function after injector creation.
366 | * Useful for application initialization.
367 | * @description
368 | * Use this method to register work which should be performed when the injector is done
369 | * loading all modules.
370 | */
371 | run: function(block) {
372 | runBlocks.push(block);
373 | return this;
374 | }
375 | };
376 |
377 | if (configFn) {
378 | config(configFn);
379 | }
380 |
381 | return moduleInstance;
382 |
383 | /**
384 | * @param {string} provider
385 | * @param {string} method
386 | * @param {String=} insertMethod
387 | * @returns {angular.Module}
388 | */
389 | function invokeLater(provider, method, insertMethod, queue) {
390 | if (!queue) queue = invokeQueue;
391 | return function() {
392 | queue[insertMethod || 'push']([provider, method, arguments]);
393 | return moduleInstance;
394 | };
395 | }
396 | });
397 | };
398 | });
399 |
400 | }
401 |
402 | setupModuleLoader(window);
403 | })(window);
404 |
405 | /**
406 | * Closure compiler type information
407 | *
408 | * @typedef { {
409 | * requires: !Array.,
410 | * invokeQueue: !Array.>,
411 | *
412 | * service: function(string, Function):angular.Module,
413 | * factory: function(string, Function):angular.Module,
414 | * value: function(string, *):angular.Module,
415 | *
416 | * filter: function(string, Function):angular.Module,
417 | *
418 | * init: function(Function):angular.Module
419 | * } }
420 | */
421 | angular.Module;
422 |
423 |
--------------------------------------------------------------------------------
/ngPlaybook/Js/angular/angular-messages.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license AngularJS v1.3.5
3 | * (c) 2010-2014 Google, Inc. http://angularjs.org
4 | * License: MIT
5 | */
6 | (function(window, angular, undefined) {'use strict';
7 |
8 | /**
9 | * @ngdoc module
10 | * @name ngMessages
11 | * @description
12 | *
13 | * The `ngMessages` module provides enhanced support for displaying messages within templates
14 | * (typically within forms or when rendering message objects that return key/value data).
15 | * Instead of relying on JavaScript code and/or complex ng-if statements within your form template to
16 | * show and hide error messages specific to the state of an input field, the `ngMessages` and
17 | * `ngMessage` directives are designed to handle the complexity, inheritance and priority
18 | * sequencing based on the order of how the messages are defined in the template.
19 | *
20 | * Currently, the ngMessages module only contains the code for the `ngMessages`
21 | * and `ngMessage` directives.
22 | *
23 | * # Usage
24 | * The `ngMessages` directive listens on a key/value collection which is set on the ngMessages attribute.
25 | * Since the {@link ngModel ngModel} directive exposes an `$error` object, this error object can be
26 | * used with `ngMessages` to display control error messages in an easier way than with just regular angular
27 | * template directives.
28 | *
29 | * ```html
30 | *
37 | * ```
38 | *
39 | * Now whatever key/value entries are present within the provided object (in this case `$error`) then
40 | * the ngMessages directive will render the inner first ngMessage directive (depending if the key values
41 | * match the attribute value present on each ngMessage directive). In other words, if your errors
42 | * object contains the following data:
43 | *
44 | * ```javascript
45 | *
46 | * myField.$error = { minlength : true, required : false };
47 | * ```
48 | *
49 | * Then the `required` message will be displayed first. When required is false then the `minlength` message
50 | * will be displayed right after (since these messages are ordered this way in the template HTML code).
51 | * The prioritization of each message is determined by what order they're present in the DOM.
52 | * Therefore, instead of having custom JavaScript code determine the priority of what errors are
53 | * present before others, the presentation of the errors are handled within the template.
54 | *
55 | * By default, ngMessages will only display one error at a time. However, if you wish to display all
56 | * messages then the `ng-messages-multiple` attribute flag can be used on the element containing the
57 | * ngMessages directive to make this happen.
58 | *
59 | * ```html
60 | *
...
61 | * ```
62 | *
63 | * ## Reusing and Overriding Messages
64 | * In addition to prioritization, ngMessages also allows for including messages from a remote or an inline
65 | * template. This allows for generic collection of messages to be reused across multiple parts of an
66 | * application.
67 | *
68 | * ```html
69 | *
73 | *
74 | * ```
75 | *
76 | * However, including generic messages may not be useful enough to match all input fields, therefore,
77 | * `ngMessages` provides the ability to override messages defined in the remote template by redefining
78 | * then within the directive container.
79 | *
80 | * ```html
81 | *
82 | *
86 | *
87 | *
103 | * ```
104 | *
105 | * In the example HTML code above the message that is set on required will override the corresponding
106 | * required message defined within the remote template. Therefore, with particular input fields (such
107 | * email addresses, date fields, autocomplete inputs, etc...), specialized error messages can be applied
108 | * while more generic messages can be used to handle other, more general input errors.
109 | *
110 | * ## Animations
111 | * If the `ngAnimate` module is active within the application then both the `ngMessages` and
112 | * `ngMessage` directives will trigger animations whenever any messages are added and removed
113 | * from the DOM by the `ngMessages` directive.
114 | *
115 | * Whenever the `ngMessages` directive contains one or more visible messages then the `.ng-active` CSS
116 | * class will be added to the element. The `.ng-inactive` CSS class will be applied when there are no
117 | * animations present. Therefore, CSS transitions and keyframes as well as JavaScript animations can
118 | * hook into the animations whenever these classes are added/removed.
119 | *
120 | * Let's say that our HTML code for our messages container looks like so:
121 | *
122 | * ```html
123 | *
124 | *
...
125 | *
...
126 | *
127 | * ```
128 | *
129 | * Then the CSS animation code for the message container looks like so:
130 | *
131 | * ```css
132 | * .my-messages {
133 | * transition:1s linear all;
134 | * }
135 | * .my-messages.ng-active {
136 | * // messages are visible
137 | * }
138 | * .my-messages.ng-inactive {
139 | * // messages are hidden
140 | * }
141 | * ```
142 | *
143 | * Whenever an inner message is attached (becomes visible) or removed (becomes hidden) then the enter
144 | * and leave animation is triggered for each particular element bound to the `ngMessage` directive.
145 | *
146 | * Therefore, the CSS code for the inner messages looks like so:
147 | *
148 | * ```css
149 | * .some-message {
150 | * transition:1s linear all;
151 | * }
152 | *
153 | * .some-message.ng-enter {}
154 | * .some-message.ng-enter.ng-enter-active {}
155 | *
156 | * .some-message.ng-leave {}
157 | * .some-message.ng-leave.ng-leave-active {}
158 | * ```
159 | *
160 | * {@link ngAnimate Click here} to learn how to use JavaScript animations or to learn more about ngAnimate.
161 | */
162 | angular.module('ngMessages', [])
163 |
164 | /**
165 | * @ngdoc directive
166 | * @module ngMessages
167 | * @name ngMessages
168 | * @restrict AE
169 | *
170 | * @description
171 | * `ngMessages` is a directive that is designed to show and hide messages based on the state
172 | * of a key/value object that it listens on. The directive itself compliments error message
173 | * reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
174 | *
175 | * `ngMessages` manages the state of internal messages within its container element. The internal
176 | * messages use the `ngMessage` directive and will be inserted/removed from the page depending
177 | * on if they're present within the key/value object. By default, only one message will be displayed
178 | * at a time and this depends on the prioritization of the messages within the template. (This can
179 | * be changed by using the ng-messages-multiple on the directive container.)
180 | *
181 | * A remote template can also be used to promote message reuseability and messages can also be
182 | * overridden.
183 | *
184 | * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
185 | *
186 | * @usage
187 | * ```html
188 | *
189 | *
190 | * ...
191 | * ...
192 | * ...
193 | *
194 | *
195 | *
196 | *
197 | * ...
198 | * ...
199 | * ...
200 | *
201 | * ```
202 | *
203 | * @param {string} ngMessages an angular expression evaluating to a key/value object
204 | * (this is typically the $error object on an ngModel instance).
205 | * @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true
206 | * @param {string=} ngMessagesInclude|include when set, the specified template will be included into the ng-messages container
207 | *
208 | * @example
209 | *
212 | *
213 | *
230 | *
231 | *
232 | * angular.module('ngMessagesExample', ['ngMessages']);
233 | *
234 | *
235 | */
236 | .directive('ngMessages', ['$compile', '$animate', '$templateRequest',
237 | function($compile, $animate, $templateRequest) {
238 | var ACTIVE_CLASS = 'ng-active';
239 | var INACTIVE_CLASS = 'ng-inactive';
240 |
241 | return {
242 | restrict: 'AE',
243 | controller: function() {
244 | this.$renderNgMessageClasses = angular.noop;
245 |
246 | var messages = [];
247 | this.registerMessage = function(index, message) {
248 | for (var i = 0; i < messages.length; i++) {
249 | if (messages[i].type == message.type) {
250 | if (index != i) {
251 | var temp = messages[index];
252 | messages[index] = messages[i];
253 | if (index < messages.length) {
254 | messages[i] = temp;
255 | } else {
256 | messages.splice(0, i); //remove the old one (and shift left)
257 | }
258 | }
259 | return;
260 | }
261 | }
262 | messages.splice(index, 0, message); //add the new one (and shift right)
263 | };
264 |
265 | this.renderMessages = function(values, multiple) {
266 | values = values || {};
267 |
268 | var found;
269 | angular.forEach(messages, function(message) {
270 | if ((!found || multiple) && truthyVal(values[message.type])) {
271 | message.attach();
272 | found = true;
273 | } else {
274 | message.detach();
275 | }
276 | });
277 |
278 | this.renderElementClasses(found);
279 |
280 | function truthyVal(value) {
281 | return value !== null && value !== false && value;
282 | }
283 | };
284 | },
285 | require: 'ngMessages',
286 | link: function($scope, element, $attrs, ctrl) {
287 | ctrl.renderElementClasses = function(bool) {
288 | bool ? $animate.setClass(element, ACTIVE_CLASS, INACTIVE_CLASS)
289 | : $animate.setClass(element, INACTIVE_CLASS, ACTIVE_CLASS);
290 | };
291 |
292 | //JavaScript treats empty strings as false, but ng-message-multiple by itself is an empty string
293 | var multiple = angular.isString($attrs.ngMessagesMultiple) ||
294 | angular.isString($attrs.multiple);
295 |
296 | var cachedValues, watchAttr = $attrs.ngMessages || $attrs['for']; //for is a reserved keyword
297 | $scope.$watchCollection(watchAttr, function(values) {
298 | cachedValues = values;
299 | ctrl.renderMessages(values, multiple);
300 | });
301 |
302 | var tpl = $attrs.ngMessagesInclude || $attrs.include;
303 | if (tpl) {
304 | $templateRequest(tpl)
305 | .then(function processTemplate(html) {
306 | var after, container = angular.element('').html(html);
307 | angular.forEach(container.children(), function(elm) {
308 | elm = angular.element(elm);
309 | after ? after.after(elm)
310 | : element.prepend(elm); //start of the container
311 | after = elm;
312 | $compile(elm)($scope);
313 | });
314 | ctrl.renderMessages(cachedValues, multiple);
315 | });
316 | }
317 | }
318 | };
319 | }])
320 |
321 |
322 | /**
323 | * @ngdoc directive
324 | * @name ngMessage
325 | * @restrict AE
326 | * @scope
327 | *
328 | * @description
329 | * `ngMessage` is a directive with the purpose to show and hide a particular message.
330 | * For `ngMessage` to operate, a parent `ngMessages` directive on a parent DOM element
331 | * must be situated since it determines which messages are visible based on the state
332 | * of the provided key/value map that `ngMessages` listens on.
333 | *
334 | * @usage
335 | * ```html
336 | *
337 | *
338 | * ...
339 | * ...
340 | * ...
341 | *
342 | *
343 | *
344 | *
345 | * ...
346 | * ...
347 | * ...
348 | *
349 | * ```
350 | *
351 | * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
352 | *
353 | * @param {string} ngMessage a string value corresponding to the message key.
354 | */
355 | .directive('ngMessage', ['$animate', function($animate) {
356 | var COMMENT_NODE = 8;
357 | return {
358 | require: '^ngMessages',
359 | transclude: 'element',
360 | terminal: true,
361 | restrict: 'AE',
362 | link: function($scope, $element, $attrs, ngMessages, $transclude) {
363 | var index, element;
364 |
365 | var commentNode = $element[0];
366 | var parentNode = commentNode.parentNode;
367 | for (var i = 0, j = 0; i < parentNode.childNodes.length; i++) {
368 | var node = parentNode.childNodes[i];
369 | if (node.nodeType == COMMENT_NODE && node.nodeValue.indexOf('ngMessage') >= 0) {
370 | if (node === commentNode) {
371 | index = j;
372 | break;
373 | }
374 | j++;
375 | }
376 | }
377 |
378 | ngMessages.registerMessage(index, {
379 | type: $attrs.ngMessage || $attrs.when,
380 | attach: function() {
381 | if (!element) {
382 | $transclude($scope, function(clone) {
383 | $animate.enter(clone, null, $element);
384 | element = clone;
385 | });
386 | }
387 | },
388 | detach: function(now) {
389 | if (element) {
390 | $animate.leave(element);
391 | element = null;
392 | }
393 | }
394 | });
395 | }
396 | };
397 | }]);
398 |
399 |
400 | })(window, window.angular);
401 |
--------------------------------------------------------------------------------
/ngPlaybook/Js/google-chart/google-chart.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @description Google Chart Api Directive Module for AngularJS
3 | * @version 0.0.11
4 | * @author Nicolas Bouillon
5 | * @author GitHub contributors
6 | * @license MIT
7 | * @year 2013
8 | */
9 | (function (document, window, angular) {
10 | 'use strict';
11 |
12 | angular.module('googlechart', [])
13 |
14 | .value('googleChartApiConfig', {
15 | version: '1',
16 | optionalSettings: {
17 | packages: ['corechart']
18 | }
19 | })
20 |
21 | .provider('googleJsapiUrl', function () {
22 | var protocol = 'https:';
23 | var url = '//www.google.com/jsapi';
24 |
25 | this.setProtocol = function (newProtocol) {
26 | protocol = newProtocol;
27 | };
28 |
29 | this.setUrl = function (newUrl) {
30 | url = newUrl;
31 | };
32 |
33 | this.$get = function () {
34 | return (protocol ? protocol : '') + url;
35 | };
36 | })
37 | .factory('googleChartApiPromise', ['$rootScope', '$q', 'googleChartApiConfig', 'googleJsapiUrl', function ($rootScope, $q, apiConfig, googleJsapiUrl) {
38 | var apiReady = $q.defer();
39 | var onLoad = function () {
40 | // override callback function
41 | var settings = {
42 | callback: function () {
43 | var oldCb = apiConfig.optionalSettings.callback;
44 | $rootScope.$apply(function () {
45 | apiReady.resolve();
46 | });
47 |
48 | if (angular.isFunction(oldCb)) {
49 | oldCb.call(this);
50 | }
51 | }
52 | };
53 |
54 | settings = angular.extend({}, apiConfig.optionalSettings, settings);
55 |
56 | window.google.load('visualization', apiConfig.version, settings);
57 | };
58 | var head = document.getElementsByTagName('head')[0];
59 | var script = document.createElement('script');
60 |
61 | script.setAttribute('type', 'text/javascript');
62 | script.src = googleJsapiUrl;
63 |
64 | if (script.addEventListener) { // Standard browsers (including IE9+)
65 | script.addEventListener('load', onLoad, false);
66 | } else { // IE8 and below
67 | script.onreadystatechange = function () {
68 | if (script.readyState === 'loaded' || script.readyState === 'complete') {
69 | script.onreadystatechange = null;
70 | onLoad();
71 | }
72 | };
73 | }
74 |
75 | head.appendChild(script);
76 |
77 | return apiReady.promise;
78 | }])
79 | .directive('googleChart', ['$timeout', '$window', '$rootScope', 'googleChartApiPromise', function ($timeout, $window, $rootScope, googleChartApiPromise) {
80 | return {
81 | restrict: 'A',
82 | scope: {
83 | beforeDraw: '&',
84 | chart: '=chart',
85 | onReady: '&',
86 | onSelect: '&',
87 | select: '&'
88 | },
89 | link: function ($scope, $elm, $attrs) {
90 | /* Watches, to refresh the chart when its data, formatters, options, view,
91 | or type change. All other values intentionally disregarded to avoid double
92 | calls to the draw function. Please avoid making changes to these objects
93 | directly from this directive.*/
94 | $scope.$watch(function () {
95 | if ($scope.chart) {
96 | return {
97 | customFormatters: $scope.chart.customFormatters,
98 | data: $scope.chart.data,
99 | formatters: $scope.chart.formatters,
100 | options: $scope.chart.options,
101 | type: $scope.chart.type,
102 | view: $scope.chart.view
103 | };
104 | }
105 | return $scope.chart;
106 | }, function () {
107 | drawAsync();
108 | }, true); // true is for deep object equality checking
109 |
110 | // Redraw the chart if the window is resized
111 | var resizeHandler = $rootScope.$on('resizeMsg', function () {
112 | $timeout(function () {
113 | // Not always defined yet in IE so check
114 | if ($scope.chartWrapper) {
115 | drawAsync();
116 | }
117 | });
118 | });
119 |
120 | //Cleanup resize handler.
121 | $scope.$on('$destroy', function () {
122 | resizeHandler();
123 | });
124 |
125 | // Keeps old formatter configuration to compare against
126 | $scope.oldChartFormatters = {};
127 |
128 | function applyFormat(formatType, formatClass, dataTable) {
129 |
130 | if (typeof ($scope.chart.formatters[formatType]) != 'undefined') {
131 | if (!angular.equals($scope.chart.formatters[formatType], $scope.oldChartFormatters[formatType])) {
132 | $scope.oldChartFormatters[formatType] = $scope.chart.formatters[formatType];
133 | $scope.formatters[formatType] = [];
134 |
135 | if (formatType === 'color') {
136 | for (var cIdx = 0; cIdx < $scope.chart.formatters[formatType].length; cIdx++) {
137 | var colorFormat = new formatClass();
138 |
139 | for (i = 0; i < $scope.chart.formatters[formatType][cIdx].formats.length; i++) {
140 | var data = $scope.chart.formatters[formatType][cIdx].formats[i];
141 |
142 | if (typeof (data.fromBgColor) != 'undefined' && typeof (data.toBgColor) != 'undefined')
143 | colorFormat.addGradientRange(data.from, data.to, data.color, data.fromBgColor, data.toBgColor);
144 | else
145 | colorFormat.addRange(data.from, data.to, data.color, data.bgcolor);
146 | }
147 |
148 | $scope.formatters[formatType].push(colorFormat)
149 | }
150 | } else {
151 |
152 | for (var i = 0; i < $scope.chart.formatters[formatType].length; i++) {
153 | $scope.formatters[formatType].push(new formatClass(
154 | $scope.chart.formatters[formatType][i])
155 | );
156 | }
157 | }
158 | }
159 |
160 |
161 | //apply formats to dataTable
162 | for (i = 0; i < $scope.formatters[formatType].length; i++) {
163 | if ($scope.chart.formatters[formatType][i].columnNum < dataTable.getNumberOfColumns())
164 | $scope.formatters[formatType][i].format(dataTable, $scope.chart.formatters[formatType][i].columnNum);
165 | }
166 |
167 |
168 | //Many formatters require HTML tags to display special formatting
169 | if (formatType === 'arrow' || formatType === 'bar' || formatType === 'color')
170 | $scope.chart.options.allowHtml = true;
171 | }
172 | }
173 |
174 | function draw() {
175 | if (!draw.triggered && ($scope.chart != undefined)) {
176 | draw.triggered = true;
177 | $timeout(function () {
178 |
179 | if (typeof ($scope.chartWrapper) == 'undefined') {
180 | var chartWrapperArgs = {
181 | chartType: $scope.chart.type,
182 | dataTable: $scope.chart.data,
183 | view: $scope.chart.view,
184 | options: $scope.chart.options,
185 | containerId: $elm[0]
186 | };
187 |
188 | $scope.chartWrapper = new google.visualization.ChartWrapper(chartWrapperArgs);
189 | google.visualization.events.addListener($scope.chartWrapper, 'ready', function () {
190 | $scope.chart.displayed = true;
191 | $scope.$apply(function (scope) {
192 | scope.onReady({ chartWrapper: scope.chartWrapper });
193 | });
194 | });
195 | google.visualization.events.addListener($scope.chartWrapper, 'error', function (err) {
196 | console.log("Chart not displayed due to error: " + err.message + ". Full error object follows.");
197 | console.log(err);
198 | });
199 | google.visualization.events.addListener($scope.chartWrapper, 'select', function () {
200 | var selectEventRetParams = { selectedItems: $scope.chartWrapper.getChart().getSelection() };
201 | // This is for backwards compatibility for people using 'selectedItem' that only wanted the first selection.
202 | selectEventRetParams['selectedItem'] = selectEventRetParams['selectedItems'][0];
203 | $scope.$apply(function () {
204 | if ($attrs.select) {
205 | console.log('Angular-Google-Chart: The \'select\' attribute is deprecated and will be removed in a future release. Please use \'onSelect\'.');
206 | $scope.select({ selectEventRetParams: selectEventRetParams });
207 | }
208 | else {
209 | $scope.onSelect({ selectEventRetParams: selectEventRetParams });
210 | }
211 | });
212 | });
213 | }
214 | else {
215 | $scope.chartWrapper.setChartType($scope.chart.type);
216 | $scope.chartWrapper.setDataTable($scope.chart.data);
217 | $scope.chartWrapper.setView($scope.chart.view);
218 | $scope.chartWrapper.setOptions($scope.chart.options);
219 | }
220 |
221 | if (typeof ($scope.formatters) === 'undefined')
222 | $scope.formatters = {};
223 |
224 | if (typeof ($scope.chart.formatters) != 'undefined') {
225 | applyFormat("number", google.visualization.NumberFormat, $scope.chartWrapper.getDataTable());
226 | applyFormat("arrow", google.visualization.ArrowFormat, $scope.chartWrapper.getDataTable());
227 | applyFormat("date", google.visualization.DateFormat, $scope.chartWrapper.getDataTable());
228 | applyFormat("bar", google.visualization.BarFormat, $scope.chartWrapper.getDataTable());
229 | applyFormat("color", google.visualization.ColorFormat, $scope.chartWrapper.getDataTable());
230 | }
231 |
232 | var customFormatters = $scope.chart.customFormatters;
233 | if (typeof (customFormatters) != 'undefined') {
234 | for (var name in customFormatters) {
235 | applyFormat(name, customFormatters[name], $scope.chartWrapper.getDataTable());
236 | }
237 | }
238 |
239 | $timeout(function () {
240 | $scope.beforeDraw({ chartWrapper: $scope.chartWrapper });
241 | $scope.chartWrapper.draw();
242 | draw.triggered = false;
243 | });
244 | }, 0, true);
245 | }
246 | }
247 |
248 | function drawAsync() {
249 | googleChartApiPromise.then(function () {
250 | draw();
251 | })
252 | }
253 | }
254 | };
255 | }])
256 |
257 | .run(['$rootScope', '$window', function ($rootScope, $window) {
258 | angular.element($window).bind('resize', function () {
259 | $rootScope.$emit('resizeMsg');
260 | });
261 | }]);
262 |
263 | })(document, window, window.angular);
264 |
--------------------------------------------------------------------------------
/ngPlaybook/Js/jasmine/boot.js:
--------------------------------------------------------------------------------
1 | /**
2 | Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
3 |
4 | If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
5 |
6 | The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.
7 |
8 | [jasmine-gem]: http://github.com/pivotal/jasmine-gem
9 | */
10 |
11 | (function() {
12 |
13 | /**
14 | * ## Require & Instantiate
15 | *
16 | * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
17 | */
18 | window.jasmine = jasmineRequire.core(jasmineRequire);
19 |
20 | /**
21 | * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
22 | */
23 | jasmineRequire.html(jasmine);
24 |
25 | /**
26 | * Create the Jasmine environment. This is used to run all specs in a project.
27 | */
28 | var env = jasmine.getEnv();
29 |
30 | /**
31 | * ## The Global Interface
32 | *
33 | * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
34 | */
35 | var jasmineInterface = jasmineRequire.interface(jasmine, env);
36 |
37 | /**
38 | * Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
39 | */
40 | if (typeof window == "undefined" && typeof exports == "object") {
41 | extend(exports, jasmineInterface);
42 | } else {
43 | extend(window, jasmineInterface);
44 | }
45 |
46 | /**
47 | * ## Runner Parameters
48 | *
49 | * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
50 | */
51 |
52 | var queryString = new jasmine.QueryString({
53 | getWindowLocation: function() { return window.location; }
54 | });
55 |
56 | var catchingExceptions = queryString.getParam("catch");
57 | env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
58 |
59 | /**
60 | * ## Reporters
61 | * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
62 | */
63 | var htmlReporter = new jasmine.HtmlReporter({
64 | env: env,
65 | onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
66 | getContainer: function() { return document.body; },
67 | createElement: function() { return document.createElement.apply(document, arguments); },
68 | createTextNode: function() { return document.createTextNode.apply(document, arguments); },
69 | timer: new jasmine.Timer()
70 | });
71 |
72 | /**
73 | * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
74 | */
75 | env.addReporter(jasmineInterface.jsApiReporter);
76 | env.addReporter(htmlReporter);
77 |
78 | /**
79 | * Filter which specs will be run by matching the start of the full name against the `spec` query param.
80 | */
81 | var specFilter = new jasmine.HtmlSpecFilter({
82 | filterString: function() { return queryString.getParam("spec"); }
83 | });
84 |
85 | env.specFilter = function(spec) {
86 | return specFilter.matches(spec.getFullName());
87 | };
88 |
89 | /**
90 | * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
91 | */
92 | window.setTimeout = window.setTimeout;
93 | window.setInterval = window.setInterval;
94 | window.clearTimeout = window.clearTimeout;
95 | window.clearInterval = window.clearInterval;
96 |
97 | /**
98 | * ## Execution
99 | *
100 | * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
101 | */
102 | var currentWindowOnload = window.onload;
103 |
104 | window.onload = function() {
105 | if (currentWindowOnload) {
106 | currentWindowOnload();
107 | }
108 | htmlReporter.initialize();
109 | env.execute();
110 | };
111 |
112 | /**
113 | * Helper function for readability above.
114 | */
115 | function extend(destination, source) {
116 | for (var property in source) destination[property] = source[property];
117 | return destination;
118 | }
119 |
120 | }());
121 |
--------------------------------------------------------------------------------
/ngPlaybook/Js/jasmine/console.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2008-2014 Pivotal Labs
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining
5 | a copy of this software and associated documentation files (the
6 | "Software"), to deal in the Software without restriction, including
7 | without limitation the rights to use, copy, modify, merge, publish,
8 | distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so, subject to
10 | the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 | function getJasmineRequireObj() {
24 | if (typeof module !== 'undefined' && module.exports) {
25 | return exports;
26 | } else {
27 | window.jasmineRequire = window.jasmineRequire || {};
28 | return window.jasmineRequire;
29 | }
30 | }
31 |
32 | getJasmineRequireObj().console = function(jRequire, j$) {
33 | j$.ConsoleReporter = jRequire.ConsoleReporter();
34 | };
35 |
36 | getJasmineRequireObj().ConsoleReporter = function() {
37 |
38 | var noopTimer = {
39 | start: function(){},
40 | elapsed: function(){ return 0; }
41 | };
42 |
43 | function ConsoleReporter(options) {
44 | var print = options.print,
45 | showColors = options.showColors || false,
46 | onComplete = options.onComplete || function() {},
47 | timer = options.timer || noopTimer,
48 | specCount,
49 | failureCount,
50 | failedSpecs = [],
51 | pendingCount,
52 | ansi = {
53 | green: '\x1B[32m',
54 | red: '\x1B[31m',
55 | yellow: '\x1B[33m',
56 | none: '\x1B[0m'
57 | };
58 |
59 | this.jasmineStarted = function() {
60 | specCount = 0;
61 | failureCount = 0;
62 | pendingCount = 0;
63 | print('Started');
64 | printNewline();
65 | timer.start();
66 | };
67 |
68 | this.jasmineDone = function() {
69 | printNewline();
70 | for (var i = 0; i < failedSpecs.length; i++) {
71 | specFailureDetails(failedSpecs[i]);
72 | }
73 |
74 | if(specCount > 0) {
75 | printNewline();
76 |
77 | var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' +
78 | failureCount + ' ' + plural('failure', failureCount);
79 |
80 | if (pendingCount) {
81 | specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount);
82 | }
83 |
84 | print(specCounts);
85 | } else {
86 | print('No specs found');
87 | }
88 |
89 | printNewline();
90 | var seconds = timer.elapsed() / 1000;
91 | print('Finished in ' + seconds + ' ' + plural('second', seconds));
92 |
93 | printNewline();
94 |
95 | onComplete(failureCount === 0);
96 | };
97 |
98 | this.specDone = function(result) {
99 | specCount++;
100 |
101 | if (result.status == 'pending') {
102 | pendingCount++;
103 | print(colored('yellow', '*'));
104 | return;
105 | }
106 |
107 | if (result.status == 'passed') {
108 | print(colored('green', '.'));
109 | return;
110 | }
111 |
112 | if (result.status == 'failed') {
113 | failureCount++;
114 | failedSpecs.push(result);
115 | print(colored('red', 'F'));
116 | }
117 | };
118 |
119 | return this;
120 |
121 | function printNewline() {
122 | print('\n');
123 | }
124 |
125 | function colored(color, str) {
126 | return showColors ? (ansi[color] + str + ansi.none) : str;
127 | }
128 |
129 | function plural(str, count) {
130 | return count == 1 ? str : str + 's';
131 | }
132 |
133 | function repeat(thing, times) {
134 | var arr = [];
135 | for (var i = 0; i < times; i++) {
136 | arr.push(thing);
137 | }
138 | return arr;
139 | }
140 |
141 | function indent(str, spaces) {
142 | var lines = (str || '').split('\n');
143 | var newArr = [];
144 | for (var i = 0; i < lines.length; i++) {
145 | newArr.push(repeat(' ', spaces).join('') + lines[i]);
146 | }
147 | return newArr.join('\n');
148 | }
149 |
150 | function specFailureDetails(result) {
151 | printNewline();
152 | print(result.fullName);
153 |
154 | for (var i = 0; i < result.failedExpectations.length; i++) {
155 | var failedExpectation = result.failedExpectations[i];
156 | printNewline();
157 | print(indent(failedExpectation.message, 2));
158 | print(indent(failedExpectation.stack, 2));
159 | }
160 |
161 | printNewline();
162 | }
163 | }
164 |
165 | return ConsoleReporter;
166 | };
167 |
--------------------------------------------------------------------------------
/ngPlaybook/Js/jasmine/jasmine-html.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2008-2014 Pivotal Labs
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining
5 | a copy of this software and associated documentation files (the
6 | "Software"), to deal in the Software without restriction, including
7 | without limitation the rights to use, copy, modify, merge, publish,
8 | distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so, subject to
10 | the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 | jasmineRequire.html = function(j$) {
24 | j$.ResultsNode = jasmineRequire.ResultsNode();
25 | j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
26 | j$.QueryString = jasmineRequire.QueryString();
27 | j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
28 | };
29 |
30 | jasmineRequire.HtmlReporter = function(j$) {
31 |
32 | var noopTimer = {
33 | start: function() {},
34 | elapsed: function() { return 0; }
35 | };
36 |
37 | function HtmlReporter(options) {
38 | var env = options.env || {},
39 | getContainer = options.getContainer,
40 | createElement = options.createElement,
41 | createTextNode = options.createTextNode,
42 | onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
43 | timer = options.timer || noopTimer,
44 | results = [],
45 | specsExecuted = 0,
46 | failureCount = 0,
47 | pendingSpecCount = 0,
48 | htmlReporterMain,
49 | symbols;
50 |
51 | this.initialize = function() {
52 | clearPrior();
53 | htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'},
54 | createDom('div', {className: 'banner'},
55 | createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}),
56 | createDom('span', {className: 'version'}, j$.version)
57 | ),
58 | createDom('ul', {className: 'symbol-summary'}),
59 | createDom('div', {className: 'alert'}),
60 | createDom('div', {className: 'results'},
61 | createDom('div', {className: 'failures'})
62 | )
63 | );
64 | getContainer().appendChild(htmlReporterMain);
65 |
66 | symbols = find('.symbol-summary');
67 | };
68 |
69 | var totalSpecsDefined;
70 | this.jasmineStarted = function(options) {
71 | totalSpecsDefined = options.totalSpecsDefined || 0;
72 | timer.start();
73 | };
74 |
75 | var summary = createDom('div', {className: 'summary'});
76 |
77 | var topResults = new j$.ResultsNode({}, '', null),
78 | currentParent = topResults;
79 |
80 | this.suiteStarted = function(result) {
81 | currentParent.addChild(result, 'suite');
82 | currentParent = currentParent.last();
83 | };
84 |
85 | this.suiteDone = function(result) {
86 | if (currentParent == topResults) {
87 | return;
88 | }
89 |
90 | currentParent = currentParent.parent;
91 | };
92 |
93 | this.specStarted = function(result) {
94 | currentParent.addChild(result, 'spec');
95 | };
96 |
97 | var failures = [];
98 | this.specDone = function(result) {
99 | if(noExpectations(result) && console && console.error) {
100 | console.error('Spec \'' + result.fullName + '\' has no expectations.');
101 | }
102 |
103 | if (result.status != 'disabled') {
104 | specsExecuted++;
105 | }
106 |
107 | symbols.appendChild(createDom('li', {
108 | className: noExpectations(result) ? 'empty' : result.status,
109 | id: 'spec_' + result.id,
110 | title: result.fullName
111 | }
112 | ));
113 |
114 | if (result.status == 'failed') {
115 | failureCount++;
116 |
117 | var failure =
118 | createDom('div', {className: 'spec-detail failed'},
119 | createDom('div', {className: 'description'},
120 | createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName)
121 | ),
122 | createDom('div', {className: 'messages'})
123 | );
124 | var messages = failure.childNodes[1];
125 |
126 | for (var i = 0; i < result.failedExpectations.length; i++) {
127 | var expectation = result.failedExpectations[i];
128 | messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message));
129 | messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack));
130 | }
131 |
132 | failures.push(failure);
133 | }
134 |
135 | if (result.status == 'pending') {
136 | pendingSpecCount++;
137 | }
138 | };
139 |
140 | this.jasmineDone = function() {
141 | var banner = find('.banner');
142 | banner.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
143 |
144 | var alert = find('.alert');
145 |
146 | alert.appendChild(createDom('span', { className: 'exceptions' },
147 | createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions'),
148 | createDom('input', {
149 | className: 'raise',
150 | id: 'raise-exceptions',
151 | type: 'checkbox'
152 | })
153 | ));
154 | var checkbox = find('#raise-exceptions');
155 |
156 | checkbox.checked = !env.catchingExceptions();
157 | checkbox.onclick = onRaiseExceptionsClick;
158 |
159 | if (specsExecuted < totalSpecsDefined) {
160 | var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
161 | alert.appendChild(
162 | createDom('span', {className: 'bar skipped'},
163 | createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage)
164 | )
165 | );
166 | }
167 | var statusBarMessage = '';
168 | var statusBarClassName = 'bar ';
169 |
170 | if (totalSpecsDefined > 0) {
171 | statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount);
172 | if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); }
173 | statusBarClassName += (failureCount > 0) ? 'failed' : 'passed';
174 | } else {
175 | statusBarClassName += 'skipped';
176 | statusBarMessage += 'No specs found';
177 | }
178 |
179 | alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage));
180 |
181 | var results = find('.results');
182 | results.appendChild(summary);
183 |
184 | summaryList(topResults, summary);
185 |
186 | function summaryList(resultsTree, domParent) {
187 | var specListNode;
188 | for (var i = 0; i < resultsTree.children.length; i++) {
189 | var resultNode = resultsTree.children[i];
190 | if (resultNode.type == 'suite') {
191 | var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id},
192 | createDom('li', {className: 'suite-detail'},
193 | createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
194 | )
195 | );
196 |
197 | summaryList(resultNode, suiteListNode);
198 | domParent.appendChild(suiteListNode);
199 | }
200 | if (resultNode.type == 'spec') {
201 | if (domParent.getAttribute('class') != 'specs') {
202 | specListNode = createDom('ul', {className: 'specs'});
203 | domParent.appendChild(specListNode);
204 | }
205 | var specDescription = resultNode.result.description;
206 | if(noExpectations(resultNode.result)) {
207 | specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
208 | }
209 | specListNode.appendChild(
210 | createDom('li', {
211 | className: resultNode.result.status,
212 | id: 'spec-' + resultNode.result.id
213 | },
214 | createDom('a', {href: specHref(resultNode.result)}, specDescription)
215 | )
216 | );
217 | }
218 | }
219 | }
220 |
221 | if (failures.length) {
222 | alert.appendChild(
223 | createDom('span', {className: 'menu bar spec-list'},
224 | createDom('span', {}, 'Spec List | '),
225 | createDom('a', {className: 'failures-menu', href: '#'}, 'Failures')));
226 | alert.appendChild(
227 | createDom('span', {className: 'menu bar failure-list'},
228 | createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'),
229 | createDom('span', {}, ' | Failures ')));
230 |
231 | find('.failures-menu').onclick = function() {
232 | setMenuModeTo('failure-list');
233 | };
234 | find('.spec-list-menu').onclick = function() {
235 | setMenuModeTo('spec-list');
236 | };
237 |
238 | setMenuModeTo('failure-list');
239 |
240 | var failureNode = find('.failures');
241 | for (var i = 0; i < failures.length; i++) {
242 | failureNode.appendChild(failures[i]);
243 | }
244 | }
245 | };
246 |
247 | return this;
248 |
249 | function find(selector) {
250 | return getContainer().querySelector('.jasmine_html-reporter ' + selector);
251 | }
252 |
253 | function clearPrior() {
254 | // return the reporter
255 | var oldReporter = find('');
256 |
257 | if(oldReporter) {
258 | getContainer().removeChild(oldReporter);
259 | }
260 | }
261 |
262 | function createDom(type, attrs, childrenVarArgs) {
263 | var el = createElement(type);
264 |
265 | for (var i = 2; i < arguments.length; i++) {
266 | var child = arguments[i];
267 |
268 | if (typeof child === 'string') {
269 | el.appendChild(createTextNode(child));
270 | } else {
271 | if (child) {
272 | el.appendChild(child);
273 | }
274 | }
275 | }
276 |
277 | for (var attr in attrs) {
278 | if (attr == 'className') {
279 | el[attr] = attrs[attr];
280 | } else {
281 | el.setAttribute(attr, attrs[attr]);
282 | }
283 | }
284 |
285 | return el;
286 | }
287 |
288 | function pluralize(singular, count) {
289 | var word = (count == 1 ? singular : singular + 's');
290 |
291 | return '' + count + ' ' + word;
292 | }
293 |
294 | function specHref(result) {
295 | return '?spec=' + encodeURIComponent(result.fullName);
296 | }
297 |
298 | function setMenuModeTo(mode) {
299 | htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode);
300 | }
301 |
302 | function noExpectations(result) {
303 | return (result.failedExpectations.length + result.passedExpectations.length) === 0 &&
304 | result.status === 'passed';
305 | }
306 | }
307 |
308 | return HtmlReporter;
309 | };
310 |
311 | jasmineRequire.HtmlSpecFilter = function() {
312 | function HtmlSpecFilter(options) {
313 | var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
314 | var filterPattern = new RegExp(filterString);
315 |
316 | this.matches = function(specName) {
317 | return filterPattern.test(specName);
318 | };
319 | }
320 |
321 | return HtmlSpecFilter;
322 | };
323 |
324 | jasmineRequire.ResultsNode = function() {
325 | function ResultsNode(result, type, parent) {
326 | this.result = result;
327 | this.type = type;
328 | this.parent = parent;
329 |
330 | this.children = [];
331 |
332 | this.addChild = function(result, type) {
333 | this.children.push(new ResultsNode(result, type, this));
334 | };
335 |
336 | this.last = function() {
337 | return this.children[this.children.length - 1];
338 | };
339 | }
340 |
341 | return ResultsNode;
342 | };
343 |
344 | jasmineRequire.QueryString = function() {
345 | function QueryString(options) {
346 |
347 | this.setParam = function(key, value) {
348 | var paramMap = queryStringToParamMap();
349 | paramMap[key] = value;
350 | options.getWindowLocation().search = toQueryString(paramMap);
351 | };
352 |
353 | this.getParam = function(key) {
354 | return queryStringToParamMap()[key];
355 | };
356 |
357 | return this;
358 |
359 | function toQueryString(paramMap) {
360 | var qStrPairs = [];
361 | for (var prop in paramMap) {
362 | qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop]));
363 | }
364 | return '?' + qStrPairs.join('&');
365 | }
366 |
367 | function queryStringToParamMap() {
368 | var paramStr = options.getWindowLocation().search.substring(1),
369 | params = [],
370 | paramMap = {};
371 |
372 | if (paramStr.length > 0) {
373 | params = paramStr.split('&');
374 | for (var i = 0; i < params.length; i++) {
375 | var p = params[i].split('=');
376 | var value = decodeURIComponent(p[1]);
377 | if (value === 'true' || value === 'false') {
378 | value = JSON.parse(value);
379 | }
380 | paramMap[decodeURIComponent(p[0])] = value;
381 | }
382 | }
383 |
384 | return paramMap;
385 | }
386 |
387 | }
388 |
389 | return QueryString;
390 | };
391 |
--------------------------------------------------------------------------------
/ngPlaybook/Js/jasmine/jasmine_favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OdeToCode/ngplaybook/8e1299cdae87c860d2828c4477f6db235e0d289a/ngPlaybook/Js/jasmine/jasmine_favicon.png
--------------------------------------------------------------------------------
/ngPlaybook/Js/tubular/tubular.js:
--------------------------------------------------------------------------------
1 | /* jQuery tubular plugin
2 | |* by Sean McCambridge
3 | |* http://www.seanmccambridge.com/tubular
4 | |* version: 1.0
5 | |* updated: October 1, 2012
6 | |* since 2010
7 | |* licensed under the MIT License
8 | |* Enjoy.
9 | |*
10 | |* Thanks,
11 | |* Sean */
12 |
13 | ; (function ($, window) {
14 |
15 | // test for feature support and return if failure
16 |
17 | // defaults
18 | var defaults = {
19 | ratio: 16 / 9, // usually either 4/3 or 16/9 -- tweak as needed
20 | videoId: 'ZCAnLxRvNNc', // toy robot in space is a good default, no?
21 | mute: true,
22 | repeat: true,
23 | width: $(window).width(),
24 | wrapperZIndex: 99,
25 | playButtonClass: 'tubular-play',
26 | pauseButtonClass: 'tubular-pause',
27 | muteButtonClass: 'tubular-mute',
28 | volumeUpClass: 'tubular-volume-up',
29 | volumeDownClass: 'tubular-volume-down',
30 | increaseVolumeBy: 10,
31 | start: 0
32 | };
33 |
34 | // methods
35 |
36 | var tubular = function (node, options) { // should be called on the wrapper div
37 | var options = $.extend({}, defaults, options),
38 | $body = $('body') // cache body node
39 | $node = $(node); // cache wrapper node
40 |
41 | // build container
42 | var tubularContainer = '