How could I detect !important rule of style property for directed DOM element?
ex:
<div class = "class">
***content***
</div>
.class{
top: 45px!important;
}
let elmStyles = document.getElementsByClassName('class')[0].style;
/* i need this =====> */ let isImportant = elmStyles.getPropertyPriority("top");
I`ve found some info about that, but I can not apply it for concrete DOMelement
https://developer.mozilla.org/ru/docs/Web/API/CSSStyleDeclaration/getPropertyPriority
You can find all the elements to which top and that particular class which .class is applied to
Means you need to loop through all the rules and find the corresponding class for it
var declaration = document.styleSheets;
for(var i=0;i<declaration.length;i++) {
for(var j=0;j<declaration[i].cssRules.length;j++) {
var rule = declaration[i].cssRules[j];
if(rule.style.getPropertyPriority("top")=="important") {
var selector = rule.selectorText;
if(selector[0]==".") {
var elements = document.getElementsByClassName(selector.substring(1));
for(var k=0;k<elements.length;k++) {
var element = elements[k];
console.log(element)
}
}
}
}
}
this loop will loop through all rules and find top is marked as !important
Then select all elements to which the class is applied and print in the console
Currently I have written only for class, for ID and tag name this is code will not work
Related
I want to make a script such that it adds an attribute style to an element with the given styles if it doesn't exist or just simply add the given styles to the pre-existing style attribute. Here is a piece of the code I wrote :
var style = function(sel, styl) {
var rVselect = document.querySelector(sel);
rVselect.getAttributeNode("style").value += styl;
};
This works perfect but has a problem. This only works when there is a style attribute ( doesn't matter empty or have some content ) given to the element. I want it make a style attribute in absense of it and then insert the styles and in work as it is working now in presense of the style attribute i.e. just simply add the new styles to the pre-existing style attribute.
Thanks in advance !
Its very simple. Here is a piece of code :
var style = function(sel, styl) {
var rVselect = document.querySelector(sel);
rVselect.style += styl;
};
If you want to add this to all matching elements go for this :
var style = function(sel, styl) {
var rVselect = document.querySelectorAll(sel);
for( var i = 0; i < rVselect.length; ++i ) {
rVselect[i].style += styl;
};
};
function(sel, styl) {
var rVselect = document.querySelector(sel);
rVselect.style = rVselect.style + styl;
};
It takes existed styles and add styles passed to argument
I am trying to create a chrome extension, which can be used to inspect elements on any webpage. It should have two functionalities -
On clicking, it should return the html markup and css styles of
that particular element.
On hover, it should highlight the particular element (just like
inspector in chrome dev tools)
I have achieved first part, but i am not able to achieve the second part.
I am new to JS and trying to achieve the hover task using plain JS, without any jQuery.
This is my content script file
console.log("Chrome extension loaded");
var all = document.body.getElementsByTagName('*');
var divs = document.body.getElementsByTagName('*');
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.h:hover { background-color: #83aff7; }';
document.getElementsByTagName('head')[0].appendChild(style);
// for click events and functionality
for (var i = 0, max = all.length; i < max; i++)
{
all[i].addEventListener("click",function() {
console.log(this);
console.log(window.getComputedStyle(this));
});
}
// for hover event
for (var i = 0, ma=divs.length; i <ma; i++)
{
(divs[i]).addEventListener('mouseover', function(){
this.classList.add('h');
});
if(this.parentNode && this.parentNode.hasAttribute("class"))
{
divs[i].addEventListener('mouseover', function(){
this.parentNode.classList.removeClass('h');
});
}
The clicking events part is working fine but in hover event, the color of parent as well as the element changes. Only the color of particular hovered element should change.
Thanks in advance!
You can use "addEventListener" to achieve "mouseover" to the element
You need to edit your css style
style.innerHTML = '.h:hover { background-color: #83aff7; }';
This says if an element with class h is being hovered, set background color. You are adding the "h" class to the parent with
$(this).parent().addClass('h');
CSS RULE 1 (if parent is of class h AND parent is hovered, color background):
style.innerHTML = '.h:hover *{ background-color: #83aff7; }';
CSS RULE 2 (if parent is of class h AND element is hovered):
style.innerHTML = '.h *:hover{ background-color: #83aff7; }';
Make sure to pick the rule that is appropriate for you.
Working JS Fiddle with both examples (your original CSS is the third box): https://jsfiddle.net/nsevpqd9/
If you do not want to edit your CSS style at all then add the class to the element itself, not the parent:
$(this).addClass('h');
I was looking here: CSS Selector for selecting an element that comes BEFORE another element?
...but wasn't able to find a correct answer for my issue.
Here is a fiddle example: https://jsfiddle.net/Munja/bm576q6j/3/
.test:hover, .test:hover + .test
With this, when I :hover element with .test class, I achieved to change style for current element with .test class and first next element with .test class.
What am I trying to achieve?
When I select any row/column (e.g agent 2), I want to apply same style for ALL elements with that same class (.test in this case).
If it is not possible to achieve this with css only, * I am willing to accept and other good solution.*
Thank you.
In your specific case you can use
tbody:hover > .test {
background: green;
}
fiddle: https://jsfiddle.net/bm576q6j/4/
Note that if you add more classes in the same tbody it will not give what you want. Check also this question: Hover on element and highlight all elements with the same class
So, after waiting for several more hours, I have decided to use JavaScript solution mentioned in answer from #BasvanStein. Posting it here as answer, to make things easier for someone else with same issue.
Here is a working fiddle: https://jsfiddle.net/Munja/bm576q6j/15/
var elms = document.getElementsByClassName("test");
var n = elms.length;
function changeColor(color) {
for(var i = 0; i < n; i ++) {
elms[i].style.backgroundColor = color;
}
}
for(var i = 0; i < n; i ++) {
elms[i].onmouseover = function() {
changeColor("red");
};
elms[i].onmouseout = function() {
changeColor("white");
};
}
Is it somehow possible to get a style property from a css class that is not used anywhere?
I'd like to read for example the color property that I want to apply to an animation with jquery ui but I want to avoid duplicating them again in the js code.
Let's say I have this:
.default-style {
color: red;
}
.disabled-style {
color: gray;
}
.current-style {}
<span class="current-style">Hello world!</span>
Now I would like to set the .default-style color to the .current-style and then animate the color from the .default-style to the .disabled-style and back on click but I don't know how to get them without creating a hidden element.
var currentColor = ""; // I'm stuck here. Get color from css class?
$("span.abc").animate({ color: currentColor });
You can cheat by creating an element, applying the class, adding the element to the document, getting its color, then removing it. If this is all done in one code block, the user will never see the element:
var div = $("<div>").addClass("default-style").appendTo(document.body);
var color = div.css("color");
div.remove();
Alternately, you can loop through document.styleSheets in the document, and loop through the rules of each stylesheet looking for the one that uses that simple class selector, then look at the styles that rule defines.
Gratuitous snippet: ;-)
var div = $("<div>").addClass("default-style").appendTo(document.body);
var color = div.css("color");
div.remove();
$("<p>The color is: " + color + " (the color of this paragraph)</p>").css("color", color).appendTo(document.body);
.default-style {
color: red;
}
.disabled-style {
color: gray;
}
.current-style {}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="current-style">Hello world!</span>
Side note: jQuery's animate function doesn't animate colors natively, you need to add a plugin to do it (jQuery UI bundles one, but if you're not using jQuery UI, you can just use one of the plugins that does this, such as this one, directly).
Correct Way ! Without cheating the document
var currentColor;
var styleSheets = document.styleSheets;
for(var j=0; !currentColor && j<styleSheets.length; j++)
{
var styleSheet = styleSheets[j];
var cssprops = styleSheet.cssRules || styleSheet.rules; // .rules is for older IE
for (var i = 0; i < cssprops.length; i++) {
if(cssprops[i].selectorText == '.default-style');
currentColor = cssprops[i].style.getPropertyCSSValue('color').cssText;
}
}
$("span.abc").animate({ color: currentColor });
Reference From https://developer.mozilla.org/en-US/docs/Web/API/document.styleSheets
I have a series of p tags on my page and I want to wrap them all into a container, e.g.
<p>foo</p>
<p>bar</p>
<p>baz</p>
I want to wrap all the above tags into a container as follows:
<div>
<p>foo</p>
<p>bar</p>
<p>baz</p>
</div>
How to wrap a NodeList in an element using vanilla JavaScript?
Posted below are a pure JavaScript version of jQuery's wrap and wrapAll methods. I can't guarantee they work exactly as they do in jQuery, but they do in fact work very similarly and should be able to accomplish the same tasks. They work with either a single HTMLElement or an array of them. I haven't tested to confirm, but they should both work in all modern browsers (and older ones to a certain extent).
Unlike the selected answer, these methods maintain the correct HTML structure by using insertBefore as well as appendChild.
wrap:
// Wrap an HTMLElement around each element in an HTMLElement array.
HTMLElement.prototype.wrap = function(elms) {
// Convert `elms` to an array, if necessary.
if (!elms.length) elms = [elms];
// Loops backwards to prevent having to clone the wrapper on the
// first element (see `child` below).
for (var i = elms.length - 1; i >= 0; i--) {
var child = (i > 0) ? this.cloneNode(true) : this;
var el = elms[i];
// Cache the current parent and sibling.
var parent = el.parentNode;
var sibling = el.nextSibling;
// Wrap the element (is automatically removed from its current
// parent).
child.appendChild(el);
// If the element had a sibling, insert the wrapper before
// the sibling to maintain the HTML structure; otherwise, just
// append it to the parent.
if (sibling) {
parent.insertBefore(child, sibling);
} else {
parent.appendChild(child);
}
}
};
See a working demo on jsFiddle.
wrapAll:
// Wrap an HTMLElement around another HTMLElement or an array of them.
HTMLElement.prototype.wrapAll = function(elms) {
var el = elms.length ? elms[0] : elms;
// Cache the current parent and sibling of the first element.
var parent = el.parentNode;
var sibling = el.nextSibling;
// Wrap the first element (is automatically removed from its
// current parent).
this.appendChild(el);
// Wrap all other elements (if applicable). Each element is
// automatically removed from its current parent and from the elms
// array.
while (elms.length) {
this.appendChild(elms[0]);
}
// If the first element had a sibling, insert the wrapper before the
// sibling to maintain the HTML structure; otherwise, just append it
// to the parent.
if (sibling) {
parent.insertBefore(this, sibling);
} else {
parent.appendChild(this);
}
};
See a working demo on jsFiddle.
You can do like this:
// create the container div
var dv = document.createElement('div');
// get all divs
var divs = document.getElementsByTagName('div');
// get the body element
var body = document.getElementsByTagName('body')[0];
// apply class to container div
dv.setAttribute('class', 'container');
// find out all those divs having class C
for(var i = 0; i < divs.length; i++)
{
if (divs[i].getAttribute('class') === 'C')
{
// put the divs having class C inside container div
dv.appendChild(divs[i]);
}
}
// finally append the container div to body
body.appendChild(dv);
I arrived at this wrapAll function by starting with Kevin's answer and fixing the problems presented below as well as those mentioned in the comments below his answer.
His function attempts to append the wrapper to the next sibling of the first node in the passed nodeList. That will be problematic if that node is also in the nodeList. To see this in action, remove all the text and other elements from between the first and second <li> in his wrapAll demo.
Contrary to the claim, his function won't work if multiple nodes are passed in an array rather than a nodeList because of the looping technique used.
These are fixed below:
// Wrap wrapper around nodes
// Just pass a collection of nodes, and a wrapper element
function wrapAll(nodes, wrapper) {
// Cache the current parent and previous sibling of the first node.
var parent = nodes[0].parentNode;
var previousSibling = nodes[0].previousSibling;
// Place each node in wrapper.
// - If nodes is an array, we must increment the index we grab from
// after each loop.
// - If nodes is a NodeList, each node is automatically removed from
// the NodeList when it is removed from its parent with appendChild.
for (var i = 0; nodes.length - i; wrapper.firstChild === nodes[0] && i++) {
wrapper.appendChild(nodes[i]);
}
// Place the wrapper just after the cached previousSibling,
// or if that is null, just before the first child.
var nextSibling = previousSibling ? previousSibling.nextSibling : parent.firstChild;
parent.insertBefore(wrapper, nextSibling);
return wrapper;
}
See the Demo and GitHub Gist.
Here's my javascript version of wrap(). Shorter but you have to create the element before calling the function.
HTMLElement.prototype.wrap = function(wrapper){
this.parentNode.insertBefore(wrapper, this);
wrapper.appendChild(this);
}
function wrapDiv(){
var wrapper = document.createElement('div'); // create the wrapper
wrapper.style.background = "#0cf"; // add style if you want
var element = document.getElementById('elementID'); // get element to wrap
element.wrap(wrapper);
}
div {
border: 2px solid #f00;
margin-bottom: 10px;
}
<ul id="elementID">
<li>Chair</li>
<li>Sofa</li>
</ul>
<button onclick="wrapDiv()">Wrap the list</button>
If you're target browsers support it, the document.querySelectorAll uses CSS selectors:
var targets = document.querySelectorAll('.c'),
head = document.querySelectorAll('body')[0],
cont = document.createElement('div');
cont.className = "container";
for (var x=0, y=targets.length; x<y; x++){
con.appendChild(targets[x]);
}
head.appendChild(cont);
Taking #Rixius 's answer a step further, you could turn it into a forEach loop with an arrow function
let parent = document.querySelector('div');
let children = parent.querySelectorAll('*');
let wrapper = document.createElement('section');
wrapper.className = "wrapper";
children.forEach((child) => {
wrapper.appendChild(child);
});
parent.appendChild(wrapper);
* { margin: 0; padding: 0; box-sizing: border-box; font-family: roboto; }
body { padding: 5vw; }
span,i,b { display: block; }
div { border: 1px solid lime; margin: 1rem; }
section { border: 1px solid red; margin: 1rem; }
<div>
<span>span</span>
<i>italic</i>
<b>bold</b>
</div>