I would like to be able to get the style from a CSS element which is not used on the webpage. For example, this is the page:
<html>
<head>
<style type="text/css">
#custom{
background-color: #000;
}
</style>
</head>
<body>
<p>Hello world</p>
</body>
</html>
as you can see the ID 'custom' has a value but is not used within the document. I would like to get all the values for 'custom' without using it in the page. The closest I have come is:
el = document.getElementById('custom');
var result;
var styleProp = 'background-color';
if(el.currentStyle){
result = el.currentStyle[styleProp];
}else if (window.getComputedStyle){
result = document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
}else{
result = "unknown";
}
Create a new element with given ID and append it to the document. Then just read the value and remove the element.
Example:
var result,
el = document.body.appendChild(document.createElement("div")),
styleProp = 'background-color',
style;
el.id = 'custom';
style = el.currentStyle || window.getComputedStyle(el, null);
result = style[styleProp] || "unknown";
// Remove the element
document.body.removeChild(el);
I don't think the answer was a very good one as it requires adding elements to the DOM which may disrupt what you are trying to do or create visual glitches.
Using document.styleSheets I think you can get a less invasive solution. (see here)
try something like:
var result;
var SS = document.styleSheets;
for(var i=0; i<SS.length; i++) {
for(var j=0; j<SS[i].cssRules.length; j++) {
if(SS[i].cssRules[j].selectorText == "#custom") {
result = SS[i].cssRules[j].style;
}
}
}
This should give you an object which will contain all of the styles as the keys. keep in mind you may need a little more complex algorithm if the style is redeclared within the stylesheets.
Related
I want to create a JavaScript object for an element which describes all the computed styles that have an effect, either directly or from a parent. Ideally in the same fashion as inspect element does (the list you see under the elements tab of the inspect console in chrome or Firefox).
Like this.
the section of inspect element I need to try to recreate;
I want to get the styles that effect any particular element selected and then know the class name or ID name where they are being set, just like in the chrome inspect element.
So far I can get the classes and ID's of that element, then I can get the style rules for each of those. But, I need to also get the styles of the parents which are in effect through parental hierarchy. First I thought to traverse up the DOM getting all the parent styles along the way and then filtering out any which don't effect children. But I know this will be fairly complicated. Can anyone help add to what I have so far?
I still need to figure out how to get the #queries that apply to the element, and that also needs to be responsive. I.e. if the screen resizes and a new media query is selected by the CSS, it needs to re calculate to get the corresponding queries. Also I need to filter out a list of rules that are not applicable to children. Is there such a list anywhere?
I thought id try another way. I tried to get the computed styles like this..
var cssClassObj = [];
cssClassObj['classA'] = [];
cssClassObj['classA']['background'] = '#000';
cssClassObj['classB'] = [];
cssClassObj['classB']['color'] = '#fff';
cssClassObj['classC'] = [];
cssClassObj['classC']['color'] = 'red';
var cssIDObj = [];
cssIDObj['starthere'] = [];
cssIDObj['starthere']['text-decoration'] = 'underline';
var i = 0;
var StyleOBJ = [];
var el = document.getElementById('starthere');
//var style = getComputedStyle(link);
var overwrittenRules = [];
var thisParentTree = [];
var ThisStyleOBJ = getObj(StyleOBJ, el, overwrittenRules, thisParentTree);
console.log(ThisStyleOBJ);
function getObj(styleObj, el, overwrittenRules, parentTree, start = true) {
if (el != document) {
var classes = el.classList;
for (var className in classes) {
if (classes.hasOwnProperty(className)) {
var cssStyles = cssClassObj[classes[className]] || null;
for (var style in cssStyles) {
if (cssStyles.hasOwnProperty(style)) {
if (typeof overwrittenRules[style] !== "undefined") {
cssStyles[style] += " :Omitted!!";
} else {
overwrittenRules[style] = true
}
}
}
StyleOBJ['class-' + classes[className]] = cssClassObj[classes[className]] || null;
if (!start) {
parentTree[++i] = el;
StyleOBJ['class-' + classes[className]]['Parentree'] = parentTree.slice();
}
}
}
if (el.id) {
StyleOBJ['id-' + el.id] = cssIDObj[el.id] || null;
}
var parent = el.parentNode;
styleObj = getObj(styleObj, parent, overwrittenRules, parentTree, false);
}
return styleObj;
}
.classA {
background: #000;
}
.classB {
color: #fff;
}
.classC {
color: red;
}
<body>
<div class="classA">
<div class="classB">
<p id="starthere" class="classC">
Open up the console to see the object. It contains all the styles and anything which is overwritten has been marked as Omitted. Each element has a parent tree of nodes, if it is a parent.
<br/><br/>
Still to do is;
<br/>
Check if !important is used and update the omitted children.
<br/>
#queries which are currently effecting the element
<br/>
find a way to automatically turn the style sheet into an object instead of having to hardcode it
</p>
</div>
</div>
Please Note that for some reason SO doesn't show the resulting object in the snippet so you have to open up the console to see the output when you click run.
It's coming together now, but needs to be finished.
Thanks in advance.
by internal style I mean
<style>
#div
{color:red;}
</style>
document.getElementsByTagName('style').innerHTML is not working... document.styleSheets either.
document.getElementsByTagName returns Array of Elements
so you need to access it with index
document.getElementsByTagName('style')[0].innerHTML
document.styleSheets is much useful if you want to get specific selector or modify something from style sheet
Example
var styleSheet = document.styleSheets[1];
// assuming second one is embedded style,
// since document.styleSheets also shows linked style sheets (like <link heref=".. >)
for (var i = 0; i < styleSheet.rules.length; i++) {
// if you are looking for selector '.main'
if (styleSheet.rules[i].selectorText === '.main') {
// get background color
var oldBg = styleSheet.rules[i].style.backgroundColor;
// set background color
styleSheet.rules[i].style.backgroundColor = '#ddd';
}
}
document.styleSheets is an array , for each of the style definition in your page .
Iterate for each of the style elements and find the rules defined.
document.styleSheets[0].rules
This is again an array. so iterate . The rule text for each of the rules can be extracted as follows
document.styleSheets[indexofstyleelement].rules[indexofrule].cssText
document.styleSheets[0].rules[0].cssText gives rule text for first of the rules defined inside first style element
<!DOCTYPE html>
<html>
<head>
<style>
#div {
color: red;
}
</style>
</head>
<body>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
function myFunction() {
var x = document.getElementsByTagName("STYLE")[1];
document.getElementById("demo").innerHTML = x.innerHTML;
}
</script>
</body>
</html>
https://jsfiddle.net/mediaguru/xt9mkncx/
using jquery use this
var x = $('style').html();
using javascript
var x=document.getElementById("home");
var y = x.firstChild.innerHTML;
Ahh I'm so stupid..
for (var i = 0; i < styles_length; i++)
{// I had:
// styles.innerHTML;
// not correct:
styles[i].innerHTML;
}
All answers by #Jag, #ABHIJITH GM, #mediaguru, #hardik are correct.
Thank you guys! And sorry for this newbie question... all day codding, my eyes are hurting, coffee time.
I have a div with id, which has some other div's without id.
Some thing like:
<div class="mainDivClass" id="mainDiv">
<div class="subDivClass">
<h2>one</h2>
Hello One!!
</div>
<div class="subDivClass">
<h2>two</h2>
Hello Two!!
</div>
<div class="subDivClass">
<h2>three</h2>
Hello Three!!
</div>
</div>
In my javascript, I am looping through above div like:
var divLists = document.getElementById('mainDiv').firstChild.childNodes;
for (var i = 0; i < tabLists.length; i++) {
var anchor = divLists[i].firstChild;
var iconFile;
if(i==0)
{
iconFile = 'details.png';
}
else
{
iconFile = 'search1.png';
}
anchor.style.backgroundImage = 'url(' + iconFile + ')';
anchor.style.backgroundRepeat = 'no-repeat';
anchor.style.backgroundPosition = '1px 2px';
anchor.className = 'toplevel-tab';
}
As shown, I am setting iconFile variable on value of i. So for i = 0, it would be details.png while for all others, it would be search1.png.
Now, I want to decide the iconFile variable value based on the h2 value of the element.
That is, if h2 is banana, banana.png will go in iconFile but if h2 is orange, orange.png will be selected.
How to get h2 value inside javascript ?
Thanks for reading!!
Nik
Don't use innerHTML, it's an unreliable proprietary Microsoft method; should you get used to using it you will immediately begin having problems if you start coding at an application level and not be able to figure out why. Stick to using DOM specifications instead.
An example that you can obviously throw in to a loop...
document.getElementById('subDivClass').getElementsByTagName('h2').firstChild.nodeValue
.parentNode - The parent element of the currently referenced element.
.parentNode.parentNode.parentNode - You can use this as much as you want to go up or around the DOM.
.childNodes[0] - Index of child elements, does NOT contain reference to text nodes AFTER an element (use treewalker for that).
.nodeValue - The text value of a node, do NOT use innerHTML.
.textContent - Gets or sets the text of an element (but no child elements); a bit easier than nodeValue though it still has reasonable limitations.
.previousSibling - The element BEFORE the reference element, not a child/parent.
.nextSibling - The element AFTER the reference element, not a child/parent.
You can reveal all objects (e.g. methods, properties and other objects) for any object using the in operator to discover what else is available to you...
for (i in document.getElementById('mainDiv')) {alert('i = '+i);}
It should be noted that if you're stuck using the HTML parser .nodeName will be all uppercase (e.g. the old Internet Explorer way) versus using the XML parser (application/xhtml+xml) the .nodeName will properly return the element's name as lowercase (unless you're really in to the 90's style or something).
It should also be noted that when you use previousSibling and nextSibling that line breaks alone will create a textNode and those line breaks will mess with CSS (setting the font-size to 5px will generally eliminate this).
If you want all the H2 elements inside the mainDivClass you can use the getElementsByTagName method:
var outerDiv = document.getElementById("mainDiv");
var h2s = outerDiv.getElementsByTagName("h2");
This returns all the H2 elements as an array of elements.
var answer = function () {
var parent = document.getElementById("mainDiv"),
h2 = parent.getElementsByTagName("h2"),
a = h2.length,
b;
for (b = 0; b < a; b += 1) {
switch (h2[b].innerHTML) {
case "one":
//do something
break;
case "two":
//do something
break;
default:
//do something else
break;
}
}
};
The h2 value will be used as below:
for (var i = 0; i < tabLists.length; i++) {
var anchor = tabLists[i].firstChild;
var iconFile;
if(tabLists[i].firstChild.innerHTML == "Tab 0")
{
iconFile = 'one.png';
}
else if(tabLists[i].firstChild.innerHTML == "apple")
{
iconFile = 'apple.png';
}
else if(tabLists[i].firstChild.innerHTML == "orange")
{
iconFile = 'banana.png';
}
else if(tabLists[i].firstChild.innerHTML == "banana")
{
iconFile = 'orange.png';
}
anchor.style.backgroundImage = 'url(' + iconFile + ')';
anchor.style.backgroundRepeat = 'no-repeat';
anchor.style.backgroundPosition = '1px 2px';
anchor.className = 'toplevel-tab';
}
I am trying to create a div element which shows some text as popup. But the problem is when i create the element using javascript, the div already contains the default style which is defined in document style sheet or external css. Like for example:
popup = document.createElement("div");
popup.setAttribute("id","myElement");
popup.style.left = "100px";
popup.style.top = "100px";
popup.style.width = "100px";
popup.style.height = "100px";
document.body.appendChild(popup);
and now when it shows up, it already has colors, borders etc because in css there is this div style which is being applied on this element. I want it to not inherit anything which is defined for the document itself, how can i do that, or may be overwrite the original style??
A way to achieve this is to override all of the available properties set with the css in this document. But with JavaScript is a lot of work.
Better way is to add an id or class to the newly created element. The style should have all of the properties that are applicable for the type of element you are creating. If you miss a property it will be set from the present css.
I would give these new divs a specific class name and link a custom stylesheet that resets all properties for that class to the desired defaults (ensuring that the linked styles have the necessary precedence in the cascade). Moving this reset into your JavaScript sounds like a bad idea.
So I made something like this. It may not be ideal solution but it atleast does what i wanted:
function displayMenu(){
var popup;
//see if there is already default style defined in the document
var styleSheets = document.styleSheets;
var size = styleSheets.length;
var cssRules = new Array();
var rules = "";
var css, len, st, sp;
for (i=0;i<size;i++){
cssRules[i] = styleSheets[i].rules || styleSheets[i].cssRules;
for (j=0;j<cssRules[i].length;j++){
if(cssRules[i][j].cssText.search(/div/i) != -1){
css = cssRules[i][j].cssText;
css = css.substr(((css.search("{"))+1),((css.search("}"))-(((css.search("{"))+1))));
if((css.search("{") == -1) && (css.search("}") == -1)) {
//no of css-properties in this specific rule
len = css.split(";").length - 1;
for (k=0;k<len;k++){
st = css.search(";") + 1;
rules += css.substr(0,(css.substr(0,st).search(":")+1)) + "0\n";
css = css.substr(st);
}
} else {} //ignore this rule
}
}
}
var reset = '.myStyle { '+ rules +' }\n';
//now create a css Class which overwrite default document properties for this <div> element
var myStyle = document.createElement('style');
myStyle.type = 'text/css';
//TODO: should be replaced with style from arguments
myStyle.innerHTML = reset;
document.getElementsByTagName('head')[0].appendChild(myStyle);
//start creating the popup menu:
var popup;
popup = document.createElement("div");
popup.setAttribute("id","guide_popup");
popup.setAttribute("class","myStyle");
//now define own style rules: (All basic properties need to be defined as there is none by defualt now)
popup.style.top = top;
popup.style.left = left;
popup.style.width = width;
popup.style.height = height;
popup.style.zIndex = index;
//TODO: should be replaced with str in aruguments
var popup_text = document.createTextNode("This is my sample text");
popup.appendChild(popup_text);
//finally process the DOM
document.body.appendChild(popup);
}
Does someone know how to empty the content of a div (without destroying it) in JavaScript?
Thanks,
Bruno
If your div looks like this:
<div id="MyDiv">content in here</div>
Then this Javascript:
document.getElementById("MyDiv").innerHTML = "";
will make it look like this:
<div id="MyDiv"></div>
If you're using jQuery ...
$('div').html('');
or
$('div').empty();
An alternative way to do it is:
var div = document.getElementById('myDiv');
while(div.firstChild)
div.removeChild(div.firstChild);
However, using document.getElementById('myDiv').innerHTML = ""; is faster.
See: Benchmark test
N.B.
Both methods preserve the div.
If by saying without destroying it, you mean to a keep a reference to the children, you can do:
var oldChildren = [];
while(element.hasChildNodes()) {
oldChildren.push(element.removeChild(element.firstChild));
}
Regarding the original tagging (html css) of your question:
You cannot remove content with CSS. You could only hide it. E.g. you can hide all children of a certain node with:
#someID > * {
display: none;
}
This doesn't work in IE6 though (but you could use #someID *).
In jQuery it would be as simple as $('#yourDivID').empty()
See the documentation.
This method works best to me:
Element.prototype.remove = function() {
this.parentElement.removeChild(this);
}
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
for(var i = this.length - 1; i >= 0; i--) {
if(this[i] && this[i].parentElement) {
this[i].parentElement.removeChild(this[i]);
}
}
}
To use it we can deploy like this:
document.getElementsByID('DIV_Id').remove();
or
document.getElementsByClassName('DIV_Class').remove();
you can .remove() each child:
const div = document.querySelector('div.my-div')
while(div.firstChild) div.firstChild.remove()
You can empty your DOM using this:
const el = document.getElementById("MyDiv");
while (el.firstChild) {
el.removeChild(el.firstChild);
}
This is supposed to be faster than the traditionally used method : document.getElementById("MyDiv").innerHTML = "";