I am making a gallery. All images are named 1.jpg, 2.jpg, 3.jpg etc - it extends all the way up to 200.jpg.
Copy and paste will be OK, but very time consuming.
<div class="slideshow-container">
<div class="slideshowDisplay fade">
<img src="/images/media/1.jpg" width="100%">
</div>
<div class="slideshowDisplay fade">
<img src="/images/media/2.jpg" width="100%">
</div>
<div class="slideshowDisplay fade">
<img src="/images/media/3.jpg" width="100%">
</div>
Can I use a for-loop or similar to create all the elements for me? My only problem is that, a for loop is used to repeat a code block multiple times is it not, so this for me wouldn't work.
Is there another way that I can create elements without having to spend a long time simply incrementing numbers by hand?
So far I have:
for(var i=0; i < 200; i++){
var newDiv = document.createElement('div');
newDiv.className = 'slideshowDisplay fade';
}
Nothing else...
Any guidance much appreciated.
Basic DOM creation and appending
You're only missing appending the new element to the slideshow-container and adding its content. You can use the i variable to create the increment image src.
var sc = document.querySelector(".slideshow-container")
for(var i=0; i < 200; i++){
var newDiv = sc.appendChild(document.createElement('div'));
newDiv.className = 'slideshowDisplay fade';
var img = newDiv.appendChild(document.createElement("img"));
img.width="100%";
img.src = "/images/media/" + (i + 1) + ".jpg";
}
String concatenation
The means of creating the src is called "string concatenation". In other words, we create a new string from multiple parts. First the "/images/media/" string, then the value of i, but adjusted up by one, and finally the ".jpg" part.
Making helper functions
FWIW, it's nice to have a personal micro-library that you use to handle certain repetitive tasks. One such inclusion can be a function for creating new Elements.
function create(elem, props, par) {
var el = document.createElement(elem)
for (var p in props) {
el[p] = props[p]
}
return par ? par.appendChild(el) : el
}
This takes a little verbosity out of creating and appending the new elements.
var sc = document.querySelector(".slideshow-container")
for(var i=0; i < 200; i++){
var newDiv = create("div", {className: "slideshowDisplay fade"}, sc);
create("img", {width: "100%", src: "/images/media/"+(i+1)+".jpg"}, newDiv);
}
Different approach to a helper function
Or instead of having the function receive the parent to which it is appended, you could allow it to receive an arbitrary number of child elements that it will append to itself.
function create(elem, props, ...children) {
var el = document.createElement(elem)
for (var p in props) {
el[p] = props[p]
}
children.forEach(ch => el.appendChild(ch))
return el
}
Then you can nest calls to create in a way that mirrors the new DOM structure.
var sc = document.querySelector(".slideshow-container")
for(var i=0; i < 200; i++){
sc.appendChild(
create("div", {className: "slideshowDisplay fade"},
create("img", {width: "100%", src: "/images/media/"+(i+1)+".jpg"})
)
);
}
Actually you need just one parent div in your DOM. Then just use functions like document.createElement and appendChild to store the newly created divs with pictures inside the parent element.
var source = "/images/media/";
var parent = document.getElementById('parent');
for (var i = 0; i < 10; i++) {
var newDiv = document.createElement('div');
newDiv.className = 'slideshowDisplay fade';
var img = document.createElement('img');
img.src = source + i + '.jpg';
img.width = '100%';
newDiv.appendChild(img);
parent.appendChild(newDiv);
}
<div class="slideshow-container" id='parent'>
</div>
Related
I was wondering if there isn't a smarter way to work with classes between javascript and css. As I understander the "only" / most common way to select all elements with the same class is by making a for loop:
jsfiddle.net/JoshuaChronstedt/obk92sh6/2/
var elems = document.getElementsByClassName("helloClass");
for (var i = 0; i < elems.length; i++) {
elems[i].style.background = "red";
}
Wouldn't it be possible to create a function to hold the for loop? I'm a noob to js and can't seem to make it work:
jsfiddle.net/JoshuaChronstedt/obk92sh6/6/
function getClass(getClassName) {
var elems = document.getElementsByClassName("getClassName");
for (var i = 0; i < elems.length; i++) {
elems[i];
}
}
getClass("helloClass").style.background = "red";
getClass("helloClassTwo").style.background = "blue";
I guess what I am ultimately trying to do is find a more readable and more DRY way of editing elements by class names.
edit:
Thanks for the snippets. I have tried using some of the code that has been sugested. But it still doesn't seem to work:
function getClass(getClassName) {
Array.from(document.querySelectorAll('.' + '\'' + getClassName + '\'')).forEach(e => e);
}
getClass(helloClass).style.background = 'yellow';
getClass(helloClassTwo).style.color = 'red';
<div class="helloClass">
hello class
</div>
<div class="helloClass">
hello class
</div>
<div class="helloClassTwo">
hello class Two
</div>
<div class="helloClassTwo">
hello class Two
</div>
You can implement map function to iterate.map function iterates elements in array.
Hence here you need to change normal object to array first using Array.from() method
var elems;
function getClass(getClassfuncCont) {
return document.getElementsByClassName(getClassfuncCont);
}
elems = getClass("helloClass");
Array.from(elems).map(element=>element.style.background = "red");
Please refer working snippet.
var elems;
function getClass(getClassfuncCont) {
return document.getElementsByClassName(getClassfuncCont);
}
elems = getClass("helloClass");
Array.from(elems).map(element=>element.style.background = "red");
<div class="helloClass">
hello class
</div>
<div class="helloClass">
hello class
</div>
<div class="helloClass">
hello class
</div>
As mentioned in one of the comments, you're passing getClassName as string when you're supposed to pass it as variable. Taking away the double quote should make it work.
However, you won't be able to modify the style property the way you're doing it right now, because your function does not return the elements. If what you're trying to do is batch-changing the background color based on class name, I suggest adding the color name as a second variable:
//renaming the function so it's more representative
function colorBackgroundByClass(getClassName,color) {
var elems = document.getElementsByClassName(getClassName);
for (var i = 0; i < elems.length; i++) {
elems[i].style.background = color;
}
}
colorBackgroundByClass("helloClass","red");
colorBackgroundByClass("helloClassTwo","blue");
I created a small script that counts images that I uploaded/inserted to my html source code. After I inserted images script creates div containers for those images. If I gave three images, then script will create three divs with class name etc. I have css rule with that class name. This was create before any images were in that container. Everything works but I just can't append those newly images to newly created divs. Is there a way using JavaScript only?
Here is a code:
if (document.getElementsByClassName("Multimedia")[0].getElementsByTagName("IMG")) {
total_number_of_images = document.getElementsByClassName("Multimedia")[0].getElementsByTagName("IMG").length;
for (i = 0; i < total_number_of_images; i = i + 1) {
document.getElementsByTagName("IMG")[i].className = "Image_clip";
child = document.getElementsByTagName("IMG")[i];
image_container = document.createElement("DIV");
image_container.className = "Image_container_div";
document.getElementsByClassName("Multimedia")[0].appendChild(image_container);
document.getElementsByTagName("IMG")[i].style.opacity = "0.8";
}
}
I tried somthenig like this:
image_container.appendChild(child);
But then I can get only two images into container... my third is out and also without className. Without this code, I get className for every image
You should cache the reference to elements rather than querying DOM in loops.
If I understood correctly, Your code should look something like the following for wrapping each image in a container <div>:
var container = document.getElementsByClassName("multimedia")[0];
// if there is only one match, use an id instead ------------^ ?
var images = container.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) {
var img = images[i];
img.className = "imageClip";
img.style.opacity = "0.8"; // Why not define this in imageClip class ..?
imageContainer = document.createElement("div");
imageContainer.className = "imageContainer";
imageContainer.appendChild(img);
container.appendChild(imageContainer);
}
This I get on Yahoo answer. Posted by YaYox: http://jsfiddle.net/ffxad4bq/4
function myFunction() {
var multimedia = document.getElementsByClassName("Multimedia")[0]
var imgs = multimedia.getElementsByTagName("IMG");
for (var i = 0; i < imgs.length; i++) {
imgs[0].className = "Image_clip";
imgs[0].style.opacity = "0.3";
multimedia.innerHTML += '<div class="Image_container_div">'+imgs[0].outerHTML+'</div>';
imgs[0].remove()
}
}
I realized what was the problem. I shouldn't itaret through images. Just leave it on zero because, when loops start, code append one image at a time. When second loop starts I don't have any more 3 images, but two, that is why one image always stays out because loop goes three times.
I have a procedure
newRows = JSON.parse(newRowsStr);
var wsr = $('#work-sample-row');
for (var i = 0, n = newRows.length; i < n; ++i)
{
var thisBox = boxHtml;
var thisNewRow = newRows[i];
thisBox.find('.work-item-preview-outer').css('background-image', thisNewRow['imageurl']);
thisBox.find('.work-title').text(thisNewRow['title']);
thisBox.find('.work-descr-short').text(thisNewRow['sumsmall']);
wsr.append(thisBox);
setTimeout(function(){thisBox.css('opacity','0');}, i * 200)
}
where
boxHtml = $('<div class="mb-30-for-mobile col-xxs-12 col-xs-6 col-sm-4 col-md-3 col-lg-3 work-column" style="opacity:0;"><a class="work-link-wrap"><div class="work-item-preview-outer"><div class="work-item-preview-inner"><h3 class="work-title"></h3><p class="work-descr-short"></p></div></div></a></div>');
and what this is meant to do inside the loop is create copies of boxHtml and add some text and styles and then make each of those copies a child of $('#work-sample-row'). I'm not seeing any errors in the console, but I'm also not seeing the children get added. What gives?
When doing thisBox = boxHtml you are not creating a copy, just created a new reference to boxHtml. if boxHtml is a jQuery wrapped element try thisBox = boxHtml.clone(); if it's not a wrapped element do thisBox = $(boxHtml).clone();
So my issue is, whenever I run this loop, it only grabs the changes to the element on the first flip through. Is there a way to make it make those changes every time?
<script>
for ( i=0; i<5; i++){
document.write('<div id=\"blah\" >text</div>');
var b = document.getElementById("blah");
b.style.width ="200px";
b.style.backgroundColor="yellow";
}
</script>
id has to be unique in a document. hence the issue. The DOM would return only 1 node even if there are multiple matches.
You can do something like this:
for (var i=0; i<5; i++){
var div = '<div class="blah" >text</div>';
div.style.width ="200px";
div.style.backgroundColor="yellow";
document.write(div);
}
I have two ideas to overcome this. The first is to create the element, change its style, and append it.
<script type="text/javascript">
for (var i = 0; i < 5; i++) {
var div = document.createElement("div");
div.style.width = "200px";
div.style.backgroundColor = "yellow";
document.appendChild(div);
}
</script>
The other idea is that you don't need a reference to the DOM element, because you're only changing style, so you can apply the style with CSS. For example:
<style type="text/css">
div.something {
width: 200px;
background-color: yellow;
}
</style>
<script type="text/javascript">
for (var i = 0; i < 5; i++) {
document.write("<div class='something'>text</div>");
// Or use the createElement/appendChild approach from above,
// where you'd need to set the div.className property as "something"
}
</script>
You need to add the element to the DOM to be able to access it later.
for(var i=0;i<5;i++)
{
//I'm not sure if you are just trying to make these changes each iteration
//or create a new element each time. If you are trying to create a new element
//each time. I'd def consider going a diff route i.e. use classes.
var b;
if( i==0 ){
b = document.createElement("DIV");
b.id = "blah";}
else{
b = document.getElementById("blah");}
b.style.width ="200px";
b.style.backgroundColor="yellow";
}
I have a tree structure as follows:
<ul id="theul275">
<li>
<div id="red"></div>
<img id="green" />
<script></script>
<div id="blue"></div>
</li>
</ul>
There are multiple UL's likes this on my page each with a different id. I am getting each UL by doing this:
var child = document.getElementById('theul' + id).getElementsByTagName('*');
the problem is, I only want to get the children of each ul which are either div's or img's.
Is there a way to get elements by multiple tag names?
I really appreciate any help because I am kind of new to JavaScript! Thanks!
Depending on what browsers you may to support, you could use the CSS selector interface.
document.getElementById('theul275').querySelectorAll('div, img');
Or use a library. There are plenty of options out there. I am familiar with two,
MooTools
$('theul275').getElements('div, img');
jQuery
$('#theul275').find('div, img');
Or get a reference to the li node, and loop through each node and check if the nodeName is DIV or IMG.
for (var i = 0, l = child.length; i < l; i++)
{
if (child[i].nodeName == 'DIV' || child[i].nodeName == 'IMG')
{
//...
}
}
You could use a iterative method for this.
var elemArray = document.getElementById('theul' + id).childNodes,
getChildByNodeName = function (elem, pattern) {
var childCollection = [],
re = new RegExp(pattern, 'g'),
getChild = function (elements) {
var childs = elements.childNodes,
i = 0;
if (childs) {
getChild(childs);
for (i = 0; i < childs.length; i += 1) {
if (childs[i].nodeName.match(pattern)) {
childCollection.push(childs[i]);
}
}
}
};
getChild(elem);
return childCollection;
}
var childs2 = getChildByNodeName(elemArray, '^(DIV|IMG)$'); // array of match elements
And just change the pattern ('^(DIV|IMG)$') to suite your needs.
If you can use jQuery, try
var child = $("#theul" + id).find("div,img");
Otherwise, see JavaScript NodeList.