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.
- checksums.yaml +7 -0
- data/LICENCE.txt +22 -0
- data/README.md +96 -0
- data/app/assets/images/apple-touch-icon-114x114.png +0 -0
- data/app/assets/images/apple-touch-icon-144x144.png +0 -0
- data/app/assets/images/apple-touch-icon-57x57.png +0 -0
- data/app/assets/images/apple-touch-icon-72x72.png +0 -0
- data/app/assets/images/favicon.ico +0 -0
- data/app/assets/images/gov.uk_logotype_crown.png +0 -0
- data/app/assets/images/gov.uk_logotype_crown_invert.png +0 -0
- data/app/assets/images/gov.uk_logotype_crown_invert_trans.png +0 -0
- data/app/assets/images/open-government-licence_2x.png +0 -0
- data/app/assets/images/opengraph-image.png +0 -0
- data/app/assets/javascripts/govuk-template.js +126 -0
- data/app/assets/javascripts/ie.js +513 -0
- data/app/assets/javascripts/modules/moj.tabs.js +83 -0
- data/app/assets/javascripts/moj.js +54 -0
- data/app/assets/javascripts/vendor/goog/webfont-debug.js +2127 -0
- data/app/assets/javascripts/vendor/jquery/jquery-1.11.0.min.js +5 -0
- data/app/assets/stylesheets/external-link-24x24.png +0 -0
- data/app/assets/stylesheets/external-link-black-12x12.png +0 -0
- data/app/assets/stylesheets/external-link-black-24x24.png +0 -0
- data/app/assets/stylesheets/external-link.png +0 -0
- data/app/assets/stylesheets/fonts-ie8.css.erb +31 -0
- data/app/assets/stylesheets/fonts.css.erb +31 -0
- data/app/assets/stylesheets/fonts/NTA-Bold-20130221.eot +0 -0
- data/app/assets/stylesheets/fonts/NTA-Bold-20130221.woff +0 -0
- data/app/assets/stylesheets/fonts/NTA-Light-20130221.eot +0 -0
- data/app/assets/stylesheets/fonts/NTA-Light-20130221.woff +0 -0
- data/app/assets/stylesheets/fonts/NTATabularNumbers-Bold.eot +0 -0
- data/app/assets/stylesheets/fonts/NTATabularNumbers-Bold.woff +0 -0
- data/app/assets/stylesheets/fonts/NTATabularNumbers-Light.eot +0 -0
- data/app/assets/stylesheets/fonts/NTATabularNumbers-Light.woff +0 -0
- data/app/assets/stylesheets/govuk-template-ie6.css.erb +652 -0
- data/app/assets/stylesheets/govuk-template-ie7.css.erb +648 -0
- data/app/assets/stylesheets/govuk-template-ie8.css.erb +631 -0
- data/app/assets/stylesheets/govuk-template-print.css.erb +78 -0
- data/app/assets/stylesheets/govuk-template.css.erb +691 -0
- data/app/assets/stylesheets/images/close.png +0 -0
- data/app/assets/stylesheets/images/govuk-crest-2x.png +0 -0
- data/app/assets/stylesheets/images/govuk-crest-ie.png +0 -0
- data/app/assets/stylesheets/images/govuk-crest.png +0 -0
- data/app/assets/stylesheets/images/separator-2x.png +0 -0
- data/app/assets/stylesheets/images/separator.png +0 -0
- data/app/assets/stylesheets/moj-template.css.erb +628 -0
- data/app/helpers/moj_helper.rb +9 -0
- data/app/views/layouts/moj_template.html.erb +223 -0
- data/lib/moj_template.rb +5 -0
- data/lib/moj_template/engine.rb +17 -0
- data/lib/moj_template/version.rb +3 -0
- data/lib/tasks/moj_template_tasks.rake +4 -0
- 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': 'йяЖ',
|
1684
|
+
'greek': 'αβΣ',
|
1685
|
+
'khmer': 'កខគ',
|
1686
|
+
'Hanuman': 'កខគ' // 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
|
+
;
|