In jQuery, we can easily get the CSS value for a given element with the css method:
$('#myElement').css('line-height'); // e.g. '16px'
Now, since this CSS value might have been inherited from a parent element, is there any way to know which element has this rule applied to it?
For example, let's say I have the following HTML:
<div class="parent">
<div id="myElement"></div>
</div>
and the following CSS:
.parent {
line-height: 20px;
}
Calling the css method on #myElement will return 20px, but it will not indicate that it was inherited from .parent.
I know I can just fire up Web Inspector/Dev Tools/Firebug, but I want to get it programmatically.
Is this at all possible?
Walk up the parentElement chain checking the css() value of each element. The first element with a parent().css() value that's different is (probably) the element being targeted by the CSS rule selector.
See this fiddle for an example: http://jsfiddle.net/broofa/VPWV9/2/ (See the console.log output)
(Note: there are almost surely complex cases where this won't work as expected but for the case as described, it works.)
I have a similar solution to broofa's. It also has the same problem though.
Here's the fiddle:
http://jsfiddle.net/2w3kt/
$.fn.getStyleParent = function(property)
{
var $source = this.get(0), // only do for 1st element :P
srcVal = $source.css(property),
$element = null;
$(this).parents().each(function()
{
var $this = $(this);
if( $this.css(property) == srcVal )
element = $this;
else
return false; // stops the loop
});
return $element;
}
Related
I created a function in Jquery which is supposed to center elements vertically (I could not do it using css, got tired and just made it programically ^^). The problem now is that I initially created it using .each, and then, since it was already creator, I tried calling it using the selector ($('something').center), but it is behaving differently for some reason.
Using the selector, it seems to be doing just the same to every element. It does it with the first element, and then just applies all values to the remaining elements. So, for example, my function takes the element height and does some operations with it, but the selector just takes the first one and then applies its parameters to everyone..
I'll keep using each since it works best right now, but I still can't understand why they are doing that..
Centering Function:
$.fn.center = function (){
/*If this is the highest element, or
if this element has full use of the width,
then there's no need to align it.
*/
if(this.height() == this.parent().height() ||
this.width() == this.parent().width())
{
this.css({
position : "relative",
top : 0
});
}
else //Should be aligned.
{
this.css({
position : "relative",
top : (this.parent().height()/2)-(this.height()/2)
});
}
return this; //Used for chaining.
};
Here's an example of what I mean ^^
http://jsfiddle.net/lrojas94/pmbttrt2/1/
For simple things, like just changing the CSS in the same way for all elements with the same class, you can call it directly without using .each(). For example:
$('.elem').css('color', '#fff');
But if each of the divs needs to end up with an individual value, you should use .each(). For example (sorry it's a bit weird):
var border = 1;
$('.elem').each(function() {
$(this).css('border', border + 'px solid #000');
border += 1;
});
Basically, if you don't use .each(), it'll check what you want to change (just once!) and apply it to all elements with that class. If you do use .each(), it'll do it individually for each element.
Simply put, this within a jQuery plugin function is not a DOM node. It's the jQuery object that wraps around all the nodes that were matched by the selector.
Your function's body should rather look like:
return this.each(function () {
var $el = $(this);
//centering logic for $el goes here
});
Is there a way do determine if a selector is currently been applied to an given element?
I know it´s possible to iterate over all CSS selectors, and test if each one is applicably or not. But I´m not sure if this is the way that Firebug and other inspector do it.
EDIT:
I need a way to do it dynamically, with JS.
You can check if an element instance is matched by a selector by using document.querySelectorAll and Array.prototype.indexOf:
function elementMatchesSelector(element, selector) {
return Array.prototype.indexOf.call(document.querySelectorAll(selector), element) > -1;
}
Of course this only works for modern browsers that support the aforementioned methods.
Alternatively you can use Element.matches:
function elementMatchesSelector(element, selector) {
var fn;
if (!element) {
return false;
}
fn = element.matches || element.mozMatchesSelector || element.msMatchesSelector || element.webkitMatchesSelector;
if (fn) {
return fn.call(element, selector);
}
return false;
}
In Firebug, you can look at the Computed Side Panel. For any given DOM element, it shows the CSS styles applied (even those applied via JavaScript). It also depicts the styles that were overridden. From the docs:
The Computed Side Panel shows all CSS style values calculated by the user agent while interpreting the given CSS information for the selected node inside the HTML Panel.
What about using getComputedStyle()
MDN Link
I feel like this could have been asked before, but I can't seem to find it, so I'll ask myself.
I want to select the parent element that is the "cause" of its children being hidden. For example, a group of elements are essentially "hidden" but not because they have display:none but because some parent along the way has display:none.
If I only have a child element and I know that it is hidden, how might I easily find the parent that is causing it to be hidden.
I realize one solution is just to recursively loop through the parents such as...
function findHiddenParent(el){
var $el = $(el);
if($el.css('display') == 'none'){
return $el;
}
return findHiddenParent($el.parent());
}
Note I haven't tested the above code, its just for conceptualizing a solution
But is there an easier way, perhaps through some selector magic?
You can use .parents() then filter that to the last element that is hidden.
$(child).parents(":hidden").last().show();
it will select the parent element highest in the hierarchy that has display: none
Demo: http://jsfiddle.net/X9W2v/
Note, :hidden will also select elements with a width/height of 0.
Here's something similar to what you've got:
function findHiddenParents ( el ) {
return $(el).parents().filter(function () {
return $(this).css('display') == 'none';
});
}
This'll return all ancestors that are hidden. If you only want the closest or the farthest, you can just return it with .first() or .last() respectively.
If you're not actually interested in which elements are hidden, but just want to reveal them all, then you can't get any simpler than this:
$(el).parents().show()
This is how I would do it in plain JavaScript. Somehow I feel it's cleaner than the jQuery solutions that involve loops or callbacks (Kevin B's one-liner looks great!). The cons are, it's longer, and it doesn't check computed styles:
<div id="container">
<div id="a" style="display: none;">A
<div id="b">B
<div id="c">C</div>
</div>
</div>
</div>
var currentNode = document.getElementById('c');
while(currentNode.parentNode && currentNode.style.display !== 'none') {
currentNode = currentNode.parentNode;
}
alert(currentNode.id);
http://jsfiddle.net/nc4h2/
I want to change the style of visible elements using CSS only. Is there a selector that does it? It needs to work with Chrome and Firefox only. (I am building an extension / addon)
If there isn't, is there a way to change the style of visible elements with a light javascript?
Visible within the current scroll position. An element can be out of the scroll vision, or partially visible.
There is no standard pure CSS rule for assessing visibility.
As others have said, jQuery (if you wanted to use jQuery) has both a CSS selector extension :visible and the ability to execute .is(':visible') on any given jQuery object to get the computed style on any given DOM element with .css("display") or .css("visibility").
It's not particularly simple in plain javascript to determine if an object is visible because you have to get the computedStyle (to take into account all possible CSS rules that might be affecting the element) and you have to make sure no parent objects are hidden causing the child element to be hidden. This is a function I have in my own personal library:
//----------------------------------------------------------------------------------------------------------------------------------
// JF.isVisible function
//
// Determines if the passed in object is visible (not visibility:hidden, not display: none
// and all parents are visible too.
//
// Source: http://snipplr.com/view/7215/javascript-dom-element-visibility-checker/
//----------------------------------------------------------------------------------------------------------------------------------
JF.isVisible = function(obj)
{
var style;
if (obj == document) return true;
if (!obj) return false;
if (!obj.parentNode) return false;
if (obj.style) {
if (obj.style.display == 'none') return false;
if (obj.style.visibility == 'hidden') return false;
}
//Try the computed style in a standard way
if (window.getComputedStyle) {
style = window.getComputedStyle(obj, "")
if (style.display == 'none') return false;
if (style.visibility == 'hidden') return false;
} else {
//Or get the computed style using IE's silly proprietary way
style = obj.currentStyle;
if (style) {
if (style['display'] == 'none') return false;
if (style['visibility'] == 'hidden') return false;
}
}
return JF.isVisible(obj.parentNode);
};
There is no pure CSS way of doing this. As Kirean's comment already said, why would you want to style visible elements only? Invisible elements won't show their styling anyway. If you don't want the invisible element to take up space (aka, laid out), you should use display: none;
If you REALLY want a selector to select the visible elements, you could do what Widor suggested and use jQuery. You could first use jQuery to first select the visible elements, add a class to them, then use CSS to select the elements by that class.
$('div:visible').addClass('visibleElement');
.visibleElement {
color: red;
}
There is no Way to select invisible elements, using pure CSS
http://www.w3.org/TR/selectors/
However, if you have a class name or other selector, using jquery you can do something like the following
jQuery(selector).each(function(){
Var $this=$(this);
if ($this.css('visibility')==='hidden')
//set your style
})
Edit: after your edit, there is definitely no way of selecting what is within the viewport with CSS alone. It is a context free language of sorts.
However, you can always fool around with an elements offset position with jquery and determine if it's within the current viewport(window.scrollposition or something similar). This type of solution gets messy quickly, though.
This looks like a :visible selector to me:
http://api.jquery.com/visible-selector/
EDIT: Saw your javascript tag before your 'no CSS' caveat.
But this is a CSS selector of sorts.
I need to use jQuery to locate all DIV tags that have no attributes on them and apply a class to each. Here's a sample HTML:
<div id="sidebar">
<div>Some text goes here</div>
<div class="something">something goes here</div>
<div>Another div with no attributes.</div>
</div>
So, I need to take that and turn it into this:
<div id="sidebar">
<div class="myClass">Some text goes here</div>
<div class="something">something goes here</div>
<div class="myClass">Another div with no attributes.</div>
</div>
How do you locate elements of type div that have no attributes via jQuery? Thanks.
Here you go:
$('div', '#sidebar').filter(function () {
return this.attributes.length === 0;
})
Live demo: http://jsfiddle.net/phbU9/
The attributes property returns a list of all attributes set on the element. "Naked" elements have an empty attributes list.
Update: Be sure to read Tim's answer below which provides a solution for older versions of IE, since my own solution doesn't work in IE8 and below.
#Šime's answer is close but doesn't work in IE 6, 7 or 8, where an element's attributes collection has an entry for every possible attribute, not just those specified in the HTML. You can get round this by checking each attribute object's specified property.
Live demo: http://jsfiddle.net/timdown/6MqmK/1/
Code:
$("div").filter(function() {
var attrs = this.attributes, attrCount = attrs.length;
if (attrCount == 0) {
return true;
} else {
for (var i = 0; i < attrCount; ++i) {
if (attrs[i].specified) {
return false;
}
}
return true;
}
});
check this out:
http://jsfiddle.net/thilakar/CHux9/
You need to give some sort of selector, in this case Ive used your side bar but it can be anything. Then get the children that have no class attribute and add a new class. See JSFiddle for the example:
http://jsfiddle.net/HenryGarle/q3x5W/
$("#sidebar").children('div:not([class])').addClass('newClass');
So this would return the 2 elements with no class tag and leave the sidebar and div with the class completely unaffected.
You could use a combination of jQuery's has attribute selector and the not selector. For example:
$('div:not([class], [id])').addClass('myClass');
jsFiddle demonstrating this
With this approach, you need to explicitly specify the attributes to check the presence of. Sime's solution would apply the class to divs that do not have any attributes at all.
To expound upon Tim Down's answer, I recommend checking that the attrs var not null special cases where the html has comment tags, etc.
try $('div:not([class])').addClass('myClass');
it is a general approach because the class will apply to all the div that have no class
$('#sidebar div')` or more general `$('div'); //returns collections of divs
to answer the question:
$('#sidebar div').addClass('myClass');