Difference between revisions of "MediaWiki:Common.js"

From Twisted Hollywood
Jump to: navigation, search
Line 108: Line 108:
 
}());
 
}());
  
/*global jQuery */
+
(function(window, $) {
/*!
+
  "use strict";
* FitText.js 1.2
 
*
 
* Copyright 2011, Dave Rupert http://daverupert.com
 
* Released under the WTFPL license
 
* http://sam.zoy.org/wtfpl/
 
*
 
* Date: Thu May 05 14:23:00 2011 -0600
 
*/
 
  
(function( $ ){
+
  var counter = 0,
 +
    $headCache = $('head'),
 +
    oldBigText = window.BigText,
 +
    oldjQueryMethod = $.fn.bigtext,
 +
    BigText = {
 +
      DEBUG_MODE: false,
 +
      DEFAULT_MIN_FONT_SIZE_PX: null,
 +
      DEFAULT_MAX_FONT_SIZE_PX: 528,
 +
      GLOBAL_STYLE_ID: 'bigtext-style',
 +
      STYLE_ID: 'bigtext-id',
 +
      LINE_CLASS_PREFIX: 'bigtext-line',
 +
      EXEMPT_CLASS: 'bigtext-exempt',
 +
      noConflict: function(restore)
 +
      {
 +
        if(restore) {
 +
          $.fn.bigtext = oldjQueryMethod;
 +
          window.BigText = oldBigText;
 +
        }
 +
        return BigText;
 +
      },
 +
      supports: {
 +
        wholeNumberFontSizeOnly: (function() {
 +
          if( !( 'getComputedStyle' in window ) ) {
 +
            return true;
 +
          }
 +
          var test = $('<div/>').css({
 +
              position: 'absolute',
 +
              'font-size': '14.1px'
 +
            }).insertBefore( $('script').eq(0) ),
 +
            computedStyle = window.getComputedStyle( test[0], null );
  
  $.fn.fitText = function( kompressor, options ) {
+
          var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px';
 +
          test.remove();
 +
          return ret;
 +
        })()
 +
      },
 +
      init: function() {
 +
        if(!$('#'+BigText.GLOBAL_STYLE_ID).length) {
 +
          $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }',
 +
                                          '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }']));
 +
        }
 +
      },
 +
      bindResize: function(eventName, resizeFunction) {
 +
        var timeoutId;
 +
        $(window).off(eventName).on(eventName, function() {
 +
          if( timeoutId ) {
 +
            clearTimeout( timeoutId );
 +
          }
 +
          timeoutId = setTimeout( resizeFunction, 100 );
 +
        });
 +
      },
 +
      getStyleId: function(id)
 +
      {
 +
        return BigText.STYLE_ID + '-' + id;
 +
      },
 +
      generateStyleTag: function(id, css)
 +
      {
 +
        return $('<style>' + css.join('\n') + '</style>').attr('id', id);
 +
      },
 +
      clearCss: function(id)
 +
      {
 +
        var styleId = BigText.getStyleId(id);
 +
        $('#' + styleId).remove();
 +
      },
 +
      generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes)
 +
      {
 +
        var css = [];
  
    // Setup options
+
         BigText.clearCss(id);
    var compressor = kompressor || 1,
 
         settings = $.extend({
 
          'minFontSize' : Number.NEGATIVE_INFINITY,
 
          'maxFontSize' : Number.POSITIVE_INFINITY
 
        }, options);
 
  
    return this.each(function(){
+
        for(var j=0, k=linesFontSizes.length; j<k; j++) {
 +
          css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' +
 +
            (minFontSizes[j] ? ' white-space: normal;' : '') +
 +
            (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') +
 +
            (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') +
 +
            '}');
 +
        }
  
       // Store the object
+
        return BigText.generateStyleTag(BigText.getStyleId(id), css);
       var $this = $(this);
+
       },
 +
       jQueryMethod: function(options)
 +
      {
 +
        BigText.init();
  
      // Resizer() resizes items based on the object width divided by the compressor * 10
+
        options = $.extend({
      var resizer = function () {
+
          minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX,
        $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));
+
          maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX,
      };
+
          childSelector: '',
 +
          resize: true
 +
        }, options || {});
  
      // Call once to set.
+
        this.each(function()
      resizer();
+
        {
 +
          var $t = $(this).addClass('bigtext'),
 +
            maxWidth = $t.width(),
 +
            id = $t.attr('id'),
 +
            $children = options.childSelector ? $t.find( options.childSelector ) : $t.children();
  
      // Call on resize. Opera debounces their resize by default.
+
          if(!id) {
      $(window).on('resize.fittext orientationchange.fittext', resizer);
+
            id = 'bigtext-id' + (counter++);
 +
            $t.attr('id', id);
 +
          }
  
    });
+
          if(options.resize) {
 +
            BigText.bindResize('resize.bigtext-event-' + id, function()
 +
            {
 +
              // TODO only call this if the width has changed.
 +
              BigText.jQueryMethod.call($('#' + id), options);
 +
            });
 +
          }
  
  };
+
          BigText.clearCss(id);
  
})( jQuery );
+
          $children.addClass(function(lineNumber, className)
 +
          {
 +
            // remove existing line classes.
 +
            return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''),
 +
                BigText.LINE_CLASS_PREFIX + lineNumber].join(' ');
 +
          });
 +
 
 +
          var sizes = BigText.calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize);
 +
          $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes));
 +
        });
 +
 
 +
        return this.trigger('bigtext:complete');
 +
      },
 +
      testLineDimensions: function($line, maxWidth, property, size, interval, units, previousWidth)
 +
      {
 +
        var width;
 +
        previousWidth = typeof previousWidth === 'number' ? previousWidth : 0;
 +
        $line.css(property, size + units);
 +
 
 +
        width = $line.width();
 +
 
 +
        if(width >= maxWidth) {
 +
    // console.log(width, ' previous: ' + previousWidth, property + ' at ' + interval, 'prior: ' + (parseFloat(size) - interval), 'new:' + parseFloat(size));
 +
          $line.css(property, '');
 +
 
 +
          if(width === maxWidth) {
 +
            return {
 +
              match: 'exact',
 +
              size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
 +
            };
 +
          }
 +
 
 +
          // Since this is an estimate, we calculate how far over the width we went with the new value.
 +
          // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value.
 +
          // Otherwise, we revert to the underestimate.
 +
          var under = maxWidth - previousWidth,
 +
            over = width - maxWidth;
 +
 
 +
          return {
 +
            match: 'estimate',
 +
            size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3))
 +
          };
 +
        }
 +
 
 +
        return width;
 +
      },
 +
      calculateSizes: function($t, $children, maxWidth, maxFontSize, minFontSize)
 +
      {
 +
        var $c = $t.clone(true)
 +
          .addClass('bigtext-cloned')
 +
          .css({
 +
            fontFamily: $t.css('font-family'),
 +
            textTransform: $t.css('text-transform'),
 +
            wordSpacing: $t.css('word-spacing'),
 +
            letterSpacing: $t.css('letter-spacing'),
 +
            position: 'absolute',
 +
            left: BigText.DEBUG_MODE ? 0 : -9999,
 +
            top: BigText.DEBUG_MODE ? 0 : -9999
 +
          })
 +
          .appendTo(document.body);
 +
 
 +
        // font-size isn't the only thing we can modify, we can also mess with:
 +
        // word-spacing and letter-spacing. WebKit does not respect subpixel
 +
        // letter-spacing, word-spacing, or font-size.
 +
        // TODO try -webkit-transform: scale() as a workaround.
 +
        var fontSizes = [],
 +
          wordSpacings = [],
 +
          minFontSizes = [],
 +
          ratios = [];
 +
 
 +
        $children.css('float', 'left').each(function() {
 +
          var $line = $(this),
 +
            // TODO replace 8, 4 with a proportional size to the calculated font-size.
 +
            intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1],
 +
            lineMax,
 +
            newFontSize;
 +
 
 +
          if($line.hasClass(BigText.EXEMPT_CLASS)) {
 +
            fontSizes.push(null);
 +
            ratios.push(null);
 +
            minFontSizes.push(false);
 +
            return;
 +
          }
 +
 
 +
          // TODO we can cache this ratio?
 +
          var autoGuessSubtraction = 32, // font size in px
 +
            currentFontSize = parseFloat($line.css('font-size')),
 +
            ratio = ( $line.width() / currentFontSize ).toFixed(6);
 +
 
 +
          newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction;
 +
 
 +
          outer: for(var m=0, n=intervals.length; m<n; m++) {
 +
            inner: for(var j=1, k=10; j<=k; j++) {
 +
              if(newFontSize + j*intervals[m] > maxFontSize) {
 +
                newFontSize = maxFontSize;
 +
                break outer;
 +
              }
 +
 
 +
              lineMax = BigText.testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax);
 +
              if(typeof lineMax !== 'number') {
 +
                newFontSize = lineMax.size;
 +
 
 +
                if(lineMax.match === 'exact') {
 +
                  break outer;
 +
                }
 +
                break inner;
 +
              }
 +
            }
 +
          }
 +
 
 +
          ratios.push(maxWidth / newFontSize);
 +
 
 +
          if(newFontSize > maxFontSize) {
 +
            fontSizes.push(maxFontSize);
 +
            minFontSizes.push(false);
 +
          } else if(!!minFontSize && newFontSize < minFontSize) {
 +
            fontSizes.push(minFontSize);
 +
            minFontSizes.push(true);
 +
          } else {
 +
            fontSizes.push(newFontSize);
 +
            minFontSizes.push(false);
 +
          }
 +
        }).each(function(lineNumber) {
 +
          var $line = $(this),
 +
            wordSpacing = 0,
 +
            interval = 1,
 +
            maxWordSpacing;
 +
 
 +
          if($line.hasClass(BigText.EXEMPT_CLASS)) {
 +
            wordSpacings.push(null);
 +
            return;
 +
          }
 +
 
 +
          // must re-use font-size, even though it was removed above.
 +
          $line.css('font-size', fontSizes[lineNumber] + 'px');
 +
 
 +
          for(var m=1, n=3; m<n; m+=interval) {
 +
            maxWordSpacing = BigText.testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing);
 +
            if(typeof maxWordSpacing !== 'number') {
 +
              wordSpacing = maxWordSpacing.size;
 +
              break;
 +
            }
 +
          }
 +
 
 +
          $line.css('font-size', '');
 +
          wordSpacings.push(wordSpacing);
 +
        }).removeAttr('style');
 +
 
 +
        if( !BigText.DEBUG_MODE ) {
 +
          $c.remove();
 +
        } else {
 +
          $c.css({
 +
            'background-color': 'rgba(255,255,255,.4)'
 +
          });
 +
        }
 +
 
 +
        return {
 +
          fontSizes: fontSizes,
 +
          wordSpacings: wordSpacings,
 +
          ratios: ratios,
 +
          minFontSizes: minFontSizes
 +
        };
 +
      }
 +
    };
 +
 
 +
  $.fn.bigtext = BigText.jQueryMethod;
 +
  window.BigText = BigText;
 +
 
 +
})(this, jQuery);

Revision as of 09:30, 29 November 2022

/* Any JavaScript here will be loaded for all users on every page load. */
/**
 * Dynamic Navigation Bars. See [[Wikipedia:NavFrame]]
 * 
 * Based on script from en.wikipedia.org, 2008-09-15.
 *
 * @source www.mediawiki.org/wiki/MediaWiki:Gadget-NavFrame.js
 * @maintainer Helder.wiki, 2012–2013
 * @maintainer Krinkle, 2013
 */
( function () {

// Set up the words in your language
var collapseCaption = 'hide';
var expandCaption = 'show';

var navigationBarHide = '[' + collapseCaption + ']';
var navigationBarShow = '[' + expandCaption + ']';

/**
 * Shows and hides content and picture (if available) of navigation bars.
 *
 * @param {number} indexNavigationBar The index of navigation bar to be toggled
 * @param {jQuery.Event} e Event object
 */
function toggleNavigationBar( indexNavigationBar, e ) {
	var navChild,
		navToggle = document.getElementById( 'NavToggle' + indexNavigationBar ),
		navFrame = document.getElementById( 'NavFrame' + indexNavigationBar );

	// Prevent browser from jumping to href "#"
	e.preventDefault();

	if ( !navFrame || !navToggle ) {
		return false;
	}

	// If shown now
	if ( navToggle.firstChild.data === navigationBarHide ) {
		for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
			if ( $( navChild ).hasClass( 'NavContent' ) || $( navChild ).hasClass( 'NavPic' ) ) {
				navChild.style.display = 'none';
			}
		}
		navToggle.firstChild.data = navigationBarShow;

	// If hidden now
	} else if ( navToggle.firstChild.data === navigationBarShow ) {
		for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
			if ( $( navChild ).hasClass( 'NavContent' ) || $( navChild ).hasClass( 'NavPic' ) ) {
				navChild.style.display = 'block';
			}
		}
		navToggle.firstChild.data = navigationBarHide;
	}
}

/**
 * Adds show/hide-button to navigation bars.
 *
 * @param {jQuery} $content
 */
function createNavigationBarToggleButton( $content ) {
	var i, j, navChild, navToggle, navToggleText, isCollapsed,
		indexNavigationBar = 0;
	// iterate over all < div >-elements
	var $divs = $content.find( 'div.NavFrame' );
	$divs.each( function ( i, navFrame ) {
		indexNavigationBar++;
		navToggle = document.createElement( 'a' );
		navToggle.className = 'NavToggle';
		navToggle.setAttribute( 'id', 'NavToggle' + indexNavigationBar );
		navToggle.setAttribute( 'href', '#' );
		$( navToggle ).on( 'click', $.proxy( toggleNavigationBar, null, indexNavigationBar ) );

		isCollapsed = $( navFrame ).hasClass( 'collapsed' );
		// backwards compatibility for old technique where the collapsed class was not yet used
		for ( navChild = navFrame.firstChild; navChild !== null && !isCollapsed; navChild = navChild.nextSibling ) {
			if ( $( navChild ).hasClass( 'NavPic' ) || $( navChild ).hasClass( 'NavContent' ) ) {
				if ( navChild.style.display === 'none' ) {
					isCollapsed = true;
				}
			}
		}
		if ( isCollapsed ) {
			for ( navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling ) {
				if ( $( navChild ).hasClass( 'NavPic' ) || $( navChild ).hasClass( 'NavContent' ) ) {
					navChild.style.display = 'none';
				}
			}
		}
		navToggleText = document.createTextNode( isCollapsed ? navigationBarShow : navigationBarHide );
		navToggle.appendChild( navToggleText );

		// Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked)
		for ( j = 0; j < navFrame.childNodes.length; j++ ) {
			if ( $( navFrame.childNodes[j] ).hasClass( 'NavHead' ) ) {
				navToggle.style.color = navFrame.childNodes[j].style.color;
				navFrame.childNodes[j].appendChild( navToggle );
			}
		}
		navFrame.setAttribute( 'id', 'NavFrame' + indexNavigationBar );
	} );
}

mw.hook( 'wikipage.content' ).add( createNavigationBarToggleButton );

}());

(function(window, $) {
  "use strict";

  var counter = 0,
    $headCache = $('head'),
    oldBigText = window.BigText,
    oldjQueryMethod = $.fn.bigtext,
    BigText = {
      DEBUG_MODE: false,
      DEFAULT_MIN_FONT_SIZE_PX: null,
      DEFAULT_MAX_FONT_SIZE_PX: 528,
      GLOBAL_STYLE_ID: 'bigtext-style',
      STYLE_ID: 'bigtext-id',
      LINE_CLASS_PREFIX: 'bigtext-line',
      EXEMPT_CLASS: 'bigtext-exempt',
      noConflict: function(restore)
      {
        if(restore) {
          $.fn.bigtext = oldjQueryMethod;
          window.BigText = oldBigText;
        }
        return BigText;
      },
      supports: {
        wholeNumberFontSizeOnly: (function() {
          if( !( 'getComputedStyle' in window ) ) {
            return true;
          }
          var test = $('<div/>').css({
              position: 'absolute',
              'font-size': '14.1px'
            }).insertBefore( $('script').eq(0) ),
            computedStyle = window.getComputedStyle( test[0], null );

          var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px';
          test.remove();
          return ret;
        })()
      },
      init: function() {
        if(!$('#'+BigText.GLOBAL_STYLE_ID).length) {
          $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }',
                                          '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }']));
        }
      },
      bindResize: function(eventName, resizeFunction) {
        var timeoutId;
        $(window).off(eventName).on(eventName, function() {
          if( timeoutId ) {
            clearTimeout( timeoutId );
          }
          timeoutId = setTimeout( resizeFunction, 100 );
        });
      },
      getStyleId: function(id)
      {
        return BigText.STYLE_ID + '-' + id;
      },
      generateStyleTag: function(id, css)
      {
        return $('<style>' + css.join('\n') + '</style>').attr('id', id);
      },
      clearCss: function(id)
      {
        var styleId = BigText.getStyleId(id);
        $('#' + styleId).remove();
      },
      generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes)
      {
        var css = [];

        BigText.clearCss(id);

        for(var j=0, k=linesFontSizes.length; j<k; j++) {
          css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' +
            (minFontSizes[j] ? ' white-space: normal;' : '') +
            (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') +
            (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') +
            '}');
        }

        return BigText.generateStyleTag(BigText.getStyleId(id), css);
      },
      jQueryMethod: function(options)
      {
        BigText.init();

        options = $.extend({
          minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX,
          maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX,
          childSelector: '',
          resize: true
        }, options || {});

        this.each(function()
        {
          var $t = $(this).addClass('bigtext'),
            maxWidth = $t.width(),
            id = $t.attr('id'),
            $children = options.childSelector ? $t.find( options.childSelector ) : $t.children();

          if(!id) {
            id = 'bigtext-id' + (counter++);
            $t.attr('id', id);
          }

          if(options.resize) {
            BigText.bindResize('resize.bigtext-event-' + id, function()
            {
              // TODO only call this if the width has changed.
              BigText.jQueryMethod.call($('#' + id), options);
            });
          }

          BigText.clearCss(id);

          $children.addClass(function(lineNumber, className)
          {
            // remove existing line classes.
            return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''),
                BigText.LINE_CLASS_PREFIX + lineNumber].join(' ');
          });

          var sizes = BigText.calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize);
          $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes));
        });

        return this.trigger('bigtext:complete');
      },
      testLineDimensions: function($line, maxWidth, property, size, interval, units, previousWidth)
      {
        var width;
        previousWidth = typeof previousWidth === 'number' ? previousWidth : 0;
        $line.css(property, size + units);

        width = $line.width();

        if(width >= maxWidth) {
    // console.log(width, ' previous: ' + previousWidth, property + ' at ' + interval, 'prior: ' + (parseFloat(size) - interval), 'new:' + parseFloat(size));
          $line.css(property, '');

          if(width === maxWidth) {
            return {
              match: 'exact',
              size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
            };
          }

          // Since this is an estimate, we calculate how far over the width we went with the new value.
          // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value.
          // Otherwise, we revert to the underestimate.
          var under = maxWidth - previousWidth,
            over = width - maxWidth;

          return {
            match: 'estimate',
            size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3))
          };
        }

        return width;
      },
      calculateSizes: function($t, $children, maxWidth, maxFontSize, minFontSize)
      {
        var $c = $t.clone(true)
          .addClass('bigtext-cloned')
          .css({
            fontFamily: $t.css('font-family'),
            textTransform: $t.css('text-transform'),
            wordSpacing: $t.css('word-spacing'),
            letterSpacing: $t.css('letter-spacing'),
            position: 'absolute',
            left: BigText.DEBUG_MODE ? 0 : -9999,
            top: BigText.DEBUG_MODE ? 0 : -9999
          })
          .appendTo(document.body);

        // font-size isn't the only thing we can modify, we can also mess with:
        // word-spacing and letter-spacing. WebKit does not respect subpixel
        // letter-spacing, word-spacing, or font-size.
        // TODO try -webkit-transform: scale() as a workaround.
        var fontSizes = [],
          wordSpacings = [],
          minFontSizes = [],
          ratios = [];

        $children.css('float', 'left').each(function() {
          var $line = $(this),
            // TODO replace 8, 4 with a proportional size to the calculated font-size.
            intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1],
            lineMax,
            newFontSize;

          if($line.hasClass(BigText.EXEMPT_CLASS)) {
            fontSizes.push(null);
            ratios.push(null);
            minFontSizes.push(false);
            return;
          }

          // TODO we can cache this ratio?
          var autoGuessSubtraction = 32, // font size in px
            currentFontSize = parseFloat($line.css('font-size')),
            ratio = ( $line.width() / currentFontSize ).toFixed(6);

          newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction;

          outer: for(var m=0, n=intervals.length; m<n; m++) {
            inner: for(var j=1, k=10; j<=k; j++) {
              if(newFontSize + j*intervals[m] > maxFontSize) {
                newFontSize = maxFontSize;
                break outer;
              }

              lineMax = BigText.testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax);
              if(typeof lineMax !== 'number') {
                newFontSize = lineMax.size;

                if(lineMax.match === 'exact') {
                  break outer;
                }
                break inner;
              }
            }
          }

          ratios.push(maxWidth / newFontSize);

          if(newFontSize > maxFontSize) {
            fontSizes.push(maxFontSize);
            minFontSizes.push(false);
          } else if(!!minFontSize && newFontSize < minFontSize) {
            fontSizes.push(minFontSize);
            minFontSizes.push(true);
          } else {
            fontSizes.push(newFontSize);
            minFontSizes.push(false);
          }
        }).each(function(lineNumber) {
          var $line = $(this),
            wordSpacing = 0,
            interval = 1,
            maxWordSpacing;

          if($line.hasClass(BigText.EXEMPT_CLASS)) {
            wordSpacings.push(null);
            return;
          }

          // must re-use font-size, even though it was removed above.
          $line.css('font-size', fontSizes[lineNumber] + 'px');

          for(var m=1, n=3; m<n; m+=interval) {
            maxWordSpacing = BigText.testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing);
            if(typeof maxWordSpacing !== 'number') {
              wordSpacing = maxWordSpacing.size;
              break;
            }
          }

          $line.css('font-size', '');
          wordSpacings.push(wordSpacing);
        }).removeAttr('style');

        if( !BigText.DEBUG_MODE ) {
          $c.remove();
        } else {
          $c.css({
            'background-color': 'rgba(255,255,255,.4)'
          });
        }

        return {
          fontSizes: fontSizes,
          wordSpacings: wordSpacings,
          ratios: ratios,
          minFontSizes: minFontSizes
        };
      }
    };

  $.fn.bigtext = BigText.jQueryMethod;
  window.BigText = BigText;

})(this, jQuery);