-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathfixsvgstack.jquery.js
147 lines (118 loc) · 3.97 KB
/
fixsvgstack.jquery.js
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
(function($) {
// Setup
// ----------
// The fix is for webkit browsers only
// [https://bugs.webkit.org/show_bug.cgi?id=91790]()
if(!(/WebKit/.test(navigator.userAgent))) {
// return functions that do nothing but support chaining
$.fn.fixSVGStack = function() { return this; };
$.fn.fixSVGStackBackground = function() { return this; };
return;
}
// Enabled / disable support for a dirty CSS-Hack
// if `USE_DIRTY_CSS_CONTENT_HACK` is true the following CSS enables the fix
// – otherwise only inline styles can be fixed
//
// ```
// .classname {
// background: transparent url('stack.svg#SVG') no-repeat top left;
// content: 'stack.svg#SVG'; /* use content to pass url to webkit fixSVGStackBackground */
// }
// ```
//
var USE_DIRTY_CSS_CONTENT_HACK = true;
// The Fix
// ----------
// Caches XML of SVG Elements (less parsing)
var cache = {};
// Reads SVG Stack via Ajax and returns one element encoded data-uri.
var i = 0;
function getdataURIFromStack(url, cb) {
if(url in cache) {
cb(cache[url]);
}
// `url` must be in the form filename.svg#id
var parts = url.split('#');
if(parts.length !== 2) {
cb(false);
}
var processStack = function(xmlText) {
var xml = (new window.DOMParser()).parseFromString(xmlText, "text/xml")
// `parts[1]` contains id
var svg = xml.getElementById(parts[1]);
if(svg == null) {
cache[url] = false;
cb(false);
}
// iOS Safari fix:
// Firefox uses viewBox and can't scale SVGs when width and height
// attributes are defined.
// Safari on iOS needs width and height to scale properly
var viewBox = svg.getAttribute('viewBox');
if(viewBox && (viewBoxData = viewBox.split(' ')).length == 4) {
svg.setAttribute('width', viewBoxData[2]);
svg.setAttribute('height', viewBoxData[3]);
}
var svgString = (new XMLSerializer()).serializeToString(svg);
var dataURI = 'data:image/svg+xml;utf-8,' + escape(svgString);
cache[url] = dataURI;
cb(dataURI);
}
// Ajax request, browser handles caching
$.ajax({
// `parts[0]` contains filename.svg
url: parts[0],
cache: true,
// Read SVG as 'text', jQuerys XML Parsing is broken with SVGs
dataType: 'text',
success: processStack
});
}
// Fix for SVG Stacks in background
$.fn.fixSVGStackBackground = function() {
this.each(function() {
var $el = $(this);
// At the heart of the bug:
// Both jquery's `$el.css('background-image')` and `getComputedStyle($el[0], null).backgroundImage`
// return and url without the #target part;
var url = $el[0].style.backgroundImage.slice(4, (- 1)).replace(/["']/g, '');
// Here is the quick and dirty hack, if enabled
if(USE_DIRTY_CSS_CONTENT_HACK) {
// Read url form `style.content`, the css content property is used to transport the information
var style = getComputedStyle($el[0], null);
if(style.backgroundImage.indexOf('.svg') !== -1 && style.content.indexOf('.svg#') !== -1) {
url = style.content.replace(/["']/g, '');
}
}
if(url.indexOf('.svg#') === -1) {
return;
}
getdataURIFromStack(url, function(dataURI) {
if(dataURI === false) {
return;
}
// Replace background-image url with dataURI
$el.css('background-image', 'url(' + dataURI + ')');
});
});
return this;
};
// Fix for SVG Stacks in img Tags
$.fn.fixSVGStack = function() {
this.each(function() {
var $el = $(this);
var url = $el.attr('src');
if(url.indexOf('.svg#') === -1) {
return;
}
getdataURIFromStack(url, function(dataURI) {
if(dataURI === false) {
return;
}
// Replace src with dataURI
$el.attr('src', dataURI);
});
});
return this;
};
})(jQuery);