开发者

Need help turning a for loop/if statement into a jQuery selector

I've got the following code:

var $elements = $("body").find("*");

for (var i = 0, len = $elements.length; i < len; i++) {
    var $e = $elements.eq(i), 
        cssFloat = $e.css("float"), 
        cssDisplay = $e.css("di开发者_开发技巧splay");

    if (cssDisplay !== "none" && 
       (cssFloat === "left" || cssFloat === "right")) { 

        $e.css("display", "inline"); 

    }

};

For performance reasons, I would like to replace the for loop and if statement with a jQuery selector that filters down all the elements to only the ones that need to apply the display: inline;.

I was thinking something along the lines of the following pseudo code:

$("body")

.find("*")
.not(selector for elements whose css display style is not "none")
.contains(selector for elements whose css float style is "left" or "right")    
.css("display", "inline");

For whatever reason, my brain is failing me. Is this possible?


You could use the $.filter() method to get what you want:

$(":visible").filter(function(index){
    return ( $.inArray( $(this).css('float'), ['left','right'] ) > -1 ); 
  }).css({display:'inline'});

This would result in the floated elements being turned into inline elements.

Demo: http://jsbin.com/utape3/edit

While the jQuery documentation states there will be performance issues using :visible, it is more efficient than using * or body *.

Performance Comparison: http://jsperf.com/splat-vs-pseudo

I'm not sure of a faster method of doing this with JavaScript. You'll notice in the performance test that I used everything including a custom selector:

$.expr[':'].floated = function(obj) {
    return ($.inArray($(obj).css('float'), ['left', 'right']) > -1);
};

$(":floated").css({display:'inline'});

I was really only partly interested in the results of that method, not being entirely familiar with how the internals handle this type of selector.

Raw JavaScript - Much Faster

I've added to the performance testing the following:

var els = document.getElementsByTagName('*');
for (var i = 0; i < els.length; i++) {
  cssTxt = els[i].style.cssText;
  if ((cssTxt.indexOf('float: left') > -1) || (cssTxt.indexOf('float: right') > -1)) {
    els[i].style.display = 'inline';
  }
}

This test assumes:

<p style="float:left">Foo</p>
<p style="float:right">Bar</p>

This was thrown together, but ridiculously fast compared to the previous jQuery methods.


This seems like a really bad idea. But here's the jQuery to do roughly what you asked. It's not going to help much because it's still going to have to look at pretty much everything on the page:

$(":visible").filter(function(){
    var cssFloat = $(this).css("float");

    return cssFloat === "left" || cssFloat === "right";
}).css("display", "inline");
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜