moj_template 0.4.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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/LICENCE.txt +22 -0
  3. data/README.md +96 -0
  4. data/app/assets/images/apple-touch-icon-114x114.png +0 -0
  5. data/app/assets/images/apple-touch-icon-144x144.png +0 -0
  6. data/app/assets/images/apple-touch-icon-57x57.png +0 -0
  7. data/app/assets/images/apple-touch-icon-72x72.png +0 -0
  8. data/app/assets/images/favicon.ico +0 -0
  9. data/app/assets/images/gov.uk_logotype_crown.png +0 -0
  10. data/app/assets/images/gov.uk_logotype_crown_invert.png +0 -0
  11. data/app/assets/images/gov.uk_logotype_crown_invert_trans.png +0 -0
  12. data/app/assets/images/open-government-licence_2x.png +0 -0
  13. data/app/assets/images/opengraph-image.png +0 -0
  14. data/app/assets/javascripts/govuk-template.js +126 -0
  15. data/app/assets/javascripts/ie.js +513 -0
  16. data/app/assets/javascripts/modules/moj.tabs.js +83 -0
  17. data/app/assets/javascripts/moj.js +54 -0
  18. data/app/assets/javascripts/vendor/goog/webfont-debug.js +2127 -0
  19. data/app/assets/javascripts/vendor/jquery/jquery-1.11.0.min.js +5 -0
  20. data/app/assets/stylesheets/external-link-24x24.png +0 -0
  21. data/app/assets/stylesheets/external-link-black-12x12.png +0 -0
  22. data/app/assets/stylesheets/external-link-black-24x24.png +0 -0
  23. data/app/assets/stylesheets/external-link.png +0 -0
  24. data/app/assets/stylesheets/fonts-ie8.css.erb +31 -0
  25. data/app/assets/stylesheets/fonts.css.erb +31 -0
  26. data/app/assets/stylesheets/fonts/NTA-Bold-20130221.eot +0 -0
  27. data/app/assets/stylesheets/fonts/NTA-Bold-20130221.woff +0 -0
  28. data/app/assets/stylesheets/fonts/NTA-Light-20130221.eot +0 -0
  29. data/app/assets/stylesheets/fonts/NTA-Light-20130221.woff +0 -0
  30. data/app/assets/stylesheets/fonts/NTATabularNumbers-Bold.eot +0 -0
  31. data/app/assets/stylesheets/fonts/NTATabularNumbers-Bold.woff +0 -0
  32. data/app/assets/stylesheets/fonts/NTATabularNumbers-Light.eot +0 -0
  33. data/app/assets/stylesheets/fonts/NTATabularNumbers-Light.woff +0 -0
  34. data/app/assets/stylesheets/govuk-template-ie6.css.erb +652 -0
  35. data/app/assets/stylesheets/govuk-template-ie7.css.erb +648 -0
  36. data/app/assets/stylesheets/govuk-template-ie8.css.erb +631 -0
  37. data/app/assets/stylesheets/govuk-template-print.css.erb +78 -0
  38. data/app/assets/stylesheets/govuk-template.css.erb +691 -0
  39. data/app/assets/stylesheets/images/close.png +0 -0
  40. data/app/assets/stylesheets/images/govuk-crest-2x.png +0 -0
  41. data/app/assets/stylesheets/images/govuk-crest-ie.png +0 -0
  42. data/app/assets/stylesheets/images/govuk-crest.png +0 -0
  43. data/app/assets/stylesheets/images/separator-2x.png +0 -0
  44. data/app/assets/stylesheets/images/separator.png +0 -0
  45. data/app/assets/stylesheets/moj-template.css.erb +628 -0
  46. data/app/helpers/moj_helper.rb +9 -0
  47. data/app/views/layouts/moj_template.html.erb +223 -0
  48. data/lib/moj_template.rb +5 -0
  49. data/lib/moj_template/engine.rb +17 -0
  50. data/lib/moj_template/version.rb +3 -0
  51. data/lib/tasks/moj_template_tasks.rake +4 -0
  52. metadata +192 -0
@@ -0,0 +1,83 @@
1
+ // Tabs modules for MOJ
2
+ // Dependencies: moj, jQuery
3
+
4
+ (function () {
5
+ 'use strict';
6
+
7
+ // Define the class
8
+ var Tabs = function (el, options) {
9
+ this.settings = $.extend({}, this.defaults, options);
10
+ this._cacheEls(el);
11
+ this._bindEvents();
12
+ if (this.settings.activatefirst) {
13
+ this._activateFirstLink();
14
+ } else {
15
+ this._activatePane('*');
16
+ }
17
+ };
18
+
19
+ Tabs.prototype = {
20
+
21
+ defaults: {
22
+ activatefirst: true,
23
+ focusfirst: false,
24
+ activetabclass: 'is-active',
25
+ activepaneclass: 'is-active',
26
+ activetabelement: 'li'
27
+ },
28
+
29
+ _cacheEls: function (wrap) {
30
+ this.$tabNav = $('.js-tabs-nav', wrap).first();
31
+ this.$tabs = $('a', this.$tabNav);
32
+ this.$tabPanes = $('.js-tabs-content', wrap).first().children();
33
+ },
34
+
35
+ _bindEvents: function () {
36
+ // store a reference to obj before 'this' becomes jQuery obj
37
+ var self = this;
38
+
39
+ this.$tabs.on('click', function (e) {
40
+ e.preventDefault();
41
+ self._activateTab($(this));
42
+ self._activatePane($(this).attr('href'));
43
+ });
44
+ },
45
+
46
+ _activateTab: function (activeLink) {
47
+ var c = this.settings.activetabclass,
48
+ e = this.settings.activetabelement;
49
+
50
+ this.$tabs.closest(e).removeClass(c);
51
+ this.$tabs.filter(activeLink).closest(e).addClass(c);
52
+ },
53
+
54
+ _activatePane: function (hash) {
55
+ var shown = this
56
+ .$tabPanes.removeClass(this.settings.activepaneclass)
57
+ .filter(hash).addClass(this.settings.activepaneclass);
58
+
59
+ if (this.settings.focusfirst) {
60
+ this._focusFirstElement(shown);
61
+ }
62
+ },
63
+
64
+ _activateFirstLink: function () {
65
+ // activate first tab
66
+ this.$tabNav.find('li').first().find('a').click();
67
+ },
68
+
69
+ _focusFirstElement: function (el) {
70
+ el.find('a, input, textarea, select, button, [tabindex]').not(':disabled').first().focus();
71
+ }
72
+
73
+ };
74
+
75
+ // Add module to MOJ namespace
76
+ moj.Modules.tabs = {
77
+ init: function () {
78
+ $('.js-tabs').each(function () {
79
+ $(this).data('moj.tabs', new Tabs($(this), $(this).data()));
80
+ });
81
+ }
82
+ };
83
+ }());
@@ -0,0 +1,54 @@
1
+ (function(){
2
+ 'use strict';
3
+
4
+ var moj = {
5
+
6
+ Modules: {},
7
+
8
+ Helpers: {},
9
+
10
+ Events: $({}),
11
+
12
+ init: function () {
13
+ for (var x in moj.Modules) {
14
+ if (typeof moj.Modules[x].init === 'function') {
15
+ moj.Modules[x].init();
16
+ }
17
+ }
18
+ // trigger initial render event
19
+ moj.Events.trigger('render');
20
+ },
21
+
22
+ // safe logging
23
+ log: function (msg) {
24
+ if (window && window.console) {
25
+ window.console.log(msg);
26
+ }
27
+ },
28
+ dir: function (obj) {
29
+ if (window && window.console) {
30
+ window.console.dir(obj);
31
+ }
32
+ }
33
+
34
+ };
35
+
36
+ window.moj = moj;
37
+ }());
38
+
39
+ (function () {
40
+ 'use strict';
41
+
42
+ // Invite interested developers to join us
43
+ moj.Modules.devs = {
44
+ init: function () {
45
+ var m = ' ___ ___ ___\n /__/\\ / /\\ / /\\\n | |::\\ / /::\\ / /:/\n | |:|:\\ / /:/\\:\\ /__/::\\\n __|__|:|\\:\\ / /:/ \\:\\\\__\\/\\:\\\n /__/::::| \\:\\/__/:/ \\__\\:\\ \\ \\:\\\n \\ \\:\\~~\\__\\/\\ \\:\\ / /:/ \\__\\:\\\n \\ \\:\\ \\ \\:\\ /:/ / /:/\n \\ \\:\\ \\ \\:\\/:/ /__/:/\n \\ \\:\\ \\ \\::/ \\__\\/\n \\__\\/ \\__\\/',
46
+ txt = '\n\nLike what you see? Want to make a difference?'+
47
+ '\n\nFind out how we\'re making the Ministry Of Justice Digital by Default.'+
48
+ '\nhttp://blogs.justice.gov.uk/digital/.'+
49
+ '\n\nGet in touch to see what positions are available and see what projects you could be working on.'+
50
+ '\nhttps://twitter.com/MOJDigital/statuses/413340917509001216';
51
+ moj.log(m+txt);
52
+ }
53
+ };
54
+ }());
@@ -0,0 +1,2127 @@
1
+ /*
2
+ * Copyright 2012 Small Batch, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ * use this file except in compliance with the License. You may obtain a copy of
6
+ * the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ * License for the specific language governing permissions and limitations under
14
+ * the License.
15
+ */
16
+
17
+
18
+ var webfont = {};
19
+
20
+ /**
21
+ * @param {Object} context
22
+ * @param {function(...)} func
23
+ * @param {...*} opt_args
24
+ */
25
+ webfont.bind = function(context, func, opt_args) {
26
+ var args = arguments.length > 2 ?
27
+ Array.prototype.slice.call(arguments, 2) : [];
28
+
29
+ return function() {
30
+ args.push.apply(args, arguments);
31
+ return func.apply(context, args);
32
+ };
33
+ };
34
+
35
+ webfont.extendsClass = function(baseClass, subClass) {
36
+
37
+ // Avoid polluting the baseClass prototype object with methods from the
38
+ // subClass
39
+ /** @constructor */
40
+ function baseExtendClass() {};
41
+ baseExtendClass.prototype = baseClass.prototype;
42
+ subClass.prototype = new baseExtendClass();
43
+
44
+ subClass.prototype.constructor = subClass;
45
+ subClass.superCtor_ = baseClass;
46
+ subClass.super_ = baseClass.prototype;
47
+ };
48
+
49
+ /**
50
+ * Handles common DOM manipulation tasks. The aim of this library is to cover
51
+ * the needs of typical font loading. Not more, not less.
52
+ * @param {HTMLDocument} doc The HTML document we'll manipulate.
53
+ * @param {webfont.UserAgent} userAgent The current user agent.
54
+ * @constructor
55
+ */
56
+ webfont.DomHelper = function(doc, userAgent) {
57
+ this.document_ = doc;
58
+ this.userAgent_ = userAgent;
59
+ };
60
+
61
+ /**
62
+ * Creates an element.
63
+ * @param {string} elem The element type.
64
+ * @param {Object=} opt_attr A hash of attribute key/value pairs.
65
+ * @param {string=} opt_innerHtml Contents of the element.
66
+ * @return {Element} the new element.
67
+ */
68
+ webfont.DomHelper.prototype.createElement = function(elem, opt_attr,
69
+ opt_innerHtml) {
70
+ var domElement = this.document_.createElement(elem);
71
+
72
+ if (opt_attr) {
73
+ for (var attr in opt_attr) {
74
+ // protect against native prototype augmentations
75
+ if (opt_attr.hasOwnProperty(attr)) {
76
+ if (attr == "style") {
77
+ this.setStyle(domElement, opt_attr[attr]);
78
+ } else {
79
+ domElement.setAttribute(attr, opt_attr[attr]);
80
+ }
81
+ }
82
+ }
83
+ }
84
+ if (opt_innerHtml) {
85
+ domElement.appendChild(this.document_.createTextNode(opt_innerHtml));
86
+ }
87
+ return domElement;
88
+ };
89
+
90
+ /**
91
+ * Inserts an element into the document. This is intended for unambiguous
92
+ * elements such as html, body, head.
93
+ * @param {string} tagName The element name.
94
+ * @param {Element} e The element to append.
95
+ * @return {boolean} True if the element was inserted.
96
+ */
97
+ webfont.DomHelper.prototype.insertInto = function(tagName, e) {
98
+ var t = this.document_.getElementsByTagName(tagName)[0];
99
+
100
+ if (!t) { // opera allows documents without a head
101
+ t = document.documentElement;
102
+ }
103
+
104
+ if (t && t.lastChild) {
105
+ // This is safer than appendChild in IE. appendChild causes random
106
+ // JS errors in IE. Sometimes errors in other JS exectution, sometimes
107
+ // complete 'This page cannot be displayed' errors. For our purposes,
108
+ // it's equivalent because we don't need to insert at any specific
109
+ // location.
110
+ t.insertBefore(e, t.lastChild);
111
+ return true;
112
+ }
113
+ return false;
114
+ };
115
+
116
+ /**
117
+ * Calls a function when the body tag exists.
118
+ * @param {function()} callback The function to call.
119
+ */
120
+ webfont.DomHelper.prototype.whenBodyExists = function(callback) {
121
+ var check = function() {
122
+ if (document.body) {
123
+ callback();
124
+ } else {
125
+ setTimeout(check, 0);
126
+ }
127
+ }
128
+ check();
129
+ };
130
+
131
+ /**
132
+ * Removes an element from the DOM.
133
+ * @param {Element} node The element to remove.
134
+ * @return {boolean} True if the element was removed.
135
+ */
136
+ webfont.DomHelper.prototype.removeElement = function(node) {
137
+ if (node.parentNode) {
138
+ node.parentNode.removeChild(node);
139
+ return true;
140
+ }
141
+ return false;
142
+ };
143
+
144
+ /**
145
+ * Creates a link to a CSS document.
146
+ * @param {string} src The URL of the stylesheet.
147
+ * @return {Element} a link element.
148
+ */
149
+ webfont.DomHelper.prototype.createCssLink = function(src) {
150
+ return this.createElement('link', {
151
+ 'rel': 'stylesheet',
152
+ 'href': src
153
+ });
154
+ };
155
+
156
+ /**
157
+ * Creates a link to a javascript document.
158
+ * @param {string} src The URL of the script.
159
+ * @return {Element} a script element.
160
+ */
161
+ webfont.DomHelper.prototype.createScriptSrc = function(src) {
162
+ return this.createElement('script', {
163
+ 'src': src
164
+ });
165
+ };
166
+
167
+ /**
168
+ * Appends a name to an element's class attribute.
169
+ * @param {Element} e The element.
170
+ * @param {string} name The class name to add.
171
+ */
172
+ webfont.DomHelper.prototype.appendClassName = function(e, name) {
173
+ var classes = e.className.split(/\s+/);
174
+ for (var i = 0, len = classes.length; i < len; i++) {
175
+ if (classes[i] == name) {
176
+ return;
177
+ }
178
+ }
179
+ classes.push(name);
180
+ e.className = classes.join(' ').replace(/^\s+/, '');
181
+ };
182
+
183
+ /**
184
+ * Removes a name to an element's class attribute.
185
+ * @param {Element} e The element.
186
+ * @param {string} name The class name to remove.
187
+ */
188
+ webfont.DomHelper.prototype.removeClassName = function(e, name) {
189
+ var classes = e.className.split(/\s+/);
190
+ var remainingClasses = [];
191
+ for (var i = 0, len = classes.length; i < len; i++) {
192
+ if (classes[i] != name) {
193
+ remainingClasses.push(classes[i]);
194
+ }
195
+ }
196
+ e.className = remainingClasses.join(' ').replace(/^\s+/, '')
197
+ .replace(/\s+$/, '');
198
+ };
199
+
200
+ /**
201
+ * Returns true if an element has a given class name and false otherwise.
202
+ * @param {Element} e The element.
203
+ * @param {string} name The class name to check for.
204
+ * @return {boolean} Whether or not the element has this class name.
205
+ */
206
+ webfont.DomHelper.prototype.hasClassName = function(e, name) {
207
+ var classes = e.className.split(/\s+/);
208
+ for (var i = 0, len = classes.length; i < len; i++) {
209
+ if (classes[i] == name) {
210
+ return true;
211
+ }
212
+ }
213
+ return false;
214
+ };
215
+
216
+ /**
217
+ * Sets the style attribute on an element.
218
+ * @param {Element} e The element.
219
+ * @param {string} styleString The style string.
220
+ */
221
+ webfont.DomHelper.prototype.setStyle = function(e, styleString) {
222
+ if (this.userAgent_.getName() == "MSIE") {
223
+ e.style.cssText = styleString;
224
+ } else {
225
+ e.setAttribute("style", styleString);
226
+ }
227
+ };
228
+
229
+ /**
230
+ * @param {string} name
231
+ * @param {string} version
232
+ * @param {string} engine
233
+ * @param {string} engineVersion
234
+ * @param {string} platform
235
+ * @param {string} platformVersion
236
+ * @param {number|undefined} documentMode
237
+ * @param {boolean} webFontSupport
238
+ * @constructor
239
+ */
240
+ webfont.UserAgent = function(name, version, engine, engineVersion, platform,
241
+ platformVersion, documentMode, webFontSupport) {
242
+ this.name_ = name;
243
+ this.version_ = version;
244
+ this.engine_ = engine;
245
+ this.engineVersion_ = engineVersion;
246
+ this.platform_ = platform;
247
+ this.platformVersion_ = platformVersion;
248
+ this.documentMode_ = documentMode;
249
+ this.webFontSupport_ = webFontSupport;
250
+ };
251
+
252
+ /**
253
+ * @return {string}
254
+ */
255
+ webfont.UserAgent.prototype.getName = function() {
256
+ return this.name_;
257
+ };
258
+
259
+ /**
260
+ * @return {string}
261
+ */
262
+ webfont.UserAgent.prototype.getVersion = function() {
263
+ return this.version_;
264
+ };
265
+
266
+ /**
267
+ * @return {string}
268
+ */
269
+ webfont.UserAgent.prototype.getEngine = function() {
270
+ return this.engine_;
271
+ };
272
+
273
+ /**
274
+ * @return {string}
275
+ */
276
+ webfont.UserAgent.prototype.getEngineVersion = function() {
277
+ return this.engineVersion_;
278
+ };
279
+
280
+ /**
281
+ * @return {string}
282
+ */
283
+ webfont.UserAgent.prototype.getPlatform = function() {
284
+ return this.platform_;
285
+ };
286
+
287
+ /**
288
+ * @return {string}
289
+ */
290
+ webfont.UserAgent.prototype.getPlatformVersion = function() {
291
+ return this.platformVersion_;
292
+ };
293
+
294
+ /**
295
+ * @return {number|undefined}
296
+ */
297
+ webfont.UserAgent.prototype.getDocumentMode = function() {
298
+ return this.documentMode_;
299
+ };
300
+
301
+ /**
302
+ * @return {boolean}
303
+ */
304
+ webfont.UserAgent.prototype.isSupportingWebFont = function() {
305
+ return this.webFontSupport_;
306
+ };
307
+
308
+ /**
309
+ * @param {string} userAgent The browser userAgent string to parse.
310
+ * @constructor
311
+ */
312
+ webfont.UserAgentParser = function(userAgent, doc) {
313
+ this.userAgent_ = userAgent;
314
+ this.doc_ = doc;
315
+ };
316
+
317
+ /**
318
+ * @const
319
+ * @type {string}
320
+ */
321
+ webfont.UserAgentParser.UNKNOWN = "Unknown";
322
+
323
+ /**
324
+ * @const
325
+ * @type {webfont.UserAgent}
326
+ */
327
+ webfont.UserAgentParser.UNKNOWN_USER_AGENT = new webfont.UserAgent(
328
+ webfont.UserAgentParser.UNKNOWN,
329
+ webfont.UserAgentParser.UNKNOWN,
330
+ webfont.UserAgentParser.UNKNOWN,
331
+ webfont.UserAgentParser.UNKNOWN,
332
+ webfont.UserAgentParser.UNKNOWN,
333
+ webfont.UserAgentParser.UNKNOWN,
334
+ undefined,
335
+ false);
336
+
337
+ /**
338
+ * Parses the user agent string and returns an object.
339
+ * @return {webfont.UserAgent}
340
+ */
341
+ webfont.UserAgentParser.prototype.parse = function() {
342
+ if (this.isIe_()) {
343
+ return this.parseIeUserAgentString_();
344
+ } else if (this.isOpera_()) {
345
+ return this.parseOperaUserAgentString_();
346
+ } else if (this.isWebKit_()) {
347
+ return this.parseWebKitUserAgentString_();
348
+ } else if (this.isGecko_()) {
349
+ return this.parseGeckoUserAgentString_();
350
+ } else {
351
+ return webfont.UserAgentParser.UNKNOWN_USER_AGENT;
352
+ }
353
+ };
354
+
355
+ /**
356
+ * @private
357
+ */
358
+ webfont.UserAgentParser.prototype.getPlatform_ = function() {
359
+ var mobileOs = this.getMatchingGroup_(this.userAgent_,
360
+ /(iPod|iPad|iPhone|Android)/, 1);
361
+
362
+ if (mobileOs != "") {
363
+ return mobileOs;
364
+ }
365
+ var os = this.getMatchingGroup_(this.userAgent_,
366
+ /(Linux|Mac_PowerPC|Macintosh|Windows)/, 1);
367
+
368
+ if (os != "") {
369
+ if (os == "Mac_PowerPC") {
370
+ os = "Macintosh";
371
+ }
372
+ return os;
373
+ }
374
+ return webfont.UserAgentParser.UNKNOWN;
375
+ };
376
+
377
+ /**
378
+ * @private
379
+ */
380
+ webfont.UserAgentParser.prototype.getPlatformVersion_ = function() {
381
+ var macVersion = this.getMatchingGroup_(this.userAgent_,
382
+ /(OS X|Windows NT|Android) ([^;)]+)/, 2);
383
+ if (macVersion) {
384
+ return macVersion;
385
+ }
386
+ var iVersion = this.getMatchingGroup_(this.userAgent_,
387
+ /(iPhone )?OS ([\d_]+)/, 2);
388
+ if (iVersion) {
389
+ return iVersion;
390
+ }
391
+ var linuxVersion = this.getMatchingGroup_(this.userAgent_,
392
+ /Linux ([i\d]+)/, 1);
393
+ if (linuxVersion) {
394
+ return linuxVersion;
395
+ }
396
+
397
+ return webfont.UserAgentParser.UNKNOWN;
398
+ };
399
+
400
+ /**
401
+ * @private
402
+ */
403
+ webfont.UserAgentParser.prototype.isIe_ = function() {
404
+ return this.userAgent_.indexOf("MSIE") != -1;
405
+ };
406
+
407
+ /**
408
+ * @private
409
+ */
410
+ webfont.UserAgentParser.prototype.parseIeUserAgentString_ = function() {
411
+ var browser = this.getMatchingGroup_(this.userAgent_, /(MSIE [\d\w\.]+)/, 1);
412
+ var engineName = webfont.UserAgentParser.UNKNOWN;
413
+ var engineVersion = webfont.UserAgentParser.UNKNOWN;
414
+
415
+ if (browser != "") {
416
+ var pair = browser.split(' ');
417
+ var name = pair[0];
418
+ var version = pair[1];
419
+
420
+ // For IE we give MSIE as the engine name and the version of IE
421
+ // instead of the specific Trident engine name and version
422
+ return new webfont.UserAgent(name, version, name, version,
423
+ this.getPlatform_(), this.getPlatformVersion_(),
424
+ this.getDocumentMode_(this.doc_), this.getMajorVersion_(version) >= 6);
425
+ }
426
+ return new webfont.UserAgent("MSIE", webfont.UserAgentParser.UNKNOWN,
427
+ "MSIE", webfont.UserAgentParser.UNKNOWN,
428
+ this.getPlatform_(), this.getPlatformVersion_(),
429
+ this.getDocumentMode_(this.doc_), false);
430
+ };
431
+
432
+ /**
433
+ * @private
434
+ */
435
+ webfont.UserAgentParser.prototype.isOpera_ = function() {
436
+ return this.userAgent_.indexOf("Opera") != -1;
437
+ };
438
+
439
+ /**
440
+ * @private
441
+ */
442
+ webfont.UserAgentParser.prototype.parseOperaUserAgentString_ = function() {
443
+ var engineName = webfont.UserAgentParser.UNKNOWN;
444
+ var engineVersion = webfont.UserAgentParser.UNKNOWN;
445
+ var enginePair = this.getMatchingGroup_(this.userAgent_,
446
+ /(Presto\/[\d\w\.]+)/, 1);
447
+
448
+ if (enginePair != "") {
449
+ var splittedEnginePair = enginePair.split('/');
450
+
451
+ engineName = splittedEnginePair[0];
452
+ engineVersion = splittedEnginePair[1];
453
+ } else {
454
+ if (this.userAgent_.indexOf("Gecko") != -1) {
455
+ engineName = "Gecko";
456
+ }
457
+ var geckoVersion = this.getMatchingGroup_(this.userAgent_, /rv:([^\)]+)/, 1);
458
+
459
+ if (geckoVersion != "") {
460
+ engineVersion = geckoVersion;
461
+ }
462
+ }
463
+ if (this.userAgent_.indexOf("Version/") != -1) {
464
+ var version = this.getMatchingGroup_(this.userAgent_, /Version\/([\d\.]+)/, 1);
465
+
466
+ if (version != "") {
467
+ return new webfont.UserAgent("Opera", version, engineName, engineVersion,
468
+ this.getPlatform_(), this.getPlatformVersion_(),
469
+ this.getDocumentMode_(this.doc_), this.getMajorVersion_(version) >= 10);
470
+ }
471
+ }
472
+ var version = this.getMatchingGroup_(this.userAgent_, /Opera[\/ ]([\d\.]+)/, 1);
473
+
474
+ if (version != "") {
475
+ return new webfont.UserAgent("Opera", version, engineName, engineVersion,
476
+ this.getPlatform_(), this.getPlatformVersion_(),
477
+ this.getDocumentMode_(this.doc_), this.getMajorVersion_(version) >= 10);
478
+ }
479
+ return new webfont.UserAgent("Opera", webfont.UserAgentParser.UNKNOWN,
480
+ engineName, engineVersion, this.getPlatform_(),
481
+ this.getPlatformVersion_(), this.getDocumentMode_(this.doc_), false);
482
+ };
483
+
484
+ /**
485
+ * @private
486
+ */
487
+ webfont.UserAgentParser.prototype.isWebKit_ = function() {
488
+ return this.userAgent_.indexOf("AppleWebKit") != -1;
489
+ };
490
+
491
+ /**
492
+ * @private
493
+ */
494
+ webfont.UserAgentParser.prototype.parseWebKitUserAgentString_ = function() {
495
+ var platform = this.getPlatform_();
496
+ var platformVersion = this.getPlatformVersion_();
497
+ var webKitVersion = this.getMatchingGroup_(this.userAgent_,
498
+ /AppleWebKit\/([\d\.\+]+)/, 1);
499
+
500
+ if (webKitVersion == "") {
501
+ webKitVersion = webfont.UserAgentParser.UNKNOWN;
502
+ }
503
+ var name = webfont.UserAgentParser.UNKNOWN;
504
+
505
+ if (this.userAgent_.indexOf("Chrome") != -1) {
506
+ name = "Chrome";
507
+ } else if (this.userAgent_.indexOf("Safari") != -1) {
508
+ name = "Safari";
509
+ } else if (this.userAgent_.indexOf("AdobeAIR") != -1) {
510
+ name = "AdobeAIR";
511
+ }
512
+ var version = webfont.UserAgentParser.UNKNOWN;
513
+
514
+ if (this.userAgent_.indexOf("Version/") != -1) {
515
+ version = this.getMatchingGroup_(this.userAgent_,
516
+ /Version\/([\d\.\w]+)/, 1);
517
+ } else if (name == "Chrome") {
518
+ version = this.getMatchingGroup_(this.userAgent_,
519
+ /Chrome\/([\d\.]+)/, 1);
520
+ } else if (name == "AdobeAIR") {
521
+ version = this.getMatchingGroup_(this.userAgent_,
522
+ /AdobeAIR\/([\d\.]+)/, 1);
523
+ }
524
+ var supportWebFont = false;
525
+ if (name == "AdobeAIR") {
526
+ var minor = this.getMatchingGroup_(version, /\d+\.(\d+)/, 1);
527
+ supportWebFont = this.getMajorVersion_(version) > 2 ||
528
+ this.getMajorVersion_(version) == 2 && parseInt(minor, 10) >= 5;
529
+ } else {
530
+ var minor = this.getMatchingGroup_(webKitVersion, /\d+\.(\d+)/, 1);
531
+ supportWebFont = this.getMajorVersion_(webKitVersion) >= 526 ||
532
+ this.getMajorVersion_(webKitVersion) >= 525 && parseInt(minor, 10) >= 13;
533
+ }
534
+
535
+ return new webfont.UserAgent(name, version, "AppleWebKit", webKitVersion,
536
+ platform, platformVersion, this.getDocumentMode_(this.doc_), supportWebFont);
537
+ };
538
+
539
+ /**
540
+ * @private
541
+ */
542
+ webfont.UserAgentParser.prototype.isGecko_ = function() {
543
+ return this.userAgent_.indexOf("Gecko") != -1;
544
+ };
545
+
546
+ /**
547
+ * @private
548
+ */
549
+ webfont.UserAgentParser.prototype.parseGeckoUserAgentString_ = function() {
550
+ var name = webfont.UserAgentParser.UNKNOWN;
551
+ var version = webfont.UserAgentParser.UNKNOWN;
552
+ var supportWebFont = false;
553
+
554
+ if (this.userAgent_.indexOf("Firefox") != -1) {
555
+ name = "Firefox";
556
+ var versionNum = this.getMatchingGroup_(this.userAgent_,
557
+ /Firefox\/([\d\w\.]+)/, 1);
558
+
559
+ if (versionNum != "") {
560
+ var minor = this.getMatchingGroup_(versionNum, /\d+\.(\d+)/, 1);
561
+
562
+ version = versionNum;
563
+ supportWebFont = versionNum != "" && this.getMajorVersion_(versionNum) >= 3 &&
564
+ parseInt(minor, 10) >= 5;
565
+ }
566
+ } else if (this.userAgent_.indexOf("Mozilla") != -1) {
567
+ name = "Mozilla";
568
+ }
569
+ var geckoVersion = this.getMatchingGroup_(this.userAgent_, /rv:([^\)]+)/, 1);
570
+
571
+ if (geckoVersion == "") {
572
+ geckoVersion = webfont.UserAgentParser.UNKNOWN;
573
+ } else {
574
+ if (!supportWebFont) {
575
+ var majorVersion = this.getMajorVersion_(geckoVersion);
576
+ var intMinorVersion = parseInt(this.getMatchingGroup_(geckoVersion, /\d+\.(\d+)/, 1), 10);
577
+ var subVersion = parseInt(this.getMatchingGroup_(geckoVersion, /\d+\.\d+\.(\d+)/, 1), 10);
578
+
579
+ supportWebFont = majorVersion > 1 ||
580
+ majorVersion == 1 && intMinorVersion > 9 ||
581
+ majorVersion == 1 && intMinorVersion == 9 && subVersion >= 2 ||
582
+ geckoVersion.match(/1\.9\.1b[123]/) != null ||
583
+ geckoVersion.match(/1\.9\.1\.[\d\.]+/) != null;
584
+ }
585
+ }
586
+ return new webfont.UserAgent(name, version, "Gecko", geckoVersion,
587
+ this.getPlatform_(), this.getPlatformVersion_(), this.getDocumentMode_(this.doc_),
588
+ supportWebFont);
589
+ };
590
+
591
+ /**
592
+ * @private
593
+ */
594
+ webfont.UserAgentParser.prototype.getMajorVersion_ = function(version) {
595
+ var majorVersion = this.getMatchingGroup_(version, /(\d+)/, 1);
596
+
597
+ if (majorVersion != "") {
598
+ return parseInt(majorVersion, 10);
599
+ }
600
+ return -1;
601
+ };
602
+
603
+ /**
604
+ * @private
605
+ */
606
+ webfont.UserAgentParser.prototype.getMatchingGroup_ = function(str,
607
+ regexp, index) {
608
+ var groups = str.match(regexp);
609
+
610
+ if (groups && groups[index]) {
611
+ return groups[index];
612
+ }
613
+ return "";
614
+ };
615
+
616
+ /**
617
+ * @private
618
+ */
619
+ webfont.UserAgentParser.prototype.getDocumentMode_ = function(doc) {
620
+ if (doc.documentMode) return doc.documentMode;
621
+ return undefined;
622
+ };
623
+
624
+ /**
625
+ * A class to dispatch events and manage the event class names on an html
626
+ * element that represent the current state of fonts on the page. Active class
627
+ * names always overwrite inactive class names of the same type, while loading
628
+ * class names may be present whenever a font is loading (regardless of if an
629
+ * associated active or inactive class name is also present).
630
+ * @param {webfont.DomHelper} domHelper
631
+ * @param {HTMLElement} htmlElement
632
+ * @param {Object} callbacks
633
+ * @param {string=} opt_namespace
634
+ * @constructor
635
+ */
636
+ webfont.EventDispatcher = function(domHelper, htmlElement, callbacks,
637
+ opt_namespace) {
638
+ this.domHelper_ = domHelper;
639
+ this.htmlElement_ = htmlElement;
640
+ this.callbacks_ = callbacks;
641
+ this.namespace_ = opt_namespace || webfont.EventDispatcher.DEFAULT_NAMESPACE;
642
+ this.cssClassName_ = new webfont.CssClassName('-');
643
+ };
644
+
645
+ /**
646
+ * @const
647
+ * @type {string}
648
+ */
649
+ webfont.EventDispatcher.DEFAULT_NAMESPACE = 'wf';
650
+
651
+ /**
652
+ * @const
653
+ * @type {string}
654
+ */
655
+ webfont.EventDispatcher.LOADING = 'loading';
656
+
657
+ /**
658
+ * @const
659
+ * @type {string}
660
+ */
661
+ webfont.EventDispatcher.ACTIVE = 'active';
662
+
663
+ /**
664
+ * @const
665
+ * @type {string}
666
+ */
667
+ webfont.EventDispatcher.INACTIVE = 'inactive';
668
+
669
+ /**
670
+ * @const
671
+ * @type {string}
672
+ */
673
+ webfont.EventDispatcher.FONT = 'font';
674
+
675
+ /**
676
+ * Dispatch the loading event and append the loading class name.
677
+ */
678
+ webfont.EventDispatcher.prototype.dispatchLoading = function() {
679
+ this.domHelper_.appendClassName(this.htmlElement_,
680
+ this.cssClassName_.build(
681
+ this.namespace_, webfont.EventDispatcher.LOADING));
682
+ this.dispatch_(webfont.EventDispatcher.LOADING);
683
+ };
684
+
685
+ /**
686
+ * Dispatch the font loading event and append the font loading class name.
687
+ * @param {string} fontFamily
688
+ * @param {string} fontDescription
689
+ */
690
+ webfont.EventDispatcher.prototype.dispatchFontLoading = function(fontFamily, fontDescription) {
691
+ this.domHelper_.appendClassName(this.htmlElement_,
692
+ this.cssClassName_.build(
693
+ this.namespace_, fontFamily, fontDescription, webfont.EventDispatcher.LOADING));
694
+ this.dispatch_(
695
+ webfont.EventDispatcher.FONT + webfont.EventDispatcher.LOADING, fontFamily, fontDescription);
696
+ };
697
+
698
+ /**
699
+ * Dispatch the font active event, remove the font loading class name, remove
700
+ * the font inactive class name, and append the font active class name.
701
+ * @param {string} fontFamily
702
+ * @param {string} fontDescription
703
+ */
704
+ webfont.EventDispatcher.prototype.dispatchFontActive = function(fontFamily, fontDescription) {
705
+ this.domHelper_.removeClassName(this.htmlElement_,
706
+ this.cssClassName_.build(
707
+ this.namespace_, fontFamily, fontDescription, webfont.EventDispatcher.LOADING));
708
+ this.domHelper_.removeClassName(this.htmlElement_,
709
+ this.cssClassName_.build(
710
+ this.namespace_, fontFamily, fontDescription, webfont.EventDispatcher.INACTIVE));
711
+ this.domHelper_.appendClassName(this.htmlElement_,
712
+ this.cssClassName_.build(
713
+ this.namespace_, fontFamily, fontDescription, webfont.EventDispatcher.ACTIVE));
714
+ this.dispatch_(
715
+ webfont.EventDispatcher.FONT + webfont.EventDispatcher.ACTIVE, fontFamily, fontDescription);
716
+ };
717
+
718
+ /**
719
+ * Dispatch the font inactive event, remove the font loading class name, and
720
+ * append the font inactive class name (unless the font active class name is
721
+ * already present).
722
+ * @param {string} fontFamily
723
+ * @param {string} fontDescription
724
+ */
725
+ webfont.EventDispatcher.prototype.dispatchFontInactive = function(fontFamily, fontDescription) {
726
+ this.domHelper_.removeClassName(this.htmlElement_,
727
+ this.cssClassName_.build(
728
+ this.namespace_, fontFamily, fontDescription, webfont.EventDispatcher.LOADING));
729
+ var hasFontActive = this.domHelper_.hasClassName(this.htmlElement_,
730
+ this.cssClassName_.build(
731
+ this.namespace_, fontFamily, fontDescription, webfont.EventDispatcher.ACTIVE));
732
+ if (!hasFontActive) {
733
+ this.domHelper_.appendClassName(this.htmlElement_,
734
+ this.cssClassName_.build(
735
+ this.namespace_, fontFamily, fontDescription, webfont.EventDispatcher.INACTIVE));
736
+ }
737
+ this.dispatch_(
738
+ webfont.EventDispatcher.FONT + webfont.EventDispatcher.INACTIVE, fontFamily, fontDescription);
739
+ };
740
+
741
+ /**
742
+ * Dispatch the inactive event, remove the loading class name, and append the
743
+ * inactive class name (unless the active class name is already present).
744
+ */
745
+ webfont.EventDispatcher.prototype.dispatchInactive = function() {
746
+ this.domHelper_.removeClassName(this.htmlElement_,
747
+ this.cssClassName_.build(
748
+ this.namespace_, webfont.EventDispatcher.LOADING));
749
+ var hasActive = this.domHelper_.hasClassName(this.htmlElement_,
750
+ this.cssClassName_.build(
751
+ this.namespace_, webfont.EventDispatcher.ACTIVE));
752
+ if (!hasActive) {
753
+ this.domHelper_.appendClassName(this.htmlElement_,
754
+ this.cssClassName_.build(
755
+ this.namespace_, webfont.EventDispatcher.INACTIVE));
756
+ }
757
+ this.dispatch_(webfont.EventDispatcher.INACTIVE);
758
+ };
759
+
760
+ /**
761
+ * Dispatch the active event, remove the loading class name, remove the inactive
762
+ * class name, and append the active class name.
763
+ */
764
+ webfont.EventDispatcher.prototype.dispatchActive = function() {
765
+ this.domHelper_.removeClassName(this.htmlElement_,
766
+ this.cssClassName_.build(
767
+ this.namespace_, webfont.EventDispatcher.LOADING));
768
+ this.domHelper_.removeClassName(this.htmlElement_,
769
+ this.cssClassName_.build(
770
+ this.namespace_, webfont.EventDispatcher.INACTIVE));
771
+ this.domHelper_.appendClassName(this.htmlElement_,
772
+ this.cssClassName_.build(
773
+ this.namespace_, webfont.EventDispatcher.ACTIVE));
774
+ this.dispatch_(webfont.EventDispatcher.ACTIVE);
775
+ };
776
+
777
+ /**
778
+ * @param {string} event
779
+ * @param {string=} opt_arg1
780
+ * @param {string=} opt_arg2
781
+ */
782
+ webfont.EventDispatcher.prototype.dispatch_ = function(event, opt_arg1, opt_arg2) {
783
+ if (this.callbacks_[event]) {
784
+ this.callbacks_[event](opt_arg1, opt_arg2);
785
+ }
786
+ };
787
+
788
+ /**
789
+ * @constructor
790
+ */
791
+ webfont.FontModuleLoader = function() {
792
+ this.modules_ = {};
793
+ };
794
+
795
+ webfont.FontModuleLoader.prototype.addModuleFactory = function(name, factory) {
796
+ this.modules_[name] = factory;
797
+ };
798
+
799
+ webfont.FontModuleLoader.prototype.getModules = function(configuration) {
800
+ var modules = [];
801
+
802
+ for (var key in configuration) {
803
+ if (configuration.hasOwnProperty(key)) {
804
+ var moduleFactory = this.modules_[key];
805
+
806
+ if (moduleFactory) {
807
+ modules.push(moduleFactory(configuration[key]));
808
+ }
809
+ }
810
+ }
811
+ return modules;
812
+ };
813
+
814
+ /**
815
+ * @constructor
816
+ * @param {webfont.DomHelper} domHelper
817
+ * @param {webfont.EventDispatcher} eventDispatcher
818
+ * @param {Object.<string, function(Object): number>} fontSizer
819
+ * @param {function(function(), number=)} asyncCall
820
+ * @param {function(): number} getTime
821
+ */
822
+ webfont.FontWatcher = function(domHelper, eventDispatcher, fontSizer,
823
+ asyncCall, getTime) {
824
+ this.domHelper_ = domHelper;
825
+ this.eventDispatcher_ = eventDispatcher;
826
+ this.fontSizer_ = fontSizer;
827
+ this.asyncCall_ = asyncCall;
828
+ this.getTime_ = getTime;
829
+ this.currentlyWatched_ = 0;
830
+ this.last_ = false;
831
+ this.success_ = false;
832
+ };
833
+
834
+ /**
835
+ * @type {string}
836
+ * @const
837
+ */
838
+ webfont.FontWatcher.DEFAULT_VARIATION = 'n4';
839
+
840
+ /**
841
+ * Watches a set of font families.
842
+ * @param {Array.<string>} fontFamilies The font family names to watch.
843
+ * @param {Object.<string, Array.<string>>} fontDescriptions The font variations
844
+ * of each family to watch. Described with FVD.
845
+ * @param {Object.<string, string>} fontTestStrings The font test strings for
846
+ * each family.
847
+ * @param {boolean} last True if this is the last set of families to watch.
848
+ */
849
+ webfont.FontWatcher.prototype.watch = function(fontFamilies, fontDescriptions,
850
+ fontTestStrings, fontWatchRunnerCtor, last) {
851
+ var length = fontFamilies.length;
852
+
853
+ for (var i = 0; i < length; i++) {
854
+ var fontFamily = fontFamilies[i];
855
+ if (!fontDescriptions[fontFamily]) {
856
+ fontDescriptions[fontFamily] = [webfont.FontWatcher.DEFAULT_VARIATION];
857
+ }
858
+ this.currentlyWatched_ += fontDescriptions[fontFamily].length;
859
+ }
860
+
861
+ if (last) {
862
+ this.last_ = last;
863
+ }
864
+
865
+ for (var i = 0; i < length; i++) {
866
+ var fontFamily = fontFamilies[i];
867
+ var descriptions = fontDescriptions[fontFamily];
868
+ var fontTestString = fontTestStrings[fontFamily];
869
+
870
+ for (var j = 0, len = descriptions.length; j < len; j++) {
871
+ var fontDescription = descriptions[j];
872
+
873
+ this.eventDispatcher_.dispatchFontLoading(fontFamily, fontDescription);
874
+
875
+ var activeCallback = webfont.bind(this, this.fontActive_);
876
+ var inactiveCallback = webfont.bind(this, this.fontInactive_)
877
+ var fontWatchRunner = new fontWatchRunnerCtor(activeCallback,
878
+ inactiveCallback, this.domHelper_, this.fontSizer_, this.asyncCall_,
879
+ this.getTime_, fontFamily, fontDescription, fontTestString);
880
+
881
+ fontWatchRunner.start();
882
+ }
883
+ }
884
+ };
885
+
886
+ /**
887
+ * Called by a FontWatchRunner when a font has been detected as active.
888
+ * @param {string} fontFamily
889
+ * @param {string} fontDescription
890
+ * @private
891
+ */
892
+ webfont.FontWatcher.prototype.fontActive_ = function(fontFamily, fontDescription) {
893
+ this.eventDispatcher_.dispatchFontActive(fontFamily, fontDescription);
894
+ this.success_ = true;
895
+ this.decreaseCurrentlyWatched_();
896
+ };
897
+
898
+ /**
899
+ * Called by a FontWatchRunner when a font has been detected as inactive.
900
+ * @param {string} fontFamily
901
+ * @param {string} fontDescription
902
+ * @private
903
+ */
904
+ webfont.FontWatcher.prototype.fontInactive_ = function(fontFamily, fontDescription) {
905
+ this.eventDispatcher_.dispatchFontInactive(fontFamily, fontDescription);
906
+ this.decreaseCurrentlyWatched_();
907
+ };
908
+
909
+ /**
910
+ * @private
911
+ */
912
+ webfont.FontWatcher.prototype.decreaseCurrentlyWatched_ = function() {
913
+ if (--this.currentlyWatched_ == 0 && this.last_) {
914
+ if (this.success_) {
915
+ this.eventDispatcher_.dispatchActive();
916
+ } else {
917
+ this.eventDispatcher_.dispatchInactive();
918
+ }
919
+ }
920
+ };
921
+
922
+ /**
923
+ * @constructor
924
+ * @param {function(string, string)} activeCallback
925
+ * @param {function(string, string)} inactiveCallback
926
+ * @param {webfont.DomHelper} domHelper
927
+ * @param {Object.<string, function(Object): number>} fontSizer
928
+ * @param {function(function(), number=)} asyncCall
929
+ * @param {function(): number} getTime
930
+ * @param {string} fontFamily
931
+ * @param {string} fontDescription
932
+ * @param {string=} opt_fontTestString
933
+ */
934
+ webfont.FontWatchRunner = function(activeCallback, inactiveCallback, domHelper,
935
+ fontSizer, asyncCall, getTime, fontFamily, fontDescription, opt_fontTestString) {
936
+ this.activeCallback_ = activeCallback;
937
+ this.inactiveCallback_ = inactiveCallback;
938
+ this.domHelper_ = domHelper;
939
+ this.fontSizer_ = fontSizer;
940
+ this.asyncCall_ = asyncCall;
941
+ this.getTime_ = getTime;
942
+ this.nameHelper_ = new webfont.CssFontFamilyName();
943
+ this.fvd_ = new webfont.FontVariationDescription();
944
+ this.fontFamily_ = fontFamily;
945
+ this.fontDescription_ = fontDescription;
946
+ this.fontTestString_ = opt_fontTestString || webfont.FontWatchRunner.DEFAULT_TEST_STRING;
947
+ this.originalSizeA_ = this.getDefaultFontSize_(
948
+ webfont.FontWatchRunner.DEFAULT_FONTS_A);
949
+ this.originalSizeB_ = this.getDefaultFontSize_(
950
+ webfont.FontWatchRunner.DEFAULT_FONTS_B);
951
+ this.lastObservedSizeA_ = this.originalSizeA_;
952
+ this.lastObservedSizeB_ = this.originalSizeB_;
953
+ this.requestedFontA_ = this.createHiddenElementWithFont_(
954
+ webfont.FontWatchRunner.DEFAULT_FONTS_A);
955
+ this.requestedFontB_ = this.createHiddenElementWithFont_(
956
+ webfont.FontWatchRunner.DEFAULT_FONTS_B);
957
+ };
958
+
959
+ /**
960
+ * A set of sans-serif fonts and a generic family that cover most platforms:
961
+ * Windows - arial - 99.71%
962
+ * Mac - arial - 97.67%
963
+ * Linux - 97.67%
964
+ * (Based on http://www.codestyle.org/css/font-family/sampler-CombinedResults.shtml)
965
+ * @type {string}
966
+ * @const
967
+ */
968
+ webfont.FontWatchRunner.DEFAULT_FONTS_A = "arial,'URW Gothic L',sans-serif";
969
+
970
+ /**
971
+ * A set of serif fonts and a generic family that cover most platforms. We
972
+ * want each of these fonts to have a different width when rendering the test
973
+ * string than each of the fonts in DEFAULT_FONTS_A:
974
+ * Windows - Georgia - 98.98%
975
+ * Mac - Georgia - 95.60%
976
+ * Linux - Century Schoolbook L - 97.97%
977
+ * (Based on http://www.codestyle.org/css/font-family/sampler-CombinedResults.shtml)
978
+ * @type {string}
979
+ * @const
980
+ */
981
+ webfont.FontWatchRunner.DEFAULT_FONTS_B = "Georgia,'Century Schoolbook L',serif";
982
+
983
+ /**
984
+ * Default test string. Characters are chosen so that their widths vary a lot
985
+ * between the fonts in the default stacks. We want each fallback stack
986
+ * to always start out at a different width than the other.
987
+ * @type {string}
988
+ * @const
989
+ */
990
+ webfont.FontWatchRunner.DEFAULT_TEST_STRING = 'BESbswy';
991
+
992
+ webfont.FontWatchRunner.prototype.start = function() {
993
+ this.started_ = this.getTime_();
994
+ this.check_();
995
+ };
996
+
997
+ /**
998
+ * Checks the size of the two spans against their original sizes during each
999
+ * async loop. If the size of one of the spans is different than the original
1000
+ * size, then we know that the font is rendering and finish with the active
1001
+ * callback. If we wait more than 5 seconds and nothing has changed, we finish
1002
+ * with the inactive callback.
1003
+ *
1004
+ * Because of an odd Webkit quirk, we wait to observe the new width twice
1005
+ * in a row before finishing with the active callback. Sometimes, Webkit will
1006
+ * render the spans with a changed width for one iteration even though the font
1007
+ * is broken. This only happens for one async loop, so waiting for 2 consistent
1008
+ * measurements allows us to work around the quirk.
1009
+ *
1010
+ * @private
1011
+ */
1012
+ webfont.FontWatchRunner.prototype.check_ = function() {
1013
+ var sizeA = this.fontSizer_.getWidth(this.requestedFontA_);
1014
+ var sizeB = this.fontSizer_.getWidth(this.requestedFontB_);
1015
+
1016
+ if ((this.originalSizeA_ != sizeA || this.originalSizeB_ != sizeB) &&
1017
+ this.lastObservedSizeA_ == sizeA && this.lastObservedSizeB_ == sizeB) {
1018
+ this.finish_(this.activeCallback_);
1019
+ } else if (this.getTime_() - this.started_ >= 5000) {
1020
+ this.finish_(this.inactiveCallback_);
1021
+ } else {
1022
+ this.lastObservedSizeA_ = sizeA;
1023
+ this.lastObservedSizeB_ = sizeB;
1024
+ this.asyncCheck_();
1025
+ }
1026
+ };
1027
+
1028
+ /**
1029
+ * @private
1030
+ */
1031
+ webfont.FontWatchRunner.prototype.asyncCheck_ = function() {
1032
+ this.asyncCall_(function(context, func) {
1033
+ return function() {
1034
+ func.call(context);
1035
+ }
1036
+ }(this, this.check_), 25);
1037
+ };
1038
+
1039
+ /**
1040
+ * @private
1041
+ * @param {function(string, string)} callback
1042
+ */
1043
+ webfont.FontWatchRunner.prototype.finish_ = function(callback) {
1044
+ this.domHelper_.removeElement(this.requestedFontA_);
1045
+ this.domHelper_.removeElement(this.requestedFontB_);
1046
+ callback(this.fontFamily_, this.fontDescription_);
1047
+ };
1048
+
1049
+ /**
1050
+ * @private
1051
+ * @param {string} defaultFonts
1052
+ */
1053
+ webfont.FontWatchRunner.prototype.getDefaultFontSize_ = function(defaultFonts) {
1054
+ var defaultFont = this.createHiddenElementWithFont_(defaultFonts, true);
1055
+ var size = this.fontSizer_.getWidth(defaultFont);
1056
+
1057
+ this.domHelper_.removeElement(defaultFont);
1058
+ return size;
1059
+ };
1060
+
1061
+ /**
1062
+ * @private
1063
+ * @param {string} defaultFonts
1064
+ * @param {boolean=} opt_withoutFontFamily
1065
+ */
1066
+ webfont.FontWatchRunner.prototype.createHiddenElementWithFont_ = function(
1067
+ defaultFonts, opt_withoutFontFamily) {
1068
+ var styleString = this.computeStyleString_(defaultFonts,
1069
+ this.fontDescription_, opt_withoutFontFamily);
1070
+ var span = this.domHelper_.createElement('span', { 'style': styleString },
1071
+ this.fontTestString_);
1072
+
1073
+ this.domHelper_.insertInto('body', span);
1074
+ return span;
1075
+ };
1076
+
1077
+ webfont.FontWatchRunner.prototype.computeStyleString_ = function(defaultFonts,
1078
+ fontDescription, opt_withoutFontFamily) {
1079
+ var variationCss = this.fvd_.expand(fontDescription);
1080
+ var styleString = "position:absolute;top:-999px;left:-999px;" +
1081
+ "font-size:300px;width:auto;height:auto;line-height:normal;margin:0;" +
1082
+ "padding:0;font-variant:normal;font-family:"
1083
+ + (opt_withoutFontFamily ? "" :
1084
+ this.nameHelper_.quote(this.fontFamily_) + ",")
1085
+ + defaultFonts + ";" + variationCss;
1086
+ return styleString;
1087
+ };
1088
+
1089
+ /**
1090
+ * @constructor
1091
+ */
1092
+ webfont.WebFont = function(domHelper, fontModuleLoader, htmlElement, asyncCall,
1093
+ userAgent) {
1094
+ this.domHelper_ = domHelper;
1095
+ this.fontModuleLoader_ = fontModuleLoader;
1096
+ this.htmlElement_ = htmlElement;
1097
+ this.asyncCall_ = asyncCall;
1098
+ this.userAgent_ = userAgent;
1099
+ this.moduleLoading_ = 0;
1100
+ this.moduleFailedLoading_ = 0;
1101
+ };
1102
+
1103
+ webfont.WebFont.prototype.addModule = function(name, factory) {
1104
+ this.fontModuleLoader_.addModuleFactory(name, factory);
1105
+ };
1106
+
1107
+ webfont.WebFont.prototype.load = function(configuration) {
1108
+ var eventDispatcher = new webfont.EventDispatcher(
1109
+ this.domHelper_, this.htmlElement_, configuration);
1110
+
1111
+ if (this.userAgent_.isSupportingWebFont()) {
1112
+ this.load_(eventDispatcher, configuration);
1113
+ } else {
1114
+ eventDispatcher.dispatchInactive();
1115
+ }
1116
+ };
1117
+
1118
+ webfont.WebFont.prototype.isModuleSupportingUserAgent_ = function(module, eventDispatcher,
1119
+ fontWatcher, support) {
1120
+ var fontWatchRunnerCtor = module.getFontWatchRunnerCtor ?
1121
+ module.getFontWatchRunnerCtor() : webfont.FontWatchRunner;
1122
+ if (!support) {
1123
+ var allModulesLoaded = --this.moduleLoading_ == 0;
1124
+
1125
+ this.moduleFailedLoading_--;
1126
+ if (allModulesLoaded) {
1127
+ if (this.moduleFailedLoading_ == 0) {
1128
+ eventDispatcher.dispatchInactive();
1129
+ } else {
1130
+ eventDispatcher.dispatchLoading();
1131
+ }
1132
+ }
1133
+ fontWatcher.watch([], {}, {}, fontWatchRunnerCtor, allModulesLoaded);
1134
+ return;
1135
+ }
1136
+ module.load(webfont.bind(this, this.onModuleReady_, eventDispatcher,
1137
+ fontWatcher, fontWatchRunnerCtor));
1138
+ };
1139
+
1140
+ webfont.WebFont.prototype.onModuleReady_ = function(eventDispatcher, fontWatcher,
1141
+ fontWatchRunnerCtor, fontFamilies, opt_fontDescriptions, opt_fontTestStrings) {
1142
+ var allModulesLoaded = --this.moduleLoading_ == 0;
1143
+
1144
+ if (allModulesLoaded) {
1145
+ eventDispatcher.dispatchLoading();
1146
+ }
1147
+ this.asyncCall_(webfont.bind(this, function(_fontWatcher, _fontFamilies,
1148
+ _fontDescriptions, _fontTestStrings, _fontWatchRunnerCtor,
1149
+ _allModulesLoaded) {
1150
+ _fontWatcher.watch(_fontFamilies, _fontDescriptions || {},
1151
+ _fontTestStrings || {}, _fontWatchRunnerCtor, _allModulesLoaded);
1152
+ }, fontWatcher, fontFamilies, opt_fontDescriptions, opt_fontTestStrings,
1153
+ fontWatchRunnerCtor, allModulesLoaded));
1154
+ };
1155
+
1156
+ webfont.WebFont.prototype.load_ = function(eventDispatcher, configuration) {
1157
+ var modules = this.fontModuleLoader_.getModules(configuration),
1158
+ self = this;
1159
+
1160
+ this.moduleFailedLoading_ = this.moduleLoading_ = modules.length;
1161
+
1162
+ var fontWatcher = new webfont.FontWatcher(this.domHelper_,
1163
+ eventDispatcher, {
1164
+ getWidth: function(elem) {
1165
+ return elem.offsetWidth;
1166
+ }}, self.asyncCall_, function() {
1167
+ return new Date().getTime();
1168
+ });
1169
+
1170
+ for (var i = 0, len = modules.length; i < len; i++) {
1171
+ var module = modules[i];
1172
+
1173
+ module.supportUserAgent(this.userAgent_,
1174
+ webfont.bind(this, this.isModuleSupportingUserAgent_, module,
1175
+ eventDispatcher, fontWatcher));
1176
+ }
1177
+ };
1178
+
1179
+ /**
1180
+ * Handles sanitization and construction of css class names.
1181
+ * @param {string=} opt_joinChar The character to join parts of the name on.
1182
+ * Defaults to '-'.
1183
+ * @constructor
1184
+ */
1185
+ webfont.CssClassName = function(opt_joinChar) {
1186
+ /** @type {string} */
1187
+ this.joinChar_ = opt_joinChar || webfont.CssClassName.DEFAULT_JOIN_CHAR;
1188
+ };
1189
+
1190
+ /**
1191
+ * @const
1192
+ * @type {string}
1193
+ */
1194
+ webfont.CssClassName.DEFAULT_JOIN_CHAR = '-';
1195
+
1196
+ /**
1197
+ * Sanitizes a string for use as a css class name. Removes non-word and
1198
+ * underscore characters.
1199
+ * @param {string} name The string.
1200
+ * @return {string} The sanitized string.
1201
+ */
1202
+ webfont.CssClassName.prototype.sanitize = function(name) {
1203
+ return name.replace(/[\W_]+/g, '').toLowerCase();
1204
+ };
1205
+
1206
+ /**
1207
+ * Builds a complete css class name given a variable number of parts.
1208
+ * Sanitizes, then joins the parts together.
1209
+ * @param {...string} var_args The parts to join.
1210
+ * @return {string} The sanitized and joined string.
1211
+ */
1212
+ webfont.CssClassName.prototype.build = function(var_args) {
1213
+ var parts = []
1214
+ for (var i = 0; i < arguments.length; i++) {
1215
+ parts.push(this.sanitize(arguments[i]));
1216
+ }
1217
+ return parts.join(this.joinChar_);
1218
+ };
1219
+
1220
+
1221
+ /**
1222
+ * Handles quoting rules for a font family name in css.
1223
+ * @constructor
1224
+ */
1225
+ webfont.CssFontFamilyName = function() {
1226
+ /** @type {string} */
1227
+ this.quote_ = "'";
1228
+ };
1229
+
1230
+ /**
1231
+ * Quotes the name.
1232
+ * @param {string} name The name to quote.
1233
+ * @return {string} The quoted name.
1234
+ */
1235
+ webfont.CssFontFamilyName.prototype.quote = function(name) {
1236
+ var quoted = [];
1237
+ var split = name.split(/,\s*/);
1238
+ for (var i = 0; i < split.length; i++) {
1239
+ var part = split[i].replace(/['"]/g, '');
1240
+ if (part.indexOf(' ') == -1) {
1241
+ quoted.push(part);
1242
+ } else {
1243
+ quoted.push(this.quote_ + part + this.quote_);
1244
+ }
1245
+ }
1246
+ return quoted.join(',');
1247
+ };
1248
+
1249
+ /**
1250
+ * @constructor
1251
+ */
1252
+ webfont.FontVariationDescription = function() {
1253
+ this.properties_ = webfont.FontVariationDescription.PROPERTIES;
1254
+ this.values_ = webfont.FontVariationDescription.VALUES;
1255
+ };
1256
+
1257
+ /**
1258
+ * @const
1259
+ */
1260
+ webfont.FontVariationDescription.PROPERTIES = [
1261
+ 'font-style',
1262
+ 'font-weight'
1263
+ ];
1264
+
1265
+ /**
1266
+ * @const
1267
+ */
1268
+ webfont.FontVariationDescription.VALUES = {
1269
+ 'font-style': [
1270
+ ['n', 'normal'],
1271
+ ['i', 'italic'],
1272
+ ['o', 'oblique']
1273
+ ],
1274
+ 'font-weight': [
1275
+ ['1', '100'],
1276
+ ['2', '200'],
1277
+ ['3', '300'],
1278
+ ['4', '400'],
1279
+ ['5', '500'],
1280
+ ['6', '600'],
1281
+ ['7', '700'],
1282
+ ['8', '800'],
1283
+ ['9', '900'],
1284
+ ['4', 'normal'],
1285
+ ['7', 'bold']
1286
+ ]
1287
+ };
1288
+
1289
+ /**
1290
+ * @private
1291
+ * @constructor
1292
+ */
1293
+ webfont.FontVariationDescription.Item = function(index, property, values) {
1294
+ this.index_ = index;
1295
+ this.property_ = property;
1296
+ this.values_ = values;
1297
+ }
1298
+
1299
+ webfont.FontVariationDescription.Item.prototype.compact = function(output, value) {
1300
+ for (var i = 0; i < this.values_.length; i++) {
1301
+ if (value == this.values_[i][1]) {
1302
+ output[this.index_] = this.values_[i][0];
1303
+ return;
1304
+ }
1305
+ }
1306
+ }
1307
+
1308
+ webfont.FontVariationDescription.Item.prototype.expand = function(output, value) {
1309
+ for (var i = 0; i < this.values_.length; i++) {
1310
+ if (value == this.values_[i][0]) {
1311
+ output[this.index_] = this.property_ + ':' + this.values_[i][1];
1312
+ return;
1313
+ }
1314
+ }
1315
+ }
1316
+
1317
+ /**
1318
+ * Compacts CSS declarations into an FVD.
1319
+ * @param {string} input A string of CSS declarations such as
1320
+ * 'font-weight:normal;font-style:italic'.
1321
+ * @return {string} The equivalent FVD such as 'n4'.
1322
+ */
1323
+ webfont.FontVariationDescription.prototype.compact = function(input) {
1324
+ var result = ['n', '4'];
1325
+ var descriptors = input.split(';');
1326
+
1327
+ for (var i = 0, len = descriptors.length; i < len; i++) {
1328
+ var pair = descriptors[i].replace(/\s+/g, '').split(':');
1329
+ if (pair.length == 2) {
1330
+ var property = pair[0];
1331
+ var value = pair[1];
1332
+ var item = this.getItem_(property);
1333
+ if (item) {
1334
+ item.compact(result, value);
1335
+ }
1336
+ }
1337
+ }
1338
+
1339
+ return result.join('');
1340
+ };
1341
+
1342
+ /**
1343
+ * Expands a FVD string into equivalent CSS declarations.
1344
+ * @param {string} fvd The FVD string, such as 'n4'.
1345
+ * @return {?string} The equivalent CSS such as
1346
+ * 'font-weight:normal;font-style:italic' or null if it cannot be parsed.
1347
+ */
1348
+ webfont.FontVariationDescription.prototype.expand = function(fvd) {
1349
+ if (fvd.length != 2) {
1350
+ return null;
1351
+ }
1352
+
1353
+ var result = [null, null];
1354
+
1355
+ for (var i = 0, len = this.properties_.length; i < len; i++) {
1356
+ var property = this.properties_[i];
1357
+ var key = fvd.substr(i, 1);
1358
+ var values = this.values_[property];
1359
+ var item = new webfont.FontVariationDescription.Item(i, property, values);
1360
+ item.expand(result, key);
1361
+ }
1362
+
1363
+ if (result[0] && result[1]) {
1364
+ return result.join(';') + ';';
1365
+ } else {
1366
+ return null;
1367
+ }
1368
+ }
1369
+
1370
+ /**
1371
+ * @private
1372
+ */
1373
+ webfont.FontVariationDescription.prototype.getItem_ = function(property) {
1374
+ for (var i = 0; i < this.properties_.length; i++) {
1375
+ if (property == this.properties_[i]) {
1376
+ var values = this.values_[property];
1377
+ return new webfont.FontVariationDescription.Item(i, property, values);
1378
+ }
1379
+ }
1380
+
1381
+ return null;
1382
+ };
1383
+
1384
+ // Name of the global object.
1385
+ var globalName = 'WebFont';
1386
+
1387
+ // Provide an instance of WebFont in the global namespace.
1388
+ window[globalName] = (function() {
1389
+ var userAgentParser = new webfont.UserAgentParser(navigator.userAgent, document);
1390
+ var userAgent = userAgentParser.parse();
1391
+ var domHelper = new webfont.DomHelper(document, userAgent);
1392
+ var asyncCall = function(func, timeout) { setTimeout(func, timeout); };
1393
+
1394
+ return new webfont.WebFont(domHelper, new webfont.FontModuleLoader(),
1395
+ document.documentElement, asyncCall, userAgent);
1396
+ })();
1397
+
1398
+ // Export the public API.
1399
+ window[globalName]['load'] = window[globalName].load;
1400
+ window[globalName]['addModule'] = window[globalName].addModule;
1401
+
1402
+ // Export the UserAgent API because we pass this object to external modules.
1403
+ webfont.UserAgent.prototype['getName'] = webfont.UserAgent.prototype.getName;
1404
+ webfont.UserAgent.prototype['getVersion'] = webfont.UserAgent.prototype.getVersion;
1405
+ webfont.UserAgent.prototype['getEngine'] = webfont.UserAgent.prototype.getEngine;
1406
+ webfont.UserAgent.prototype['getEngineVersion'] = webfont.UserAgent.prototype.getEngineVersion;
1407
+ webfont.UserAgent.prototype['getPlatform'] = webfont.UserAgent.prototype.getPlatform;
1408
+ webfont.UserAgent.prototype['getPlatformVersion'] = webfont.UserAgent.prototype.getPlatformVersion;
1409
+ webfont.UserAgent.prototype['getDocumentMode'] = webfont.UserAgent.prototype.getDocumentMode;
1410
+ webfont.UserAgent.prototype['isSupportingWebFont'] = webfont.UserAgent.prototype.isSupportingWebFont;
1411
+
1412
+ /**
1413
+ *
1414
+ * WebFont.load({
1415
+ * ascender: {
1416
+ * key:'ec2de397-11ae-4c10-937f-bf94283a70c1',
1417
+ * families:['AyitaPro:regular,bold,bolditalic,italic']
1418
+ * }
1419
+ * });
1420
+ *
1421
+ * @constructor
1422
+ */
1423
+ webfont.AscenderScript = function(domHelper, configuration) {
1424
+ this.domHelper_ = domHelper;
1425
+ this.configuration_ = configuration;
1426
+ };
1427
+
1428
+ webfont.AscenderScript.NAME = 'ascender';
1429
+
1430
+ webfont.AscenderScript.VARIATIONS = {
1431
+ 'regular': 'n4',
1432
+ 'bold': 'n7',
1433
+ 'italic': 'i4',
1434
+ 'bolditalic': 'i7',
1435
+ 'r': 'n4',
1436
+ 'b': 'n7',
1437
+ 'i': 'i4',
1438
+ 'bi': 'i7'
1439
+ };
1440
+
1441
+ webfont.AscenderScript.prototype.supportUserAgent = function(userAgent, support) {
1442
+ return support(userAgent.isSupportingWebFont());
1443
+ };
1444
+
1445
+ webfont.AscenderScript.prototype.load = function(onReady) {
1446
+ var key = this.configuration_['key'];
1447
+ var protocol = (('https:' == document.location.protocol) ? 'https:' : 'http:');
1448
+ var url = protocol + '//webfonts.fontslive.com/css/' + key + '.css';
1449
+ this.domHelper_.insertInto('head', this.domHelper_.createCssLink(url));
1450
+ var fv = this.parseFamiliesAndVariations(this.configuration_['families']);
1451
+ onReady(fv.families, fv.variations);
1452
+ };
1453
+
1454
+ webfont.AscenderScript.prototype.parseFamiliesAndVariations = function(providedFamilies){
1455
+ var families, variations, fv;
1456
+ families = [];
1457
+ variations = {};
1458
+ for(var i = 0, len = providedFamilies.length; i < len; i++){
1459
+ fv = this.parseFamilyAndVariations(providedFamilies[i]);
1460
+ families.push(fv.family);
1461
+ variations[fv.family] = fv.variations;
1462
+ }
1463
+ return { families:families, variations:variations };
1464
+ };
1465
+
1466
+ webfont.AscenderScript.prototype.parseFamilyAndVariations = function(providedFamily){
1467
+ var family, variations, parts;
1468
+ parts = providedFamily.split(':');
1469
+ family = parts[0];
1470
+ variations = [];
1471
+ if(parts[1]){
1472
+ variations = this.parseVariations(parts[1]);
1473
+ }else{
1474
+ variations = ['n4'];
1475
+ }
1476
+ return { family:family, variations:variations };
1477
+ };
1478
+
1479
+ webfont.AscenderScript.prototype.parseVariations = function(source){
1480
+ var providedVariations = source.split(',');
1481
+ var variations = [];
1482
+ for(var i = 0, len = providedVariations.length; i < len; i++){
1483
+ var pv = providedVariations[i];
1484
+ if(pv){
1485
+ var v = webfont.AscenderScript.VARIATIONS[pv];
1486
+ variations.push(v ? v : pv);
1487
+ }
1488
+ }
1489
+ return variations;
1490
+ };
1491
+
1492
+ window['WebFont'].addModule(webfont.AscenderScript.NAME, function(configuration) {
1493
+ var userAgentParser = new webfont.UserAgentParser(navigator.userAgent, document);
1494
+ var userAgent = userAgentParser.parse();
1495
+ var domHelper = new webfont.DomHelper(document, userAgent);
1496
+ return new webfont.AscenderScript(domHelper, configuration);
1497
+ });
1498
+
1499
+ /**
1500
+ * @constructor
1501
+ */
1502
+ webfont.LastResortWebKitFontWatchRunner = function(activeCallback,
1503
+ inactiveCallback, domHelper, fontSizer, asyncCall, getTime, fontFamily,
1504
+ fontDescription, opt_fontTestString) {
1505
+ webfont.LastResortWebKitFontWatchRunner.superCtor_.call(this,
1506
+ activeCallback, inactiveCallback, domHelper, fontSizer, asyncCall,
1507
+ getTime, fontFamily, fontDescription, opt_fontTestString);
1508
+ this.webKitLastResortFontSizes_ = this.setUpWebKitLastResortFontSizes_();
1509
+ this.webKitLastResortSizeChange_ = false;
1510
+ };
1511
+ webfont.extendsClass(webfont.FontWatchRunner, webfont.LastResortWebKitFontWatchRunner);
1512
+
1513
+ webfont.LastResortWebKitFontWatchRunner.METRICS_COMPATIBLE_FONTS = {
1514
+ "Arimo": true,
1515
+ "Cousine": true,
1516
+ "Tinos": true
1517
+ };
1518
+
1519
+ /**
1520
+ * While loading a web font webkit applies a last resort fallback font to the
1521
+ * element on which the web font is applied.
1522
+ * See file: WebKit/Source/WebCore/css/CSSFontFaceSource.cpp.
1523
+ * Looking at the different implementation for the different platforms,
1524
+ * the last resort fallback font is different. This code uses the default
1525
+ * OS/browsers values.
1526
+ */
1527
+ webfont.LastResortWebKitFontWatchRunner.prototype
1528
+ .setUpWebKitLastResortFontSizes_ = function() {
1529
+ var lastResortFonts = ["Times New Roman",
1530
+ "Lucida Sans Unicode", "Courier New", "Tahoma", "Arial",
1531
+ "Microsoft Sans Serif", "Times", "Lucida Console", "Sans", "Serif",
1532
+ "Monospace"];
1533
+ var lastResortFontSizes = lastResortFonts.length;
1534
+ var webKitLastResortFontSizes = {};
1535
+ var element = this.createHiddenElementWithFont_(lastResortFonts[0], true);
1536
+
1537
+ webKitLastResortFontSizes[this.fontSizer_.getWidth(element)] = true;
1538
+ for (var i = 1; i < lastResortFontSizes; i++) {
1539
+ var font = lastResortFonts[i];
1540
+ this.domHelper_.setStyle(element, this.computeStyleString_(font,
1541
+ this.fontDescription_, true));
1542
+ webKitLastResortFontSizes[this.fontSizer_.getWidth(element)] = true;
1543
+
1544
+ // Another WebKit quirk if the normal weight/style is loaded first,
1545
+ // the size of the normal weight is returned when loading another weight.
1546
+ if (this.fontDescription_[1] != '4') {
1547
+ this.domHelper_.setStyle(element, this.computeStyleString_(font,
1548
+ this.fontDescription_[0] + '4', true));
1549
+ webKitLastResortFontSizes[this.fontSizer_.getWidth(element)] = true;
1550
+ }
1551
+ }
1552
+ this.domHelper_.removeElement(element);
1553
+ return webKitLastResortFontSizes;
1554
+ };
1555
+
1556
+ webfont.LastResortWebKitFontWatchRunner.prototype.check_ = function() {
1557
+ var sizeA = this.fontSizer_.getWidth(this.requestedFontA_);
1558
+ var sizeB = this.fontSizer_.getWidth(this.requestedFontB_);
1559
+
1560
+ if (!this.webKitLastResortSizeChange_ && sizeA == sizeB &&
1561
+ this.webKitLastResortFontSizes_[sizeA]) {
1562
+ this.webKitLastResortFontSizes_ = {};
1563
+ this.webKitLastResortFontSizes_[sizeA] = true;
1564
+ this.webKitLastResortSizeChange_ = true;
1565
+ }
1566
+ if ((this.originalSizeA_ != sizeA || this.originalSizeB_ != sizeB) &&
1567
+ (!this.webKitLastResortFontSizes_[sizeA] &&
1568
+ !this.webKitLastResortFontSizes_[sizeB])) {
1569
+ this.finish_(this.activeCallback_);
1570
+ } else if (this.getTime_() - this.started_ >= 5000) {
1571
+
1572
+ // In order to handle the fact that a font could be the same size as the
1573
+ // default browser font on a webkit browser, mark the font as active
1574
+ // after 5 seconds if the latest 2 sizes are in webKitLastResortFontSizes_
1575
+ // and the font name is known to be metrics compatible.
1576
+ if (this.webKitLastResortFontSizes_[sizeA]
1577
+ && this.webKitLastResortFontSizes_[sizeB] &&
1578
+ webfont.LastResortWebKitFontWatchRunner.METRICS_COMPATIBLE_FONTS[
1579
+ this.fontFamily_]) {
1580
+ this.finish_(this.activeCallback_);
1581
+ } else {
1582
+ this.finish_(this.inactiveCallback_);
1583
+ }
1584
+ } else {
1585
+ this.asyncCheck_();
1586
+ }
1587
+ };
1588
+
1589
+ /**
1590
+ * @constructor
1591
+ */
1592
+ webfont.FontApiUrlBuilder = function(apiUrl) {
1593
+ if (apiUrl) {
1594
+ this.apiUrl_ = apiUrl;
1595
+ } else {
1596
+ var protocol = 'https:' == window.location.protocol ? 'https:' : 'http:';
1597
+
1598
+ this.apiUrl_ = protocol + webfont.FontApiUrlBuilder.DEFAULT_API_URL;
1599
+ }
1600
+ this.fontFamilies_ = [];
1601
+ this.subsets_ = [];
1602
+ };
1603
+
1604
+
1605
+ webfont.FontApiUrlBuilder.DEFAULT_API_URL = '//fonts.googleapis.com/css';
1606
+
1607
+
1608
+ webfont.FontApiUrlBuilder.prototype.setFontFamilies = function(fontFamilies) {
1609
+ this.parseFontFamilies_(fontFamilies);
1610
+ };
1611
+
1612
+
1613
+ webfont.FontApiUrlBuilder.prototype.parseFontFamilies_ =
1614
+ function(fontFamilies) {
1615
+ var length = fontFamilies.length;
1616
+
1617
+ for (var i = 0; i < length; i++) {
1618
+ var elements = fontFamilies[i].split(':');
1619
+
1620
+ if (elements.length == 3) {
1621
+ this.subsets_.push(elements.pop());
1622
+ }
1623
+ this.fontFamilies_.push(elements.join(':'));
1624
+ }
1625
+ };
1626
+
1627
+
1628
+ webfont.FontApiUrlBuilder.prototype.webSafe = function(string) {
1629
+ return string.replace(/ /g, '+');
1630
+ };
1631
+
1632
+
1633
+ webfont.FontApiUrlBuilder.prototype.build = function() {
1634
+ if (this.fontFamilies_.length == 0) {
1635
+ throw new Error('No fonts to load !');
1636
+ }
1637
+ if (this.apiUrl_.indexOf("kit=") != -1) {
1638
+ return this.apiUrl_;
1639
+ }
1640
+ var length = this.fontFamilies_.length;
1641
+ var sb = [];
1642
+
1643
+ for (var i = 0; i < length; i++) {
1644
+ sb.push(this.webSafe(this.fontFamilies_[i]));
1645
+ }
1646
+ var url = this.apiUrl_ + '?family=' + sb.join('%7C'); // '|' escaped.
1647
+
1648
+ if (this.subsets_.length > 0) {
1649
+ url += '&subset=' + this.subsets_.join(',');
1650
+ }
1651
+
1652
+ return url;
1653
+ };
1654
+
1655
+ /**
1656
+ * @constructor
1657
+ */
1658
+ webfont.FontApiParser = function(fontFamilies) {
1659
+ this.fontFamilies_ = fontFamilies;
1660
+ this.parsedFontFamilies_ = [];
1661
+ this.variations_ = {};
1662
+ this.fontTestStrings_ = {};
1663
+ this.fvd_ = new webfont.FontVariationDescription();
1664
+ };
1665
+
1666
+ webfont.FontApiParser.VARIATIONS = {
1667
+ 'ultralight': 'n2',
1668
+ 'light': 'n3',
1669
+ 'regular': 'n4',
1670
+ 'bold': 'n7',
1671
+ 'italic': 'i4',
1672
+ 'bolditalic': 'i7',
1673
+ 'ul': 'n2',
1674
+ 'l': 'n3',
1675
+ 'r': 'n4',
1676
+ 'b': 'n7',
1677
+ 'i': 'i4',
1678
+ 'bi': 'i7'
1679
+ };
1680
+
1681
+ webfont.FontApiParser.INT_FONTS = {
1682
+ 'latin': webfont.FontWatchRunner.DEFAULT_TEST_STRING,
1683
+ 'cyrillic': '&#1081;&#1103;&#1046;',
1684
+ 'greek': '&#945;&#946;&#931;',
1685
+ 'khmer': '&#x1780;&#x1781;&#x1782;',
1686
+ 'Hanuman': '&#x1780;&#x1781;&#x1782;' // For backward compatibility
1687
+ };
1688
+
1689
+ webfont.FontApiParser.prototype.parse = function() {
1690
+ var length = this.fontFamilies_.length;
1691
+
1692
+ for (var i = 0; i < length; i++) {
1693
+ var elements = this.fontFamilies_[i].split(":");
1694
+ var fontFamily = elements[0];
1695
+ var variations = ['n4'];
1696
+
1697
+ if (elements.length >= 2) {
1698
+ var fvds = this.parseVariations_(elements[1]);
1699
+
1700
+ if (fvds.length > 0) {
1701
+ variations = fvds;
1702
+ }
1703
+ if (elements.length == 3) {
1704
+ var subsets = this.parseSubsets_(elements[2]);
1705
+ if (subsets.length > 0) {
1706
+ var fontTestString = webfont.FontApiParser.INT_FONTS[subsets[0]];
1707
+
1708
+ if (fontTestString) {
1709
+ this.fontTestStrings_[fontFamily] = fontTestString;
1710
+ }
1711
+ }
1712
+ }
1713
+ }
1714
+
1715
+ // For backward compatibility
1716
+ if (!this.fontTestStrings_[fontFamily]) {
1717
+ var hanumanTestString = webfont.FontApiParser.INT_FONTS[fontFamily];
1718
+ if (hanumanTestString) {
1719
+ this.fontTestStrings_[fontFamily] = hanumanTestString;
1720
+ }
1721
+ }
1722
+ this.parsedFontFamilies_.push(fontFamily);
1723
+ this.variations_[fontFamily] = variations;
1724
+ }
1725
+ };
1726
+
1727
+ webfont.FontApiParser.prototype.generateFontVariationDescription_ = function(variation) {
1728
+ if (!variation.match(/^[\w ]+$/)) {
1729
+ return '';
1730
+ }
1731
+
1732
+ var fvd = webfont.FontApiParser.VARIATIONS[variation];
1733
+
1734
+ if (fvd) {
1735
+ return fvd;
1736
+ } else {
1737
+ var groups = variation.match(/^(\d*)(\w*)$/);
1738
+ var numericMatch = groups[1];
1739
+ var styleMatch = groups[2];
1740
+ var s = styleMatch ? styleMatch : 'n';
1741
+ var w = numericMatch ? numericMatch.substr(0, 1) : '4';
1742
+ var css = this.fvd_.expand([s, w].join(''));
1743
+ if (css) {
1744
+ return this.fvd_.compact(css);
1745
+ } else {
1746
+ return null;
1747
+ }
1748
+ }
1749
+ };
1750
+
1751
+ webfont.FontApiParser.prototype.parseVariations_ = function(variations) {
1752
+ var finalVariations = [];
1753
+
1754
+ if (!variations) {
1755
+ return finalVariations;
1756
+ }
1757
+ var providedVariations = variations.split(",");
1758
+ var length = providedVariations.length;
1759
+
1760
+ for (var i = 0; i < length; i++) {
1761
+ var variation = providedVariations[i];
1762
+ var fvd = this.generateFontVariationDescription_(variation);
1763
+
1764
+ if (fvd) {
1765
+ finalVariations.push(fvd);
1766
+ }
1767
+ }
1768
+ return finalVariations;
1769
+ };
1770
+
1771
+
1772
+ webfont.FontApiParser.prototype.parseSubsets_ = function(subsets) {
1773
+ var finalSubsets = [];
1774
+
1775
+ if (!subsets) {
1776
+ return finalSubsets;
1777
+ }
1778
+ return subsets.split(",");
1779
+ };
1780
+
1781
+
1782
+ webfont.FontApiParser.prototype.getFontFamilies = function() {
1783
+ return this.parsedFontFamilies_;
1784
+ };
1785
+
1786
+ webfont.FontApiParser.prototype.getVariations = function() {
1787
+ return this.variations_;
1788
+ };
1789
+
1790
+ webfont.FontApiParser.prototype.getFontTestStrings = function() {
1791
+ return this.fontTestStrings_;
1792
+ };
1793
+
1794
+ /**
1795
+ * @constructor
1796
+ */
1797
+ webfont.GoogleFontApi = function(userAgent, domHelper, configuration) {
1798
+ this.userAgent_ = userAgent;
1799
+ this.domHelper_ = domHelper;
1800
+ this.configuration_ = configuration;
1801
+ };
1802
+
1803
+ webfont.GoogleFontApi.NAME = 'google';
1804
+
1805
+ webfont.GoogleFontApi.prototype.supportUserAgent = function(userAgent, support) {
1806
+ support(userAgent.isSupportingWebFont());
1807
+ };
1808
+
1809
+ webfont.GoogleFontApi.prototype.getFontWatchRunnerCtor = function() {
1810
+ if (this.userAgent_.getEngine() == "AppleWebKit") {
1811
+ return webfont.LastResortWebKitFontWatchRunner;
1812
+ }
1813
+ return webfont.FontWatchRunner;
1814
+ };
1815
+
1816
+ webfont.GoogleFontApi.prototype.load = function(onReady) {
1817
+ var domHelper = this.domHelper_;
1818
+ var nonBlockingIe = this.userAgent_.getName() == 'MSIE' &&
1819
+ this.configuration_['blocking'] != true;
1820
+
1821
+ if (nonBlockingIe) {
1822
+ domHelper.whenBodyExists(webfont.bind(this, this.insertLink_, onReady));
1823
+ } else {
1824
+ this.insertLink_(onReady);
1825
+ }
1826
+ };
1827
+
1828
+ webfont.GoogleFontApi.prototype.insertLink_ = function(onReady) {
1829
+ var domHelper = this.domHelper_;
1830
+ var fontApiUrlBuilder = new webfont.FontApiUrlBuilder(
1831
+ this.configuration_['api']);
1832
+ var fontFamilies = this.configuration_['families'];
1833
+ fontApiUrlBuilder.setFontFamilies(fontFamilies);
1834
+
1835
+ var fontApiParser = new webfont.FontApiParser(fontFamilies);
1836
+ fontApiParser.parse();
1837
+
1838
+ domHelper.insertInto('head', domHelper.createCssLink(
1839
+ fontApiUrlBuilder.build()));
1840
+ onReady(fontApiParser.getFontFamilies(), fontApiParser.getVariations(),
1841
+ fontApiParser.getFontTestStrings());
1842
+ };
1843
+
1844
+ window['WebFont'].addModule(webfont.GoogleFontApi.NAME, function(configuration) {
1845
+ var userAgentParser = new webfont.UserAgentParser(navigator.userAgent, document);
1846
+ var userAgent = userAgentParser.parse();
1847
+ return new webfont.GoogleFontApi(userAgent,
1848
+ new webfont.DomHelper(document, userAgent), configuration);
1849
+ });
1850
+
1851
+ /**
1852
+ *
1853
+ * WebFont.load({
1854
+ * custom: {
1855
+ * families: ['Font1', 'Font2'],
1856
+ * urls: [ 'http://moo', 'http://meuh' ] }
1857
+ * });
1858
+ *
1859
+ * @constructor
1860
+ */
1861
+ webfont.CustomCss = function(domHelper, configuration) {
1862
+ this.domHelper_ = domHelper;
1863
+ this.configuration_ = configuration;
1864
+ };
1865
+
1866
+ webfont.CustomCss.NAME = 'custom';
1867
+
1868
+ webfont.CustomCss.prototype.load = function(onReady) {
1869
+ var urls = this.configuration_['urls'] || [];
1870
+ var families = this.configuration_['families'] || [];
1871
+
1872
+ for (var i = 0, len = urls.length; i < len; i++) {
1873
+ var url = urls[i];
1874
+
1875
+ this.domHelper_.insertInto('head', this.domHelper_.createCssLink(url));
1876
+ }
1877
+ onReady(families);
1878
+ };
1879
+
1880
+ webfont.CustomCss.prototype.supportUserAgent = function(userAgent, support) {
1881
+ return support(userAgent.isSupportingWebFont());
1882
+ };
1883
+
1884
+ window['WebFont'].addModule(webfont.CustomCss.NAME, function(configuration) {
1885
+ var userAgentParser = new webfont.UserAgentParser(navigator.userAgent, document);
1886
+ var userAgent = userAgentParser.parse();
1887
+ var domHelper = new webfont.DomHelper(document, userAgent);
1888
+ return new webfont.CustomCss(domHelper, configuration);
1889
+ });
1890
+
1891
+ /**
1892
+ * @constructor
1893
+ */
1894
+ webfont.FontdeckScript = function(global, domHelper, configuration) {
1895
+ this.global_ = global;
1896
+ this.domHelper_ = domHelper;
1897
+ this.configuration_ = configuration;
1898
+ this.fontFamilies_ = [];
1899
+ this.fontVariations_ = {};
1900
+ this.fvd_ = new webfont.FontVariationDescription();
1901
+ };
1902
+
1903
+ webfont.FontdeckScript.NAME = 'fontdeck';
1904
+ webfont.FontdeckScript.HOOK = '__webfontfontdeckmodule__';
1905
+ webfont.FontdeckScript.API = '//f.fontdeck.com/s/css/js/';
1906
+
1907
+ webfont.FontdeckScript.prototype.getScriptSrc = function(projectId) {
1908
+ var protocol = 'https:' == this.global_.location.protocol ? 'https:' : 'http:';
1909
+ var api = this.configuration_['api'] || webfont.FontdeckScript.API;
1910
+ return protocol + api + this.global_.document.location.hostname + '/' + projectId + '.js';
1911
+ };
1912
+
1913
+ webfont.FontdeckScript.prototype.supportUserAgent = function(userAgent, support) {
1914
+ var projectId = this.configuration_['id'];
1915
+ var self = this;
1916
+
1917
+ if (projectId) {
1918
+ // Provide data to Fontdeck for processing.
1919
+ if (!this.global_[webfont.FontdeckScript.HOOK]) {
1920
+ this.global_[webfont.FontdeckScript.HOOK] = {};
1921
+ }
1922
+
1923
+ // Fontdeck will call this function to indicate support status
1924
+ // and what fonts are provided.
1925
+ this.global_[webfont.FontdeckScript.HOOK][projectId] = function(fontdeckSupports, data) {
1926
+ for (var i = 0, j = data['fonts'].length; i<j; ++i) {
1927
+ var font = data['fonts'][i];
1928
+ // Add the FVDs
1929
+ self.fontFamilies_.push(font['name']);
1930
+ self.fontVariations_[font['name']] = [self.fvd_.compact("font-weight:" + font['weight'] + ";font-style:" + font['style'])];
1931
+ }
1932
+ support(fontdeckSupports);
1933
+ };
1934
+
1935
+ // Call the Fontdeck API.
1936
+ var script = this.domHelper_.createScriptSrc(this.getScriptSrc(projectId));
1937
+ this.domHelper_.insertInto('head', script);
1938
+
1939
+ } else {
1940
+ support(true);
1941
+ }
1942
+ };
1943
+
1944
+ webfont.FontdeckScript.prototype.load = function(onReady) {
1945
+ onReady(this.fontFamilies_, this.fontVariations_);
1946
+ };
1947
+
1948
+ window['WebFont'].addModule(webfont.FontdeckScript.NAME, function(configuration) {
1949
+ var userAgentParser = new webfont.UserAgentParser(navigator.userAgent, document);
1950
+ var userAgent = userAgentParser.parse();
1951
+ var domHelper = new webfont.DomHelper(document, userAgent);
1952
+ return new webfont.FontdeckScript(window, domHelper, configuration);
1953
+ });
1954
+
1955
+ /**
1956
+ webfont.load({
1957
+ monotype: {
1958
+ projectId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'//this is your Fonts.com Web fonts projectId
1959
+ }
1960
+ });
1961
+ */
1962
+
1963
+ /**
1964
+ * @constructor
1965
+ */
1966
+ webfont.MonotypeScript = function (global, userAgent, domHelper, doc, configuration) {
1967
+ this.global_ = global;
1968
+ this.userAgent_ = userAgent;
1969
+ this.domHelper_ = domHelper;
1970
+ this.doc_ = doc;
1971
+ this.configuration_ = configuration;
1972
+ this.fontFamilies_ = [];
1973
+ this.fontVariations_ = {};
1974
+ };
1975
+
1976
+ /**
1977
+ * name of the module through which external API is supposed to call the MonotypeFontAPI.
1978
+ * @const
1979
+ */
1980
+ webfont.MonotypeScript.NAME = 'monotype';
1981
+
1982
+ /**
1983
+ * __mti_fntLst is the name of function that exposes Monotype's font list.
1984
+ * @const
1985
+ */
1986
+ webfont.MonotypeScript.HOOK = '__mti_fntLst';
1987
+
1988
+ /**
1989
+ * __MonotypeAPIScript__ is the id of script added by google API. Currently 'webfonts.fonts.com' supports only one script in a page.
1990
+ * This may require change in future if 'webfonts.fonts.com' begins supporting multiple scripts per page.
1991
+ * @const
1992
+ */
1993
+ webfont.MonotypeScript.SCRIPTID = '__MonotypeAPIScript__';
1994
+
1995
+ webfont.MonotypeScript.prototype.supportUserAgent = function (userAgent, support) {
1996
+ var self = this;
1997
+ var projectId = self.configuration_['projectId'];
1998
+ if (projectId) {
1999
+ var sc = self.domHelper_.createScriptSrc(self.getScriptSrc(projectId));
2000
+ sc["id"] = webfont.MonotypeScript.SCRIPTID + projectId;
2001
+
2002
+ sc["onreadystatechange"] = function (e) {
2003
+ if (sc["readyState"] === "loaded" || sc["readyState"] === "complete") {
2004
+ sc["onreadystatechange"] = null;
2005
+ sc["onload"](e);
2006
+ }
2007
+ };
2008
+
2009
+ sc["onload"] = function (e) {
2010
+ if (self.global_[webfont.MonotypeScript.HOOK + projectId]) {
2011
+ var mti_fnts = self.global_[webfont.MonotypeScript.HOOK + projectId]();
2012
+ if (mti_fnts && mti_fnts.length) {
2013
+ var i;
2014
+ for (i = 0; i < mti_fnts.length; i++) {
2015
+ self.fontFamilies_.push(mti_fnts[i]["fontfamily"]);
2016
+ }
2017
+ }
2018
+ }
2019
+ support(userAgent.isSupportingWebFont());
2020
+ };
2021
+
2022
+ this.domHelper_.insertInto('head', sc);
2023
+ }
2024
+ else {
2025
+ support(true);
2026
+ }
2027
+ };
2028
+
2029
+ webfont.MonotypeScript.prototype.getScriptSrc = function (projectId) {
2030
+ var p = this.protocol();
2031
+ var api = (this.configuration_['api'] || 'fast.fonts.com/jsapi').replace(/^.*http(s?):(\/\/)?/, "");
2032
+ return p + "//" + api + '/' + projectId + '.js';
2033
+ };
2034
+
2035
+ webfont.MonotypeScript.prototype.load = function (onReady) {
2036
+ onReady(this.fontFamilies_, this.fontVariations_);
2037
+ };
2038
+
2039
+ webfont.MonotypeScript.prototype.protocol = function () {
2040
+ var supportedProtocols = ["http:", "https:"];
2041
+ var defaultProtocol = supportedProtocols[0];
2042
+ if (this.doc_ && this.doc_.location && this.doc_.location.protocol) {
2043
+ var i = 0;
2044
+ for (i = 0; i < supportedProtocols.length; i++) {
2045
+ if (this.doc_.location.protocol === supportedProtocols[i]) {
2046
+ return this.doc_.location.protocol;
2047
+ }
2048
+ }
2049
+ }
2050
+
2051
+ return defaultProtocol;
2052
+ };
2053
+
2054
+ window['WebFont'].addModule(webfont.MonotypeScript.NAME, function (configuration) {
2055
+ var userAgentParser = new webfont.UserAgentParser(navigator.userAgent, document);
2056
+ var userAgent = userAgentParser.parse();
2057
+ var domHelper = new webfont.DomHelper(document, userAgent);
2058
+ return new webfont.MonotypeScript(window, userAgent, domHelper, document, configuration);
2059
+ });
2060
+
2061
+ /**
2062
+ * @constructor
2063
+ */
2064
+ webfont.TypekitScript = function(global, domHelper, configuration) {
2065
+ this.global_ = global;
2066
+ this.domHelper_ = domHelper;
2067
+ this.configuration_ = configuration;
2068
+ this.fontFamilies_ = [];
2069
+ this.fontVariations_ = {};
2070
+ };
2071
+
2072
+ webfont.TypekitScript.NAME = 'typekit';
2073
+ webfont.TypekitScript.HOOK = '__webfonttypekitmodule__';
2074
+
2075
+ webfont.TypekitScript.prototype.getScriptSrc = function(kitId) {
2076
+ var protocol = 'https:' == window.location.protocol ? 'https:' : 'http:';
2077
+ var api = this.configuration_['api'] || protocol + '//use.typekit.com';
2078
+ return api + '/' + kitId + '.js';
2079
+ };
2080
+
2081
+ webfont.TypekitScript.prototype.supportUserAgent = function(userAgent, support) {
2082
+ var kitId = this.configuration_['id'];
2083
+ var configuration = this.configuration_;
2084
+ var self = this;
2085
+
2086
+ if (kitId) {
2087
+ // Provide data to Typekit for processing.
2088
+ if (!this.global_[webfont.TypekitScript.HOOK]) {
2089
+ this.global_[webfont.TypekitScript.HOOK] = {};
2090
+ }
2091
+
2092
+ // Typekit will call 'init' to indicate whether it supports fonts
2093
+ // and what fonts will be provided.
2094
+ this.global_[webfont.TypekitScript.HOOK][kitId] = function(callback) {
2095
+ var init = function(typekitSupports, fontFamilies, fontVariations) {
2096
+ self.fontFamilies_ = fontFamilies;
2097
+ self.fontVariations_ = fontVariations;
2098
+ support(typekitSupports);
2099
+ };
2100
+ callback(userAgent, configuration, init);
2101
+ };
2102
+
2103
+ // Load the Typekit script.
2104
+ var script = this.domHelper_.createScriptSrc(this.getScriptSrc(kitId))
2105
+ this.domHelper_.insertInto('head', script);
2106
+
2107
+ } else {
2108
+ support(true);
2109
+ }
2110
+ };
2111
+
2112
+ webfont.TypekitScript.prototype.load = function(onReady) {
2113
+ onReady(this.fontFamilies_, this.fontVariations_);
2114
+ };
2115
+
2116
+ window['WebFont'].addModule(webfont.TypekitScript.NAME, function(configuration) {
2117
+ var userAgentParser = new webfont.UserAgentParser(navigator.userAgent, document);
2118
+ var userAgent = userAgentParser.parse();
2119
+ var domHelper = new webfont.DomHelper(document, userAgent);
2120
+ return new webfont.TypekitScript(window, domHelper, configuration);
2121
+ });
2122
+
2123
+
2124
+ if (window['WebFontConfig']) {
2125
+ window['WebFont']['load'](window['WebFontConfig']);
2126
+ }
2127
+ ;