jquery.text.shadow.performance

JavaScript performance comparison

Revision 9 of this test case created

Preparation code

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<style type="text/css">
                        div.testing{background:black;color:red;height:200px;width:100%;text-align:center;margin:20px 0 0;text-shadow:0 1px 0 #FFF;}
                        div.testing > span {text-align:center;}
                </style>
<div class="testing">
                        testing string
                </div>
<script>
Benchmark.prototype.setup = function() {
    /*
     * Plugin: jquery.text.shadow
     * Version: 1.4
     *
     * Description:
     * - Improved text-shadow plugin for jQuery.
     */

    (function($){
        var methods=[function(rx){return {x:0,y:0};},function(rx){return {x:rx[0],y:rx[0]};},function(rx){return {x:rx[0],y:rx[1]};},function(rx){return {x:rx[0],y:rx[1],radius:rx[2]};}];
        $.extend($,{
                textShadowParseEx:function(value){
                        var position=value.match(/-?(\d+)(?=[a-z%]+)/gi),
                                color=value.match(/#[0-9a-f]+|(?:rgb|hsb)a?\([^\)]*\)|\b[a-z]+\b/i),
                                shadow={x:0,y:0,radius:0,color:color[0] || 'transparent'},
                                posLength=position.length || 0,
                                colorLength=color.length || 0;
                       
                        if (posLength>0 || colorLength>0)
                        {
                                $.extend(shadow,methods[Math.min(3,posLength)](position));
                                if ((!shadow.x && !shadow.y && !shadow.radius) || shadow.color == 'transparent')
                                        $.extend(shadow,{x:0,y:0,radius:0,color:null});
                        }
                       
                        return shadow;
                },
                textShadowParse:function(str){
                        var values=str.split(','),index=values.length;
               
                        if (index>0)
                        {
                                var stack=[];
                       
                                while(index--)
                                        stack.push(this.textShadowParseEx(values[index]))
   
                                return stack;
                        }
                       
                        return [this.textShadowParseEx(str)];
                }
        });
        $.fn.stextShadowParse=function(value){
                return $.textShadowParse(value);
        }
    })(jQuery);
    $.browser.msie
        ? (function($){
                var textShadow=function(element){
                        var shadowElement=document.createElement('span');
               
                        return $.extend(this,{
                                append:function(){
                                        var nodes=element.childNodes;
                                        for (var i=0,il=nodes.length;i<il;i++)
                                                if (! /jQueryTextShadow/i.test(nodes[i].className))
                                                        shadowElement.appendChild(nodes[i].cloneNode(true));
                                               
                                        element.appendChild(shadowElement);
                                       
                                        if ((element.offsetHeight || element.clientHeight)<(shadowElement.offsetHeight || shadowElement.clientHeight))
                                                        shadowElement.style.width=(parseInt(shadowElement.style.width)+1)+'px';
                                },
                                set:function(options){
                                        shadowElement.className='jQueryTextShadow index'+options.index;
   
                                        try
                                        {
                                                $.extend(shadowElement.style,{
                                                        padding:options.padding,
                                                        width:options.width+'px',
                                                        position:'absolute',
                                                        zIndex:'-1',
                                                        color:options.color,
                                                        left:options.posX+'px',
                                                        top:options.posY+'px'
                                                });
                                        }
                                        catch(e) {return false;}
   
                                        if (options.radius!=0)
                                                shadowElement.style.filter=options.opacity!=null
                                                        ? 'progid:DXImageTransform.Microsoft.Blur(pixelradius='+parseInt(options.radius)+', enabled=\'true\', makeShadow=\'true\', ShadowOpacity='+options.opacity+')'
                                                        : 'progid:DXImageTransform.Microsoft.Blur(pixelradius='+parseInt(options.radius)+', enabled=\'true\')';
                                                       
                                        return true;
                                },
                                destroy:function(){
                                        if (shadowElement.parentNode) element.removeChild(shadowElement);
                                }
                        });
                };
                $.extend(textShadow,{
                        prepareParent:$.browser.version<8
                                ? function (element) {
                                        element.style.zoom=1;
                                        element.style.zIndex=0;
                                        if (element.currentStyle['position']!='absolute') element.style.position='relative';
                                }
                                : function (element) {;
                                        element.style.zIndex=0;
                                        if (element.currentStyle['position']!='absolute') element.style.position='relative';
                                },
                        getIndex:function(el,shadow)
                        {
                                if (!('textShadowController' in el))
                                {
                                        textShadow.prepareParent(el);
                                        el.textShadowController={stackSize:1,stack:[shadow],freeSize:0,free:[]};
                                       
                                        return 0;
                                }
                               
                                var index=el.textShadowController.freeSize>0 ? el.textShadowController.free[--el.textShadowController.freeSize] : el.textShadowController.stackSize++;
                                el.textShadowController.stack[index]=shadow;
                               
                                return index;
                        },
                        add:function(el,props){
                                if (props.x==0 && props.y==0 && props.radius==0) return false;
                       
                                var style=el.currentStyle,
                                        shadow=new textShadow(el),
                                        index=textShadow.getIndex(el,shadow),
                                        config={
                                        padding:style["padding"],
                                        width:Math.max(0,(el.offsetWidth || el.clientWidth)-parseInt(style['padding-left'])-parseInt(style['padding-right'])),
                                        color:props.color!=null ? props.color : el.style.color,
                                        posX:(-parseInt(props.radius)+parseInt(props.x)),
                                        posY:(-parseInt(props.radius)+parseInt(props.y)),
                                        radius: props.radius || 0,
                                        index: index
                                };
                               
                                shadow.set(config) ? shadow.append() : textShadow.remove(el,index);    
                        },
                        remove:function(el,textShadowIndex){
                                if (textShadowIndex in el.textShadowController.stack)
                                {
                                        el.textShadowController.stack[textShadowIndex].destroy();
                                        el.textShadowController.stack[textShadowIndex]=null;
                                        delete el.textShadowController.stack[textShadowIndex];
                                        el.textShadowController.free[el.textShadowController.freeSize++]=textShadowIndex;
                                       
                                        return true;
                                }
                               
                                return false;
                        },
                        addMethods:{
                                0:function(c){
                                        for (var index=0,indexLength=c.length;index<indexLength;index++)
                                        {
                                                var parse=$.textShadowParse(c[index].currentStyle['text-shadow']);
                                                for (var j=0,jl=parse.length;j<jl;j++)
                                                        textShadow.add(c[index],parse[j]);
                                        }
                                },
                                1:function(c,options){
                                        for (var index=0,indexLength=c.length;index<indexLength;index++)
                                        {
                                                if ("length" in options)
                                                        for (var j=0,jl=options.length;j<jl;j++)
                                                                textShadow.add(c[index],$.extend({x:0,y:0,radius:0,color:null},options[j]));
                                                else
                                                        textShadow.add(c[index],$.extend({x:0,y:0,radius:0,color:null},options));
                                        }
                                },
                                2:function(c,options){
                                        for (var index=0,indexLength=c.length;index<indexLength;index++)
                                        {
                                                var parse=$.textShadowParse(c[index].currentStyle['text-shadow']),
                                                        j=Math.max(options.length || 0,parse.length);
                                       
                                                if (j>0)
                                                {
                                                        while(j--)
                                                                textShadow.add(c[index],(options[j] && parse[j])
                                                                                                                        ? $.extend(options[j],parse[j])
                                                                                                                        : (options[j])
                                                                                                                                ? options[j]
                                                                                                                                : parse[j]);
                                                }
                                                else
                                                        textShadow.add(c[index],$.extend(options,parse[0]));
                                        }
                                }
                        }
                });
                $.extend($.fn,{
                        stextShadow:function(options,auto){
                                var argsLength=arguments.length;
                       
                                if (argsLength in textShadow.addMethods)
                                        textShadow.addMethods[argsLength](this,options);
                        },
                        stextShadowRemove:function(textShadowIndex){
                                for (var index=0,indexLength=this.length;index<indexLength;index++)
                                {
                                        var el=this[index];
                                        if ('textShadowController' in el)
                                        {
                                                if (arguments.length>0)
                                                        textShadow.remove(el,textShadowIndex);
                                                else
                                                        for (var index=0,indexLength=el.textShadowController.stack.length;index<indexLength;index++)
                                                                textShadow.remove(el,index);
                                        }
                                }
                        }
                });
        })(jQuery)
        : (function($){
                $.extend($.fn,{
                        stextShadow:function(){return true},
                        stextShadowRemove:function(){return true}
                });
        })(jQuery);
    //---------------------------------------------------------
   
    $.browser.msie
    ? (function($) {
        var posShadowMethods={
                        0:function(rx){return {x:0,y:0};},
                        1:function(rx){return {x:rx[0],y:rx[0]};},
                        2:function(rx){return {x:rx[0],y:rx[1]};},
                        3:function(rx){return {x:rx[0],y:rx[1],radius:rx[2]};}
                },
                setStyle=$.browser.version<7
                                ? function (el) {
                                        el.style.zIndex=0;
                                        el.style.position="relative";
                                }
                                : function (el) {
                                        el.style.zoom=1;
                                        el.style.zIndex=0;
                                        el.style.position="relative";
                                }
                fTextShadowParse=function(value)
                {
                        if (!value) return {x:0,y:0,radius:0,color:null};
   
                        var position=value.match(/(\d+)(?=[a-z%]+)/gi),
                                color=value.match(/#[0-9a-f]+|(?:rgb|hsb)a?\([^\)]*\)|\b[a-z]+\b/i),
                                shadow={x:0,y:0,radius:0,color:null},
                                posLength=position ? position.length : 0,
                                colorLength=color ? color.length : 0;
                               
                        if (posLength>0 || colorLength>0)
                        {
                                $.extend(shadow,posShadowMethods[posLength](position));
                                if ((!shadow.x && !shadow.y && !shadow.radius) || shadow.color == 'transparent')
                                        $.extend(shadow,{x:0,y:0,radius:0,color:null});
                        }
                       
                        return shadow;
                };
               
        $.fn.fTextShadow = function(option) {          
                for (var index=0,indexLength=this.length;index<indexLength;index++)
                {
                        var jel=$(this[index]),
                                el=this[index],
                                shadow=fTextShadowParse(el.currentStyle['text-shadow']);
                               
                        shadow = $.extend(shadow,option);
                        jel.fTextShadowRemove();
                       
                        if (shadow.x==0 && shadow.y==0 && shadow.radius==0)
                                return;
                       
                        setStyle(el);
                               
                        var span=document.createElement("span");               
                        span.className="jQueryTextShadow";
                        span.appendChild(document.createTextNode(el.textContent || el.innerText));
   
                        $.extend(span.style,{
                                padding:el.currentStyle['padding'],
                                width:(jel.width()+1)+'px',
                                position:'absolute',
                                zIndex:'-1',
                                color:shadow.color!=null ? shadow.color : el.style.color,
                                left:(-parseInt(shadow.radius)+parseInt(shadow.x))+'px',
                                top:(-parseInt(shadow.radius)+parseInt(shadow.y))+'px'
                        });    
                       
                        if (shadow.radius!=0)
                                span.style.filter=shadow.opacity!=null
                                                                        ? "progid:DXImageTransform.Microsoft.Blur(pixelradius="+parseInt(shadow.radius)+", enabled='true', makeShadow='true', ShadowOpacity="+shadow.opacity+")"
                                                                        : "progid:DXImageTransform.Microsoft.Blur(pixelradius="+parseInt(shadow.radius)+", enabled='true')";
                       
                        jel.append(span);
                }
               
                return true;
        };
        $.fn.fTextShadowRemove = function() {
                if (!$.browser.msie) return;
                return this.children("span.jQueryTextShadow").remove();
        };
    })(jQuery)
    : (function($) {
        $.fn.fTextShadow = $.fn.fTextShadowRemove = function() {return true;};
    })(jQuery);
   
    /**** Textshadow START -->> *****/
    (function($) {
        $.fn.textShadow = function(option) {
                if (!$.browser.msie) return;
                var IE6 = $.browser.version < 7;
                return this.each(function() {
                        var el = $(this);
                        var shadow = el.textShadowParse(this.currentStyle["text-shadow"]);
                        shadow = $.extend(shadow, option);
                        el.textShadowRemove();
                        if (shadow.x == 0 && shadow.y == 0 && shadow.radius == 0) return;
                        if (el.css("position")=="static") {
                                el.css({position:"relative"});
                        }
                        el.css({zIndex:"0"});
                        if (IE6) {
                                el.css({zoom:"1"});
                        }
                        var span=document.createElement("span");
                        $(span).addClass("jQueryTextShadow");
                        $(span).html(el.html());
                        $(span).css({
                                padding:                this.currentStyle["padding"],  
                                width:          el.width()+1,
                                position:       "absolute",
                                zIndex:         "-1",
                                color:          shadow.color!=null?shadow.color:el.css("color"),
                                left:                   (-parseInt(shadow.radius)+parseInt(shadow.x))+"px",
                                top:                    (-parseInt(shadow.radius)+parseInt(shadow.y))+"px"
                        });
                        if (shadow.radius != 0) {
                                if (shadow.opacity != null) {
                                        $(span).css("filter", "progid:DXImageTransform.Microsoft.Blur(pixelradius="+parseInt(shadow.radius)+", enabled='true', makeShadow='true', ShadowOpacity="+shadow.opacity+")");
                                } else {
                                        $(span).css("filter", "progid:DXImageTransform.Microsoft.Blur(pixelradius="+parseInt(shadow.radius)+", enabled='true')");
                                }
                        }      
                        el.append(span);
               
          });
        };
        $.fn.textShadowParse = function(value)
        {
                value = String(value)
                        .replace(/^\s+|\s+$/gi, '')
                        .replace(/\s*!\s*important/i, '')
                        .replace(/\(\s*([^,\)]+)\s*,\s*([^,\)]+)\s*,\s*([^,\)]+)\s*,\s*([^\)]+)\s*\)/g, '($1/$2/$3/$4)')
                        .replace(/\(\s*([^,\)]+)\s*,\s*([^,\)]+)\s*,\s*([^\)]+)\s*\)/g, '($1/$2/$3)')
                var shadow = {
                        x      : 0,
                        y      : 0,
                        radius : 0,
                        color  : null
                };
                if (value.length > 1 || value[0].toLowerCase() != 'none') {
                        value = value.replace(/\//g, ',');
                        var color;
                        if ( value.match(/(\#[0-9a-f]{6}|\#[0-9a-f]{3}|(rgb|hsb)a?\([^\)]*\)|\b[a-z]+\b)/i) && (color = RegExp.$1) ) {
                                shadow.color = color.replace(/^\s+/, '');
                                value = value.replace(shadow.color, '');
                        }
                        value = value
                                .replace(/^\s+|\s+$/g, '')
                                .split(/\s+/)
                                .map(function(item) {
                                                return (item || '').replace(/^0[a-z]*$/, '') ? item : 0 ;
                                        });
                        switch (value.length)
                        {
                                case 1:
                                        shadow.x = shadow.y = value[0];
                                        break;
                                case 2:
                                        shadow.x = value[0];
                                        shadow.y = value[1];
                                        break;
                                case 3:
                                        shadow.x = value[0];
                                        shadow.y = value[1];
                                        shadow.radius = value[2];
                                        break;
                        }
                        if ((!shadow.x && !shadow.y && !shadow.radius) || shadow.color == 'transparent') {
                                shadow.x = shadow.y = shadow.radius = 0;
                                shadow.color = null;
                        }
                }
                return shadow;
        };
        $.fn.textShadowRemove = function() {
                if (!$.browser.msie) return;
                return this.each(function() {
                        $(this).children("span.jQueryTextShadow").remove();
                });
        };
    })(jQuery);
   
    if(typeof Array.prototype.map == 'undefined') {
        Array.prototype.map = function(fnc) {
                var a = new Array(this.length);
                for (var i = 0; i < this.length; i++) {
                        a[i] = fnc(this[i]);
                }
                return a;
        }
    }
    /**** Textshadow ENDE -->> *****/
    testElement=$('.testing');
};
</script>

Preparation code output

testing string

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
jquery.text.shadow
testElement.stextShadow();
testElement.stextShadowRemove();
 
pending…
normal textshadow
testElement.textShadow();
pending…
optimized textshadow
testElement.fTextShadow();
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment