mirror of
https://ghproxy.net/https://github.com/AlxMedia/magaziner.git
synced 2025-08-28 12:37:59 +08:00
Initial commit
This commit is contained in:
commit
b0607606ae
369 changed files with 85494 additions and 0 deletions
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
/**
|
||||
* WebFont-Loader Module.
|
||||
*
|
||||
* @see https://github.com/typekit/webfontloader
|
||||
* @package Kirki
|
||||
* @category Modules
|
||||
* @author Ari Stathopoulos (@aristath)
|
||||
* @copyright Copyright (c) 2019, Ari Stathopoulos (@aristath)
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
* @since 3.0.26
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds script for tooltips.
|
||||
*/
|
||||
class Kirki_Modules_Webfont_Loader {
|
||||
|
||||
/**
|
||||
* The object instance.
|
||||
*
|
||||
* @static
|
||||
* @access private
|
||||
* @since 3.0.26
|
||||
* @var object
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Only load the webfont script if this is true.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @since 3.0.26
|
||||
* @var bool
|
||||
*/
|
||||
public static $load = false;
|
||||
|
||||
/**
|
||||
* The class constructor
|
||||
*
|
||||
* @access protected
|
||||
* @since 3.0.26
|
||||
*/
|
||||
protected function __construct() {
|
||||
add_action( 'wp_head', array( $this, 'enqueue_scripts' ), 20 );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 20 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instance of this object.
|
||||
* Prevents duplicate instances which avoid artefacts and improves performance.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @since 3.0.26
|
||||
* @return object
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( ! self::$instance ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts.
|
||||
*
|
||||
* @access public
|
||||
* @since 3.0.26
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
global $wp_customize;
|
||||
if ( self::$load || $wp_customize || is_customize_preview() ) {
|
||||
wp_enqueue_script( 'webfont-loader', trailingslashit( Kirki::$url ) . 'modules/webfont-loader/vendor-typekit/webfontloader.js', array(), '3.0.28', true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $load property of this object.
|
||||
*
|
||||
* @access public
|
||||
* @since 3.0.35
|
||||
* @param bool $load Set to false to disable loading.
|
||||
* @return void
|
||||
*/
|
||||
public function set_load( $load ) {
|
||||
self::$load = $load;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
/* Web Font Loader v{{version}} - (c) Adobe Systems, Google. License: Apache 2.0 */
|
||||
(function(){{{source}}}());
|
|
@ -0,0 +1,46 @@
|
|||
goog.provide('webfont.CssClassName');
|
||||
|
||||
/**
|
||||
* Handles sanitization and construction of css class names.
|
||||
* @param {string=} opt_joinChar The character to join parts of the name on.
|
||||
* Defaults to '-'.
|
||||
* @constructor
|
||||
*/
|
||||
webfont.CssClassName = function(opt_joinChar) {
|
||||
/** @type {string} */
|
||||
this.joinChar_ = opt_joinChar || webfont.CssClassName.DEFAULT_JOIN_CHAR;
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.CssClassName.DEFAULT_JOIN_CHAR = '-';
|
||||
|
||||
goog.scope(function () {
|
||||
var CssClassName = webfont.CssClassName;
|
||||
|
||||
/**
|
||||
* Sanitizes a string for use as a css class name. Removes non-word and
|
||||
* underscore characters.
|
||||
* @param {string} name The string.
|
||||
* @return {string} The sanitized string.
|
||||
*/
|
||||
CssClassName.prototype.sanitize = function(name) {
|
||||
return name.replace(/[\W_]+/g, '').toLowerCase();
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds a complete css class name given a variable number of parts.
|
||||
* Sanitizes, then joins the parts together.
|
||||
* @param {...string} var_args The parts to join.
|
||||
* @return {string} The sanitized and joined string.
|
||||
*/
|
||||
CssClassName.prototype.build = function(var_args) {
|
||||
var parts = []
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
parts.push(this.sanitize(arguments[i]));
|
||||
}
|
||||
return parts.join(this.joinChar_);
|
||||
};
|
||||
});
|
|
@ -0,0 +1,405 @@
|
|||
goog.provide('webfont.DomHelper');
|
||||
|
||||
/**
|
||||
* Handles common DOM manipulation tasks. The aim of this library is to cover
|
||||
* the needs of typical font loading. Not more, not less.
|
||||
* @param {Window} mainWindow The main window webfontloader.js is loaded in.
|
||||
* @param {Window=} opt_loadWindow The window we'll load the font into. By
|
||||
* default, the main window is used.
|
||||
* @constructor
|
||||
*/
|
||||
webfont.DomHelper = function(mainWindow, opt_loadWindow) {
|
||||
this.mainWindow_ = mainWindow;
|
||||
this.loadWindow_ = opt_loadWindow || mainWindow;
|
||||
|
||||
/** @type {string} */
|
||||
this.protocol_;
|
||||
|
||||
/** @type {Document} */
|
||||
this.document_ = this.loadWindow_.document;
|
||||
};
|
||||
|
||||
goog.scope(function () {
|
||||
var DomHelper = webfont.DomHelper;
|
||||
|
||||
/**
|
||||
* The NativeFontWatchRunnner depends on the correct and reliable
|
||||
* |onload| event, and browsers with the native font loading API
|
||||
* have reliable @onload support as far as we know. So we use the
|
||||
* event for such a case and unconditionally invokes the callback
|
||||
* otherwise.
|
||||
*
|
||||
* @const
|
||||
* @type {boolean}
|
||||
*/
|
||||
DomHelper.CAN_WAIT_STYLESHEET = !!window['FontFace'];
|
||||
|
||||
/**
|
||||
* Creates an element.
|
||||
* @param {string} elem The element type.
|
||||
* @param {Object=} opt_attr A hash of attribute key/value pairs.
|
||||
* @param {string=} opt_innerHtml Contents of the element.
|
||||
* @return {Element} the new element.
|
||||
*/
|
||||
DomHelper.prototype.createElement = function(elem, opt_attr,
|
||||
opt_innerHtml) {
|
||||
var domElement = this.document_.createElement(elem);
|
||||
|
||||
if (opt_attr) {
|
||||
for (var attr in opt_attr) {
|
||||
// protect against native prototype augmentations
|
||||
if (opt_attr.hasOwnProperty(attr)) {
|
||||
if (attr == "style") {
|
||||
this.setStyle(domElement, opt_attr[attr]);
|
||||
} else {
|
||||
domElement.setAttribute(attr, opt_attr[attr]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opt_innerHtml) {
|
||||
domElement.appendChild(this.document_.createTextNode(opt_innerHtml));
|
||||
}
|
||||
return domElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts an element into the document. This is intended for unambiguous
|
||||
* elements such as html, body, head.
|
||||
* @param {string} tagName The element name.
|
||||
* @param {Element} e The element to append.
|
||||
* @return {boolean} True if the element was inserted.
|
||||
*/
|
||||
DomHelper.prototype.insertInto = function(tagName, e) {
|
||||
var t = this.document_.getElementsByTagName(tagName)[0];
|
||||
|
||||
if (!t) { // opera allows documents without a head
|
||||
t = document.documentElement;
|
||||
}
|
||||
|
||||
// This is safer than appendChild in IE. appendChild causes random
|
||||
// JS errors in IE. Sometimes errors in other JS exectution, sometimes
|
||||
// complete 'This page cannot be displayed' errors. For our purposes,
|
||||
// it's equivalent because we don't need to insert at any specific
|
||||
// location.
|
||||
t.insertBefore(e, t.lastChild);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls a function when the body tag exists.
|
||||
* @param {function()} callback The function to call.
|
||||
*/
|
||||
DomHelper.prototype.whenBodyExists = function(callback) {
|
||||
var that = this;
|
||||
|
||||
if (that.document_.body) {
|
||||
callback();
|
||||
} else {
|
||||
if (that.document_.addEventListener) {
|
||||
that.document_.addEventListener('DOMContentLoaded', callback);
|
||||
} else {
|
||||
that.document_.attachEvent('onreadystatechange', function () {
|
||||
if (that.document_.readyState == 'interactive' || that.document_.readyState == 'complete') {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes an element from the DOM.
|
||||
* @param {Element} node The element to remove.
|
||||
* @return {boolean} True if the element was removed.
|
||||
*/
|
||||
DomHelper.prototype.removeElement = function(node) {
|
||||
if (node.parentNode) {
|
||||
node.parentNode.removeChild(node);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated Use updateClassName().
|
||||
*
|
||||
* Appends a name to an element's class attribute.
|
||||
* @param {Element} e The element.
|
||||
* @param {string} name The class name to add.
|
||||
*/
|
||||
DomHelper.prototype.appendClassName = function(e, name) {
|
||||
this.updateClassName(e, [name]);
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated Use updateClassName().
|
||||
*
|
||||
* Removes a name to an element's class attribute.
|
||||
* @param {Element} e The element.
|
||||
* @param {string} name The class name to remove.
|
||||
*/
|
||||
DomHelper.prototype.removeClassName = function(e, name) {
|
||||
this.updateClassName(e, null, [name]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates an element's class attribute in a single change. This
|
||||
* allows multiple updates in a single class name change so there
|
||||
* is no chance for a browser to relayout in between changes.
|
||||
*
|
||||
* @param {Element} e The element.
|
||||
* @param {Array.<string>=} opt_add List of class names to add.
|
||||
* @param {Array.<string>=} opt_remove List of class names to remove.
|
||||
*/
|
||||
DomHelper.prototype.updateClassName = function (e, opt_add, opt_remove) {
|
||||
var add = opt_add || [],
|
||||
remove = opt_remove || [];
|
||||
|
||||
var classes = e.className.split(/\s+/);
|
||||
|
||||
for (var i = 0; i < add.length; i += 1) {
|
||||
var found = false;
|
||||
|
||||
for (var j = 0; j < classes.length; j += 1) {
|
||||
if (add[i] === classes[j]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
classes.push(add[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var remainingClasses = [];
|
||||
|
||||
for (var i = 0; i < classes.length; i += 1) {
|
||||
var found = false;
|
||||
|
||||
for (var j = 0; j < remove.length; j += 1) {
|
||||
if (classes[i] === remove[j]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
remainingClasses.push(classes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
e.className = remainingClasses.join(' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/^\s+|\s+$/, '');
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if an element has a given class name and false otherwise.
|
||||
* @param {Element} e The element.
|
||||
* @param {string} name The class name to check for.
|
||||
* @return {boolean} Whether or not the element has this class name.
|
||||
*/
|
||||
DomHelper.prototype.hasClassName = function(e, name) {
|
||||
var classes = e.className.split(/\s+/);
|
||||
for (var i = 0, len = classes.length; i < len; i++) {
|
||||
if (classes[i] == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the style attribute on an element.
|
||||
* @param {Element} e The element.
|
||||
* @param {string} styleString The style string.
|
||||
*/
|
||||
DomHelper.prototype.setStyle = function(e, styleString) {
|
||||
e.style.cssText = styleString;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Window} The main window webfontloader.js is loaded in (for config).
|
||||
*/
|
||||
DomHelper.prototype.getMainWindow = function() {
|
||||
return this.mainWindow_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Window} The window that we're loading the font(s) into.
|
||||
*/
|
||||
DomHelper.prototype.getLoadWindow = function() {
|
||||
return this.loadWindow_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the hostname of the current document.
|
||||
* @return {string} hostname.
|
||||
*/
|
||||
DomHelper.prototype.getHostName = function() {
|
||||
return this.getLoadWindow().location.hostname || this.getMainWindow().location.hostname;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a style element.
|
||||
* @param {string} css Contents of the style element.
|
||||
* @return {Element} a DOM element.
|
||||
*/
|
||||
DomHelper.prototype.createStyle = function(css) {
|
||||
var e = this.createElement('style');
|
||||
|
||||
e.setAttribute('type', 'text/css');
|
||||
if (e.styleSheet) { // IE
|
||||
e.styleSheet.cssText = css;
|
||||
} else {
|
||||
e.appendChild(document.createTextNode(css));
|
||||
}
|
||||
return e;
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads an external stylesheet.
|
||||
*
|
||||
* @param {string} href the URL of the stylesheet
|
||||
* @param {function(Error)=} opt_callback Called when the stylesheet has loaded or failed to
|
||||
* load. Note that the callback is *NOT* guaranteed to be called in all browsers. The first
|
||||
* argument to the callback is an error object that is falsy when there are no errors and
|
||||
* truthy when there are.
|
||||
* @param {boolean=} opt_async True if the stylesheet should be loaded asynchronously. Defaults to false.
|
||||
* @return {Element} The link element
|
||||
*/
|
||||
DomHelper.prototype.loadStylesheet = function (href, opt_callback, opt_async) {
|
||||
var link = this.createElement('link', {
|
||||
'rel': 'stylesheet',
|
||||
'href': href,
|
||||
'media': (opt_async ? 'only x' : 'all')
|
||||
});
|
||||
|
||||
var sheets = this.document_.styleSheets,
|
||||
eventFired = false,
|
||||
asyncResolved = !opt_async,
|
||||
callbackArg = null,
|
||||
callback = opt_callback || null;
|
||||
|
||||
function mayInvokeCallback() {
|
||||
if (callback && eventFired && asyncResolved) {
|
||||
callback(callbackArg);
|
||||
callback = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (DomHelper.CAN_WAIT_STYLESHEET) {
|
||||
link.onload = function () {
|
||||
eventFired = true;
|
||||
mayInvokeCallback();
|
||||
};
|
||||
|
||||
link.onerror = function () {
|
||||
eventFired = true;
|
||||
callbackArg = new Error('Stylesheet failed to load');
|
||||
mayInvokeCallback();
|
||||
};
|
||||
} else {
|
||||
// Some callers expect opt_callback being called asynchronously.
|
||||
setTimeout(function () {
|
||||
eventFired = true;
|
||||
mayInvokeCallback();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function onStylesheetAvailable(callback) {
|
||||
for (var i = 0; i < sheets.length; i++) {
|
||||
if (sheets[i].href && sheets[i].href.indexOf(href) !== -1) {
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
onStylesheetAvailable(callback);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function onMediaAvailable(callback) {
|
||||
for (var i = 0; i < sheets.length; i++) {
|
||||
if (sheets[i].href && sheets[i].href.indexOf(href) !== -1 && sheets[i].media) {
|
||||
/**
|
||||
* @type {string|MediaList|null}
|
||||
*/
|
||||
var media = sheets[i].media;
|
||||
|
||||
if (media === "all" || (media.mediaText && media.mediaText === "all")) {
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
onMediaAvailable(callback);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
this.insertInto('head', link);
|
||||
|
||||
if (opt_async) {
|
||||
onStylesheetAvailable(function () {
|
||||
link.media = "all";
|
||||
// The media type change doesn't take effect immediately on Chrome, so
|
||||
// we'll query the media attribute on the stylesheet until it changes
|
||||
// to "all".
|
||||
onMediaAvailable(function () {
|
||||
asyncResolved = true;
|
||||
mayInvokeCallback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return link;
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads an external script file.
|
||||
* @param {string} src URL of the script.
|
||||
* @param {function(Error)=} opt_callback callback when the script has loaded. The first argument to
|
||||
* the callback is an error object that is falsy when there are no errors and truthy when there are.
|
||||
* @param {number=} opt_timeout The number of milliseconds after which the callback will be called
|
||||
* with a timeout error. Defaults to 5 seconds.
|
||||
* @return {Element} The script element
|
||||
*/
|
||||
DomHelper.prototype.loadScript = function(src, opt_callback, opt_timeout) {
|
||||
var head = this.document_.getElementsByTagName('head')[0];
|
||||
|
||||
if (head) {
|
||||
var script = this.createElement('script', {
|
||||
'src': src
|
||||
});
|
||||
var done = false;
|
||||
script.onload = script.onreadystatechange = function() {
|
||||
if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
|
||||
done = true;
|
||||
if (opt_callback) {
|
||||
opt_callback(null);
|
||||
}
|
||||
script.onload = script.onreadystatechange = null;
|
||||
// Avoid a bizarre issue with unclosed <base> tag in IE6 - http://blog.dotsmart.net/2008/04/
|
||||
if (script.parentNode.tagName == 'HEAD') head.removeChild(script);
|
||||
}
|
||||
};
|
||||
head.appendChild(script);
|
||||
|
||||
setTimeout(function () {
|
||||
if (!done) {
|
||||
done = true;
|
||||
if (opt_callback) {
|
||||
opt_callback(new Error('Script load timeout'));
|
||||
}
|
||||
}
|
||||
}, opt_timeout || 5000);
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
});
|
|
@ -0,0 +1,195 @@
|
|||
goog.provide('webfont.EventDispatcher');
|
||||
|
||||
goog.require('webfont.CssClassName');
|
||||
|
||||
/**
|
||||
* A class to dispatch events and manage the event class names on an html
|
||||
* element that represent the current state of fonts on the page. Active class
|
||||
* names always overwrite inactive class names of the same type, while loading
|
||||
* class names may be present whenever a font is loading (regardless of if an
|
||||
* associated active or inactive class name is also present).
|
||||
*
|
||||
* @param {webfont.DomHelper} domHelper
|
||||
* @param {Object} config
|
||||
* @constructor
|
||||
*/
|
||||
webfont.EventDispatcher = function(domHelper, config) {
|
||||
this.domHelper_ = domHelper;
|
||||
this.htmlElement_ = domHelper.getLoadWindow().document.documentElement;
|
||||
this.callbacks_ = config;
|
||||
this.namespace_ = webfont.EventDispatcher.DEFAULT_NAMESPACE;
|
||||
this.cssClassName_ = new webfont.CssClassName('-');
|
||||
this.dispatchEvents_ = config['events'] !== false;
|
||||
this.setClasses_ = config['classes'] !== false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.EventDispatcher.DEFAULT_NAMESPACE = 'wf';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.EventDispatcher.LOADING = 'loading';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.EventDispatcher.ACTIVE = 'active';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.EventDispatcher.INACTIVE = 'inactive';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.EventDispatcher.FONT = 'font';
|
||||
|
||||
goog.scope(function () {
|
||||
var EventDispatcher = webfont.EventDispatcher;
|
||||
|
||||
/**
|
||||
* Dispatch the loading event and append the loading class name.
|
||||
*/
|
||||
EventDispatcher.prototype.dispatchLoading = function() {
|
||||
if (this.setClasses_) {
|
||||
this.domHelper_.updateClassName(this.htmlElement_,
|
||||
[
|
||||
this.cssClassName_.build(this.namespace_, webfont.EventDispatcher.LOADING)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
this.dispatch_(webfont.EventDispatcher.LOADING);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatch the font loading event and append the font loading class name.
|
||||
* @param {webfont.Font} font
|
||||
*/
|
||||
EventDispatcher.prototype.dispatchFontLoading = function(font) {
|
||||
if (this.setClasses_) {
|
||||
this.domHelper_.updateClassName(this.htmlElement_,
|
||||
[
|
||||
this.cssClassName_.build(this.namespace_, font.getName(), font.getVariation().toString(), webfont.EventDispatcher.LOADING)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
this.dispatch_(webfont.EventDispatcher.FONT + webfont.EventDispatcher.LOADING, font);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatch the font active event, remove the font loading class name, remove
|
||||
* the font inactive class name, and append the font active class name.
|
||||
* @param {webfont.Font} font
|
||||
*/
|
||||
EventDispatcher.prototype.dispatchFontActive = function(font) {
|
||||
if (this.setClasses_) {
|
||||
this.domHelper_.updateClassName(
|
||||
this.htmlElement_,
|
||||
[
|
||||
this.cssClassName_.build(this.namespace_, font.getName(), font.getVariation().toString(), webfont.EventDispatcher.ACTIVE)
|
||||
],
|
||||
[
|
||||
this.cssClassName_.build(this.namespace_, font.getName(), font.getVariation().toString(), webfont.EventDispatcher.LOADING),
|
||||
this.cssClassName_.build(this.namespace_, font.getName(), font.getVariation().toString(), webfont.EventDispatcher.INACTIVE)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
this.dispatch_(webfont.EventDispatcher.FONT + webfont.EventDispatcher.ACTIVE, font);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatch the font inactive event, remove the font loading class name, and
|
||||
* append the font inactive class name (unless the font active class name is
|
||||
* already present).
|
||||
* @param {webfont.Font} font
|
||||
*/
|
||||
EventDispatcher.prototype.dispatchFontInactive = function(font) {
|
||||
if (this.setClasses_) {
|
||||
var hasFontActive = this.domHelper_.hasClassName(this.htmlElement_,
|
||||
this.cssClassName_.build(this.namespace_, font.getName(), font.getVariation().toString(), webfont.EventDispatcher.ACTIVE)
|
||||
),
|
||||
add = [],
|
||||
remove = [
|
||||
this.cssClassName_.build(this.namespace_, font.getName(), font.getVariation().toString(), webfont.EventDispatcher.LOADING)
|
||||
];
|
||||
|
||||
if (!hasFontActive) {
|
||||
add.push(this.cssClassName_.build(this.namespace_, font.getName(), font.getVariation().toString(), webfont.EventDispatcher.INACTIVE));
|
||||
}
|
||||
|
||||
this.domHelper_.updateClassName(this.htmlElement_, add, remove);
|
||||
}
|
||||
|
||||
this.dispatch_(webfont.EventDispatcher.FONT + webfont.EventDispatcher.INACTIVE, font);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatch the inactive event, remove the loading class name, and append the
|
||||
* inactive class name (unless the active class name is already present).
|
||||
*/
|
||||
EventDispatcher.prototype.dispatchInactive = function() {
|
||||
if (this.setClasses_) {
|
||||
var hasActive = this.domHelper_.hasClassName(this.htmlElement_,
|
||||
this.cssClassName_.build(this.namespace_, webfont.EventDispatcher.ACTIVE)
|
||||
),
|
||||
add = [],
|
||||
remove = [
|
||||
this.cssClassName_.build(this.namespace_, webfont.EventDispatcher.LOADING)
|
||||
];
|
||||
|
||||
if (!hasActive) {
|
||||
add.push(this.cssClassName_.build(this.namespace_, webfont.EventDispatcher.INACTIVE));
|
||||
}
|
||||
|
||||
this.domHelper_.updateClassName(this.htmlElement_, add, remove);
|
||||
}
|
||||
|
||||
this.dispatch_(webfont.EventDispatcher.INACTIVE);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatch the active event, remove the loading class name, remove the inactive
|
||||
* class name, and append the active class name.
|
||||
*/
|
||||
EventDispatcher.prototype.dispatchActive = function() {
|
||||
if (this.setClasses_) {
|
||||
this.domHelper_.updateClassName(this.htmlElement_,
|
||||
[
|
||||
this.cssClassName_.build(this.namespace_, webfont.EventDispatcher.ACTIVE)
|
||||
],
|
||||
[
|
||||
this.cssClassName_.build(this.namespace_, webfont.EventDispatcher.LOADING),
|
||||
this.cssClassName_.build(this.namespace_, webfont.EventDispatcher.INACTIVE)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
this.dispatch_(webfont.EventDispatcher.ACTIVE);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} event
|
||||
* @param {webfont.Font=} opt_font
|
||||
*/
|
||||
EventDispatcher.prototype.dispatch_ = function(event, opt_font) {
|
||||
if (this.dispatchEvents_ && this.callbacks_[event]) {
|
||||
if (opt_font) {
|
||||
this.callbacks_[event](opt_font.getName(), opt_font.getVariation());
|
||||
} else {
|
||||
this.callbacks_[event]();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
|
@ -0,0 +1,140 @@
|
|||
goog.provide('webfont.Font');
|
||||
|
||||
/**
|
||||
* This class is an abstraction for a single font or typeface.
|
||||
* It contains the font name and the variation (i.e. style
|
||||
* and weight.) A collection Font instances can represent a
|
||||
* font family.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} name The font family name
|
||||
* @param {string=} opt_variation A font variation description
|
||||
*/
|
||||
webfont.Font = function (name, opt_variation) {
|
||||
this.name_ = name;
|
||||
this.weight_ = 4;
|
||||
this.style_ = 'n'
|
||||
|
||||
var variation = opt_variation || 'n4',
|
||||
match = variation.match(/^([nio])([1-9])$/i);
|
||||
|
||||
if (match) {
|
||||
this.style_ = match[1];
|
||||
this.weight_ = parseInt(match[2], 10);
|
||||
}
|
||||
};
|
||||
|
||||
goog.scope(function () {
|
||||
var Font = webfont.Font;
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
Font.prototype.getName = function () {
|
||||
return this.name_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
Font.prototype.getCssName = function () {
|
||||
return this.quote_(this.name_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a CSS string representation of the font that
|
||||
* can be used as the CSS font property shorthand.
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
Font.prototype.toCssString = function () {
|
||||
return this.getCssStyle() + ' ' + this.getCssWeight() + ' 300px ' + this.getCssName();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} name
|
||||
* @return {string}
|
||||
*/
|
||||
Font.prototype.quote_ = function (name) {
|
||||
var quoted = [];
|
||||
var split = name.split(/,\s*/);
|
||||
for (var i = 0; i < split.length; i++) {
|
||||
var part = split[i].replace(/['"]/g, '');
|
||||
if (part.indexOf(' ') == -1 && !(/^\d/.test(part))) {
|
||||
quoted.push(part);
|
||||
} else {
|
||||
quoted.push("'" + part + "'");
|
||||
}
|
||||
}
|
||||
return quoted.join(',');
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
Font.prototype.getVariation = function () {
|
||||
return this.style_ + this.weight_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
Font.prototype.getCssVariation = function () {
|
||||
return 'font-style:' + this.getCssStyle() + ';font-weight:' + this.getCssWeight() + ';';
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
Font.prototype.getCssWeight = function () {
|
||||
return this.weight_ + '00';
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
Font.prototype.getCssStyle = function () {
|
||||
var style = 'normal';
|
||||
|
||||
if (this.style_ === 'o') {
|
||||
style = 'oblique';
|
||||
} else if (this.style_ === 'i') {
|
||||
style = 'italic';
|
||||
}
|
||||
|
||||
return style;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a CSS font declaration and returns a font
|
||||
* variation description.
|
||||
*
|
||||
* @param {string} css
|
||||
* @return {string}
|
||||
*/
|
||||
Font.parseCssVariation = function (css) {
|
||||
var weight = 4,
|
||||
style = 'n',
|
||||
m = null;
|
||||
|
||||
if (css) {
|
||||
m = css.match(/(normal|oblique|italic)/i);
|
||||
|
||||
if (m && m[1]) {
|
||||
style = m[1].substr(0, 1).toLowerCase();
|
||||
}
|
||||
|
||||
m = css.match(/([1-9]00|normal|bold)/i);
|
||||
|
||||
if (m && m[1]) {
|
||||
if (/bold/i.test(m[1])) {
|
||||
weight = 7;
|
||||
} else if (/[1-9]00/.test(m[1])) {
|
||||
weight = parseInt(m[1].substr(0, 1), 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
return style + weight;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
goog.provide('webfont.FontModule');
|
||||
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
webfont.FontModule = function () {};
|
||||
|
||||
goog.scope(function () {
|
||||
var FontModule = webfont.FontModule;
|
||||
|
||||
/**
|
||||
* @param {function(Array.<webfont.Font>, webfont.FontTestStrings=, Object.<string, boolean>=)} onReady
|
||||
*/
|
||||
FontModule.prototype.load = function (onReady) {};
|
||||
});
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
goog.provide('webfont.FontModuleLoader');
|
||||
goog.provide('webfont.FontModuleFactory');
|
||||
|
||||
/** @typedef {function(Object, webfont.DomHelper): webfont.FontModule} */
|
||||
webfont.FontModuleFactory;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
webfont.FontModuleLoader = function() {
|
||||
/**
|
||||
* @type {Object.<string, webfont.FontModuleFactory>}
|
||||
*/
|
||||
this.modules_ = {};
|
||||
};
|
||||
|
||||
goog.scope(function () {
|
||||
var FontModuleLoader = webfont.FontModuleLoader;
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {webfont.FontModuleFactory} factory
|
||||
*/
|
||||
FontModuleLoader.prototype.addModuleFactory = function(name, factory) {
|
||||
this.modules_[name] = factory;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Object} configuration
|
||||
* @param {webfont.DomHelper} domHelper
|
||||
* @return {Array.<webfont.FontModule>}
|
||||
*/
|
||||
FontModuleLoader.prototype.getModules = function(configuration, domHelper) {
|
||||
var modules = [];
|
||||
|
||||
for (var key in configuration) {
|
||||
if (configuration.hasOwnProperty(key)) {
|
||||
var moduleFactory = this.modules_[key];
|
||||
|
||||
if (moduleFactory) {
|
||||
modules.push(moduleFactory(configuration[key], domHelper));
|
||||
}
|
||||
}
|
||||
}
|
||||
return modules;
|
||||
};
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
goog.provide('webfont.FontRuler');
|
||||
|
||||
/**
|
||||
* An element that can be used to measure the metrics
|
||||
* of a given font and string.
|
||||
* @constructor
|
||||
* @param {webfont.DomHelper} domHelper
|
||||
* @param {string} fontTestString
|
||||
*/
|
||||
webfont.FontRuler = function (domHelper, fontTestString) {
|
||||
this.domHelper_ = domHelper;
|
||||
this.fontTestString_ = fontTestString;
|
||||
this.el_ = this.domHelper_.createElement('span', {
|
||||
"aria-hidden": "true"
|
||||
}, this.fontTestString_);
|
||||
};
|
||||
|
||||
goog.scope(function () {
|
||||
var FontRuler = webfont.FontRuler;
|
||||
|
||||
/**
|
||||
* @param {webfont.Font} font
|
||||
*/
|
||||
FontRuler.prototype.setFont = function(font) {
|
||||
this.domHelper_.setStyle(this.el_, this.computeStyleString_(font));
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts the ruler into the DOM.
|
||||
*/
|
||||
FontRuler.prototype.insert = function() {
|
||||
this.domHelper_.insertInto('body', this.el_);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {webfont.Font} font
|
||||
* @return {string}
|
||||
*/
|
||||
FontRuler.prototype.computeStyleString_ = function(font) {
|
||||
return "display:block;position:absolute;top:-9999px;left:-9999px;" +
|
||||
"font-size:300px;width:auto;height:auto;line-height:normal;margin:0;" +
|
||||
"padding:0;font-variant:normal;white-space:nowrap;font-family:" +
|
||||
font.getCssName() + ";" + font.getCssVariation();
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {number}
|
||||
*/
|
||||
FontRuler.prototype.getWidth = function() {
|
||||
return this.el_.offsetWidth;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the ruler element from the DOM.
|
||||
*/
|
||||
FontRuler.prototype.remove = function() {
|
||||
this.domHelper_.removeElement(this.el_);
|
||||
};
|
||||
});
|
|
@ -0,0 +1,171 @@
|
|||
goog.provide('webfont.FontWatcher');
|
||||
|
||||
goog.require('webfont.FontWatchRunner');
|
||||
goog.require('webfont.NativeFontWatchRunner');
|
||||
|
||||
/**
|
||||
* @typedef {Object.<string, Array.<string>>}
|
||||
*/
|
||||
webfont.FontTestStrings;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {webfont.DomHelper} domHelper
|
||||
* @param {webfont.EventDispatcher} eventDispatcher
|
||||
* @param {number=} opt_timeout
|
||||
*/
|
||||
webfont.FontWatcher = function(domHelper, eventDispatcher, opt_timeout) {
|
||||
this.domHelper_ = domHelper;
|
||||
this.eventDispatcher_ = eventDispatcher;
|
||||
this.currentlyWatched_ = 0;
|
||||
this.last_ = false;
|
||||
this.success_ = false;
|
||||
this.timeout_ = opt_timeout;
|
||||
};
|
||||
|
||||
goog.scope(function () {
|
||||
var FontWatcher = webfont.FontWatcher,
|
||||
FontWatchRunner = webfont.FontWatchRunner,
|
||||
NativeFontWatchRunner = webfont.NativeFontWatchRunner;
|
||||
|
||||
/**
|
||||
* @type {null|boolean}
|
||||
*/
|
||||
FontWatcher.SHOULD_USE_NATIVE_LOADER = null;
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
FontWatcher.getUserAgent = function () {
|
||||
return window.navigator.userAgent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
FontWatcher.getVendor = function () {
|
||||
return window.navigator.vendor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if this browser has support for
|
||||
* the CSS font loading API.
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
FontWatcher.shouldUseNativeLoader = function () {
|
||||
if (FontWatcher.SHOULD_USE_NATIVE_LOADER === null) {
|
||||
if (!!window.FontFace) {
|
||||
var match = /Gecko.*Firefox\/(\d+)/.exec(FontWatcher.getUserAgent());
|
||||
var safari10Match = /OS X.*Version\/10\..*Safari/.exec(FontWatcher.getUserAgent()) && /Apple/.exec(FontWatcher.getVendor());
|
||||
|
||||
if (match) {
|
||||
FontWatcher.SHOULD_USE_NATIVE_LOADER = parseInt(match[1], 10) > 42;
|
||||
} else if (safari10Match) {
|
||||
FontWatcher.SHOULD_USE_NATIVE_LOADER = false;
|
||||
} else {
|
||||
FontWatcher.SHOULD_USE_NATIVE_LOADER = true;
|
||||
}
|
||||
} else {
|
||||
FontWatcher.SHOULD_USE_NATIVE_LOADER = false;
|
||||
}
|
||||
}
|
||||
return FontWatcher.SHOULD_USE_NATIVE_LOADER;
|
||||
};
|
||||
|
||||
/**
|
||||
* Watches a set of font families.
|
||||
* @param {Array.<webfont.Font>} fonts The fonts to watch.
|
||||
* @param {webfont.FontTestStrings} fontTestStrings The font test strings for
|
||||
* each family.
|
||||
* @param {Object.<String, boolean>} metricCompatibleFonts
|
||||
* @param {boolean} last True if this is the last set of fonts to watch.
|
||||
*/
|
||||
FontWatcher.prototype.watchFonts = function(fonts,
|
||||
fontTestStrings, metricCompatibleFonts, last) {
|
||||
var length = fonts.length,
|
||||
testStrings = fontTestStrings || {};
|
||||
|
||||
if (length === 0 && last) {
|
||||
this.eventDispatcher_.dispatchInactive();
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentlyWatched_ += fonts.length;
|
||||
|
||||
if (last) {
|
||||
this.last_ = last;
|
||||
}
|
||||
|
||||
var i, fontWatchRunners = [];
|
||||
for (i = 0; i < fonts.length; i++) {
|
||||
var font = fonts[i],
|
||||
testString = testStrings[font.getName()];
|
||||
|
||||
this.eventDispatcher_.dispatchFontLoading(font);
|
||||
|
||||
var fontWatchRunner = null;
|
||||
|
||||
if (FontWatcher.shouldUseNativeLoader()) {
|
||||
fontWatchRunner = new NativeFontWatchRunner(
|
||||
goog.bind(this.fontActive_, this),
|
||||
goog.bind(this.fontInactive_, this),
|
||||
this.domHelper_,
|
||||
font,
|
||||
this.timeout_,
|
||||
testString
|
||||
);
|
||||
} else {
|
||||
fontWatchRunner = new FontWatchRunner(
|
||||
goog.bind(this.fontActive_, this),
|
||||
goog.bind(this.fontInactive_, this),
|
||||
this.domHelper_,
|
||||
font,
|
||||
this.timeout_,
|
||||
metricCompatibleFonts,
|
||||
testString
|
||||
);
|
||||
}
|
||||
|
||||
fontWatchRunners.push(fontWatchRunner);
|
||||
}
|
||||
|
||||
for (i = 0; i < fontWatchRunners.length; i++) {
|
||||
fontWatchRunners[i].start();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by a FontWatchRunner when a font has been detected as active.
|
||||
* @param {webfont.Font} font
|
||||
* @private
|
||||
*/
|
||||
FontWatcher.prototype.fontActive_ = function(font) {
|
||||
this.eventDispatcher_.dispatchFontActive(font);
|
||||
this.success_ = true;
|
||||
this.decreaseCurrentlyWatched_();
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by a FontWatchRunner when a font has been detected as inactive.
|
||||
* @param {webfont.Font} font
|
||||
* @private
|
||||
*/
|
||||
FontWatcher.prototype.fontInactive_ = function(font) {
|
||||
this.eventDispatcher_.dispatchFontInactive(font);
|
||||
this.decreaseCurrentlyWatched_();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FontWatcher.prototype.decreaseCurrentlyWatched_ = function() {
|
||||
if (--this.currentlyWatched_ == 0 && this.last_) {
|
||||
if (this.success_) {
|
||||
this.eventDispatcher_.dispatchActive();
|
||||
} else {
|
||||
this.eventDispatcher_.dispatchInactive();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
|
@ -0,0 +1,249 @@
|
|||
goog.provide('webfont.FontWatchRunner');
|
||||
|
||||
goog.require('webfont.Font');
|
||||
goog.require('webfont.FontRuler');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {function(webfont.Font)} activeCallback
|
||||
* @param {function(webfont.Font)} inactiveCallback
|
||||
* @param {webfont.DomHelper} domHelper
|
||||
* @param {webfont.Font} font
|
||||
* @param {number=} opt_timeout
|
||||
* @param {Object.<string, boolean>=} opt_metricCompatibleFonts
|
||||
* @param {string=} opt_fontTestString
|
||||
*/
|
||||
webfont.FontWatchRunner = function(activeCallback, inactiveCallback, domHelper,
|
||||
font, opt_timeout, opt_metricCompatibleFonts, opt_fontTestString) {
|
||||
this.activeCallback_ = activeCallback;
|
||||
this.inactiveCallback_ = inactiveCallback;
|
||||
this.domHelper_ = domHelper;
|
||||
this.font_ = font;
|
||||
this.fontTestString_ = opt_fontTestString || webfont.FontWatchRunner.DEFAULT_TEST_STRING;
|
||||
this.lastResortWidths_ = {};
|
||||
this.timeout_ = opt_timeout || 3000;
|
||||
|
||||
this.metricCompatibleFonts_ = opt_metricCompatibleFonts || null;
|
||||
|
||||
this.fontRulerA_ = null;
|
||||
this.fontRulerB_ = null;
|
||||
this.lastResortRulerA_ = null;
|
||||
this.lastResortRulerB_ = null;
|
||||
|
||||
this.setupRulers_();
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
* @const
|
||||
*/
|
||||
webfont.FontWatchRunner.LastResortFonts = {
|
||||
SERIF: 'serif',
|
||||
SANS_SERIF: 'sans-serif'
|
||||
};
|
||||
|
||||
/**
|
||||
* Default test string. Characters are chosen so that their widths vary a lot
|
||||
* between the fonts in the default stacks. We want each fallback stack
|
||||
* to always start out at a different width than the other.
|
||||
* @type {string}
|
||||
* @const
|
||||
*/
|
||||
webfont.FontWatchRunner.DEFAULT_TEST_STRING = 'BESbswy';
|
||||
|
||||
goog.scope(function () {
|
||||
var FontWatchRunner = webfont.FontWatchRunner,
|
||||
Font = webfont.Font,
|
||||
FontRuler = webfont.FontRuler;
|
||||
|
||||
/**
|
||||
* @type {null|boolean}
|
||||
*/
|
||||
FontWatchRunner.HAS_WEBKIT_FALLBACK_BUG = null;
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
FontWatchRunner.getUserAgent = function () {
|
||||
return window.navigator.userAgent;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if this browser is WebKit and it has the fallback bug
|
||||
* which is present in WebKit 536.11 and earlier.
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
FontWatchRunner.hasWebKitFallbackBug = function () {
|
||||
if (FontWatchRunner.HAS_WEBKIT_FALLBACK_BUG === null) {
|
||||
var match = /AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(FontWatchRunner.getUserAgent());
|
||||
|
||||
FontWatchRunner.HAS_WEBKIT_FALLBACK_BUG = !!match &&
|
||||
(parseInt(match[1], 10) < 536 ||
|
||||
(parseInt(match[1], 10) === 536 &&
|
||||
parseInt(match[2], 10) <= 11));
|
||||
}
|
||||
return FontWatchRunner.HAS_WEBKIT_FALLBACK_BUG;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FontWatchRunner.prototype.setupRulers_ = function() {
|
||||
this.fontRulerA_ = new FontRuler(this.domHelper_, this.fontTestString_);
|
||||
this.fontRulerB_ = new FontRuler(this.domHelper_, this.fontTestString_);
|
||||
this.lastResortRulerA_ = new FontRuler(this.domHelper_, this.fontTestString_);
|
||||
this.lastResortRulerB_ = new FontRuler(this.domHelper_, this.fontTestString_);
|
||||
|
||||
this.fontRulerA_.setFont(new Font(this.font_.getName() + ',' + FontWatchRunner.LastResortFonts.SERIF, this.font_.getVariation()));
|
||||
this.fontRulerB_.setFont(new Font(this.font_.getName() + ',' + FontWatchRunner.LastResortFonts.SANS_SERIF, this.font_.getVariation()));
|
||||
this.lastResortRulerA_.setFont(new Font(FontWatchRunner.LastResortFonts.SERIF, this.font_.getVariation()));
|
||||
this.lastResortRulerB_.setFont(new Font(FontWatchRunner.LastResortFonts.SANS_SERIF, this.font_.getVariation()));
|
||||
|
||||
this.fontRulerA_.insert();
|
||||
this.fontRulerB_.insert();
|
||||
this.lastResortRulerA_.insert();
|
||||
this.lastResortRulerB_.insert();
|
||||
};
|
||||
|
||||
FontWatchRunner.prototype.start = function() {
|
||||
this.lastResortWidths_[FontWatchRunner.LastResortFonts.SERIF] = this.lastResortRulerA_.getWidth();
|
||||
this.lastResortWidths_[FontWatchRunner.LastResortFonts.SANS_SERIF] = this.lastResortRulerB_.getWidth();
|
||||
|
||||
this.started_ = goog.now();
|
||||
|
||||
this.check_();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the given width matches the generic font family width.
|
||||
*
|
||||
* @private
|
||||
* @param {number} width
|
||||
* @param {string} lastResortFont
|
||||
* @return {boolean}
|
||||
*/
|
||||
FontWatchRunner.prototype.widthMatches_ = function(width, lastResortFont) {
|
||||
return width === this.lastResortWidths_[lastResortFont];
|
||||
};
|
||||
|
||||
/**
|
||||
* Return true if the given widths match any of the generic font family
|
||||
* widths.
|
||||
*
|
||||
* @private
|
||||
* @param {number} a
|
||||
* @param {number} b
|
||||
* @return {boolean}
|
||||
*/
|
||||
FontWatchRunner.prototype.widthsMatchLastResortWidths_ = function(a, b) {
|
||||
for (var font in FontWatchRunner.LastResortFonts) {
|
||||
if (FontWatchRunner.LastResortFonts.hasOwnProperty(font)) {
|
||||
if (this.widthMatches_(a, FontWatchRunner.LastResortFonts[font]) &&
|
||||
this.widthMatches_(b, FontWatchRunner.LastResortFonts[font])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns true if the loading has timed out.
|
||||
* @return {boolean}
|
||||
*/
|
||||
FontWatchRunner.prototype.hasTimedOut_ = function() {
|
||||
return goog.now() - this.started_ >= this.timeout_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if both fonts match the normal fallback fonts.
|
||||
*
|
||||
* @private
|
||||
* @param {number} a
|
||||
* @param {number} b
|
||||
* @return {boolean}
|
||||
*/
|
||||
FontWatchRunner.prototype.isFallbackFont_ = function (a, b) {
|
||||
return this.widthMatches_(a, FontWatchRunner.LastResortFonts.SERIF) &&
|
||||
this.widthMatches_(b, FontWatchRunner.LastResortFonts.SANS_SERIF);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the WebKit bug is present and both widths match a last resort font.
|
||||
*
|
||||
* @private
|
||||
* @param {number} a
|
||||
* @param {number} b
|
||||
* @return {boolean}
|
||||
*/
|
||||
FontWatchRunner.prototype.isLastResortFont_ = function (a, b) {
|
||||
return FontWatchRunner.hasWebKitFallbackBug() && this.widthsMatchLastResortWidths_(a, b);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the current font is metric compatible. Also returns true
|
||||
* if we do not have a list of metric compatible fonts.
|
||||
*
|
||||
* @private
|
||||
* @return {boolean}
|
||||
*/
|
||||
FontWatchRunner.prototype.isMetricCompatibleFont_ = function () {
|
||||
return this.metricCompatibleFonts_ === null || this.metricCompatibleFonts_.hasOwnProperty(this.font_.getName());
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks the width of the two spans against their original widths during each
|
||||
* async loop. If the width of one of the spans is different than the original
|
||||
* width, then we know that the font is rendering and finish with the active
|
||||
* callback. If we wait more than 5 seconds and nothing has changed, we finish
|
||||
* with the inactive callback.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
FontWatchRunner.prototype.check_ = function() {
|
||||
var widthA = this.fontRulerA_.getWidth();
|
||||
var widthB = this.fontRulerB_.getWidth();
|
||||
|
||||
if (this.isFallbackFont_(widthA, widthB) || this.isLastResortFont_(widthA, widthB)) {
|
||||
if (this.hasTimedOut_()) {
|
||||
if (this.isLastResortFont_(widthA, widthB) && this.isMetricCompatibleFont_()) {
|
||||
this.finish_(this.activeCallback_);
|
||||
} else {
|
||||
this.finish_(this.inactiveCallback_);
|
||||
}
|
||||
} else {
|
||||
this.asyncCheck_();
|
||||
}
|
||||
} else {
|
||||
this.finish_(this.activeCallback_);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FontWatchRunner.prototype.asyncCheck_ = function() {
|
||||
setTimeout(goog.bind(function () {
|
||||
this.check_();
|
||||
}, this), 50);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {function(webfont.Font)} callback
|
||||
*/
|
||||
FontWatchRunner.prototype.finish_ = function(callback) {
|
||||
// Remove elements and trigger callback (which adds active/inactive class) asynchronously to avoid reflow chain if
|
||||
// several fonts are finished loading right after each other
|
||||
setTimeout(goog.bind(function () {
|
||||
this.fontRulerA_.remove();
|
||||
this.fontRulerB_.remove();
|
||||
this.lastResortRulerA_.remove();
|
||||
this.lastResortRulerB_.remove();
|
||||
callback(this.font_);
|
||||
}, this), 0);
|
||||
};
|
||||
|
||||
});
|
|
@ -0,0 +1,97 @@
|
|||
goog.provide('webfont');
|
||||
|
||||
goog.require('webfont.WebFont');
|
||||
|
||||
goog.require('webfont.modules.Typekit');
|
||||
goog.require('webfont.modules.Fontdeck');
|
||||
goog.require('webfont.modules.Monotype');
|
||||
goog.require('webfont.modules.Custom');
|
||||
goog.require('webfont.modules.google.GoogleFontApi');
|
||||
|
||||
/**
|
||||
* @define {boolean}
|
||||
*/
|
||||
var INCLUDE_CUSTOM_MODULE = false;
|
||||
|
||||
/**
|
||||
* @define {boolean}
|
||||
*/
|
||||
var INCLUDE_FONTDECK_MODULE = false;
|
||||
|
||||
/**
|
||||
* @define {boolean}
|
||||
*/
|
||||
var INCLUDE_MONOTYPE_MODULE = false;
|
||||
|
||||
/**
|
||||
* @define {boolean}
|
||||
*/
|
||||
var INCLUDE_TYPEKIT_MODULE = false;
|
||||
|
||||
/**
|
||||
* @define {boolean}
|
||||
*/
|
||||
var INCLUDE_GOOGLE_MODULE = false;
|
||||
|
||||
/**
|
||||
* @define {string}
|
||||
*/
|
||||
var WEBFONT = 'WebFont';
|
||||
|
||||
/**
|
||||
* @define {string}
|
||||
*/
|
||||
var WEBFONT_CONFIG = 'WebFontConfig';
|
||||
|
||||
/**
|
||||
* @type {webfont.WebFont}
|
||||
*/
|
||||
var webFontLoader = new webfont.WebFont(window);
|
||||
|
||||
if (INCLUDE_CUSTOM_MODULE) {
|
||||
webFontLoader.addModule(webfont.modules.Custom.NAME, function (configuration, domHelper) {
|
||||
return new webfont.modules.Custom(domHelper, configuration);
|
||||
});
|
||||
}
|
||||
|
||||
if (INCLUDE_FONTDECK_MODULE) {
|
||||
webFontLoader.addModule(webfont.modules.Fontdeck.NAME, function (configuration, domHelper) {
|
||||
return new webfont.modules.Fontdeck(domHelper, configuration);
|
||||
});
|
||||
}
|
||||
|
||||
if (INCLUDE_MONOTYPE_MODULE) {
|
||||
webFontLoader.addModule(webfont.modules.Monotype.NAME, function (configuration, domHelper) {
|
||||
return new webfont.modules.Monotype(domHelper, configuration);
|
||||
});
|
||||
}
|
||||
|
||||
if (INCLUDE_TYPEKIT_MODULE) {
|
||||
webFontLoader.addModule(webfont.modules.Typekit.NAME, function (configuration, domHelper) {
|
||||
return new webfont.modules.Typekit(domHelper, configuration);
|
||||
});
|
||||
}
|
||||
|
||||
if (INCLUDE_GOOGLE_MODULE) {
|
||||
webFontLoader.addModule(webfont.modules.google.GoogleFontApi.NAME, function (configuration, domHelper) {
|
||||
return new webfont.modules.google.GoogleFontApi(domHelper, configuration);
|
||||
});
|
||||
}
|
||||
|
||||
var exports = {
|
||||
'load': goog.bind(webFontLoader.load, webFontLoader)
|
||||
};
|
||||
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(function () {
|
||||
return exports;
|
||||
});
|
||||
} else if (typeof module !== "undefined" && module.exports) {
|
||||
module.exports = exports;
|
||||
} else {
|
||||
window[WEBFONT] = exports;
|
||||
|
||||
if (window[WEBFONT_CONFIG]) {
|
||||
webFontLoader.load(window[WEBFONT_CONFIG]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
goog.provide('webfont.NativeFontWatchRunner');
|
||||
|
||||
goog.require('webfont.Font');
|
||||
|
||||
goog.scope(function () {
|
||||
/**
|
||||
* @constructor
|
||||
* @param {function(webfont.Font)} activeCallback
|
||||
* @param {function(webfont.Font)} inactiveCallback
|
||||
* @param {webfont.DomHelper} domHelper
|
||||
* @param {webfont.Font} font
|
||||
* @param {number=} opt_timeout
|
||||
* @param {string=} opt_fontTestString
|
||||
*/
|
||||
webfont.NativeFontWatchRunner = function(activeCallback, inactiveCallback, domHelper, font, opt_timeout, opt_fontTestString) {
|
||||
this.activeCallback_ = activeCallback;
|
||||
this.inactiveCallback_ = inactiveCallback;
|
||||
this.font_ = font;
|
||||
this.domHelper_ = domHelper;
|
||||
this.timeout_ = opt_timeout || 3000;
|
||||
this.fontTestString_ = opt_fontTestString || undefined;
|
||||
};
|
||||
|
||||
var NativeFontWatchRunner = webfont.NativeFontWatchRunner;
|
||||
|
||||
NativeFontWatchRunner.prototype.start = function () {
|
||||
var doc = this.domHelper_.getLoadWindow().document,
|
||||
that = this;
|
||||
|
||||
var start = goog.now();
|
||||
|
||||
var loader = new Promise(function (resolve, reject) {
|
||||
var check = function () {
|
||||
var now = goog.now();
|
||||
|
||||
if (now - start >= that.timeout_) {
|
||||
reject();
|
||||
} else {
|
||||
doc.fonts.load(that.font_.toCssString(), that.fontTestString_).then(function (fonts) {
|
||||
if (fonts.length >= 1) {
|
||||
resolve();
|
||||
} else {
|
||||
setTimeout(check, 25);
|
||||
}
|
||||
}, function () {
|
||||
reject();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
check();
|
||||
});
|
||||
|
||||
var timeoutId = null,
|
||||
timer = new Promise(function (resolve, reject) {
|
||||
timeoutId = setTimeout(reject, that.timeout_);
|
||||
});
|
||||
|
||||
Promise.race([timer, loader]).then(function () {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
}
|
||||
that.activeCallback_(that.font_);
|
||||
}, function () {
|
||||
that.inactiveCallback_(that.font_);
|
||||
});
|
||||
};
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
goog.provide('webfont.StyleSheetWaiter');
|
||||
|
||||
/**
|
||||
* A utility class for handling callback from DomHelper.loadStylesheet().
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
webfont.StyleSheetWaiter = function() {
|
||||
/** @private @type {number} */
|
||||
this.waitingCount_ = 0;
|
||||
/** @private @type {Function} */
|
||||
this.onReady_ = null;
|
||||
};
|
||||
|
||||
goog.scope(function () {
|
||||
var StyleSheetWaiter = webfont.StyleSheetWaiter;
|
||||
|
||||
/**
|
||||
* @return {function(Error)}
|
||||
*/
|
||||
StyleSheetWaiter.prototype.startWaitingLoad = function() {
|
||||
var self = this;
|
||||
self.waitingCount_++;
|
||||
return function(error) {
|
||||
self.waitingCount_--;
|
||||
self.fireIfReady_();
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Function} fn
|
||||
*/
|
||||
StyleSheetWaiter.prototype.waitWhileNeededThen = function(fn) {
|
||||
this.onReady_ = fn;
|
||||
this.fireIfReady_();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
StyleSheetWaiter.prototype.fireIfReady_ = function() {
|
||||
var isReady = 0 == this.waitingCount_;
|
||||
if (isReady && this.onReady_) {
|
||||
this.onReady_();
|
||||
this.onReady_ = null;
|
||||
}
|
||||
};
|
||||
});
|
|
@ -0,0 +1,97 @@
|
|||
goog.provide('webfont.WebFont');
|
||||
|
||||
goog.require('webfont.DomHelper');
|
||||
goog.require('webfont.EventDispatcher');
|
||||
goog.require('webfont.FontWatcher');
|
||||
goog.require('webfont.FontModuleLoader');
|
||||
|
||||
/**
|
||||
* @param {Window} mainWindow The main application window containing
|
||||
* webfontloader.js.
|
||||
* @constructor
|
||||
*/
|
||||
webfont.WebFont = function(mainWindow) {
|
||||
this.mainWindow_ = mainWindow;
|
||||
this.fontModuleLoader_ = new webfont.FontModuleLoader();
|
||||
this.moduleLoading_ = 0;
|
||||
this.events_ = true;
|
||||
this.classes_ = true;
|
||||
};
|
||||
|
||||
goog.scope(function () {
|
||||
var WebFont = webfont.WebFont,
|
||||
DomHelper = webfont.DomHelper,
|
||||
EventDispatcher = webfont.EventDispatcher,
|
||||
FontWatcher = webfont.FontWatcher;
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {webfont.FontModuleFactory} factory
|
||||
*/
|
||||
WebFont.prototype.addModule = function(name, factory) {
|
||||
this.fontModuleLoader_.addModuleFactory(name, factory);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Object} configuration
|
||||
*/
|
||||
WebFont.prototype.load = function(configuration) {
|
||||
var context = configuration['context'] || this.mainWindow_;
|
||||
this.domHelper_ = new DomHelper(this.mainWindow_, context);
|
||||
|
||||
this.events_ = configuration['events'] !== false;
|
||||
this.classes_ = configuration['classes'] !== false;
|
||||
|
||||
var eventDispatcher = new EventDispatcher(
|
||||
this.domHelper_,
|
||||
configuration
|
||||
);
|
||||
|
||||
this.load_(eventDispatcher, configuration);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {webfont.EventDispatcher} eventDispatcher
|
||||
* @param {webfont.FontWatcher} fontWatcher
|
||||
* @param {Array.<webfont.Font>} fonts
|
||||
* @param {webfont.FontTestStrings=} opt_fontTestStrings
|
||||
* @param {Object.<string, boolean>=} opt_metricCompatibleFonts
|
||||
*/
|
||||
WebFont.prototype.onModuleReady_ = function(eventDispatcher, fontWatcher, fonts, opt_fontTestStrings, opt_metricCompatibleFonts) {
|
||||
var allModulesLoaded = --this.moduleLoading_ == 0;
|
||||
|
||||
if (this.classes_ || this.events_) {
|
||||
setTimeout(function () {
|
||||
fontWatcher.watchFonts(fonts, opt_fontTestStrings || null, opt_metricCompatibleFonts || null, allModulesLoaded);
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {webfont.EventDispatcher} eventDispatcher
|
||||
* @param {Object} configuration
|
||||
*/
|
||||
WebFont.prototype.load_ = function(eventDispatcher, configuration) {
|
||||
var modules = [],
|
||||
timeout = configuration['timeout'],
|
||||
self = this;
|
||||
|
||||
// Immediately dispatch the loading event before initializing the modules
|
||||
// so we know for sure that the loading event is synchronous.
|
||||
eventDispatcher.dispatchLoading();
|
||||
|
||||
modules = this.fontModuleLoader_.getModules(configuration, this.domHelper_);
|
||||
|
||||
var fontWatcher = new webfont.FontWatcher(this.domHelper_, eventDispatcher, timeout);
|
||||
|
||||
this.moduleLoading_ = modules.length;
|
||||
|
||||
for (var i = 0, len = modules.length; i < len; i++) {
|
||||
var module = modules[i];
|
||||
|
||||
module.load(function (fonts, opt_fontTestStrings, opt_metricCompatibleFonts) {
|
||||
self.onModuleReady_(eventDispatcher, fontWatcher, fonts, opt_fontTestStrings, opt_metricCompatibleFonts);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -0,0 +1,34 @@
|
|||
core:
|
||||
- ../tools/compiler/base.js
|
||||
- core/domhelper.js
|
||||
- core/stylesheetwaiter.js
|
||||
- core/cssclassname.js
|
||||
- core/font.js
|
||||
- core/eventdispatcher.js
|
||||
- core/fontmodule.js
|
||||
- core/fontmoduleloader.js
|
||||
- core/fontruler.js
|
||||
- core/nativefontwatchrunner.js
|
||||
- core/fontwatchrunner.js
|
||||
- core/fontwatcher.js
|
||||
- core/webfont.js
|
||||
- core/initialize.js
|
||||
|
||||
|
||||
|
||||
google:
|
||||
- modules/google/fontapiurlbuilder.js
|
||||
- modules/google/fontapiparser.js
|
||||
- modules/google/googlefontapi.js
|
||||
|
||||
fontdeck:
|
||||
- modules/fontdeck.js
|
||||
|
||||
typekit:
|
||||
- modules/typekit.js
|
||||
|
||||
monotype:
|
||||
- modules/monotype.js
|
||||
|
||||
custom:
|
||||
- modules/custom.js
|
|
@ -0,0 +1,63 @@
|
|||
goog.provide('webfont.modules.Custom');
|
||||
|
||||
goog.require('webfont.Font');
|
||||
goog.require('webfont.StyleSheetWaiter');
|
||||
|
||||
/**
|
||||
*
|
||||
* WebFont.load({
|
||||
* custom: {
|
||||
* families: ['Font1', 'Font2'],
|
||||
* urls: [ 'https://moo', 'https://meuh' ] }
|
||||
* });
|
||||
*
|
||||
* @constructor
|
||||
* @implements {webfont.FontModule}
|
||||
*/
|
||||
webfont.modules.Custom = function(domHelper, configuration) {
|
||||
this.domHelper_ = domHelper;
|
||||
this.configuration_ = configuration;
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.modules.Custom.NAME = 'custom';
|
||||
|
||||
goog.scope(function () {
|
||||
var Custom = webfont.modules.Custom,
|
||||
Font = webfont.Font,
|
||||
StyleSheetWaiter = webfont.StyleSheetWaiter;
|
||||
|
||||
Custom.prototype.load = function(onReady) {
|
||||
var i, len;
|
||||
var urls = this.configuration_['urls'] || [];
|
||||
var familiesConfiguration = this.configuration_['families'] || [];
|
||||
var fontTestStrings = this.configuration_['testStrings'] || {};
|
||||
var waiter = new StyleSheetWaiter();
|
||||
for (i = 0, len = urls.length; i < len; i++) {
|
||||
this.domHelper_.loadStylesheet(urls[i], waiter.startWaitingLoad());
|
||||
}
|
||||
|
||||
var fonts = [];
|
||||
|
||||
for (i = 0, len = familiesConfiguration.length; i < len; i++) {
|
||||
var components = familiesConfiguration[i].split(":");
|
||||
|
||||
if (components[1]) {
|
||||
var variations = components[1].split(",");
|
||||
|
||||
for (var j = 0; j < variations.length; j += 1) {
|
||||
fonts.push(new Font(components[0], variations[j]));
|
||||
}
|
||||
} else {
|
||||
fonts.push(new Font(components[0]));
|
||||
}
|
||||
}
|
||||
|
||||
waiter.waitWhileNeededThen(function() {
|
||||
onReady(fonts, fontTestStrings);
|
||||
});
|
||||
};
|
||||
});
|
|
@ -0,0 +1,66 @@
|
|||
goog.provide('webfont.modules.Fontdeck');
|
||||
|
||||
goog.require('webfont.Font');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {webfont.FontModule}
|
||||
*/
|
||||
webfont.modules.Fontdeck = function(domHelper, configuration) {
|
||||
this.domHelper_ = domHelper;
|
||||
this.configuration_ = configuration;
|
||||
this.fonts_ = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.modules.Fontdeck.NAME = 'fontdeck';
|
||||
webfont.modules.Fontdeck.HOOK = '__webfontfontdeckmodule__';
|
||||
webfont.modules.Fontdeck.API = 'https://f.fontdeck.com/s/css/js/';
|
||||
|
||||
goog.scope(function () {
|
||||
var Fontdeck = webfont.modules.Fontdeck,
|
||||
Font = webfont.Font,
|
||||
FontVariationDescription = webfont.FontVariationDescription;
|
||||
|
||||
Fontdeck.prototype.getScriptSrc = function(projectId) {
|
||||
// For empty iframes, fall back to main window's hostname.
|
||||
var hostname = this.domHelper_.getHostName();
|
||||
var api = this.configuration_['api'] || webfont.modules.Fontdeck.API;
|
||||
return api + hostname + '/' + projectId + '.js';
|
||||
};
|
||||
|
||||
Fontdeck.prototype.load = function(onReady) {
|
||||
var projectId = this.configuration_['id'];
|
||||
var loadWindow = this.domHelper_.getLoadWindow();
|
||||
var self = this;
|
||||
|
||||
if (projectId) {
|
||||
// Provide data to Fontdeck for processing.
|
||||
if (!loadWindow[webfont.modules.Fontdeck.HOOK]) {
|
||||
loadWindow[webfont.modules.Fontdeck.HOOK] = {};
|
||||
}
|
||||
|
||||
// Fontdeck will call this function to indicate support status
|
||||
// and what fonts are provided.
|
||||
loadWindow[webfont.modules.Fontdeck.HOOK][projectId] = function(fontdeckSupports, data) {
|
||||
for (var i = 0, j = data['fonts'].length; i<j; ++i) {
|
||||
var font = data['fonts'][i];
|
||||
self.fonts_.push(new Font(font['name'], Font.parseCssVariation('font-weight:' + font['weight'] + ';font-style:' + font['style'])));
|
||||
}
|
||||
onReady(self.fonts_);
|
||||
};
|
||||
|
||||
// Call the Fontdeck API.
|
||||
this.domHelper_.loadScript(this.getScriptSrc(projectId), function (err) {
|
||||
if (err) {
|
||||
onReady([]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
onReady([]);
|
||||
}
|
||||
};
|
||||
});
|
|
@ -0,0 +1,181 @@
|
|||
goog.provide('webfont.modules.google.FontApiParser');
|
||||
|
||||
goog.require('webfont.Font');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
webfont.modules.google.FontApiParser = function(fontFamilies) {
|
||||
this.fontFamilies_ = fontFamilies;
|
||||
this.parsedFonts_ = [];
|
||||
this.fontTestStrings_ = {};
|
||||
};
|
||||
|
||||
webfont.modules.google.FontApiParser.INT_FONTS = {
|
||||
'latin': webfont.FontWatchRunner.DEFAULT_TEST_STRING,
|
||||
'latin-ext': '\u00E7\u00F6\u00FC\u011F\u015F',
|
||||
'cyrillic': '\u0439\u044f\u0416',
|
||||
'greek': '\u03b1\u03b2\u03a3',
|
||||
'khmer': '\u1780\u1781\u1782',
|
||||
'Hanuman': '\u1780\u1781\u1782' // For backward compatibility
|
||||
};
|
||||
|
||||
webfont.modules.google.FontApiParser.WEIGHTS = {
|
||||
'thin': '1',
|
||||
'extralight': '2',
|
||||
'extra-light': '2',
|
||||
'ultralight': '2',
|
||||
'ultra-light': '2',
|
||||
'light': '3',
|
||||
'regular': '4',
|
||||
'book': '4',
|
||||
'medium': '5',
|
||||
'semi-bold': '6',
|
||||
'semibold': '6',
|
||||
'demi-bold': '6',
|
||||
'demibold': '6',
|
||||
'bold': '7',
|
||||
'extra-bold': '8',
|
||||
'extrabold': '8',
|
||||
'ultra-bold': '8',
|
||||
'ultrabold': '8',
|
||||
'black': '9',
|
||||
'heavy': '9',
|
||||
'l': '3',
|
||||
'r': '4',
|
||||
'b': '7'
|
||||
};
|
||||
|
||||
webfont.modules.google.FontApiParser.STYLES = {
|
||||
'i': 'i',
|
||||
'italic': 'i',
|
||||
'n': 'n',
|
||||
'normal': 'n'
|
||||
};
|
||||
|
||||
webfont.modules.google.FontApiParser.VARIATION_MATCH =
|
||||
new RegExp("^(thin|(?:(?:extra|ultra)-?)?light|regular|book|medium|" +
|
||||
"(?:(?:semi|demi|extra|ultra)-?)?bold|black|heavy|l|r|b|[1-9]00)?(n|i" +
|
||||
"|normal|italic)?$");
|
||||
|
||||
goog.scope(function () {
|
||||
var FontApiParser = webfont.modules.google.FontApiParser,
|
||||
Font = webfont.Font;
|
||||
|
||||
FontApiParser.prototype.parse = function() {
|
||||
var length = this.fontFamilies_.length;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
var elements = this.fontFamilies_[i].split(":");
|
||||
var fontFamily = elements[0].replace(/\+/g, " ");
|
||||
var variations = ['n4'];
|
||||
|
||||
if (elements.length >= 2) {
|
||||
var fvds = this.parseVariations_(elements[1]);
|
||||
|
||||
if (fvds.length > 0) {
|
||||
variations = fvds;
|
||||
}
|
||||
if (elements.length == 3) {
|
||||
var subsets = this.parseSubsets_(elements[2]);
|
||||
if (subsets.length > 0) {
|
||||
var fontTestString = FontApiParser.INT_FONTS[subsets[0]];
|
||||
|
||||
if (fontTestString) {
|
||||
this.fontTestStrings_[fontFamily] = fontTestString;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For backward compatibility
|
||||
if (!this.fontTestStrings_[fontFamily]) {
|
||||
var hanumanTestString = FontApiParser.INT_FONTS[fontFamily];
|
||||
if (hanumanTestString) {
|
||||
this.fontTestStrings_[fontFamily] = hanumanTestString;
|
||||
}
|
||||
}
|
||||
|
||||
for (var j = 0; j < variations.length; j += 1) {
|
||||
this.parsedFonts_.push(new Font(fontFamily, variations[j]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
FontApiParser.prototype.generateFontVariationDescription_ = function(variation) {
|
||||
if (!variation.match(/^[\w-]+$/)) {
|
||||
return '';
|
||||
}
|
||||
var normalizedVariation = variation.toLowerCase();
|
||||
var groups = FontApiParser.VARIATION_MATCH.exec(normalizedVariation);
|
||||
if (groups == null) {
|
||||
return '';
|
||||
}
|
||||
var styleMatch = this.normalizeStyle_(groups[2]);
|
||||
var weightMatch = this.normalizeWeight_(groups[1]);
|
||||
return [styleMatch, weightMatch].join('');
|
||||
};
|
||||
|
||||
|
||||
FontApiParser.prototype.normalizeStyle_ = function(parsedStyle) {
|
||||
if (parsedStyle == null || parsedStyle == '') {
|
||||
return 'n';
|
||||
}
|
||||
return FontApiParser.STYLES[parsedStyle];
|
||||
};
|
||||
|
||||
|
||||
FontApiParser.prototype.normalizeWeight_ = function(parsedWeight) {
|
||||
if (parsedWeight == null || parsedWeight == '') {
|
||||
return '4';
|
||||
}
|
||||
var weight = FontApiParser.WEIGHTS[parsedWeight];
|
||||
if (weight) {
|
||||
return weight;
|
||||
}
|
||||
if (isNaN(parsedWeight)) {
|
||||
return '4';
|
||||
}
|
||||
return parsedWeight.substr(0, 1);
|
||||
};
|
||||
|
||||
|
||||
FontApiParser.prototype.parseVariations_ = function(variations) {
|
||||
var finalVariations = [];
|
||||
|
||||
if (!variations) {
|
||||
return finalVariations;
|
||||
}
|
||||
var providedVariations = variations.split(",");
|
||||
var length = providedVariations.length;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
var variation = providedVariations[i];
|
||||
var fvd = this.generateFontVariationDescription_(variation);
|
||||
|
||||
if (fvd) {
|
||||
finalVariations.push(fvd);
|
||||
}
|
||||
}
|
||||
return finalVariations;
|
||||
};
|
||||
|
||||
|
||||
FontApiParser.prototype.parseSubsets_ = function(subsets) {
|
||||
var finalSubsets = [];
|
||||
|
||||
if (!subsets) {
|
||||
return finalSubsets;
|
||||
}
|
||||
return subsets.split(",");
|
||||
};
|
||||
|
||||
|
||||
FontApiParser.prototype.getFonts = function() {
|
||||
return this.parsedFonts_;
|
||||
};
|
||||
|
||||
FontApiParser.prototype.getFontTestStrings = function() {
|
||||
return this.fontTestStrings_;
|
||||
};
|
||||
});
|
|
@ -0,0 +1,77 @@
|
|||
goog.provide('webfont.modules.google.FontApiUrlBuilder');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
webfont.modules.google.FontApiUrlBuilder = function(apiUrl, text) {
|
||||
if (apiUrl) {
|
||||
this.apiUrl_ = apiUrl;
|
||||
} else {
|
||||
this.apiUrl_ = webfont.modules.google.FontApiUrlBuilder.DEFAULT_API_URL;
|
||||
}
|
||||
this.fontFamilies_ = [];
|
||||
this.subsets_ = [];
|
||||
this.text_ = text || '';
|
||||
};
|
||||
|
||||
|
||||
webfont.modules.google.FontApiUrlBuilder.DEFAULT_API_URL = 'https://fonts.googleapis.com/css';
|
||||
|
||||
goog.scope(function () {
|
||||
var FontApiUrlBuilder = webfont.modules.google.FontApiUrlBuilder;
|
||||
|
||||
FontApiUrlBuilder.prototype.setFontFamilies = function(fontFamilies) {
|
||||
this.parseFontFamilies_(fontFamilies);
|
||||
};
|
||||
|
||||
|
||||
FontApiUrlBuilder.prototype.parseFontFamilies_ =
|
||||
function(fontFamilies) {
|
||||
var length = fontFamilies.length;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
var elements = fontFamilies[i].split(':');
|
||||
|
||||
if (elements.length == 3) {
|
||||
this.subsets_.push(elements.pop());
|
||||
}
|
||||
var joinCharacter = '';
|
||||
if (elements.length == 2 && elements[1] != ''){
|
||||
joinCharacter = ':';
|
||||
}
|
||||
this.fontFamilies_.push(elements.join(joinCharacter));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FontApiUrlBuilder.prototype.webSafe = function(string) {
|
||||
return string.replace(/ /g, '+');
|
||||
};
|
||||
|
||||
|
||||
FontApiUrlBuilder.prototype.build = function() {
|
||||
if (this.fontFamilies_.length == 0) {
|
||||
throw new Error('No fonts to load!');
|
||||
}
|
||||
if (this.apiUrl_.indexOf("kit=") != -1) {
|
||||
return this.apiUrl_;
|
||||
}
|
||||
var length = this.fontFamilies_.length;
|
||||
var sb = [];
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
sb.push(this.webSafe(this.fontFamilies_[i]));
|
||||
}
|
||||
var url = this.apiUrl_ + '?family=' + sb.join('%7C'); // '|' escaped.
|
||||
|
||||
if (this.subsets_.length > 0) {
|
||||
url += '&subset=' + this.subsets_.join(',');
|
||||
}
|
||||
|
||||
if (this.text_.length > 0) {
|
||||
url += '&text=' + encodeURIComponent(this.text_);
|
||||
}
|
||||
|
||||
return url;
|
||||
};
|
||||
});
|
|
@ -0,0 +1,54 @@
|
|||
goog.provide('webfont.modules.google.GoogleFontApi');
|
||||
|
||||
goog.require('webfont.modules.google.FontApiUrlBuilder');
|
||||
goog.require('webfont.modules.google.FontApiParser');
|
||||
goog.require('webfont.FontWatchRunner');
|
||||
goog.require('webfont.StyleSheetWaiter');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {webfont.FontModule}
|
||||
*/
|
||||
webfont.modules.google.GoogleFontApi = function(domHelper, configuration) {
|
||||
this.domHelper_ = domHelper;
|
||||
this.configuration_ = configuration;
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.modules.google.GoogleFontApi.NAME = 'google';
|
||||
|
||||
goog.scope(function () {
|
||||
var GoogleFontApi = webfont.modules.google.GoogleFontApi,
|
||||
FontWatchRunner = webfont.FontWatchRunner,
|
||||
StyleSheetWaiter = webfont.StyleSheetWaiter,
|
||||
FontApiUrlBuilder = webfont.modules.google.FontApiUrlBuilder,
|
||||
FontApiParser = webfont.modules.google.FontApiParser;
|
||||
|
||||
GoogleFontApi.METRICS_COMPATIBLE_FONTS = {
|
||||
"Arimo": true,
|
||||
"Cousine": true,
|
||||
"Tinos": true
|
||||
};
|
||||
|
||||
GoogleFontApi.prototype.load = function(onReady) {
|
||||
var waiter = new StyleSheetWaiter();
|
||||
var domHelper = this.domHelper_;
|
||||
var fontApiUrlBuilder = new FontApiUrlBuilder(
|
||||
this.configuration_['api'],
|
||||
this.configuration_['text']
|
||||
);
|
||||
var fontFamilies = this.configuration_['families'];
|
||||
fontApiUrlBuilder.setFontFamilies(fontFamilies);
|
||||
|
||||
var fontApiParser = new FontApiParser(fontFamilies);
|
||||
fontApiParser.parse();
|
||||
|
||||
domHelper.loadStylesheet(fontApiUrlBuilder.build(), waiter.startWaitingLoad());
|
||||
waiter.waitWhileNeededThen(function() {
|
||||
onReady(fontApiParser.getFonts(), fontApiParser.getFontTestStrings(), GoogleFontApi.METRICS_COMPATIBLE_FONTS);
|
||||
});
|
||||
};
|
||||
});
|
|
@ -0,0 +1,110 @@
|
|||
goog.provide('webfont.modules.Monotype');
|
||||
|
||||
goog.require('webfont.Font');
|
||||
|
||||
/**
|
||||
webfont.load({
|
||||
monotype: {
|
||||
projectId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'//this is your Fonts.com Web fonts projectId
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {webfont.FontModule}
|
||||
*/
|
||||
webfont.modules.Monotype = function(domHelper, configuration) {
|
||||
this.domHelper_ = domHelper;
|
||||
this.configuration_ = configuration;
|
||||
};
|
||||
|
||||
/**
|
||||
* name of the module through which external API is supposed to call the MonotypeFontAPI.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.modules.Monotype.NAME = 'monotype';
|
||||
|
||||
/**
|
||||
* __mti_fntLst is the name of function that exposes Monotype's font list.
|
||||
* @const
|
||||
*/
|
||||
webfont.modules.Monotype.HOOK = '__mti_fntLst';
|
||||
|
||||
/**
|
||||
* __MonotypeAPIScript__ is the id of script added by google API. Currently 'fonts.com' supports only one script in a page.
|
||||
* This may require change in future if 'fonts.com' begins supporting multiple scripts per page.
|
||||
* @const
|
||||
*/
|
||||
webfont.modules.Monotype.SCRIPTID = '__MonotypeAPIScript__';
|
||||
|
||||
/**
|
||||
* __MonotypeConfiguration__ is function exposed to fonts.com. fonts.com will use this function to get webfontloader configuration
|
||||
* @const
|
||||
*/
|
||||
webfont.modules.Monotype.CONFIGURATION = '__MonotypeConfiguration__';
|
||||
|
||||
goog.scope(function() {
|
||||
var Monotype = webfont.modules.Monotype,
|
||||
Font = webfont.Font;
|
||||
|
||||
|
||||
Monotype.prototype.getScriptSrc = function(projectId, version) {
|
||||
var api = (this.configuration_['api'] || 'https://fast.fonts.net/jsapi')
|
||||
return api + '/' + projectId + '.js' + (version ? '?v=' + version : '');
|
||||
};
|
||||
|
||||
Monotype.prototype.load = function(onReady) {
|
||||
var self = this;
|
||||
var projectId = self.configuration_['projectId'];
|
||||
var version = self.configuration_['version'];
|
||||
|
||||
|
||||
function checkAndLoadIfDownloaded() {
|
||||
if (loadWindow[Monotype.HOOK + projectId]) {
|
||||
var mti_fnts = loadWindow[Monotype.HOOK + projectId](),
|
||||
fonts = [],
|
||||
fntVariation;
|
||||
|
||||
if (mti_fnts) {
|
||||
for (var i = 0; i < mti_fnts.length; i++) {
|
||||
var fnt = mti_fnts[i]["fontfamily"];
|
||||
|
||||
//Check if font-style and font-weight is available
|
||||
if (mti_fnts[i]["fontStyle"] != undefined && mti_fnts[i]["fontWeight"] != undefined) {
|
||||
fntVariation = mti_fnts[i]["fontStyle"] + mti_fnts[i]["fontWeight"];
|
||||
fonts.push(new Font(fnt, fntVariation));
|
||||
} else {
|
||||
fonts.push(new Font(fnt));
|
||||
}
|
||||
}
|
||||
}
|
||||
onReady(fonts);
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
checkAndLoadIfDownloaded();
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
if (projectId) {
|
||||
var loadWindow = self.domHelper_.getLoadWindow();
|
||||
|
||||
var script = this.domHelper_.loadScript(self.getScriptSrc(projectId, version), function(err) {
|
||||
if (err) {
|
||||
onReady([]);
|
||||
} else {
|
||||
loadWindow[Monotype.CONFIGURATION+ projectId] = function() {
|
||||
return self.configuration_;
|
||||
};
|
||||
|
||||
checkAndLoadIfDownloaded();
|
||||
}
|
||||
});
|
||||
script["id"] = Monotype.SCRIPTID + projectId;
|
||||
} else {
|
||||
onReady([]);
|
||||
}
|
||||
};
|
||||
});
|
|
@ -0,0 +1,73 @@
|
|||
goog.provide('webfont.modules.Typekit');
|
||||
|
||||
goog.require('webfont.Font');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {webfont.FontModule}
|
||||
*/
|
||||
webfont.modules.Typekit = function(domHelper, configuration) {
|
||||
this.domHelper_ = domHelper;
|
||||
this.configuration_ = configuration;
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
webfont.modules.Typekit.NAME = 'typekit';
|
||||
|
||||
goog.scope(function () {
|
||||
var Typekit = webfont.modules.Typekit,
|
||||
Font = webfont.Font;
|
||||
|
||||
Typekit.prototype.getScriptSrc = function(kitId) {
|
||||
var api = this.configuration_['api'] || 'https://use.typekit.net';
|
||||
return api + '/' + kitId + '.js';
|
||||
};
|
||||
|
||||
Typekit.prototype.load = function(onReady) {
|
||||
var kitId = this.configuration_['id'];
|
||||
var configuration = this.configuration_;
|
||||
var loadWindow = this.domHelper_.getLoadWindow();
|
||||
var that = this;
|
||||
|
||||
if (kitId) {
|
||||
// Load the Typekit script. Once it is done loading we grab its configuration
|
||||
// and use that to populate the fonts we should watch.
|
||||
this.domHelper_.loadScript(this.getScriptSrc(kitId), function (err) {
|
||||
if (err) {
|
||||
onReady([]);
|
||||
} else {
|
||||
if (loadWindow['Typekit'] && loadWindow['Typekit']['config'] && loadWindow['Typekit']['config']['fn']) {
|
||||
var fn = loadWindow['Typekit']['config']['fn'],
|
||||
fonts = [];
|
||||
|
||||
for (var i = 0; i < fn.length; i += 2) {
|
||||
var font = fn[i],
|
||||
variations = fn[i + 1];
|
||||
|
||||
for (var j = 0; j < variations.length; j++) {
|
||||
fonts.push(new Font(font, variations[j]));
|
||||
}
|
||||
}
|
||||
|
||||
// Kick off font loading but disable font events so
|
||||
// we don't duplicate font watching.
|
||||
try {
|
||||
loadWindow['Typekit']['load']({
|
||||
'events': false,
|
||||
'classes': false,
|
||||
'async': true
|
||||
});
|
||||
} catch (e) {}
|
||||
|
||||
onReady(fonts);
|
||||
}
|
||||
}
|
||||
}, 2000);
|
||||
} else {
|
||||
onReady([]);
|
||||
}
|
||||
};
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
/* Web Font Loader v1.6.28 - (c) Adobe Systems, Google. License: Apache 2.0 */(function(){function aa(a,b,c){return a.call.apply(a.bind,arguments)}function ba(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}}function p(a,b,c){p=Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?aa:ba;return p.apply(null,arguments)}var q=Date.now||function(){return+new Date};function ca(a,b){this.a=a;this.o=b||a;this.c=this.o.document}var da=!!window.FontFace;function t(a,b,c,d){b=a.c.createElement(b);if(c)for(var e in c)c.hasOwnProperty(e)&&("style"==e?b.style.cssText=c[e]:b.setAttribute(e,c[e]));d&&b.appendChild(a.c.createTextNode(d));return b}function u(a,b,c){a=a.c.getElementsByTagName(b)[0];a||(a=document.documentElement);a.insertBefore(c,a.lastChild)}function v(a){a.parentNode&&a.parentNode.removeChild(a)}
|
||||
function w(a,b,c){b=b||[];c=c||[];for(var d=a.className.split(/\s+/),e=0;e<b.length;e+=1){for(var f=!1,g=0;g<d.length;g+=1)if(b[e]===d[g]){f=!0;break}f||d.push(b[e])}b=[];for(e=0;e<d.length;e+=1){f=!1;for(g=0;g<c.length;g+=1)if(d[e]===c[g]){f=!0;break}f||b.push(d[e])}a.className=b.join(" ").replace(/\s+/g," ").replace(/^\s+|\s+$/,"")}function y(a,b){for(var c=a.className.split(/\s+/),d=0,e=c.length;d<e;d++)if(c[d]==b)return!0;return!1}
|
||||
function ea(a){return a.o.location.hostname||a.a.location.hostname}function z(a,b,c){function d(){m&&e&&f&&(m(g),m=null)}b=t(a,"link",{rel:"stylesheet",href:b,media:"all"});var e=!1,f=!0,g=null,m=c||null;da?(b.onload=function(){e=!0;d()},b.onerror=function(){e=!0;g=Error("Stylesheet failed to load");d()}):setTimeout(function(){e=!0;d()},0);u(a,"head",b)}
|
||||
function A(a,b,c,d){var e=a.c.getElementsByTagName("head")[0];if(e){var f=t(a,"script",{src:b}),g=!1;f.onload=f.onreadystatechange=function(){g||this.readyState&&"loaded"!=this.readyState&&"complete"!=this.readyState||(g=!0,c&&c(null),f.onload=f.onreadystatechange=null,"HEAD"==f.parentNode.tagName&&e.removeChild(f))};e.appendChild(f);setTimeout(function(){g||(g=!0,c&&c(Error("Script load timeout")))},d||5E3);return f}return null};function B(){this.a=0;this.c=null}function C(a){a.a++;return function(){a.a--;D(a)}}function E(a,b){a.c=b;D(a)}function D(a){0==a.a&&a.c&&(a.c(),a.c=null)};function F(a){this.a=a||"-"}F.prototype.c=function(a){for(var b=[],c=0;c<arguments.length;c++)b.push(arguments[c].replace(/[\W_]+/g,"").toLowerCase());return b.join(this.a)};function G(a,b){this.c=a;this.f=4;this.a="n";var c=(b||"n4").match(/^([nio])([1-9])$/i);c&&(this.a=c[1],this.f=parseInt(c[2],10))}function fa(a){return H(a)+" "+(a.f+"00")+" 300px "+I(a.c)}function I(a){var b=[];a=a.split(/,\s*/);for(var c=0;c<a.length;c++){var d=a[c].replace(/['"]/g,"");-1!=d.indexOf(" ")||/^\d/.test(d)?b.push("'"+d+"'"):b.push(d)}return b.join(",")}function J(a){return a.a+a.f}function H(a){var b="normal";"o"===a.a?b="oblique":"i"===a.a&&(b="italic");return b}
|
||||
function ga(a){var b=4,c="n",d=null;a&&((d=a.match(/(normal|oblique|italic)/i))&&d[1]&&(c=d[1].substr(0,1).toLowerCase()),(d=a.match(/([1-9]00|normal|bold)/i))&&d[1]&&(/bold/i.test(d[1])?b=7:/[1-9]00/.test(d[1])&&(b=parseInt(d[1].substr(0,1),10))));return c+b};function ha(a,b){this.c=a;this.f=a.o.document.documentElement;this.h=b;this.a=new F("-");this.j=!1!==b.events;this.g=!1!==b.classes}function ia(a){a.g&&w(a.f,[a.a.c("wf","loading")]);K(a,"loading")}function L(a){if(a.g){var b=y(a.f,a.a.c("wf","active")),c=[],d=[a.a.c("wf","loading")];b||c.push(a.a.c("wf","inactive"));w(a.f,c,d)}K(a,"inactive")}function K(a,b,c){if(a.j&&a.h[b])if(c)a.h[b](c.c,J(c));else a.h[b]()};function ja(){this.c={}}function ka(a,b,c){var d=[],e;for(e in b)if(b.hasOwnProperty(e)){var f=a.c[e];f&&d.push(f(b[e],c))}return d};function M(a,b){this.c=a;this.f=b;this.a=t(this.c,"span",{"aria-hidden":"true"},this.f)}function N(a){u(a.c,"body",a.a)}function O(a){return"display:block;position:absolute;top:-9999px;left:-9999px;font-size:300px;width:auto;height:auto;line-height:normal;margin:0;padding:0;font-variant:normal;white-space:nowrap;font-family:"+I(a.c)+";"+("font-style:"+H(a)+";font-weight:"+(a.f+"00")+";")};function P(a,b,c,d,e,f){this.g=a;this.j=b;this.a=d;this.c=c;this.f=e||3E3;this.h=f||void 0}P.prototype.start=function(){var a=this.c.o.document,b=this,c=q(),d=new Promise(function(d,e){function f(){q()-c>=b.f?e():a.fonts.load(fa(b.a),b.h).then(function(a){1<=a.length?d():setTimeout(f,25)},function(){e()})}f()}),e=null,f=new Promise(function(a,d){e=setTimeout(d,b.f)});Promise.race([f,d]).then(function(){e&&(clearTimeout(e),e=null);b.g(b.a)},function(){b.j(b.a)})};function Q(a,b,c,d,e,f,g){this.v=a;this.B=b;this.c=c;this.a=d;this.s=g||"BESbswy";this.f={};this.w=e||3E3;this.u=f||null;this.m=this.j=this.h=this.g=null;this.g=new M(this.c,this.s);this.h=new M(this.c,this.s);this.j=new M(this.c,this.s);this.m=new M(this.c,this.s);a=new G(this.a.c+",serif",J(this.a));a=O(a);this.g.a.style.cssText=a;a=new G(this.a.c+",sans-serif",J(this.a));a=O(a);this.h.a.style.cssText=a;a=new G("serif",J(this.a));a=O(a);this.j.a.style.cssText=a;a=new G("sans-serif",J(this.a));a=
|
||||
O(a);this.m.a.style.cssText=a;N(this.g);N(this.h);N(this.j);N(this.m)}var R={D:"serif",C:"sans-serif"},S=null;function T(){if(null===S){var a=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent);S=!!a&&(536>parseInt(a[1],10)||536===parseInt(a[1],10)&&11>=parseInt(a[2],10))}return S}Q.prototype.start=function(){this.f.serif=this.j.a.offsetWidth;this.f["sans-serif"]=this.m.a.offsetWidth;this.A=q();U(this)};
|
||||
function la(a,b,c){for(var d in R)if(R.hasOwnProperty(d)&&b===a.f[R[d]]&&c===a.f[R[d]])return!0;return!1}function U(a){var b=a.g.a.offsetWidth,c=a.h.a.offsetWidth,d;(d=b===a.f.serif&&c===a.f["sans-serif"])||(d=T()&&la(a,b,c));d?q()-a.A>=a.w?T()&&la(a,b,c)&&(null===a.u||a.u.hasOwnProperty(a.a.c))?V(a,a.v):V(a,a.B):ma(a):V(a,a.v)}function ma(a){setTimeout(p(function(){U(this)},a),50)}function V(a,b){setTimeout(p(function(){v(this.g.a);v(this.h.a);v(this.j.a);v(this.m.a);b(this.a)},a),0)};function W(a,b,c){this.c=a;this.a=b;this.f=0;this.m=this.j=!1;this.s=c}var X=null;W.prototype.g=function(a){var b=this.a;b.g&&w(b.f,[b.a.c("wf",a.c,J(a).toString(),"active")],[b.a.c("wf",a.c,J(a).toString(),"loading"),b.a.c("wf",a.c,J(a).toString(),"inactive")]);K(b,"fontactive",a);this.m=!0;na(this)};
|
||||
W.prototype.h=function(a){var b=this.a;if(b.g){var c=y(b.f,b.a.c("wf",a.c,J(a).toString(),"active")),d=[],e=[b.a.c("wf",a.c,J(a).toString(),"loading")];c||d.push(b.a.c("wf",a.c,J(a).toString(),"inactive"));w(b.f,d,e)}K(b,"fontinactive",a);na(this)};function na(a){0==--a.f&&a.j&&(a.m?(a=a.a,a.g&&w(a.f,[a.a.c("wf","active")],[a.a.c("wf","loading"),a.a.c("wf","inactive")]),K(a,"active")):L(a.a))};function oa(a){this.j=a;this.a=new ja;this.h=0;this.f=this.g=!0}oa.prototype.load=function(a){this.c=new ca(this.j,a.context||this.j);this.g=!1!==a.events;this.f=!1!==a.classes;pa(this,new ha(this.c,a),a)};
|
||||
function qa(a,b,c,d,e){var f=0==--a.h;(a.f||a.g)&&setTimeout(function(){var a=e||null,m=d||null||{};if(0===c.length&&f)L(b.a);else{b.f+=c.length;f&&(b.j=f);var h,l=[];for(h=0;h<c.length;h++){var k=c[h],n=m[k.c],r=b.a,x=k;r.g&&w(r.f,[r.a.c("wf",x.c,J(x).toString(),"loading")]);K(r,"fontloading",x);r=null;if(null===X)if(window.FontFace){var x=/Gecko.*Firefox\/(\d+)/.exec(window.navigator.userAgent),xa=/OS X.*Version\/10\..*Safari/.exec(window.navigator.userAgent)&&/Apple/.exec(window.navigator.vendor);
|
||||
X=x?42<parseInt(x[1],10):xa?!1:!0}else X=!1;X?r=new P(p(b.g,b),p(b.h,b),b.c,k,b.s,n):r=new Q(p(b.g,b),p(b.h,b),b.c,k,b.s,a,n);l.push(r)}for(h=0;h<l.length;h++)l[h].start()}},0)}function pa(a,b,c){var d=[],e=c.timeout;ia(b);var d=ka(a.a,c,a.c),f=new W(a.c,b,e);a.h=d.length;b=0;for(c=d.length;b<c;b++)d[b].load(function(b,d,c){qa(a,f,b,d,c)})};function ra(a,b){this.c=a;this.a=b}
|
||||
ra.prototype.load=function(a){function b(){if(f["__mti_fntLst"+d]){var c=f["__mti_fntLst"+d](),e=[],h;if(c)for(var l=0;l<c.length;l++){var k=c[l].fontfamily;void 0!=c[l].fontStyle&&void 0!=c[l].fontWeight?(h=c[l].fontStyle+c[l].fontWeight,e.push(new G(k,h))):e.push(new G(k))}a(e)}else setTimeout(function(){b()},50)}var c=this,d=c.a.projectId,e=c.a.version;if(d){var f=c.c.o;A(this.c,(c.a.api||"https://fast.fonts.net/jsapi")+"/"+d+".js"+(e?"?v="+e:""),function(e){e?a([]):(f["__MonotypeConfiguration__"+
|
||||
d]=function(){return c.a},b())}).id="__MonotypeAPIScript__"+d}else a([])};function sa(a,b){this.c=a;this.a=b}sa.prototype.load=function(a){var b,c,d=this.a.urls||[],e=this.a.families||[],f=this.a.testStrings||{},g=new B;b=0;for(c=d.length;b<c;b++)z(this.c,d[b],C(g));var m=[];b=0;for(c=e.length;b<c;b++)if(d=e[b].split(":"),d[1])for(var h=d[1].split(","),l=0;l<h.length;l+=1)m.push(new G(d[0],h[l]));else m.push(new G(d[0]));E(g,function(){a(m,f)})};function ta(a,b){a?this.c=a:this.c=ua;this.a=[];this.f=[];this.g=b||""}var ua="https://fonts.googleapis.com/css";function va(a,b){for(var c=b.length,d=0;d<c;d++){var e=b[d].split(":");3==e.length&&a.f.push(e.pop());var f="";2==e.length&&""!=e[1]&&(f=":");a.a.push(e.join(f))}}
|
||||
function wa(a){if(0==a.a.length)throw Error("No fonts to load!");if(-1!=a.c.indexOf("kit="))return a.c;for(var b=a.a.length,c=[],d=0;d<b;d++)c.push(a.a[d].replace(/ /g,"+"));b=a.c+"?family="+c.join("%7C");0<a.f.length&&(b+="&subset="+a.f.join(","));0<a.g.length&&(b+="&text="+encodeURIComponent(a.g));return b};function ya(a){this.f=a;this.a=[];this.c={}}
|
||||
var za={latin:"BESbswy","latin-ext":"\u00e7\u00f6\u00fc\u011f\u015f",cyrillic:"\u0439\u044f\u0416",greek:"\u03b1\u03b2\u03a3",khmer:"\u1780\u1781\u1782",Hanuman:"\u1780\u1781\u1782"},Aa={thin:"1",extralight:"2","extra-light":"2",ultralight:"2","ultra-light":"2",light:"3",regular:"4",book:"4",medium:"5","semi-bold":"6",semibold:"6","demi-bold":"6",demibold:"6",bold:"7","extra-bold":"8",extrabold:"8","ultra-bold":"8",ultrabold:"8",black:"9",heavy:"9",l:"3",r:"4",b:"7"},Ba={i:"i",italic:"i",n:"n",normal:"n"},
|
||||
Ca=/^(thin|(?:(?:extra|ultra)-?)?light|regular|book|medium|(?:(?:semi|demi|extra|ultra)-?)?bold|black|heavy|l|r|b|[1-9]00)?(n|i|normal|italic)?$/;
|
||||
function Da(a){for(var b=a.f.length,c=0;c<b;c++){var d=a.f[c].split(":"),e=d[0].replace(/\+/g," "),f=["n4"];if(2<=d.length){var g;var m=d[1];g=[];if(m)for(var m=m.split(","),h=m.length,l=0;l<h;l++){var k;k=m[l];if(k.match(/^[\w-]+$/)){var n=Ca.exec(k.toLowerCase());if(null==n)k="";else{k=n[2];k=null==k||""==k?"n":Ba[k];n=n[1];if(null==n||""==n)n="4";else var r=Aa[n],n=r?r:isNaN(n)?"4":n.substr(0,1);k=[k,n].join("")}}else k="";k&&g.push(k)}0<g.length&&(f=g);3==d.length&&(d=d[2],g=[],d=d?d.split(","):
|
||||
g,0<d.length&&(d=za[d[0]])&&(a.c[e]=d))}a.c[e]||(d=za[e])&&(a.c[e]=d);for(d=0;d<f.length;d+=1)a.a.push(new G(e,f[d]))}};function Ea(a,b){this.c=a;this.a=b}var Fa={Arimo:!0,Cousine:!0,Tinos:!0};Ea.prototype.load=function(a){var b=new B,c=this.c,d=new ta(this.a.api,this.a.text),e=this.a.families;va(d,e);var f=new ya(e);Da(f);z(c,wa(d),C(b));E(b,function(){a(f.a,f.c,Fa)})};function Ga(a,b){this.c=a;this.a=b}Ga.prototype.load=function(a){var b=this.a.id,c=this.c.o;b?A(this.c,(this.a.api||"https://use.typekit.net")+"/"+b+".js",function(b){if(b)a([]);else if(c.Typekit&&c.Typekit.config&&c.Typekit.config.fn){b=c.Typekit.config.fn;for(var e=[],f=0;f<b.length;f+=2)for(var g=b[f],m=b[f+1],h=0;h<m.length;h++)e.push(new G(g,m[h]));try{c.Typekit.load({events:!1,classes:!1,async:!0})}catch(l){}a(e)}},2E3):a([])};function Ha(a,b){this.c=a;this.f=b;this.a=[]}Ha.prototype.load=function(a){var b=this.f.id,c=this.c.o,d=this;b?(c.__webfontfontdeckmodule__||(c.__webfontfontdeckmodule__={}),c.__webfontfontdeckmodule__[b]=function(b,c){for(var g=0,m=c.fonts.length;g<m;++g){var h=c.fonts[g];d.a.push(new G(h.name,ga("font-weight:"+h.weight+";font-style:"+h.style)))}a(d.a)},A(this.c,(this.f.api||"https://f.fontdeck.com/s/css/js/")+ea(this.c)+"/"+b+".js",function(b){b&&a([])})):a([])};var Y=new oa(window);Y.a.c.custom=function(a,b){return new sa(b,a)};Y.a.c.fontdeck=function(a,b){return new Ha(b,a)};Y.a.c.monotype=function(a,b){return new ra(b,a)};Y.a.c.typekit=function(a,b){return new Ga(b,a)};Y.a.c.google=function(a,b){return new Ea(b,a)};var Z={load:p(Y.load,Y)};"function"===typeof define&&define.amd?define(function(){return Z}):"undefined"!==typeof module&&module.exports?module.exports=Z:(window.WebFont=Z,window.WebFontConfig&&Y.load(window.WebFontConfig));}());
|
Loading…
Add table
Add a link
Reference in a new issue