angularjs-on-rails 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/javascripts/angular-animate.js +77 -21
- data/app/assets/javascripts/angular-cookies.js +17 -15
- data/app/assets/javascripts/angular-loader.js +2 -2
- data/app/assets/javascripts/angular-mocks.js +11 -3
- data/app/assets/javascripts/angular-resource.js +12 -12
- data/app/assets/javascripts/angular-route.js +2 -4
- data/app/assets/javascripts/angular-sanitize.js +40 -30
- data/app/assets/javascripts/angular-scenario.js +909 -744
- data/app/assets/javascripts/angular-touch.js +1 -1
- data/app/assets/javascripts/angular.js +908 -743
- data/lib/angularjs-on-rails/version.rb +1 -1
- data/lib/generators/angular/install/templates/index.html +0 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3cb4699d08b726e41a28f3719681f041dc10c230
|
4
|
+
data.tar.gz: b901dda615033812c74498b9a6642cf81e1c38cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e79bb84bc0f3a9f3914b0b069d67e5427df4c04529927393c7d9324ef214c03d763ede1074d36aeaa941007901d7ad66e57da77cb54815d52f20ffa646ffed8
|
7
|
+
data.tar.gz: a436a7f3ff30dfc33592491d1822a1722569799eefc412ed79575f2275a2c73e8aa57d1250a6a03a9dd6ea1e86bac1f2ed162930bf7b74cd0539664e55b8d204
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
## AngularJS on Rails [](http://badge.fury.io/rb/angularjs-on-rails)
|
2
2
|
|
3
|
-
wraps the [AngularJS 1.2.
|
3
|
+
wraps the [AngularJS 1.2.21](http://angularjs.org) library for use in [Rails 3.x](http://rubyonrails.org/) and above. This project is an application skeleton for a typical AngularJS web app. You can use it to quickly bootstrap your angular webapp projects.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.2.
|
2
|
+
* @license AngularJS v1.2.21
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -52,9 +52,9 @@
|
|
52
52
|
* }
|
53
53
|
*
|
54
54
|
* .slide.ng-enter { } /* starting animations for enter */
|
55
|
-
* .slide.ng-enter-active { } /* terminal animations for enter */
|
55
|
+
* .slide.ng-enter.ng-enter-active { } /* terminal animations for enter */
|
56
56
|
* .slide.ng-leave { } /* starting animations for leave */
|
57
|
-
* .slide.ng-leave-active { } /* terminal animations for leave */
|
57
|
+
* .slide.ng-leave.ng-leave-active { } /* terminal animations for leave */
|
58
58
|
* </style>
|
59
59
|
*
|
60
60
|
* <!--
|
@@ -64,8 +64,22 @@
|
|
64
64
|
* <ANY class="slide" ng-include="..."></ANY>
|
65
65
|
* ```
|
66
66
|
*
|
67
|
-
* Keep in mind that if an animation is running, any child elements cannot be animated
|
68
|
-
* animation has completed.
|
67
|
+
* Keep in mind that, by default, if an animation is running, any child elements cannot be animated
|
68
|
+
* until the parent element's animation has completed. This blocking feature can be overridden by
|
69
|
+
* placing the `ng-animate-children` attribute on a parent container tag.
|
70
|
+
*
|
71
|
+
* ```html
|
72
|
+
* <div class="slide-animation" ng-if="on" ng-animate-children>
|
73
|
+
* <div class="fade-animation" ng-if="on">
|
74
|
+
* <div class="explode-animation" ng-if="on">
|
75
|
+
* ...
|
76
|
+
* </div>
|
77
|
+
* </div>
|
78
|
+
* </div>
|
79
|
+
* ```
|
80
|
+
*
|
81
|
+
* When the `on` expression value changes and an animation is triggered then each of the elements within
|
82
|
+
* will all animate without the block being applied to child elements.
|
69
83
|
*
|
70
84
|
* <h2>CSS-defined Animations</h2>
|
71
85
|
* The animate service will automatically apply two CSS classes to the animated element and these two CSS classes
|
@@ -255,6 +269,19 @@ angular.module('ngAnimate', ['ng'])
|
|
255
269
|
* Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.
|
256
270
|
*
|
257
271
|
*/
|
272
|
+
.directive('ngAnimateChildren', function() {
|
273
|
+
var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';
|
274
|
+
return function(scope, element, attrs) {
|
275
|
+
var val = attrs.ngAnimateChildren;
|
276
|
+
if(angular.isString(val) && val.length === 0) { //empty attribute
|
277
|
+
element.data(NG_ANIMATE_CHILDREN, true);
|
278
|
+
} else {
|
279
|
+
scope.$watch(val, function(value) {
|
280
|
+
element.data(NG_ANIMATE_CHILDREN, !!value);
|
281
|
+
});
|
282
|
+
}
|
283
|
+
};
|
284
|
+
})
|
258
285
|
|
259
286
|
//this private service is only used within CSS-enabled animations
|
260
287
|
//IE8 + IE9 do not support rAF natively, but that is fine since they
|
@@ -283,6 +310,7 @@ angular.module('ngAnimate', ['ng'])
|
|
283
310
|
|
284
311
|
var ELEMENT_NODE = 1;
|
285
312
|
var NG_ANIMATE_STATE = '$$ngAnimateState';
|
313
|
+
var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren';
|
286
314
|
var NG_ANIMATE_CLASS_NAME = 'ng-animate';
|
287
315
|
var rootAnimateState = {running: true};
|
288
316
|
|
@@ -332,6 +360,12 @@ angular.module('ngAnimate', ['ng'])
|
|
332
360
|
return classNameFilter.test(className);
|
333
361
|
};
|
334
362
|
|
363
|
+
function blockElementAnimations(element) {
|
364
|
+
var data = element.data(NG_ANIMATE_STATE) || {};
|
365
|
+
data.running = true;
|
366
|
+
element.data(NG_ANIMATE_STATE, data);
|
367
|
+
}
|
368
|
+
|
335
369
|
function lookup(name) {
|
336
370
|
if (name) {
|
337
371
|
var matches = [],
|
@@ -558,7 +592,7 @@ angular.module('ngAnimate', ['ng'])
|
|
558
592
|
parentElement = prepareElement(parentElement);
|
559
593
|
afterElement = prepareElement(afterElement);
|
560
594
|
|
561
|
-
|
595
|
+
blockElementAnimations(element);
|
562
596
|
$delegate.enter(element, parentElement, afterElement);
|
563
597
|
$rootScope.$$postDigest(function() {
|
564
598
|
element = stripCommentsFromElement(element);
|
@@ -596,7 +630,7 @@ angular.module('ngAnimate', ['ng'])
|
|
596
630
|
leave : function(element, doneCallback) {
|
597
631
|
element = angular.element(element);
|
598
632
|
cancelChildAnimations(element);
|
599
|
-
|
633
|
+
blockElementAnimations(element);
|
600
634
|
$rootScope.$$postDigest(function() {
|
601
635
|
performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() {
|
602
636
|
$delegate.leave(element);
|
@@ -640,7 +674,7 @@ angular.module('ngAnimate', ['ng'])
|
|
640
674
|
afterElement = prepareElement(afterElement);
|
641
675
|
|
642
676
|
cancelChildAnimations(element);
|
643
|
-
|
677
|
+
blockElementAnimations(element);
|
644
678
|
$delegate.move(element, parentElement, afterElement);
|
645
679
|
$rootScope.$$postDigest(function() {
|
646
680
|
element = stripCommentsFromElement(element);
|
@@ -814,9 +848,12 @@ angular.module('ngAnimate', ['ng'])
|
|
814
848
|
|
815
849
|
//only allow animations if the currently running animation is not structural
|
816
850
|
//or if there is no animation running at all
|
817
|
-
var skipAnimations
|
818
|
-
|
819
|
-
|
851
|
+
var skipAnimations;
|
852
|
+
if (runner.isClassBased) {
|
853
|
+
skipAnimations = ngAnimateState.running ||
|
854
|
+
ngAnimateState.disabled ||
|
855
|
+
(lastAnimation && !lastAnimation.isClassBased);
|
856
|
+
}
|
820
857
|
|
821
858
|
//skip the animation if animations are disabled, a parent is already being animated,
|
822
859
|
//the element is not currently attached to the document body or then completely close
|
@@ -1033,30 +1070,49 @@ angular.module('ngAnimate', ['ng'])
|
|
1033
1070
|
}
|
1034
1071
|
|
1035
1072
|
function animationsDisabled(element, parentElement) {
|
1036
|
-
if (rootAnimateState.disabled)
|
1073
|
+
if (rootAnimateState.disabled) {
|
1074
|
+
return true;
|
1075
|
+
}
|
1037
1076
|
|
1038
|
-
if(isMatchingElement(element, $rootElement)) {
|
1039
|
-
return rootAnimateState.
|
1077
|
+
if (isMatchingElement(element, $rootElement)) {
|
1078
|
+
return rootAnimateState.running;
|
1040
1079
|
}
|
1041
1080
|
|
1081
|
+
var allowChildAnimations, parentRunningAnimation, hasParent;
|
1042
1082
|
do {
|
1043
1083
|
//the element did not reach the root element which means that it
|
1044
1084
|
//is not apart of the DOM. Therefore there is no reason to do
|
1045
1085
|
//any animations on it
|
1046
|
-
if(parentElement.length === 0) break;
|
1086
|
+
if (parentElement.length === 0) break;
|
1047
1087
|
|
1048
1088
|
var isRoot = isMatchingElement(parentElement, $rootElement);
|
1049
|
-
var state = isRoot ? rootAnimateState : parentElement.data(NG_ANIMATE_STATE);
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1089
|
+
var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {});
|
1090
|
+
if (state.disabled) {
|
1091
|
+
return true;
|
1092
|
+
}
|
1093
|
+
|
1094
|
+
//no matter what, for an animation to work it must reach the root element
|
1095
|
+
//this implies that the element is attached to the DOM when the animation is run
|
1096
|
+
if (isRoot) {
|
1097
|
+
hasParent = true;
|
1053
1098
|
}
|
1054
1099
|
|
1055
|
-
|
1100
|
+
//once a flag is found that is strictly false then everything before
|
1101
|
+
//it will be discarded and all child animations will be restricted
|
1102
|
+
if (allowChildAnimations !== false) {
|
1103
|
+
var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN);
|
1104
|
+
if(angular.isDefined(animateChildrenFlag)) {
|
1105
|
+
allowChildAnimations = animateChildrenFlag;
|
1106
|
+
}
|
1107
|
+
}
|
1108
|
+
|
1109
|
+
parentRunningAnimation = parentRunningAnimation ||
|
1110
|
+
state.running ||
|
1111
|
+
(state.last && !state.last.isClassBased);
|
1056
1112
|
}
|
1057
1113
|
while(parentElement = parentElement.parent());
|
1058
1114
|
|
1059
|
-
return
|
1115
|
+
return !hasParent || (!allowChildAnimations && parentRunningAnimation);
|
1060
1116
|
}
|
1061
1117
|
}]);
|
1062
1118
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.2.
|
2
|
+
* @license AngularJS v1.2.21
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -39,12 +39,13 @@ angular.module('ngCookies', ['ng']).
|
|
39
39
|
* @example
|
40
40
|
*
|
41
41
|
* ```js
|
42
|
-
*
|
43
|
-
*
|
44
|
-
*
|
45
|
-
*
|
46
|
-
*
|
47
|
-
*
|
42
|
+
* angular.module('cookiesExample', ['ngCookies'])
|
43
|
+
* .controller('ExampleController', ['$cookies', function($cookies) {
|
44
|
+
* // Retrieving a cookie
|
45
|
+
* var favoriteCookie = $cookies.myFavorite;
|
46
|
+
* // Setting a cookie
|
47
|
+
* $cookies.myFavorite = 'oatmeal';
|
48
|
+
* }]);
|
48
49
|
* ```
|
49
50
|
*/
|
50
51
|
factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
|
@@ -142,14 +143,15 @@ angular.module('ngCookies', ['ng']).
|
|
142
143
|
* @example
|
143
144
|
*
|
144
145
|
* ```js
|
145
|
-
*
|
146
|
-
*
|
147
|
-
*
|
148
|
-
*
|
149
|
-
*
|
150
|
-
*
|
151
|
-
*
|
152
|
-
*
|
146
|
+
* angular.module('cookieStoreExample', ['ngCookies'])
|
147
|
+
* .controller('ExampleController', ['$cookieStore', function($cookieStore) {
|
148
|
+
* // Put cookie
|
149
|
+
* $cookieStore.put('myFavorite','oatmeal');
|
150
|
+
* // Get cookie
|
151
|
+
* var favoriteCookie = $cookieStore.get('myFavorite');
|
152
|
+
* // Removing a cookie
|
153
|
+
* $cookieStore.remove('myFavorite');
|
154
|
+
* }]);
|
153
155
|
* ```
|
154
156
|
*/
|
155
157
|
factory('$cookieStore', ['$cookies', function($cookies) {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.2.
|
2
|
+
* @license AngularJS v1.2.21
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -69,7 +69,7 @@ function minErr(module) {
|
|
69
69
|
return match;
|
70
70
|
});
|
71
71
|
|
72
|
-
message = message + '\nhttp://errors.angularjs.org/1.2.
|
72
|
+
message = message + '\nhttp://errors.angularjs.org/1.2.21/' +
|
73
73
|
(module ? module + '/' : '') + code;
|
74
74
|
for (i = 2; i < arguments.length; i++) {
|
75
75
|
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.2.
|
2
|
+
* @license AngularJS v1.2.21
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -462,7 +462,7 @@ angular.mock.$IntervalProvider = function() {
|
|
462
462
|
iteration = 0,
|
463
463
|
skipApply = (angular.isDefined(invokeApply) && !invokeApply);
|
464
464
|
|
465
|
-
count = (angular.isDefined(count)) ? count : 0
|
465
|
+
count = (angular.isDefined(count)) ? count : 0;
|
466
466
|
promise.then(null, null, fn);
|
467
467
|
|
468
468
|
promise.$$intervalId = nextRepeatId;
|
@@ -1722,11 +1722,12 @@ angular.mock.$RootElementProvider = function() {
|
|
1722
1722
|
/**
|
1723
1723
|
* @ngdoc module
|
1724
1724
|
* @name ngMock
|
1725
|
+
* @packageName angular-mocks
|
1725
1726
|
* @description
|
1726
1727
|
*
|
1727
1728
|
* # ngMock
|
1728
1729
|
*
|
1729
|
-
* The `ngMock` module
|
1730
|
+
* The `ngMock` module provides support to inject and mock Angular services into unit tests.
|
1730
1731
|
* In addition, ngMock also extends various core ng services such that they can be
|
1731
1732
|
* inspected and controlled in a synchronous manner within test code.
|
1732
1733
|
*
|
@@ -1751,6 +1752,7 @@ angular.module('ngMock', ['ng']).provider({
|
|
1751
1752
|
* @ngdoc module
|
1752
1753
|
* @name ngMockE2E
|
1753
1754
|
* @module ngMockE2E
|
1755
|
+
* @packageName angular-mocks
|
1754
1756
|
* @description
|
1755
1757
|
*
|
1756
1758
|
* The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
|
@@ -1965,6 +1967,12 @@ if(window.jasmine || window.mocha) {
|
|
1965
1967
|
(window.afterEach || window.teardown)(function() {
|
1966
1968
|
var injector = currentSpec.$injector;
|
1967
1969
|
|
1970
|
+
angular.forEach(currentSpec.$modules, function(module) {
|
1971
|
+
if (module && module.$$hashKey) {
|
1972
|
+
module.$$hashKey = undefined;
|
1973
|
+
}
|
1974
|
+
});
|
1975
|
+
|
1968
1976
|
currentSpec.$injector = null;
|
1969
1977
|
currentSpec.$modules = null;
|
1970
1978
|
currentSpec = null;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.2.
|
2
|
+
* @license AngularJS v1.2.21
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -114,8 +114,8 @@ function shallowClearAndCopy(src, dst) {
|
|
114
114
|
*
|
115
115
|
* - **`action`** – {string} – The name of action. This name becomes the name of the method on
|
116
116
|
* your resource object.
|
117
|
-
* - **`method`** – {string} – HTTP
|
118
|
-
* `DELETE`,
|
117
|
+
* - **`method`** – {string} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`,
|
118
|
+
* `DELETE`, `JSONP`, etc).
|
119
119
|
* - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of
|
120
120
|
* the parameter value is a function, it will be executed every time when a param value needs to
|
121
121
|
* be obtained for a request (unless the param was overridden).
|
@@ -295,20 +295,20 @@ function shallowClearAndCopy(src, dst) {
|
|
295
295
|
* # Creating a custom 'PUT' request
|
296
296
|
* In this example we create a custom method on our resource to make a PUT request
|
297
297
|
* ```js
|
298
|
-
*
|
298
|
+
* var app = angular.module('app', ['ngResource', 'ngRoute']);
|
299
299
|
*
|
300
|
-
*
|
301
|
-
*
|
302
|
-
*
|
300
|
+
* // Some APIs expect a PUT request in the format URL/object/ID
|
301
|
+
* // Here we are creating an 'update' method
|
302
|
+
* app.factory('Notes', ['$resource', function($resource) {
|
303
303
|
* return $resource('/notes/:id', null,
|
304
304
|
* {
|
305
305
|
* 'update': { method:'PUT' }
|
306
306
|
* });
|
307
|
-
*
|
307
|
+
* }]);
|
308
308
|
*
|
309
|
-
*
|
310
|
-
*
|
311
|
-
*
|
309
|
+
* // In our controller we get the ID from the URL using ngRoute and $routeParams
|
310
|
+
* // We pass in $routeParams and our Notes factory along with $scope
|
311
|
+
* app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',
|
312
312
|
function($scope, $routeParams, Notes) {
|
313
313
|
* // First get a note object from the factory
|
314
314
|
* var note = Notes.get({ id:$routeParams.id });
|
@@ -318,7 +318,7 @@ function shallowClearAndCopy(src, dst) {
|
|
318
318
|
* Notes.update({ id:$id }, note);
|
319
319
|
*
|
320
320
|
* // This will PUT /notes/ID with the note object in the request payload
|
321
|
-
*
|
321
|
+
* }]);
|
322
322
|
* ```
|
323
323
|
*/
|
324
324
|
angular.module('ngResource', ['ng']).
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.2.
|
2
|
+
* @license AngularJS v1.2.21
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -473,9 +473,7 @@ function $RouteProvider(){
|
|
473
473
|
for (var i = 1, len = m.length; i < len; ++i) {
|
474
474
|
var key = keys[i - 1];
|
475
475
|
|
476
|
-
var val =
|
477
|
-
? decodeURIComponent(m[i])
|
478
|
-
: m[i];
|
476
|
+
var val = m[i];
|
479
477
|
|
480
478
|
if (key && val) {
|
481
479
|
params[key.name] = val;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.2.
|
2
|
+
* @license AngularJS v1.2.21
|
3
3
|
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
@@ -57,20 +57,21 @@ var $sanitizeMinErr = angular.$$minErr('$sanitize');
|
|
57
57
|
* @returns {string} Sanitized html.
|
58
58
|
*
|
59
59
|
* @example
|
60
|
-
<example module="
|
60
|
+
<example module="sanitizeExample" deps="angular-sanitize.js">
|
61
61
|
<file name="index.html">
|
62
62
|
<script>
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
angular.module('sanitizeExample', ['ngSanitize'])
|
64
|
+
.controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
|
65
|
+
$scope.snippet =
|
66
|
+
'<p style="color:blue">an html\n' +
|
67
|
+
'<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
|
68
|
+
'snippet</p>';
|
69
|
+
$scope.deliberatelyTrustDangerousSnippet = function() {
|
70
|
+
return $sce.trustAsHtml($scope.snippet);
|
71
|
+
};
|
72
|
+
}]);
|
72
73
|
</script>
|
73
|
-
<div ng-controller="
|
74
|
+
<div ng-controller="ExampleController">
|
74
75
|
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
|
75
76
|
<table>
|
76
77
|
<tr>
|
@@ -158,11 +159,11 @@ function sanitizeText(chars) {
|
|
158
159
|
|
159
160
|
// Regular Expressions for parsing tags and attributes
|
160
161
|
var START_TAG_REGEXP =
|
161
|
-
|
162
|
-
END_TAG_REGEXP =
|
162
|
+
/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,
|
163
|
+
END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/,
|
163
164
|
ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
|
164
165
|
BEGIN_TAG_REGEXP = /^</,
|
165
|
-
BEGING_END_TAGE_REGEXP =
|
166
|
+
BEGING_END_TAGE_REGEXP = /^<\//,
|
166
167
|
COMMENT_REGEXP = /<!--(.*?)-->/g,
|
167
168
|
DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
|
168
169
|
CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
|
@@ -236,10 +237,11 @@ function makeMap(str) {
|
|
236
237
|
* @param {object} handler
|
237
238
|
*/
|
238
239
|
function htmlParser( html, handler ) {
|
239
|
-
var index, chars, match, stack = [], last = html;
|
240
|
+
var index, chars, match, stack = [], last = html, text;
|
240
241
|
stack.last = function() { return stack[ stack.length - 1 ]; };
|
241
242
|
|
242
243
|
while ( html ) {
|
244
|
+
text = '';
|
243
245
|
chars = true;
|
244
246
|
|
245
247
|
// Make sure we're not in a script or style element
|
@@ -278,16 +280,23 @@ function htmlParser( html, handler ) {
|
|
278
280
|
match = html.match( START_TAG_REGEXP );
|
279
281
|
|
280
282
|
if ( match ) {
|
281
|
-
|
282
|
-
match[
|
283
|
+
// We only have a valid start-tag if there is a '>'.
|
284
|
+
if ( match[4] ) {
|
285
|
+
html = html.substring( match[0].length );
|
286
|
+
match[0].replace( START_TAG_REGEXP, parseStartTag );
|
287
|
+
}
|
283
288
|
chars = false;
|
289
|
+
} else {
|
290
|
+
// no ending tag found --- this piece should be encoded as an entity.
|
291
|
+
text += '<';
|
292
|
+
html = html.substring(1);
|
284
293
|
}
|
285
294
|
}
|
286
295
|
|
287
296
|
if ( chars ) {
|
288
297
|
index = html.indexOf("<");
|
289
298
|
|
290
|
-
|
299
|
+
text += index < 0 ? html : html.substring( 0, index );
|
291
300
|
html = index < 0 ? "" : html.substring( index );
|
292
301
|
|
293
302
|
if (handler.chars) handler.chars( decodeEntities(text) );
|
@@ -498,20 +507,21 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
|
|
498
507
|
<span ng-bind-html="linky_expression | linky"></span>
|
499
508
|
*
|
500
509
|
* @example
|
501
|
-
<example module="
|
510
|
+
<example module="linkyExample" deps="angular-sanitize.js">
|
502
511
|
<file name="index.html">
|
503
512
|
<script>
|
504
|
-
|
505
|
-
$scope
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
+
angular.module('linkyExample', ['ngSanitize'])
|
514
|
+
.controller('ExampleController', ['$scope', function($scope) {
|
515
|
+
$scope.snippet =
|
516
|
+
'Pretty text with some links:\n'+
|
517
|
+
'http://angularjs.org/,\n'+
|
518
|
+
'mailto:us@somewhere.org,\n'+
|
519
|
+
'another@somewhere.org,\n'+
|
520
|
+
'and one more: ftp://127.0.0.1/.';
|
521
|
+
$scope.snippetWithTarget = 'http://angularjs.org/';
|
522
|
+
}]);
|
513
523
|
</script>
|
514
|
-
<div ng-controller="
|
524
|
+
<div ng-controller="ExampleController">
|
515
525
|
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
|
516
526
|
<table>
|
517
527
|
<tr>
|