webfontloader 1.3.0 → 1.3.1
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/CHANGELOG +5 -0
- data/Rakefile +2 -1
- data/lib/webfontloader.rb +1 -1
- data/spec/core/font_spec.js +9 -4
- data/spec/core/fontruler_spec.js +3 -10
- data/spec/core/fontwatcher_spec.js +22 -23
- data/spec/core/fontwatchrunner_spec.js +206 -231
- data/spec/deps.js +27 -0
- data/spec/google/lastresortwebkitfontwatchrunner_spec.js +47 -58
- data/spec/index.html +14 -25
- data/src/ascender/ascender_script.js +52 -45
- data/src/core/browserinfo.js +54 -47
- data/src/core/cssclassname.js +27 -22
- data/src/core/cssfontfamilyname.js +23 -17
- data/src/core/domhelper.js +209 -203
- data/src/core/eventdispatcher.js +111 -103
- data/src/core/font.js +110 -68
- data/src/core/fontmoduleloader.js +56 -13
- data/src/core/fontruler.js +52 -43
- data/src/core/fontvariationdescription.js +82 -76
- data/src/core/fontwatcher.js +93 -88
- data/src/core/fontwatchrunner.js +161 -161
- data/src/core/initialize.js +22 -15
- data/src/core/namespace.js +0 -29
- data/src/core/size.js +31 -25
- data/src/core/useragent.js +63 -48
- data/src/core/useragentparser.js +317 -306
- data/src/custom/customcss.js +31 -24
- data/src/fontdeck/fontdeck_script.js +46 -37
- data/src/google/fontapiparser.js +105 -97
- data/src/google/fontapiurlbuilder.js +46 -41
- data/src/google/googlefontapi.js +48 -32
- data/src/google/lastresortwebkitfontwatchrunner.js +80 -67
- data/src/modules.yml +6 -6
- data/src/monotype/monotype_script.js +47 -40
- data/src/typekit/typekit_script.js +41 -35
- data/tools/compiler/base.js +1548 -0
- data/tools/compiler/compiler.jar +0 -0
- data/webfontloader.gemspec +4 -2
- metadata +18 -16
data/src/core/cssclassname.js
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
goog.provide('webfont.CssClassName');
|
2
|
+
|
1
3
|
/**
|
2
4
|
* Handles sanitization and construction of css class names.
|
3
5
|
* @param {string=} opt_joinChar The character to join parts of the name on.
|
@@ -15,27 +17,30 @@ webfont.CssClassName = function(opt_joinChar) {
|
|
15
17
|
*/
|
16
18
|
webfont.CssClassName.DEFAULT_JOIN_CHAR = '-';
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
* underscore characters.
|
21
|
-
* @param {string} name The string.
|
22
|
-
* @return {string} The sanitized string.
|
23
|
-
*/
|
24
|
-
webfont.CssClassName.prototype.sanitize = function(name) {
|
25
|
-
return name.replace(/[\W_]+/g, '').toLowerCase();
|
26
|
-
};
|
20
|
+
goog.scope(function () {
|
21
|
+
var CssClassName = webfont.CssClassName;
|
27
22
|
|
28
|
-
/**
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
parts.push(this.sanitize(arguments[i]));
|
38
|
-
}
|
39
|
-
return parts.join(this.joinChar_);
|
40
|
-
};
|
23
|
+
/**
|
24
|
+
* Sanitizes a string for use as a css class name. Removes non-word and
|
25
|
+
* underscore characters.
|
26
|
+
* @param {string} name The string.
|
27
|
+
* @return {string} The sanitized string.
|
28
|
+
*/
|
29
|
+
CssClassName.prototype.sanitize = function(name) {
|
30
|
+
return name.replace(/[\W_]+/g, '').toLowerCase();
|
31
|
+
};
|
41
32
|
|
33
|
+
/**
|
34
|
+
* Builds a complete css class name given a variable number of parts.
|
35
|
+
* Sanitizes, then joins the parts together.
|
36
|
+
* @param {...string} var_args The parts to join.
|
37
|
+
* @return {string} The sanitized and joined string.
|
38
|
+
*/
|
39
|
+
CssClassName.prototype.build = function(var_args) {
|
40
|
+
var parts = []
|
41
|
+
for (var i = 0; i < arguments.length; i++) {
|
42
|
+
parts.push(this.sanitize(arguments[i]));
|
43
|
+
}
|
44
|
+
return parts.join(this.joinChar_);
|
45
|
+
};
|
46
|
+
});
|
@@ -1,3 +1,5 @@
|
|
1
|
+
goog.provide('webfont.CssFontFamilyName');
|
2
|
+
|
1
3
|
/**
|
2
4
|
* Handles quoting rules for a font family name in css.
|
3
5
|
* @constructor
|
@@ -7,21 +9,25 @@ webfont.CssFontFamilyName = function() {
|
|
7
9
|
this.quote_ = "'";
|
8
10
|
};
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
var
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
goog.scope(function () {
|
13
|
+
var CssFontFamilyName = webfont.CssFontFamilyName;
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Quotes the name.
|
17
|
+
* @param {string} name The name to quote.
|
18
|
+
* @return {string} The quoted name.
|
19
|
+
*/
|
20
|
+
CssFontFamilyName.prototype.quote = function(name) {
|
21
|
+
var quoted = [];
|
22
|
+
var split = name.split(/,\s*/);
|
23
|
+
for (var i = 0; i < split.length; i++) {
|
24
|
+
var part = split[i].replace(/['"]/g, '');
|
25
|
+
if (part.indexOf(' ') == -1) {
|
26
|
+
quoted.push(part);
|
27
|
+
} else {
|
28
|
+
quoted.push(this.quote_ + part + this.quote_);
|
29
|
+
}
|
24
30
|
}
|
25
|
-
|
26
|
-
|
27
|
-
};
|
31
|
+
return quoted.join(',');
|
32
|
+
};
|
33
|
+
});
|
data/src/core/domhelper.js
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
goog.provide('webfont.DomHelper');
|
2
|
+
|
1
3
|
/**
|
2
4
|
* Handles common DOM manipulation tasks. The aim of this library is to cover
|
3
5
|
* the needs of typical font loading. Not more, not less.
|
@@ -17,215 +19,219 @@ webfont.DomHelper = function(mainWindow, opt_loadWindow) {
|
|
17
19
|
this.supportForStyle_ = undefined;
|
18
20
|
};
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
22
|
+
goog.scope(function () {
|
23
|
+
var DomHelper = webfont.DomHelper;
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Creates an element.
|
27
|
+
* @param {string} elem The element type.
|
28
|
+
* @param {Object=} opt_attr A hash of attribute key/value pairs.
|
29
|
+
* @param {string=} opt_innerHtml Contents of the element.
|
30
|
+
* @return {Element} the new element.
|
31
|
+
*/
|
32
|
+
DomHelper.prototype.createElement = function(elem, opt_attr,
|
33
|
+
opt_innerHtml) {
|
34
|
+
var domElement = this.document_.createElement(elem);
|
35
|
+
|
36
|
+
if (opt_attr) {
|
37
|
+
for (var attr in opt_attr) {
|
38
|
+
// protect against native prototype augmentations
|
39
|
+
if (opt_attr.hasOwnProperty(attr)) {
|
40
|
+
if (attr == "style") {
|
41
|
+
this.setStyle(domElement, opt_attr[attr]);
|
42
|
+
} else {
|
43
|
+
domElement.setAttribute(attr, opt_attr[attr]);
|
44
|
+
}
|
39
45
|
}
|
40
46
|
}
|
41
47
|
}
|
42
|
-
|
43
|
-
|
44
|
-
domElement.appendChild(this.document_.createTextNode(opt_innerHtml));
|
45
|
-
}
|
46
|
-
return domElement;
|
47
|
-
};
|
48
|
-
|
49
|
-
/**
|
50
|
-
* Inserts an element into the document. This is intended for unambiguous
|
51
|
-
* elements such as html, body, head.
|
52
|
-
* @param {string} tagName The element name.
|
53
|
-
* @param {Element} e The element to append.
|
54
|
-
* @return {boolean} True if the element was inserted.
|
55
|
-
*/
|
56
|
-
webfont.DomHelper.prototype.insertInto = function(tagName, e) {
|
57
|
-
var t = this.document_.getElementsByTagName(tagName)[0];
|
58
|
-
|
59
|
-
if (!t) { // opera allows documents without a head
|
60
|
-
t = document.documentElement;
|
61
|
-
}
|
62
|
-
|
63
|
-
if (t && t.lastChild) {
|
64
|
-
// This is safer than appendChild in IE. appendChild causes random
|
65
|
-
// JS errors in IE. Sometimes errors in other JS exectution, sometimes
|
66
|
-
// complete 'This page cannot be displayed' errors. For our purposes,
|
67
|
-
// it's equivalent because we don't need to insert at any specific
|
68
|
-
// location.
|
69
|
-
t.insertBefore(e, t.lastChild);
|
70
|
-
return true;
|
71
|
-
}
|
72
|
-
return false;
|
73
|
-
};
|
74
|
-
|
75
|
-
/**
|
76
|
-
* Calls a function when the body tag exists.
|
77
|
-
* @param {function()} callback The function to call.
|
78
|
-
*/
|
79
|
-
webfont.DomHelper.prototype.whenBodyExists = function(callback) {
|
80
|
-
var check = function() {
|
81
|
-
if (document.body) {
|
82
|
-
callback();
|
83
|
-
} else {
|
84
|
-
setTimeout(check, 0);
|
48
|
+
if (opt_innerHtml) {
|
49
|
+
domElement.appendChild(this.document_.createTextNode(opt_innerHtml));
|
85
50
|
}
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
};
|
102
|
-
|
103
|
-
/**
|
104
|
-
* Creates a link to a CSS document.
|
105
|
-
* @param {string} src The URL of the stylesheet.
|
106
|
-
* @return {Element} a link element.
|
107
|
-
*/
|
108
|
-
webfont.DomHelper.prototype.createCssLink = function(src) {
|
109
|
-
return this.createElement('link', {
|
110
|
-
'rel': 'stylesheet',
|
111
|
-
'href': src
|
112
|
-
});
|
113
|
-
};
|
114
|
-
|
115
|
-
/**
|
116
|
-
* Creates a link to a javascript document.
|
117
|
-
* @param {string} src The URL of the script.
|
118
|
-
* @return {Element} a script element.
|
119
|
-
*/
|
120
|
-
webfont.DomHelper.prototype.createScriptSrc = function(src) {
|
121
|
-
return this.createElement('script', {
|
122
|
-
'src': src
|
123
|
-
});
|
124
|
-
};
|
125
|
-
|
126
|
-
/**
|
127
|
-
* Appends a name to an element's class attribute.
|
128
|
-
* @param {Element} e The element.
|
129
|
-
* @param {string} name The class name to add.
|
130
|
-
*/
|
131
|
-
webfont.DomHelper.prototype.appendClassName = function(e, name) {
|
132
|
-
var classes = e.className.split(/\s+/);
|
133
|
-
for (var i = 0, len = classes.length; i < len; i++) {
|
134
|
-
if (classes[i] == name) {
|
135
|
-
return;
|
51
|
+
return domElement;
|
52
|
+
};
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Inserts an element into the document. This is intended for unambiguous
|
56
|
+
* elements such as html, body, head.
|
57
|
+
* @param {string} tagName The element name.
|
58
|
+
* @param {Element} e The element to append.
|
59
|
+
* @return {boolean} True if the element was inserted.
|
60
|
+
*/
|
61
|
+
DomHelper.prototype.insertInto = function(tagName, e) {
|
62
|
+
var t = this.document_.getElementsByTagName(tagName)[0];
|
63
|
+
|
64
|
+
if (!t) { // opera allows documents without a head
|
65
|
+
t = document.documentElement;
|
136
66
|
}
|
137
|
-
}
|
138
|
-
classes.push(name);
|
139
|
-
e.className = classes.join(' ')
|
140
|
-
.replace(/\s+/g, ' ')
|
141
|
-
.replace(/^\s+|\s+$/, '');
|
142
|
-
};
|
143
67
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
for (var i = 0, len = classes.length; i < len; i++) {
|
153
|
-
if (classes[i] != name) {
|
154
|
-
remainingClasses.push(classes[i]);
|
68
|
+
if (t && t.lastChild) {
|
69
|
+
// This is safer than appendChild in IE. appendChild causes random
|
70
|
+
// JS errors in IE. Sometimes errors in other JS exectution, sometimes
|
71
|
+
// complete 'This page cannot be displayed' errors. For our purposes,
|
72
|
+
// it's equivalent because we don't need to insert at any specific
|
73
|
+
// location.
|
74
|
+
t.insertBefore(e, t.lastChild);
|
75
|
+
return true;
|
155
76
|
}
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
77
|
+
return false;
|
78
|
+
};
|
79
|
+
|
80
|
+
/**
|
81
|
+
* Calls a function when the body tag exists.
|
82
|
+
* @param {function()} callback The function to call.
|
83
|
+
*/
|
84
|
+
DomHelper.prototype.whenBodyExists = function(callback) {
|
85
|
+
var check = function() {
|
86
|
+
if (document.body) {
|
87
|
+
callback();
|
88
|
+
} else {
|
89
|
+
setTimeout(check, 0);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
check();
|
93
|
+
};
|
94
|
+
|
95
|
+
/**
|
96
|
+
* Removes an element from the DOM.
|
97
|
+
* @param {Element} node The element to remove.
|
98
|
+
* @return {boolean} True if the element was removed.
|
99
|
+
*/
|
100
|
+
DomHelper.prototype.removeElement = function(node) {
|
101
|
+
if (node.parentNode) {
|
102
|
+
node.parentNode.removeChild(node);
|
172
103
|
return true;
|
173
104
|
}
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
105
|
+
return false;
|
106
|
+
};
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Creates a link to a CSS document.
|
110
|
+
* @param {string} src The URL of the stylesheet.
|
111
|
+
* @return {Element} a link element.
|
112
|
+
*/
|
113
|
+
DomHelper.prototype.createCssLink = function(src) {
|
114
|
+
return this.createElement('link', {
|
115
|
+
'rel': 'stylesheet',
|
116
|
+
'href': src
|
117
|
+
});
|
118
|
+
};
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Creates a link to a javascript document.
|
122
|
+
* @param {string} src The URL of the script.
|
123
|
+
* @return {Element} a script element.
|
124
|
+
*/
|
125
|
+
DomHelper.prototype.createScriptSrc = function(src) {
|
126
|
+
return this.createElement('script', {
|
127
|
+
'src': src
|
128
|
+
});
|
129
|
+
};
|
130
|
+
|
131
|
+
/**
|
132
|
+
* Appends a name to an element's class attribute.
|
133
|
+
* @param {Element} e The element.
|
134
|
+
* @param {string} name The class name to add.
|
135
|
+
*/
|
136
|
+
DomHelper.prototype.appendClassName = function(e, name) {
|
137
|
+
var classes = e.className.split(/\s+/);
|
138
|
+
for (var i = 0, len = classes.length; i < len; i++) {
|
139
|
+
if (classes[i] == name) {
|
140
|
+
return;
|
141
|
+
}
|
142
|
+
}
|
143
|
+
classes.push(name);
|
144
|
+
e.className = classes.join(' ')
|
145
|
+
.replace(/\s+/g, ' ')
|
146
|
+
.replace(/^\s+|\s+$/, '');
|
147
|
+
};
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Removes a name to an element's class attribute.
|
151
|
+
* @param {Element} e The element.
|
152
|
+
* @param {string} name The class name to remove.
|
153
|
+
*/
|
154
|
+
DomHelper.prototype.removeClassName = function(e, name) {
|
155
|
+
var classes = e.className.split(/\s+/);
|
156
|
+
var remainingClasses = [];
|
157
|
+
for (var i = 0, len = classes.length; i < len; i++) {
|
158
|
+
if (classes[i] != name) {
|
159
|
+
remainingClasses.push(classes[i]);
|
160
|
+
}
|
161
|
+
}
|
162
|
+
e.className = remainingClasses.join(' ')
|
163
|
+
.replace(/\s+/g, ' ')
|
164
|
+
.replace(/^\s+|\s+$/, '');
|
165
|
+
};
|
166
|
+
|
167
|
+
/**
|
168
|
+
* Returns true if an element has a given class name and false otherwise.
|
169
|
+
* @param {Element} e The element.
|
170
|
+
* @param {string} name The class name to check for.
|
171
|
+
* @return {boolean} Whether or not the element has this class name.
|
172
|
+
*/
|
173
|
+
DomHelper.prototype.hasClassName = function(e, name) {
|
174
|
+
var classes = e.className.split(/\s+/);
|
175
|
+
for (var i = 0, len = classes.length; i < len; i++) {
|
176
|
+
if (classes[i] == name) {
|
177
|
+
return true;
|
178
|
+
}
|
179
|
+
}
|
180
|
+
return false;
|
181
|
+
};
|
182
|
+
|
183
|
+
/**
|
184
|
+
* Sets the style attribute on an element.
|
185
|
+
* @param {Element} e The element.
|
186
|
+
* @param {string} styleString The style string.
|
187
|
+
*/
|
188
|
+
DomHelper.prototype.setStyle = function(e, styleString) {
|
189
|
+
if (this.hasSupportForStyle_()) {
|
190
|
+
e.setAttribute("style", styleString);
|
191
|
+
} else {
|
192
|
+
e.style.cssText = styleString;
|
193
|
+
}
|
194
|
+
};
|
195
|
+
|
196
|
+
/**
|
197
|
+
* Check if getting and setting the style attribute on an element with
|
198
|
+
* getAttribute/setAttribute is supported. In old IE, you must use style.cssText
|
199
|
+
* instead. Feature detection is only done the first time this is called.
|
200
|
+
* @private
|
201
|
+
* @return {boolean} Whether or not the feature is supported.
|
202
|
+
*/
|
203
|
+
DomHelper.prototype.hasSupportForStyle_ = function() {
|
204
|
+
if (this.supportForStyle_ === undefined) {
|
205
|
+
var e = this.document_.createElement('p');
|
206
|
+
e.innerHTML = '<a style="top:1px;">w</a>';
|
207
|
+
this.supportForStyle_ = /top/.test(e.getElementsByTagName('a')[0].getAttribute('style'));
|
208
|
+
}
|
209
|
+
return this.supportForStyle_
|
210
|
+
};
|
211
|
+
|
212
|
+
/**
|
213
|
+
* @return {Window} The main window webfontloader.js is loaded in (for config).
|
214
|
+
*/
|
215
|
+
DomHelper.prototype.getMainWindow = function() {
|
216
|
+
return this.mainWindow_;
|
217
|
+
};
|
218
|
+
|
219
|
+
/**
|
220
|
+
* @return {Window} The window that we're loading the font(s) into.
|
221
|
+
*/
|
222
|
+
DomHelper.prototype.getLoadWindow = function() {
|
223
|
+
return this.loadWindow_;
|
224
|
+
};
|
225
|
+
|
226
|
+
/**
|
227
|
+
* @return {string} The protocol (http: or https:) to request resources in.
|
228
|
+
*/
|
229
|
+
DomHelper.prototype.getProtocol = function() {
|
230
|
+
var protocol = this.loadWindow_.location.protocol;
|
231
|
+
// For empty iframes, fallback to main window's protocol.
|
232
|
+
if (protocol == 'about:') {
|
233
|
+
protocol = this.mainWindow_.location.protocol;
|
234
|
+
}
|
235
|
+
return protocol == 'https:' ? 'https:' : 'http:';
|
236
|
+
};
|
237
|
+
});
|