Update jquery.webfonts from upstream

Bug: 50836
Change-Id: I6c1f79b2392d458214c897cf8542ed9a89c550f8
This commit is contained in:
Amir E. Aharoni
2013-07-10 18:26:22 +03:00
parent b9c7b5934f
commit ed7589c3b8

View File

@@ -23,9 +23,11 @@
this.options = $.extend( {}, $.fn.webfonts.defaults, options ); this.options = $.extend( {}, $.fn.webfonts.defaults, options );
this.$element = $( element ); this.$element = $( element );
this.repository = $.extend( WebFonts.repository, this.options.repository ); this.repository = $.extend( WebFonts.repository, this.options.repository );
// List of loaded fonts
this.fonts = []; this.fonts = [];
this.originalFontFamily = this.$element.css( 'font-family' ); this.originalFontFamily = this.$element.css( 'font-family' );
this.language = this.$element.attr( 'lang' ) || $( 'html' ).attr( 'lang' ); this.language = this.$element.attr( 'lang' ) || $( 'html' ).attr( 'lang' );
this.init(); this.init();
}; };
@@ -37,9 +39,11 @@
// Utility methods to work on the repository. // Utility methods to work on the repository.
defaultFont: function( language ) { defaultFont: function( language ) {
var defaultFont = null; var defaultFont = null;
if ( this.languages[language] ) { if ( this.languages[language] ) {
defaultFont = this.languages[language][0]; defaultFont = this.languages[language][0];
} }
return defaultFont; return defaultFont;
}, },
@@ -63,11 +67,10 @@
* Initialize. * Initialize.
*/ */
init: function() { init: function() {
var fontFamily;
if ( this.language ) { if ( this.language ) {
fontFamily = this.getFont( this.language ); this.apply( this.getFont( this.language ) );
this.apply( fontFamily );
} }
this.parse(); this.parse();
}, },
@@ -102,9 +105,7 @@
} }
// Set the font of this element if it's not excluded // Set the font of this element if it's not excluded
if ( !$element.is( this.options.exclude ) ) { $element.not( this.options.exclude ).css( 'font-family', fontStack.join() );
$element.css( 'font-family', fontStack.join() );
}
// Set the font of this element's children if they are not excluded. // Set the font of this element's children if they are not excluded.
// font-family of <input>, <textarea> and <button> must be changed explicitly. // font-family of <input>, <textarea> and <button> must be changed explicitly.
@@ -114,33 +115,63 @@
}, },
/** /**
* Load a given fontFamily if not loaded already * Load given font families if not loaded already. Creates the CSS rules
* and appends them to document.
* *
* @param fontFamily String font family name * @param {Array|String} fontFamilies List of font families
*/ */
load: function( fontFamily ) { load: function( fontFamilies ) {
if ( $.inArray( fontFamily, this.fonts ) >= 0 ) { var css, fontFamily, i,
return true; fontFaceRule = '';
// Convert to array if string given (old signature)
if ( typeof fontFamilies === 'string' ) {
fontFamilies = [fontFamilies];
} }
var styleString = this.getCSS( fontFamily, 'normal' );
if ( styleString ) { for ( i = 0; i < fontFamilies.length; i++ ) {
injectCSS( styleString ); fontFamily = fontFamilies[i];
} else { if ( $.inArray( fontFamily, this.fonts ) >= 0 ) {
// Font not found continue;
return false; }
css = this.getCSS( fontFamily, 'normal' );
if ( css !== false ) {
fontFaceRule += css;
this.fonts.push( fontFamily );
}
} }
this.fonts.push( fontFamily );
injectCSS( fontFaceRule );
return true; return true;
}, },
/** /**
* Parse the element for custom font-family styles and for nodes with * Parse the element for custom font-family styles and for nodes with
* different language than element * different language than what the element itself has.
*/ */
parse: function() { parse: function() {
var webfonts = this; var append,
webfonts = this,
// Fonts can be added indirectly via classes, but also with
// style attributes. For lang attributes we will use our font
// if they don't have explicit font already.
$elements = webfonts.$element.find( '*[lang], [style], [class]' ),
// List of fonts to load in a batch
fontQueue = [],
// List of elements to apply a certain font family in a batch.
// Object keys are the font family, values are list of plain elements.
elementQueue = {};
webfonts.$element.find( '*[lang], [style], [class]' ).each( function( i, element ) { // Append function that keeps the array as a set (no dupes)
append = function( array, value ) {
if ( $.inArray( value, array ) < 0 ) {
array.push( value );
}
};
$elements.each( function( i, element ) {
var fontFamilyStyle, fontFamily, var fontFamilyStyle, fontFamily,
$element = $( element ); $element = $( element );
@@ -152,28 +183,30 @@
// Remove the ' and " characters if any. // Remove the ' and " characters if any.
fontFamily = $.trim( fontFamily.replace( /["']/g, '' ) ); fontFamily = $.trim( fontFamily.replace( /["']/g, '' ) );
if ( webfonts.load( fontFamily ) ) { append( fontQueue, fontFamily );
// Font family overrides the lang attribute, // Load and apply fonts for other language tagged elements (batched)
// but was it the fontfamily allocated for the current } else if ( element.lang && element.lang !== webfonts.$element.attr( 'lang' ) ) {
// language? fontFamily = webfonts.getFont( element.lang );
if ( fontFamily === webfonts.getFont( element.lang ) ) { // We do not have fonts for all languages
return true; if ( fontFamily !== null ) {
} append( fontQueue, fontFamily );
elementQueue[fontFamily] = elementQueue[fontFamily] || [];
elementQueue[fontFamily].push( element );
} }
} }
} );
if ( element.lang && element.lang !== webfonts.$element.attr( 'lang' ) ) { // Process in batch the accumulated fonts and elements
fontFamily = webfonts.getFont( element.lang ); this.load( fontQueue );
webfonts.apply( fontFamily, $( element ) ); $.each( elementQueue, function( fontFamily, elements ) {
} webfonts.apply( fontFamily, $( elements ) );
} ); } );
}, },
/** /**
* List all fonts for the given language * List all fonts for the given language
* *
* @param language mixed: [optional] language code. If undefined all * @param language mixed: [optional] language code. If undefined all fonts will be listed
* fonts will be listed
* @return Array font names array * @return Array font names array
*/ */
list: function( language ) { list: function( language ) {
@@ -207,6 +240,7 @@
languages.push( language ); languages.push( language );
} }
} }
return languages; return languages;
}, },
@@ -227,7 +261,7 @@
}, },
/** /**
* unbind the plugin * Unbind the plugin
*/ */
unbind: function() { unbind: function() {
this.$element.data( 'webfonts', null ); this.$element.data( 'webfonts', null );
@@ -238,20 +272,21 @@
* of the body so that it gets loaded. * of the body so that it gets loaded.
* *
* @param fontFamily The font-family name * @param fontFamily The font-family name
* @param variant The font variant, eg: bold, italic etc. Default is * @param variant The font variant, eg: bold, italic etc. Default is normal.
* normal.
*/ */
getCSS: function( fontFamily, variant ) { getCSS: function( fontFamily, variant ) {
var webfonts, fontconfig, base, version, versionSuffix, styleString, userAgent, fontStyle, fontFormats; var webfonts, base, version, versionSuffix,
fontFaceRule, userAgent, fontStyle, fontFormats,
fontconfig = this.repository.get( fontFamily );
webfonts = this;
variant = variant || 'normal'; variant = variant || 'normal';
fontconfig = this.repository.get( fontFamily );
if ( variant !== 'normal' ) { if ( variant !== 'normal' ) {
if ( fontconfig.variants !== undefined && fontconfig.variants[variant] ) { if ( fontconfig.variants !== undefined && fontconfig.variants[variant] ) {
fontconfig = this.repository.get( fontconfig.variants[variant] ); fontconfig = this.repository.get( fontconfig.variants[variant] );
} }
} }
if ( !fontconfig ) { if ( !fontconfig ) {
return false; return false;
} }
@@ -259,69 +294,79 @@
base = this.repository.base; base = this.repository.base;
version = fontconfig.version; version = fontconfig.version;
versionSuffix = '?version=' + version + '&20120101'; versionSuffix = '?version=' + version + '&20120101';
styleString = '@font-face { font-family: \'' + fontFamily + '\';\n'; fontFaceRule = '@font-face { font-family: \'' + fontFamily + '\';\n';
userAgent = window.navigator.userAgent; userAgent = window.navigator.userAgent;
fontStyle = fontconfig.fontstyle || 'normal'; fontStyle = fontconfig.fontstyle || 'normal';
fontFormats = []; fontFormats = [];
if ( fontconfig.eot ) { if ( fontconfig.eot ) {
styleString += '\tsrc: url(\'' + base + fontconfig.eot + versionSuffix + '\');\n'; fontFaceRule += '\tsrc: url(\'' + base + fontconfig.eot + versionSuffix + '\');\n';
} }
styleString += '\tsrc: '; fontFaceRule += '\tsrc: ';
// If the font is present locally, use it. // If the font is present locally, use it.
if ( userAgent.match( /Android 2\.3/ ) === null ) { if ( userAgent.match( /Android 2\.3/ ) === null ) {
// Android 2.3.x does not respect local() syntax. // Android 2.3.x does not respect local() syntax.
// http://code.google.com/p/android/issues/detail?id=10609 // http://code.google.com/p/android/issues/detail?id=10609
styleString += 'local(\'' + fontFamily + '\'),'; fontFaceRule += 'local(\'' + fontFamily + '\'),';
} }
if ( fontconfig.woff ) { if ( fontconfig.woff ) {
fontFormats.push( '\t\turl(\'' + base + fontconfig.woff + versionSuffix fontFormats.push( '\t\turl(\'' + base + fontconfig.woff + versionSuffix
+ '\') format(\'woff\')' ); + '\') format(\'woff\')' );
} }
if ( fontconfig.svg ) { if ( fontconfig.svg ) {
fontFormats.push( '\t\turl(\'' + base + fontconfig.svg + versionSuffix + '#' fontFormats.push( '\t\turl(\'' + base + fontconfig.svg + versionSuffix + '#'
+ fontFamily + '\') format(\'svg\')' ); + fontFamily + '\') format(\'svg\')' );
} }
if ( fontconfig.ttf ) { if ( fontconfig.ttf ) {
fontFormats.push( '\t\turl(\'' + base + fontconfig.ttf + versionSuffix fontFormats.push( '\t\turl(\'' + base + fontconfig.ttf + versionSuffix
+ '\') format(\'truetype\')' ); + '\') format(\'truetype\')' );
} }
styleString += fontFormats.join() + ';\n';
fontFaceRule += fontFormats.join() + ';\n';
if ( fontconfig.fontweight ) { if ( fontconfig.fontweight ) {
styleString += '\tfont-weight:' + fontconfig.fontweight + ';'; fontFaceRule += '\tfont-weight:' + fontconfig.fontweight + ';';
} }
styleString += '\tfont-style:' + fontStyle + ';';
fontFaceRule += '\tfont-style:' + fontStyle + ';';
if ( fontconfig.fontweight !== undefined ) { if ( fontconfig.fontweight !== undefined ) {
styleString += '\tfont-weight:' + fontconfig.fontweight + ';'; fontFaceRule += '\tfont-weight:' + fontconfig.fontweight + ';';
} }
if ( fontconfig.fontstyle !== undefined ) { if ( fontconfig.fontstyle !== undefined ) {
styleString += '\tfont-style:' + fontconfig.fontstyle + ';'; fontFaceRule += '\tfont-style:' + fontconfig.fontstyle + ';';
} else { } else {
styleString += '\tfont-style: normal;'; fontFaceRule += '\tfont-style: normal;';
} }
styleString += '}'; fontFaceRule += '}';
webfonts = this;
if ( fontconfig.variants !== undefined ) { if ( fontconfig.variants !== undefined ) {
$.each( fontconfig.variants, function ( variant, variantFontFamily ) { $.each( fontconfig.variants, function ( variant ) {
styleString += webfonts.getCSS( fontFamily, variant ); fontFaceRule += webfonts.getCSS( fontFamily, variant );
} ); } );
} }
return styleString; return fontFaceRule;
} }
}; };
$.fn.webfonts = function( option ) { $.fn.webfonts = function( option ) {
return this.each( function() { return this.each( function() {
var $this, data, options; var $this = $( this ),
$this = $( this ); data = $this.data( 'webfonts' ),
data = $this.data( 'webfonts' ); options = typeof option === 'object' && option;
options = typeof option === 'object' && option;
if ( !data ) { if ( !data ) {
$this.data( 'webfonts', ( data = new WebFonts( this, options ) ) ); $this.data( 'webfonts', ( data = new WebFonts( this, options ) ) );
} }
if ( typeof option === 'string' ) { if ( typeof option === 'string' ) {
data[option](); data[option]();
} }
@@ -337,7 +382,6 @@
$.fn.webfonts.Constructor = WebFonts; $.fn.webfonts.Constructor = WebFonts;
// Private methods for the WebFonts prototype // Private methods for the WebFonts prototype
// =================================
/** /**
* Create a new style tag and add it to the DOM. * Create a new style tag and add it to the DOM.
@@ -347,10 +391,13 @@
*/ */
function injectCSS( css ) { function injectCSS( css ) {
var s = document.createElement( 'style' ); var s = document.createElement( 'style' );
s.type = 'text/css'; s.type = 'text/css';
s.rel = 'stylesheet'; s.rel = 'stylesheet';
// Insert into document before setting cssText // Insert into document before setting cssText
document.getElementsByTagName( 'head' )[0].appendChild( s ); document.getElementsByTagName( 'head' )[0].appendChild( s );
if ( s.styleSheet ) { if ( s.styleSheet ) {
s.styleSheet.cssText = css; s.styleSheet.cssText = css;
// IE // IE
@@ -358,7 +405,7 @@
// Safari sometimes borks on null // Safari sometimes borks on null
s.appendChild( document.createTextNode( String( css ) ) ); s.appendChild( document.createTextNode( String( css ) ) );
} }
return s; return s;
} }
} )( jQuery, window, document ); } )( jQuery, window, document );