admin管理员组文章数量:1296919
I need to find all block elements in a given node. Block elements are not just elements that have display:block
in the CSS, but also default block elements like div
and p
.
I know I can just get puted style of the element and check for the display
property, however, my code will execute in a long loop and getting puted styles flushes reflow stack every time, so it will be very expansive.
I'm looking for some trick to do this without getComputedStyle
.
Edit
Here's my current code that I would like to improve:
var isBlockOrLineBreak = function(node)
{
if (!node) {
return false;
}
var nodeType = node.nodeType;
return nodeType == 1 && (!inlineDisplayRegex.test(getComputedStyleProperty(node, "display")) || node.tagName === "BR")
|| nodeType == 9 || nodeType == 11;
};
Another edit
jQuery's .css calls getComputedStyle under the hood. So that's not what I'm looking for.
My solution
Thanks everyone for suggestions. Unfortunately, none of them matched what I was looking for. After a lot of digging through documentation I realized that there's no real way to do this without getComputedStyle. However, I came up with the code that should avoid getComputedStyle as much as humanly possible. Here's the code:
$.extend($.expr[':'], {
block: function(a) {
var tagNames = {
"ADDRESS": true,"BLOCKQUOTE": true,"CENTER": true,"DIR": true,"DIV": true,
"DL": true,"FIELDSET": true,"FORM": true,"H1": true,"H2": true,"H3": true,
"H4": true,"H5": true,"H6": true,"HR": true,"ISINDEX": true,"MENU": true,
"NOFRAMES": true,"NOSCRIPT": true,"OL": true,"P": true,"PRE": true,"TABLE": true,
"UL": true,"DD": true,"DT": true,"FRAMESET": true,"LI": true,"TBODY": true,
"TD": true,"TFOOT": true,"TH": true,"THEAD": true,"TR": true
};
return $(a).is(function() {
if (tagNames[this.tagName.toUpperCase()]) {
if (this.style.display === "block")
{
return true;
}
if (this.style.display !== "" || this.style.float !== "")
{
return false;
}
else {
return $(this).css("display") === "block";
}
}
else {
if (this.style.display === "block") {
return
}
else {
return $(this).css("display") === "block";
}
}
});
}
});
Usage of this code is very simple just do $(":block") or $("form :block"). This will avoid using .css property in a lot of cases, and only fallback to it as a last resort.
Starx's answer was what gave me the idea to do this, so I'm going to mark his message as an answer.
I need to find all block elements in a given node. Block elements are not just elements that have display:block
in the CSS, but also default block elements like div
and p
.
I know I can just get puted style of the element and check for the display
property, however, my code will execute in a long loop and getting puted styles flushes reflow stack every time, so it will be very expansive.
I'm looking for some trick to do this without getComputedStyle
.
Edit
Here's my current code that I would like to improve:
var isBlockOrLineBreak = function(node)
{
if (!node) {
return false;
}
var nodeType = node.nodeType;
return nodeType == 1 && (!inlineDisplayRegex.test(getComputedStyleProperty(node, "display")) || node.tagName === "BR")
|| nodeType == 9 || nodeType == 11;
};
Another edit
jQuery's .css calls getComputedStyle under the hood. So that's not what I'm looking for.
My solution
Thanks everyone for suggestions. Unfortunately, none of them matched what I was looking for. After a lot of digging through documentation I realized that there's no real way to do this without getComputedStyle. However, I came up with the code that should avoid getComputedStyle as much as humanly possible. Here's the code:
$.extend($.expr[':'], {
block: function(a) {
var tagNames = {
"ADDRESS": true,"BLOCKQUOTE": true,"CENTER": true,"DIR": true,"DIV": true,
"DL": true,"FIELDSET": true,"FORM": true,"H1": true,"H2": true,"H3": true,
"H4": true,"H5": true,"H6": true,"HR": true,"ISINDEX": true,"MENU": true,
"NOFRAMES": true,"NOSCRIPT": true,"OL": true,"P": true,"PRE": true,"TABLE": true,
"UL": true,"DD": true,"DT": true,"FRAMESET": true,"LI": true,"TBODY": true,
"TD": true,"TFOOT": true,"TH": true,"THEAD": true,"TR": true
};
return $(a).is(function() {
if (tagNames[this.tagName.toUpperCase()]) {
if (this.style.display === "block")
{
return true;
}
if (this.style.display !== "" || this.style.float !== "")
{
return false;
}
else {
return $(this).css("display") === "block";
}
}
else {
if (this.style.display === "block") {
return
}
else {
return $(this).css("display") === "block";
}
}
});
}
});
Usage of this code is very simple just do $(":block") or $("form :block"). This will avoid using .css property in a lot of cases, and only fallback to it as a last resort.
Starx's answer was what gave me the idea to do this, so I'm going to mark his message as an answer.
Share edited Mar 17, 2012 at 1:10 Ilya Volodin asked Mar 16, 2012 at 3:31 Ilya VolodinIlya Volodin 11.3k2 gold badges49 silver badges49 bronze badges 4- I'm not tying to avoid the looping, just trying to avoid calling getComputedStyle in a loop. – Ilya Volodin Commented Mar 16, 2012 at 3:38
- how would you know if you don't get the puted style? and it would be better if you included your code also. – Joseph Commented Mar 16, 2012 at 3:48
- Well, that's sort of why I'm asking the question. I'm not sure how to do this without getComputedStyle, but maybe somebody can e up with a smart trick that I didn't think about. – Ilya Volodin Commented Mar 16, 2012 at 3:58
- 1 See the 2nd response in this post: stackoverflow./questions/4220478/… - uses regex matching on the tag name itself. – TheOx Commented Mar 16, 2012 at 4:05
3 Answers
Reset to default 4For the answer to this problem, we take into account the universal CSS selector and the jQuery .filter()
function:
$("*").filter(function(index) {
return $(this).css("display") == 'block';
});
This code looks at all elements it can find, and it returns a list of elements if they pass a filter. The element passes a filter if the filter function returns true
for that element. In this case, the filter tests the display
property of each found element and tests it against the desired value.
Now, you also mentioned that you want to find p
and div
elements. Luckily, we also have a way to find these in the filter function. Using jQuery's prop
function, we can return a property of an element. In this case, we are interested in the tagName
property of the DOM elements being filtered. Combining this feature with the above filter, we get:
$("*").filter(function(index) {
var $this = $(this);
var tagName = $this.prop("tagName").toLowerCase();
return $this.css("display") == 'block' || tagName == 'p' || tagName == 'div';
});
Notice how we set the tagName
variable to lowercase, because we cannot expect a certain case for the tagName
property (correct me if I'm wrong).
The best way I see is to
- assign a mon class to all the
not-native
block element and - using jQuery's
mulitple-selector
.
Then we can do it as simple as this this
CSS:
.block { display: block; }
jQuery:
var blockelements = $("div, p, table, ..., .block");
// ^ represents other block tags
If you want to include all the block elements. Here is a link
maybe this helps.
$('*').each( function(){
if ($(this).css("display") === "block")
$(this).css("background", "yellow") ;
});
jsfiddle
本文标签: javascriptFind all block elementsStack Overflow
版权声明:本文标题:javascript - Find all block elements - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741646244a2390199.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论