1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
'use strict';
(function(){
var svgDirectives = {};
angular.forEach([
'clipPath',
'colorProfile',
'src',
'cursor',
'fill',
'filter',
'marker',
'markerStart',
'markerMid',
'markerEnd',
'mask',
'stroke'
],
function(attr) {
svgDirectives[attr] = [
'$rootScope',
'$location',
'$interpolate',
'$sniffer',
'urlResolve',
'computeSVGAttrValue',
'svgAttrExpressions',
function(
$rootScope,
$location,
$interpolate,
$sniffer,
urlResolve,
computeSVGAttrValue,
svgAttrExpressions) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var initialUrl;
//Only apply to svg elements to avoid unnecessary observing
//Check that is in html5Mode and that history is supported
if ((!svgAttrExpressions.SVG_ELEMENT.test(element[0] &&
element[0].toString())) ||
!$location.$$html5 ||
!$sniffer.history) return;
//Assumes no expressions, since svg is unforgiving of xml violations
initialUrl = attrs[attr];
attrs.$observe(attr, updateValue);
$rootScope.$on('$locationChangeSuccess', updateValue);
function updateValue () {
var newVal = computeSVGAttrValue(initialUrl);
//Prevent recursive updating
if (newVal && attrs[attr] !== newVal) attrs.$set(attr, newVal);
}
}
};
}];
});
angular.module('ngSVGAttributes', []).
factory('urlResolve', [function() {
//Duplicate of urlResolve & urlParsingNode in angular core
var urlParsingNode = document.createElement('a');
return function urlResolve(url) {
urlParsingNode.setAttribute('href', url);
return urlParsingNode;
};
}]).
value('svgAttrExpressions', {
FUNC_URI: /^url\((.*)\)$/,
SVG_ELEMENT: /SVG[a-zA-Z]*Element/,
HASH_PART: /#.*/
}).
factory('computeSVGAttrValue', [
'$location', '$sniffer', 'svgAttrExpressions', 'urlResolve',
function($location, $sniffer, svgAttrExpressions, urlResolve) {
return function computeSVGAttrValue(url) {
var match, fullUrl;
if (match = svgAttrExpressions.FUNC_URI.exec(url)) {
//hash in html5Mode, forces to be relative to current url instead of base
if (match[1].indexOf('#') === 0) {
fullUrl = $location.absUrl().
replace(svgAttrExpressions.HASH_PART, '') +
match[1];
}
//Presumably links to external SVG document
else {
fullUrl = urlResolve(match[1]);
}
}
return fullUrl ? 'url(' + fullUrl + ')' : null;
};
}
]
).
directive(svgDirectives);
}());
|