I want to get only the computed styles of the elements on a page, without all the inherited styles
var allElements = document.querySelectorAll( '*' );
for (var i=0;i<allElements.length;i++){
var element = allElements[i];
var css = getComputedStyle(element);
}
this obviously gets a gigantic list of all the styles.
I need only the 'computed styles' that would show up in Chrome's inspector thing when the "show inherited" checkbox is disabled.
What's the JS for this?
EDIT:
I'm basically looking to save all the css I've modified in Chrome inspector. I'm laying out things on a page and I'm playing with fonts and elements placement (dragging jquery draggables around). I want to save the positions and CSS of everything.
Maybe I went way too complex and there's a simple way to save all the modified styles in Chrome inspector?
Try getting computed styles of an element and its parent element, then remove identical properties:
var elems = document.getElementsByTagName('*');
var data = '';
for(var n=0;n<elems.length;n++){
if(elems[n].parentNode.tagName){
data+=elems[n].tagName + ': ' + elems[n].className+'\n';
var style = [];
var prStyle = [];
var result = [];
var css = window.getComputedStyle(elems[n], null);
var prCss = window.getComputedStyle(elems[n].parentNode, null);
for(var i=0;i<css.length;i++){
if(css.getPropertyValue(css[i])){
style[i] = css[i]+':'+css.getPropertyValue(css[i]);
}
}
for(var i=0;i<prCss.length;i++){
if(prCss.getPropertyValue(prCss[i])){
prStyle[i] = prCss[i]+':'+prCss.getPropertyValue(prCss[i]);
}
}
for(var i=0;i<style.length;i++){
if(style[i]!=prStyle[i]){
result.push(style[i]);
}
}
for(var i=0;i<result.length;i++) data+=i+':'+result[i]+'\n';
}
data+='-----------------------\n';
}
return data;
Related
I have found the following code from stackoverflow:
<script type="text/javascript">
var allTags = document.body.getElementsByTagName('*');
var classNames = {};
for (var tg = 0; tg< allTags.length; tg++) {
var tag = allTags[tg];
if (tag.className) {
var classes = tag.className.split(" ");
for (var cn = 0; cn < classes.length; cn++){
var cName = classes[cn];
if (! classNames[cName])
{
classNames[cName] = true;
}
}
}
}
var classList = [];
for (var name in classNames)
classList.push(name+'<br />');
document.getElementById('allclasses').innerHTML = classList.sort();
</script>
The above works awesome but just for classes, what about ID's
Now there is one scenario that with the div like this:
<div class="head">
internal divs having classes, IDs should be ignored --
</div>
<div class="footer">
internal divs having classes, IDs should be ignored --
</div>
How can i make above changes to the code, I am asking because I am dumb in Javascript, and i need to make it work as task given..
Assuming you just wanted a list if IDs, like your class list, there is a jQuery version.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/LXhtr/
ID Version in jQuery:
var ids = {};
$('[id]').each(function () {
var id = this.id;
ids[id] = id;
});
var idList = [];
for (var id in ids) {
idList.push(id + '<br />');
}
$('#allids').html(idList.sort());
Notes:
$('[id]') is a jQuery selector that returns any element with an id. $('[class]') does the same for any elements with classes. As you can see jQuery is a lot leaner than raw JavaScript. There is still scope to make these even shorter if required, but that would move so far from your existing code you might not recognize anything :)
Update: http://jsfiddle.net/TrueBlueAussie/LXhtr/3/
You wanted to exclude anything within a class="header" or class="footer".
You can do this in jQuery with selectors like :not([class=header]):not([class=header] *) which basically says, do not include this match, or anything beneath this match.
var ids = {};
$('[id]:not([class=header]):not([class=footer]):not([class=header] *):not([class=footer] *)').each(function () {
var id = this.id;
ids[id] = id;
});
var idList = [];
for (var id in ids) {
idList.push(id + ' <br/>');
}
$('#allids ').html(idList.sort());
I do not have access to the HTML of the pages (they are program-built dynamically).
I do have access to the JS page it is linked to.
For example I can do somethin like this and it works:
window.onload=function(){
var output = document.getElementById('main_co');
var i=1;
var val="";
while(i<=1)
{ if(!document.getElementById('timedrpact01'+i))
{
var ele = document.createElement("div"); ele.setAttribute("id","timedrpact01"+i);
ele.setAttribute("class","inner");
ele.innerHTML=" Hi there!" ;
output.appendChild(ele);
I would like to use this basis insert a button that would allow to switch from one CSS set (there are several files invoked) to another _another path.
Many thanks
The external stylesheets are referenced using link, as in:
<link rel="stylesheet" href="http://example.com/path-to-css">
So, get hold of the appropriate link element using:
var css = document.getElementsByTagName("link")[0];
Here, we got hold of the first link available by specifying the [0] index.
Then, overwrite the href attribute to point it to the new path.
css.setAttribute("href", "http://example.com/path-to-css");
window.onload=function(){
var output = document.getElementById('main_co');
var i=1;
var val="";
//switch all the href's to another path
var switchStyleSheet = function() {
var links = document.getElementsByTagName("link");
for(var i=0; lkC = links.length; i < lkC; i++)
links[0].href = links[0].href.replace('path_to_file', '_path_to_file');
};
while(i<=1) //while is not required here, if i is 1
{
if(!document.getElementById('timedrpact01'+i)) {
var ele = document.createElement("div"); ele.setAttribute("id","timedrpact01"+i);
ele.setAttribute("class","inner");
ele.innerHTML=" Hi there!" ;
var button = document.createElement('button');
if(button.addEventListener) {
button.addEventListener('click', switchStyleSheet);
}
else {
button.attachEvent('click', switchStyleSheet);
}
output.appendChild(button);
output.appendChild(ele);
}
}
}
I need to animate several items at the same time, several times on click. I'm not allowed to use Jquery so I'm working with native javascript and CSS3.
Array.prototype.forEach.call(els, function(el) {
elemId = el.getAttribute("id");
var toWidth = boxPos[thisId][elemId].width;
var toHeight = boxPos[thisId][elemId].height;
var toTop = boxPos[thisId][elemId].top;
var toLeft = boxPos[thisId][elemId].left;
var from = "0% {width:"+currPos[elemId].width+"; height:"+currPos[elemId].height+"; top:"+currPos[elemId].top+"; left:"+currPos[elemId].left+";}";
var to = "100% { width:"+toWidth+"; height:"+toHeight+"; top:"+toTop+"; left:"+toLeft+";}";
currPos[elemId].width = toWidth;
currPos[elemId].height = toHeight;
currPos[elemId].top = toTop;
currPos[elemId].left = toLeft;
var styleSheets = document.styleSheets;
for (var i = 0; i < styleSheets.length; ++i) {
for (var j = 0; j < styleSheets[i].cssRules.length; ++j) {
if (styleSheets[i].cssRules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && styleSheets[i].cssRules[j].name == elemId){
keyframes = styleSheets[i].cssRules[j];
}
}
}
keyframes.deleteRule("0%");
keyframes.deleteRule("100%");
keyframes.insertRule(from);
keyframes.insertRule(to);
el.style.webkitAnimationName = elemId;
});
I've searched around the site and have tried using some of the code. The animation will run once, all the elements but just the first time :'(
Here's a non working example code http://jsfiddle.net/kR384/2/
The animation will run once, all the elements but just the first time
You seem to be looking for the animation-iteration-count CSS property, which specifies how often an animation will run. You can set it to infinite or any numerical (positive) value.
The problem you have with your animations is that they are only started on the first click. After that, you don't change the element's styles (reassigning the animation-name doesn't help) - so no animation will get triggered (even if you changed the keyframes rules). The article at http://css-tricks.com/restart-css-animation/ discusses this and a few solutions.
In your case it would even make sense to change the name of animation to something containing the "state":
if( …cssRules[j].name.split("-")[0] == elemId)
keyframes = styleSheets[i].cssRules[j];
…
var newname = elemId+"-"+thisId;
keyframes.name = newname;
…
el.style.animationName = newname;
(Demo with standard properties and a few bugfixes, updated demo with webkit prefixes)
I was able to fix it just by adding a setTimeout(0) to call the animation after the animation name was set to none.
Here's the fixed code http://jsfiddle.net/kR384/3/:
function resetAndRun(o){
one.style.webkitAnimationName = "none";
…
ten.style.webkitAnimationName = "none";
setTimeout(function(){o.animateBox();}, 0);
}
I hope it's useful for someone.
I have a button that is defined as follows :
<button type="button" id="ext-gen26" class=" x-btn-text">button text here</button>
And I'm trying to grab it based on the text value. Hhowever, none of its attributes contain the text value. It's generated in a pretty custom way by the look of it.
Does anyone know of a way to find this value programmatically, besides just going through the HTML text? Other than attributes?
Forgot one other thing, the id for this button changes regularly and using jQuery to grab it results in breaking the page for some reason. If you need any background on why I need this, let me know.
This is the JavaScript I am trying to grab it with:
var all = document.getElementsByTagName('*');
for (var i=0, max=all.length; i < max; i++)
{
var elem = all[i];
if(elem.getAttribute("id") == 'ext-gen26'){
if(elem.attributes != null){
for (var x = 0; x < elem.attributes.length; x++) {
var attrib = elem.attributes[x];
alert(attrib.name + " = " + attrib.value);
}
}
}
};
It only comes back with the three attributes that are defined in the code.
innerHTML, text, and textContent - all come back as null.
You can do that through the textContent/innerText properties (browser-dependant). Here's an example that will work no matter which property the browser uses:
var elem = document.getElementById('ext-gen26');
var txt = elem.textContent || elem.innerText;
alert(txt);
http://jsfiddle.net/ThiefMaster/EcMRT/
You could also do it using jQuery:
alert($('#ext-gen26').text());
If you're trying to locate the button entirely by its text content, I'd grab a list of all buttons and loop through them to find this one:
function findButtonbyTextContent(text) {
var buttons = document.querySelectorAll('button');
for (var i=0, l=buttons.length; i<l; i++) {
if (buttons[i].firstChild.nodeValue == text)
return buttons[i];
}
}
Of course, if the content of this button changes even a little your code will need to be updated.
One liner for finding a button based on it's text.
const findButtonByText = text =>
[...document.querySelectorAll('button')]
.find(btn => btn.textContent.includes(text))
Any ideas on how I would convert this jQuery to vanilla JS:
$('.section > h1').after('<p>This paragraph was inserted with jQuery</p>');
I am new to jQuery and even newer to vanilla JS.
This is as far as I got:
var newP = document.createElement('p');
var pTxt = document.createTextNode('This paragraph was inserted with JavaScript');
var header = document.getElementsByTagName('h1');
Not sure where to go from here?
jQuery does a lot for you behind the scenes. The equivalent plain DOM code might look something like this:
// Get all header elements
var header = document.getElementsByTagName('h1'),
parent,
newP,
text;
// Loop through the elements
for (var i=0, m = header.length; i < m; i++) {
parent = header[i].parentNode;
// Check for "section" in the parent's classname
if (/(?:^|\s)section(?:\s|$)/i.test(parent.className)) {
newP = document.createElement("p");
text = document.createTextNode('This paragraph was inserted with JavaScript');
newP.appendChild(text);
// Insert the new P element after the header element in its parent node
parent.insertBefore(newP, header[i].nextSibling);
}
}
See it in action
Note that you can also use textContent/innerText instead of creating the text node. It's good that you're trying to learn how to directly manipulate the DOM rather than just letting jQuery do all the work. It's nice to understand this stuff, just remember that jQuery and other frameworks are there to lighten these loads for you :)
You might find this function useful (I didn't test)
function insertAfter(node, referenceNode) {
referenceNode.parentNode.insertBefore(node, referenceNode.nextSibling);
}
Oh it's not so bad...
var h1s = document.getElementsByTagName('h1');
for (var i=0, l=h1s.length; i<l; i++) {
var h1 = h1s[i], parent = h1.parentNode;
if (parent.className.match(/\bsection\b/i)) {
var p = document.createElement('p');
p.innerHTML = 'This paragraph was inserted with JavaScript';
parent.insertBefore(p, h1.nextSibling);
}
}