diff --git a/ajax/libs/slabText/2.2/jquery.slabtext.js b/ajax/libs/slabText/2.2/jquery.slabtext.js new file mode 100644 index 000000000..278385c46 --- /dev/null +++ b/ajax/libs/slabText/2.2/jquery.slabtext.js @@ -0,0 +1,240 @@ +/*! jQuery slabtext plugin v2.2 MIT/GPL2 @freqdec */ +(function( $ ){ + + $.fn.slabText = function(options) { + + var settings = { + // The ratio used when calculating the characters per line + // (parent width / (font-size * fontRatio)). + "fontRatio" : 0.78, + // Always recalculate the characters per line, not just when the + // font-size changes? Defaults to true (CPU intensive) + "forceNewCharCount" : true, + // Do we wrap ampersands in + "wrapAmpersand" : true, + // Under what pixel width do we remove the slabtext styling? + "headerBreakpoint" : null, + "viewportBreakpoint" : null, + // Don't attach a resize event + "noResizeEvent" : false, + // By many milliseconds do we throttle the resize event + "resizeThrottleTime" : 300, + // The maximum pixel font size the script can set + "maxFontSize" : 999, + // Do we try to tweak the letter-spacing or word-spacing? + "postTweak" : true, + // Decimal precision to use when setting CSS values + "precision" : 3, + // The min num of chars a line has to contain + "minCharsPerLine" : 0 + }; + + // Add the slabtexted classname to the body to initiate the styling of + // the injected spans + $("body").addClass("slabtexted"); + + return this.each(function(){ + + if(options) { + $.extend(settings, options); + }; + + var $this = $(this), + keepSpans = $("span.slabtext", $this).length, + words = keepSpans ? [] : String($.trim($this.text())).replace(/\s{2,}/g, " ").split(" "), + origFontSize = null, + idealCharPerLine = null, + fontRatio = settings.fontRatio, + forceNewCharCount = settings.forceNewCharCount, + headerBreakpoint = settings.headerBreakpoint, + viewportBreakpoint = settings.viewportBreakpoint, + postTweak = settings.postTweak, + precision = settings.precision, + resizeThrottleTime = settings.resizeThrottleTime, + minCharsPerLine = settings.minCharsPerLine, + resizeThrottle = null, + viewportWidth = $(window).width(), + headLink = $this.find("a:first").attr("href") || $this.attr("href"), + linkTitle = headLink ? $this.find("a:first").attr("title") : ""; + + if(!keepSpans && minCharsPerLine && words.join(" ").length < minCharsPerLine) { + return; + }; + + // Calculates the pixel equivalent of 1em within the current header + var grabPixelFontSize = function() { + var dummy = jQuery('
 
').appendTo($this), + emH = dummy.height(); + dummy.remove(); + return emH; + }; + + // Most of this function is a (very) stripped down AS3 to JS port of + // the slabtype algorithm by Eric Loyer with the original comments + // left intact + // http://erikloyer.com/index.php/blog/the_slabtype_algorithm_part_1_background/ + var resizeSlabs = function resizeSlabs() { + + // Cache the parent containers width + var parentWidth = $this.width(), + fs; + + // Remove the slabtextdone and slabtextinactive classnames to enable the inline-block shrink-wrap effect + $this.removeClass("slabtextdone slabtextinactive"); + + if(viewportBreakpoint && viewportBreakpoint > viewportWidth + || + headerBreakpoint && headerBreakpoint > parentWidth) { + // Add the slabtextinactive classname to set the spans as inline + // and to reset the font-size to 1em (inherit won't work in IE6/7) + $this.addClass("slabtextinactive"); + return; + }; + + fs = grabPixelFontSize(); + // If the parent containers font-size has changed or the "forceNewCharCount" option is true (the default), + // then recalculate the "characters per line" count and re-render the inner spans + // Setting "forceNewCharCount" to false will save CPU cycles... + if(!keepSpans && (forceNewCharCount || fs != origFontSize)) { + + origFontSize = fs; + + var newCharPerLine = Math.min(60, Math.floor(parentWidth / (origFontSize * fontRatio))), + wordIndex = 0, + lineText = [], + counter = 0, + preText = "", + postText = "", + finalText = "", + slice, + preDiff, + postDiff; + + if(newCharPerLine != idealCharPerLine) { + idealCharPerLine = newCharPerLine; + + while (wordIndex < words.length) { + + postText = ""; + + // build two strings (preText and postText) word by word, with one + // string always one word behind the other, until + // the length of one string is less than the ideal number of characters + // per line, while the length of the other is greater than that ideal + while (postText.length < idealCharPerLine) { + preText = postText; + postText += words[wordIndex] + " "; + if(++wordIndex >= words.length) { + break; + }; + }; + + // This bit hacks in a minimum characters per line test + // on the last line + if(minCharsPerLine) { + slice = words.slice(wordIndex).join(" "); + if(slice.length < minCharsPerLine) { + postText += slice; + preText = postText; + wordIndex = words.length + 2; + }; + }; + + // calculate the character difference between the two strings and the + // ideal number of characters per line + preDiff = idealCharPerLine - preText.length; + postDiff = postText.length - idealCharPerLine; + + // if the smaller string is closer to the length of the ideal than + // the longer string, and doesn’t contain less than minCharsPerLine + // characters, then use that one for the line + if((preDiff < postDiff) && (preText.length >= (minCharsPerLine || 2))) { + finalText = preText; + wordIndex--; + // otherwise, use the longer string for the line + } else { + finalText = postText; + }; + + // HTML-escape the text + finalText = $('
').text(finalText).html() + + // Wrap ampersands in spans with class `amp` for specific styling + if(settings.wrapAmpersand) { + finalText = finalText.replace(/&/g, '&'); + }; + + finalText = $.trim(finalText) + + lineText.push('' + finalText + ""); + }; + + $this.html(lineText.join(" ")); + // If we have a headLink, add it back just inside our target, around all the slabText spans + if(headLink) { + $this.wrapInner(''); + }; + }; + } else { + // We only need the font-size for the resize-to-fit functionality + // if not injecting the spans + origFontSize = fs; + }; + + $("span.slabtext", $this).each(function() { + var $span = $(this), + // the .text method appears as fast as using custom -data attributes in this case + innerText = $span.text(), + wordSpacing = innerText.split(" ").length > 1, + diff, + ratio, + fontSize; + + if(postTweak) { + $span.css({ + "word-spacing":0, + "letter-spacing":0 + }); + }; + + ratio = parentWidth / $span.width(); + fontSize = parseFloat(this.style.fontSize) || origFontSize; + + $span.css("font-size", Math.min((fontSize * ratio).toFixed(precision), settings.maxFontSize) + "px"); + + // Do we still have space to try to fill or crop + diff = !!postTweak ? parentWidth - $span.width() : false; + + // A "dumb" tweak in the blind hope that the browser will + // resize the text to better fit the available space. + // Better "dumb" and fast... + if(diff) { + $span.css((wordSpacing ? 'word' : 'letter') + '-spacing', (diff / (wordSpacing ? innerText.split(" ").length - 1 : innerText.length)).toFixed(precision) + "px"); + }; + }); + + // Add the class slabtextdone to set a display:block on the child spans + // and avoid styling & layout issues associated with inline-block + $this.addClass("slabtextdone"); + }; + + // Immediate resize + resizeSlabs(); + + if(!settings.noResizeEvent) { + $(window).resize(function() { + // Only run the resize code if the viewport width has changed. + // we ignore the viewport height as it will be constantly changing. + if($(window).width() == viewportWidth) { + return; + }; + + viewportWidth = $(window).width(); + + clearTimeout(resizeThrottle); + resizeThrottle = setTimeout(resizeSlabs, resizeThrottleTime); + }); + }; + }); + }; +})(jQuery); \ No newline at end of file diff --git a/ajax/libs/slabText/2.2/jquery.slabtext.min.js b/ajax/libs/slabText/2.2/jquery.slabtext.min.js new file mode 100644 index 000000000..eee573fcb --- /dev/null +++ b/ajax/libs/slabText/2.2/jquery.slabtext.min.js @@ -0,0 +1,2 @@ +/*! jQuery slabtext plugin v2.2 MIT/GPL2 @freqdec */ +(function($){$.fn.slabText=function(options){var settings={fontRatio:0.78,forceNewCharCount:true,wrapAmpersand:true,headerBreakpoint:null,viewportBreakpoint:null,noResizeEvent:false,resizeThrottleTime:300,maxFontSize:999,postTweak:true,precision:3,minCharsPerLine:0};$("body").addClass("slabtexted");return this.each(function(){if(options){$.extend(settings,options);}var $this=$(this),keepSpans=$("span.slabtext",$this).length,words=keepSpans?[]:String($.trim($this.text())).replace(/\s{2,}/g," ").split(" "),origFontSize=null,idealCharPerLine=null,fontRatio=settings.fontRatio,forceNewCharCount=settings.forceNewCharCount,headerBreakpoint=settings.headerBreakpoint,viewportBreakpoint=settings.viewportBreakpoint,postTweak=settings.postTweak,precision=settings.precision,resizeThrottleTime=settings.resizeThrottleTime,minCharsPerLine=settings.minCharsPerLine,resizeThrottle=null,viewportWidth=$(window).width(),headLink=$this.find("a:first").attr("href")||$this.attr("href"),linkTitle=headLink?$this.find("a:first").attr("title"):"";if(!keepSpans&&minCharsPerLine&&words.join(" ").length 
').appendTo($this),emH=dummy.height();dummy.remove();return emH;};var resizeSlabs=function resizeSlabs(){var parentWidth=$this.width(),fs;$this.removeClass("slabtextdone slabtextinactive");if(viewportBreakpoint&&viewportBreakpoint>viewportWidth||headerBreakpoint&&headerBreakpoint>parentWidth){$this.addClass("slabtextinactive");return;}fs=grabPixelFontSize();if(!keepSpans&&(forceNewCharCount||fs!=origFontSize)){origFontSize=fs;var newCharPerLine=Math.min(60,Math.floor(parentWidth/(origFontSize*fontRatio))),wordIndex=0,lineText=[],counter=0,preText="",postText="",finalText="",slice,preDiff,postDiff;if(newCharPerLine!=idealCharPerLine){idealCharPerLine=newCharPerLine;while(wordIndex=words.length){break;}}if(minCharsPerLine){slice=words.slice(wordIndex).join(" ");if(slice.length=(minCharsPerLine||2))){finalText=preText;wordIndex--;}else{finalText=postText;}finalText=$("
").text(finalText).html();if(settings.wrapAmpersand){finalText=finalText.replace(/&/g,'&');}finalText=$.trim(finalText);lineText.push(''+finalText+"");}$this.html(lineText.join(" "));if(headLink){$this.wrapInner('");}}}else{origFontSize=fs;}$("span.slabtext",$this).each(function(){var $span=$(this),innerText=$span.text(),wordSpacing=innerText.split(" ").length>1,diff,ratio,fontSize;if(postTweak){$span.css({"word-spacing":0,"letter-spacing":0});}ratio=parentWidth/$span.width();fontSize=parseFloat(this.style.fontSize)||origFontSize;$span.css("font-size",Math.min((fontSize*ratio).toFixed(precision),settings.maxFontSize)+"px");diff=!!postTweak?parentWidth-$span.width():false;if(diff){$span.css((wordSpacing?"word":"letter")+"-spacing",(diff/(wordSpacing?innerText.split(" ").length-1:innerText.length)).toFixed(precision)+"px");}});$this.addClass("slabtextdone");};resizeSlabs();if(!settings.noResizeEvent){$(window).resize(function(){if($(window).width()==viewportWidth){return;}viewportWidth=$(window).width();clearTimeout(resizeThrottle);resizeThrottle=setTimeout(resizeSlabs,resizeThrottleTime);});}});};})(jQuery); \ No newline at end of file diff --git a/ajax/libs/slabText/package.json b/ajax/libs/slabText/package.json new file mode 100755 index 000000000..f0e9de8e3 --- /dev/null +++ b/ajax/libs/slabText/package.json @@ -0,0 +1,27 @@ +{ + "name": "slabText", + "filename": "jquery.slabtext.min.js", + "version": "2.2", + "description": "A jQuery plugin for producing big, bold & responsive headlines.", + "homepage": "http://www.frequency-decoder.com/demo/slabText/", + "keywords": [ + "headlines", + "jquery", + "popular", + "responsive", + "typography" + ], + "maintainers": [ + { + "name": "Brian McAllister", + "email": "frequency.decoder@gmail.com", + "web": "http://www.frequency-decoder.com/" + } + ], + "repositories": [ + { + "type": "git", + "url": "https://github.com/freqdec/slabText" + } + ] +}