(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: 1056,
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(){
BigText.jQueryMethod.call($('#' + id), options);
});
}
BigText.clearCss(id);
$children.addClass(function(lineNumber, className){
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){
$line.css(property, '');
if(width===maxWidth){
return {
match: 'exact',
size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
};}
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);
var fontSizes=[],
wordSpacings=[],
minFontSizes=[],
ratios=[];
$children.css('float', 'left').each(function(){
var $line=$(this),
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;
}
var autoGuessSubtraction=32,
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;
}
$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);