I often use the CSS universal selector to reset the dimensions in my HTML document:
* {
border: 0;
margin: 0;
padding: 0;
}
Can this be done with JavaScript too?
For normal HTML elements there is the style property.
But how to speak to the universal selector?
getElementsByTagName("*") will return all elements from DOM. Then you may set styles for each element in the collection:
var allElements = document.getElementsByTagName("*");
for (var i = 0, len = allElements.length; i < len; i++) {
var element = allElements[i];
// element.style.border = ...
}
You don't need to iterate all the elements. You can demand this operation to the CSS engine of your browser. Something like that:
;(function(exports) {
var style = document.querySelector("head")
.appendChild(document.createElement("style"));
var styleSheet = document.styleSheets[document.styleSheets.length - 1];
styleSheet.insertRule("* {}", 0);
exports.universal = styleSheet.cssRules[0];
}(window));
From now, you have a window.universal object that you can use to style all the elements. For instance:
window.universal.style.border = "1px solid red";
Of course you don't need to create at runtime the <style> tag. You can always have that in plain HTML too.
You can test it running this snippet:
;(function(exports) {
var style = document.querySelector("head")
.appendChild(document.createElement("style"));
var styleSheet = document.styleSheets[document.styleSheets.length - 1];
styleSheet.insertRule("* {}", 0);
exports.universal = styleSheet.cssRules[0];
}(window));
console.log("universal" in window); // true
window.universal.style.border = "1px solid red";
<div>
Hello
<span>World</span>
</div>
In raw javascript you can do this:
document.getElementsByTagName('*')
but I wouldn't recommend adding css to all elements using js.
Thanks VisioN for the solution! I just remembered that you can do the same with the new JavaScript Query Selector API:
var allElements = document.querySelectorAll('*');
for (var i = 0; i < allElements.length; i++) {
var element = allElements[i];
element.style.border = '0px';
element.style.margin = '0px';
element.style.padding = '0px';
}
Related
My question is:
Is that possible to add the same element without rewriting the same variable.
I am creating a slider, and i need to append a div with a class slide-el into block slider.
Here is a part of code
var body, html, sliderBody, btnLeft, btnRight, i, parts, vHeight, vWidth;
//Variable definitions
var i = 0,
parts = 3,
//Main html elements
body = document.body,
html = document.element,
//viewport Height and Width
vHeight = window.innerHeight,
vWidth = window.innerWidth,
sliderBody = _id("slider"),
btnLeft = _id("btn-left"),
btnRight = _id("btn-right"),
urls = ["http://www.wallpapereast.com/static/images/pier_1080.jpg",
"http://www.wallpapereast.com/static/images/pier_1080.jpg",
"http://www.wallpapereast.com/static/images/pier_1080.jpg",
"http://www.wallpapereast.com/static/images/pier_1080.jpg"];
slide = _createEl("div");
slide.className += "slide-el";
function _id(el){
return document.getElementById(""+ el +"");
}
function _createEl(el){
return document.createElement(""+ el +"");
}
window.onload = function(){
slideLayout();
}
function slideLayout(){
for(var i=0; i < urls.length; i++){
sliderBody.appendChild(slide);
}
}
The problem is that I can't append the same element that many times. It just creates one element instead of 4.
For you to understand better I made a fiddle:
https://jsfiddle.net/ud7dvn3z/
appendChild will remove the node from wherever it is before appending it to its new location, so you need to make copies of the node instead. You can use cloneNode for that. The true makes cloneNode perform a deep clone, i.e. with all its child nodes.
for(var i = 0; i < urls.length; i++){
sliderBody.appendChild(slide.cloneNode(true));
}
Okey guys! I found an answer. I have to put
slide = _createEl("div");
slide.className += "slide-el";
into for loop.
Now it looks like this:
for(var i=0; i < urls.length; i++){
slide = _createEl("div");
slide.className += "slide-el";
sliderBody.appendChild(slide);
}
My question is:
Is that possible to add the same element without rewriting the same variable.
I am creating a slider, and i need to append a div with a class slide-el into block slider.
Here is a part of code
var body, html, sliderBody, btnLeft, btnRight, i, parts, vHeight, vWidth;
//Variable definitions
var i = 0,
parts = 3,
//Main html elements
body = document.body,
html = document.element,
//viewport Height and Width
vHeight = window.innerHeight,
vWidth = window.innerWidth,
sliderBody = _id("slider"),
btnLeft = _id("btn-left"),
btnRight = _id("btn-right"),
urls = ["http://www.wallpapereast.com/static/images/pier_1080.jpg",
"http://www.wallpapereast.com/static/images/pier_1080.jpg",
"http://www.wallpapereast.com/static/images/pier_1080.jpg",
"http://www.wallpapereast.com/static/images/pier_1080.jpg"];
slide = _createEl("div");
slide.className += "slide-el";
function _id(el){
return document.getElementById(""+ el +"");
}
function _createEl(el){
return document.createElement(""+ el +"");
}
window.onload = function(){
slideLayout();
}
function slideLayout(){
for(var i=0; i < urls.length; i++){
sliderBody.appendChild(slide);
}
}
The problem is that I can't append the same element that many times. It just creates one element instead of 4.
For you to understand better I made a fiddle:
https://jsfiddle.net/ud7dvn3z/
appendChild will remove the node from wherever it is before appending it to its new location, so you need to make copies of the node instead. You can use cloneNode for that. The true makes cloneNode perform a deep clone, i.e. with all its child nodes.
for(var i = 0; i < urls.length; i++){
sliderBody.appendChild(slide.cloneNode(true));
}
Okey guys! I found an answer. I have to put
slide = _createEl("div");
slide.className += "slide-el";
into for loop.
Now it looks like this:
for(var i=0; i < urls.length; i++){
slide = _createEl("div");
slide.className += "slide-el";
sliderBody.appendChild(slide);
}
I am trying to wrap each span in a container. To achieve this I used a for loop to create multiple containers and then append the span to the container of the same index.
Why isnt my logic working?
Html: Two span tags (Sorry html code wont show)
Javascript:
var spans = document.getElementsByTagName('span'),
body = document.getElementsByTagName('body')[0];
for(var i = 0; i < spans.length; i++)
{
var container = document.createElement('figure');
container.setAttribute('class', 'container');
body.appendChild(container);
container.appendChild(spans[i]);
}
Edit: https://jsfiddle.net/tsrLutpg/1/
Part of the reason for the oddity is because the HTMLCollection set to spans is "live." This means, as you modify a <span>, the collection changes to reflect that change.
In this case, the collection changes the order the <span>s are listed in. As you're iterating, some may be wrapped twice moving from one <figure> to another, while others may remain unaltered when they move to an index that's already been visited.
<span>Foo</span>
<span>Bar</span>
<span>Baz</span>
for (var i = 0; i < spans.length; i++)
{
// ...
console.log(Array.from(spans).map(s => s.outerHTML));
container.appendChild(spans[i]);
}
// ["<span>Foo</span>", "<span>Bar</span>", "<span>Baz</span>"] (1 2 3)
// ["<span>Bar</span>", "<span>Baz</span>", "<span>Foo</span>"] (2 3 1)
// ["<span>Bar</span>", "<span>Foo</span>", "<span>Baz</span>"] (2 1 3)
You can avoid this by creating a static collection of the <span>s to iterate over, that doesn't change as the <span>s change.
In modern browsers, you can use Array.from() for this (similar to the above snippet).
var spans = Array.from(document.getElementsByTagName('span'));
https://jsfiddle.net/394La14t/
For compatibility, MDN offers a polyfill you can use. Or, you can call .slice() instead.
var spans = Array.prototype.slice.call(document.getElementsByTagName('span'), 0);
Here is the solution that properly wraps span tags:
var spans = document.getElementsByTagName("span");
for (var i = 0; i < spans.length; i++) {
var container = document.createElement("figure");
container.className = "container";
var span = spans[i];
span = span.parentNode.replaceChild(container, span);
container.appendChild(span);
}
If you're using jQuery library on the page, you could use next line of code:
$("span").wrap("<div class = 'outer'></div>")
Here is an alternative solution using insertBefore, before appendChild:
var containers = [];
var body = document.getElementsByTagName('body')[0];
var spans = document.getElementsByTagName('span');
for (var i = 0; i < spans.length; i++) {
containers[i] = document.createElement('figure');
body.insertBefore(containers[i],spans[i]);
containers[i].appendChild(spans[i]);
}
span {
background-color: rgb(191,191,255);
}
figure {
border: 1px solid rgb(0,0,255);
}
<span>ABC</span>
<span>ABC</span>
<span>ABC</span>
<span>ABC</span>
<span>ABC</span>
<span>ABC</span>
<span>ABC</span>
<span>ABC</span>
<span>ABC</span>
<span>ABC</span>
<span>ABC</span>
Just respect the order of your spans, instead of inserting the container after all of their spans insert it where the old span used to be. Change:
body.appendChild(container);
To:
spans[i].parentNode.insertBefore(container, spans[i]);
And now it works:
var spans = document.getElementsByTagName('span'),
body = document.getElementsByTagName('body')[0];
for(var i = 0; i < spans.length; i++)
{
var container = document.createElement('figure');
container.setAttribute('class', 'container');
spans[i].parentNode.insertBefore(container, spans[i]);
container.appendChild(spans[i]);
}
<span></span>
<span></span>
I need to change the content of all "h1" tags in my html file when the page load using javascript.
So I write the following code
window.onload = function () {
var h1html = document.createElement("h1");
var h1htmltext = document.createTextNode("header 1");
h1html.appendChild(h1htmltext);
document.getElementsByTagName("h1").appendChild(h1html);
};
If you're sure you only have one h1 tag you could simply do
window.onload = function () {
document.getElementsByTagName("h1")[0].innerHTML = "header 1";
}
if multiple h1 tags are present you could do
window.onload = function () {
var h1Elems = document.getElementsByTagName("h1");
var pos;
for (pos in h1Elems) {
h1Elems[pos].innerHTML = "header 1";
}
}
Use this:
for(var i = 0, elems = document.getElementsByTagName('h1'); i < elems.length; i++) {
elems[i].innerHTML = "new";
}
fiddle
You need to change the innerHTML of each elements, as such
function changeall(){
var headers=document.getElementsByTagName("h1");
var newheadertext="hello";
for(var i in headers){
headers[i].innerHTML=newheadertext;
}
}
getElementsByTagName returns a node list; you need to loop through it.
var headers = document.getElementsByTagName("h1");
for(var i = 0; i < headers.length; i++) {
var header = headers[i];
var text = document.createTextNode("header 1");
while(header.childNodes.length) {
header.removeChild(header.firstChild);
}
header.appendChild(text);
}
I made a few assumptions there:
You don’t actually want to nest headers
You want to replace the content
You want an old-standards-compliant way
If you don’t need support for old browsers, just use textContent:
var headers = document.getElementsByTagName("h1");
for(var i = 0; i < headers.length; i++) {
headers[i].textContent = "header 1";
}
Below is the javascript I have for my page:
window.onmouseover = function(){
var body = document.getElementsByTagName("body")
var h1 = document.getElementsByTagName("h1");
var a = document.getElementsByTagName("a");
var p = document.getElementsByTagName("p")
for(var j = 0; j < p.length; j++) {
body[j].style.fontFamily = "helvetica";
body[j].style.backgroundColor = "rgb(250, 250, 240)"
p[j].style.fontFamily = "courier";
a[j].onclick = function() {
this.style.backgroundColor = "Black"
}
}
}
I have one h1 element, one a element, and 10 p elements. For some reason, this code only changes the font of the first p element, although everything else works fine? Why is this and how can I fix it?
If you have only one a element and (of course) only one body you cannot iterate over 10 of them. This causes an error on the second iteration of the cycle. Use this code instead.
window.onmouseover = function(){
var body = document.getElementsByTagName("body")
var h1 = document.getElementsByTagName("h1");
var a = document.getElementsByTagName("a");
var p = document.getElementsByTagName("p")
body[0].style.fontFamily = "helvetica";
body[0].style.backgroundColor = "rgb(250, 250, 240)"
a[0].onclick = function() {
this.style.backgroundColor = "Black"
}
for (var j = 0; j < p.length; j++) {
p[j].style.fontFamily = "courier";
}
}
It may be generating an error the second time through the loop, since body[1] would be invalid. Move things around so that only manipulations on p are inside the loop.