├── .gitignore
├── Gemfile
├── MIT-LICENSE
├── README.md
├── Rakefile
├── angularjs-rails.gemspec
├── lib
├── angularjs-rails.rb
└── angularjs-rails
│ ├── engine.rb
│ ├── sprockets.rb
│ └── version.rb
├── tasks
└── angularjs-rails
│ ├── stable_updater.rb
│ ├── unstable_updater.rb
│ └── updater.rb
└── vendor
└── assets
└── javascripts
├── angular-animate.js
├── angular-aria.js
├── angular-cookies.js
├── angular-loader.js
├── angular-message-format.js
├── angular-messages.js
├── angular-mocks.js
├── angular-parse-ext.js
├── angular-resource.js
├── angular-route.js
├── angular-sanitize.js
├── angular-touch.js
├── angular.js
└── unstable
├── angular2-polyfills.js
└── angular2.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.gem
3 | *.rbc
4 | .bundle
5 | .config
6 | .yardoc
7 | Gemfile.lock
8 | InstalledFiles
9 | _yardoc
10 | coverage
11 | doc/
12 | lib/bundler/man
13 | pkg
14 | rdoc
15 | spec/reports
16 | test/tmp
17 | test/version_tmp
18 | tmp
19 | /.idea
20 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Specify your gem's dependencies in angularjs-rails.gemspec
4 | gemspec
5 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Angular.JS RubyGem Copyright (c) 2012 Hirav Gandhi
2 |
3 | Angular.JS and related components Copyright (c) 2010-2012 Google Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angularjs-rails
2 |
3 | angularjs-rails wraps the [Angular.js](http://angularjs.org) library for use in Rails 3.1 and above. Assets will minify automatically during production.
4 |
5 | **If you find this gem useful, please consider donating - your contributions will help me keep this gem updated.**
6 |
7 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NCT7TZEFY2T9Y)
8 |
9 |
10 | ## Usage
11 |
12 | Add the following to your Gemfile:
13 |
14 | gem 'angularjs-rails'
15 |
16 | Add the following directive to your JavaScript manifest file (application.js):
17 |
18 | //= require angular
19 |
20 | If you desire to require (optional) Angular files, you may include them as well in your JavaScript manifest file (application.js). For example:
21 |
22 | //= require angular-animate
23 | //= require angular-resource
24 |
25 | To use the 'unstable' branch, add the following directive to your JavaScript manifest file (application.js):
26 |
27 | //= require unstable/angular2
28 |
29 | ## Versioning
30 |
31 | Every attempt is made to mirror the currently shipping Angular.js version number wherever possible.
32 |
33 | The major, minor, and patch version numbers will always represent the Angular.js version.
34 |
35 | ## IMPORTANT: Requesting upgrades for new Angular.js versions
36 |
37 | To request that the latest version of Angular.JS be pushed as a gem to RubyGems, please create a new issue instead of pull requests.
38 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | require "bundler/gem_tasks"
3 |
4 | require_relative 'tasks/angularjs-rails/stable_updater'
5 | require_relative 'tasks/angularjs-rails/unstable_updater'
6 |
7 | desc "Update Angular JS assets"
8 | task :update_angular do
9 | AngularJS::Rails::StableUpdater.update_js!
10 | AngularJS::Rails::UnstableUpdater.update_js!
11 | end
12 |
--------------------------------------------------------------------------------
/angularjs-rails.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 | require File.expand_path('../lib/angularjs-rails/version', __FILE__)
3 |
4 | Gem::Specification.new do |s|
5 | s.name = 'angularjs-rails'
6 | s.version = AngularJS::Rails::VERSION
7 | s.date = Time.new.strftime("%Y-%m-%d")
8 | s.summary = 'Angular.js on Rails'
9 | s.description = 'Injects Angular.js into your asset pipeline as well as other Angular modules.'
10 | s.authors = ["Hirav Gandhi"]
11 | s.email = 'hgandhi@alumni.stanford.edu'
12 | s.files = Dir["{lib,vendor}/**/*"] + ["MIT-LICENSE", "README.md"]
13 | s.homepage = 'https://github.com/hiravgandhi/angularjs-rails/'
14 | s.license = 'MIT'
15 |
16 | s.add_development_dependency 'rake'
17 | s.add_development_dependency 'versionomy'
18 | s.add_development_dependency 'nokogiri'
19 | end
20 |
--------------------------------------------------------------------------------
/lib/angularjs-rails.rb:
--------------------------------------------------------------------------------
1 | require "angularjs-rails/version"
2 |
3 | module AngularJS
4 | module Rails
5 | if defined? ::Rails::Engine
6 | require "angularjs-rails/engine"
7 | elsif defined? Sprockets
8 | require "angularjs-rails/sprockets"
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/angularjs-rails/engine.rb:
--------------------------------------------------------------------------------
1 | module AngularJS
2 | module Rails
3 | class Engine < ::Rails::Engine
4 | end
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/lib/angularjs-rails/sprockets.rb:
--------------------------------------------------------------------------------
1 | require 'sprockets'
2 |
3 | Sprockets.append_path File.expand_path("../../../vendor/assets/javascripts", __FILE__)
4 |
--------------------------------------------------------------------------------
/lib/angularjs-rails/version.rb:
--------------------------------------------------------------------------------
1 | module AngularJS
2 | module Rails
3 | VERSION = "1.8.0"
4 | UNSTABLE_VERSION = "2.0.0-beta.17"
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/tasks/angularjs-rails/stable_updater.rb:
--------------------------------------------------------------------------------
1 | require_relative 'updater'
2 |
3 | module AngularJS::Rails
4 | class StableUpdater < Updater
5 | def current_gem_version
6 | Versionomy.parse(AngularJS::Rails::VERSION).convert(:rubygems)
7 | end
8 |
9 | # Currently stable versions have even minor
10 | def own_version(version)
11 | version.release_type == :final
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/tasks/angularjs-rails/unstable_updater.rb:
--------------------------------------------------------------------------------
1 | require_relative 'updater'
2 |
3 | module AngularJS::Rails
4 | class UnstableUpdater < Updater
5 | def base_path
6 | ROOT_PATH.join('unstable')
7 | end
8 |
9 | def current_gem_version
10 | Versionomy.parse(AngularJS::Rails::UNSTABLE_VERSION).convert(:rubygems)
11 | end
12 |
13 | def own_version(version)
14 | # Currently unstable versions have some minor
15 | version.release_type != :final
16 | end
17 |
18 | def version_constant_name
19 | "UNSTABLE_VERSION"
20 | end
21 |
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/tasks/angularjs-rails/updater.rb:
--------------------------------------------------------------------------------
1 | require 'nokogiri'
2 | require 'open-uri'
3 | require 'versionomy'
4 | require 'pathname'
5 | require 'tempfile'
6 |
7 | module AngularJS::Rails
8 | class Updater
9 | BASE_URL = 'https://code.angularjs.org'
10 | ROOT_PATH = Pathname.new('vendor/assets/javascripts')
11 |
12 | def initialize
13 | end
14 |
15 | def base_path
16 | ROOT_PATH
17 | end
18 |
19 | def update_js!
20 | if latest_version >= current_gem_version
21 | clean
22 | download_files
23 | update_version_to(latest_version)
24 | end
25 | end
26 |
27 | def current_gem_version
28 | raise NotImplementedError
29 | end
30 |
31 | def available_versions
32 | upstream_versions.find_all {|v| own_version(v) }
33 | end
34 |
35 | def latest_version
36 | available_versions.last
37 | end
38 |
39 | def version_constant_name
40 | "VERSION"
41 | end
42 |
43 | private
44 |
45 | def clean
46 | base_path.children.each do |f|
47 | f.delete if f.file?
48 | end
49 | end
50 |
51 | def update_version_to(version)
52 | version_file = Pathname.new('lib/angularjs-rails/version.rb')
53 | content = version_file.read
54 | version_line = content.lines.find { |l| l =~ /^\s+#{version_constant_name}/ }
55 |
56 | # version_to_convert = Versionomy.parse(version).convert(:rubygems).to_s
57 |
58 | new_version_line = version_line.gsub(/"[^"]+"/, %Q{"#{version}"})
59 | version_file.open('w+') do |f|
60 | f.write content.gsub(version_line, new_version_line)
61 | end
62 | end
63 |
64 | def upstream_versions
65 | @upstream_versions ||= Nokogiri::HTML.parse(open(BASE_URL)).
66 | css('a').map { |e| Versionomy.parse e.text[0..-2] rescue nil }.compact.sort
67 | end
68 |
69 | def own_version(v)
70 | true
71 | end
72 |
73 | def self.update_js!
74 | self.new.update_js!
75 | end
76 |
77 | def download_files
78 | url = BASE_URL + "/" + latest_version.to_s
79 | Nokogiri::HTML.parse(open(url)).
80 | css('a').
81 |
82 | #only angular js files
83 | map{|a| a[:href] =~ /angular[^.]*\.js/ ? a : nil }.compact.
84 |
85 | each do |a|
86 | download_file(a[:href], url)
87 | end
88 | end
89 |
90 | def download_file(file, url)
91 | full_url = url + "/" + file
92 | full_path = base_path.join(file)
93 | full_path.open('w+') do |f|
94 | f.write open(full_url).read
95 | end
96 | end
97 | end
98 | end
99 |
100 |
101 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/angular-aria.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license AngularJS v1.8.0
3 | * (c) 2010-2020 Google, Inc. http://angularjs.org
4 | * License: MIT
5 | */
6 | (function(window, angular) {'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 | * ## Usage
19 | *
20 | * For ngAria to do its magic, simply include the module `ngAria` as a dependency. The following
21 | * directives are supported:
22 | * `ngModel`, `ngChecked`, `ngReadonly`, `ngRequired`, `ngValue`, `ngDisabled`, `ngShow`, `ngHide`,
23 | * `ngClick`, `ngDblClick`, and `ngMessages`.
24 | *
25 | * Below is a more detailed breakdown of the attributes handled by ngAria:
26 | *
27 | * | Directive | Supported Attributes |
28 | * |---------------------------------------------|-----------------------------------------------------------------------------------------------------|
29 | * | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required, input roles |
30 | * | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled |
31 | * | {@link ng.directive:ngRequired ngRequired} | aria-required |
32 | * | {@link ng.directive:ngChecked ngChecked} | aria-checked |
33 | * | {@link ng.directive:ngReadonly ngReadonly} | aria-readonly |
34 | * | {@link ng.directive:ngValue ngValue} | aria-checked |
35 | * | {@link ng.directive:ngShow ngShow} | aria-hidden |
36 | * | {@link ng.directive:ngHide ngHide} | aria-hidden |
37 | * | {@link ng.directive:ngDblclick ngDblclick} | tabindex |
38 | * | {@link module:ngMessages ngMessages} | aria-live |
39 | * | {@link ng.directive:ngClick ngClick} | tabindex, keydown event, button role |
40 | *
41 | * Find out more information about each directive by reading the
42 | * {@link guide/accessibility ngAria Developer Guide}.
43 | *
44 | * ## Example
45 | * Using ngDisabled with ngAria:
46 | * ```html
47 | *
48 | * ```
49 | * Becomes:
50 | * ```html
51 | *
52 | * ```
53 | *
54 | * ## Disabling Specific Attributes
55 | * It is possible to disable individual attributes added by ngAria with the
56 | * {@link ngAria.$ariaProvider#config config} method. For more details, see the
57 | * {@link guide/accessibility Developer Guide}.
58 | *
59 | * ## Disabling `ngAria` on Specific Elements
60 | * It is possible to make `ngAria` ignore a specific element, by adding the `ng-aria-disable`
61 | * attribute on it. Note that only the element itself (and not its child elements) will be ignored.
62 | */
63 | var ARIA_DISABLE_ATTR = 'ngAriaDisable';
64 |
65 | var ngAriaModule = angular.module('ngAria', ['ng']).
66 | info({ angularVersion: '1.8.0' }).
67 | provider('$aria', $AriaProvider);
68 |
69 | /**
70 | * Internal Utilities
71 | */
72 | var nodeBlackList = ['BUTTON', 'A', 'INPUT', 'TEXTAREA', 'SELECT', 'DETAILS', 'SUMMARY'];
73 |
74 | var isNodeOneOf = function(elem, nodeTypeArray) {
75 | if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) {
76 | return true;
77 | }
78 | };
79 | /**
80 | * @ngdoc provider
81 | * @name $ariaProvider
82 | * @this
83 | *
84 | * @description
85 | *
86 | * Used for configuring the ARIA attributes injected and managed by ngAria.
87 | *
88 | * ```js
89 | * angular.module('myApp', ['ngAria'], function config($ariaProvider) {
90 | * $ariaProvider.config({
91 | * ariaValue: true,
92 | * tabindex: false
93 | * });
94 | * });
95 | *```
96 | *
97 | * ## Dependencies
98 | * Requires the {@link ngAria} module to be installed.
99 | *
100 | */
101 | function $AriaProvider() {
102 | var config = {
103 | ariaHidden: true,
104 | ariaChecked: true,
105 | ariaReadonly: true,
106 | ariaDisabled: true,
107 | ariaRequired: true,
108 | ariaInvalid: true,
109 | ariaValue: true,
110 | tabindex: true,
111 | bindKeydown: true,
112 | bindRoleForClick: true
113 | };
114 |
115 | /**
116 | * @ngdoc method
117 | * @name $ariaProvider#config
118 | *
119 | * @param {object} config object to enable/disable specific ARIA attributes
120 | *
121 | * - **ariaHidden** – `{boolean}` – Enables/disables aria-hidden tags
122 | * - **ariaChecked** – `{boolean}` – Enables/disables aria-checked tags
123 | * - **ariaReadonly** – `{boolean}` – Enables/disables aria-readonly tags
124 | * - **ariaDisabled** – `{boolean}` – Enables/disables aria-disabled tags
125 | * - **ariaRequired** – `{boolean}` – Enables/disables aria-required tags
126 | * - **ariaInvalid** – `{boolean}` – Enables/disables aria-invalid tags
127 | * - **ariaValue** – `{boolean}` – Enables/disables aria-valuemin, aria-valuemax and
128 | * aria-valuenow tags
129 | * - **tabindex** – `{boolean}` – Enables/disables tabindex tags
130 | * - **bindKeydown** – `{boolean}` – Enables/disables keyboard event binding on non-interactive
131 | * elements (such as `div` or `li`) using ng-click, making them more accessible to users of
132 | * assistive technologies
133 | * - **bindRoleForClick** – `{boolean}` – Adds role=button to non-interactive elements (such as
134 | * `div` or `li`) using ng-click, making them more accessible to users of assistive
135 | * technologies
136 | *
137 | * @description
138 | * Enables/disables various ARIA attributes
139 | */
140 | this.config = function(newConfig) {
141 | config = angular.extend(config, newConfig);
142 | };
143 |
144 | function watchExpr(attrName, ariaAttr, nodeBlackList, negate) {
145 | return function(scope, elem, attr) {
146 | if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return;
147 |
148 | var ariaCamelName = attr.$normalize(ariaAttr);
149 | if (config[ariaCamelName] && !isNodeOneOf(elem, nodeBlackList) && !attr[ariaCamelName]) {
150 | scope.$watch(attr[attrName], function(boolVal) {
151 | // ensure boolean value
152 | boolVal = negate ? !boolVal : !!boolVal;
153 | elem.attr(ariaAttr, boolVal);
154 | });
155 | }
156 | };
157 | }
158 | /**
159 | * @ngdoc service
160 | * @name $aria
161 | *
162 | * @description
163 | *
164 | * The $aria service contains helper methods for applying common
165 | * [ARIA](http://www.w3.org/TR/wai-aria/) attributes to HTML directives.
166 | *
167 | * ngAria injects common accessibility attributes that tell assistive technologies when HTML
168 | * elements are enabled, selected, hidden, and more. To see how this is performed with ngAria,
169 | * let's review a code snippet from ngAria itself:
170 | *
171 | *```js
172 | * ngAriaModule.directive('ngDisabled', ['$aria', function($aria) {
173 | * return $aria.$$watchExpr('ngDisabled', 'aria-disabled', nodeBlackList, false);
174 | * }])
175 | *```
176 | * Shown above, the ngAria module creates a directive with the same signature as the
177 | * traditional `ng-disabled` directive. But this ngAria version is dedicated to
178 | * solely managing accessibility attributes on custom elements. The internal `$aria` service is
179 | * used to watch the boolean attribute `ngDisabled`. If it has not been explicitly set by the
180 | * developer, `aria-disabled` is injected as an attribute with its value synchronized to the
181 | * value in `ngDisabled`.
182 | *
183 | * Because ngAria hooks into the `ng-disabled` directive, developers do not have to do
184 | * anything to enable this feature. The `aria-disabled` attribute is automatically managed
185 | * simply as a silent side-effect of using `ng-disabled` with the ngAria module.
186 | *
187 | * The full list of directives that interface with ngAria:
188 | * * **ngModel**
189 | * * **ngChecked**
190 | * * **ngReadonly**
191 | * * **ngRequired**
192 | * * **ngDisabled**
193 | * * **ngValue**
194 | * * **ngShow**
195 | * * **ngHide**
196 | * * **ngClick**
197 | * * **ngDblclick**
198 | * * **ngMessages**
199 | *
200 | * Read the {@link guide/accessibility ngAria Developer Guide} for a thorough explanation of each
201 | * directive.
202 | *
203 | *
204 | * ## Dependencies
205 | * Requires the {@link ngAria} module to be installed.
206 | */
207 | this.$get = function() {
208 | return {
209 | config: function(key) {
210 | return config[key];
211 | },
212 | $$watchExpr: watchExpr
213 | };
214 | };
215 | }
216 |
217 |
218 | ngAriaModule.directive('ngShow', ['$aria', function($aria) {
219 | return $aria.$$watchExpr('ngShow', 'aria-hidden', [], true);
220 | }])
221 | .directive('ngHide', ['$aria', function($aria) {
222 | return $aria.$$watchExpr('ngHide', 'aria-hidden', [], false);
223 | }])
224 | .directive('ngValue', ['$aria', function($aria) {
225 | return $aria.$$watchExpr('ngValue', 'aria-checked', nodeBlackList, false);
226 | }])
227 | .directive('ngChecked', ['$aria', function($aria) {
228 | return $aria.$$watchExpr('ngChecked', 'aria-checked', nodeBlackList, false);
229 | }])
230 | .directive('ngReadonly', ['$aria', function($aria) {
231 | return $aria.$$watchExpr('ngReadonly', 'aria-readonly', nodeBlackList, false);
232 | }])
233 | .directive('ngRequired', ['$aria', function($aria) {
234 | return $aria.$$watchExpr('ngRequired', 'aria-required', nodeBlackList, false);
235 | }])
236 | .directive('ngModel', ['$aria', function($aria) {
237 |
238 | function shouldAttachAttr(attr, normalizedAttr, elem, allowBlacklistEls) {
239 | return $aria.config(normalizedAttr) &&
240 | !elem.attr(attr) &&
241 | (allowBlacklistEls || !isNodeOneOf(elem, nodeBlackList)) &&
242 | (elem.attr('type') !== 'hidden' || elem[0].nodeName !== 'INPUT');
243 | }
244 |
245 | function shouldAttachRole(role, elem) {
246 | // if element does not have role attribute
247 | // AND element type is equal to role (if custom element has a type equaling shape) <-- remove?
248 | // AND element is not in nodeBlackList
249 | return !elem.attr('role') && (elem.attr('type') === role) && !isNodeOneOf(elem, nodeBlackList);
250 | }
251 |
252 | function getShape(attr, elem) {
253 | var type = attr.type,
254 | role = attr.role;
255 |
256 | return ((type || role) === 'checkbox' || role === 'menuitemcheckbox') ? 'checkbox' :
257 | ((type || role) === 'radio' || role === 'menuitemradio') ? 'radio' :
258 | (type === 'range' || role === 'progressbar' || role === 'slider') ? 'range' : '';
259 | }
260 |
261 | return {
262 | restrict: 'A',
263 | require: 'ngModel',
264 | priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value
265 | compile: function(elem, attr) {
266 | if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return;
267 |
268 | var shape = getShape(attr, elem);
269 |
270 | return {
271 | post: function(scope, elem, attr, ngModel) {
272 | var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem, false);
273 |
274 | function ngAriaWatchModelValue() {
275 | return ngModel.$modelValue;
276 | }
277 |
278 | function getRadioReaction(newVal) {
279 | // Strict comparison would cause a BC
280 | // eslint-disable-next-line eqeqeq
281 | var boolVal = (attr.value == ngModel.$viewValue);
282 | elem.attr('aria-checked', boolVal);
283 | }
284 |
285 | function getCheckboxReaction() {
286 | elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue));
287 | }
288 |
289 | switch (shape) {
290 | case 'radio':
291 | case 'checkbox':
292 | if (shouldAttachRole(shape, elem)) {
293 | elem.attr('role', shape);
294 | }
295 | if (shouldAttachAttr('aria-checked', 'ariaChecked', elem, false)) {
296 | scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
297 | getRadioReaction : getCheckboxReaction);
298 | }
299 | if (needsTabIndex) {
300 | elem.attr('tabindex', 0);
301 | }
302 | break;
303 | case 'range':
304 | if (shouldAttachRole(shape, elem)) {
305 | elem.attr('role', 'slider');
306 | }
307 | if ($aria.config('ariaValue')) {
308 | var needsAriaValuemin = !elem.attr('aria-valuemin') &&
309 | (attr.hasOwnProperty('min') || attr.hasOwnProperty('ngMin'));
310 | var needsAriaValuemax = !elem.attr('aria-valuemax') &&
311 | (attr.hasOwnProperty('max') || attr.hasOwnProperty('ngMax'));
312 | var needsAriaValuenow = !elem.attr('aria-valuenow');
313 |
314 | if (needsAriaValuemin) {
315 | attr.$observe('min', function ngAriaValueMinReaction(newVal) {
316 | elem.attr('aria-valuemin', newVal);
317 | });
318 | }
319 | if (needsAriaValuemax) {
320 | attr.$observe('max', function ngAriaValueMinReaction(newVal) {
321 | elem.attr('aria-valuemax', newVal);
322 | });
323 | }
324 | if (needsAriaValuenow) {
325 | scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) {
326 | elem.attr('aria-valuenow', newVal);
327 | });
328 | }
329 | }
330 | if (needsTabIndex) {
331 | elem.attr('tabindex', 0);
332 | }
333 | break;
334 | }
335 |
336 | if (!attr.hasOwnProperty('ngRequired') && ngModel.$validators.required
337 | && shouldAttachAttr('aria-required', 'ariaRequired', elem, false)) {
338 | // ngModel.$error.required is undefined on custom controls
339 | attr.$observe('required', function() {
340 | elem.attr('aria-required', !!attr['required']);
341 | });
342 | }
343 |
344 | if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem, true)) {
345 | scope.$watch(function ngAriaInvalidWatch() {
346 | return ngModel.$invalid;
347 | }, function ngAriaInvalidReaction(newVal) {
348 | elem.attr('aria-invalid', !!newVal);
349 | });
350 | }
351 | }
352 | };
353 | }
354 | };
355 | }])
356 | .directive('ngDisabled', ['$aria', function($aria) {
357 | return $aria.$$watchExpr('ngDisabled', 'aria-disabled', nodeBlackList, false);
358 | }])
359 | .directive('ngMessages', function() {
360 | return {
361 | restrict: 'A',
362 | require: '?ngMessages',
363 | link: function(scope, elem, attr, ngMessages) {
364 | if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return;
365 |
366 | if (!elem.attr('aria-live')) {
367 | elem.attr('aria-live', 'assertive');
368 | }
369 | }
370 | };
371 | })
372 | .directive('ngClick',['$aria', '$parse', function($aria, $parse) {
373 | return {
374 | restrict: 'A',
375 | compile: function(elem, attr) {
376 | if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return;
377 |
378 | var fn = $parse(attr.ngClick);
379 | return function(scope, elem, attr) {
380 |
381 | if (!isNodeOneOf(elem, nodeBlackList)) {
382 |
383 | if ($aria.config('bindRoleForClick') && !elem.attr('role')) {
384 | elem.attr('role', 'button');
385 | }
386 |
387 | if ($aria.config('tabindex') && !elem.attr('tabindex')) {
388 | elem.attr('tabindex', 0);
389 | }
390 |
391 | if ($aria.config('bindKeydown') && !attr.ngKeydown && !attr.ngKeypress && !attr.ngKeyup) {
392 | elem.on('keydown', function(event) {
393 | var keyCode = event.which || event.keyCode;
394 |
395 | if (keyCode === 13 || keyCode === 32) {
396 | // If the event is triggered on a non-interactive element ...
397 | if (nodeBlackList.indexOf(event.target.nodeName) === -1 && !event.target.isContentEditable) {
398 | // ... prevent the default browser behavior (e.g. scrolling when pressing spacebar)
399 | // See https://github.com/angular/angular.js/issues/16664
400 | event.preventDefault();
401 | }
402 | scope.$apply(callback);
403 | }
404 |
405 | function callback() {
406 | fn(scope, { $event: event });
407 | }
408 | });
409 | }
410 | }
411 | };
412 | }
413 | };
414 | }])
415 | .directive('ngDblclick', ['$aria', function($aria) {
416 | return function(scope, elem, attr) {
417 | if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return;
418 |
419 | if ($aria.config('tabindex') && !elem.attr('tabindex') && !isNodeOneOf(elem, nodeBlackList)) {
420 | elem.attr('tabindex', 0);
421 | }
422 | };
423 | }]);
424 |
425 |
426 | })(window, window.angular);
427 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/angular-cookies.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license AngularJS v1.8.0
3 | * (c) 2010-2020 Google, Inc. http://angularjs.org
4 | * License: MIT
5 | */
6 | (function(window, angular) {'use strict';
7 |
8 | /**
9 | * @ngdoc module
10 | * @name ngCookies
11 | * @description
12 | *
13 | * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
14 | *
15 | * See {@link ngCookies.$cookies `$cookies`} for usage.
16 | */
17 |
18 |
19 | angular.module('ngCookies', ['ng']).
20 | info({ angularVersion: '1.8.0' }).
21 | /**
22 | * @ngdoc provider
23 | * @name $cookiesProvider
24 | * @description
25 | * Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
26 | * */
27 | provider('$cookies', [/** @this */function $CookiesProvider() {
28 | /**
29 | * @ngdoc property
30 | * @name $cookiesProvider#defaults
31 | * @description
32 | *
33 | * Object containing default options to pass when setting cookies.
34 | *
35 | * The object may have following properties:
36 | *
37 | * - **path** - `{string}` - The cookie will be available only for this path and its
38 | * sub-paths. By default, this is the URL that appears in your `` tag.
39 | * - **domain** - `{string}` - The cookie will be available only for this domain and
40 | * its sub-domains. For security reasons the user agent will not accept the cookie
41 | * if the current domain is not a sub-domain of this domain or equal to it.
42 | * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
43 | * or a Date object indicating the exact date/time this cookie will expire.
44 | * - **secure** - `{boolean}` - If `true`, then the cookie will only be available through a
45 | * secured connection.
46 | * - **samesite** - `{string}` - prevents the browser from sending the cookie along with cross-site requests.
47 | * Accepts the values `lax` and `strict`. See the [OWASP Wiki](https://www.owasp.org/index.php/SameSite)
48 | * for more info. Note that as of May 2018, not all browsers support `SameSite`,
49 | * so it cannot be used as a single measure against Cross-Site-Request-Forgery (CSRF) attacks.
50 | *
51 | * Note: By default, the address that appears in your `` tag will be used as the path.
52 | * This is important so that cookies will be visible for all routes when html5mode is enabled.
53 | *
54 | * @example
55 | *
56 | * ```js
57 | * angular.module('cookiesProviderExample', ['ngCookies'])
58 | * .config(['$cookiesProvider', function($cookiesProvider) {
59 | * // Setting default options
60 | * $cookiesProvider.defaults.domain = 'foo.com';
61 | * $cookiesProvider.defaults.secure = true;
62 | * }]);
63 | * ```
64 | **/
65 | var defaults = this.defaults = {};
66 |
67 | function calcOptions(options) {
68 | return options ? angular.extend({}, defaults, options) : defaults;
69 | }
70 |
71 | /**
72 | * @ngdoc service
73 | * @name $cookies
74 | *
75 | * @description
76 | * Provides read/write access to browser's cookies.
77 | *
78 | *
79 | * Up until AngularJS 1.3, `$cookies` exposed properties that represented the
80 | * current browser cookie values. In version 1.4, this behavior has changed, and
81 | * `$cookies` now provides a standard api of getters, setters etc.
82 | *
83 | *
84 | * Requires the {@link ngCookies `ngCookies`} module to be installed.
85 | *
86 | * @example
87 | *
88 | * ```js
89 | * angular.module('cookiesExample', ['ngCookies'])
90 | * .controller('ExampleController', ['$cookies', function($cookies) {
91 | * // Retrieving a cookie
92 | * var favoriteCookie = $cookies.get('myFavorite');
93 | * // Setting a cookie
94 | * $cookies.put('myFavorite', 'oatmeal');
95 | * }]);
96 | * ```
97 | */
98 | this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
99 | return {
100 | /**
101 | * @ngdoc method
102 | * @name $cookies#get
103 | *
104 | * @description
105 | * Returns the value of given cookie key
106 | *
107 | * @param {string} key Id to use for lookup.
108 | * @returns {string} Raw cookie value.
109 | */
110 | get: function(key) {
111 | return $$cookieReader()[key];
112 | },
113 |
114 | /**
115 | * @ngdoc method
116 | * @name $cookies#getObject
117 | *
118 | * @description
119 | * Returns the deserialized value of given cookie key
120 | *
121 | * @param {string} key Id to use for lookup.
122 | * @returns {Object} Deserialized cookie value.
123 | */
124 | getObject: function(key) {
125 | var value = this.get(key);
126 | return value ? angular.fromJson(value) : value;
127 | },
128 |
129 | /**
130 | * @ngdoc method
131 | * @name $cookies#getAll
132 | *
133 | * @description
134 | * Returns a key value object with all the cookies
135 | *
136 | * @returns {Object} All cookies
137 | */
138 | getAll: function() {
139 | return $$cookieReader();
140 | },
141 |
142 | /**
143 | * @ngdoc method
144 | * @name $cookies#put
145 | *
146 | * @description
147 | * Sets a value for given cookie key
148 | *
149 | * @param {string} key Id for the `value`.
150 | * @param {string} value Raw value to be stored.
151 | * @param {Object=} options Options object.
152 | * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
153 | */
154 | put: function(key, value, options) {
155 | $$cookieWriter(key, value, calcOptions(options));
156 | },
157 |
158 | /**
159 | * @ngdoc method
160 | * @name $cookies#putObject
161 | *
162 | * @description
163 | * Serializes and sets a value for given cookie key
164 | *
165 | * @param {string} key Id for the `value`.
166 | * @param {Object} value Value to be stored.
167 | * @param {Object=} options Options object.
168 | * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
169 | */
170 | putObject: function(key, value, options) {
171 | this.put(key, angular.toJson(value), options);
172 | },
173 |
174 | /**
175 | * @ngdoc method
176 | * @name $cookies#remove
177 | *
178 | * @description
179 | * Remove given cookie
180 | *
181 | * @param {string} key Id of the key-value pair to delete.
182 | * @param {Object=} options Options object.
183 | * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
184 | */
185 | remove: function(key, options) {
186 | $$cookieWriter(key, undefined, calcOptions(options));
187 | }
188 | };
189 | }];
190 | }]);
191 |
192 | /**
193 | * @name $$cookieWriter
194 | * @requires $document
195 | *
196 | * @description
197 | * This is a private service for writing cookies
198 | *
199 | * @param {string} name Cookie name
200 | * @param {string=} value Cookie value (if undefined, cookie will be deleted)
201 | * @param {Object=} options Object with options that need to be stored for the cookie.
202 | */
203 | function $$CookieWriter($document, $log, $browser) {
204 | var cookiePath = $browser.baseHref();
205 | var rawDocument = $document[0];
206 |
207 | function buildCookieString(name, value, options) {
208 | var path, expires;
209 | options = options || {};
210 | expires = options.expires;
211 | path = angular.isDefined(options.path) ? options.path : cookiePath;
212 | if (angular.isUndefined(value)) {
213 | expires = 'Thu, 01 Jan 1970 00:00:00 GMT';
214 | value = '';
215 | }
216 | if (angular.isString(expires)) {
217 | expires = new Date(expires);
218 | }
219 |
220 | var str = encodeURIComponent(name) + '=' + encodeURIComponent(value);
221 | str += path ? ';path=' + path : '';
222 | str += options.domain ? ';domain=' + options.domain : '';
223 | str += expires ? ';expires=' + expires.toUTCString() : '';
224 | str += options.secure ? ';secure' : '';
225 | str += options.samesite ? ';samesite=' + options.samesite : '';
226 |
227 | // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
228 | // - 300 cookies
229 | // - 20 cookies per unique domain
230 | // - 4096 bytes per cookie
231 | var cookieLength = str.length + 1;
232 | if (cookieLength > 4096) {
233 | $log.warn('Cookie \'' + name +
234 | '\' possibly not set or overflowed because it was too large (' +
235 | cookieLength + ' > 4096 bytes)!');
236 | }
237 |
238 | return str;
239 | }
240 |
241 | return function(name, value, options) {
242 | rawDocument.cookie = buildCookieString(name, value, options);
243 | };
244 | }
245 |
246 | $$CookieWriter.$inject = ['$document', '$log', '$browser'];
247 |
248 | angular.module('ngCookies').provider('$$cookieWriter', /** @this */ function $$CookieWriterProvider() {
249 | this.$get = $$CookieWriter;
250 | });
251 |
252 |
253 | })(window, window.angular);
254 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/angular-loader.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license AngularJS v1.8.0
3 | * (c) 2010-2020 Google, Inc. http://angularjs.org
4 | * License: MIT
5 | */
6 |
7 | (function() {'use strict';
8 | // NOTE:
9 | // These functions are copied here from `src/Angular.js`, because they are needed inside the
10 | // `angular-loader.js` closure and need to be available before the main `angular.js` script has
11 | // been loaded.
12 | function isFunction(value) {return typeof value === 'function';}
13 | function isDefined(value) {return typeof value !== 'undefined';}
14 | function isNumber(value) {return typeof value === 'number';}
15 | function isObject(value) {return value !== null && typeof value === 'object';}
16 | function isScope(obj) {return obj && obj.$evalAsync && obj.$watch;}
17 | function isUndefined(value) {return typeof value === 'undefined';}
18 | function isWindow(obj) {return obj && obj.window === obj;}
19 | function sliceArgs(args, startIndex) {return Array.prototype.slice.call(args, startIndex || 0);}
20 | function toJsonReplacer(key, value) {
21 | var val = value;
22 |
23 | if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
24 | val = undefined;
25 | } else if (isWindow(value)) {
26 | val = '$WINDOW';
27 | } else if (value && window.document === value) {
28 | val = '$DOCUMENT';
29 | } else if (isScope(value)) {
30 | val = '$SCOPE';
31 | }
32 |
33 | return val;
34 | }
35 |
36 | /* exported toDebugString */
37 |
38 | function serializeObject(obj, maxDepth) {
39 | var seen = [];
40 |
41 | // There is no direct way to stringify object until reaching a specific depth
42 | // and a very deep object can cause a performance issue, so we copy the object
43 | // based on this specific depth and then stringify it.
44 | if (isValidObjectMaxDepth(maxDepth)) {
45 | // This file is also included in `angular-loader`, so `copy()` might not always be available in
46 | // the closure. Therefore, it is lazily retrieved as `angular.copy()` when needed.
47 | obj = angular.copy(obj, null, maxDepth);
48 | }
49 | return JSON.stringify(obj, function(key, val) {
50 | val = toJsonReplacer(key, val);
51 | if (isObject(val)) {
52 |
53 | if (seen.indexOf(val) >= 0) return '...';
54 |
55 | seen.push(val);
56 | }
57 | return val;
58 | });
59 | }
60 |
61 | function toDebugString(obj, maxDepth) {
62 | if (typeof obj === 'function') {
63 | return obj.toString().replace(/ \{[\s\S]*$/, '');
64 | } else if (isUndefined(obj)) {
65 | return 'undefined';
66 | } else if (typeof obj !== 'string') {
67 | return serializeObject(obj, maxDepth);
68 | }
69 | return obj;
70 | }
71 |
72 | /* exported
73 | minErrConfig,
74 | errorHandlingConfig,
75 | isValidObjectMaxDepth
76 | */
77 |
78 | var minErrConfig = {
79 | objectMaxDepth: 5,
80 | urlErrorParamsEnabled: true
81 | };
82 |
83 | /**
84 | * @ngdoc function
85 | * @name angular.errorHandlingConfig
86 | * @module ng
87 | * @kind function
88 | *
89 | * @description
90 | * Configure several aspects of error handling in AngularJS if used as a setter or return the
91 | * current configuration if used as a getter. The following options are supported:
92 | *
93 | * - **objectMaxDepth**: The maximum depth to which objects are traversed when stringified for error messages.
94 | *
95 | * Omitted or undefined options will leave the corresponding configuration values unchanged.
96 | *
97 | * @param {Object=} config - The configuration object. May only contain the options that need to be
98 | * updated. Supported keys:
99 | *
100 | * * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a
101 | * non-positive or non-numeric value, removes the max depth limit.
102 | * Default: 5
103 | *
104 | * * `urlErrorParamsEnabled` **{Boolean}** - Specifies whether the generated error url will
105 | * contain the parameters of the thrown error. Disabling the parameters can be useful if the
106 | * generated error url is very long.
107 | *
108 | * Default: true. When used without argument, it returns the current value.
109 | */
110 | function errorHandlingConfig(config) {
111 | if (isObject(config)) {
112 | if (isDefined(config.objectMaxDepth)) {
113 | minErrConfig.objectMaxDepth = isValidObjectMaxDepth(config.objectMaxDepth) ? config.objectMaxDepth : NaN;
114 | }
115 | if (isDefined(config.urlErrorParamsEnabled) && isBoolean(config.urlErrorParamsEnabled)) {
116 | minErrConfig.urlErrorParamsEnabled = config.urlErrorParamsEnabled;
117 | }
118 | } else {
119 | return minErrConfig;
120 | }
121 | }
122 |
123 | /**
124 | * @private
125 | * @param {Number} maxDepth
126 | * @return {boolean}
127 | */
128 | function isValidObjectMaxDepth(maxDepth) {
129 | return isNumber(maxDepth) && maxDepth > 0;
130 | }
131 |
132 |
133 | /**
134 | * @description
135 | *
136 | * This object provides a utility for producing rich Error messages within
137 | * AngularJS. It can be called as follows:
138 | *
139 | * var exampleMinErr = minErr('example');
140 | * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
141 | *
142 | * The above creates an instance of minErr in the example namespace. The
143 | * resulting error will have a namespaced error code of example.one. The
144 | * resulting error will replace {0} with the value of foo, and {1} with the
145 | * value of bar. The object is not restricted in the number of arguments it can
146 | * take.
147 | *
148 | * If fewer arguments are specified than necessary for interpolation, the extra
149 | * interpolation markers will be preserved in the final string.
150 | *
151 | * Since data will be parsed statically during a build step, some restrictions
152 | * are applied with respect to how minErr instances are created and called.
153 | * Instances should have names of the form namespaceMinErr for a minErr created
154 | * using minErr('namespace'). Error codes, namespaces and template strings
155 | * should all be static strings, not variables or general expressions.
156 | *
157 | * @param {string} module The namespace to use for the new minErr instance.
158 | * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
159 | * error from returned function, for cases when a particular type of error is useful.
160 | * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
161 | */
162 |
163 | function minErr(module, ErrorConstructor) {
164 | ErrorConstructor = ErrorConstructor || Error;
165 |
166 | var url = 'https://errors.angularjs.org/1.8.0/';
167 | var regex = url.replace('.', '\\.') + '[\\s\\S]*';
168 | var errRegExp = new RegExp(regex, 'g');
169 |
170 | return function() {
171 | var code = arguments[0],
172 | template = arguments[1],
173 | message = '[' + (module ? module + ':' : '') + code + '] ',
174 | templateArgs = sliceArgs(arguments, 2).map(function(arg) {
175 | return toDebugString(arg, minErrConfig.objectMaxDepth);
176 | }),
177 | paramPrefix, i;
178 |
179 | // A minErr message has two parts: the message itself and the url that contains the
180 | // encoded message.
181 | // The message's parameters can contain other error messages which also include error urls.
182 | // To prevent the messages from getting too long, we strip the error urls from the parameters.
183 |
184 | message += template.replace(/\{\d+\}/g, function(match) {
185 | var index = +match.slice(1, -1);
186 |
187 | if (index < templateArgs.length) {
188 | return templateArgs[index].replace(errRegExp, '');
189 | }
190 |
191 | return match;
192 | });
193 |
194 | message += '\n' + url + (module ? module + '/' : '') + code;
195 |
196 | if (minErrConfig.urlErrorParamsEnabled) {
197 | for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
198 | message += paramPrefix + 'p' + i + '=' + encodeURIComponent(templateArgs[i]);
199 | }
200 | }
201 |
202 | return new ErrorConstructor(message);
203 | };
204 | }
205 |
206 | /**
207 | * @ngdoc type
208 | * @name angular.Module
209 | * @module ng
210 | * @description
211 | *
212 | * Interface for configuring AngularJS {@link angular.module modules}.
213 | */
214 |
215 | function setupModuleLoader(window) {
216 |
217 | var $injectorMinErr = minErr('$injector');
218 | var ngMinErr = minErr('ng');
219 |
220 | function ensure(obj, name, factory) {
221 | return obj[name] || (obj[name] = factory());
222 | }
223 |
224 | var angular = ensure(window, 'angular', Object);
225 |
226 | // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
227 | angular.$$minErr = angular.$$minErr || minErr;
228 |
229 | return ensure(angular, 'module', function() {
230 | /** @type {Object.} */
231 | var modules = {};
232 |
233 | /**
234 | * @ngdoc function
235 | * @name angular.module
236 | * @module ng
237 | * @description
238 | *
239 | * The `angular.module` is a global place for creating, registering and retrieving AngularJS
240 | * modules.
241 | * All modules (AngularJS core or 3rd party) that should be available to an application must be
242 | * registered using this mechanism.
243 | *
244 | * Passing one argument retrieves an existing {@link angular.Module},
245 | * whereas passing more than one argument creates a new {@link angular.Module}
246 | *
247 | *
248 | * # Module
249 | *
250 | * A module is a collection of services, directives, controllers, filters, and configuration information.
251 | * `angular.module` is used to configure the {@link auto.$injector $injector}.
252 | *
253 | * ```js
254 | * // Create a new module
255 | * var myModule = angular.module('myModule', []);
256 | *
257 | * // register a new service
258 | * myModule.value('appName', 'MyCoolApp');
259 | *
260 | * // configure existing services inside initialization blocks.
261 | * myModule.config(['$locationProvider', function($locationProvider) {
262 | * // Configure existing providers
263 | * $locationProvider.hashPrefix('!');
264 | * }]);
265 | * ```
266 | *
267 | * Then you can create an injector and load your modules like this:
268 | *
269 | * ```js
270 | * var injector = angular.injector(['ng', 'myModule'])
271 | * ```
272 | *
273 | * However it's more likely that you'll just use
274 | * {@link ng.directive:ngApp ngApp} or
275 | * {@link angular.bootstrap} to simplify this process for you.
276 | *
277 | * @param {!string} name The name of the module to create or retrieve.
278 | * @param {!Array.=} requires If specified then new module is being created. If
279 | * unspecified then the module is being retrieved for further configuration.
280 | * @param {Function=} configFn Optional configuration function for the module. Same as
281 | * {@link angular.Module#config Module#config()}.
282 | * @returns {angular.Module} new module with the {@link angular.Module} api.
283 | */
284 | return function module(name, requires, configFn) {
285 |
286 | var info = {};
287 |
288 | var assertNotHasOwnProperty = function(name, context) {
289 | if (name === 'hasOwnProperty') {
290 | throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
291 | }
292 | };
293 |
294 | assertNotHasOwnProperty(name, 'module');
295 | if (requires && modules.hasOwnProperty(name)) {
296 | modules[name] = null;
297 | }
298 | return ensure(modules, name, function() {
299 | if (!requires) {
300 | throw $injectorMinErr('nomod', 'Module \'{0}\' is not available! You either misspelled ' +
301 | 'the module name or forgot to load it. If registering a module ensure that you ' +
302 | 'specify the dependencies as the second argument.', name);
303 | }
304 |
305 | /** @type {!Array.>} */
306 | var invokeQueue = [];
307 |
308 | /** @type {!Array.} */
309 | var configBlocks = [];
310 |
311 | /** @type {!Array.} */
312 | var runBlocks = [];
313 |
314 | var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
315 |
316 | /** @type {angular.Module} */
317 | var moduleInstance = {
318 | // Private state
319 | _invokeQueue: invokeQueue,
320 | _configBlocks: configBlocks,
321 | _runBlocks: runBlocks,
322 |
323 | /**
324 | * @ngdoc method
325 | * @name angular.Module#info
326 | * @module ng
327 | *
328 | * @param {Object=} info Information about the module
329 | * @returns {Object|Module} The current info object for this module if called as a getter,
330 | * or `this` if called as a setter.
331 | *
332 | * @description
333 | * Read and write custom information about this module.
334 | * For example you could put the version of the module in here.
335 | *
336 | * ```js
337 | * angular.module('myModule', []).info({ version: '1.0.0' });
338 | * ```
339 | *
340 | * The version could then be read back out by accessing the module elsewhere:
341 | *
342 | * ```
343 | * var version = angular.module('myModule').info().version;
344 | * ```
345 | *
346 | * You can also retrieve this information during runtime via the
347 | * {@link $injector#modules `$injector.modules`} property:
348 | *
349 | * ```js
350 | * var version = $injector.modules['myModule'].info().version;
351 | * ```
352 | */
353 | info: function(value) {
354 | if (isDefined(value)) {
355 | if (!isObject(value)) throw ngMinErr('aobj', 'Argument \'{0}\' must be an object', 'value');
356 | info = value;
357 | return this;
358 | }
359 | return info;
360 | },
361 |
362 | /**
363 | * @ngdoc property
364 | * @name angular.Module#requires
365 | * @module ng
366 | *
367 | * @description
368 | * Holds the list of modules which the injector will load before the current module is
369 | * loaded.
370 | */
371 | requires: requires,
372 |
373 | /**
374 | * @ngdoc property
375 | * @name angular.Module#name
376 | * @module ng
377 | *
378 | * @description
379 | * Name of the module.
380 | */
381 | name: name,
382 |
383 |
384 | /**
385 | * @ngdoc method
386 | * @name angular.Module#provider
387 | * @module ng
388 | * @param {string} name service name
389 | * @param {Function} providerType Construction function for creating new instance of the
390 | * service.
391 | * @description
392 | * See {@link auto.$provide#provider $provide.provider()}.
393 | */
394 | provider: invokeLaterAndSetModuleName('$provide', 'provider'),
395 |
396 | /**
397 | * @ngdoc method
398 | * @name angular.Module#factory
399 | * @module ng
400 | * @param {string} name service name
401 | * @param {Function} providerFunction Function for creating new instance of the service.
402 | * @description
403 | * See {@link auto.$provide#factory $provide.factory()}.
404 | */
405 | factory: invokeLaterAndSetModuleName('$provide', 'factory'),
406 |
407 | /**
408 | * @ngdoc method
409 | * @name angular.Module#service
410 | * @module ng
411 | * @param {string} name service name
412 | * @param {Function} constructor A constructor function that will be instantiated.
413 | * @description
414 | * See {@link auto.$provide#service $provide.service()}.
415 | */
416 | service: invokeLaterAndSetModuleName('$provide', 'service'),
417 |
418 | /**
419 | * @ngdoc method
420 | * @name angular.Module#value
421 | * @module ng
422 | * @param {string} name service name
423 | * @param {*} object Service instance object.
424 | * @description
425 | * See {@link auto.$provide#value $provide.value()}.
426 | */
427 | value: invokeLater('$provide', 'value'),
428 |
429 | /**
430 | * @ngdoc method
431 | * @name angular.Module#constant
432 | * @module ng
433 | * @param {string} name constant name
434 | * @param {*} object Constant value.
435 | * @description
436 | * Because the constants are fixed, they get applied before other provide methods.
437 | * See {@link auto.$provide#constant $provide.constant()}.
438 | */
439 | constant: invokeLater('$provide', 'constant', 'unshift'),
440 |
441 | /**
442 | * @ngdoc method
443 | * @name angular.Module#decorator
444 | * @module ng
445 | * @param {string} name The name of the service to decorate.
446 | * @param {Function} decorFn This function will be invoked when the service needs to be
447 | * instantiated and should return the decorated service instance.
448 | * @description
449 | * See {@link auto.$provide#decorator $provide.decorator()}.
450 | */
451 | decorator: invokeLaterAndSetModuleName('$provide', 'decorator', configBlocks),
452 |
453 | /**
454 | * @ngdoc method
455 | * @name angular.Module#animation
456 | * @module ng
457 | * @param {string} name animation name
458 | * @param {Function} animationFactory Factory function for creating new instance of an
459 | * animation.
460 | * @description
461 | *
462 | * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
463 | *
464 | *
465 | * Defines an animation hook that can be later used with
466 | * {@link $animate $animate} service and directives that use this service.
467 | *
468 | * ```js
469 | * module.animation('.animation-name', function($inject1, $inject2) {
470 | * return {
471 | * eventName : function(element, done) {
472 | * //code to run the animation
473 | * //once complete, then run done()
474 | * return function cancellationFunction(element) {
475 | * //code to cancel the animation
476 | * }
477 | * }
478 | * }
479 | * })
480 | * ```
481 | *
482 | * See {@link ng.$animateProvider#register $animateProvider.register()} and
483 | * {@link ngAnimate ngAnimate module} for more information.
484 | */
485 | animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
486 |
487 | /**
488 | * @ngdoc method
489 | * @name angular.Module#filter
490 | * @module ng
491 | * @param {string} name Filter name - this must be a valid AngularJS expression identifier
492 | * @param {Function} filterFactory Factory function for creating new instance of filter.
493 | * @description
494 | * See {@link ng.$filterProvider#register $filterProvider.register()}.
495 | *
496 | *
497 | * **Note:** Filter names must be valid AngularJS {@link expression} identifiers, such as `uppercase` or `orderBy`.
498 | * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
499 | * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
500 | * (`myapp_subsection_filterx`).
501 | *
502 | */
503 | filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
504 |
505 | /**
506 | * @ngdoc method
507 | * @name angular.Module#controller
508 | * @module ng
509 | * @param {string|Object} name Controller name, or an object map of controllers where the
510 | * keys are the names and the values are the constructors.
511 | * @param {Function} constructor Controller constructor function.
512 | * @description
513 | * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
514 | */
515 | controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
516 |
517 | /**
518 | * @ngdoc method
519 | * @name angular.Module#directive
520 | * @module ng
521 | * @param {string|Object} name Directive name, or an object map of directives where the
522 | * keys are the names and the values are the factories.
523 | * @param {Function} directiveFactory Factory function for creating new instance of
524 | * directives.
525 | * @description
526 | * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
527 | */
528 | directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
529 |
530 | /**
531 | * @ngdoc method
532 | * @name angular.Module#component
533 | * @module ng
534 | * @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match ``),
535 | * or an object map of components where the keys are the names and the values are the component definition objects.
536 | * @param {Object} options Component definition object (a simplified
537 | * {@link ng.$compile#directive-definition-object directive definition object})
538 | *
539 | * @description
540 | * See {@link ng.$compileProvider#component $compileProvider.component()}.
541 | */
542 | component: invokeLaterAndSetModuleName('$compileProvider', 'component'),
543 |
544 | /**
545 | * @ngdoc method
546 | * @name angular.Module#config
547 | * @module ng
548 | * @param {Function} configFn Execute this function on module load. Useful for service
549 | * configuration.
550 | * @description
551 | * Use this method to configure services by injecting their
552 | * {@link angular.Module#provider `providers`}, e.g. for adding routes to the
553 | * {@link ngRoute.$routeProvider $routeProvider}.
554 | *
555 | * Note that you can only inject {@link angular.Module#provider `providers`} and
556 | * {@link angular.Module#constant `constants`} into this function.
557 | *
558 | * For more about how to configure services, see
559 | * {@link providers#provider-recipe Provider Recipe}.
560 | */
561 | config: config,
562 |
563 | /**
564 | * @ngdoc method
565 | * @name angular.Module#run
566 | * @module ng
567 | * @param {Function} initializationFn Execute this function after injector creation.
568 | * Useful for application initialization.
569 | * @description
570 | * Use this method to register work which should be performed when the injector is done
571 | * loading all modules.
572 | */
573 | run: function(block) {
574 | runBlocks.push(block);
575 | return this;
576 | }
577 | };
578 |
579 | if (configFn) {
580 | config(configFn);
581 | }
582 |
583 | return moduleInstance;
584 |
585 | /**
586 | * @param {string} provider
587 | * @param {string} method
588 | * @param {String=} insertMethod
589 | * @returns {angular.Module}
590 | */
591 | function invokeLater(provider, method, insertMethod, queue) {
592 | if (!queue) queue = invokeQueue;
593 | return function() {
594 | queue[insertMethod || 'push']([provider, method, arguments]);
595 | return moduleInstance;
596 | };
597 | }
598 |
599 | /**
600 | * @param {string} provider
601 | * @param {string} method
602 | * @returns {angular.Module}
603 | */
604 | function invokeLaterAndSetModuleName(provider, method, queue) {
605 | if (!queue) queue = invokeQueue;
606 | return function(recipeName, factoryFunction) {
607 | if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
608 | queue.push([provider, method, arguments]);
609 | return moduleInstance;
610 | };
611 | }
612 | });
613 | };
614 | });
615 |
616 | }
617 |
618 | setupModuleLoader(window);
619 | })(window);
620 |
621 | /**
622 | * Closure compiler type information
623 | *
624 | * @typedef { {
625 | * requires: !Array.,
626 | * invokeQueue: !Array.>,
627 | *
628 | * service: function(string, Function):angular.Module,
629 | * factory: function(string, Function):angular.Module,
630 | * value: function(string, *):angular.Module,
631 | *
632 | * filter: function(string, Function):angular.Module,
633 | *
634 | * init: function(Function):angular.Module
635 | * } }
636 | */
637 | angular.Module;
638 |
639 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/angular-messages.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license AngularJS v1.8.0
3 | * (c) 2010-2020 Google, Inc. http://angularjs.org
4 | * License: MIT
5 | */
6 | (function(window, angular) {'use strict';
7 |
8 | var forEach;
9 | var isArray;
10 | var isString;
11 | var jqLite;
12 |
13 | /**
14 | * @ngdoc module
15 | * @name ngMessages
16 | * @description
17 | *
18 | * The `ngMessages` module provides enhanced support for displaying messages within templates
19 | * (typically within forms or when rendering message objects that return key/value data).
20 | * Instead of relying on JavaScript code and/or complex ng-if statements within your form template to
21 | * show and hide error messages specific to the state of an input field, the `ngMessages` and
22 | * `ngMessage` directives are designed to handle the complexity, inheritance and priority
23 | * sequencing based on the order of how the messages are defined in the template.
24 | *
25 | * Currently, the ngMessages module only contains the code for the `ngMessages`, `ngMessagesInclude`
26 | * `ngMessage`, `ngMessageExp` and `ngMessageDefault` directives.
27 | *
28 | * ## Usage
29 | * The `ngMessages` directive allows keys in a key/value collection to be associated with a child element
30 | * (or 'message') that will show or hide based on the truthiness of that key's value in the collection. A common use
31 | * case for `ngMessages` is to display error messages for inputs using the `$error` object exposed by the
32 | * {@link ngModel ngModel} directive.
33 | *
34 | * The child elements of the `ngMessages` directive are matched to the collection keys by a `ngMessage` or
35 | * `ngMessageExp` directive. The value of these attributes must match a key in the collection that is provided by
36 | * the `ngMessages` directive.
37 | *
38 | * Consider the following example, which illustrates a typical use case of `ngMessages`. Within the form `myForm` we
39 | * have a text input named `myField` which is bound to the scope variable `field` using the {@link ngModel ngModel}
40 | * directive.
41 | *
42 | * The `myField` field is a required input of type `email` with a maximum length of 15 characters.
43 | *
44 | * ```html
45 | *
56 | * ```
57 | *
58 | * In order to show error messages corresponding to `myField` we first create an element with an `ngMessages` attribute
59 | * set to the `$error` object owned by the `myField` input in our `myForm` form.
60 | *
61 | * Within this element we then create separate elements for each of the possible errors that `myField` could have.
62 | * The `ngMessage` attribute is used to declare which element(s) will appear for which error - for example,
63 | * setting `ng-message="required"` specifies that this particular element should be displayed when there
64 | * is no value present for the required field `myField` (because the key `required` will be `true` in the object
65 | * `myForm.myField.$error`).
66 | *
67 | * ### Message order
68 | *
69 | * By default, `ngMessages` will only display one message for a particular key/value collection at any time. If more
70 | * than one message (or error) key is currently true, then which message is shown is determined by the order of messages
71 | * in the HTML template code (messages declared first are prioritised). This mechanism means the developer does not have
72 | * to prioritize messages using custom JavaScript code.
73 | *
74 | * Given the following error object for our example (which informs us that the field `myField` currently has both the
75 | * `required` and `email` errors):
76 | *
77 | * ```javascript
78 | *
79 | * myField.$error = { required : true, email: true, maxlength: false };
80 | * ```
81 | * The `required` message will be displayed to the user since it appears before the `email` message in the DOM.
82 | * Once the user types a single character, the `required` message will disappear (since the field now has a value)
83 | * but the `email` message will be visible because it is still applicable.
84 | *
85 | * ### Displaying multiple messages at the same time
86 | *
87 | * While `ngMessages` will by default only display one error element at a time, the `ng-messages-multiple` attribute can
88 | * be applied to the `ngMessages` container element to cause it to display all applicable error messages at once:
89 | *
90 | * ```html
91 | *
92 | *
...
93 | *
94 | *
95 | * ...
96 | * ```
97 | *
98 | * ## Reusing and Overriding Messages
99 | * In addition to prioritization, ngMessages also allows for including messages from a remote or an inline
100 | * template. This allows for generic collection of messages to be reused across multiple parts of an
101 | * application.
102 | *
103 | * ```html
104 | *
108 | *
109 | *
110 | *
111 | *
112 | * ```
113 | *
114 | * However, including generic messages may not be useful enough to match all input fields, therefore,
115 | * `ngMessages` provides the ability to override messages defined in the remote template by redefining
116 | * them within the directive container.
117 | *
118 | * ```html
119 | *
120 | *
124 | *
125 | *
148 | * ```
149 | *
150 | * In the example HTML code above the message that is set on required will override the corresponding
151 | * required message defined within the remote template. Therefore, with particular input fields (such
152 | * email addresses, date fields, autocomplete inputs, etc...), specialized error messages can be applied
153 | * while more generic messages can be used to handle other, more general input errors.
154 | *
155 | * ## Dynamic Messaging
156 | * ngMessages also supports using expressions to dynamically change key values. Using arrays and
157 | * repeaters to list messages is also supported. This means that the code below will be able to
158 | * fully adapt itself and display the appropriate message when any of the expression data changes:
159 | *
160 | * ```html
161 | *
178 | * ```
179 | *
180 | * The `errorMessage.type` expression can be a string value or it can be an array so
181 | * that multiple errors can be associated with a single error message:
182 | *
183 | * ```html
184 | *
193 | *
194 | *
You did not enter your email address
195 | *
196 | * Your email must be between 5 and 100 characters long
197 | *
198 | *
199 | * ```
200 | *
201 | * Feel free to use other structural directives such as ng-if and ng-switch to further control
202 | * what messages are active and when. Be careful, if you place ng-message on the same element
203 | * as these structural directives, AngularJS may not be able to determine if a message is active
204 | * or not. Therefore it is best to place the ng-message on a child element of the structural
205 | * directive.
206 | *
207 | * ```html
208 | *
209 | *
210 | *
Please enter something
211 | *
212 | *
213 | * ```
214 | *
215 | * ## Animations
216 | * If the `ngAnimate` module is active within the application then the `ngMessages`, `ngMessage` and
217 | * `ngMessageExp` directives will trigger animations whenever any messages are added and removed from
218 | * the DOM by the `ngMessages` directive.
219 | *
220 | * Whenever the `ngMessages` directive contains one or more visible messages then the `.ng-active` CSS
221 | * class will be added to the element. The `.ng-inactive` CSS class will be applied when there are no
222 | * messages present. Therefore, CSS transitions and keyframes as well as JavaScript animations can
223 | * hook into the animations whenever these classes are added/removed.
224 | *
225 | * Let's say that our HTML code for our messages container looks like so:
226 | *
227 | * ```html
228 | *
229 | *
...
230 | *
...
231 | *
232 | * ```
233 | *
234 | * Then the CSS animation code for the message container looks like so:
235 | *
236 | * ```css
237 | * .my-messages {
238 | * transition:1s linear all;
239 | * }
240 | * .my-messages.ng-active {
241 | * // messages are visible
242 | * }
243 | * .my-messages.ng-inactive {
244 | * // messages are hidden
245 | * }
246 | * ```
247 | *
248 | * Whenever an inner message is attached (becomes visible) or removed (becomes hidden) then the enter
249 | * and leave animation is triggered for each particular element bound to the `ngMessage` directive.
250 | *
251 | * Therefore, the CSS code for the inner messages looks like so:
252 | *
253 | * ```css
254 | * .some-message {
255 | * transition:1s linear all;
256 | * }
257 | *
258 | * .some-message.ng-enter {}
259 | * .some-message.ng-enter.ng-enter-active {}
260 | *
261 | * .some-message.ng-leave {}
262 | * .some-message.ng-leave.ng-leave-active {}
263 | * ```
264 | *
265 | * {@link ngAnimate See the ngAnimate docs} to learn how to use JavaScript animations or to learn
266 | * more about ngAnimate.
267 | *
268 | * ## Displaying a default message
269 | * If the ngMessages renders no inner ngMessage directive (i.e. when none of the truthy
270 | * keys are matched by a defined message), then it will render a default message
271 | * using the {@link ngMessageDefault} directive.
272 | * Note that matched messages will always take precedence over unmatched messages. That means
273 | * the default message will not be displayed when another message is matched. This is also
274 | * true for `ng-messages-multiple`.
275 | *
276 | * ```html
277 | *
278 | *
This field is required
279 | *
This field is too short
280 | *
This field has an input error
281 | *
282 | * ```
283 | *
284 |
285 | */
286 | angular.module('ngMessages', [], function initAngularHelpers() {
287 | // Access helpers from AngularJS core.
288 | // Do it inside a `config` block to ensure `window.angular` is available.
289 | forEach = angular.forEach;
290 | isArray = angular.isArray;
291 | isString = angular.isString;
292 | jqLite = angular.element;
293 | })
294 | .info({ angularVersion: '1.8.0' })
295 |
296 | /**
297 | * @ngdoc directive
298 | * @module ngMessages
299 | * @name ngMessages
300 | * @restrict AE
301 | *
302 | * @description
303 | * `ngMessages` is a directive that is designed to show and hide messages based on the state
304 | * of a key/value object that it listens on. The directive itself complements error message
305 | * reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
306 | *
307 | * `ngMessages` manages the state of internal messages within its container element. The internal
308 | * messages use the `ngMessage` directive and will be inserted/removed from the page depending
309 | * on if they're present within the key/value object. By default, only one message will be displayed
310 | * at a time and this depends on the prioritization of the messages within the template. (This can
311 | * be changed by using the `ng-messages-multiple` or `multiple` attribute on the directive container.)
312 | *
313 | * A remote template can also be used (With {@link ngMessagesInclude}) to promote message
314 | * reusability and messages can also be overridden.
315 | *
316 | * A default message can also be displayed when no `ngMessage` directive is inserted, using the
317 | * {@link ngMessageDefault} directive.
318 | *
319 | * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
320 | *
321 | * @usage
322 | * ```html
323 | *
324 | *
325 | * ...
326 | * ...
327 | * ...
328 | * ...
329 | *
330 | *
331 | *
332 | *
333 | * ...
334 | * ...
335 | * ...
336 | * ...
337 | *
338 | * ```
339 | *
340 | * @param {string} ngMessages an AngularJS expression evaluating to a key/value object
341 | * (this is typically the $error object on an ngModel instance).
342 | * @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true
343 | *
344 | * @example
345 | *
348 | *
349 | *
368 | *
369 | *
370 | * angular.module('ngMessagesExample', ['ngMessages']);
371 | *
372 | *
373 | */
374 | .directive('ngMessages', ['$animate', function($animate) {
375 | var ACTIVE_CLASS = 'ng-active';
376 | var INACTIVE_CLASS = 'ng-inactive';
377 |
378 | return {
379 | require: 'ngMessages',
380 | restrict: 'AE',
381 | controller: ['$element', '$scope', '$attrs', function NgMessagesCtrl($element, $scope, $attrs) {
382 | var ctrl = this;
383 | var latestKey = 0;
384 | var nextAttachId = 0;
385 |
386 | this.getAttachId = function getAttachId() { return nextAttachId++; };
387 |
388 | var messages = this.messages = {};
389 | var renderLater, cachedCollection;
390 |
391 | this.render = function(collection) {
392 | collection = collection || {};
393 |
394 | renderLater = false;
395 | cachedCollection = collection;
396 |
397 | // this is true if the attribute is empty or if the attribute value is truthy
398 | var multiple = isAttrTruthy($scope, $attrs.ngMessagesMultiple) ||
399 | isAttrTruthy($scope, $attrs.multiple);
400 |
401 | var unmatchedMessages = [];
402 | var matchedKeys = {};
403 | var truthyKeys = 0;
404 | var messageItem = ctrl.head;
405 | var messageFound = false;
406 | var totalMessages = 0;
407 |
408 | // we use != instead of !== to allow for both undefined and null values
409 | while (messageItem != null) {
410 | totalMessages++;
411 | var messageCtrl = messageItem.message;
412 |
413 | var messageUsed = false;
414 | if (!messageFound) {
415 | forEach(collection, function(value, key) {
416 | if (truthy(value) && !messageUsed) {
417 | truthyKeys++;
418 |
419 | if (messageCtrl.test(key)) {
420 | // this is to prevent the same error name from showing up twice
421 | if (matchedKeys[key]) return;
422 | matchedKeys[key] = true;
423 |
424 | messageUsed = true;
425 | messageCtrl.attach();
426 | }
427 | }
428 | });
429 | }
430 |
431 | if (messageUsed) {
432 | // unless we want to display multiple messages then we should
433 | // set a flag here to avoid displaying the next message in the list
434 | messageFound = !multiple;
435 | } else {
436 | unmatchedMessages.push(messageCtrl);
437 | }
438 |
439 | messageItem = messageItem.next;
440 | }
441 |
442 | forEach(unmatchedMessages, function(messageCtrl) {
443 | messageCtrl.detach();
444 | });
445 |
446 | var messageMatched = unmatchedMessages.length !== totalMessages;
447 | var attachDefault = ctrl.default && !messageMatched && truthyKeys > 0;
448 |
449 | if (attachDefault) {
450 | ctrl.default.attach();
451 | } else if (ctrl.default) {
452 | ctrl.default.detach();
453 | }
454 |
455 | if (messageMatched || attachDefault) {
456 | $animate.setClass($element, ACTIVE_CLASS, INACTIVE_CLASS);
457 | } else {
458 | $animate.setClass($element, INACTIVE_CLASS, ACTIVE_CLASS);
459 | }
460 | };
461 |
462 | $scope.$watchCollection($attrs.ngMessages || $attrs['for'], ctrl.render);
463 |
464 | this.reRender = function() {
465 | if (!renderLater) {
466 | renderLater = true;
467 | $scope.$evalAsync(function() {
468 | if (renderLater && cachedCollection) {
469 | ctrl.render(cachedCollection);
470 | }
471 | });
472 | }
473 | };
474 |
475 | this.register = function(comment, messageCtrl, isDefault) {
476 | if (isDefault) {
477 | ctrl.default = messageCtrl;
478 | } else {
479 | var nextKey = latestKey.toString();
480 | messages[nextKey] = {
481 | message: messageCtrl
482 | };
483 | insertMessageNode($element[0], comment, nextKey);
484 | comment.$$ngMessageNode = nextKey;
485 | latestKey++;
486 | }
487 |
488 | ctrl.reRender();
489 | };
490 |
491 | this.deregister = function(comment, isDefault) {
492 | if (isDefault) {
493 | delete ctrl.default;
494 | } else {
495 | var key = comment.$$ngMessageNode;
496 | delete comment.$$ngMessageNode;
497 | removeMessageNode($element[0], comment, key);
498 | delete messages[key];
499 | }
500 | ctrl.reRender();
501 | };
502 |
503 | function findPreviousMessage(parent, comment) {
504 | var prevNode = comment;
505 | var parentLookup = [];
506 |
507 | while (prevNode && prevNode !== parent) {
508 | var prevKey = prevNode.$$ngMessageNode;
509 | if (prevKey && prevKey.length) {
510 | return messages[prevKey];
511 | }
512 |
513 | // dive deeper into the DOM and examine its children for any ngMessage
514 | // comments that may be in an element that appears deeper in the list
515 | if (prevNode.childNodes.length && parentLookup.indexOf(prevNode) === -1) {
516 | parentLookup.push(prevNode);
517 | prevNode = prevNode.childNodes[prevNode.childNodes.length - 1];
518 | } else if (prevNode.previousSibling) {
519 | prevNode = prevNode.previousSibling;
520 | } else {
521 | prevNode = prevNode.parentNode;
522 | parentLookup.push(prevNode);
523 | }
524 | }
525 | }
526 |
527 | function insertMessageNode(parent, comment, key) {
528 | var messageNode = messages[key];
529 | if (!ctrl.head) {
530 | ctrl.head = messageNode;
531 | } else {
532 | var match = findPreviousMessage(parent, comment);
533 | if (match) {
534 | messageNode.next = match.next;
535 | match.next = messageNode;
536 | } else {
537 | messageNode.next = ctrl.head;
538 | ctrl.head = messageNode;
539 | }
540 | }
541 | }
542 |
543 | function removeMessageNode(parent, comment, key) {
544 | var messageNode = messages[key];
545 |
546 | // This message node may have already been removed by a call to deregister()
547 | if (!messageNode) return;
548 |
549 | var match = findPreviousMessage(parent, comment);
550 | if (match) {
551 | match.next = messageNode.next;
552 | } else {
553 | ctrl.head = messageNode.next;
554 | }
555 | }
556 | }]
557 | };
558 |
559 | function isAttrTruthy(scope, attr) {
560 | return (isString(attr) && attr.length === 0) || //empty attribute
561 | truthy(scope.$eval(attr));
562 | }
563 |
564 | function truthy(val) {
565 | return isString(val) ? val.length : !!val;
566 | }
567 | }])
568 |
569 | /**
570 | * @ngdoc directive
571 | * @name ngMessagesInclude
572 | * @restrict AE
573 | * @scope
574 | *
575 | * @description
576 | * `ngMessagesInclude` is a directive with the purpose to import existing ngMessage template
577 | * code from a remote template and place the downloaded template code into the exact spot
578 | * that the ngMessagesInclude directive is placed within the ngMessages container. This allows
579 | * for a series of pre-defined messages to be reused and also allows for the developer to
580 | * determine what messages are overridden due to the placement of the ngMessagesInclude directive.
581 | *
582 | * @usage
583 | * ```html
584 | *
585 | *
586 | * ...
587 | *
588 | *
589 | *
590 | *
591 | * ...
592 | *
593 | * ```
594 | *
595 | * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
596 | *
597 | * @param {string} ngMessagesInclude|src a string value corresponding to the remote template.
598 | */
599 | .directive('ngMessagesInclude',
600 | ['$templateRequest', '$document', '$compile', function($templateRequest, $document, $compile) {
601 |
602 | return {
603 | restrict: 'AE',
604 | require: '^^ngMessages', // we only require this for validation sake
605 | link: function($scope, element, attrs) {
606 | var src = attrs.ngMessagesInclude || attrs.src;
607 | $templateRequest(src).then(function(html) {
608 | if ($scope.$$destroyed) return;
609 |
610 | if (isString(html) && !html.trim()) {
611 | // Empty template - nothing to compile
612 | replaceElementWithMarker(element, src);
613 | } else {
614 | // Non-empty template - compile and link
615 | $compile(html)($scope, function(contents) {
616 | element.after(contents);
617 | replaceElementWithMarker(element, src);
618 | });
619 | }
620 | });
621 | }
622 | };
623 |
624 | // Helpers
625 | function replaceElementWithMarker(element, src) {
626 | // A comment marker is placed for debugging purposes
627 | var comment = $compile.$$createComment ?
628 | $compile.$$createComment('ngMessagesInclude', src) :
629 | $document[0].createComment(' ngMessagesInclude: ' + src + ' ');
630 | var marker = jqLite(comment);
631 | element.after(marker);
632 |
633 | // Don't pollute the DOM anymore by keeping an empty directive element
634 | element.remove();
635 | }
636 | }])
637 |
638 | /**
639 | * @ngdoc directive
640 | * @name ngMessage
641 | * @restrict AE
642 | * @scope
643 | * @priority 1
644 | *
645 | * @description
646 | * `ngMessage` is a directive with the purpose to show and hide a particular message.
647 | * For `ngMessage` to operate, a parent `ngMessages` directive on a parent DOM element
648 | * must be situated since it determines which messages are visible based on the state
649 | * of the provided key/value map that `ngMessages` listens on.
650 | *
651 | * More information about using `ngMessage` can be found in the
652 | * {@link module:ngMessages `ngMessages` module documentation}.
653 | *
654 | * @usage
655 | * ```html
656 | *
657 | *
658 | * ...
659 | * ...
660 | *
661 | *
662 | *
663 | *
664 | * ...
665 | * ...
666 | *
667 | * ```
668 | *
669 | * @param {expression} ngMessage|when a string value corresponding to the message key.
670 | */
671 | .directive('ngMessage', ngMessageDirectiveFactory())
672 |
673 |
674 | /**
675 | * @ngdoc directive
676 | * @name ngMessageExp
677 | * @restrict AE
678 | * @priority 1
679 | * @scope
680 | *
681 | * @description
682 | * `ngMessageExp` is the same as {@link directive:ngMessage `ngMessage`}, but instead of a static
683 | * value, it accepts an expression to be evaluated for the message key.
684 | *
685 | * @usage
686 | * ```html
687 | *
688 | *
689 | * ...
690 | *
691 | *
692 | *
693 | *
694 | * ...
695 | *
696 | * ```
697 | *
698 | * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
699 | *
700 | * @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key.
701 | */
702 | .directive('ngMessageExp', ngMessageDirectiveFactory())
703 |
704 | /**
705 | * @ngdoc directive
706 | * @name ngMessageDefault
707 | * @restrict AE
708 | * @scope
709 | *
710 | * @description
711 | * `ngMessageDefault` is a directive with the purpose to show and hide a default message for
712 | * {@link directive:ngMessages}, when none of provided messages matches.
713 | *
714 | * More information about using `ngMessageDefault` can be found in the
715 | * {@link module:ngMessages `ngMessages` module documentation}.
716 | *
717 | * @usage
718 | * ```html
719 | *
720 | *
721 | * ...
722 | * ...
723 | * ...
724 | *
725 | *
726 | *
727 | *
728 | * ...
729 | * ...
730 | * ...
731 | *
732 | *
733 | */
734 | .directive('ngMessageDefault', ngMessageDirectiveFactory(true));
735 |
736 | function ngMessageDirectiveFactory(isDefault) {
737 | return ['$animate', function($animate) {
738 | return {
739 | restrict: 'AE',
740 | transclude: 'element',
741 | priority: 1, // must run before ngBind, otherwise the text is set on the comment
742 | terminal: true,
743 | require: '^^ngMessages',
744 | link: function(scope, element, attrs, ngMessagesCtrl, $transclude) {
745 | var commentNode, records, staticExp, dynamicExp;
746 |
747 | if (!isDefault) {
748 | commentNode = element[0];
749 | staticExp = attrs.ngMessage || attrs.when;
750 | dynamicExp = attrs.ngMessageExp || attrs.whenExp;
751 |
752 | var assignRecords = function(items) {
753 | records = items
754 | ? (isArray(items)
755 | ? items
756 | : items.split(/[\s,]+/))
757 | : null;
758 | ngMessagesCtrl.reRender();
759 | };
760 |
761 | if (dynamicExp) {
762 | assignRecords(scope.$eval(dynamicExp));
763 | scope.$watchCollection(dynamicExp, assignRecords);
764 | } else {
765 | assignRecords(staticExp);
766 | }
767 | }
768 |
769 | var currentElement, messageCtrl;
770 | ngMessagesCtrl.register(commentNode, messageCtrl = {
771 | test: function(name) {
772 | return contains(records, name);
773 | },
774 | attach: function() {
775 | if (!currentElement) {
776 | $transclude(function(elm, newScope) {
777 | $animate.enter(elm, null, element);
778 | currentElement = elm;
779 |
780 | // Each time we attach this node to a message we get a new id that we can match
781 | // when we are destroying the node later.
782 | var $$attachId = currentElement.$$attachId = ngMessagesCtrl.getAttachId();
783 |
784 | // in the event that the element or a parent element is destroyed
785 | // by another structural directive then it's time
786 | // to deregister the message from the controller
787 | currentElement.on('$destroy', function() {
788 | // If the message element was removed via a call to `detach` then `currentElement` will be null
789 | // So this handler only handles cases where something else removed the message element.
790 | if (currentElement && currentElement.$$attachId === $$attachId) {
791 | ngMessagesCtrl.deregister(commentNode, isDefault);
792 | messageCtrl.detach();
793 | }
794 | newScope.$destroy();
795 | });
796 | });
797 | }
798 | },
799 | detach: function() {
800 | if (currentElement) {
801 | var elm = currentElement;
802 | currentElement = null;
803 | $animate.leave(elm);
804 | }
805 | }
806 | }, isDefault);
807 |
808 | // We need to ensure that this directive deregisters itself when it no longer exists
809 | // Normally this is done when the attached element is destroyed; but if this directive
810 | // gets removed before we attach the message to the DOM there is nothing to watch
811 | // in which case we must deregister when the containing scope is destroyed.
812 | scope.$on('$destroy', function() {
813 | ngMessagesCtrl.deregister(commentNode, isDefault);
814 | });
815 | }
816 | };
817 | }];
818 |
819 | function contains(collection, key) {
820 | if (collection) {
821 | return isArray(collection)
822 | ? collection.indexOf(key) >= 0
823 | : collection.hasOwnProperty(key);
824 | }
825 | }
826 | }
827 |
828 |
829 | })(window, window.angular);
830 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/angular-resource.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license AngularJS v1.8.0
3 | * (c) 2010-2020 Google, Inc. http://angularjs.org
4 | * License: MIT
5 | */
6 | (function(window, angular) {'use strict';
7 |
8 | var $resourceMinErr = angular.$$minErr('$resource');
9 |
10 | // Helper functions and regex to lookup a dotted path on an object
11 | // stopping at undefined/null. The path must be composed of ASCII
12 | // identifiers (just like $parse)
13 | var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;
14 |
15 | function isValidDottedPath(path) {
16 | return (path != null && path !== '' && path !== 'hasOwnProperty' &&
17 | MEMBER_NAME_REGEX.test('.' + path));
18 | }
19 |
20 | function lookupDottedPath(obj, path) {
21 | if (!isValidDottedPath(path)) {
22 | throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path);
23 | }
24 | var keys = path.split('.');
25 | for (var i = 0, ii = keys.length; i < ii && angular.isDefined(obj); i++) {
26 | var key = keys[i];
27 | obj = (obj !== null) ? obj[key] : undefined;
28 | }
29 | return obj;
30 | }
31 |
32 | /**
33 | * Create a shallow copy of an object and clear other fields from the destination
34 | */
35 | function shallowClearAndCopy(src, dst) {
36 | dst = dst || {};
37 |
38 | angular.forEach(dst, function(value, key) {
39 | delete dst[key];
40 | });
41 |
42 | for (var key in src) {
43 | if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
44 | dst[key] = src[key];
45 | }
46 | }
47 |
48 | return dst;
49 | }
50 |
51 | /**
52 | * @ngdoc module
53 | * @name ngResource
54 | * @description
55 | *
56 | * The `ngResource` module provides interaction support with RESTful services
57 | * via the $resource service.
58 | *
59 | * See {@link ngResource.$resourceProvider} and {@link ngResource.$resource} for usage.
60 | */
61 |
62 | /**
63 | * @ngdoc provider
64 | * @name $resourceProvider
65 | *
66 | * @description
67 | *
68 | * Use `$resourceProvider` to change the default behavior of the {@link ngResource.$resource}
69 | * service.
70 | *
71 | * ## Dependencies
72 | * Requires the {@link ngResource } module to be installed.
73 | *
74 | */
75 |
76 | /**
77 | * @ngdoc service
78 | * @name $resource
79 | * @requires $http
80 | * @requires ng.$log
81 | * @requires $q
82 | * @requires ng.$timeout
83 | *
84 | * @description
85 | * A factory which creates a resource object that lets you interact with
86 | * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
87 | *
88 | * The returned resource object has action methods which provide high-level behaviors without
89 | * the need to interact with the low level {@link ng.$http $http} service.
90 | *
91 | * Requires the {@link ngResource `ngResource`} module to be installed.
92 | *
93 | * By default, trailing slashes will be stripped from the calculated URLs,
94 | * which can pose problems with server backends that do not expect that
95 | * behavior. This can be disabled by configuring the `$resourceProvider` like
96 | * this:
97 | *
98 | * ```js
99 | app.config(['$resourceProvider', function($resourceProvider) {
100 | // Don't strip trailing slashes from calculated URLs
101 | $resourceProvider.defaults.stripTrailingSlashes = false;
102 | }]);
103 | * ```
104 | *
105 | * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
106 | * `/user/:username`. If you are using a URL with a port number (e.g.
107 | * `http://example.com:8080/api`), it will be respected.
108 | *
109 | * If you are using a url with a suffix, just add the suffix, like this:
110 | * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')`
111 | * or even `$resource('http://example.com/resource/:resource_id.:format')`
112 | * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be
113 | * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you
114 | * can escape it with `/\.`.
115 | *
116 | * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
117 | * `actions` methods. If a parameter value is a function, it will be called every time
118 | * a param value needs to be obtained for a request (unless the param was overridden). The
119 | * function will be passed the current data value as an argument.
120 | *
121 | * Each key value in the parameter object is first bound to url template if present and then any
122 | * excess keys are appended to the url search query after the `?`.
123 | *
124 | * Given a template `/path/:verb` and parameter `{verb: 'greet', salutation: 'Hello'}` results in
125 | * URL `/path/greet?salutation=Hello`.
126 | *
127 | * If the parameter value is prefixed with `@`, then the value for that parameter will be
128 | * extracted from the corresponding property on the `data` object (provided when calling actions
129 | * with a request body).
130 | * For example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of
131 | * `someParam` will be `data.someProp`.
132 | * Note that the parameter will be ignored, when calling a "GET" action method (i.e. an action
133 | * method that does not accept a request body).
134 | *
135 | * @param {Object.