diff --git a/Resources.php b/Resources.php index 46427214..2b5b70bc 100644 --- a/Resources.php +++ b/Resources.php @@ -143,10 +143,10 @@ $wgResourceModules['ext.uls.preferences'] = array( $wgResourceModules['ext.uls.webfonts'] = array( 'scripts' => 'resources/js/ext.uls.webfonts.js', - 'styles' => 'resources/css/ext.uls.webfonts.css', 'dependencies' => array( 'jquery.webfonts', 'ext.uls.init', + 'jquery.uls.data', 'ext.uls.webfonts.repository', 'ext.uls.preferences', ), diff --git a/UniversalLanguageSelector.php b/UniversalLanguageSelector.php index b98d9208..94ce4e27 100644 --- a/UniversalLanguageSelector.php +++ b/UniversalLanguageSelector.php @@ -155,7 +155,7 @@ $GLOBALS['wgULSNoImeSelectors'] = array( '#wpCaptchaWord', '.ve-ce-documentNode' * Autonym * @since 2013.09 */ -$GLOBALS['wgULSNoWebfontsSelectors'] = array( '.autonym' ); +$GLOBALS['wgULSNoWebfontsSelectors'] = array( '#p-lang li.interlanguage-link > a' ); /** * Base path of ULS font repository. diff --git a/lib/jquery.webfonts.js b/lib/jquery.webfonts.js index 63c34f61..e7ce234b 100644 --- a/lib/jquery.webfonts.js +++ b/lib/jquery.webfonts.js @@ -58,13 +58,14 @@ /** * Get the default font family for given language. * @param {String} language Language code. + * @param {array} classes * @return {String} Font family name */ - getFont: function( language ) { + getFont: function( language, classes ) { language = ( language || this.language ).toLowerCase(); if ( this.options.fontSelector ) { - return this.options.fontSelector( this.repository, language ); + return this.options.fontSelector( this.repository, language, classes ); } else { return this.repository.defaultFont( language ); } @@ -199,7 +200,6 @@ // Note: it depends on the browser whether this returns font names // which don't exist. In Chrome it does, while in Opera it doesn't. fontFamilyStyle = $element.css( 'fontFamily' ); - // Note: It is unclear whether this can ever be falsy. Maybe also // browser specific. if ( fontFamilyStyle ) { @@ -220,7 +220,7 @@ // browser settings. return; } else { - fontFamily = webfonts.getFont( element.lang ); + fontFamily = webfonts.getFont( element.lang, element.className.split(/\s+/) ); } if ( !fontFamily ) { @@ -269,8 +269,8 @@ // whether the font is inherited from top element to which plugin applied return this.$element.css( 'fontFamily' ) !== elementFontFamily - // whether the element has generic font family - && ( $.inArray( elementFontFamily, + // whether the element has generic font family + && ( $.inArray( elementFontFamily, ['monospace', 'serif', 'cursive','fantasy', 'sans-serif'] ) < 0 ); }, diff --git a/resources/css/ext.uls.webfonts.css b/resources/css/ext.uls.webfonts.css deleted file mode 100644 index eb348f9a..00000000 --- a/resources/css/ext.uls.webfonts.css +++ /dev/null @@ -1,4 +0,0 @@ -#p-lang li.interlanguage-link, -.autonym { /* provide autonym class for simplifying the Autonym font usage */ - font-family: 'Autonym', sans-serif; -} diff --git a/resources/js/ext.uls.webfonts.js b/resources/js/ext.uls.webfonts.js index f315c173..30a41ec0 100644 --- a/resources/js/ext.uls.webfonts.js +++ b/resources/js/ext.uls.webfonts.js @@ -18,7 +18,11 @@ */ ( function ( $, mw, undefined ) { 'use strict'; - var mediawikiFontRepository, ulsPreferences; + var mediawikiFontRepository, ulsPreferences, + // Text to prepend the sample text. 0D00 is an unassigned unicode point. + tofuSalt = '\u0D00', + // cache languages with tofu. + tofuLanguages = {}; mw.webfonts = mw.webfonts || {}; ulsPreferences = mw.uls.preferences(); @@ -48,19 +52,107 @@ } }; + + /** + * Detect tofu + * + * Create a temporary span in the page with fontsize 72px and font-family + * sans-serif for each letter of the text. + * For each of these spans, calculate the width and height. If they are same + * for all spans, we can understand that each of the letter is rendered using + * same glyph - it must be a tofu. + * + * @param {string} text + * @return {boolean} + */ + function detectTofu( text ) { + var index, + $fixture, + width = {}, + height = {}, + length = Math.min( 4, text.length ), + detected = false; + + text = tofuSalt + text; + $fixture = $( '' ) + .css( { + fontSize: '72px', + fontFamily: 'sans-serif' + } ) + .appendTo( 'body' ); + + for ( index = 0; index < length; index++ ) { + $fixture.text( text[index] ); + width[index] = $fixture.width() || width[index-1]; + height[index] = $fixture.height(); + + if( index > 0 && + ( width[index] !== width[index - 1] || + height[index] !== height[index - 1] ) + ) { + detected = false; + break; + } + } + + $fixture.remove(); + + if ( index === length ) { + detected = true; + } + + return detected; + } + mediawikiFontRepository = $.webfonts.repository; mediawikiFontRepository.base = mw.config.get( 'wgULSFontRepositoryBasePath' ); mw.webfonts.setup = function () { // Initialize webfonts $.fn.webfonts.defaults = $.extend( $.fn.webfonts.defaults, { - fontSelector: function ( repository, language ) { - var font; + /** + * Font selector - depending the language and optionally + * based on the class given choose a font. + * + * @param {Object} repository + * @param {string} language + * @param {array} classes + */ + fontSelector: function ( repository, language, classes ) { + var font, tofu, autonym, defaultFont; + if ( !language ) { + return null; + } + + defaultFont = repository.defaultFont( language ); + + if ( classes && $.inArray( 'autonym', classes ) >= 0 ) { + autonym = true; + } + + // If the user has a font preference, apply it always. font = mw.webfonts.preferences.getFont( language ); + if ( !font || autonym ) { + // Is there any default font for this language? + if ( ( !defaultFont || defaultFont === 'system' ) && !autonym ) { + return font; + } - if ( !font ) { - font = repository.defaultFont( language ); + // There is a default font for this language, + // but check whether the user sees tofu for it. + tofu = tofuLanguages[language] || + detectTofu( $.uls.data.getAutonym( language ) ); + + if ( tofu ) { + mw.log( 'tofu detected for ' + language ); + // Cache the languages with tofu + tofuLanguages[language] = true; + font = autonym ? 'Autonym' : defaultFont; + } else { + // No tofu and no font preference. Use system font. + font = 'system'; + } } if ( font === 'system' ) { @@ -70,15 +162,16 @@ return font; }, + exclude: ( function () { var excludes = $.fn.webfonts.defaults.exclude; if ( mw.user.options.get( 'editfont' ) !== 'default' ) { - // Exclude textboxes from webfonts if user has edit area font option + // Exclude textboxes from webfonts if the user has edit area font option // set using 'Preferences' page - excludes = ( excludes ) - ? excludes + ',textarea' - : 'textarea'; + excludes = ( excludes ) ? + excludes + ',textarea' : + 'textarea'; } return excludes;