webfontloader 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGELOG +5 -0
  2. data/Rakefile +2 -1
  3. data/lib/webfontloader.rb +1 -1
  4. data/spec/core/font_spec.js +9 -4
  5. data/spec/core/fontruler_spec.js +3 -10
  6. data/spec/core/fontwatcher_spec.js +22 -23
  7. data/spec/core/fontwatchrunner_spec.js +206 -231
  8. data/spec/deps.js +27 -0
  9. data/spec/google/lastresortwebkitfontwatchrunner_spec.js +47 -58
  10. data/spec/index.html +14 -25
  11. data/src/ascender/ascender_script.js +52 -45
  12. data/src/core/browserinfo.js +54 -47
  13. data/src/core/cssclassname.js +27 -22
  14. data/src/core/cssfontfamilyname.js +23 -17
  15. data/src/core/domhelper.js +209 -203
  16. data/src/core/eventdispatcher.js +111 -103
  17. data/src/core/font.js +110 -68
  18. data/src/core/fontmoduleloader.js +56 -13
  19. data/src/core/fontruler.js +52 -43
  20. data/src/core/fontvariationdescription.js +82 -76
  21. data/src/core/fontwatcher.js +93 -88
  22. data/src/core/fontwatchrunner.js +161 -161
  23. data/src/core/initialize.js +22 -15
  24. data/src/core/namespace.js +0 -29
  25. data/src/core/size.js +31 -25
  26. data/src/core/useragent.js +63 -48
  27. data/src/core/useragentparser.js +317 -306
  28. data/src/custom/customcss.js +31 -24
  29. data/src/fontdeck/fontdeck_script.js +46 -37
  30. data/src/google/fontapiparser.js +105 -97
  31. data/src/google/fontapiurlbuilder.js +46 -41
  32. data/src/google/googlefontapi.js +48 -32
  33. data/src/google/lastresortwebkitfontwatchrunner.js +80 -67
  34. data/src/modules.yml +6 -6
  35. data/src/monotype/monotype_script.js +47 -40
  36. data/src/typekit/typekit_script.js +41 -35
  37. data/tools/compiler/base.js +1548 -0
  38. data/tools/compiler/compiler.jar +0 -0
  39. data/webfontloader.gemspec +4 -2
  40. metadata +18 -16
@@ -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
- * Sanitizes a string for use as a css class name. Removes non-word and
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
- * Builds a complete css class name given a variable number of parts.
30
- * Sanitizes, then joins the parts together.
31
- * @param {...string} var_args The parts to join.
32
- * @return {string} The sanitized and joined string.
33
- */
34
- webfont.CssClassName.prototype.build = function(var_args) {
35
- var parts = []
36
- for (var i = 0; i < arguments.length; i++) {
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
- * Quotes the name.
12
- * @param {string} name The name to quote.
13
- * @return {string} The quoted name.
14
- */
15
- webfont.CssFontFamilyName.prototype.quote = function(name) {
16
- var quoted = [];
17
- var split = name.split(/,\s*/);
18
- for (var i = 0; i < split.length; i++) {
19
- var part = split[i].replace(/['"]/g, '');
20
- if (part.indexOf(' ') == -1) {
21
- quoted.push(part);
22
- } else {
23
- quoted.push(this.quote_ + part + this.quote_);
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
- return quoted.join(',');
27
- };
31
+ return quoted.join(',');
32
+ };
33
+ });
@@ -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
- * Creates an element.
22
- * @param {string} elem The element type.
23
- * @param {Object=} opt_attr A hash of attribute key/value pairs.
24
- * @param {string=} opt_innerHtml Contents of the element.
25
- * @return {Element} the new element.
26
- */
27
- webfont.DomHelper.prototype.createElement = function(elem, opt_attr,
28
- opt_innerHtml) {
29
- var domElement = this.document_.createElement(elem);
30
-
31
- if (opt_attr) {
32
- for (var attr in opt_attr) {
33
- // protect against native prototype augmentations
34
- if (opt_attr.hasOwnProperty(attr)) {
35
- if (attr == "style") {
36
- this.setStyle(domElement, opt_attr[attr]);
37
- } else {
38
- domElement.setAttribute(attr, opt_attr[attr]);
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
- if (opt_innerHtml) {
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
- check();
88
- };
89
-
90
- /**
91
- * Removes an element from the DOM.
92
- * @param {Element} node The element to remove.
93
- * @return {boolean} True if the element was removed.
94
- */
95
- webfont.DomHelper.prototype.removeElement = function(node) {
96
- if (node.parentNode) {
97
- node.parentNode.removeChild(node);
98
- return true;
99
- }
100
- return false;
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
- * Removes a name to an element's class attribute.
146
- * @param {Element} e The element.
147
- * @param {string} name The class name to remove.
148
- */
149
- webfont.DomHelper.prototype.removeClassName = function(e, name) {
150
- var classes = e.className.split(/\s+/);
151
- var remainingClasses = [];
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
- e.className = remainingClasses.join(' ')
158
- .replace(/\s+/g, ' ')
159
- .replace(/^\s+|\s+$/, '');
160
- };
161
-
162
- /**
163
- * Returns true if an element has a given class name and false otherwise.
164
- * @param {Element} e The element.
165
- * @param {string} name The class name to check for.
166
- * @return {boolean} Whether or not the element has this class name.
167
- */
168
- webfont.DomHelper.prototype.hasClassName = function(e, name) {
169
- var classes = e.className.split(/\s+/);
170
- for (var i = 0, len = classes.length; i < len; i++) {
171
- if (classes[i] == name) {
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
- return false;
176
- };
177
-
178
- /**
179
- * Sets the style attribute on an element.
180
- * @param {Element} e The element.
181
- * @param {string} styleString The style string.
182
- */
183
- webfont.DomHelper.prototype.setStyle = function(e, styleString) {
184
- if (this.hasSupportForStyle_()) {
185
- e.setAttribute("style", styleString);
186
- } else {
187
- e.style.cssText = styleString;
188
- }
189
- };
190
-
191
- /**
192
- * Check if getting and setting the style attribute on an element with
193
- * getAttribute/setAttribute is supported. In old IE, you must use style.cssText
194
- * instead. Feature detection is only done the first time this is called.
195
- * @private
196
- * @return {boolean} Whether or not the feature is supported.
197
- */
198
- webfont.DomHelper.prototype.hasSupportForStyle_ = function() {
199
- if (this.supportForStyle_ === undefined) {
200
- var e = this.document_.createElement('p');
201
- e.innerHTML = '<a style="top:1px;">w</a>';
202
- this.supportForStyle_ = /top/.test(e.getElementsByTagName('a')[0].getAttribute('style'));
203
- }
204
- return this.supportForStyle_
205
- };
206
-
207
- /**
208
- * @return {Window} The main window webfontloader.js is loaded in (for config).
209
- */
210
- webfont.DomHelper.prototype.getMainWindow = function() {
211
- return this.mainWindow_;
212
- };
213
-
214
- /**
215
- * @return {Window} The window that we're loading the font(s) into.
216
- */
217
- webfont.DomHelper.prototype.getLoadWindow = function() {
218
- return this.loadWindow_;
219
- };
220
-
221
- /**
222
- * @return {string} The protocol (http: or https:) to request resources in.
223
- */
224
- webfont.DomHelper.prototype.getProtocol = function() {
225
- var protocol = this.loadWindow_.location.protocol;
226
- // For empty iframes, fallback to main window's protocol.
227
- if (protocol == 'about:') {
228
- protocol = this.mainWindow_.location.protocol;
229
- }
230
- return protocol == 'https:' ? 'https:' : 'http:';
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
+ });