mongo_browser 0.2.0.rc2 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -1
- data/.rspec +1 -1
- data/.travis.yml +6 -1
- data/CHANGELOG.md +15 -0
- data/{grunt.js → Gruntfile.js} +10 -8
- data/Procfile +1 -0
- data/README.md +44 -2
- data/Rakefile +1 -12
- data/app/assets/images/ajax-loader.gif +0 -0
- data/app/assets/javascripts/app/controllers/{breadcrumbs.js.coffee → breadcrumbs_controller.js.coffee} +4 -7
- data/app/assets/javascripts/app/controllers/collections/index_controller.js.coffee +38 -0
- data/app/assets/javascripts/app/controllers/collections/stats_controller.js.coffee +17 -0
- data/app/assets/javascripts/app/controllers/{databases.js.coffee → databases/index_controller.js.coffee} +11 -15
- data/app/assets/javascripts/app/controllers/databases/stats_controller.js.coffee +15 -0
- data/app/assets/javascripts/app/controllers/documents/index_controller.js.coffee +54 -0
- data/app/assets/javascripts/app/controllers/documents/show_controller.js.coffee +38 -0
- data/app/assets/javascripts/app/controllers/main_controller.js.coffee +15 -0
- data/app/assets/javascripts/app/controllers/servers/show_controller.js.coffee +17 -0
- data/app/assets/javascripts/app/directives.js.coffee +23 -0
- data/app/assets/javascripts/app/filters.js.coffee +14 -1
- data/app/assets/javascripts/app/modules/alerts.js.coffee +58 -0
- data/app/assets/javascripts/app/modules/pager.js.coffee +2 -2
- data/app/assets/javascripts/app/modules/spinner.js.coffee +29 -0
- data/app/assets/javascripts/app/modules/table_filter.js.coffee +4 -4
- data/app/assets/javascripts/app/resources.js.coffee +14 -8
- data/app/assets/javascripts/app/services.js.coffee +11 -33
- data/app/assets/javascripts/application.js.coffee +62 -34
- data/app/assets/javascripts/application.test.js.coffee +5 -0
- data/app/assets/javascripts/compiled_templates.js.coffee +1 -0
- data/app/assets/javascripts/vendor.js.coffee +0 -1
- data/app/assets/stylesheets/application.css.scss +36 -18
- data/{public/index.html → app/views/index.erb} +8 -8
- data/bin/mongo_browser +2 -13
- data/config.ru +3 -1
- data/lib/mongo_browser.rb +1 -0
- data/lib/mongo_browser/api.rb +11 -0
- data/lib/mongo_browser/api/collections.rb +34 -0
- data/lib/mongo_browser/api/databases.rb +32 -0
- data/lib/mongo_browser/api/documents.rb +37 -0
- data/lib/mongo_browser/api/mongo.rb +41 -0
- data/lib/mongo_browser/application.rb +8 -174
- data/lib/mongo_browser/application/development.rb +32 -0
- data/lib/mongo_browser/cli.rb +48 -0
- data/lib/mongo_browser/entities.rb +43 -0
- data/lib/mongo_browser/models/collection.rb +7 -12
- data/lib/mongo_browser/models/document.rb +5 -1
- data/lib/mongo_browser/models/pager.rb +22 -9
- data/lib/mongo_browser/version.rb +1 -1
- data/mongo_browser.gemspec +22 -15
- data/package.json +30 -0
- data/public/ng/templates/alerts.html +6 -0
- data/public/ng/templates/collections/index.html +39 -0
- data/public/ng/templates/collections/stats.html +18 -0
- data/public/ng/templates/databases/index.html +35 -0
- data/public/ng/templates/databases/stats.html +18 -0
- data/public/ng/templates/documents/index.html +40 -0
- data/public/ng/templates/documents/show.html +17 -0
- data/{app/assets → public/ng}/templates/pager.html +0 -0
- data/{app/assets/templates/server_info.html → public/ng/templates/server/show.html} +1 -1
- data/{app/assets → public/ng}/templates/table_filter.html +0 -0
- data/script/ci_all +5 -1
- data/script/ci_e2e +5 -2
- data/script/ci_javascripts +1 -1
- data/script/ci_rspec +1 -1
- data/spec/javascripts/app/controllers/{breadcrumbs_spec.js.coffee → breadcrumbs_controller_spec.js.coffee} +1 -1
- data/spec/javascripts/app/controllers/collections/index_controller_spec.js.coffee +95 -0
- data/spec/javascripts/app/controllers/collections/stats_controller_spec.js.coffee +34 -0
- data/spec/javascripts/app/controllers/databases/index_controller_spec.js.coffee +93 -0
- data/spec/javascripts/app/controllers/databases/stats_controller_spec.js.coffee +30 -0
- data/spec/javascripts/app/controllers/documents/index_controller_spec.js.coffee +108 -0
- data/spec/javascripts/app/controllers/documents/show_controller_spec.js.coffee +94 -0
- data/spec/javascripts/app/controllers/{main_spec.js.coffee → main_controller_spec.js.coffee} +2 -2
- data/spec/javascripts/app/controllers/{server_info_spec.js.coffee → server/show_controller_spec.js.coffee} +5 -6
- data/spec/javascripts/app/directives_spec.js.coffee +108 -24
- data/spec/javascripts/app/filters_spec.js.coffee +31 -5
- data/spec/javascripts/app/modules/alerts_spec.js.coffee +138 -0
- data/spec/javascripts/app/modules/dialogs_spec.js.coffee +1 -2
- data/spec/javascripts/app/modules/pager_spec.js.coffee +0 -1
- data/spec/javascripts/app/modules/spinner_spec.js.coffee +65 -0
- data/spec/javascripts/app/modules/table_filter_spec.js.coffee +9 -9
- data/spec/javascripts/app/resources_spec.js.coffee +99 -0
- data/spec/javascripts/app/services_spec.js.coffee +31 -71
- data/spec/javascripts/config/{testacular-e2e.conf.js → karma-e2e.conf.js} +1 -1
- data/spec/javascripts/config/{testacular.conf.js → karma.conf.js} +2 -3
- data/spec/javascripts/e2e/collection_stats_scenario.js.coffee +12 -0
- data/spec/javascripts/e2e/collections_scenario.js.coffee +59 -20
- data/spec/javascripts/e2e/database_stats_scenario.js.coffee +11 -0
- data/spec/javascripts/e2e/databases_scenario.js.coffee +37 -36
- data/spec/javascripts/e2e/document_show_scenario.js.coffee +31 -0
- data/spec/javascripts/e2e/documents_pagination_scenario.js.coffee +33 -0
- data/spec/javascripts/e2e/documents_scenario.js.coffee +43 -4
- data/spec/javascripts/e2e/server_info_scenario.js.coffee +8 -2
- data/spec/javascripts/helpers/mocks.js.coffee +2 -0
- data/spec/javascripts/helpers_e2e/dsl.js.coffee +20 -0
- data/spec/javascripts/lib/angular-mocks.js +64 -16
- data/spec/javascripts/lib/angular-scenario.js +724 -561
- data/spec/javascripts/runner.html +5 -5
- data/spec/lib/api/collections_spec.rb +62 -0
- data/spec/lib/api/databases_spec.rb +58 -0
- data/spec/lib/api/documents_spec.rb +135 -0
- data/spec/lib/api/mongo_spec.rb +27 -0
- data/spec/lib/cli_spec.rb +19 -0
- data/spec/lib/entities_spec.rb +39 -0
- data/spec/lib/models/collection_spec.rb +16 -10
- data/spec/lib/models/database_spec.rb +4 -4
- data/spec/lib/models/document_spec.rb +5 -5
- data/spec/lib/models/pager_spec.rb +20 -11
- data/spec/spec_helper.rb +7 -15
- data/spec/support/api_example_group.rb +45 -0
- data/spec/support/fixtures.rb +10 -6
- data/spec/support/matchers/expose.rb +18 -0
- data/vendor/assets/javascripts/angular/angular-bootstrap.js +1 -1
- data/vendor/assets/javascripts/angular/angular-resource.js +78 -56
- data/vendor/assets/javascripts/angular/angular-sanitize.js +3 -1
- data/vendor/assets/javascripts/angular/angular.js +720 -404
- metadata +323 -183
- data/app/assets/javascripts/app.js.coffee +0 -8
- data/app/assets/javascripts/app/controllers.js.coffee +0 -2
- data/app/assets/javascripts/app/controllers/alerts.js.coffee +0 -12
- data/app/assets/javascripts/app/controllers/collections.js.coffee +0 -40
- data/app/assets/javascripts/app/controllers/documents.js.coffee +0 -49
- data/app/assets/javascripts/app/controllers/main.js.coffee +0 -10
- data/app/assets/javascripts/app/controllers/server_info.js.coffee +0 -14
- data/app/assets/javascripts/templates.js.coffee +0 -1
- data/app/assets/javascripts/templates/.gitkeep +0 -0
- data/app/assets/templates/collections.html +0 -53
- data/app/assets/templates/databases.html +0 -32
- data/app/assets/templates/documents.html +0 -45
- data/config-e2e.ru +0 -20
- data/spec/features/collections_list_spec.rb +0 -64
- data/spec/features/documents_list_spec.rb +0 -139
- data/spec/features/server_info_spec.rb +0 -23
- data/spec/javascripts/app/controllers/alerts_spec.js.coffee +0 -36
- data/spec/javascripts/app/controllers/collections_spec.js.coffee +0 -78
- data/spec/javascripts/app/controllers/databases_spec.js.coffee +0 -55
- data/spec/javascripts/app/controllers/documents_spec.js.coffee +0 -62
- data/spec/javascripts/helpers_e2e/app_element.js.coffee +0 -6
- data/spec/support/feature_example_group.rb +0 -53
- data/spec/support/matchers/have_flash_message.rb +0 -16
- data/spec/support/mongod.rb +0 -91
- data/spec/support/mongodb.conf +0 -47
|
@@ -9403,8 +9403,9 @@ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
|
|
|
9403
9403
|
|
|
9404
9404
|
|
|
9405
9405
|
})( window );
|
|
9406
|
+
|
|
9406
9407
|
/**
|
|
9407
|
-
* @license AngularJS v1.0.
|
|
9408
|
+
* @license AngularJS v1.0.7
|
|
9408
9409
|
* (c) 2010-2012 Google, Inc. http://angularjs.org
|
|
9409
9410
|
* License: MIT
|
|
9410
9411
|
*/
|
|
@@ -9439,12 +9440,12 @@ var uppercase = function(string){return isString(string) ? string.toUpperCase()
|
|
|
9439
9440
|
|
|
9440
9441
|
var manualLowercase = function(s) {
|
|
9441
9442
|
return isString(s)
|
|
9442
|
-
? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})
|
|
9443
|
+
? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
|
|
9443
9444
|
: s;
|
|
9444
9445
|
};
|
|
9445
9446
|
var manualUppercase = function(s) {
|
|
9446
9447
|
return isString(s)
|
|
9447
|
-
? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})
|
|
9448
|
+
? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
|
|
9448
9449
|
: s;
|
|
9449
9450
|
};
|
|
9450
9451
|
|
|
@@ -9457,11 +9458,8 @@ if ('i' !== 'I'.toLowerCase()) {
|
|
|
9457
9458
|
uppercase = manualUppercase;
|
|
9458
9459
|
}
|
|
9459
9460
|
|
|
9460
|
-
function fromCharCode(code) {return String.fromCharCode(code);}
|
|
9461
|
-
|
|
9462
9461
|
|
|
9463
|
-
var
|
|
9464
|
-
/** holds major version number for IE or NaN for real browsers */
|
|
9462
|
+
var /** holds major version number for IE or NaN for real browsers */
|
|
9465
9463
|
msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),
|
|
9466
9464
|
jqLite, // delay binding since jQuery could be loaded after us.
|
|
9467
9465
|
jQuery, // delay binding
|
|
@@ -9475,6 +9473,29 @@ var Error = window.Error,
|
|
|
9475
9473
|
nodeName_,
|
|
9476
9474
|
uid = ['0', '0', '0'];
|
|
9477
9475
|
|
|
9476
|
+
|
|
9477
|
+
/**
|
|
9478
|
+
* @private
|
|
9479
|
+
* @param {*} obj
|
|
9480
|
+
* @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
|
|
9481
|
+
*/
|
|
9482
|
+
function isArrayLike(obj) {
|
|
9483
|
+
if (!obj || (typeof obj.length !== 'number')) return false;
|
|
9484
|
+
|
|
9485
|
+
// We have on object which has length property. Should we treat it as array?
|
|
9486
|
+
if (typeof obj.hasOwnProperty != 'function' &&
|
|
9487
|
+
typeof obj.constructor != 'function') {
|
|
9488
|
+
// This is here for IE8: it is a bogus object treat it as array;
|
|
9489
|
+
return true;
|
|
9490
|
+
} else {
|
|
9491
|
+
return obj instanceof JQLite || // JQLite
|
|
9492
|
+
(jQuery && obj instanceof jQuery) || // jQuery
|
|
9493
|
+
toString.call(obj) !== '[object Object]' || // some browser native object
|
|
9494
|
+
typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj)
|
|
9495
|
+
}
|
|
9496
|
+
}
|
|
9497
|
+
|
|
9498
|
+
|
|
9478
9499
|
/**
|
|
9479
9500
|
* @ngdoc function
|
|
9480
9501
|
* @name angular.forEach
|
|
@@ -9513,7 +9534,7 @@ function forEach(obj, iterator, context) {
|
|
|
9513
9534
|
}
|
|
9514
9535
|
} else if (obj.forEach && obj.forEach !== forEach) {
|
|
9515
9536
|
obj.forEach(iterator, context);
|
|
9516
|
-
} else if (
|
|
9537
|
+
} else if (isArrayLike(obj)) {
|
|
9517
9538
|
for (key = 0; key < obj.length; key++)
|
|
9518
9539
|
iterator.call(context, obj[key], key);
|
|
9519
9540
|
} else {
|
|
@@ -9558,7 +9579,7 @@ function reverseParams(iteratorFn) {
|
|
|
9558
9579
|
/**
|
|
9559
9580
|
* A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
|
|
9560
9581
|
* characters such as '012ABC'. The reason why we are not using simply a number counter is that
|
|
9561
|
-
* the number string gets longer over time, and it can also overflow, where as the
|
|
9582
|
+
* the number string gets longer over time, and it can also overflow, where as the nextId
|
|
9562
9583
|
* will grow much slower, it is a string, and it will never overflow.
|
|
9563
9584
|
*
|
|
9564
9585
|
* @returns an unique alpha-numeric string
|
|
@@ -9585,6 +9606,21 @@ function nextUid() {
|
|
|
9585
9606
|
return uid.join('');
|
|
9586
9607
|
}
|
|
9587
9608
|
|
|
9609
|
+
|
|
9610
|
+
/**
|
|
9611
|
+
* Set or clear the hashkey for an object.
|
|
9612
|
+
* @param obj object
|
|
9613
|
+
* @param h the hashkey (!truthy to delete the hashkey)
|
|
9614
|
+
*/
|
|
9615
|
+
function setHashKey(obj, h) {
|
|
9616
|
+
if (h) {
|
|
9617
|
+
obj.$$hashKey = h;
|
|
9618
|
+
}
|
|
9619
|
+
else {
|
|
9620
|
+
delete obj.$$hashKey;
|
|
9621
|
+
}
|
|
9622
|
+
}
|
|
9623
|
+
|
|
9588
9624
|
/**
|
|
9589
9625
|
* @ngdoc function
|
|
9590
9626
|
* @name angular.extend
|
|
@@ -9596,8 +9632,10 @@ function nextUid() {
|
|
|
9596
9632
|
*
|
|
9597
9633
|
* @param {Object} dst Destination object.
|
|
9598
9634
|
* @param {...Object} src Source object(s).
|
|
9635
|
+
* @returns {Object} Reference to `dst`.
|
|
9599
9636
|
*/
|
|
9600
9637
|
function extend(dst) {
|
|
9638
|
+
var h = dst.$$hashKey;
|
|
9601
9639
|
forEach(arguments, function(obj){
|
|
9602
9640
|
if (obj !== dst) {
|
|
9603
9641
|
forEach(obj, function(value, key){
|
|
@@ -9605,6 +9643,8 @@ function extend(dst) {
|
|
|
9605
9643
|
});
|
|
9606
9644
|
}
|
|
9607
9645
|
});
|
|
9646
|
+
|
|
9647
|
+
setHashKey(dst,h);
|
|
9608
9648
|
return dst;
|
|
9609
9649
|
}
|
|
9610
9650
|
|
|
@@ -9954,19 +9994,19 @@ function copy(source, destination){
|
|
|
9954
9994
|
} else {
|
|
9955
9995
|
if (source === destination) throw Error("Can't copy equivalent objects or arrays");
|
|
9956
9996
|
if (isArray(source)) {
|
|
9957
|
-
|
|
9958
|
-
destination.pop();
|
|
9959
|
-
}
|
|
9997
|
+
destination.length = 0;
|
|
9960
9998
|
for ( var i = 0; i < source.length; i++) {
|
|
9961
9999
|
destination.push(copy(source[i]));
|
|
9962
10000
|
}
|
|
9963
10001
|
} else {
|
|
10002
|
+
var h = destination.$$hashKey;
|
|
9964
10003
|
forEach(destination, function(value, key){
|
|
9965
10004
|
delete destination[key];
|
|
9966
10005
|
});
|
|
9967
10006
|
for ( var key in source) {
|
|
9968
10007
|
destination[key] = copy(source[key]);
|
|
9969
10008
|
}
|
|
10009
|
+
setHashKey(destination,h);
|
|
9970
10010
|
}
|
|
9971
10011
|
}
|
|
9972
10012
|
return destination;
|
|
@@ -10006,7 +10046,7 @@ function shallowCopy(src, dst) {
|
|
|
10006
10046
|
* During a property comparision, properties of `function` type and properties with names
|
|
10007
10047
|
* that begin with `$` are ignored.
|
|
10008
10048
|
*
|
|
10009
|
-
* Scope and DOMWindow objects are being compared only
|
|
10049
|
+
* Scope and DOMWindow objects are being compared only by identify (`===`).
|
|
10010
10050
|
*
|
|
10011
10051
|
* @param {*} o1 Object or value to compare.
|
|
10012
10052
|
* @param {*} o2 Object or value to compare.
|
|
@@ -10032,13 +10072,15 @@ function equals(o1, o2) {
|
|
|
10032
10072
|
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
|
|
10033
10073
|
keySet = {};
|
|
10034
10074
|
for(key in o1) {
|
|
10035
|
-
if (key.charAt(0)
|
|
10036
|
-
|
|
10037
|
-
}
|
|
10075
|
+
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
|
|
10076
|
+
if (!equals(o1[key], o2[key])) return false;
|
|
10038
10077
|
keySet[key] = true;
|
|
10039
10078
|
}
|
|
10040
10079
|
for(key in o2) {
|
|
10041
|
-
if (!keySet[key] &&
|
|
10080
|
+
if (!keySet[key] &&
|
|
10081
|
+
key.charAt(0) !== '$' &&
|
|
10082
|
+
o2[key] !== undefined &&
|
|
10083
|
+
!isFunction(o2[key])) return false;
|
|
10042
10084
|
}
|
|
10043
10085
|
return true;
|
|
10044
10086
|
}
|
|
@@ -10064,7 +10106,7 @@ function sliceArgs(args, startIndex) {
|
|
|
10064
10106
|
*
|
|
10065
10107
|
* @description
|
|
10066
10108
|
* Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
|
|
10067
|
-
* `fn`). You can supply optional `args` that are
|
|
10109
|
+
* `fn`). You can supply optional `args` that are prebound to the function. This feature is also
|
|
10068
10110
|
* known as [function currying](http://en.wikipedia.org/wiki/Currying).
|
|
10069
10111
|
*
|
|
10070
10112
|
* @param {Object} self Context which `fn` should be evaluated in.
|
|
@@ -10165,9 +10207,18 @@ function startingTag(element) {
|
|
|
10165
10207
|
// are not allowed to have children. So we just ignore it.
|
|
10166
10208
|
element.html('');
|
|
10167
10209
|
} catch(e) {}
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10210
|
+
// As Per DOM Standards
|
|
10211
|
+
var TEXT_NODE = 3;
|
|
10212
|
+
var elemHtml = jqLite('<div>').append(element).html();
|
|
10213
|
+
try {
|
|
10214
|
+
return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
|
|
10215
|
+
elemHtml.
|
|
10216
|
+
match(/^(<[^>]+>)/)[1].
|
|
10217
|
+
replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
|
|
10218
|
+
} catch(e) {
|
|
10219
|
+
return lowercase(elemHtml);
|
|
10220
|
+
}
|
|
10221
|
+
|
|
10171
10222
|
}
|
|
10172
10223
|
|
|
10173
10224
|
|
|
@@ -10234,7 +10285,7 @@ function encodeUriQuery(val, pctEncodeSpaces) {
|
|
|
10234
10285
|
replace(/%3A/gi, ':').
|
|
10235
10286
|
replace(/%24/g, '$').
|
|
10236
10287
|
replace(/%2C/gi, ',').
|
|
10237
|
-
replace((pctEncodeSpaces ?
|
|
10288
|
+
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
|
|
10238
10289
|
}
|
|
10239
10290
|
|
|
10240
10291
|
|
|
@@ -10248,10 +10299,10 @@ function encodeUriQuery(val, pctEncodeSpaces) {
|
|
|
10248
10299
|
*
|
|
10249
10300
|
* @description
|
|
10250
10301
|
*
|
|
10251
|
-
* Use this directive to auto-bootstrap
|
|
10302
|
+
* Use this directive to auto-bootstrap an application. Only
|
|
10252
10303
|
* one directive can be used per HTML document. The directive
|
|
10253
10304
|
* designates the root of the application and is typically placed
|
|
10254
|
-
*
|
|
10305
|
+
* at the root of the page.
|
|
10255
10306
|
*
|
|
10256
10307
|
* In the example below if the `ngApp` directive would not be placed
|
|
10257
10308
|
* on the `html` element then the document would not be compiled
|
|
@@ -10323,22 +10374,38 @@ function angularInit(element, bootstrap) {
|
|
|
10323
10374
|
* @returns {AUTO.$injector} Returns the newly created injector for this app.
|
|
10324
10375
|
*/
|
|
10325
10376
|
function bootstrap(element, modules) {
|
|
10326
|
-
|
|
10327
|
-
|
|
10328
|
-
|
|
10329
|
-
|
|
10330
|
-
|
|
10331
|
-
|
|
10332
|
-
|
|
10333
|
-
|
|
10334
|
-
['$rootScope', '$rootElement', '$compile', '$injector',
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
|
|
10338
|
-
|
|
10339
|
-
|
|
10340
|
-
|
|
10341
|
-
|
|
10377
|
+
var resumeBootstrapInternal = function() {
|
|
10378
|
+
element = jqLite(element);
|
|
10379
|
+
modules = modules || [];
|
|
10380
|
+
modules.unshift(['$provide', function($provide) {
|
|
10381
|
+
$provide.value('$rootElement', element);
|
|
10382
|
+
}]);
|
|
10383
|
+
modules.unshift('ng');
|
|
10384
|
+
var injector = createInjector(modules);
|
|
10385
|
+
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
|
|
10386
|
+
function(scope, element, compile, injector) {
|
|
10387
|
+
scope.$apply(function() {
|
|
10388
|
+
element.data('$injector', injector);
|
|
10389
|
+
compile(element)(scope);
|
|
10390
|
+
});
|
|
10391
|
+
}]
|
|
10392
|
+
);
|
|
10393
|
+
return injector;
|
|
10394
|
+
};
|
|
10395
|
+
|
|
10396
|
+
var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
|
|
10397
|
+
|
|
10398
|
+
if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
|
|
10399
|
+
return resumeBootstrapInternal();
|
|
10400
|
+
}
|
|
10401
|
+
|
|
10402
|
+
window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
|
|
10403
|
+
angular.resumeBootstrap = function(extraModules) {
|
|
10404
|
+
forEach(extraModules, function(module) {
|
|
10405
|
+
modules.push(module);
|
|
10406
|
+
});
|
|
10407
|
+
resumeBootstrapInternal();
|
|
10408
|
+
};
|
|
10342
10409
|
}
|
|
10343
10410
|
|
|
10344
10411
|
var SNAKE_CASE_REGEXP = /[A-Z]/g;
|
|
@@ -10371,7 +10438,7 @@ function bindJQuery() {
|
|
|
10371
10438
|
}
|
|
10372
10439
|
|
|
10373
10440
|
/**
|
|
10374
|
-
* throw error
|
|
10441
|
+
* throw error if the argument is falsy.
|
|
10375
10442
|
*/
|
|
10376
10443
|
function assertArg(arg, name, reason) {
|
|
10377
10444
|
if (!arg) {
|
|
@@ -10652,11 +10719,11 @@ function setupModuleLoader(window) {
|
|
|
10652
10719
|
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
|
|
10653
10720
|
*/
|
|
10654
10721
|
var version = {
|
|
10655
|
-
full: '1.0.
|
|
10656
|
-
major: 1, //
|
|
10722
|
+
full: '1.0.7', // all of these placeholder strings will be replaced by grunt's
|
|
10723
|
+
major: 1, // package task
|
|
10657
10724
|
minor: 0,
|
|
10658
|
-
dot:
|
|
10659
|
-
codeName: '
|
|
10725
|
+
dot: 7,
|
|
10726
|
+
codeName: 'monochromatic-rainbow'
|
|
10660
10727
|
};
|
|
10661
10728
|
|
|
10662
10729
|
|
|
@@ -10801,18 +10868,18 @@ function publishExternalAPI(angular){
|
|
|
10801
10868
|
* - [after()](http://api.jquery.com/after/)
|
|
10802
10869
|
* - [append()](http://api.jquery.com/append/)
|
|
10803
10870
|
* - [attr()](http://api.jquery.com/attr/)
|
|
10804
|
-
* - [bind()](http://api.jquery.com/bind/)
|
|
10805
|
-
* - [children()](http://api.jquery.com/children/)
|
|
10871
|
+
* - [bind()](http://api.jquery.com/bind/) - Does not support namespaces
|
|
10872
|
+
* - [children()](http://api.jquery.com/children/) - Does not support selectors
|
|
10806
10873
|
* - [clone()](http://api.jquery.com/clone/)
|
|
10807
10874
|
* - [contents()](http://api.jquery.com/contents/)
|
|
10808
10875
|
* - [css()](http://api.jquery.com/css/)
|
|
10809
10876
|
* - [data()](http://api.jquery.com/data/)
|
|
10810
10877
|
* - [eq()](http://api.jquery.com/eq/)
|
|
10811
|
-
* - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name
|
|
10878
|
+
* - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name
|
|
10812
10879
|
* - [hasClass()](http://api.jquery.com/hasClass/)
|
|
10813
10880
|
* - [html()](http://api.jquery.com/html/)
|
|
10814
|
-
* - [next()](http://api.jquery.com/next/)
|
|
10815
|
-
* - [parent()](http://api.jquery.com/parent/)
|
|
10881
|
+
* - [next()](http://api.jquery.com/next/) - Does not support selectors
|
|
10882
|
+
* - [parent()](http://api.jquery.com/parent/) - Does not support selectors
|
|
10816
10883
|
* - [prepend()](http://api.jquery.com/prepend/)
|
|
10817
10884
|
* - [prop()](http://api.jquery.com/prop/)
|
|
10818
10885
|
* - [ready()](http://api.jquery.com/ready/)
|
|
@@ -10824,11 +10891,11 @@ function publishExternalAPI(angular){
|
|
|
10824
10891
|
* - [text()](http://api.jquery.com/text/)
|
|
10825
10892
|
* - [toggleClass()](http://api.jquery.com/toggleClass/)
|
|
10826
10893
|
* - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.
|
|
10827
|
-
* - [unbind()](http://api.jquery.com/unbind/)
|
|
10894
|
+
* - [unbind()](http://api.jquery.com/unbind/) - Does not support namespaces
|
|
10828
10895
|
* - [val()](http://api.jquery.com/val/)
|
|
10829
10896
|
* - [wrap()](http://api.jquery.com/wrap/)
|
|
10830
10897
|
*
|
|
10831
|
-
* ## In addtion to the above, Angular
|
|
10898
|
+
* ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
|
|
10832
10899
|
*
|
|
10833
10900
|
* - `controller(name)` - retrieves the controller of the current element or its parent. By default
|
|
10834
10901
|
* retrieves controller associated with the `ngController` directive. If `name` is provided as
|
|
@@ -11371,23 +11438,43 @@ forEach({
|
|
|
11371
11438
|
|
|
11372
11439
|
if (!eventFns) {
|
|
11373
11440
|
if (type == 'mouseenter' || type == 'mouseleave') {
|
|
11374
|
-
var
|
|
11441
|
+
var contains = document.body.contains || document.body.compareDocumentPosition ?
|
|
11442
|
+
function( a, b ) {
|
|
11443
|
+
var adown = a.nodeType === 9 ? a.documentElement : a,
|
|
11444
|
+
bup = b && b.parentNode;
|
|
11445
|
+
return a === bup || !!( bup && bup.nodeType === 1 && (
|
|
11446
|
+
adown.contains ?
|
|
11447
|
+
adown.contains( bup ) :
|
|
11448
|
+
a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
|
|
11449
|
+
));
|
|
11450
|
+
} :
|
|
11451
|
+
function( a, b ) {
|
|
11452
|
+
if ( b ) {
|
|
11453
|
+
while ( (b = b.parentNode) ) {
|
|
11454
|
+
if ( b === a ) {
|
|
11455
|
+
return true;
|
|
11456
|
+
}
|
|
11457
|
+
}
|
|
11458
|
+
}
|
|
11459
|
+
return false;
|
|
11460
|
+
};
|
|
11375
11461
|
|
|
11376
|
-
events
|
|
11377
|
-
|
|
11462
|
+
events[type] = [];
|
|
11463
|
+
|
|
11464
|
+
// Refer to jQuery's implementation of mouseenter & mouseleave
|
|
11465
|
+
// Read about mouseenter and mouseleave:
|
|
11466
|
+
// http://www.quirksmode.org/js/events_mouse.html#link8
|
|
11467
|
+
var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"}
|
|
11468
|
+
bindFn(element, eventmap[type], function(event) {
|
|
11469
|
+
var ret, target = this, related = event.relatedTarget;
|
|
11470
|
+
// For mousenter/leave call the handler if related is outside the target.
|
|
11471
|
+
// NB: No relatedTarget if the mouse left/entered the browser window
|
|
11472
|
+
if ( !related || (related !== target && !contains(target, related)) ){
|
|
11473
|
+
handle(event, type);
|
|
11474
|
+
}
|
|
11378
11475
|
|
|
11379
|
-
bindFn(element, 'mouseover', function(event) {
|
|
11380
|
-
counter++;
|
|
11381
|
-
if (counter == 1) {
|
|
11382
|
-
handle(event, 'mouseenter');
|
|
11383
|
-
}
|
|
11384
|
-
});
|
|
11385
|
-
bindFn(element, 'mouseout', function(event) {
|
|
11386
|
-
counter --;
|
|
11387
|
-
if (counter == 0) {
|
|
11388
|
-
handle(event, 'mouseleave');
|
|
11389
|
-
}
|
|
11390
11476
|
});
|
|
11477
|
+
|
|
11391
11478
|
} else {
|
|
11392
11479
|
addEventListenerFn(element, type, handle);
|
|
11393
11480
|
events[type] = [];
|
|
@@ -11416,14 +11503,14 @@ forEach({
|
|
|
11416
11503
|
children: function(element) {
|
|
11417
11504
|
var children = [];
|
|
11418
11505
|
forEach(element.childNodes, function(element){
|
|
11419
|
-
if (element.
|
|
11506
|
+
if (element.nodeType === 1)
|
|
11420
11507
|
children.push(element);
|
|
11421
11508
|
});
|
|
11422
11509
|
return children;
|
|
11423
11510
|
},
|
|
11424
11511
|
|
|
11425
11512
|
contents: function(element) {
|
|
11426
|
-
return element.childNodes;
|
|
11513
|
+
return element.childNodes || [];
|
|
11427
11514
|
},
|
|
11428
11515
|
|
|
11429
11516
|
append: function(element, node) {
|
|
@@ -11486,7 +11573,16 @@ forEach({
|
|
|
11486
11573
|
},
|
|
11487
11574
|
|
|
11488
11575
|
next: function(element) {
|
|
11489
|
-
|
|
11576
|
+
if (element.nextElementSibling) {
|
|
11577
|
+
return element.nextElementSibling;
|
|
11578
|
+
}
|
|
11579
|
+
|
|
11580
|
+
// IE8 doesn't have nextElementSibling
|
|
11581
|
+
var elm = element.nextSibling;
|
|
11582
|
+
while (elm != null && elm.nodeType !== 1) {
|
|
11583
|
+
elm = elm.nextSibling;
|
|
11584
|
+
}
|
|
11585
|
+
return elm;
|
|
11490
11586
|
},
|
|
11491
11587
|
|
|
11492
11588
|
find: function(element, selector) {
|
|
@@ -11694,7 +11790,7 @@ function annotate(fn) {
|
|
|
11694
11790
|
}
|
|
11695
11791
|
} else if (isArray(fn)) {
|
|
11696
11792
|
last = fn.length - 1;
|
|
11697
|
-
assertArgFn(fn[last], 'fn')
|
|
11793
|
+
assertArgFn(fn[last], 'fn');
|
|
11698
11794
|
$inject = fn.slice(0, last);
|
|
11699
11795
|
} else {
|
|
11700
11796
|
assertArgFn(fn, 'fn', true);
|
|
@@ -11728,19 +11824,19 @@ function annotate(fn) {
|
|
|
11728
11824
|
* # Injection Function Annotation
|
|
11729
11825
|
*
|
|
11730
11826
|
* JavaScript does not have annotations, and annotations are needed for dependency injection. The
|
|
11731
|
-
* following
|
|
11827
|
+
* following are all valid ways of annotating function with injection arguments and are equivalent.
|
|
11732
11828
|
*
|
|
11733
11829
|
* <pre>
|
|
11734
11830
|
* // inferred (only works if code not minified/obfuscated)
|
|
11735
|
-
* $
|
|
11831
|
+
* $injector.invoke(function(serviceA){});
|
|
11736
11832
|
*
|
|
11737
11833
|
* // annotated
|
|
11738
11834
|
* function explicit(serviceA) {};
|
|
11739
11835
|
* explicit.$inject = ['serviceA'];
|
|
11740
|
-
* $
|
|
11836
|
+
* $injector.invoke(explicit);
|
|
11741
11837
|
*
|
|
11742
11838
|
* // inline
|
|
11743
|
-
* $
|
|
11839
|
+
* $injector.invoke(['serviceA', function(serviceA){}]);
|
|
11744
11840
|
* </pre>
|
|
11745
11841
|
*
|
|
11746
11842
|
* ## Inference
|
|
@@ -11824,7 +11920,7 @@ function annotate(fn) {
|
|
|
11824
11920
|
* This method does not work with code minfication / obfuscation. For this reason the following annotation strategies
|
|
11825
11921
|
* are supported.
|
|
11826
11922
|
*
|
|
11827
|
-
* # The `$
|
|
11923
|
+
* # The `$inject` property
|
|
11828
11924
|
*
|
|
11829
11925
|
* If a function has an `$inject` property and its value is an array of strings, then the strings represent names of
|
|
11830
11926
|
* services to be injected into the function.
|
|
@@ -11857,7 +11953,7 @@ function annotate(fn) {
|
|
|
11857
11953
|
* // ...
|
|
11858
11954
|
* };
|
|
11859
11955
|
* tmpFn.$inject = ['$compile', '$rootScope'];
|
|
11860
|
-
* injector.invoke(
|
|
11956
|
+
* injector.invoke(tmpFn);
|
|
11861
11957
|
*
|
|
11862
11958
|
* // To better support inline function the inline annotation is supported
|
|
11863
11959
|
* injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
|
|
@@ -11886,7 +11982,7 @@ function annotate(fn) {
|
|
|
11886
11982
|
* @description
|
|
11887
11983
|
*
|
|
11888
11984
|
* Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.
|
|
11889
|
-
* The providers share the same name as the instance they create with
|
|
11985
|
+
* The providers share the same name as the instance they create with `Provider` suffixed to them.
|
|
11890
11986
|
*
|
|
11891
11987
|
* A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of
|
|
11892
11988
|
* a service. The Provider can have additional methods which would allow for configuration of the provider.
|
|
@@ -11910,7 +12006,7 @@ function annotate(fn) {
|
|
|
11910
12006
|
*
|
|
11911
12007
|
* beforeEach(module(function($provide) {
|
|
11912
12008
|
* $provide.provider('greet', GreetProvider);
|
|
11913
|
-
* });
|
|
12009
|
+
* }));
|
|
11914
12010
|
*
|
|
11915
12011
|
* it('should greet', inject(function(greet) {
|
|
11916
12012
|
* expect(greet('angular')).toEqual('Hello angular!');
|
|
@@ -11923,9 +12019,7 @@ function annotate(fn) {
|
|
|
11923
12019
|
* inject(function(greet) {
|
|
11924
12020
|
* expect(greet('angular')).toEqual('Ahoj angular!');
|
|
11925
12021
|
* });
|
|
11926
|
-
* )
|
|
11927
|
-
*
|
|
11928
|
-
* });
|
|
12022
|
+
* });
|
|
11929
12023
|
* </pre>
|
|
11930
12024
|
*/
|
|
11931
12025
|
|
|
@@ -12019,7 +12113,7 @@ function annotate(fn) {
|
|
|
12019
12113
|
*
|
|
12020
12114
|
* @param {string} name The name of the service to decorate.
|
|
12021
12115
|
* @param {function()} decorator This function will be invoked when the service needs to be
|
|
12022
|
-
*
|
|
12116
|
+
* instantiated. The function is called using the {@link AUTO.$injector#invoke
|
|
12023
12117
|
* injector.invoke} method and is therefore fully injectable. Local injection arguments:
|
|
12024
12118
|
*
|
|
12025
12119
|
* * `$delegate` - The original service instance, which can be monkey patched, configured,
|
|
@@ -12072,7 +12166,7 @@ function createInjector(modulesToLoad) {
|
|
|
12072
12166
|
}
|
|
12073
12167
|
|
|
12074
12168
|
function provider(name, provider_) {
|
|
12075
|
-
if (isFunction(provider_)) {
|
|
12169
|
+
if (isFunction(provider_) || isArray(provider_)) {
|
|
12076
12170
|
provider_ = providerInjector.instantiate(provider_);
|
|
12077
12171
|
}
|
|
12078
12172
|
if (!provider_.$get) {
|
|
@@ -12189,7 +12283,7 @@ function createInjector(modulesToLoad) {
|
|
|
12189
12283
|
args.push(
|
|
12190
12284
|
locals && locals.hasOwnProperty(key)
|
|
12191
12285
|
? locals[key]
|
|
12192
|
-
: getService(key
|
|
12286
|
+
: getService(key)
|
|
12193
12287
|
);
|
|
12194
12288
|
}
|
|
12195
12289
|
if (!fn.$inject) {
|
|
@@ -12219,6 +12313,8 @@ function createInjector(modulesToLoad) {
|
|
|
12219
12313
|
var Constructor = function() {},
|
|
12220
12314
|
instance, returnedValue;
|
|
12221
12315
|
|
|
12316
|
+
// Check if Type is annotated and use just the given function at n-1 as parameter
|
|
12317
|
+
// e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
|
|
12222
12318
|
Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
|
|
12223
12319
|
instance = new Constructor();
|
|
12224
12320
|
returnedValue = invoke(Type, instance, locals);
|
|
@@ -12234,6 +12330,7 @@ function createInjector(modulesToLoad) {
|
|
|
12234
12330
|
};
|
|
12235
12331
|
}
|
|
12236
12332
|
}
|
|
12333
|
+
|
|
12237
12334
|
/**
|
|
12238
12335
|
* @ngdoc function
|
|
12239
12336
|
* @name ng.$anchorScroll
|
|
@@ -12289,7 +12386,7 @@ function $AnchorScrollProvider() {
|
|
|
12289
12386
|
}
|
|
12290
12387
|
|
|
12291
12388
|
// does not scroll when user clicks on anchor link that is currently on
|
|
12292
|
-
// (no url change, no $
|
|
12389
|
+
// (no url change, no $location.hash() change), browser native does scroll
|
|
12293
12390
|
if (autoScrollingEnabled) {
|
|
12294
12391
|
$rootScope.$watch(function autoScrollWatch() {return $location.hash();},
|
|
12295
12392
|
function autoScrollWatchAction() {
|
|
@@ -12538,7 +12635,7 @@ function Browser(window, document, $log, $sniffer) {
|
|
|
12538
12635
|
*/
|
|
12539
12636
|
self.baseHref = function() {
|
|
12540
12637
|
var href = baseElement.attr('href');
|
|
12541
|
-
return href ? href.replace(/^https?\:\/\/[^\/]*/, '') :
|
|
12638
|
+
return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : '';
|
|
12542
12639
|
};
|
|
12543
12640
|
|
|
12544
12641
|
//////////////////////////////////////////////////////////////
|
|
@@ -12577,14 +12674,15 @@ function Browser(window, document, $log, $sniffer) {
|
|
|
12577
12674
|
} else {
|
|
12578
12675
|
if (isString(value)) {
|
|
12579
12676
|
cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;
|
|
12677
|
+
|
|
12678
|
+
// per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
|
|
12679
|
+
// - 300 cookies
|
|
12680
|
+
// - 20 cookies per unique domain
|
|
12681
|
+
// - 4096 bytes per cookie
|
|
12580
12682
|
if (cookieLength > 4096) {
|
|
12581
12683
|
$log.warn("Cookie '"+ name +"' possibly not set or overflowed because it was too large ("+
|
|
12582
12684
|
cookieLength + " > 4096 bytes)!");
|
|
12583
12685
|
}
|
|
12584
|
-
if (lastCookies.length > 20) {
|
|
12585
|
-
$log.warn("Cookie '"+ name +"' possibly not set or overflowed because too many cookies " +
|
|
12586
|
-
"were already set (" + lastCookies.length + " > 20 )");
|
|
12587
|
-
}
|
|
12588
12686
|
}
|
|
12589
12687
|
}
|
|
12590
12688
|
} else {
|
|
@@ -12597,7 +12695,13 @@ function Browser(window, document, $log, $sniffer) {
|
|
|
12597
12695
|
cookie = cookieArray[i];
|
|
12598
12696
|
index = cookie.indexOf('=');
|
|
12599
12697
|
if (index > 0) { //ignore nameless cookies
|
|
12600
|
-
|
|
12698
|
+
var name = unescape(cookie.substring(0, index));
|
|
12699
|
+
// the first value that is seen for a cookie is the most
|
|
12700
|
+
// specific one. values for the same cookie name that
|
|
12701
|
+
// follow are for less specific paths.
|
|
12702
|
+
if (lastCookies[name] === undefined) {
|
|
12703
|
+
lastCookies[name] = unescape(cookie.substring(index + 1));
|
|
12704
|
+
}
|
|
12601
12705
|
}
|
|
12602
12706
|
}
|
|
12603
12707
|
}
|
|
@@ -12661,6 +12765,7 @@ function $BrowserProvider(){
|
|
|
12661
12765
|
return new Browser($window, $document, $log, $sniffer);
|
|
12662
12766
|
}];
|
|
12663
12767
|
}
|
|
12768
|
+
|
|
12664
12769
|
/**
|
|
12665
12770
|
* @ngdoc object
|
|
12666
12771
|
* @name ng.$cacheFactory
|
|
@@ -12987,7 +13092,8 @@ function $CompileProvider($provide) {
|
|
|
12987
13092
|
Suffix = 'Directive',
|
|
12988
13093
|
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
|
|
12989
13094
|
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
|
|
12990
|
-
MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: '
|
|
13095
|
+
MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ',
|
|
13096
|
+
urlSanitizationWhitelist = /^\s*(https?|ftp|mailto|file):/;
|
|
12991
13097
|
|
|
12992
13098
|
|
|
12993
13099
|
/**
|
|
@@ -13041,11 +13147,41 @@ function $CompileProvider($provide) {
|
|
|
13041
13147
|
};
|
|
13042
13148
|
|
|
13043
13149
|
|
|
13150
|
+
/**
|
|
13151
|
+
* @ngdoc function
|
|
13152
|
+
* @name ng.$compileProvider#urlSanitizationWhitelist
|
|
13153
|
+
* @methodOf ng.$compileProvider
|
|
13154
|
+
* @function
|
|
13155
|
+
*
|
|
13156
|
+
* @description
|
|
13157
|
+
* Retrieves or overrides the default regular expression that is used for whitelisting of safe
|
|
13158
|
+
* urls during a[href] sanitization.
|
|
13159
|
+
*
|
|
13160
|
+
* The sanitization is a security measure aimed at prevent XSS attacks via html links.
|
|
13161
|
+
*
|
|
13162
|
+
* Any url about to be assigned to a[href] via data-binding is first normalized and turned into an
|
|
13163
|
+
* absolute url. Afterwards the url is matched against the `urlSanitizationWhitelist` regular
|
|
13164
|
+
* expression. If a match is found the original url is written into the dom. Otherwise the
|
|
13165
|
+
* absolute url is prefixed with `'unsafe:'` string and only then it is written into the DOM.
|
|
13166
|
+
*
|
|
13167
|
+
* @param {RegExp=} regexp New regexp to whitelist urls with.
|
|
13168
|
+
* @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
|
|
13169
|
+
* chaining otherwise.
|
|
13170
|
+
*/
|
|
13171
|
+
this.urlSanitizationWhitelist = function(regexp) {
|
|
13172
|
+
if (isDefined(regexp)) {
|
|
13173
|
+
urlSanitizationWhitelist = regexp;
|
|
13174
|
+
return this;
|
|
13175
|
+
}
|
|
13176
|
+
return urlSanitizationWhitelist;
|
|
13177
|
+
};
|
|
13178
|
+
|
|
13179
|
+
|
|
13044
13180
|
this.$get = [
|
|
13045
13181
|
'$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
|
|
13046
|
-
'$controller', '$rootScope',
|
|
13182
|
+
'$controller', '$rootScope', '$document',
|
|
13047
13183
|
function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
|
|
13048
|
-
$controller, $rootScope) {
|
|
13184
|
+
$controller, $rootScope, $document) {
|
|
13049
13185
|
|
|
13050
13186
|
var Attributes = function(element, attr) {
|
|
13051
13187
|
this.$$element = element;
|
|
@@ -13067,7 +13203,8 @@ function $CompileProvider($provide) {
|
|
|
13067
13203
|
*/
|
|
13068
13204
|
$set: function(key, value, writeAttr, attrName) {
|
|
13069
13205
|
var booleanKey = getBooleanAttrName(this.$$element[0], key),
|
|
13070
|
-
$$observers = this.$$observers
|
|
13206
|
+
$$observers = this.$$observers,
|
|
13207
|
+
normalizedVal;
|
|
13071
13208
|
|
|
13072
13209
|
if (booleanKey) {
|
|
13073
13210
|
this.$$element.prop(key, value);
|
|
@@ -13086,6 +13223,19 @@ function $CompileProvider($provide) {
|
|
|
13086
13223
|
}
|
|
13087
13224
|
}
|
|
13088
13225
|
|
|
13226
|
+
|
|
13227
|
+
// sanitize a[href] values
|
|
13228
|
+
if (nodeName_(this.$$element[0]) === 'A' && key === 'href') {
|
|
13229
|
+
urlSanitizationNode.setAttribute('href', value);
|
|
13230
|
+
|
|
13231
|
+
// href property always returns normalized absolute url, so we can match against that
|
|
13232
|
+
normalizedVal = urlSanitizationNode.href;
|
|
13233
|
+
if (!normalizedVal.match(urlSanitizationWhitelist)) {
|
|
13234
|
+
this[key] = value = 'unsafe:' + normalizedVal;
|
|
13235
|
+
}
|
|
13236
|
+
}
|
|
13237
|
+
|
|
13238
|
+
|
|
13089
13239
|
if (writeAttr !== false) {
|
|
13090
13240
|
if (value === null || value === undefined) {
|
|
13091
13241
|
this.$$element.removeAttr(attrName);
|
|
@@ -13129,7 +13279,8 @@ function $CompileProvider($provide) {
|
|
|
13129
13279
|
}
|
|
13130
13280
|
};
|
|
13131
13281
|
|
|
13132
|
-
var
|
|
13282
|
+
var urlSanitizationNode = $document[0].createElement('a'),
|
|
13283
|
+
startSymbol = $interpolate.startSymbol(),
|
|
13133
13284
|
endSymbol = $interpolate.endSymbol(),
|
|
13134
13285
|
denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
|
|
13135
13286
|
? identity
|
|
@@ -13144,13 +13295,13 @@ function $CompileProvider($provide) {
|
|
|
13144
13295
|
|
|
13145
13296
|
function compile($compileNodes, transcludeFn, maxPriority) {
|
|
13146
13297
|
if (!($compileNodes instanceof jqLite)) {
|
|
13147
|
-
// jquery always rewraps,
|
|
13298
|
+
// jquery always rewraps, whereas we need to preserve the original selector so that we can modify it.
|
|
13148
13299
|
$compileNodes = jqLite($compileNodes);
|
|
13149
13300
|
}
|
|
13150
13301
|
// We can not compile top level text elements since text nodes can be merged and we will
|
|
13151
13302
|
// not be able to attach scope data to them, so we will wrap them in <span>
|
|
13152
13303
|
forEach($compileNodes, function(node, index){
|
|
13153
|
-
if (node.nodeType == 3 /* text node */) {
|
|
13304
|
+
if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) {
|
|
13154
13305
|
$compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
|
|
13155
13306
|
}
|
|
13156
13307
|
});
|
|
@@ -13162,7 +13313,14 @@ function $CompileProvider($provide) {
|
|
|
13162
13313
|
var $linkNode = cloneConnectFn
|
|
13163
13314
|
? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
|
|
13164
13315
|
: $compileNodes;
|
|
13165
|
-
|
|
13316
|
+
|
|
13317
|
+
// Attach scope only to non-text nodes.
|
|
13318
|
+
for(var i = 0, ii = $linkNode.length; i<ii; i++) {
|
|
13319
|
+
var node = $linkNode[i];
|
|
13320
|
+
if (node.nodeType == 1 /* element */ || node.nodeType == 9 /* document */) {
|
|
13321
|
+
$linkNode.eq(i).data('$scope', scope);
|
|
13322
|
+
}
|
|
13323
|
+
}
|
|
13166
13324
|
safeAddClass($linkNode, 'ng-scope');
|
|
13167
13325
|
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
|
|
13168
13326
|
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
|
|
@@ -13189,7 +13347,7 @@ function $CompileProvider($provide) {
|
|
|
13189
13347
|
* functions return values - the linking functions - are combined into a composite linking
|
|
13190
13348
|
* function, which is the a linking function for the node.
|
|
13191
13349
|
*
|
|
13192
|
-
* @param {NodeList} nodeList an array of nodes to compile
|
|
13350
|
+
* @param {NodeList} nodeList an array of nodes or NodeList to compile
|
|
13193
13351
|
* @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
|
|
13194
13352
|
* scope argument is auto-generated to the new child of the transcluded parent scope.
|
|
13195
13353
|
* @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then the
|
|
@@ -13199,68 +13357,75 @@ function $CompileProvider($provide) {
|
|
|
13199
13357
|
* @returns {?function} A composite linking function of all of the matched directives or null.
|
|
13200
13358
|
*/
|
|
13201
13359
|
function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {
|
|
13202
|
-
|
|
13203
|
-
|
|
13360
|
+
var linkFns = [],
|
|
13361
|
+
nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
|
|
13204
13362
|
|
|
13205
|
-
|
|
13206
|
-
|
|
13363
|
+
for(var i = 0; i < nodeList.length; i++) {
|
|
13364
|
+
attrs = new Attributes();
|
|
13207
13365
|
|
|
13208
|
-
|
|
13209
|
-
|
|
13366
|
+
// we must always refer to nodeList[i] since the nodes can be replaced underneath us.
|
|
13367
|
+
directives = collectDirectives(nodeList[i], [], attrs, maxPriority);
|
|
13210
13368
|
|
|
13211
|
-
|
|
13212
|
-
|
|
13213
|
-
|
|
13369
|
+
nodeLinkFn = (directives.length)
|
|
13370
|
+
? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
|
|
13371
|
+
: null;
|
|
13214
13372
|
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13373
|
+
childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes || !nodeList[i].childNodes.length)
|
|
13374
|
+
? null
|
|
13375
|
+
: compileNodes(nodeList[i].childNodes,
|
|
13376
|
+
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
|
|
13219
13377
|
|
|
13220
|
-
|
|
13221
|
-
|
|
13222
|
-
|
|
13223
|
-
|
|
13378
|
+
linkFns.push(nodeLinkFn);
|
|
13379
|
+
linkFns.push(childLinkFn);
|
|
13380
|
+
linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
|
|
13381
|
+
}
|
|
13224
13382
|
|
|
13225
|
-
|
|
13226
|
-
|
|
13383
|
+
// return a linking function if we have found anything, null otherwise
|
|
13384
|
+
return linkFnFound ? compositeLinkFn : null;
|
|
13227
13385
|
|
|
13228
|
-
|
|
13229
|
-
|
|
13386
|
+
function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
|
|
13387
|
+
var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;
|
|
13230
13388
|
|
|
13231
|
-
|
|
13232
|
-
|
|
13233
|
-
|
|
13234
|
-
|
|
13389
|
+
// copy nodeList so that linking doesn't break due to live list updates.
|
|
13390
|
+
var stableNodeList = [];
|
|
13391
|
+
for (i = 0, ii = nodeList.length; i < ii; i++) {
|
|
13392
|
+
stableNodeList.push(nodeList[i]);
|
|
13393
|
+
}
|
|
13235
13394
|
|
|
13236
|
-
|
|
13237
|
-
|
|
13238
|
-
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13395
|
+
for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
|
|
13396
|
+
node = stableNodeList[n];
|
|
13397
|
+
nodeLinkFn = linkFns[i++];
|
|
13398
|
+
childLinkFn = linkFns[i++];
|
|
13399
|
+
|
|
13400
|
+
if (nodeLinkFn) {
|
|
13401
|
+
if (nodeLinkFn.scope) {
|
|
13402
|
+
childScope = scope.$new(isObject(nodeLinkFn.scope));
|
|
13403
|
+
jqLite(node).data('$scope', childScope);
|
|
13404
|
+
} else {
|
|
13405
|
+
childScope = scope;
|
|
13406
|
+
}
|
|
13407
|
+
childTranscludeFn = nodeLinkFn.transclude;
|
|
13408
|
+
if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
|
|
13409
|
+
nodeLinkFn(childLinkFn, childScope, node, $rootElement,
|
|
13410
|
+
(function(transcludeFn) {
|
|
13411
|
+
return function(cloneFn) {
|
|
13412
|
+
var transcludeScope = scope.$new();
|
|
13413
|
+
transcludeScope.$$transcluded = true;
|
|
13414
|
+
|
|
13415
|
+
return transcludeFn(transcludeScope, cloneFn).
|
|
13416
|
+
bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
|
|
13252
13417
|
};
|
|
13253
13418
|
})(childTranscludeFn || transcludeFn)
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13419
|
+
);
|
|
13420
|
+
} else {
|
|
13421
|
+
nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
|
|
13422
|
+
}
|
|
13423
|
+
} else if (childLinkFn) {
|
|
13424
|
+
childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
|
|
13425
|
+
}
|
|
13426
|
+
}
|
|
13427
|
+
}
|
|
13428
|
+
}
|
|
13264
13429
|
|
|
13265
13430
|
|
|
13266
13431
|
/**
|
|
@@ -13341,9 +13506,9 @@ function $CompileProvider($provide) {
|
|
|
13341
13506
|
|
|
13342
13507
|
|
|
13343
13508
|
/**
|
|
13344
|
-
* Once the directives have been collected their compile functions
|
|
13509
|
+
* Once the directives have been collected, their compile functions are executed. This method
|
|
13345
13510
|
* is responsible for inlining directive templates as well as terminating the application
|
|
13346
|
-
* of the directives if the terminal directive has been reached
|
|
13511
|
+
* of the directives if the terminal directive has been reached.
|
|
13347
13512
|
*
|
|
13348
13513
|
* @param {Array} directives Array of collected directives to execute their compile function.
|
|
13349
13514
|
* this needs to be pre-sorted by priority order.
|
|
@@ -13351,11 +13516,11 @@ function $CompileProvider($provide) {
|
|
|
13351
13516
|
* @param {Object} templateAttrs The shared attribute function
|
|
13352
13517
|
* @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
|
|
13353
13518
|
* scope argument is auto-generated to the new child of the transcluded parent scope.
|
|
13354
|
-
* @param {
|
|
13355
|
-
* argument has the root jqLite array so that we can replace
|
|
13519
|
+
* @param {JQLite} jqCollection If we are working on the root of the compile tree then this
|
|
13520
|
+
* argument has the root jqLite array so that we can replace nodes on it.
|
|
13356
13521
|
* @returns linkFn
|
|
13357
13522
|
*/
|
|
13358
|
-
function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
|
|
13523
|
+
function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection) {
|
|
13359
13524
|
var terminalPriority = -Number.MAX_VALUE,
|
|
13360
13525
|
preLinkFns = [],
|
|
13361
13526
|
postLinkFns = [],
|
|
@@ -13407,9 +13572,9 @@ function $CompileProvider($provide) {
|
|
|
13407
13572
|
if (directiveValue == 'element') {
|
|
13408
13573
|
$template = jqLite(compileNode);
|
|
13409
13574
|
$compileNode = templateAttrs.$$element =
|
|
13410
|
-
jqLite('
|
|
13575
|
+
jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));
|
|
13411
13576
|
compileNode = $compileNode[0];
|
|
13412
|
-
replaceWith(
|
|
13577
|
+
replaceWith(jqCollection, jqLite($template[0]), compileNode);
|
|
13413
13578
|
childTranscludeFn = compile($template, transcludeFn, terminalPriority);
|
|
13414
13579
|
} else {
|
|
13415
13580
|
$template = jqLite(JQLiteClone(compileNode)).contents();
|
|
@@ -13433,7 +13598,7 @@ function $CompileProvider($provide) {
|
|
|
13433
13598
|
throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);
|
|
13434
13599
|
}
|
|
13435
13600
|
|
|
13436
|
-
replaceWith(
|
|
13601
|
+
replaceWith(jqCollection, $compileNode, compileNode);
|
|
13437
13602
|
|
|
13438
13603
|
var newTemplateAttrs = {$attr: {}};
|
|
13439
13604
|
|
|
@@ -13461,7 +13626,7 @@ function $CompileProvider($provide) {
|
|
|
13461
13626
|
assertNoDuplicate('template', templateDirective, directive, $compileNode);
|
|
13462
13627
|
templateDirective = directive;
|
|
13463
13628
|
nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),
|
|
13464
|
-
nodeLinkFn, $compileNode, templateAttrs,
|
|
13629
|
+
nodeLinkFn, $compileNode, templateAttrs, jqCollection, directive.replace,
|
|
13465
13630
|
childTranscludeFn);
|
|
13466
13631
|
ii = directives.length;
|
|
13467
13632
|
} else if (directive.compile) {
|
|
@@ -13551,6 +13716,8 @@ function $CompileProvider($provide) {
|
|
|
13551
13716
|
lastValue,
|
|
13552
13717
|
parentGet, parentSet;
|
|
13553
13718
|
|
|
13719
|
+
scope.$$isolateBindings[scopeName] = mode + attrName;
|
|
13720
|
+
|
|
13554
13721
|
switch (mode) {
|
|
13555
13722
|
|
|
13556
13723
|
case '@': {
|
|
@@ -13592,7 +13759,7 @@ function $CompileProvider($provide) {
|
|
|
13592
13759
|
parentGet = $parse(attrs[attrName]);
|
|
13593
13760
|
scope[scopeName] = function(locals) {
|
|
13594
13761
|
return parentGet(parentScope, locals);
|
|
13595
|
-
}
|
|
13762
|
+
};
|
|
13596
13763
|
break;
|
|
13597
13764
|
}
|
|
13598
13765
|
|
|
@@ -13761,8 +13928,8 @@ function $CompileProvider($provide) {
|
|
|
13761
13928
|
}
|
|
13762
13929
|
|
|
13763
13930
|
directives.unshift(derivedSyncDirective);
|
|
13764
|
-
afterTemplateNodeLinkFn = applyDirectivesToNode(directives,
|
|
13765
|
-
afterTemplateChildLinkFn = compileNodes($compileNode.
|
|
13931
|
+
afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn);
|
|
13932
|
+
afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
|
|
13766
13933
|
|
|
13767
13934
|
|
|
13768
13935
|
while(linkQueue.length) {
|
|
@@ -13841,10 +14008,10 @@ function $CompileProvider($provide) {
|
|
|
13841
14008
|
function addAttrInterpolateDirective(node, directives, value, name) {
|
|
13842
14009
|
var interpolateFn = $interpolate(value, true);
|
|
13843
14010
|
|
|
13844
|
-
|
|
13845
14011
|
// no interpolation found -> ignore
|
|
13846
14012
|
if (!interpolateFn) return;
|
|
13847
14013
|
|
|
14014
|
+
|
|
13848
14015
|
directives.push({
|
|
13849
14016
|
priority: 100,
|
|
13850
14017
|
compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {
|
|
@@ -14027,7 +14194,7 @@ function $ControllerProvider() {
|
|
|
14027
14194
|
* @description
|
|
14028
14195
|
* `$controller` service is responsible for instantiating controllers.
|
|
14029
14196
|
*
|
|
14030
|
-
* It's just simple call to {@link AUTO.$injector $injector}, but extracted into
|
|
14197
|
+
* It's just a simple call to {@link AUTO.$injector $injector}, but extracted into
|
|
14031
14198
|
* a service, so that one can override this service with {@link https://gist.github.com/1649788
|
|
14032
14199
|
* BC version}.
|
|
14033
14200
|
*/
|
|
@@ -14072,14 +14239,15 @@ function $DocumentProvider(){
|
|
|
14072
14239
|
* the browser console.
|
|
14073
14240
|
*
|
|
14074
14241
|
* In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
|
|
14075
|
-
* {@link ngMock.$exceptionHandler mock $exceptionHandler}
|
|
14242
|
+
* {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
|
|
14076
14243
|
*
|
|
14077
14244
|
* @param {Error} exception Exception associated with the error.
|
|
14078
14245
|
* @param {string=} cause optional information about the context in which
|
|
14079
14246
|
* the error was thrown.
|
|
14247
|
+
*
|
|
14080
14248
|
*/
|
|
14081
14249
|
function $ExceptionHandlerProvider() {
|
|
14082
|
-
this.$get = ['$log', function($log){
|
|
14250
|
+
this.$get = ['$log', function($log) {
|
|
14083
14251
|
return function(exception, cause) {
|
|
14084
14252
|
$log.error.apply($log, arguments);
|
|
14085
14253
|
};
|
|
@@ -14267,7 +14435,7 @@ function $InterpolateProvider() {
|
|
|
14267
14435
|
}];
|
|
14268
14436
|
}
|
|
14269
14437
|
|
|
14270
|
-
var URL_MATCH = /^([^:]+):\/\/(\w+:{0,1}\w*@)?([\w\.-]
|
|
14438
|
+
var URL_MATCH = /^([^:]+):\/\/(\w+:{0,1}\w*@)?(\{?[\w\.-]*\}?)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
|
|
14271
14439
|
PATH_MATCH = /^([^\?#]*)?(\?([^#]*))?(#(.*))?$/,
|
|
14272
14440
|
HASH_MATCH = PATH_MATCH,
|
|
14273
14441
|
DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
|
|
@@ -14346,7 +14514,8 @@ function convertToHashbangUrl(url, basePath, hashPrefix) {
|
|
|
14346
14514
|
var match = matchUrl(url);
|
|
14347
14515
|
|
|
14348
14516
|
// already hashbang url
|
|
14349
|
-
if (decodeURIComponent(match.path) == basePath)
|
|
14517
|
+
if (decodeURIComponent(match.path) == basePath && !isUndefined(match.hash) &&
|
|
14518
|
+
match.hash.indexOf(hashPrefix) === 0) {
|
|
14350
14519
|
return url;
|
|
14351
14520
|
// convert html5 url -> hashbang url
|
|
14352
14521
|
} else {
|
|
@@ -14843,6 +15012,10 @@ function $LocationProvider(){
|
|
|
14843
15012
|
// update $location when $browser url changes
|
|
14844
15013
|
$browser.onUrlChange(function(newUrl) {
|
|
14845
15014
|
if ($location.absUrl() != newUrl) {
|
|
15015
|
+
if ($rootScope.$broadcast('$locationChangeStart', newUrl, $location.absUrl()).defaultPrevented) {
|
|
15016
|
+
$browser.url($location.absUrl());
|
|
15017
|
+
return;
|
|
15018
|
+
}
|
|
14846
15019
|
$rootScope.$evalAsync(function() {
|
|
14847
15020
|
var oldUrl = $location.absUrl();
|
|
14848
15021
|
|
|
@@ -15151,10 +15324,10 @@ function lex(text, csp){
|
|
|
15151
15324
|
function readIdent() {
|
|
15152
15325
|
var ident = "",
|
|
15153
15326
|
start = index,
|
|
15154
|
-
lastDot, peekIndex, methodName;
|
|
15327
|
+
lastDot, peekIndex, methodName, ch;
|
|
15155
15328
|
|
|
15156
15329
|
while (index < text.length) {
|
|
15157
|
-
|
|
15330
|
+
ch = text.charAt(index);
|
|
15158
15331
|
if (ch == '.' || isIdent(ch) || isNumber(ch)) {
|
|
15159
15332
|
if (ch == '.') lastDot = index;
|
|
15160
15333
|
ident += ch;
|
|
@@ -15168,7 +15341,7 @@ function lex(text, csp){
|
|
|
15168
15341
|
if (lastDot) {
|
|
15169
15342
|
peekIndex = index;
|
|
15170
15343
|
while(peekIndex < text.length) {
|
|
15171
|
-
|
|
15344
|
+
ch = text.charAt(peekIndex);
|
|
15172
15345
|
if (ch == '(') {
|
|
15173
15346
|
methodName = ident.substr(lastDot - start + 1);
|
|
15174
15347
|
ident = ident.substr(0, lastDot - start);
|
|
@@ -15421,8 +15594,8 @@ function parser(text, json, $filter, csp){
|
|
|
15421
15594
|
text.substring(0, token.index) + "] can not be assigned to", token);
|
|
15422
15595
|
}
|
|
15423
15596
|
right = logicalOR();
|
|
15424
|
-
return function(
|
|
15425
|
-
return left.assign(
|
|
15597
|
+
return function(scope, locals){
|
|
15598
|
+
return left.assign(scope, right(scope, locals), locals);
|
|
15426
15599
|
};
|
|
15427
15600
|
} else {
|
|
15428
15601
|
return left;
|
|
@@ -15539,12 +15712,12 @@ function parser(text, json, $filter, csp){
|
|
|
15539
15712
|
var field = expect().text;
|
|
15540
15713
|
var getter = getterFn(field, csp);
|
|
15541
15714
|
return extend(
|
|
15542
|
-
function(
|
|
15543
|
-
return getter(object(
|
|
15715
|
+
function(scope, locals, self) {
|
|
15716
|
+
return getter(self || object(scope, locals), locals);
|
|
15544
15717
|
},
|
|
15545
15718
|
{
|
|
15546
|
-
assign:function(
|
|
15547
|
-
return setter(object(
|
|
15719
|
+
assign:function(scope, value, locals) {
|
|
15720
|
+
return setter(object(scope, locals), field, value);
|
|
15548
15721
|
}
|
|
15549
15722
|
}
|
|
15550
15723
|
);
|
|
@@ -15585,14 +15758,14 @@ function parser(text, json, $filter, csp){
|
|
|
15585
15758
|
} while (expect(','));
|
|
15586
15759
|
}
|
|
15587
15760
|
consume(')');
|
|
15588
|
-
return function(
|
|
15761
|
+
return function(scope, locals){
|
|
15589
15762
|
var args = [],
|
|
15590
|
-
context = contextGetter ? contextGetter(
|
|
15763
|
+
context = contextGetter ? contextGetter(scope, locals) : scope;
|
|
15591
15764
|
|
|
15592
15765
|
for ( var i = 0; i < argsFn.length; i++) {
|
|
15593
|
-
args.push(argsFn[i](
|
|
15766
|
+
args.push(argsFn[i](scope, locals));
|
|
15594
15767
|
}
|
|
15595
|
-
var fnPtr = fn(
|
|
15768
|
+
var fnPtr = fn(scope, locals, context) || noop;
|
|
15596
15769
|
// IE stupidity!
|
|
15597
15770
|
return fnPtr.apply
|
|
15598
15771
|
? fnPtr.apply(context, args)
|
|
@@ -15634,8 +15807,7 @@ function parser(text, json, $filter, csp){
|
|
|
15634
15807
|
var object = {};
|
|
15635
15808
|
for ( var i = 0; i < keyValues.length; i++) {
|
|
15636
15809
|
var keyValue = keyValues[i];
|
|
15637
|
-
|
|
15638
|
-
object[keyValue.key] = value;
|
|
15810
|
+
object[keyValue.key] = keyValue.value(self, locals);
|
|
15639
15811
|
}
|
|
15640
15812
|
return object;
|
|
15641
15813
|
};
|
|
@@ -15757,7 +15929,7 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4) {
|
|
|
15757
15929
|
}
|
|
15758
15930
|
return pathVal;
|
|
15759
15931
|
};
|
|
15760
|
-
}
|
|
15932
|
+
}
|
|
15761
15933
|
|
|
15762
15934
|
function getterFn(path, csp) {
|
|
15763
15935
|
if (getterFnCache.hasOwnProperty(path)) {
|
|
@@ -15772,7 +15944,7 @@ function getterFn(path, csp) {
|
|
|
15772
15944
|
fn = (pathKeysLength < 6)
|
|
15773
15945
|
? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4])
|
|
15774
15946
|
: function(scope, locals) {
|
|
15775
|
-
var i = 0, val
|
|
15947
|
+
var i = 0, val;
|
|
15776
15948
|
do {
|
|
15777
15949
|
val = cspSafeGetterFn(
|
|
15778
15950
|
pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++]
|
|
@@ -15837,9 +16009,10 @@ function getterFn(path, csp) {
|
|
|
15837
16009
|
* @param {string} expression String expression to compile.
|
|
15838
16010
|
* @returns {function(context, locals)} a function which represents the compiled expression:
|
|
15839
16011
|
*
|
|
15840
|
-
* * `context
|
|
15841
|
-
* against (
|
|
15842
|
-
* * `locals
|
|
16012
|
+
* * `context` – `{object}` – an object against which any expressions embedded in the strings
|
|
16013
|
+
* are evaluated against (tipically a scope object).
|
|
16014
|
+
* * `locals` – `{object=}` – local variables context object, useful for overriding values in
|
|
16015
|
+
* `context`.
|
|
15843
16016
|
*
|
|
15844
16017
|
* The return function also has an `assign` property, if the expression is assignable, which
|
|
15845
16018
|
* allows one to set values to expressions.
|
|
@@ -15875,8 +16048,8 @@ function $ParseProvider() {
|
|
|
15875
16048
|
* interface for interacting with an object that represents the result of an action that is
|
|
15876
16049
|
* performed asynchronously, and may or may not be finished at any given point in time.
|
|
15877
16050
|
*
|
|
15878
|
-
* From the perspective of dealing with error handling, deferred and promise
|
|
15879
|
-
* asynchronous
|
|
16051
|
+
* From the perspective of dealing with error handling, deferred and promise APIs are to
|
|
16052
|
+
* asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
|
|
15880
16053
|
*
|
|
15881
16054
|
* <pre>
|
|
15882
16055
|
* // for the purpose of this example let's assume that variables `$q` and `scope` are
|
|
@@ -15910,7 +16083,7 @@ function $ParseProvider() {
|
|
|
15910
16083
|
*
|
|
15911
16084
|
* At first it might not be obvious why this extra complexity is worth the trouble. The payoff
|
|
15912
16085
|
* comes in the way of
|
|
15913
|
-
* [guarantees that promise and deferred
|
|
16086
|
+
* [guarantees that promise and deferred APIs make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
|
|
15914
16087
|
*
|
|
15915
16088
|
* Additionally the promise api allows for composition that is very hard to do with the
|
|
15916
16089
|
* traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
|
|
@@ -15922,7 +16095,7 @@ function $ParseProvider() {
|
|
|
15922
16095
|
*
|
|
15923
16096
|
* A new instance of deferred is constructed by calling `$q.defer()`.
|
|
15924
16097
|
*
|
|
15925
|
-
* The purpose of the deferred object is to expose the associated Promise instance as well as
|
|
16098
|
+
* The purpose of the deferred object is to expose the associated Promise instance as well as APIs
|
|
15926
16099
|
* that can be used for signaling the successful or unsuccessful completion of the task.
|
|
15927
16100
|
*
|
|
15928
16101
|
* **Methods**
|
|
@@ -15965,7 +16138,7 @@ function $ParseProvider() {
|
|
|
15965
16138
|
* return result + 1;
|
|
15966
16139
|
* });
|
|
15967
16140
|
*
|
|
15968
|
-
* // promiseB will be resolved immediately after promiseA is resolved and
|
|
16141
|
+
* // promiseB will be resolved immediately after promiseA is resolved and its value will be
|
|
15969
16142
|
* // the result of promiseA incremented by 1
|
|
15970
16143
|
* </pre>
|
|
15971
16144
|
*
|
|
@@ -15984,8 +16157,32 @@ function $ParseProvider() {
|
|
|
15984
16157
|
* models and avoiding unnecessary browser repaints, which would result in flickering UI.
|
|
15985
16158
|
* - $q promises are recognized by the templating engine in angular, which means that in templates
|
|
15986
16159
|
* you can treat promises attached to a scope as if they were the resulting values.
|
|
15987
|
-
* - Q has many more features
|
|
16160
|
+
* - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
|
|
15988
16161
|
* all the important functionality needed for common async tasks.
|
|
16162
|
+
*
|
|
16163
|
+
* # Testing
|
|
16164
|
+
*
|
|
16165
|
+
* <pre>
|
|
16166
|
+
* it('should simulate promise', inject(function($q, $rootScope) {
|
|
16167
|
+
* var deferred = $q.defer();
|
|
16168
|
+
* var promise = deferred.promise;
|
|
16169
|
+
* var resolvedValue;
|
|
16170
|
+
*
|
|
16171
|
+
* promise.then(function(value) { resolvedValue = value; });
|
|
16172
|
+
* expect(resolvedValue).toBeUndefined();
|
|
16173
|
+
*
|
|
16174
|
+
* // Simulate resolving of promise
|
|
16175
|
+
* deferred.resolve(123);
|
|
16176
|
+
* // Note that the 'then' function does not get called synchronously.
|
|
16177
|
+
* // This is because we want the promise API to always be async, whether or not
|
|
16178
|
+
* // it got called synchronously or asynchronously.
|
|
16179
|
+
* expect(resolvedValue).toBeUndefined();
|
|
16180
|
+
*
|
|
16181
|
+
* // Propagate promise resolution to 'then' functions using $apply().
|
|
16182
|
+
* $rootScope.$apply();
|
|
16183
|
+
* expect(resolvedValue).toEqual(123);
|
|
16184
|
+
* });
|
|
16185
|
+
* </pre>
|
|
15989
16186
|
*/
|
|
15990
16187
|
function $QProvider() {
|
|
15991
16188
|
|
|
@@ -16151,14 +16348,11 @@ function qFactory(nextTick, exceptionHandler) {
|
|
|
16151
16348
|
* @methodOf ng.$q
|
|
16152
16349
|
* @description
|
|
16153
16350
|
* Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
|
|
16154
|
-
* This is useful when you are dealing with
|
|
16351
|
+
* This is useful when you are dealing with an object that might or might not be a promise, or if
|
|
16155
16352
|
* the promise comes from a source that can't be trusted.
|
|
16156
16353
|
*
|
|
16157
16354
|
* @param {*} value Value or a promise
|
|
16158
|
-
* @returns {Promise} Returns a
|
|
16159
|
-
* each value coresponding to the promise at the same index in the `promises` array. If any of
|
|
16160
|
-
* the promises is resolved with a rejection, this resulting promise will be resolved with the
|
|
16161
|
-
* same rejection.
|
|
16355
|
+
* @returns {Promise} Returns a promise of the passed value or promise
|
|
16162
16356
|
*/
|
|
16163
16357
|
var when = function(value, callback, errback) {
|
|
16164
16358
|
var result = defer(),
|
|
@@ -16218,7 +16412,7 @@ function qFactory(nextTick, exceptionHandler) {
|
|
|
16218
16412
|
*
|
|
16219
16413
|
* @param {Array.<Promise>} promises An array of promises.
|
|
16220
16414
|
* @returns {Promise} Returns a single promise that will be resolved with an array of values,
|
|
16221
|
-
* each value
|
|
16415
|
+
* each value corresponding to the promise at the same index in the `promises` array. If any of
|
|
16222
16416
|
* the promises is resolved with a rejection, this resulting promise will be resolved with the
|
|
16223
16417
|
* same rejection.
|
|
16224
16418
|
*/
|
|
@@ -16272,8 +16466,13 @@ function $RouteProvider(){
|
|
|
16272
16466
|
*
|
|
16273
16467
|
* @param {string} path Route path (matched against `$location.path`). If `$location.path`
|
|
16274
16468
|
* contains redundant trailing slash or is missing one, the route will still match and the
|
|
16275
|
-
* `$location.path` will be updated to add or drop the trailing slash to
|
|
16469
|
+
* `$location.path` will be updated to add or drop the trailing slash to exactly match the
|
|
16276
16470
|
* route definition.
|
|
16471
|
+
*
|
|
16472
|
+
* `path` can contain named groups starting with a colon (`:name`). All characters up to the
|
|
16473
|
+
* next slash are matched and stored in `$routeParams` under the given `name` when the route
|
|
16474
|
+
* matches.
|
|
16475
|
+
*
|
|
16277
16476
|
* @param {Object} route Mapping information to be assigned to `$route.current` on route
|
|
16278
16477
|
* match.
|
|
16279
16478
|
*
|
|
@@ -16510,8 +16709,9 @@ function $RouteProvider(){
|
|
|
16510
16709
|
* {@link ng.directive:ngView ngView} listens for the directive
|
|
16511
16710
|
* to instantiate the controller and render the view.
|
|
16512
16711
|
*
|
|
16712
|
+
* @param {Object} angularEvent Synthetic event object.
|
|
16513
16713
|
* @param {Route} current Current route information.
|
|
16514
|
-
* @param {Route} previous Previous route information.
|
|
16714
|
+
* @param {Route|Undefined} previous Previous route information, or undefined if current is first route entered.
|
|
16515
16715
|
*/
|
|
16516
16716
|
|
|
16517
16717
|
/**
|
|
@@ -16538,8 +16738,7 @@ function $RouteProvider(){
|
|
|
16538
16738
|
* instance of the Controller.
|
|
16539
16739
|
*/
|
|
16540
16740
|
|
|
16541
|
-
var
|
|
16542
|
-
forceReload = false,
|
|
16741
|
+
var forceReload = false,
|
|
16543
16742
|
$route = {
|
|
16544
16743
|
routes: routes,
|
|
16545
16744
|
|
|
@@ -16567,21 +16766,36 @@ function $RouteProvider(){
|
|
|
16567
16766
|
|
|
16568
16767
|
/////////////////////////////////////////////////////
|
|
16569
16768
|
|
|
16769
|
+
/**
|
|
16770
|
+
* @param on {string} current url
|
|
16771
|
+
* @param when {string} route when template to match the url against
|
|
16772
|
+
* @return {?Object}
|
|
16773
|
+
*/
|
|
16570
16774
|
function switchRouteMatcher(on, when) {
|
|
16571
16775
|
// TODO(i): this code is convoluted and inefficient, we should construct the route matching
|
|
16572
16776
|
// regex only once and then reuse it
|
|
16573
|
-
|
|
16777
|
+
|
|
16778
|
+
// Escape regexp special characters.
|
|
16779
|
+
when = '^' + when.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") + '$';
|
|
16780
|
+
var regex = '',
|
|
16574
16781
|
params = [],
|
|
16575
16782
|
dst = {};
|
|
16576
|
-
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
|
|
16582
|
-
|
|
16583
|
-
|
|
16584
|
-
|
|
16783
|
+
|
|
16784
|
+
var re = /:(\w+)/g,
|
|
16785
|
+
paramMatch,
|
|
16786
|
+
lastMatchedIndex = 0;
|
|
16787
|
+
|
|
16788
|
+
while ((paramMatch = re.exec(when)) !== null) {
|
|
16789
|
+
// Find each :param in `when` and replace it with a capturing group.
|
|
16790
|
+
// Append all other sections of when unchanged.
|
|
16791
|
+
regex += when.slice(lastMatchedIndex, paramMatch.index);
|
|
16792
|
+
regex += '([^\\/]*)';
|
|
16793
|
+
params.push(paramMatch[1]);
|
|
16794
|
+
lastMatchedIndex = re.lastIndex;
|
|
16795
|
+
}
|
|
16796
|
+
// Append trailing path part.
|
|
16797
|
+
regex += when.substr(lastMatchedIndex);
|
|
16798
|
+
|
|
16585
16799
|
var match = on.match(new RegExp(regex));
|
|
16586
16800
|
if (match) {
|
|
16587
16801
|
forEach(params, function(name, index) {
|
|
@@ -16595,7 +16809,7 @@ function $RouteProvider(){
|
|
|
16595
16809
|
var next = parseRoute(),
|
|
16596
16810
|
last = $route.current;
|
|
16597
16811
|
|
|
16598
|
-
if (next && last && next
|
|
16812
|
+
if (next && last && next.$$route === last.$$route
|
|
16599
16813
|
&& equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {
|
|
16600
16814
|
last.params = next.params;
|
|
16601
16815
|
copy(last.params, $routeParams);
|
|
@@ -16670,11 +16884,11 @@ function $RouteProvider(){
|
|
|
16670
16884
|
// Match a route
|
|
16671
16885
|
var params, match;
|
|
16672
16886
|
forEach(routes, function(route, path) {
|
|
16673
|
-
if (!match && (params =
|
|
16887
|
+
if (!match && (params = switchRouteMatcher($location.path(), path))) {
|
|
16674
16888
|
match = inherit(route, {
|
|
16675
16889
|
params: extend({}, $location.search(), params),
|
|
16676
16890
|
pathParams: params});
|
|
16677
|
-
match
|
|
16891
|
+
match.$$route = route;
|
|
16678
16892
|
}
|
|
16679
16893
|
});
|
|
16680
16894
|
// No route matched; fallback to "otherwise" route
|
|
@@ -16734,22 +16948,22 @@ function $RouteParamsProvider() {
|
|
|
16734
16948
|
/**
|
|
16735
16949
|
* DESIGN NOTES
|
|
16736
16950
|
*
|
|
16737
|
-
* The design decisions behind the scope
|
|
16951
|
+
* The design decisions behind the scope are heavily favored for speed and memory consumption.
|
|
16738
16952
|
*
|
|
16739
16953
|
* The typical use of scope is to watch the expressions, which most of the time return the same
|
|
16740
16954
|
* value as last time so we optimize the operation.
|
|
16741
16955
|
*
|
|
16742
|
-
* Closures construction is expensive
|
|
16743
|
-
* -
|
|
16956
|
+
* Closures construction is expensive in terms of speed as well as memory:
|
|
16957
|
+
* - No closures, instead use prototypical inheritance for API
|
|
16744
16958
|
* - Internal state needs to be stored on scope directly, which means that private state is
|
|
16745
16959
|
* exposed as $$____ properties
|
|
16746
16960
|
*
|
|
16747
16961
|
* Loop operations are optimized by using while(count--) { ... }
|
|
16748
16962
|
* - this means that in order to keep the same order of execution as addition we have to add
|
|
16749
|
-
* items to the array at the
|
|
16963
|
+
* items to the array at the beginning (shift) instead of at the end (push)
|
|
16750
16964
|
*
|
|
16751
16965
|
* Child scopes are created and removed often
|
|
16752
|
-
* - Using array would be slow since inserts in
|
|
16966
|
+
* - Using an array would be slow since inserts in middle are expensive so we use linked list
|
|
16753
16967
|
*
|
|
16754
16968
|
* There are few watches then a lot of observers. This is why you don't want the observer to be
|
|
16755
16969
|
* implemented in the same way as watch. Watch requires return of initialization function which
|
|
@@ -16771,7 +16985,7 @@ function $RouteParamsProvider() {
|
|
|
16771
16985
|
* @methodOf ng.$rootScopeProvider
|
|
16772
16986
|
* @description
|
|
16773
16987
|
*
|
|
16774
|
-
* Sets the number of digest
|
|
16988
|
+
* Sets the number of digest iterations the scope should attempt to execute before giving up and
|
|
16775
16989
|
* assuming that the model is unstable.
|
|
16776
16990
|
*
|
|
16777
16991
|
* The current default is 10 iterations.
|
|
@@ -16822,7 +17036,7 @@ function $RootScopeProvider(){
|
|
|
16822
17036
|
expect(scope.greeting).toEqual(undefined);
|
|
16823
17037
|
|
|
16824
17038
|
scope.$watch('name', function() {
|
|
16825
|
-
|
|
17039
|
+
scope.greeting = scope.salutation + ' ' + scope.name + '!';
|
|
16826
17040
|
}); // initialize the watch
|
|
16827
17041
|
|
|
16828
17042
|
expect(scope.greeting).toEqual(undefined);
|
|
@@ -16865,8 +17079,10 @@ function $RootScopeProvider(){
|
|
|
16865
17079
|
this.$$nextSibling = this.$$prevSibling =
|
|
16866
17080
|
this.$$childHead = this.$$childTail = null;
|
|
16867
17081
|
this['this'] = this.$root = this;
|
|
17082
|
+
this.$$destroyed = false;
|
|
16868
17083
|
this.$$asyncQueue = [];
|
|
16869
17084
|
this.$$listeners = {};
|
|
17085
|
+
this.$$isolateBindings = {};
|
|
16870
17086
|
}
|
|
16871
17087
|
|
|
16872
17088
|
/**
|
|
@@ -16983,7 +17199,7 @@ function $RootScopeProvider(){
|
|
|
16983
17199
|
scope.counter = 0;
|
|
16984
17200
|
|
|
16985
17201
|
expect(scope.counter).toEqual(0);
|
|
16986
|
-
scope.$watch('name', function(newValue, oldValue) { counter = counter + 1; });
|
|
17202
|
+
scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });
|
|
16987
17203
|
expect(scope.counter).toEqual(0);
|
|
16988
17204
|
|
|
16989
17205
|
scope.$digest();
|
|
@@ -17049,7 +17265,7 @@ function $RootScopeProvider(){
|
|
|
17049
17265
|
* @function
|
|
17050
17266
|
*
|
|
17051
17267
|
* @description
|
|
17052
|
-
*
|
|
17268
|
+
* Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children.
|
|
17053
17269
|
* Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the
|
|
17054
17270
|
* `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are
|
|
17055
17271
|
* firing. This means that it is possible to get into an infinite loop. This function will throw
|
|
@@ -17076,7 +17292,7 @@ function $RootScopeProvider(){
|
|
|
17076
17292
|
|
|
17077
17293
|
expect(scope.counter).toEqual(0);
|
|
17078
17294
|
scope.$watch('name', function(newValue, oldValue) {
|
|
17079
|
-
counter = counter + 1;
|
|
17295
|
+
scope.counter = scope.counter + 1;
|
|
17080
17296
|
});
|
|
17081
17297
|
expect(scope.counter).toEqual(0);
|
|
17082
17298
|
|
|
@@ -17198,10 +17414,12 @@ function $RootScopeProvider(){
|
|
|
17198
17414
|
* perform any necessary cleanup.
|
|
17199
17415
|
*/
|
|
17200
17416
|
$destroy: function() {
|
|
17201
|
-
|
|
17417
|
+
// we can't destroy the root scope or a scope that has been already destroyed
|
|
17418
|
+
if ($rootScope == this || this.$$destroyed) return;
|
|
17202
17419
|
var parent = this.$parent;
|
|
17203
17420
|
|
|
17204
17421
|
this.$broadcast('$destroy');
|
|
17422
|
+
this.$$destroyed = true;
|
|
17205
17423
|
|
|
17206
17424
|
if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
|
|
17207
17425
|
if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
|
|
@@ -17346,10 +17564,6 @@ function $RootScopeProvider(){
|
|
|
17346
17564
|
* Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of
|
|
17347
17565
|
* event life cycle.
|
|
17348
17566
|
*
|
|
17349
|
-
* @param {string} name Event name to listen on.
|
|
17350
|
-
* @param {function(event)} listener Function to call when the event is emitted.
|
|
17351
|
-
* @returns {function()} Returns a deregistration function for this listener.
|
|
17352
|
-
*
|
|
17353
17567
|
* The event listener function format is: `function(event, args...)`. The `event` object
|
|
17354
17568
|
* passed into the listener has the following attributes:
|
|
17355
17569
|
*
|
|
@@ -17360,6 +17574,10 @@ function $RootScopeProvider(){
|
|
|
17360
17574
|
* propagation (available only for events that were `$emit`-ed).
|
|
17361
17575
|
* - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.
|
|
17362
17576
|
* - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
|
|
17577
|
+
*
|
|
17578
|
+
* @param {string} name Event name to listen on.
|
|
17579
|
+
* @param {function(event, args...)} listener Function to call when the event is emitted.
|
|
17580
|
+
* @returns {function()} Returns a deregistration function for this listener.
|
|
17363
17581
|
*/
|
|
17364
17582
|
$on: function(name, listener) {
|
|
17365
17583
|
var namedListeners = this.$$listeners[name];
|
|
@@ -17389,7 +17607,7 @@ function $RootScopeProvider(){
|
|
|
17389
17607
|
* Afterwards, the event traverses upwards toward the root scope and calls all registered
|
|
17390
17608
|
* listeners along the way. The event will stop propagating if one of the listeners cancels it.
|
|
17391
17609
|
*
|
|
17392
|
-
* Any exception
|
|
17610
|
+
* Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
|
|
17393
17611
|
* onto the {@link ng.$exceptionHandler $exceptionHandler} service.
|
|
17394
17612
|
*
|
|
17395
17613
|
* @param {string} name Event name to emit.
|
|
@@ -17458,7 +17676,7 @@ function $RootScopeProvider(){
|
|
|
17458
17676
|
* Any exception emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed
|
|
17459
17677
|
* onto the {@link ng.$exceptionHandler $exceptionHandler} service.
|
|
17460
17678
|
*
|
|
17461
|
-
* @param {string} name Event name to
|
|
17679
|
+
* @param {string} name Event name to broadcast.
|
|
17462
17680
|
* @param {...*} args Optional set of arguments which will be passed onto the event listeners.
|
|
17463
17681
|
* @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
|
|
17464
17682
|
*/
|
|
@@ -17537,7 +17755,7 @@ function $RootScopeProvider(){
|
|
|
17537
17755
|
|
|
17538
17756
|
/**
|
|
17539
17757
|
* function used as an initial value for watchers.
|
|
17540
|
-
* because it's
|
|
17758
|
+
* because it's unique we can easily tell it apart from other values
|
|
17541
17759
|
*/
|
|
17542
17760
|
function initWatchVal() {}
|
|
17543
17761
|
}];
|
|
@@ -17604,10 +17822,23 @@ function $SnifferProvider() {
|
|
|
17604
17822
|
* @example
|
|
17605
17823
|
<doc:example>
|
|
17606
17824
|
<doc:source>
|
|
17607
|
-
<
|
|
17608
|
-
|
|
17825
|
+
<script>
|
|
17826
|
+
function Ctrl($scope, $window) {
|
|
17827
|
+
$scope.$window = $window;
|
|
17828
|
+
$scope.greeting = 'Hello, World!';
|
|
17829
|
+
}
|
|
17830
|
+
</script>
|
|
17831
|
+
<div ng-controller="Ctrl">
|
|
17832
|
+
<input type="text" ng-model="greeting" />
|
|
17833
|
+
<button ng-click="$window.alert(greeting)">ALERT</button>
|
|
17834
|
+
</div>
|
|
17609
17835
|
</doc:source>
|
|
17610
17836
|
<doc:scenario>
|
|
17837
|
+
it('should display the greeting in the input box', function() {
|
|
17838
|
+
input('greeting').enter('Hello, E2E Tests');
|
|
17839
|
+
// If we click the button it will block the test runner
|
|
17840
|
+
// element(':button').click();
|
|
17841
|
+
});
|
|
17611
17842
|
</doc:scenario>
|
|
17612
17843
|
</doc:example>
|
|
17613
17844
|
*/
|
|
@@ -17751,7 +17982,7 @@ function $HttpProvider() {
|
|
|
17751
17982
|
/**
|
|
17752
17983
|
* @ngdoc function
|
|
17753
17984
|
* @name ng.$http
|
|
17754
|
-
* @requires $
|
|
17985
|
+
* @requires $httpBackend
|
|
17755
17986
|
* @requires $browser
|
|
17756
17987
|
* @requires $cacheFactory
|
|
17757
17988
|
* @requires $rootScope
|
|
@@ -17760,7 +17991,7 @@ function $HttpProvider() {
|
|
|
17760
17991
|
*
|
|
17761
17992
|
* @description
|
|
17762
17993
|
* The `$http` service is a core Angular service that facilitates communication with the remote
|
|
17763
|
-
* HTTP servers via browser's {@link https://developer.mozilla.org/en/xmlhttprequest
|
|
17994
|
+
* HTTP servers via the browser's {@link https://developer.mozilla.org/en/xmlhttprequest
|
|
17764
17995
|
* XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.
|
|
17765
17996
|
*
|
|
17766
17997
|
* For unit testing applications that use `$http` service, see
|
|
@@ -17770,13 +18001,13 @@ function $HttpProvider() {
|
|
|
17770
18001
|
* $resource} service.
|
|
17771
18002
|
*
|
|
17772
18003
|
* The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
|
|
17773
|
-
* the $q service. While for simple usage
|
|
17774
|
-
* it is important to familiarize yourself with these
|
|
18004
|
+
* the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
|
|
18005
|
+
* it is important to familiarize yourself with these APIs and the guarantees they provide.
|
|
17775
18006
|
*
|
|
17776
18007
|
*
|
|
17777
18008
|
* # General usage
|
|
17778
18009
|
* The `$http` service is a function which takes a single argument — a configuration object —
|
|
17779
|
-
* that is used to generate an
|
|
18010
|
+
* that is used to generate an HTTP request and returns a {@link ng.$q promise}
|
|
17780
18011
|
* with two $http specific methods: `success` and `error`.
|
|
17781
18012
|
*
|
|
17782
18013
|
* <pre>
|
|
@@ -17787,22 +18018,25 @@ function $HttpProvider() {
|
|
|
17787
18018
|
* }).
|
|
17788
18019
|
* error(function(data, status, headers, config) {
|
|
17789
18020
|
* // called asynchronously if an error occurs
|
|
17790
|
-
* // or server returns response with status
|
|
17791
|
-
* // code outside of the <200, 400) range
|
|
18021
|
+
* // or server returns response with an error status.
|
|
17792
18022
|
* });
|
|
17793
18023
|
* </pre>
|
|
17794
18024
|
*
|
|
17795
|
-
* Since the returned value of calling the $http function is a
|
|
18025
|
+
* Since the returned value of calling the $http function is a `promise`, you can also use
|
|
17796
18026
|
* the `then` method to register callbacks, and these callbacks will receive a single argument –
|
|
17797
|
-
* an object representing the response. See the
|
|
18027
|
+
* an object representing the response. See the API signature and type info below for more
|
|
17798
18028
|
* details.
|
|
17799
18029
|
*
|
|
18030
|
+
* A response status code between 200 and 299 is considered a success status and
|
|
18031
|
+
* will result in the success callback being called. Note that if the response is a redirect,
|
|
18032
|
+
* XMLHttpRequest will transparently follow it, meaning that the error callback will not be
|
|
18033
|
+
* called for such responses.
|
|
17800
18034
|
*
|
|
17801
18035
|
* # Shortcut methods
|
|
17802
18036
|
*
|
|
17803
|
-
* Since all
|
|
17804
|
-
* POST
|
|
17805
|
-
* were created
|
|
18037
|
+
* Since all invocations of the $http service require passing in an HTTP method and URL, and
|
|
18038
|
+
* POST/PUT requests require request data to be provided as well, shortcut methods
|
|
18039
|
+
* were created:
|
|
17806
18040
|
*
|
|
17807
18041
|
* <pre>
|
|
17808
18042
|
* $http.get('/someUrl').success(successCallback);
|
|
@@ -17821,25 +18055,25 @@ function $HttpProvider() {
|
|
|
17821
18055
|
*
|
|
17822
18056
|
* # Setting HTTP Headers
|
|
17823
18057
|
*
|
|
17824
|
-
* The $http service will automatically add certain
|
|
18058
|
+
* The $http service will automatically add certain HTTP headers to all requests. These defaults
|
|
17825
18059
|
* can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
|
|
17826
18060
|
* object, which currently contains this default configuration:
|
|
17827
18061
|
*
|
|
17828
18062
|
* - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
|
|
17829
18063
|
* - `Accept: application/json, text/plain, * / *`
|
|
17830
18064
|
* - `X-Requested-With: XMLHttpRequest`
|
|
17831
|
-
* - `$httpProvider.defaults.headers.post`: (header defaults for
|
|
18065
|
+
* - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
|
|
17832
18066
|
* - `Content-Type: application/json`
|
|
17833
|
-
* - `$httpProvider.defaults.headers.put` (header defaults for
|
|
18067
|
+
* - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
|
|
17834
18068
|
* - `Content-Type: application/json`
|
|
17835
18069
|
*
|
|
17836
|
-
* To add or overwrite these defaults, simply add or remove a property from
|
|
18070
|
+
* To add or overwrite these defaults, simply add or remove a property from these configuration
|
|
17837
18071
|
* objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
|
|
17838
|
-
* with
|
|
18072
|
+
* with the lowercased HTTP method name as the key, e.g.
|
|
17839
18073
|
* `$httpProvider.defaults.headers.get['My-Header']='value'`.
|
|
17840
18074
|
*
|
|
17841
|
-
* Additionally, the defaults can be set at runtime via the `$http.defaults` object in
|
|
17842
|
-
*
|
|
18075
|
+
* Additionally, the defaults can be set at runtime via the `$http.defaults` object in the same
|
|
18076
|
+
* fashion.
|
|
17843
18077
|
*
|
|
17844
18078
|
*
|
|
17845
18079
|
* # Transforming Requests and Responses
|
|
@@ -17849,32 +18083,36 @@ function $HttpProvider() {
|
|
|
17849
18083
|
*
|
|
17850
18084
|
* Request transformations:
|
|
17851
18085
|
*
|
|
17852
|
-
* -
|
|
18086
|
+
* - If the `data` property of the request configuration object contains an object, serialize it into
|
|
17853
18087
|
* JSON format.
|
|
17854
18088
|
*
|
|
17855
18089
|
* Response transformations:
|
|
17856
18090
|
*
|
|
17857
|
-
* -
|
|
17858
|
-
* -
|
|
18091
|
+
* - If XSRF prefix is detected, strip it (see Security Considerations section below).
|
|
18092
|
+
* - If JSON response is detected, deserialize it using a JSON parser.
|
|
18093
|
+
*
|
|
18094
|
+
* To globally augment or override the default transforms, modify the `$httpProvider.defaults.transformRequest` and
|
|
18095
|
+
* `$httpProvider.defaults.transformResponse` properties. These properties are by default an
|
|
18096
|
+
* array of transform functions, which allows you to `push` or `unshift` a new transformation function into the
|
|
18097
|
+
* transformation chain. You can also decide to completely override any default transformations by assigning your
|
|
18098
|
+
* transformation functions to these properties directly without the array wrapper.
|
|
17859
18099
|
*
|
|
17860
|
-
*
|
|
17861
|
-
*
|
|
17862
|
-
* transforms, override the `$httpProvider.defaults.transformRequest` and
|
|
17863
|
-
* `$httpProvider.defaults.transformResponse` properties of the `$httpProvider`.
|
|
18100
|
+
* Similarly, to locally override the request/response transforms, augment the `transformRequest` and/or
|
|
18101
|
+
* `transformResponse` properties of the configuration object passed into `$http`.
|
|
17864
18102
|
*
|
|
17865
18103
|
*
|
|
17866
18104
|
* # Caching
|
|
17867
18105
|
*
|
|
17868
|
-
* To enable caching set the configuration property `cache` to `true`. When the cache is
|
|
18106
|
+
* To enable caching, set the configuration property `cache` to `true`. When the cache is
|
|
17869
18107
|
* enabled, `$http` stores the response from the server in local cache. Next time the
|
|
17870
18108
|
* response is served from the cache without sending a request to the server.
|
|
17871
18109
|
*
|
|
17872
18110
|
* Note that even if the response is served from cache, delivery of the data is asynchronous in
|
|
17873
18111
|
* the same way that real requests are.
|
|
17874
18112
|
*
|
|
17875
|
-
* If there are multiple GET requests for the same
|
|
18113
|
+
* If there are multiple GET requests for the same URL that should be cached using the same
|
|
17876
18114
|
* cache, but the cache is not populated yet, only one request to the server will be made and
|
|
17877
|
-
* the remaining requests will be fulfilled using the response
|
|
18115
|
+
* the remaining requests will be fulfilled using the response from the first request.
|
|
17878
18116
|
*
|
|
17879
18117
|
*
|
|
17880
18118
|
* # Response interceptors
|
|
@@ -17926,7 +18164,7 @@ function $HttpProvider() {
|
|
|
17926
18164
|
* When designing web applications, consider security threats from:
|
|
17927
18165
|
*
|
|
17928
18166
|
* - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
|
|
17929
|
-
* JSON
|
|
18167
|
+
* JSON vulnerability}
|
|
17930
18168
|
* - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}
|
|
17931
18169
|
*
|
|
17932
18170
|
* Both server and the client must cooperate in order to eliminate these threats. Angular comes
|
|
@@ -17936,8 +18174,8 @@ function $HttpProvider() {
|
|
|
17936
18174
|
* ## JSON Vulnerability Protection
|
|
17937
18175
|
*
|
|
17938
18176
|
* A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
|
|
17939
|
-
* JSON
|
|
17940
|
-
* {@link http://en.wikipedia.org/wiki/
|
|
18177
|
+
* JSON vulnerability} allows third party website to turn your JSON resource URL into
|
|
18178
|
+
* {@link http://en.wikipedia.org/wiki/JSONP JSONP} request under some conditions. To
|
|
17941
18179
|
* counter this your server can prefix all JSON requests with following string `")]}',\n"`.
|
|
17942
18180
|
* Angular will automatically strip the prefix before processing it as JSON.
|
|
17943
18181
|
*
|
|
@@ -17958,19 +18196,19 @@ function $HttpProvider() {
|
|
|
17958
18196
|
* ## Cross Site Request Forgery (XSRF) Protection
|
|
17959
18197
|
*
|
|
17960
18198
|
* {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which
|
|
17961
|
-
* an unauthorized site can gain your user's private data. Angular provides
|
|
18199
|
+
* an unauthorized site can gain your user's private data. Angular provides a mechanism
|
|
17962
18200
|
* to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
|
|
17963
18201
|
* called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that
|
|
17964
18202
|
* runs on your domain could read the cookie, your server can be assured that the XHR came from
|
|
17965
18203
|
* JavaScript running on your domain.
|
|
17966
18204
|
*
|
|
17967
18205
|
* To take advantage of this, your server needs to set a token in a JavaScript readable session
|
|
17968
|
-
* cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent
|
|
18206
|
+
* cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
|
|
17969
18207
|
* server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
|
|
17970
|
-
* that only JavaScript running on your domain could have
|
|
17971
|
-
* unique for each user and must be verifiable by the server (to prevent the JavaScript making
|
|
18208
|
+
* that only JavaScript running on your domain could have sent the request. The token must be
|
|
18209
|
+
* unique for each user and must be verifiable by the server (to prevent the JavaScript from making
|
|
17972
18210
|
* up its own tokens). We recommend that the token is a digest of your site's authentication
|
|
17973
|
-
* cookie with {@link
|
|
18211
|
+
* cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt} for added security.
|
|
17974
18212
|
*
|
|
17975
18213
|
*
|
|
17976
18214
|
* @param {object} config Object describing the request to be made and how it should be
|
|
@@ -18148,7 +18386,7 @@ function $HttpProvider() {
|
|
|
18148
18386
|
* @methodOf ng.$http
|
|
18149
18387
|
*
|
|
18150
18388
|
* @description
|
|
18151
|
-
* Shortcut method to perform `GET` request
|
|
18389
|
+
* Shortcut method to perform `GET` request.
|
|
18152
18390
|
*
|
|
18153
18391
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
|
18154
18392
|
* @param {Object=} config Optional configuration object
|
|
@@ -18161,7 +18399,7 @@ function $HttpProvider() {
|
|
|
18161
18399
|
* @methodOf ng.$http
|
|
18162
18400
|
*
|
|
18163
18401
|
* @description
|
|
18164
|
-
* Shortcut method to perform `DELETE` request
|
|
18402
|
+
* Shortcut method to perform `DELETE` request.
|
|
18165
18403
|
*
|
|
18166
18404
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
|
18167
18405
|
* @param {Object=} config Optional configuration object
|
|
@@ -18174,7 +18412,7 @@ function $HttpProvider() {
|
|
|
18174
18412
|
* @methodOf ng.$http
|
|
18175
18413
|
*
|
|
18176
18414
|
* @description
|
|
18177
|
-
* Shortcut method to perform `HEAD` request
|
|
18415
|
+
* Shortcut method to perform `HEAD` request.
|
|
18178
18416
|
*
|
|
18179
18417
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
|
18180
18418
|
* @param {Object=} config Optional configuration object
|
|
@@ -18187,7 +18425,7 @@ function $HttpProvider() {
|
|
|
18187
18425
|
* @methodOf ng.$http
|
|
18188
18426
|
*
|
|
18189
18427
|
* @description
|
|
18190
|
-
* Shortcut method to perform `JSONP` request
|
|
18428
|
+
* Shortcut method to perform `JSONP` request.
|
|
18191
18429
|
*
|
|
18192
18430
|
* @param {string} url Relative or absolute URL specifying the destination of the request.
|
|
18193
18431
|
* Should contain `JSON_CALLBACK` string.
|
|
@@ -18202,7 +18440,7 @@ function $HttpProvider() {
|
|
|
18202
18440
|
* @methodOf ng.$http
|
|
18203
18441
|
*
|
|
18204
18442
|
* @description
|
|
18205
|
-
* Shortcut method to perform `POST` request
|
|
18443
|
+
* Shortcut method to perform `POST` request.
|
|
18206
18444
|
*
|
|
18207
18445
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
|
18208
18446
|
* @param {*} data Request content
|
|
@@ -18216,7 +18454,7 @@ function $HttpProvider() {
|
|
|
18216
18454
|
* @methodOf ng.$http
|
|
18217
18455
|
*
|
|
18218
18456
|
* @description
|
|
18219
|
-
* Shortcut method to perform `PUT` request
|
|
18457
|
+
* Shortcut method to perform `PUT` request.
|
|
18220
18458
|
*
|
|
18221
18459
|
* @param {string} url Relative or absolute URL specifying the destination of the request
|
|
18222
18460
|
* @param {*} data Request content
|
|
@@ -18268,7 +18506,7 @@ function $HttpProvider() {
|
|
|
18268
18506
|
|
|
18269
18507
|
|
|
18270
18508
|
/**
|
|
18271
|
-
* Makes the request
|
|
18509
|
+
* Makes the request.
|
|
18272
18510
|
*
|
|
18273
18511
|
* !!! ACCESSES CLOSURE VARS:
|
|
18274
18512
|
* $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests
|
|
@@ -18378,6 +18616,7 @@ function $HttpProvider() {
|
|
|
18378
18616
|
|
|
18379
18617
|
}];
|
|
18380
18618
|
}
|
|
18619
|
+
|
|
18381
18620
|
var XHR = window.XMLHttpRequest || function() {
|
|
18382
18621
|
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
|
|
18383
18622
|
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
|
|
@@ -18445,8 +18684,30 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
|
|
|
18445
18684
|
// always async
|
|
18446
18685
|
xhr.onreadystatechange = function() {
|
|
18447
18686
|
if (xhr.readyState == 4) {
|
|
18448
|
-
|
|
18449
|
-
|
|
18687
|
+
var responseHeaders = xhr.getAllResponseHeaders();
|
|
18688
|
+
|
|
18689
|
+
// TODO(vojta): remove once Firefox 21 gets released.
|
|
18690
|
+
// begin: workaround to overcome Firefox CORS http response headers bug
|
|
18691
|
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=608735
|
|
18692
|
+
// Firefox already patched in nightly. Should land in Firefox 21.
|
|
18693
|
+
|
|
18694
|
+
// CORS "simple response headers" http://www.w3.org/TR/cors/
|
|
18695
|
+
var value,
|
|
18696
|
+
simpleHeaders = ["Cache-Control", "Content-Language", "Content-Type",
|
|
18697
|
+
"Expires", "Last-Modified", "Pragma"];
|
|
18698
|
+
if (!responseHeaders) {
|
|
18699
|
+
responseHeaders = "";
|
|
18700
|
+
forEach(simpleHeaders, function (header) {
|
|
18701
|
+
var value = xhr.getResponseHeader(header);
|
|
18702
|
+
if (value) {
|
|
18703
|
+
responseHeaders += header + ": " + value + "\n";
|
|
18704
|
+
}
|
|
18705
|
+
});
|
|
18706
|
+
}
|
|
18707
|
+
// end of the workaround.
|
|
18708
|
+
|
|
18709
|
+
completeRequest(callback, status || xhr.status, xhr.responseText,
|
|
18710
|
+
responseHeaders);
|
|
18450
18711
|
}
|
|
18451
18712
|
};
|
|
18452
18713
|
|
|
@@ -18592,17 +18853,17 @@ function $TimeoutProvider() {
|
|
|
18592
18853
|
* block and delegates any exceptions to
|
|
18593
18854
|
* {@link ng.$exceptionHandler $exceptionHandler} service.
|
|
18594
18855
|
*
|
|
18595
|
-
* The return value of registering a timeout function is a promise which will be resolved when
|
|
18856
|
+
* The return value of registering a timeout function is a promise, which will be resolved when
|
|
18596
18857
|
* the timeout is reached and the timeout function is executed.
|
|
18597
18858
|
*
|
|
18598
|
-
* To cancel a
|
|
18859
|
+
* To cancel a timeout request, call `$timeout.cancel(promise)`.
|
|
18599
18860
|
*
|
|
18600
18861
|
* In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
|
|
18601
18862
|
* synchronously flush the queue of deferred functions.
|
|
18602
18863
|
*
|
|
18603
|
-
* @param {function()} fn A function,
|
|
18864
|
+
* @param {function()} fn A function, whose execution should be delayed.
|
|
18604
18865
|
* @param {number=} [delay=0] Delay in milliseconds.
|
|
18605
|
-
* @param {boolean=} [invokeApply=true] If set to false skips model dirty checking, otherwise
|
|
18866
|
+
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
|
|
18606
18867
|
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
|
|
18607
18868
|
* @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
|
|
18608
18869
|
* promise will be resolved with is the return value of the `fn` function.
|
|
@@ -18642,7 +18903,7 @@ function $TimeoutProvider() {
|
|
|
18642
18903
|
* @methodOf ng.$timeout
|
|
18643
18904
|
*
|
|
18644
18905
|
* @description
|
|
18645
|
-
* Cancels a task associated with the `promise`. As a result of this the promise will be
|
|
18906
|
+
* Cancels a task associated with the `promise`. As a result of this, the promise will be
|
|
18646
18907
|
* resolved with a rejection.
|
|
18647
18908
|
*
|
|
18648
18909
|
* @param {Promise=} promise Promise returned by the `$timeout` function.
|
|
@@ -18668,7 +18929,7 @@ function $TimeoutProvider() {
|
|
|
18668
18929
|
*
|
|
18669
18930
|
* Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To
|
|
18670
18931
|
* achieve this a filter definition consists of a factory function which is annotated with dependencies and is
|
|
18671
|
-
* responsible for creating a
|
|
18932
|
+
* responsible for creating a filter function.
|
|
18672
18933
|
*
|
|
18673
18934
|
* <pre>
|
|
18674
18935
|
* // Filter registration
|
|
@@ -18730,7 +18991,7 @@ function $TimeoutProvider() {
|
|
|
18730
18991
|
*
|
|
18731
18992
|
* The general syntax in templates is as follows:
|
|
18732
18993
|
*
|
|
18733
|
-
* {{ expression | [
|
|
18994
|
+
* {{ expression [| filter_name[:parameter_value] ... ] }}
|
|
18734
18995
|
*
|
|
18735
18996
|
* @param {String} name Name of the filter function to retrieve
|
|
18736
18997
|
* @return {Function} the filter function
|
|
@@ -18806,22 +19067,22 @@ function $FilterProvider($provide) {
|
|
|
18806
19067
|
|
|
18807
19068
|
Search: <input ng-model="searchText">
|
|
18808
19069
|
<table id="searchTextResults">
|
|
18809
|
-
<tr><th>Name</th><th>Phone</th
|
|
19070
|
+
<tr><th>Name</th><th>Phone</th></tr>
|
|
18810
19071
|
<tr ng-repeat="friend in friends | filter:searchText">
|
|
18811
19072
|
<td>{{friend.name}}</td>
|
|
18812
19073
|
<td>{{friend.phone}}</td>
|
|
18813
|
-
|
|
19074
|
+
</tr>
|
|
18814
19075
|
</table>
|
|
18815
19076
|
<hr>
|
|
18816
19077
|
Any: <input ng-model="search.$"> <br>
|
|
18817
19078
|
Name only <input ng-model="search.name"><br>
|
|
18818
|
-
Phone only <input ng-model="search.phone"
|
|
19079
|
+
Phone only <input ng-model="search.phone"><br>
|
|
18819
19080
|
<table id="searchObjResults">
|
|
18820
|
-
<tr><th>Name</th><th>Phone</th
|
|
19081
|
+
<tr><th>Name</th><th>Phone</th></tr>
|
|
18821
19082
|
<tr ng-repeat="friend in friends | filter:search">
|
|
18822
19083
|
<td>{{friend.name}}</td>
|
|
18823
19084
|
<td>{{friend.phone}}</td>
|
|
18824
|
-
|
|
19085
|
+
</tr>
|
|
18825
19086
|
</table>
|
|
18826
19087
|
</doc:source>
|
|
18827
19088
|
<doc:scenario>
|
|
@@ -18845,7 +19106,7 @@ function $FilterProvider($provide) {
|
|
|
18845
19106
|
*/
|
|
18846
19107
|
function filterFilter() {
|
|
18847
19108
|
return function(array, expression) {
|
|
18848
|
-
if (!(array
|
|
19109
|
+
if (!isArray(array)) return array;
|
|
18849
19110
|
var predicates = [];
|
|
18850
19111
|
predicates.check = function(value) {
|
|
18851
19112
|
for (var j = 0; j < predicates.length; j++) {
|
|
@@ -19094,7 +19355,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
|
|
|
19094
19355
|
fraction += '0';
|
|
19095
19356
|
}
|
|
19096
19357
|
|
|
19097
|
-
if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);
|
|
19358
|
+
if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
|
|
19098
19359
|
}
|
|
19099
19360
|
|
|
19100
19361
|
parts.push(isNegative ? pattern.negPre : pattern.posPre);
|
|
@@ -19118,6 +19379,7 @@ function padNumber(num, digits, trim) {
|
|
|
19118
19379
|
|
|
19119
19380
|
|
|
19120
19381
|
function dateGetter(name, size, offset, trim) {
|
|
19382
|
+
offset = offset || 0;
|
|
19121
19383
|
return function(date) {
|
|
19122
19384
|
var value = date['get' + name]();
|
|
19123
19385
|
if (offset > 0 || value > -offset)
|
|
@@ -19137,8 +19399,13 @@ function dateStrGetter(name, shortForm) {
|
|
|
19137
19399
|
}
|
|
19138
19400
|
|
|
19139
19401
|
function timeZoneGetter(date) {
|
|
19140
|
-
var
|
|
19141
|
-
|
|
19402
|
+
var zone = -1 * date.getTimezoneOffset();
|
|
19403
|
+
var paddedZone = (zone >= 0) ? "+" : "";
|
|
19404
|
+
|
|
19405
|
+
paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
|
|
19406
|
+
padNumber(Math.abs(zone % 60), 2);
|
|
19407
|
+
|
|
19408
|
+
return paddedZone;
|
|
19142
19409
|
}
|
|
19143
19410
|
|
|
19144
19411
|
function ampmGetter(date, formats) {
|
|
@@ -19202,7 +19469,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
|
|
|
19202
19469
|
* * `'ss'`: Second in minute, padded (00-59)
|
|
19203
19470
|
* * `'s'`: Second in minute (0-59)
|
|
19204
19471
|
* * `'a'`: am/pm marker
|
|
19205
|
-
* * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200
|
|
19472
|
+
* * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
|
|
19206
19473
|
*
|
|
19207
19474
|
* `format` string can also be one of the following predefined
|
|
19208
19475
|
* {@link guide/i18n localizable formats}:
|
|
@@ -19223,8 +19490,9 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
|
|
|
19223
19490
|
* (e.g. `"h o''clock"`).
|
|
19224
19491
|
*
|
|
19225
19492
|
* @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
|
|
19226
|
-
* number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and
|
|
19227
|
-
* shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).
|
|
19493
|
+
* number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its
|
|
19494
|
+
* shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
|
|
19495
|
+
* specified in the string input, the time is considered to be in the local timezone.
|
|
19228
19496
|
* @param {string=} format Formatting rules (see Description). If not specified,
|
|
19229
19497
|
* `mediumDate` is used.
|
|
19230
19498
|
* @returns {string} Formatted string or the input if input is not recognized as date/millis.
|
|
@@ -19244,7 +19512,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
|
|
|
19244
19512
|
expect(binding("1288323623006 | date:'medium'")).
|
|
19245
19513
|
toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
|
|
19246
19514
|
expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).
|
|
19247
|
-
toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2}
|
|
19515
|
+
toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
|
|
19248
19516
|
expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).
|
|
19249
19517
|
toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
|
|
19250
19518
|
});
|
|
@@ -19513,12 +19781,12 @@ function limitToFilter(){
|
|
|
19513
19781
|
(<a href ng-click="predicate = '-name'; reverse=false">^</a>)</th>
|
|
19514
19782
|
<th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
|
|
19515
19783
|
<th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
|
|
19516
|
-
|
|
19784
|
+
</tr>
|
|
19517
19785
|
<tr ng-repeat="friend in friends | orderBy:predicate:reverse">
|
|
19518
19786
|
<td>{{friend.name}}</td>
|
|
19519
19787
|
<td>{{friend.phone}}</td>
|
|
19520
19788
|
<td>{{friend.age}}</td>
|
|
19521
|
-
|
|
19789
|
+
</tr>
|
|
19522
19790
|
</table>
|
|
19523
19791
|
</div>
|
|
19524
19792
|
</doc:source>
|
|
@@ -19550,7 +19818,7 @@ function limitToFilter(){
|
|
|
19550
19818
|
orderByFilter.$inject = ['$parse'];
|
|
19551
19819
|
function orderByFilter($parse){
|
|
19552
19820
|
return function(array, sortPredicate, reverseOrder) {
|
|
19553
|
-
if (!(array
|
|
19821
|
+
if (!isArray(array)) return array;
|
|
19554
19822
|
if (!sortPredicate) return array;
|
|
19555
19823
|
sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
|
|
19556
19824
|
sortPredicate = map(sortPredicate, function(predicate){
|
|
@@ -19618,15 +19886,25 @@ function ngDirective(directive) {
|
|
|
19618
19886
|
*
|
|
19619
19887
|
* The reasoning for this change is to allow easy creation of action links with `ngClick` directive
|
|
19620
19888
|
* without changing the location or causing page reloads, e.g.:
|
|
19621
|
-
*
|
|
19889
|
+
* `<a href="" ng-click="model.$save()">Save</a>`
|
|
19622
19890
|
*/
|
|
19623
19891
|
var htmlAnchorDirective = valueFn({
|
|
19624
19892
|
restrict: 'E',
|
|
19625
19893
|
compile: function(element, attr) {
|
|
19626
|
-
|
|
19627
|
-
|
|
19628
|
-
|
|
19629
|
-
|
|
19894
|
+
|
|
19895
|
+
if (msie <= 8) {
|
|
19896
|
+
|
|
19897
|
+
// turn <a href ng-click="..">link</a> into a stylable link in IE
|
|
19898
|
+
// but only if it doesn't have name attribute, in which case it's an anchor
|
|
19899
|
+
if (!attr.href && !attr.name) {
|
|
19900
|
+
attr.$set('href', '');
|
|
19901
|
+
}
|
|
19902
|
+
|
|
19903
|
+
// add a comment node to anchors to workaround IE bug that causes element content to be reset
|
|
19904
|
+
// to new attribute content if attribute is updated with value containing @ and element also
|
|
19905
|
+
// contains value with @
|
|
19906
|
+
// see issue #1949
|
|
19907
|
+
element.append(document.createComment('IE fix'));
|
|
19630
19908
|
}
|
|
19631
19909
|
|
|
19632
19910
|
return function(scope, element) {
|
|
@@ -19634,7 +19912,6 @@ var htmlAnchorDirective = valueFn({
|
|
|
19634
19912
|
// if we have no href url, then don't navigate anywhere.
|
|
19635
19913
|
if (!element.attr('href')) {
|
|
19636
19914
|
event.preventDefault();
|
|
19637
|
-
return false; // Needed for opera
|
|
19638
19915
|
}
|
|
19639
19916
|
});
|
|
19640
19917
|
}
|
|
@@ -19707,7 +19984,7 @@ var htmlAnchorDirective = valueFn({
|
|
|
19707
19984
|
it('should execute ng-click but not reload when no href but name specified', function() {
|
|
19708
19985
|
element('#link-5').click();
|
|
19709
19986
|
expect(input('value').val()).toEqual('5');
|
|
19710
|
-
expect(element('#link-5').attr('href')).toBe(
|
|
19987
|
+
expect(element('#link-5').attr('href')).toBe(undefined);
|
|
19711
19988
|
});
|
|
19712
19989
|
|
|
19713
19990
|
it('should only change url when only ng-href', function() {
|
|
@@ -19950,8 +20227,9 @@ forEach(['src', 'href'], function(attrName) {
|
|
|
19950
20227
|
|
|
19951
20228
|
// on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
|
|
19952
20229
|
// then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
|
|
19953
|
-
// to set the property as well to achieve the desired effect
|
|
19954
|
-
|
|
20230
|
+
// to set the property as well to achieve the desired effect.
|
|
20231
|
+
// we use attr[attrName] value since $set can sanitize the url.
|
|
20232
|
+
if (msie) element.prop(attrName, attr[attrName]);
|
|
19955
20233
|
});
|
|
19956
20234
|
}
|
|
19957
20235
|
};
|
|
@@ -19971,13 +20249,13 @@ var nullFormCtrl = {
|
|
|
19971
20249
|
*
|
|
19972
20250
|
* @property {boolean} $pristine True if user has not interacted with the form yet.
|
|
19973
20251
|
* @property {boolean} $dirty True if user has already interacted with the form.
|
|
19974
|
-
* @property {boolean} $valid True if all of the
|
|
20252
|
+
* @property {boolean} $valid True if all of the containing forms and controls are valid.
|
|
19975
20253
|
* @property {boolean} $invalid True if at least one containing control or form is invalid.
|
|
19976
20254
|
*
|
|
19977
20255
|
* @property {Object} $error Is an object hash, containing references to all invalid controls or
|
|
19978
20256
|
* forms, where:
|
|
19979
20257
|
*
|
|
19980
|
-
* - keys are validation tokens (error names) — such as `
|
|
20258
|
+
* - keys are validation tokens (error names) — such as `required`, `url` or `email`),
|
|
19981
20259
|
* - values are arrays of controls or forms that are invalid with given error.
|
|
19982
20260
|
*
|
|
19983
20261
|
* @description
|
|
@@ -20090,7 +20368,7 @@ function FormController(element, attrs) {
|
|
|
20090
20368
|
* does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
|
|
20091
20369
|
* sub-group of controls needs to be determined.
|
|
20092
20370
|
*
|
|
20093
|
-
* @param {string=} ngForm
|
|
20371
|
+
* @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into
|
|
20094
20372
|
* related scope, under this name.
|
|
20095
20373
|
*
|
|
20096
20374
|
*/
|
|
@@ -20163,12 +20441,12 @@ function FormController(element, attrs) {
|
|
|
20163
20441
|
</script>
|
|
20164
20442
|
<form name="myForm" ng-controller="Ctrl">
|
|
20165
20443
|
userType: <input name="input" ng-model="userType" required>
|
|
20166
|
-
<span class="error" ng-show="myForm.input.$error.
|
|
20444
|
+
<span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
|
|
20167
20445
|
<tt>userType = {{userType}}</tt><br>
|
|
20168
20446
|
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
|
|
20169
20447
|
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
|
|
20170
20448
|
<tt>myForm.$valid = {{myForm.$valid}}</tt><br>
|
|
20171
|
-
<tt>myForm.$error.
|
|
20449
|
+
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
|
|
20172
20450
|
</form>
|
|
20173
20451
|
</doc:source>
|
|
20174
20452
|
<doc:scenario>
|
|
@@ -20330,8 +20608,8 @@ var inputType = {
|
|
|
20330
20608
|
*
|
|
20331
20609
|
* @param {string} ngModel Assignable angular expression to data-bind to.
|
|
20332
20610
|
* @param {string=} name Property name of the form under which the control is published.
|
|
20333
|
-
* @param {string=} min Sets the `min` validation error key if the value entered is less
|
|
20334
|
-
* @param {string=} max Sets the `max` validation error key if the value entered is greater
|
|
20611
|
+
* @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
|
|
20612
|
+
* @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
|
|
20335
20613
|
* @param {string=} required Sets `required` validation error key if the value is not entered.
|
|
20336
20614
|
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
|
20337
20615
|
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
|
@@ -20643,6 +20921,15 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
|
|
20643
20921
|
} else {
|
|
20644
20922
|
var timeout;
|
|
20645
20923
|
|
|
20924
|
+
var deferListener = function() {
|
|
20925
|
+
if (!timeout) {
|
|
20926
|
+
timeout = $browser.defer(function() {
|
|
20927
|
+
listener();
|
|
20928
|
+
timeout = null;
|
|
20929
|
+
});
|
|
20930
|
+
}
|
|
20931
|
+
};
|
|
20932
|
+
|
|
20646
20933
|
element.bind('keydown', function(event) {
|
|
20647
20934
|
var key = event.keyCode;
|
|
20648
20935
|
|
|
@@ -20650,16 +20937,16 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
|
|
20650
20937
|
// command modifiers arrows
|
|
20651
20938
|
if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
|
|
20652
20939
|
|
|
20653
|
-
|
|
20654
|
-
timeout = $browser.defer(function() {
|
|
20655
|
-
listener();
|
|
20656
|
-
timeout = null;
|
|
20657
|
-
});
|
|
20658
|
-
}
|
|
20940
|
+
deferListener();
|
|
20659
20941
|
});
|
|
20660
20942
|
|
|
20661
20943
|
// if user paste into input using mouse, we need "change" event to catch it
|
|
20662
20944
|
element.bind('change', listener);
|
|
20945
|
+
|
|
20946
|
+
// if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
|
|
20947
|
+
if ($sniffer.hasEvent('paste')) {
|
|
20948
|
+
element.bind('paste cut', deferListener);
|
|
20949
|
+
}
|
|
20663
20950
|
}
|
|
20664
20951
|
|
|
20665
20952
|
|
|
@@ -20958,7 +21245,7 @@ function checkboxInputType(scope, element, attr, ctrl) {
|
|
|
20958
21245
|
<tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
|
|
20959
21246
|
<tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
|
|
20960
21247
|
<tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
|
|
20961
|
-
<tt>myForm.
|
|
21248
|
+
<tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>
|
|
20962
21249
|
<tt>myForm.$valid = {{myForm.$valid}}</tt><br>
|
|
20963
21250
|
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
|
|
20964
21251
|
<tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>
|
|
@@ -21221,7 +21508,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
|
|
21221
21508
|
* For example {@link ng.directive:input input} or
|
|
21222
21509
|
* {@link ng.directive:select select} directives call it.
|
|
21223
21510
|
*
|
|
21224
|
-
* It internally calls all `
|
|
21511
|
+
* It internally calls all `parsers` and if resulted value is valid, updates the model and
|
|
21225
21512
|
* calls all registered change listeners.
|
|
21226
21513
|
*
|
|
21227
21514
|
* @param {string} value Value from the view.
|
|
@@ -21527,7 +21814,7 @@ var ngValueDirective = function() {
|
|
|
21527
21814
|
* Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
|
|
21528
21815
|
* `{{ expression }}` which is similar but less verbose.
|
|
21529
21816
|
*
|
|
21530
|
-
*
|
|
21817
|
+
* One scenario in which the use of `ngBind` is preferred over `{{ expression }}` binding is when
|
|
21531
21818
|
* it's desirable to put bindings into template that is momentarily displayed by the browser in its
|
|
21532
21819
|
* raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the
|
|
21533
21820
|
* bindings invisible to the user while the page is loading.
|
|
@@ -21656,6 +21943,7 @@ var ngBindHtmlUnsafeDirective = [function() {
|
|
|
21656
21943
|
function classDirective(name, selector) {
|
|
21657
21944
|
name = 'ngClass' + name;
|
|
21658
21945
|
return ngDirective(function(scope, element, attr) {
|
|
21946
|
+
var oldVal = undefined;
|
|
21659
21947
|
|
|
21660
21948
|
scope.$watch(attr[name], ngClassWatchAction, true);
|
|
21661
21949
|
|
|
@@ -21667,9 +21955,9 @@ function classDirective(name, selector) {
|
|
|
21667
21955
|
|
|
21668
21956
|
if (name !== 'ngClass') {
|
|
21669
21957
|
scope.$watch('$index', function($index, old$index) {
|
|
21670
|
-
var mod = $index
|
|
21671
|
-
if (mod !== old$index
|
|
21672
|
-
if (mod
|
|
21958
|
+
var mod = $index & 1;
|
|
21959
|
+
if (mod !== old$index & 1) {
|
|
21960
|
+
if (mod === selector) {
|
|
21673
21961
|
addClass(scope.$eval(attr[name]));
|
|
21674
21962
|
} else {
|
|
21675
21963
|
removeClass(scope.$eval(attr[name]));
|
|
@@ -21679,13 +21967,14 @@ function classDirective(name, selector) {
|
|
|
21679
21967
|
}
|
|
21680
21968
|
|
|
21681
21969
|
|
|
21682
|
-
function ngClassWatchAction(newVal
|
|
21970
|
+
function ngClassWatchAction(newVal) {
|
|
21683
21971
|
if (selector === true || scope.$index % 2 === selector) {
|
|
21684
|
-
if (oldVal && (newVal
|
|
21972
|
+
if (oldVal && !equals(newVal,oldVal)) {
|
|
21685
21973
|
removeClass(oldVal);
|
|
21686
21974
|
}
|
|
21687
21975
|
addClass(newVal);
|
|
21688
21976
|
}
|
|
21977
|
+
oldVal = copy(newVal);
|
|
21689
21978
|
}
|
|
21690
21979
|
|
|
21691
21980
|
|
|
@@ -21718,7 +22007,7 @@ function classDirective(name, selector) {
|
|
|
21718
22007
|
*
|
|
21719
22008
|
* The directive won't add duplicate classes if a particular class was already set.
|
|
21720
22009
|
*
|
|
21721
|
-
* When the expression changes, the previously added classes are removed and only then the
|
|
22010
|
+
* When the expression changes, the previously added classes are removed and only then the
|
|
21722
22011
|
* new classes are added.
|
|
21723
22012
|
*
|
|
21724
22013
|
* @element ANY
|
|
@@ -21811,7 +22100,7 @@ var ngClassOddDirective = classDirective('Odd', 0);
|
|
|
21811
22100
|
* @name ng.directive:ngClassEven
|
|
21812
22101
|
*
|
|
21813
22102
|
* @description
|
|
21814
|
-
* The `ngClassOdd` and `ngClassEven`
|
|
22103
|
+
* The `ngClassOdd` and `ngClassEven` directives work exactly as
|
|
21815
22104
|
* {@link ng.directive:ngClass ngClass}, except it works in
|
|
21816
22105
|
* conjunction with `ngRepeat` and takes affect only on odd (even) rows.
|
|
21817
22106
|
*
|
|
@@ -21869,7 +22158,7 @@ var ngClassEvenDirective = classDirective('Even', 1);
|
|
|
21869
22158
|
* `angular.min.js` files. Following is the css rule:
|
|
21870
22159
|
*
|
|
21871
22160
|
* <pre>
|
|
21872
|
-
* [ng\:cloak], [ng-cloak], .ng-cloak {
|
|
22161
|
+
* [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
|
|
21873
22162
|
* display: none;
|
|
21874
22163
|
* }
|
|
21875
22164
|
* </pre>
|
|
@@ -21928,8 +22217,7 @@ var ngCloakDirective = ngDirective({
|
|
|
21928
22217
|
* * Controller — The `ngController` directive specifies a Controller class; the class has
|
|
21929
22218
|
* methods that typically express the business logic behind the application.
|
|
21930
22219
|
*
|
|
21931
|
-
* Note that an alternative way to define controllers is via the
|
|
21932
|
-
* service.
|
|
22220
|
+
* Note that an alternative way to define controllers is via the {@link ng.$route $route} service.
|
|
21933
22221
|
*
|
|
21934
22222
|
* @element ANY
|
|
21935
22223
|
* @scope
|
|
@@ -22020,16 +22308,32 @@ var ngControllerDirective = [function() {
|
|
|
22020
22308
|
* @name ng.directive:ngCsp
|
|
22021
22309
|
* @priority 1000
|
|
22022
22310
|
*
|
|
22311
|
+
* @element html
|
|
22023
22312
|
* @description
|
|
22024
22313
|
* Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
|
|
22025
|
-
*
|
|
22026
|
-
*
|
|
22027
|
-
*
|
|
22028
|
-
*
|
|
22029
|
-
*
|
|
22030
|
-
*
|
|
22031
|
-
*
|
|
22032
|
-
*
|
|
22314
|
+
*
|
|
22315
|
+
* This is necessary when developing things like Google Chrome Extensions.
|
|
22316
|
+
*
|
|
22317
|
+
* CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
|
|
22318
|
+
* For us to be compatible, we just need to implement the "getterFn" in $parse without violating
|
|
22319
|
+
* any of these restrictions.
|
|
22320
|
+
*
|
|
22321
|
+
* AngularJS uses `Function(string)` generated functions as a speed optimization. By applying `ngCsp`
|
|
22322
|
+
* it is be possible to opt into the CSP compatible mode. When this mode is on AngularJS will
|
|
22323
|
+
* evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
|
|
22324
|
+
* be raised.
|
|
22325
|
+
*
|
|
22326
|
+
* In order to use this feature put `ngCsp` directive on the root element of the application.
|
|
22327
|
+
*
|
|
22328
|
+
* @example
|
|
22329
|
+
* This example shows how to apply the `ngCsp` directive to the `html` tag.
|
|
22330
|
+
<pre>
|
|
22331
|
+
<!doctype html>
|
|
22332
|
+
<html ng-app ng-csp>
|
|
22333
|
+
...
|
|
22334
|
+
...
|
|
22335
|
+
</html>
|
|
22336
|
+
</pre>
|
|
22033
22337
|
*/
|
|
22034
22338
|
|
|
22035
22339
|
var ngCspDirective = ['$sniffer', function($sniffer) {
|
|
@@ -22654,7 +22958,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
|
|
|
22654
22958
|
if (!isNaN(value)) {
|
|
22655
22959
|
//if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
|
|
22656
22960
|
//check it against pluralization rules in $locale service
|
|
22657
|
-
if (!whens
|
|
22961
|
+
if (!(value in whens)) value = $locale.pluralCat(value - offset);
|
|
22658
22962
|
return whensExpFns[value](scope, element, true);
|
|
22659
22963
|
} else {
|
|
22660
22964
|
return '';
|
|
@@ -22758,14 +23062,17 @@ var ngRepeatDirective = ngDirective({
|
|
|
22758
23062
|
scope.$watch(function ngRepeatWatch(scope){
|
|
22759
23063
|
var index, length,
|
|
22760
23064
|
collection = scope.$eval(rhs),
|
|
22761
|
-
|
|
22762
|
-
childScope,
|
|
23065
|
+
cursor = iterStartElement, // current position of the node
|
|
22763
23066
|
// Same as lastOrder but it has the current state. It will become the
|
|
22764
23067
|
// lastOrder on the next iteration.
|
|
22765
23068
|
nextOrder = new HashQueueMap(),
|
|
23069
|
+
arrayBound,
|
|
23070
|
+
childScope,
|
|
22766
23071
|
key, value, // key/value of iteration
|
|
22767
|
-
array,
|
|
22768
|
-
|
|
23072
|
+
array,
|
|
23073
|
+
last; // last object information {scope, element, index}
|
|
23074
|
+
|
|
23075
|
+
|
|
22769
23076
|
|
|
22770
23077
|
if (!isArray(collection)) {
|
|
22771
23078
|
// if object, extract keys, sort them and use to determine order of iteration over obj props
|
|
@@ -22780,6 +23087,8 @@ var ngRepeatDirective = ngDirective({
|
|
|
22780
23087
|
array = collection || [];
|
|
22781
23088
|
}
|
|
22782
23089
|
|
|
23090
|
+
arrayBound = array.length-1;
|
|
23091
|
+
|
|
22783
23092
|
// we are not using forEach for perf reasons (trying to avoid #call)
|
|
22784
23093
|
for (index = 0, length = array.length; index < length; index++) {
|
|
22785
23094
|
key = (collection === array) ? index : array[index];
|
|
@@ -22815,7 +23124,7 @@ var ngRepeatDirective = ngDirective({
|
|
|
22815
23124
|
childScope.$index = index;
|
|
22816
23125
|
|
|
22817
23126
|
childScope.$first = (index === 0);
|
|
22818
|
-
childScope.$last = (index ===
|
|
23127
|
+
childScope.$last = (index === arrayBound);
|
|
22819
23128
|
childScope.$middle = !(childScope.$first || childScope.$last);
|
|
22820
23129
|
|
|
22821
23130
|
if (!last) {
|
|
@@ -22982,11 +23291,13 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
|
22982
23291
|
* @description
|
|
22983
23292
|
* Conditionally change the DOM structure.
|
|
22984
23293
|
*
|
|
22985
|
-
* @
|
|
22986
|
-
* <ANY ng-switch
|
|
23294
|
+
* @usage
|
|
23295
|
+
* <ANY ng-switch="expression">
|
|
23296
|
+
* <ANY ng-switch-when="matchValue1">...</ANY>
|
|
22987
23297
|
* <ANY ng-switch-when="matchValue2">...</ANY>
|
|
22988
23298
|
* ...
|
|
22989
23299
|
* <ANY ng-switch-default>...</ANY>
|
|
23300
|
+
* </ANY>
|
|
22990
23301
|
*
|
|
22991
23302
|
* @scope
|
|
22992
23303
|
* @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
|
|
@@ -23036,52 +23347,54 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
|
|
|
23036
23347
|
var NG_SWITCH = 'ng-switch';
|
|
23037
23348
|
var ngSwitchDirective = valueFn({
|
|
23038
23349
|
restrict: 'EA',
|
|
23039
|
-
|
|
23350
|
+
require: 'ngSwitch',
|
|
23351
|
+
// asks for $scope to fool the BC controller module
|
|
23352
|
+
controller: ['$scope', function ngSwitchController() {
|
|
23353
|
+
this.cases = {};
|
|
23354
|
+
}],
|
|
23355
|
+
link: function(scope, element, attr, ctrl) {
|
|
23040
23356
|
var watchExpr = attr.ngSwitch || attr.on,
|
|
23041
|
-
|
|
23042
|
-
|
|
23043
|
-
|
|
23044
|
-
|
|
23045
|
-
|
|
23046
|
-
|
|
23047
|
-
|
|
23048
|
-
|
|
23049
|
-
|
|
23050
|
-
|
|
23051
|
-
|
|
23052
|
-
|
|
23053
|
-
|
|
23054
|
-
|
|
23055
|
-
|
|
23056
|
-
|
|
23057
|
-
|
|
23058
|
-
|
|
23059
|
-
|
|
23060
|
-
element.append(caseElement);
|
|
23061
|
-
});
|
|
23062
|
-
}
|
|
23063
|
-
});
|
|
23064
|
-
};
|
|
23357
|
+
selectedTransclude,
|
|
23358
|
+
selectedElement,
|
|
23359
|
+
selectedScope;
|
|
23360
|
+
|
|
23361
|
+
scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
|
|
23362
|
+
if (selectedElement) {
|
|
23363
|
+
selectedScope.$destroy();
|
|
23364
|
+
selectedElement.remove();
|
|
23365
|
+
selectedElement = selectedScope = null;
|
|
23366
|
+
}
|
|
23367
|
+
if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {
|
|
23368
|
+
scope.$eval(attr.change);
|
|
23369
|
+
selectedScope = scope.$new();
|
|
23370
|
+
selectedTransclude(selectedScope, function(caseElement) {
|
|
23371
|
+
selectedElement = caseElement;
|
|
23372
|
+
element.append(caseElement);
|
|
23373
|
+
});
|
|
23374
|
+
}
|
|
23375
|
+
});
|
|
23065
23376
|
}
|
|
23066
23377
|
});
|
|
23067
23378
|
|
|
23068
23379
|
var ngSwitchWhenDirective = ngDirective({
|
|
23069
23380
|
transclude: 'element',
|
|
23070
23381
|
priority: 500,
|
|
23382
|
+
require: '^ngSwitch',
|
|
23071
23383
|
compile: function(element, attrs, transclude) {
|
|
23072
|
-
|
|
23073
|
-
|
|
23074
|
-
|
|
23384
|
+
return function(scope, element, attr, ctrl) {
|
|
23385
|
+
ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;
|
|
23386
|
+
};
|
|
23075
23387
|
}
|
|
23076
23388
|
});
|
|
23077
23389
|
|
|
23078
23390
|
var ngSwitchDefaultDirective = ngDirective({
|
|
23079
23391
|
transclude: 'element',
|
|
23080
23392
|
priority: 500,
|
|
23393
|
+
require: '^ngSwitch',
|
|
23081
23394
|
compile: function(element, attrs, transclude) {
|
|
23082
|
-
|
|
23083
|
-
|
|
23084
|
-
|
|
23395
|
+
return function(scope, element, attr, ctrl) {
|
|
23396
|
+
ctrl.cases['?'] = transclude;
|
|
23397
|
+
};
|
|
23085
23398
|
}
|
|
23086
23399
|
});
|
|
23087
23400
|
|
|
@@ -23170,7 +23483,7 @@ var ngTranscludeDirective = ngDirective({
|
|
|
23170
23483
|
<hr />
|
|
23171
23484
|
|
|
23172
23485
|
<pre>$location.path() = {{$location.path()}}</pre>
|
|
23173
|
-
<pre>$route.current.
|
|
23486
|
+
<pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
|
|
23174
23487
|
<pre>$route.current.params = {{$route.current.params}}</pre>
|
|
23175
23488
|
<pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
|
|
23176
23489
|
<pre>$routeParams = {{$routeParams}}</pre>
|
|
@@ -23289,7 +23602,7 @@ var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$c
|
|
|
23289
23602
|
if (current.controller) {
|
|
23290
23603
|
locals.$scope = lastScope;
|
|
23291
23604
|
controller = $controller(current.controller, locals);
|
|
23292
|
-
element.
|
|
23605
|
+
element.children().data('$ngControllerController', controller);
|
|
23293
23606
|
}
|
|
23294
23607
|
|
|
23295
23608
|
link(lastScope);
|
|
@@ -23378,7 +23691,8 @@ var scriptDirective = ['$templateCache', function($templateCache) {
|
|
|
23378
23691
|
* `select` model to be bound to a non-string value. This is because an option element can currently
|
|
23379
23692
|
* be bound to string values only.
|
|
23380
23693
|
*
|
|
23381
|
-
* @param {string}
|
|
23694
|
+
* @param {string} ngModel Assignable angular expression to data-bind to.
|
|
23695
|
+
* @param {string=} name Property name of the form under which the control is published.
|
|
23382
23696
|
* @param {string=} required The control is considered valid only if value is entered.
|
|
23383
23697
|
* @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
|
|
23384
23698
|
* the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
|
|
@@ -23473,7 +23787,7 @@ var scriptDirective = ['$templateCache', function($templateCache) {
|
|
|
23473
23787
|
|
|
23474
23788
|
var ngOptionsDirective = valueFn({ terminal: true });
|
|
23475
23789
|
var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
23476
|
-
//
|
|
23790
|
+
//0000111110000000000022220000000000000000000000333300000000000000444444444444444440000000005555555555555555500000006666666666666666600000000000000077770
|
|
23477
23791
|
var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/,
|
|
23478
23792
|
nullModelCtrl = {$setViewValue: noop};
|
|
23479
23793
|
|
|
@@ -23616,7 +23930,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
|
23616
23930
|
var lastView;
|
|
23617
23931
|
ctrl.$render = function() {
|
|
23618
23932
|
var items = new HashMap(ctrl.$viewValue);
|
|
23619
|
-
forEach(selectElement.
|
|
23933
|
+
forEach(selectElement.find('option'), function(option) {
|
|
23620
23934
|
option.selected = isDefined(items.get(option.value));
|
|
23621
23935
|
});
|
|
23622
23936
|
};
|
|
@@ -23633,7 +23947,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
|
23633
23947
|
selectElement.bind('change', function() {
|
|
23634
23948
|
scope.$apply(function() {
|
|
23635
23949
|
var array = [];
|
|
23636
|
-
forEach(selectElement.
|
|
23950
|
+
forEach(selectElement.find('option'), function(option) {
|
|
23637
23951
|
if (option.selected) {
|
|
23638
23952
|
array.push(option.value);
|
|
23639
23953
|
}
|
|
@@ -23745,10 +24059,6 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
|
23745
24059
|
|
|
23746
24060
|
if (multiple) {
|
|
23747
24061
|
selectedSet = new HashMap(modelValue);
|
|
23748
|
-
} else if (modelValue === null || nullOption) {
|
|
23749
|
-
// if we are not multiselect, and we are null then we have to add the nullOption
|
|
23750
|
-
optionGroups[''].push({selected:modelValue === null, id:'', label:''});
|
|
23751
|
-
selectedSet = true;
|
|
23752
24062
|
}
|
|
23753
24063
|
|
|
23754
24064
|
// We now build up the list of options we need (we merge later)
|
|
@@ -23773,9 +24083,14 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
|
23773
24083
|
selected: selected // determine if we should be selected
|
|
23774
24084
|
});
|
|
23775
24085
|
}
|
|
23776
|
-
if (!multiple
|
|
23777
|
-
|
|
23778
|
-
|
|
24086
|
+
if (!multiple) {
|
|
24087
|
+
if (nullOption || modelValue === null) {
|
|
24088
|
+
// insert null option if we have a placeholder, or the model is null
|
|
24089
|
+
optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});
|
|
24090
|
+
} else if (!selectedSet) {
|
|
24091
|
+
// option could not be found, we have to insert the undefined item
|
|
24092
|
+
optionGroups[''].unshift({id:'?', label:'', selected:true});
|
|
24093
|
+
}
|
|
23779
24094
|
}
|
|
23780
24095
|
|
|
23781
24096
|
// Now we need to update the list of DOM nodes to match the optionGroups we computed above
|
|
@@ -23819,7 +24134,8 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
|
|
|
23819
24134
|
if (existingOption.id !== option.id) {
|
|
23820
24135
|
lastElement.val(existingOption.id = option.id);
|
|
23821
24136
|
}
|
|
23822
|
-
|
|
24137
|
+
// lastElement.prop('selected') provided by jQuery has side-effects
|
|
24138
|
+
if (lastElement[0].selected !== option.selected) {
|
|
23823
24139
|
lastElement.prop('selected', (existingOption.selected = option.selected));
|
|
23824
24140
|
}
|
|
23825
24141
|
} else {
|
|
@@ -24911,160 +25227,6 @@ angular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, er
|
|
|
24911
25227
|
this.line = line;
|
|
24912
25228
|
};
|
|
24913
25229
|
|
|
24914
|
-
/**
|
|
24915
|
-
* The representation of define blocks. Don't used directly, instead use
|
|
24916
|
-
* define() in your tests.
|
|
24917
|
-
*
|
|
24918
|
-
* @param {string} descName Name of the block
|
|
24919
|
-
* @param {Object} parent describe or undefined if the root.
|
|
24920
|
-
*/
|
|
24921
|
-
angular.scenario.Describe = function(descName, parent) {
|
|
24922
|
-
this.only = parent && parent.only;
|
|
24923
|
-
this.beforeEachFns = [];
|
|
24924
|
-
this.afterEachFns = [];
|
|
24925
|
-
this.its = [];
|
|
24926
|
-
this.children = [];
|
|
24927
|
-
this.name = descName;
|
|
24928
|
-
this.parent = parent;
|
|
24929
|
-
this.id = angular.scenario.Describe.id++;
|
|
24930
|
-
|
|
24931
|
-
/**
|
|
24932
|
-
* Calls all before functions.
|
|
24933
|
-
*/
|
|
24934
|
-
var beforeEachFns = this.beforeEachFns;
|
|
24935
|
-
this.setupBefore = function() {
|
|
24936
|
-
if (parent) parent.setupBefore.call(this);
|
|
24937
|
-
angular.forEach(beforeEachFns, function(fn) { fn.call(this); }, this);
|
|
24938
|
-
};
|
|
24939
|
-
|
|
24940
|
-
/**
|
|
24941
|
-
* Calls all after functions.
|
|
24942
|
-
*/
|
|
24943
|
-
var afterEachFns = this.afterEachFns;
|
|
24944
|
-
this.setupAfter = function() {
|
|
24945
|
-
angular.forEach(afterEachFns, function(fn) { fn.call(this); }, this);
|
|
24946
|
-
if (parent) parent.setupAfter.call(this);
|
|
24947
|
-
};
|
|
24948
|
-
};
|
|
24949
|
-
|
|
24950
|
-
// Shared Unique ID generator for every describe block
|
|
24951
|
-
angular.scenario.Describe.id = 0;
|
|
24952
|
-
|
|
24953
|
-
// Shared Unique ID generator for every it (spec)
|
|
24954
|
-
angular.scenario.Describe.specId = 0;
|
|
24955
|
-
|
|
24956
|
-
/**
|
|
24957
|
-
* Defines a block to execute before each it or nested describe.
|
|
24958
|
-
*
|
|
24959
|
-
* @param {function()} body Body of the block.
|
|
24960
|
-
*/
|
|
24961
|
-
angular.scenario.Describe.prototype.beforeEach = function(body) {
|
|
24962
|
-
this.beforeEachFns.push(body);
|
|
24963
|
-
};
|
|
24964
|
-
|
|
24965
|
-
/**
|
|
24966
|
-
* Defines a block to execute after each it or nested describe.
|
|
24967
|
-
*
|
|
24968
|
-
* @param {function()} body Body of the block.
|
|
24969
|
-
*/
|
|
24970
|
-
angular.scenario.Describe.prototype.afterEach = function(body) {
|
|
24971
|
-
this.afterEachFns.push(body);
|
|
24972
|
-
};
|
|
24973
|
-
|
|
24974
|
-
/**
|
|
24975
|
-
* Creates a new describe block that's a child of this one.
|
|
24976
|
-
*
|
|
24977
|
-
* @param {string} name Name of the block. Appended to the parent block's name.
|
|
24978
|
-
* @param {function()} body Body of the block.
|
|
24979
|
-
*/
|
|
24980
|
-
angular.scenario.Describe.prototype.describe = function(name, body) {
|
|
24981
|
-
var child = new angular.scenario.Describe(name, this);
|
|
24982
|
-
this.children.push(child);
|
|
24983
|
-
body.call(child);
|
|
24984
|
-
};
|
|
24985
|
-
|
|
24986
|
-
/**
|
|
24987
|
-
* Same as describe() but makes ddescribe blocks the only to run.
|
|
24988
|
-
*
|
|
24989
|
-
* @param {string} name Name of the test.
|
|
24990
|
-
* @param {function()} body Body of the block.
|
|
24991
|
-
*/
|
|
24992
|
-
angular.scenario.Describe.prototype.ddescribe = function(name, body) {
|
|
24993
|
-
var child = new angular.scenario.Describe(name, this);
|
|
24994
|
-
child.only = true;
|
|
24995
|
-
this.children.push(child);
|
|
24996
|
-
body.call(child);
|
|
24997
|
-
};
|
|
24998
|
-
|
|
24999
|
-
/**
|
|
25000
|
-
* Use to disable a describe block.
|
|
25001
|
-
*/
|
|
25002
|
-
angular.scenario.Describe.prototype.xdescribe = angular.noop;
|
|
25003
|
-
|
|
25004
|
-
/**
|
|
25005
|
-
* Defines a test.
|
|
25006
|
-
*
|
|
25007
|
-
* @param {string} name Name of the test.
|
|
25008
|
-
* @param {function()} vody Body of the block.
|
|
25009
|
-
*/
|
|
25010
|
-
angular.scenario.Describe.prototype.it = function(name, body) {
|
|
25011
|
-
this.its.push({
|
|
25012
|
-
id: angular.scenario.Describe.specId++,
|
|
25013
|
-
definition: this,
|
|
25014
|
-
only: this.only,
|
|
25015
|
-
name: name,
|
|
25016
|
-
before: this.setupBefore,
|
|
25017
|
-
body: body,
|
|
25018
|
-
after: this.setupAfter
|
|
25019
|
-
});
|
|
25020
|
-
};
|
|
25021
|
-
|
|
25022
|
-
/**
|
|
25023
|
-
* Same as it() but makes iit tests the only test to run.
|
|
25024
|
-
*
|
|
25025
|
-
* @param {string} name Name of the test.
|
|
25026
|
-
* @param {function()} body Body of the block.
|
|
25027
|
-
*/
|
|
25028
|
-
angular.scenario.Describe.prototype.iit = function(name, body) {
|
|
25029
|
-
this.it.apply(this, arguments);
|
|
25030
|
-
this.its[this.its.length-1].only = true;
|
|
25031
|
-
};
|
|
25032
|
-
|
|
25033
|
-
/**
|
|
25034
|
-
* Use to disable a test block.
|
|
25035
|
-
*/
|
|
25036
|
-
angular.scenario.Describe.prototype.xit = angular.noop;
|
|
25037
|
-
|
|
25038
|
-
/**
|
|
25039
|
-
* Gets an array of functions representing all the tests (recursively).
|
|
25040
|
-
* that can be executed with SpecRunner's.
|
|
25041
|
-
*
|
|
25042
|
-
* @return {Array<Object>} Array of it blocks {
|
|
25043
|
-
* definition : Object // parent Describe
|
|
25044
|
-
* only: boolean
|
|
25045
|
-
* name: string
|
|
25046
|
-
* before: Function
|
|
25047
|
-
* body: Function
|
|
25048
|
-
* after: Function
|
|
25049
|
-
* }
|
|
25050
|
-
*/
|
|
25051
|
-
angular.scenario.Describe.prototype.getSpecs = function() {
|
|
25052
|
-
var specs = arguments[0] || [];
|
|
25053
|
-
angular.forEach(this.children, function(child) {
|
|
25054
|
-
child.getSpecs(specs);
|
|
25055
|
-
});
|
|
25056
|
-
angular.forEach(this.its, function(it) {
|
|
25057
|
-
specs.push(it);
|
|
25058
|
-
});
|
|
25059
|
-
var only = [];
|
|
25060
|
-
angular.forEach(specs, function(it) {
|
|
25061
|
-
if (it.only) {
|
|
25062
|
-
only.push(it);
|
|
25063
|
-
}
|
|
25064
|
-
});
|
|
25065
|
-
return (only.length && only) || specs;
|
|
25066
|
-
};
|
|
25067
|
-
|
|
25068
25230
|
/**
|
|
25069
25231
|
* Runner for scenarios
|
|
25070
25232
|
*
|
|
@@ -25635,13 +25797,13 @@ angular.scenario.dsl('binding', function() {
|
|
|
25635
25797
|
*/
|
|
25636
25798
|
angular.scenario.dsl('input', function() {
|
|
25637
25799
|
var chain = {};
|
|
25638
|
-
var supportInputEvent =
|
|
25800
|
+
var supportInputEvent = 'oninput' in document.createElement('div') && msie != 9;
|
|
25639
25801
|
|
|
25640
25802
|
chain.enter = function(value, event) {
|
|
25641
25803
|
return this.addFutureAction("input '" + this.name + "' enter '" + value + "'", function($window, $document, done) {
|
|
25642
25804
|
var input = $document.elements('[ng\\:model="$1"]', this.name).filter(':input');
|
|
25643
25805
|
input.val(value);
|
|
25644
|
-
input.trigger(event || supportInputEvent
|
|
25806
|
+
input.trigger(event || (supportInputEvent ? 'input' : 'change'));
|
|
25645
25807
|
done();
|
|
25646
25808
|
});
|
|
25647
25809
|
};
|
|
@@ -26108,7 +26270,7 @@ angular.scenario.output('xml', function(context, runner, model) {
|
|
|
26108
26270
|
if (step.error) {
|
|
26109
26271
|
var error = $('<error></error>');
|
|
26110
26272
|
stepContext.append(error);
|
|
26111
|
-
error.text(formatException(
|
|
26273
|
+
error.text(formatException(step.error));
|
|
26112
26274
|
}
|
|
26113
26275
|
});
|
|
26114
26276
|
});
|
|
@@ -26121,6 +26283,7 @@ angular.scenario.output('xml', function(context, runner, model) {
|
|
|
26121
26283
|
angular.scenario.output('object', function(context, runner, model) {
|
|
26122
26284
|
runner.$window.$result = model.value;
|
|
26123
26285
|
});
|
|
26286
|
+
|
|
26124
26287
|
bindJQuery();
|
|
26125
26288
|
publishExternalAPI(angular);
|
|
26126
26289
|
|
|
@@ -26144,4 +26307,4 @@ if (config.autotest) {
|
|
|
26144
26307
|
})(window, document);
|
|
26145
26308
|
|
|
26146
26309
|
angular.element(document).find('head').append('<style type="text/css">@charset "UTF-8";\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\n.ng-cloak, .x-ng-cloak {\n display: none;\n}\n\nng\\:form {\n display: block;\n}\n</style>');
|
|
26147
|
-
angular.element(document).find('head').append('<style type="text/css">@charset "UTF-8";\n/* CSS Document */\n\n/** Structure */\nbody {\n font-family: Arial, sans-serif;\n margin: 0;\n font-size: 14px;\n}\n\n#system-error {\n font-size: 1.5em;\n text-align: center;\n}\n\n#json, #xml {\n display: none;\n}\n\n#header {\n position: fixed;\n width: 100%;\n}\n\n#specs {\n padding-top: 50px;\n}\n\n#header .angular {\n font-family: Courier New, monospace;\n font-weight: bold;\n}\n\n#header h1 {\n font-weight: normal;\n float: left;\n font-size: 30px;\n line-height: 30px;\n margin: 0;\n padding: 10px 10px;\n height: 30px;\n}\n\n#application h2,\n#specs h2 {\n margin: 0;\n padding: 0.5em;\n font-size: 1.1em;\n}\n\n#status-legend {\n margin-top: 10px;\n margin-right: 10px;\n}\n\n#header,\n#application,\n.test-info,\n.test-actions li {\n overflow: hidden;\n}\n\n#application {\n margin: 10px;\n}\n\n#application iframe {\n width: 100%;\n height: 758px;\n}\n\n#application .popout {\n float: right;\n}\n\n#application iframe {\n border: none;\n}\n\n.tests li,\n.test-actions li,\n.test-it li,\n.test-it ol,\n.status-display {\n list-style-type: none;\n}\n\n.tests,\n.test-it ol,\n.status-display {\n margin: 0;\n padding: 0;\n}\n\n.test-info {\n margin-left: 1em;\n margin-top: 0.5em;\n border-radius: 8px 0 0 8px;\n -webkit-border-radius: 8px 0 0 8px;\n -moz-border-radius: 8px 0 0 8px;\n cursor: pointer;\n}\n\n.test-info:hover .test-name {\n text-decoration: underline;\n}\n\n.test-info .closed:before {\n content: \'\\25b8\\00A0\';\n}\n\n.test-info .open:before {\n content: \'\\25be\\00A0\';\n font-weight: bold;\n}\n\n.test-it ol {\n margin-left: 2.5em;\n}\n\n.status-display,\n.status-display li {\n float: right;\n}\n\n.status-display li {\n padding: 5px 10px;\n}\n\n.timer-result,\n.test-title {\n display: inline-block;\n margin: 0;\n padding: 4px;\n}\n\n.test-actions .test-title,\n.test-actions .test-result {\n display: table-cell;\n padding-left: 0.5em;\n padding-right: 0.5em;\n}\n\n.test-actions {\n display: table;\n}\n\n.test-actions li {\n display: table-row;\n}\n\n.timer-result {\n width: 4em;\n padding: 0 10px;\n text-align: right;\n font-family: monospace;\n}\n\n.test-it pre,\n.test-actions pre {\n clear: left;\n color: black;\n margin-left: 6em;\n}\n\n.test-describe {\n padding-bottom: 0.5em;\n}\n\n.test-describe .test-describe {\n margin: 5px 5px 10px 2em;\n}\n\n.test-actions .status-pending .test-title:before {\n content: \'\\00bb\\00A0\';\n}\n\n.scrollpane {\n max-height: 20em;\n overflow: auto;\n}\n\n/** Colors */\n\n#header {\n background-color: #F2C200;\n}\n\n#specs h2 {\n border-top: 2px solid #BABAD1;\n}\n\n#specs h2,\n#application h2 {\n background-color: #efefef;\n}\n\n#application {\n border: 1px solid #BABAD1;\n}\n\n.test-describe .test-describe {\n border-left: 1px solid #BABAD1;\n border-right: 1px solid #BABAD1;\n border-bottom: 1px solid #BABAD1;\n}\n\n.status-display {\n border: 1px solid #777;\n}\n\n.status-display .status-pending,\n.status-pending .test-info {\n background-color: #F9EEBC;\n}\n\n.status-display .status-success,\n.status-success .test-info {\n background-color: #B1D7A1;\n}\n\n.status-display .status-failure,\n.status-failure .test-info {\n background-color: #FF8286;\n}\n\n.status-display .status-error,\n.status-error .test-info {\n background-color: black;\n color: white;\n}\n\n.test-actions .status-success .test-title {\n color: #30B30A;\n}\n\n.test-actions .status-failure .test-title {\n color: #DF0000;\n}\n\n.test-actions .status-error .test-title {\n color: black;\n}\n\n.test-actions .timer-result {\n color: #888;\n}\n</style>');
|
|
26310
|
+
angular.element(document).find('head').append('<style type="text/css">@charset "UTF-8";\n/* CSS Document */\n\n/** Structure */\nbody {\n font-family: Arial, sans-serif;\n margin: 0;\n font-size: 14px;\n}\n\n#system-error {\n font-size: 1.5em;\n text-align: center;\n}\n\n#json, #xml {\n display: none;\n}\n\n#header {\n position: fixed;\n width: 100%;\n}\n\n#specs {\n padding-top: 50px;\n}\n\n#header .angular {\n font-family: Courier New, monospace;\n font-weight: bold;\n}\n\n#header h1 {\n font-weight: normal;\n float: left;\n font-size: 30px;\n line-height: 30px;\n margin: 0;\n padding: 10px 10px;\n height: 30px;\n}\n\n#application h2,\n#specs h2 {\n margin: 0;\n padding: 0.5em;\n font-size: 1.1em;\n}\n\n#status-legend {\n margin-top: 10px;\n margin-right: 10px;\n}\n\n#header,\n#application,\n.test-info,\n.test-actions li {\n overflow: hidden;\n}\n\n#application {\n margin: 10px;\n}\n\n#application iframe {\n width: 100%;\n height: 758px;\n}\n\n#application .popout {\n float: right;\n}\n\n#application iframe {\n border: none;\n}\n\n.tests li,\n.test-actions li,\n.test-it li,\n.test-it ol,\n.status-display {\n list-style-type: none;\n}\n\n.tests,\n.test-it ol,\n.status-display {\n margin: 0;\n padding: 0;\n}\n\n.test-info {\n margin-left: 1em;\n margin-top: 0.5em;\n border-radius: 8px 0 0 8px;\n -webkit-border-radius: 8px 0 0 8px;\n -moz-border-radius: 8px 0 0 8px;\n cursor: pointer;\n}\n\n.test-info:hover .test-name {\n text-decoration: underline;\n}\n\n.test-info .closed:before {\n content: \'\\25b8\\00A0\';\n}\n\n.test-info .open:before {\n content: \'\\25be\\00A0\';\n font-weight: bold;\n}\n\n.test-it ol {\n margin-left: 2.5em;\n}\n\n.status-display,\n.status-display li {\n float: right;\n}\n\n.status-display li {\n padding: 5px 10px;\n}\n\n.timer-result,\n.test-title {\n display: inline-block;\n margin: 0;\n padding: 4px;\n}\n\n.test-actions .test-title,\n.test-actions .test-result {\n display: table-cell;\n padding-left: 0.5em;\n padding-right: 0.5em;\n}\n\n.test-actions {\n display: table;\n}\n\n.test-actions li {\n display: table-row;\n}\n\n.timer-result {\n width: 4em;\n padding: 0 10px;\n text-align: right;\n font-family: monospace;\n}\n\n.test-it pre,\n.test-actions pre {\n clear: left;\n color: black;\n margin-left: 6em;\n}\n\n.test-describe {\n padding-bottom: 0.5em;\n}\n\n.test-describe .test-describe {\n margin: 5px 5px 10px 2em;\n}\n\n.test-actions .status-pending .test-title:before {\n content: \'\\00bb\\00A0\';\n}\n\n.scrollpane {\n max-height: 20em;\n overflow: auto;\n}\n\n/** Colors */\n\n#header {\n background-color: #F2C200;\n}\n\n#specs h2 {\n border-top: 2px solid #BABAD1;\n}\n\n#specs h2,\n#application h2 {\n background-color: #efefef;\n}\n\n#application {\n border: 1px solid #BABAD1;\n}\n\n.test-describe .test-describe {\n border-left: 1px solid #BABAD1;\n border-right: 1px solid #BABAD1;\n border-bottom: 1px solid #BABAD1;\n}\n\n.status-display {\n border: 1px solid #777;\n}\n\n.status-display .status-pending,\n.status-pending .test-info {\n background-color: #F9EEBC;\n}\n\n.status-display .status-success,\n.status-success .test-info {\n background-color: #B1D7A1;\n}\n\n.status-display .status-failure,\n.status-failure .test-info {\n background-color: #FF8286;\n}\n\n.status-display .status-error,\n.status-error .test-info {\n background-color: black;\n color: white;\n}\n\n.test-actions .status-success .test-title {\n color: #30B30A;\n}\n\n.test-actions .status-failure .test-title {\n color: #DF0000;\n}\n\n.test-actions .status-error .test-title {\n color: black;\n}\n\n.test-actions .timer-result {\n color: #888;\n}\n</style>');
|