moj_template 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ ;