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 computed style of the element and check for the display
property, however, my code will execute in a long loop and getting computed 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.
A Block-level element occupies the entire horizontal space of its parent element (container), and vertical space equal to the height of its contents, thereby creating a "block". Browsers typically display the block-level element with a newline both before and after the element.
As you can see in the example above, even though I typed "Hello" inside of the li tag and immediately followed it with "World", the single li tag will not allow the "World" to be on the same line. This demonstrates that the li tag is taking 100% of the available width, proving that li is a block level element.
Block Elements For example, the <p>, <h1>, <h2>, <h3>, <h4>, <h5>, <h6>, <ul>, <ol>, <dl>, <pre>, <hr />, <blockquote>, and <address> elements are all block level elements. They all start on their own new line, and anything that follows them appears on its own new line.
The BR element is defined to be element of special and that is defined to be inline. It's also not being displayed in its own like like a block element, but just creating a line break. Thus BR is an inline element.
For 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
not-native
block element andmulitple-selector
.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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With