Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
60dd6849
Commit
60dd6849
authored
Aug 06, 2014
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
working on angular upgrade
parent
378e55ed
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
971 additions
and
593 deletions
+971
-593
src/app/app.js
+2
-2
src/app/components/require.config.js
+1
-3
src/app/controllers/graphiteTarget.js
+40
-27
src/app/partials/graphite/editor.html
+2
-2
src/vendor/angular/angular-route.js
+926
-0
src/vendor/angular/angular-sanitize.js
+0
-559
src/vendor/angular/angular.js
+0
-0
No files found.
src/app/app.js
View file @
60dd6849
...
...
@@ -8,7 +8,7 @@ define([
'require'
,
'config'
,
'bootstrap'
,
'angular-
sanitiz
e'
,
'angular-
rout
e'
,
'angular-strap'
,
'angular-dragdrop'
,
'extend-jquery'
,
...
...
@@ -61,8 +61,8 @@ function (angular, $, _, appLevelRequire, config) {
});
var
apps_deps
=
[
'ngRoute'
,
'$strap.directives'
,
'ngSanitize'
,
'ngDragDrop'
,
'grafana'
,
'pasvaz.bindonce'
...
...
src/app/components/require.config.js
View file @
60dd6849
...
...
@@ -14,9 +14,9 @@ require.config({
moment
:
'../vendor/moment'
,
filesaver
:
'../vendor/filesaver'
,
angular
:
'../vendor/angular/angular'
,
'angular-route'
:
'../vendor/angular/angular-route'
,
'angular-dragdrop'
:
'../vendor/angular/angular-dragdrop'
,
'angular-strap'
:
'../vendor/angular/angular-strap'
,
'angular-sanitize'
:
'../vendor/angular/angular-sanitize'
,
timepicker
:
'../vendor/angular/timepicker'
,
datepicker
:
'../vendor/angular/datepicker'
,
bindonce
:
'../vendor/angular/bindonce'
,
...
...
@@ -85,8 +85,6 @@ require.config({
'jquery.flot.stack'
:
[
'jquery'
,
'jquery.flot'
],
'jquery.flot.stackpercent'
:[
'jquery'
,
'jquery.flot'
],
'jquery.flot.time'
:
[
'jquery'
,
'jquery.flot'
],
'angular-sanitize'
:
[
'angular'
],
'angular-cookies'
:
[
'angular'
],
'angular-dragdrop'
:
[
'jquery'
,
'jquery-ui'
,
'angular'
],
'angular-loader'
:
[
'angular'
],
...
...
src/app/controllers/graphiteTarget.js
View file @
60dd6849
...
...
@@ -10,7 +10,7 @@ function (angular, _, config, gfunc, Parser) {
var
module
=
angular
.
module
(
'grafana.controllers'
);
module
.
controller
(
'GraphiteTargetCtrl'
,
function
(
$scope
)
{
module
.
controller
(
'GraphiteTargetCtrl'
,
function
(
$scope
,
$sce
)
{
$scope
.
init
=
function
()
{
$scope
.
target
.
target
=
$scope
.
target
.
target
||
''
;
...
...
@@ -90,19 +90,7 @@ function (angular, _, config, gfunc, Parser) {
}
$scope
.
segments
=
_
.
map
(
astNode
.
segments
,
function
(
segment
)
{
var
node
=
{
type
:
segment
.
type
,
val
:
segment
.
value
,
html
:
segment
.
value
};
if
(
segment
.
value
===
'*'
)
{
node
.
html
=
'<i class="icon-asterisk"><i>'
;
}
if
(
segment
.
type
===
'template'
)
{
node
.
val
=
node
.
html
=
'[['
+
segment
.
value
+
']]'
;
node
.
html
=
"<span style='color: #ECEC09'>"
+
node
.
html
+
"</span>"
;
}
return
node
;
return
new
MetricSegment
(
segment
);
});
}
}
...
...
@@ -111,13 +99,13 @@ function (angular, _, config, gfunc, Parser) {
var
arr
=
$scope
.
segments
.
slice
(
0
,
index
);
return
_
.
reduce
(
arr
,
function
(
result
,
segment
)
{
return
result
?
(
result
+
"."
+
segment
.
val
)
:
segment
.
val
;
return
result
?
(
result
+
"."
+
segment
.
val
ue
)
:
segment
.
value
;
},
""
);
}
function
checkOtherSegments
(
fromIndex
)
{
if
(
fromIndex
===
0
)
{
$scope
.
segments
.
push
(
{
html
:
'select metric'
}
);
$scope
.
segments
.
push
(
new
MetricSegment
(
'select metric'
)
);
return
;
}
...
...
@@ -126,12 +114,12 @@ function (angular, _, config, gfunc, Parser) {
.
then
(
function
(
segments
)
{
if
(
segments
.
length
===
0
)
{
$scope
.
segments
=
$scope
.
segments
.
splice
(
0
,
fromIndex
);
$scope
.
segments
.
push
(
{
html
:
'select metric'
}
);
$scope
.
segments
.
push
(
new
MetricSegment
(
'select metric'
)
);
return
;
}
if
(
segments
[
0
].
expandable
)
{
if
(
$scope
.
segments
.
length
===
fromIndex
)
{
$scope
.
segments
.
push
(
{
html
:
'select metric'
}
);
$scope
.
segments
.
push
(
new
MetricSegment
(
'select metric'
)
);
}
else
{
return
checkOtherSegments
(
fromIndex
+
1
);
...
...
@@ -161,21 +149,19 @@ function (angular, _, config, gfunc, Parser) {
return
$scope
.
datasource
.
metricFindQuery
(
$scope
.
filter
,
query
)
.
then
(
function
(
segments
)
{
_
.
each
(
segments
,
function
(
segment
)
{
segment
.
html
=
segment
.
val
=
segment
.
text
;
$scope
.
altSegments
=
_
.
map
(
segments
,
function
(
segment
)
{
return
new
MetricSegment
({
value
:
segment
.
text
,
expandable
:
segment
.
expandable
})
;
});
_
.
each
(
$scope
.
filter
.
templateParameters
,
function
(
templateParameter
)
{
segments
.
unshif
t
({
$scope
.
altSegments
.
unshift
(
new
MetricSegmen
t
({
type
:
'template'
,
html
:
'[['
+
templateParameter
.
name
+
']]'
,
val
:
'[['
+
templateParameter
.
name
+
']]'
,
value
:
'[['
+
templateParameter
.
name
+
']]'
,
expandable
:
true
,
});
})
)
;
});
segments
.
unshift
({
val
:
'*'
,
html
:
'<i class="icon-asterisk"></i>'
,
expandable
:
true
});
$scope
.
altSegments
=
segments
;
$scope
.
altSegments
.
unshift
(
new
MetricSegment
(
'*'
));
})
.
then
(
null
,
function
(
err
)
{
$scope
.
parserError
=
err
.
message
||
'Failed to issue metric query'
;
...
...
@@ -185,7 +171,7 @@ function (angular, _, config, gfunc, Parser) {
$scope
.
setSegment
=
function
(
altIndex
,
segmentIndex
)
{
delete
$scope
.
parserError
;
$scope
.
segments
[
segmentIndex
].
val
=
$scope
.
altSegments
[
altIndex
].
val
;
$scope
.
segments
[
segmentIndex
].
val
ue
=
$scope
.
altSegments
[
altIndex
].
value
;
$scope
.
segments
[
segmentIndex
].
html
=
$scope
.
altSegments
[
altIndex
].
html
;
if
(
$scope
.
functions
.
length
>
0
&&
$scope
.
functions
[
0
].
def
.
fake
)
{
...
...
@@ -284,6 +270,33 @@ function (angular, _, config, gfunc, Parser) {
$scope
.
panel
.
targets
.
push
(
clone
);
};
function
MetricSegment
(
options
)
{
if
(
options
===
'*'
||
options
.
value
===
'*'
)
{
this
.
value
=
'*'
;
this
.
html
=
$sce
.
trustAsHtml
(
'<i class="icon-asterisk"><i>'
);
this
.
expandable
=
true
;
return
;
}
if
(
_
.
isString
(
options
))
{
this
.
value
=
options
;
this
.
html
=
$sce
.
trustAsHtml
(
this
.
value
);
return
;
}
this
.
value
=
options
.
value
;
this
.
type
=
options
.
type
;
this
.
expandable
=
options
.
expandable
;
if
(
options
.
type
===
'template'
)
{
this
.
value
=
'[['
+
options
.
value
+
']]'
;
this
.
html
=
$sce
.
trustAsHtml
(
"<span style='color: #ECEC09'>"
+
this
.
value
+
"</span>"
);
}
else
{
this
.
html
=
$sce
.
trustAsHtml
(
this
.
value
);
}
}
});
module
.
directive
(
'focusMe'
,
function
(
$timeout
,
$parse
)
{
...
...
src/app/partials/graphite/editor.html
View file @
60dd6849
...
...
@@ -72,11 +72,11 @@
data-toggle=
"dropdown"
ng-click=
"getAltSegments($index)"
focus-me=
"segment.focus"
ng-bind-html
-unsafe
=
"segment.html"
>
ng-bind-html=
"segment.html"
>
</a>
<ul
class=
"dropdown-menu scrollable grafana-segment-dropdown-menu"
role=
"menu"
>
<li
ng-repeat=
"altSegment in altSegments"
role=
"menuitem"
>
<a
href=
"javascript:void(0)"
tabindex=
"1"
ng-click=
"setSegment($index, $parent.$index)"
ng-bind-html
-unsafe
=
"altSegment.html"
></a>
<a
href=
"javascript:void(0)"
tabindex=
"1"
ng-click=
"setSegment($index, $parent.$index)"
ng-bind-html=
"altSegment.html"
></a>
</li>
</ul>
</li>
...
...
src/vendor/angular/angular-route.js
0 → 100644
View file @
60dd6849
/**
* @license AngularJS v1.2.21
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
(
function
(
window
,
angular
,
undefined
)
{
'use strict'
;
/**
* @ngdoc module
* @name ngRoute
* @description
*
* # ngRoute
*
* The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
*
* ## Example
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
*
*
* <div doc-module-components="ngRoute"></div>
*/
/* global -ngRouteModule */
var
ngRouteModule
=
angular
.
module
(
'ngRoute'
,
[
'ng'
]).
provider
(
'$route'
,
$RouteProvider
);
/**
* @ngdoc provider
* @name $routeProvider
* @kind function
*
* @description
*
* Used for configuring routes.
*
* ## Example
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
*
* ## Dependencies
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*/
function
$RouteProvider
(){
function
inherit
(
parent
,
extra
)
{
return
angular
.
extend
(
new
(
angular
.
extend
(
function
()
{},
{
prototype
:
parent
}))(),
extra
);
}
var
routes
=
{};
/**
* @ngdoc method
* @name $routeProvider#when
*
* @param {string} path Route path (matched against `$location.path`). If `$location.path`
* contains redundant trailing slash or is missing one, the route will still match and the
* `$location.path` will be updated to add or drop the trailing slash to exactly match the
* route definition.
*
* * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
* to the next slash are matched and stored in `$routeParams` under the given `name`
* when the route matches.
* * `path` can contain named groups starting with a colon and ending with a star:
* e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
* when the route matches.
* * `path` can contain optional named groups with a question mark: e.g.`:name?`.
*
* For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
* `/color/brown/largecode/code/with/slashes/edit` and extract:
*
* * `color: brown`
* * `largecode: code/with/slashes`.
*
*
* @param {Object} route Mapping information to be assigned to `$route.current` on route
* match.
*
* Object properties:
*
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with
* newly created scope or the name of a {@link angular.Module#controller registered
* controller} if passed as a string.
* - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
* published to scope under the `controllerAs` name.
* - `template` – `{string=|function()=}` – html template as a string or a function that
* returns an html template as a string which should be used by {@link
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
* This property takes precedence over `templateUrl`.
*
* If `template` is a function, it will be called with the following parameters:
*
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
* template that should be used by {@link ngRoute.directive:ngView ngView}.
*
* If `templateUrl` is a function, it will be called with the following parameters:
*
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
* be injected into the controller. If any of these dependencies are promises, the router
* will wait for them all to be resolved or one to be rejected before the controller is
* instantiated.
* If all the promises are resolved successfully, the values of the resolved promises are
* injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
* fired. If any of the promises are rejected the
* {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object
* is:
*
* - `key` – `{string}`: a name of a dependency to be injected into the controller.
* - `factory` - `{string|function}`: If `string` then it is an alias for a service.
* Otherwise if function, then it is {@link auto.$injector#invoke injected}
* and the return value is treated as the dependency. If the result is a promise, it is
* resolved before its value is injected into the controller. Be aware that
* `ngRoute.$routeParams` will still refer to the previous route within these resolve
* functions. Use `$route.current.params` to access the new route parameters, instead.
*
* - `redirectTo` – {(string|function())=} – value to update
* {@link ng.$location $location} path with and trigger route redirection.
*
* If `redirectTo` is a function, it will be called with the following parameters:
*
* - `{Object.<string>}` - route parameters extracted from the current
* `$location.path()` by applying the current route templateUrl.
* - `{string}` - current `$location.path()`
* - `{Object}` - current `$location.search()`
*
* The custom `redirectTo` function is expected to return a string which will be used
* to update `$location.path()` and `$location.search()`.
*
* - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`
* or `$location.hash()` changes.
*
* If the option is set to `false` and url in the browser changes, then
* `$routeUpdate` event is broadcasted on the root scope.
*
* - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
*
* If the option is set to `true`, then the particular route can be matched without being
* case sensitive
*
* @returns {Object} self
*
* @description
* Adds a new route definition to the `$route` service.
*/
this
.
when
=
function
(
path
,
route
)
{
routes
[
path
]
=
angular
.
extend
(
{
reloadOnSearch
:
true
},
route
,
path
&&
pathRegExp
(
path
,
route
)
);
// create redirection for trailing slashes
if
(
path
)
{
var
redirectPath
=
(
path
[
path
.
length
-
1
]
==
'/'
)
?
path
.
substr
(
0
,
path
.
length
-
1
)
:
path
+
'/'
;
routes
[
redirectPath
]
=
angular
.
extend
(
{
redirectTo
:
path
},
pathRegExp
(
redirectPath
,
route
)
);
}
return
this
;
};
/**
* @param path {string} path
* @param opts {Object} options
* @return {?Object}
*
* @description
* Normalizes the given path, returning a regular expression
* and the original path.
*
* Inspired by pathRexp in visionmedia/express/lib/utils.js.
*/
function
pathRegExp
(
path
,
opts
)
{
var
insensitive
=
opts
.
caseInsensitiveMatch
,
ret
=
{
originalPath
:
path
,
regexp
:
path
},
keys
=
ret
.
keys
=
[];
path
=
path
.
replace
(
/
([
().
])
/g
,
'
\\
$1'
)
.
replace
(
/
(\/)?
:
(\w
+
)([\?\*])?
/g
,
function
(
_
,
slash
,
key
,
option
){
var
optional
=
option
===
'?'
?
option
:
null
;
var
star
=
option
===
'*'
?
option
:
null
;
keys
.
push
({
name
:
key
,
optional
:
!!
optional
});
slash
=
slash
||
''
;
return
''
+
(
optional
?
''
:
slash
)
+
'(?:'
+
(
optional
?
slash
:
''
)
+
(
star
&&
'(.+?)'
||
'([^/]+)'
)
+
(
optional
||
''
)
+
')'
+
(
optional
||
''
);
})
.
replace
(
/
([\/
$
\*])
/g
,
'
\\
$1'
);
ret
.
regexp
=
new
RegExp
(
'^'
+
path
+
'$'
,
insensitive
?
'i'
:
''
);
return
ret
;
}
/**
* @ngdoc method
* @name $routeProvider#otherwise
*
* @description
* Sets route definition that will be used on route change when no other route definition
* is matched.
*
* @param {Object} params Mapping information to be assigned to `$route.current`.
* @returns {Object} self
*/
this
.
otherwise
=
function
(
params
)
{
this
.
when
(
null
,
params
);
return
this
;
};
this
.
$get
=
[
'$rootScope'
,
'$location'
,
'$routeParams'
,
'$q'
,
'$injector'
,
'$http'
,
'$templateCache'
,
'$sce'
,
function
(
$rootScope
,
$location
,
$routeParams
,
$q
,
$injector
,
$http
,
$templateCache
,
$sce
)
{
/**
* @ngdoc service
* @name $route
* @requires $location
* @requires $routeParams
*
* @property {Object} current Reference to the current route definition.
* The route definition contains:
*
* - `controller`: The controller constructor as define in route definition.
* - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
* controller instantiation. The `locals` contain
* the resolved values of the `resolve` map. Additionally the `locals` also contain:
*
* - `$scope` - The current route scope.
* - `$template` - The current route template HTML.
*
* @property {Object} routes Object with all route configuration Objects as its properties.
*
* @description
* `$route` is used for deep-linking URLs to controllers and views (HTML partials).
* It watches `$location.url()` and tries to map the path to an existing route definition.
*
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*
* You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
*
* The `$route` service is typically used in conjunction with the
* {@link ngRoute.directive:ngView `ngView`} directive and the
* {@link ngRoute.$routeParams `$routeParams`} service.
*
* @example
* This example shows how changing the URL hash causes the `$route` to match a route against the
* URL, and the `ngView` pulls in the partial.
*
* Note that this example is using {@link ng.directive:script inlined templates}
* to get it working on jsfiddle as well.
*
* <example name="$route-service" module="ngRouteExample"
* deps="angular-route.js" fixBase="true">
* <file name="index.html">
* <div ng-controller="MainController">
* Choose:
* <a href="Book/Moby">Moby</a> |
* <a href="Book/Moby/ch/1">Moby: Ch1</a> |
* <a href="Book/Gatsby">Gatsby</a> |
* <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
* <a href="Book/Scarlet">Scarlet Letter</a><br/>
*
* <div ng-view></div>
*
* <hr />
*
* <pre>$location.path() = {{$location.path()}}</pre>
* <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
* <pre>$route.current.params = {{$route.current.params}}</pre>
* <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
* <pre>$routeParams = {{$routeParams}}</pre>
* </div>
* </file>
*
* <file name="book.html">
* controller: {{name}}<br />
* Book Id: {{params.bookId}}<br />
* </file>
*
* <file name="chapter.html">
* controller: {{name}}<br />
* Book Id: {{params.bookId}}<br />
* Chapter Id: {{params.chapterId}}
* </file>
*
* <file name="script.js">
* angular.module('ngRouteExample', ['ngRoute'])
*
* .controller('MainController', function($scope, $route, $routeParams, $location) {
* $scope.$route = $route;
* $scope.$location = $location;
* $scope.$routeParams = $routeParams;
* })
*
* .controller('BookController', function($scope, $routeParams) {
* $scope.name = "BookController";
* $scope.params = $routeParams;
* })
*
* .controller('ChapterController', function($scope, $routeParams) {
* $scope.name = "ChapterController";
* $scope.params = $routeParams;
* })
*
* .config(function($routeProvider, $locationProvider) {
* $routeProvider
* .when('/Book/:bookId', {
* templateUrl: 'book.html',
* controller: 'BookController',
* resolve: {
* // I will cause a 1 second delay
* delay: function($q, $timeout) {
* var delay = $q.defer();
* $timeout(delay.resolve, 1000);
* return delay.promise;
* }
* }
* })
* .when('/Book/:bookId/ch/:chapterId', {
* templateUrl: 'chapter.html',
* controller: 'ChapterController'
* });
*
* // configure html5 to get links working on jsfiddle
* $locationProvider.html5Mode(true);
* });
*
* </file>
*
* <file name="protractor.js" type="protractor">
* it('should load and compile correct template', function() {
* element(by.linkText('Moby: Ch1')).click();
* var content = element(by.css('[ng-view]')).getText();
* expect(content).toMatch(/controller\: ChapterController/);
* expect(content).toMatch(/Book Id\: Moby/);
* expect(content).toMatch(/Chapter Id\: 1/);
*
* element(by.partialLinkText('Scarlet')).click();
*
* content = element(by.css('[ng-view]')).getText();
* expect(content).toMatch(/controller\: BookController/);
* expect(content).toMatch(/Book Id\: Scarlet/);
* });
* </file>
* </example>
*/
/**
* @ngdoc event
* @name $route#$routeChangeStart
* @eventType broadcast on root scope
* @description
* Broadcasted before a route change. At this point the route services starts
* resolving all of the dependencies needed for the route change to occur.
* Typically this involves fetching the view template as well as any dependencies
* defined in `resolve` route property. Once all of the dependencies are resolved
* `$routeChangeSuccess` is fired.
*
* @param {Object} angularEvent Synthetic event object.
* @param {Route} next Future route information.
* @param {Route} current Current route information.
*/
/**
* @ngdoc event
* @name $route#$routeChangeSuccess
* @eventType broadcast on root scope
* @description
* Broadcasted after a route dependencies are resolved.
* {@link ngRoute.directive:ngView ngView} listens for the directive
* to instantiate the controller and render the view.
*
* @param {Object} angularEvent Synthetic event object.
* @param {Route} current Current route information.
* @param {Route|Undefined} previous Previous route information, or undefined if current is
* first route entered.
*/
/**
* @ngdoc event
* @name $route#$routeChangeError
* @eventType broadcast on root scope
* @description
* Broadcasted if any of the resolve promises are rejected.
*
* @param {Object} angularEvent Synthetic event object
* @param {Route} current Current route information.
* @param {Route} previous Previous route information.
* @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
*/
/**
* @ngdoc event
* @name $route#$routeUpdate
* @eventType broadcast on root scope
* @description
*
* The `reloadOnSearch` property has been set to false, and we are reusing the same
* instance of the Controller.
*/
var
forceReload
=
false
,
$route
=
{
routes
:
routes
,
/**
* @ngdoc method
* @name $route#reload
*
* @description
* Causes `$route` service to reload the current route even if
* {@link ng.$location $location} hasn't changed.
*
* As a result of that, {@link ngRoute.directive:ngView ngView}
* creates new scope, reinstantiates the controller.
*/
reload
:
function
()
{
forceReload
=
true
;
$rootScope
.
$evalAsync
(
updateRoute
);
}
};
$rootScope
.
$on
(
'$locationChangeSuccess'
,
updateRoute
);
return
$route
;
/////////////////////////////////////////////////////
/**
* @param on {string} current url
* @param route {Object} route regexp to match the url against
* @return {?Object}
*
* @description
* Check if the route matches the current url.
*
* Inspired by match in
* visionmedia/express/lib/router/router.js.
*/
function
switchRouteMatcher
(
on
,
route
)
{
var
keys
=
route
.
keys
,
params
=
{};
if
(
!
route
.
regexp
)
return
null
;
var
m
=
route
.
regexp
.
exec
(
on
);
if
(
!
m
)
return
null
;
for
(
var
i
=
1
,
len
=
m
.
length
;
i
<
len
;
++
i
)
{
var
key
=
keys
[
i
-
1
];
var
val
=
m
[
i
];
if
(
key
&&
val
)
{
params
[
key
.
name
]
=
val
;
}
}
return
params
;
}
function
updateRoute
()
{
var
next
=
parseRoute
(),
last
=
$route
.
current
;
if
(
next
&&
last
&&
next
.
$$route
===
last
.
$$route
&&
angular
.
equals
(
next
.
pathParams
,
last
.
pathParams
)
&&
!
next
.
reloadOnSearch
&&
!
forceReload
)
{
last
.
params
=
next
.
params
;
angular
.
copy
(
last
.
params
,
$routeParams
);
$rootScope
.
$broadcast
(
'$routeUpdate'
,
last
);
}
else
if
(
next
||
last
)
{
forceReload
=
false
;
$rootScope
.
$broadcast
(
'$routeChangeStart'
,
next
,
last
);
$route
.
current
=
next
;
if
(
next
)
{
if
(
next
.
redirectTo
)
{
if
(
angular
.
isString
(
next
.
redirectTo
))
{
$location
.
path
(
interpolate
(
next
.
redirectTo
,
next
.
params
)).
search
(
next
.
params
)
.
replace
();
}
else
{
$location
.
url
(
next
.
redirectTo
(
next
.
pathParams
,
$location
.
path
(),
$location
.
search
()))
.
replace
();
}
}
}
$q
.
when
(
next
).
then
(
function
()
{
if
(
next
)
{
var
locals
=
angular
.
extend
({},
next
.
resolve
),
template
,
templateUrl
;
angular
.
forEach
(
locals
,
function
(
value
,
key
)
{
locals
[
key
]
=
angular
.
isString
(
value
)
?
$injector
.
get
(
value
)
:
$injector
.
invoke
(
value
);
});
if
(
angular
.
isDefined
(
template
=
next
.
template
))
{
if
(
angular
.
isFunction
(
template
))
{
template
=
template
(
next
.
params
);
}
}
else
if
(
angular
.
isDefined
(
templateUrl
=
next
.
templateUrl
))
{
if
(
angular
.
isFunction
(
templateUrl
))
{
templateUrl
=
templateUrl
(
next
.
params
);
}
templateUrl
=
$sce
.
getTrustedResourceUrl
(
templateUrl
);
if
(
angular
.
isDefined
(
templateUrl
))
{
next
.
loadedTemplateUrl
=
templateUrl
;
template
=
$http
.
get
(
templateUrl
,
{
cache
:
$templateCache
}).
then
(
function
(
response
)
{
return
response
.
data
;
});
}
}
if
(
angular
.
isDefined
(
template
))
{
locals
[
'$template'
]
=
template
;
}
return
$q
.
all
(
locals
);
}
}).
// after route change
then
(
function
(
locals
)
{
if
(
next
==
$route
.
current
)
{
if
(
next
)
{
next
.
locals
=
locals
;
angular
.
copy
(
next
.
params
,
$routeParams
);
}
$rootScope
.
$broadcast
(
'$routeChangeSuccess'
,
next
,
last
);
}
},
function
(
error
)
{
if
(
next
==
$route
.
current
)
{
$rootScope
.
$broadcast
(
'$routeChangeError'
,
next
,
last
,
error
);
}
});
}
}
/**
* @returns {Object} the current active route, by matching it against the URL
*/
function
parseRoute
()
{
// Match a route
var
params
,
match
;
angular
.
forEach
(
routes
,
function
(
route
,
path
)
{
if
(
!
match
&&
(
params
=
switchRouteMatcher
(
$location
.
path
(),
route
)))
{
match
=
inherit
(
route
,
{
params
:
angular
.
extend
({},
$location
.
search
(),
params
),
pathParams
:
params
});
match
.
$$route
=
route
;
}
});
// No route matched; fallback to "otherwise" route
return
match
||
routes
[
null
]
&&
inherit
(
routes
[
null
],
{
params
:
{},
pathParams
:{}});
}
/**
* @returns {string} interpolation of the redirect path with the parameters
*/
function
interpolate
(
string
,
params
)
{
var
result
=
[];
angular
.
forEach
((
string
||
''
).
split
(
':'
),
function
(
segment
,
i
)
{
if
(
i
===
0
)
{
result
.
push
(
segment
);
}
else
{
var
segmentMatch
=
segment
.
match
(
/
(\w
+
)(
.*
)
/
);
var
key
=
segmentMatch
[
1
];
result
.
push
(
params
[
key
]);
result
.
push
(
segmentMatch
[
2
]
||
''
);
delete
params
[
key
];
}
});
return
result
.
join
(
''
);
}
}];
}
ngRouteModule
.
provider
(
'$routeParams'
,
$RouteParamsProvider
);
/**
* @ngdoc service
* @name $routeParams
* @requires $route
*
* @description
* The `$routeParams` service allows you to retrieve the current set of route parameters.
*
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*
* The route parameters are a combination of {@link ng.$location `$location`}'s
* {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.
* The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
*
* In case of parameter name collision, `path` params take precedence over `search` params.
*
* The service guarantees that the identity of the `$routeParams` object will remain unchanged
* (but its properties will likely change) even when a route change occurs.
*
* Note that the `$routeParams` are only updated *after* a route change completes successfully.
* This means that you cannot rely on `$routeParams` being correct in route resolve functions.
* Instead you can use `$route.current.params` to access the new route's parameters.
*
* @example
* ```js
* // Given:
* // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
* // Route: /Chapter/:chapterId/Section/:sectionId
* //
* // Then
* $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
* ```
*/
function
$RouteParamsProvider
()
{
this
.
$get
=
function
()
{
return
{};
};
}
ngRouteModule
.
directive
(
'ngView'
,
ngViewFactory
);
ngRouteModule
.
directive
(
'ngView'
,
ngViewFillContentFactory
);
/**
* @ngdoc directive
* @name ngView
* @restrict ECA
*
* @description
* # Overview
* `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
* including the rendered template of the current route into the main layout (`index.html`) file.
* Every time the current route changes, the included view changes with it according to the
* configuration of the `$route` service.
*
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*
* @animations
* enter - animation is used to bring new content into the browser.
* leave - animation is used to animate existing content away.
*
* The enter and leave animation occur concurrently.
*
* @scope
* @priority 400
* @param {string=} onload Expression to evaluate whenever the view updates.
*
* @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
* $anchorScroll} to scroll the viewport after the view is updated.
*
* - If the attribute is not set, disable scrolling.
* - If the attribute is set without value, enable scrolling.
* - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
* as an expression yields a truthy value.
* @example
<example name="ngView-directive" module="ngViewExample"
deps="angular-route.js;angular-animate.js"
animations="true" fixBase="true">
<file name="index.html">
<div ng-controller="MainCtrl as main">
Choose:
<a href="Book/Moby">Moby</a> |
<a href="Book/Moby/ch/1">Moby: Ch1</a> |
<a href="Book/Gatsby">Gatsby</a> |
<a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
<a href="Book/Scarlet">Scarlet Letter</a><br/>
<div class="view-animate-container">
<div ng-view class="view-animate"></div>
</div>
<hr />
<pre>$location.path() = {{main.$location.path()}}</pre>
<pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
<pre>$route.current.params = {{main.$route.current.params}}</pre>
<pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre>
<pre>$routeParams = {{main.$routeParams}}</pre>
</div>
</file>
<file name="book.html">
<div>
controller: {{book.name}}<br />
Book Id: {{book.params.bookId}}<br />
</div>
</file>
<file name="chapter.html">
<div>
controller: {{chapter.name}}<br />
Book Id: {{chapter.params.bookId}}<br />
Chapter Id: {{chapter.params.chapterId}}
</div>
</file>
<file name="animations.css">
.view-animate-container {
position:relative;
height:100px!important;
position:relative;
background:white;
border:1px solid black;
height:40px;
overflow:hidden;
}
.view-animate {
padding:10px;
}
.view-animate.ng-enter, .view-animate.ng-leave {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
display:block;
width:100%;
border-left:1px solid black;
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
padding:10px;
}
.view-animate.ng-enter {
left:100%;
}
.view-animate.ng-enter.ng-enter-active {
left:0;
}
.view-animate.ng-leave.ng-leave-active {
left:-100%;
}
</file>
<file name="script.js">
angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider
.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: 'BookCtrl',
controllerAs: 'book'
})
.when('/Book/:bookId/ch/:chapterId', {
templateUrl: 'chapter.html',
controller: 'ChapterCtrl',
controllerAs: 'chapter'
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
}])
.controller('MainCtrl', ['$route', '$routeParams', '$location',
function($route, $routeParams, $location) {
this.$route = $route;
this.$location = $location;
this.$routeParams = $routeParams;
}])
.controller('BookCtrl', ['$routeParams', function($routeParams) {
this.name = "BookCtrl";
this.params = $routeParams;
}])
.controller('ChapterCtrl', ['$routeParams', function($routeParams) {
this.name = "ChapterCtrl";
this.params = $routeParams;
}]);
</file>
<file name="protractor.js" type="protractor">
it('should load and compile correct template', function() {
element(by.linkText('Moby: Ch1')).click();
var content = element(by.css('[ng-view]')).getText();
expect(content).toMatch(/controller\: ChapterCtrl/);
expect(content).toMatch(/Book Id\: Moby/);
expect(content).toMatch(/Chapter Id\: 1/);
element(by.partialLinkText('Scarlet')).click();
content = element(by.css('[ng-view]')).getText();
expect(content).toMatch(/controller\: BookCtrl/);
expect(content).toMatch(/Book Id\: Scarlet/);
});
</file>
</example>
*/
/**
* @ngdoc event
* @name ngView#$viewContentLoaded
* @eventType emit on the current ngView scope
* @description
* Emitted every time the ngView content is reloaded.
*/
ngViewFactory
.
$inject
=
[
'$route'
,
'$anchorScroll'
,
'$animate'
];
function
ngViewFactory
(
$route
,
$anchorScroll
,
$animate
)
{
return
{
restrict
:
'ECA'
,
terminal
:
true
,
priority
:
400
,
transclude
:
'element'
,
link
:
function
(
scope
,
$element
,
attr
,
ctrl
,
$transclude
)
{
var
currentScope
,
currentElement
,
previousElement
,
autoScrollExp
=
attr
.
autoscroll
,
onloadExp
=
attr
.
onload
||
''
;
scope
.
$on
(
'$routeChangeSuccess'
,
update
);
update
();
function
cleanupLastView
()
{
if
(
previousElement
)
{
previousElement
.
remove
();
previousElement
=
null
;
}
if
(
currentScope
)
{
currentScope
.
$destroy
();
currentScope
=
null
;
}
if
(
currentElement
)
{
$animate
.
leave
(
currentElement
,
function
()
{
previousElement
=
null
;
});
previousElement
=
currentElement
;
currentElement
=
null
;
}
}
function
update
()
{
var
locals
=
$route
.
current
&&
$route
.
current
.
locals
,
template
=
locals
&&
locals
.
$template
;
if
(
angular
.
isDefined
(
template
))
{
var
newScope
=
scope
.
$new
();
var
current
=
$route
.
current
;
// Note: This will also link all children of ng-view that were contained in the original
// html. If that content contains controllers, ... they could pollute/change the scope.
// However, using ng-view on an element with additional content does not make sense...
// Note: We can't remove them in the cloneAttchFn of $transclude as that
// function is called before linking the content, which would apply child
// directives to non existing elements.
var
clone
=
$transclude
(
newScope
,
function
(
clone
)
{
$animate
.
enter
(
clone
,
null
,
currentElement
||
$element
,
function
onNgViewEnter
()
{
if
(
angular
.
isDefined
(
autoScrollExp
)
&&
(
!
autoScrollExp
||
scope
.
$eval
(
autoScrollExp
)))
{
$anchorScroll
();
}
});
cleanupLastView
();
});
currentElement
=
clone
;
currentScope
=
current
.
scope
=
newScope
;
currentScope
.
$emit
(
'$viewContentLoaded'
);
currentScope
.
$eval
(
onloadExp
);
}
else
{
cleanupLastView
();
}
}
}
};
}
// This directive is called during the $transclude call of the first `ngView` directive.
// It will replace and compile the content of the element with the loaded template.
// We need this directive so that the element content is already filled when
// the link function of another directive on the same element as ngView
// is called.
ngViewFillContentFactory
.
$inject
=
[
'$compile'
,
'$controller'
,
'$route'
];
function
ngViewFillContentFactory
(
$compile
,
$controller
,
$route
)
{
return
{
restrict
:
'ECA'
,
priority
:
-
400
,
link
:
function
(
scope
,
$element
)
{
var
current
=
$route
.
current
,
locals
=
current
.
locals
;
$element
.
html
(
locals
.
$template
);
var
link
=
$compile
(
$element
.
contents
());
if
(
current
.
controller
)
{
locals
.
$scope
=
scope
;
var
controller
=
$controller
(
current
.
controller
,
locals
);
if
(
current
.
controllerAs
)
{
scope
[
current
.
controllerAs
]
=
controller
;
}
$element
.
data
(
'$ngControllerController'
,
controller
);
$element
.
children
().
data
(
'$ngControllerController'
,
controller
);
}
link
(
scope
);
}
};
}
})(
window
,
window
.
angular
);
\ No newline at end of file
src/vendor/angular/angular-sanitize.js
deleted
100644 → 0
View file @
378e55ed
/**
* @license AngularJS v1.1.5
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(
function
(
window
,
angular
,
undefined
)
{
'use strict'
;
/**
* @ngdoc overview
* @name ngSanitize
* @description
*/
/*
* HTML Parser By Misko Hevery (misko@hevery.com)
* based on: HTML Parser By John Resig (ejohn.org)
* Original code by Erik Arvidsson, Mozilla Public License
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
*
* // Use like so:
* htmlParser(htmlString, {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* });
*
*/
/**
* @ngdoc service
* @name ngSanitize.$sanitize
* @function
*
* @description
* The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
* then serialized back to properly escaped html string. This means that no unsafe input can make
* it into the returned string, however, since our parser is more strict than a typical browser
* parser, it's possible that some obscure input, which would be recognized as valid HTML by a
* browser, won't make it through the sanitizer.
*
* @param {string} html Html input.
* @returns {string} Sanitized html.
*
* @example
<doc:example module="ngSanitize">
<doc:source>
<script>
function Ctrl($scope) {
$scope.snippet =
'<p style="color:blue">an html\n' +
'<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
'snippet</p>';
}
</script>
<div ng-controller="Ctrl">
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
<table>
<tr>
<td>Filter</td>
<td>Source</td>
<td>Rendered</td>
</tr>
<tr id="html-filter">
<td>html filter</td>
<td>
<pre><div ng-bind-html="snippet"><br/></div></pre>
</td>
<td>
<div ng-bind-html="snippet"></div>
</td>
</tr>
<tr id="escaped-html">
<td>no filter</td>
<td><pre><div ng-bind="snippet"><br/></div></pre></td>
<td><div ng-bind="snippet"></div></td>
</tr>
<tr id="html-unsafe-filter">
<td>unsafe html filter</td>
<td><pre><div ng-bind-html-unsafe="snippet"><br/></div></pre></td>
<td><div ng-bind-html-unsafe="snippet"></div></td>
</tr>
</table>
</div>
</doc:source>
<doc:scenario>
it('should sanitize the html snippet ', function() {
expect(using('#html-filter').element('div').html()).
toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
});
it('should escape snippet without any filter', function() {
expect(using('#escaped-html').element('div').html()).
toBe("<p style=\"color:blue\">an html\n" +
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
"snippet</p>");
});
it('should inline raw snippet if filtered as unsafe', function() {
expect(using('#html-unsafe-filter').element("div").html()).
toBe("<p style=\"color:blue\">an html\n" +
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
"snippet</p>");
});
it('should update', function() {
input('snippet').enter('new <b>text</b>');
expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');
expect(using('#escaped-html').element('div').html()).toBe("new <b>text</b>");
expect(using('#html-unsafe-filter').binding("snippet")).toBe('new <b>text</b>');
});
</doc:scenario>
</doc:example>
*/
var
$sanitize
=
function
(
html
)
{
var
buf
=
[];
htmlParser
(
html
,
htmlSanitizeWriter
(
buf
));
return
buf
.
join
(
''
);
};
// Regular Expressions for parsing tags and attributes
var
START_TAG_REGEXP
=
/^<
\s
*
([\w
:-
]
+
)((?:\s
+
[\w
:-
]
+
(?:\s
*=
\s
*
(?:(?:
"
[^
"
]
*"
)
|
(?:
'
[^
'
]
*'
)
|
[^
>
\s]
+
))?)
*
)\s
*
(\/?)\s
*>/
,
END_TAG_REGEXP
=
/^<
\s
*
\/\s
*
([\w
:-
]
+
)[^
>
]
*>/
,
ATTR_REGEXP
=
/
([\w
:-
]
+
)(?:\s
*=
\s
*
(?:(?:
"
((?:[^
"
])
*
)
"
)
|
(?:
'
((?:[^
'
])
*
)
'
)
|
([^
>
\s]
+
)))?
/g
,
BEGIN_TAG_REGEXP
=
/^</
,
BEGING_END_TAGE_REGEXP
=
/^<
\s
*
\/
/
,
COMMENT_REGEXP
=
/<!--
(
.*
?)
-->/g
,
CDATA_REGEXP
=
/<!
\[
CDATA
\[(
.*
?)
]]>/g
,
URI_REGEXP
=
/^
((
ftp|https
?)
:
\/\/
|mailto:|tel:|#
)
/
,
NON_ALPHANUMERIC_REGEXP
=
/
([^\#
-~| |!
])
/g
;
// Match everything outside of normal chars and " (quote character)
// Good source of info about elements and attributes
// http://dev.w3.org/html5/spec/Overview.html#semantics
// http://simon.html5.org/html-elements
// Safe Void Elements - HTML5
// http://dev.w3.org/html5/spec/Overview.html#void-elements
var
voidElements
=
makeMap
(
"area,br,col,hr,img,wbr"
);
// Elements that you can, intentionally, leave open (and which close themselves)
// http://dev.w3.org/html5/spec/Overview.html#optional-tags
var
optionalEndTagBlockElements
=
makeMap
(
"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"
),
optionalEndTagInlineElements
=
makeMap
(
"rp,rt"
),
optionalEndTagElements
=
angular
.
extend
({},
optionalEndTagInlineElements
,
optionalEndTagBlockElements
);
// Safe Block Elements - HTML5
var
blockElements
=
angular
.
extend
({},
optionalEndTagBlockElements
,
makeMap
(
"address,article,aside,"
+
"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,"
+
"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"
));
// Inline Elements - HTML5
var
inlineElements
=
angular
.
extend
({},
optionalEndTagInlineElements
,
makeMap
(
"a,abbr,acronym,b,bdi,bdo,"
+
"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,"
+
"span,strike,strong,sub,sup,time,tt,u,var"
));
// Special Elements (can contain anything)
var
specialElements
=
makeMap
(
"script,style"
);
var
validElements
=
angular
.
extend
({},
voidElements
,
blockElements
,
inlineElements
,
optionalEndTagElements
);
//Attributes that have href and hence need to be sanitized
var
uriAttrs
=
makeMap
(
"background,cite,href,longdesc,src,usemap"
);
var
validAttrs
=
angular
.
extend
({},
uriAttrs
,
makeMap
(
'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'
+
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'
+
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'
+
'scope,scrolling,shape,span,start,summary,target,title,type,'
+
'valign,value,vspace,width'
));
function
makeMap
(
str
)
{
var
obj
=
{},
items
=
str
.
split
(
','
),
i
;
for
(
i
=
0
;
i
<
items
.
length
;
i
++
)
obj
[
items
[
i
]]
=
true
;
return
obj
;
}
/**
* @example
* htmlParser(htmlString, {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* });
*
* @param {string} html string
* @param {object} handler
*/
function
htmlParser
(
html
,
handler
)
{
var
index
,
chars
,
match
,
stack
=
[],
last
=
html
;
stack
.
last
=
function
()
{
return
stack
[
stack
.
length
-
1
];
};
while
(
html
)
{
chars
=
true
;
// Make sure we're not in a script or style element
if
(
!
stack
.
last
()
||
!
specialElements
[
stack
.
last
()
]
)
{
// Comment
if
(
html
.
indexOf
(
"<!--"
)
===
0
)
{
index
=
html
.
indexOf
(
"-->"
);
if
(
index
>=
0
)
{
if
(
handler
.
comment
)
handler
.
comment
(
html
.
substring
(
4
,
index
)
);
html
=
html
.
substring
(
index
+
3
);
chars
=
false
;
}
// end tag
}
else
if
(
BEGING_END_TAGE_REGEXP
.
test
(
html
)
)
{
match
=
html
.
match
(
END_TAG_REGEXP
);
if
(
match
)
{
html
=
html
.
substring
(
match
[
0
].
length
);
match
[
0
].
replace
(
END_TAG_REGEXP
,
parseEndTag
);
chars
=
false
;
}
// start tag
}
else
if
(
BEGIN_TAG_REGEXP
.
test
(
html
)
)
{
match
=
html
.
match
(
START_TAG_REGEXP
);
if
(
match
)
{
html
=
html
.
substring
(
match
[
0
].
length
);
match
[
0
].
replace
(
START_TAG_REGEXP
,
parseStartTag
);
chars
=
false
;
}
}
if
(
chars
)
{
index
=
html
.
indexOf
(
"<"
);
var
text
=
index
<
0
?
html
:
html
.
substring
(
0
,
index
);
html
=
index
<
0
?
""
:
html
.
substring
(
index
);
if
(
handler
.
chars
)
handler
.
chars
(
decodeEntities
(
text
)
);
}
}
else
{
html
=
html
.
replace
(
new
RegExp
(
"(.*)<
\\
s*
\\
/
\\
s*"
+
stack
.
last
()
+
"[^>]*>"
,
'i'
),
function
(
all
,
text
){
text
=
text
.
replace
(
COMMENT_REGEXP
,
"$1"
).
replace
(
CDATA_REGEXP
,
"$1"
);
if
(
handler
.
chars
)
handler
.
chars
(
decodeEntities
(
text
)
);
return
""
;
});
parseEndTag
(
""
,
stack
.
last
()
);
}
if
(
html
==
last
)
{
throw
"Parse Error: "
+
html
;
}
last
=
html
;
}
// Clean up any remaining tags
parseEndTag
();
function
parseStartTag
(
tag
,
tagName
,
rest
,
unary
)
{
tagName
=
angular
.
lowercase
(
tagName
);
if
(
blockElements
[
tagName
]
)
{
while
(
stack
.
last
()
&&
inlineElements
[
stack
.
last
()
]
)
{
parseEndTag
(
""
,
stack
.
last
()
);
}
}
if
(
optionalEndTagElements
[
tagName
]
&&
stack
.
last
()
==
tagName
)
{
parseEndTag
(
""
,
tagName
);
}
unary
=
voidElements
[
tagName
]
||
!!
unary
;
if
(
!
unary
)
stack
.
push
(
tagName
);
var
attrs
=
{};
rest
.
replace
(
ATTR_REGEXP
,
function
(
match
,
name
,
doubleQuotedValue
,
singleQoutedValue
,
unqoutedValue
)
{
var
value
=
doubleQuotedValue
||
singleQoutedValue
||
unqoutedValue
||
''
;
attrs
[
name
]
=
decodeEntities
(
value
);
});
if
(
handler
.
start
)
handler
.
start
(
tagName
,
attrs
,
unary
);
}
function
parseEndTag
(
tag
,
tagName
)
{
var
pos
=
0
,
i
;
tagName
=
angular
.
lowercase
(
tagName
);
if
(
tagName
)
// Find the closest opened tag of the same type
for
(
pos
=
stack
.
length
-
1
;
pos
>=
0
;
pos
--
)
if
(
stack
[
pos
]
==
tagName
)
break
;
if
(
pos
>=
0
)
{
// Close all the open elements, up the stack
for
(
i
=
stack
.
length
-
1
;
i
>=
pos
;
i
--
)
if
(
handler
.
end
)
handler
.
end
(
stack
[
i
]
);
// Remove the open elements from the stack
stack
.
length
=
pos
;
}
}
}
/**
* decodes all entities into regular string
* @param value
* @returns {string} A string with decoded entities.
*/
var
hiddenPre
=
document
.
createElement
(
"pre"
);
function
decodeEntities
(
value
)
{
hiddenPre
.
innerHTML
=
value
.
replace
(
/</g
,
"<"
);
return
hiddenPre
.
innerText
||
hiddenPre
.
textContent
||
''
;
}
/**
* Escapes all potentially dangerous characters, so that the
* resulting string can be safely inserted into attribute or
* element text.
* @param value
* @returns escaped text
*/
function
encodeEntities
(
value
)
{
return
value
.
replace
(
/&/g
,
'&'
).
replace
(
NON_ALPHANUMERIC_REGEXP
,
function
(
value
){
return
'&#'
+
value
.
charCodeAt
(
0
)
+
';'
;
}).
replace
(
/</g
,
'<'
).
replace
(
/>/g
,
'>'
);
}
/**
* create an HTML/XML writer which writes to buffer
* @param {Array} buf use buf.jain('') to get out sanitized html string
* @returns {object} in the form of {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* }
*/
function
htmlSanitizeWriter
(
buf
){
var
ignore
=
false
;
var
out
=
angular
.
bind
(
buf
,
buf
.
push
);
return
{
start
:
function
(
tag
,
attrs
,
unary
){
tag
=
angular
.
lowercase
(
tag
);
if
(
!
ignore
&&
specialElements
[
tag
])
{
ignore
=
tag
;
}
if
(
!
ignore
&&
validElements
[
tag
]
==
true
)
{
out
(
'<'
);
out
(
tag
);
angular
.
forEach
(
attrs
,
function
(
value
,
key
){
var
lkey
=
angular
.
lowercase
(
key
);
if
(
validAttrs
[
lkey
]
==
true
&&
(
uriAttrs
[
lkey
]
!==
true
||
value
.
match
(
URI_REGEXP
)))
{
out
(
' '
);
out
(
key
);
out
(
'="'
);
out
(
encodeEntities
(
value
));
out
(
'"'
);
}
});
out
(
unary
?
'/>'
:
'>'
);
}
},
end
:
function
(
tag
){
tag
=
angular
.
lowercase
(
tag
);
if
(
!
ignore
&&
validElements
[
tag
]
==
true
)
{
out
(
'</'
);
out
(
tag
);
out
(
'>'
);
}
if
(
tag
==
ignore
)
{
ignore
=
false
;
}
},
chars
:
function
(
chars
){
if
(
!
ignore
)
{
out
(
encodeEntities
(
chars
));
}
}
};
}
// define ngSanitize module and register $sanitize service
angular
.
module
(
'ngSanitize'
,
[]).
value
(
'$sanitize'
,
$sanitize
);
/**
* @ngdoc directive
* @name ngSanitize.directive:ngBindHtml
*
* @description
* Creates a binding that will sanitize the result of evaluating the `expression` with the
* {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.
*
* See {@link ngSanitize.$sanitize $sanitize} docs for examples.
*
* @element ANY
* @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
*/
angular
.
module
(
'ngSanitize'
).
directive
(
'ngBindHtml'
,
[
'$sanitize'
,
function
(
$sanitize
)
{
return
function
(
scope
,
element
,
attr
)
{
element
.
addClass
(
'ng-binding'
).
data
(
'$binding'
,
attr
.
ngBindHtml
);
scope
.
$watch
(
attr
.
ngBindHtml
,
function
ngBindHtmlWatchAction
(
value
)
{
value
=
$sanitize
(
value
);
element
.
html
(
value
||
''
);
});
};
}]);
/**
* @ngdoc filter
* @name ngSanitize.filter:linky
* @function
*
* @description
* Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
* plain email address links.
*
* @param {string} text Input text.
* @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
* @returns {string} Html-linkified text.
*
* @usage
<span ng-bind-html="linky_expression | linky"></span>
*
* @example
<doc:example module="ngSanitize">
<doc:source>
<script>
function Ctrl($scope) {
$scope.snippet =
'Pretty text with some links:\n'+
'http://angularjs.org/,\n'+
'mailto:us@somewhere.org,\n'+
'another@somewhere.org,\n'+
'and one more: ftp://127.0.0.1/.';
$scope.snippetWithTarget = 'http://angularjs.org/';
}
</script>
<div ng-controller="Ctrl">
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
<table>
<tr>
<td>Filter</td>
<td>Source</td>
<td>Rendered</td>
</tr>
<tr id="linky-filter">
<td>linky filter</td>
<td>
<pre><div ng-bind-html="snippet | linky"><br></div></pre>
</td>
<td>
<div ng-bind-html="snippet | linky"></div>
</td>
</tr>
<tr id="linky-target">
<td>linky target</td>
<td>
<pre><div ng-bind-html="snippetWithTarget | linky:'_blank'"><br></div></pre>
</td>
<td>
<div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
</td>
</tr>
<tr id="escaped-html">
<td>no filter</td>
<td><pre><div ng-bind="snippet"><br></div></pre></td>
<td><div ng-bind="snippet"></div></td>
</tr>
</table>
</doc:source>
<doc:scenario>
it('should linkify the snippet with urls', function() {
expect(using('#linky-filter').binding('snippet | linky')).
toBe('Pretty text with some links: ' +
'<a href="http://angularjs.org/">http://angularjs.org/</a>, ' +
'<a href="mailto:us@somewhere.org">us@somewhere.org</a>, ' +
'<a href="mailto:another@somewhere.org">another@somewhere.org</a>, ' +
'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
});
it ('should not linkify snippet without the linky filter', function() {
expect(using('#escaped-html').binding('snippet')).
toBe("Pretty text with some links:\n" +
"http://angularjs.org/,\n" +
"mailto:us@somewhere.org,\n" +
"another@somewhere.org,\n" +
"and one more: ftp://127.0.0.1/.");
});
it('should update', function() {
input('snippet').enter('new http://link.');
expect(using('#linky-filter').binding('snippet | linky')).
toBe('new <a href="http://link">http://link</a>.');
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
});
it('should work with the target property', function() {
expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")).
toBe('<a target="_blank" href="http://angularjs.org/">http://angularjs.org/</a>');
});
</doc:scenario>
</doc:example>
*/
angular
.
module
(
'ngSanitize'
).
filter
(
'linky'
,
function
()
{
var
LINKY_URL_REGEXP
=
/
((
ftp|https
?)
:
\/\/
|
(
mailto:
)?[
A-Za-z0-9._%+-
]
+@
)\S
*
[^\s\.\;\,\(\)\{\}\<\>]
/
,
MAILTO_REGEXP
=
/^mailto:/
;
return
function
(
text
,
target
)
{
if
(
!
text
)
return
text
;
var
match
;
var
raw
=
text
;
var
html
=
[];
// TODO(vojta): use $sanitize instead
var
writer
=
htmlSanitizeWriter
(
html
);
var
url
;
var
i
;
var
properties
=
{};
if
(
angular
.
isDefined
(
target
))
{
properties
.
target
=
target
;
}
while
((
match
=
raw
.
match
(
LINKY_URL_REGEXP
)))
{
// We can not end in these as they are sometimes found at the end of the sentence
url
=
match
[
0
];
// if we did not match ftp/http/mailto then assume mailto
if
(
match
[
2
]
==
match
[
3
])
url
=
'mailto:'
+
url
;
i
=
match
.
index
;
writer
.
chars
(
raw
.
substr
(
0
,
i
));
properties
.
href
=
url
;
writer
.
start
(
'a'
,
properties
);
writer
.
chars
(
match
[
0
].
replace
(
MAILTO_REGEXP
,
''
));
writer
.
end
(
'a'
);
raw
=
raw
.
substring
(
i
+
match
[
0
].
length
);
}
writer
.
chars
(
raw
);
return
html
.
join
(
''
);
};
});
})(
window
,
window
.
angular
);
\ No newline at end of file
src/vendor/angular/angular.js
View file @
60dd6849
This source diff could not be displayed because it is too large. You can
view the blob
instead.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment