Target Dynamically Created Divs - javascript

I dynamically create a number of divs using javascript based on the number of sections in an external text file. The divs are initially populated with a graph but I'd like to be able to individually toggle the divs over to the raw data that was used to build each graph.
If the text file has 25 sections and creates 25 divs, how do I 'select' say, the 15th div to toggle to the alternate view?
http://jsfiddle.net/EwNRJ/2357/ - demo of a manual solution and framework of the dynamic solution
for (var i = 5; i < count+1; i++) {
new_divs += '<button class="div' + count + '_toggle">toggle ' + count + '</button>;
new_divs += '<div id="div' + count + '_main" class="main" ></div>';
new_divs += '<div id="div' + count + '_alt" class="alt" ></div>';
}

Use jQuery to select all of the child elements $('.container .child'), and then you can use the eq() function to get the nth element. Note that the arrays are zero-indexed, so the fifth element is element 4.
$(document).ready(function() {
// get 5th element (remember arrays are zero-indexed/start at 0)
var $fifth = $('.container .child').eq(4);
// show the fifth element has been selected by setting color to red
$fifth.css({color: 'red'});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
<div class="child">8</div>
</div>

Related

How to make an array with multiple parallel values from multiple divs in javascript?

I want to apply function to multiple div pairs in multiple wrappers. Divs should be selected in parallel by order from 2 different classes.
The best what I can think of is to make an array with n pairs of divs from n number of modules, but I don't know if the concept itself and syntax is right.
Now, I want to apply function to first/second/third/... object-1 and descript-1 divs inside only one module at the same time. And the same goes for next module, instead function should be applied to object-2 - descript-2 pair.
Updated code:
Now I have three different functions, one for next-prev buttons, one for thumbnail control and last one for showing object/description class divs and highlighting thumbs.
I've made nested functions attempt but it doesn't work. Should I declare vars, and get content before making 3 separate modules.forEach functions?
<script>
// nodes Array
let modules = Array.prototype.slice.call(document.querySelectorAll(".module"));
// Loop over the modules without index.
modules.forEach(function(module){
var divIndex = 1;
showDivs(divIndex);
// Objects, descr, thumbs
let objects = module.querySelectorAll(".object");
let descripts = module.querySelectorAll(".descript");
let thumbs = module.querySelectorAll(".thumb");
// next-prev buttons
function plusDivs(n) {
showDivs(divIndex += n);
}
// thumb control
function currentDiv(n) {
showDivs(divIndex = n);
}
// div display
function showDivs(n) {
if (n > objects.length) {divIndex = 1}
if (n < 1) {divIndex = objects.length}
// hide content, shade thumb
objects.style.display = "none";
descripts.style.display = "none";
thumbs.className = thumbs.className.replace(" active", "");
// show only selected object-descr pair and highlight thumb
for(var i = 0; i < objects.length; i++) {
objects[divIndex-1].style.display = "block";
descripts[divIndex-1].style.display = "block";
thumbs[divIndex-1].className += " active";
}
}
});
</script>
<div class="module">
<div class="content">LOREM IPSUM 1</div>
<div class="wrapper">
<div class="content">LOREM IPSUM 1</div>
<div class="object">o1</div>
<div class="object">o2</div>
<div class="object">o3</div>
<div class="descript">d1</div>
<div class="descript">d2</div>
<div class="descript">d3</div>
<div class="thumb" onclick="currentDiv(1)">t1</div>
<div class="thumb" onclick="currentDiv(2)">t2</div>
<div class="thumb" onclick="currentDiv(3)">t3</div>
<a class="prev" onclick="plusDivs(-1)">X</a>
<a class="next" onclick="plusDivs(1)">X</a>
</div>
</div>
<div class="module">
<div class="content">LOREM IPSUM 2</div>
<div class="wrapper">
<div class="content">LOREM IPSUM 2</div>
<div class="object">o4</div>
<div class="object">o5</div>
<div class="object">o6</div>
<div class="descript">d4</div>
<div class="descript">d5</div>
<div class="descript">d6</div>
<div class="thumb" onclick="currentDiv(1)">t4</div>
<div class="thumb" onclick="currentDiv(2)">t5</div>
<div class="thumb" onclick="currentDiv(3)">t6</div>
<a class="prev" onclick="plusDivs(-1)">X</a>
<a class="next" onclick="plusDivs(1)">X</a>
</div>
</div>
Is this what you are looking for? See comments inline. Also, don't use .getElementsByClassName().
// Convert the node list into an Array for the best browser compatibility with Array.forEach()
let modules = Array.prototype.slice.call(document.querySelectorAll("div[class^='module-']"));
// Loop over the modules.
// The Array.forEach() method is much simpler than manual loops because you don't have
// to maintain the loop indexer.
modules.forEach(function(module){
// Get the objects and descriptions (no arrays needed here because we're just
// going to need to use indexes against the node lists.
let objects = module.querySelectorAll("div[class='object']");
let descriptions = module.querySelectorAll("div[class='descript']");
// Clear out the objects and descriptions in the module.
// Start by getting all the objects and descriptions into an array.
let objectsDescriptions = Array.prototype.slice.call(
module.querySelectorAll("[class='object'], [class='descript']"));
// Then remove each item in the array from the document
objectsDescriptions.forEach(function(element){ element.parentNode.removeChild(element); });
// Loop the amount of times that matches the number of items in one of the arrays.
// Here, a regular counting loop makes the most sense because it's all about looping
// the correct number of times, not looping over DOM elements.
for(var i = 0; i < objects.length; i++){
// Repopulate the module with the current child elements, but in the new sequence
module.insertBefore(objects[i], module.querySelector(".thumb"));
module.insertBefore(descriptions[i], module.querySelector(".thumb"));
}
// Set up all the clickable elements to have click event handlers
module.addEventListener("click", function(evt){
// Check to see if it was a thumb or a prev/next that was clicked
if(evt.target.classList.contains("thumb")){
// Show the div that has the same index as the thumbnail that was clicked
let thumbs = Array.prototype.slice.call(evt.target.parentNode.querySelectorAll(".thumb"));
showDiv(evt.target.parentNode, thumbs.indexOf(evt.target));
} else if(evt.target.classList.contains("prev") || evt.target.classList.contains("next")){
// Show the div according to the data-offset attribute of the clicked element
showDiv(evt.target.parentNode, +evt.target.dataset.offset, true);
}
});
});
// ****************************************************************
// CODE TO SHOW DIVS
// ****************************************************************
let currentIndex = 0;
// div display
function showDiv(parent, index, nav) {
// Hide all the objects and descriptions
let items = parent.querySelectorAll(".object, .descript");
Array.prototype.slice.call(items).forEach(function(el){
el.classList.add("hidden");
});
if(nav){
currentIndex += index; // Adjust for the offset
if(currentIndex < 0){
currentIndex = 0;
} else if(currentIndex > (items.length / 2) - 1){
currentIndex = (items.length / 2) - 1;
}
// Show just the ones that are supposed to be shown
parent.querySelectorAll(".object")[currentIndex].classList.remove("hidden");
parent.querySelectorAll(".descript")[currentIndex].classList.remove("hidden");
} else {
// Show just the ones that are supposed to be shown
parent.querySelectorAll(".object")[index].classList.remove("hidden");
parent.querySelectorAll(".descript")[index].classList.remove("hidden");
}
}
.hidden { display:none; }
.thumb, .prev, .next { cursor:pointer; color:blue; }
<div class="module-1">
<div class="object">o1</div>
<div class="object">o2</div>
<div class="object">o3</div>
<div class="descript">d1</div>
<div class="descript">d2</div>
<div class="descript">d3</div>
<div class="thumb">t1</div>
<div class="thumb">t2</div>
<div class="thumb">t3</div>
<span class="prev" data-offset="-1"><</span>
<span class="next" data-offset="1">></span>
</div>
<div class="module-2">
<div class="object">o4</div>
<div class="object">o5</div>
<div class="object">o6</div>
<div class="descript">d4</div>
<div class="descript">d5</div>
<div class="descript">d6</div>
<div class="thumb">t4</div>
<div class="thumb">t5</div>
<div class="thumb">t6</div>
<span class="prev" data-offset="-1"><</span>
<span class="next" data-offset="1">></span>
</div>

How to dynamically update what is being appended using javascript

I am trying to append a box to a list. This box should have a heading which identifies it, but I am having trouble figuring out how to increment each heading by 1.
Currently, the boxes are being generated by this code when a button is clicked.
function createBoxYes(i) {
var box = '<div class="panel-heading">Question 1</div>';
$("#yesColumn").append(box);
}
However, I am trying to increment the Question number based on the input, i. It should equal i + 1. My first thought was to put an id on the div, but if I used findElementById("question"), then it would select all of the boxes, and I want to simply have each box generated to remain unchanged.
Thanks for the help!
This may help you.
function createBoxYes(i) {
var box = '<div class="panel-heading">Question' + (i + 1) +'</div>';
$("#yesColumn").append(box);
}
Just put i+1 in there.
I hope this ll helps you:
var questions = 1;
function createBoxYes() {
var box = '<div class="panel-heading">Question ' + ++questions + '</div>';
$("#yesColumn").append(box);
}
$('#addBox').bind('click', createBoxYes);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet" />
<div id="yesColumn" class="panel panel-default">
<div class="panel-heading">Question 1</div>
</div>
<button id="addBox" class="btn btn-info">Add</button>

Append div tag dynamically inside an existing html structure

I need to append a div tag inside an existing html structure. The problem is I am not able to target the div after which I need to append the new div. I need to append my div inside the "auto-scroll" div. And the div that is appended is getting dynamically generated.
What is happening at present is the divs are getting appended inside the div with id "cases". But I want it to append inside the "auto-scroll" div.
Here is the html structure:
<div class="wrapper" id="cases">
<div class="row">
<div class="col-md-12 case-view-header">Header text</div>
</div>
<div class="auto-scroll">
</div>
</div>
My code:
$.each(caseRecords, function(index, value) {
var tb = $('#cases');
var autoscroll = $('.auto-scroll');
var html = "<div class='row data animate-row'>";
html = html + " <div class='col-xs-12 col-sm-2 col-md-2 col-lg-2 case-view-other height-fix'>" + this.c.CaseNumber + "</div>";
html = html + " <div class='col-xs-12 col-sm-4 col-md-4 col-lg-4 case-view-other height-fix'>" + this.c.Account.Name + "</div>";
html = html + " <div class='col-md-3 case-view-other height-fix'>" + this.cm.MilestoneType.Name + "</div>";
html = html + " <div class='col-xs-12 col-sm-3 col-md-3 col-lg-3 case-view-other height-fix align-center timer-case'> ";
html = html + " <div id='CountDownTimer" + index + "' data-timer='" + this.seconds + "'></div>";
html = html + " <div id='CountDownTimerText" + index + "' style='display: inline-block; position:absolute;'></div>";
html = html + " </div>";
html = html + "</div>";
tb.append(html);
setupCounter('CountDownTimer' + index, 'CountDownTimerText' + index, this.targetSeconds);
});
What is happening at present is the divs are getting appended inside the div with id "cases". But I want it to append inside the "auto-scroll" div.
That is because tb is object of #cases div and you are appending contents to it. you need to target the inner div with class auto-scroll:
var tb = $('#cases .auto-scroll');
var tb = $('.auto-scroll').append(html);
instead of
tb.append(html);
use
autoscroll.append(html);
because tb is #cases whereas autoscroll is the element which you required

javascript adding new elements with progressive IDs and updating the existing ones

I have already 3 existing boxes on a page (divs) with a unique ID (1,2,3) each. I want to have a button by each one of them that allows the user to add new boxes right below. These boxes should follow the already existing numbering. However, doing this will also imply to update the IDs of the already existing boxes underneath the new ones so the numbers match.
This is my code:
function add_box(n) {
document.getElementById("box"+(n<)).setAttribute("id", "box");
var div = document.createElement("div");
div.id="box"+(n+1);
var txt = document.createTextNode("A new box");
div.appendChild(txt);
var newbox = document.getElementById("box"+n);
insertAfter(div,newbox);
}
HTML
<div id="box1">Whatever</div><input type="button" onclick="add_box(1)">
<div id="box2">Whatever</div><input type="button" onclick="add_box(2)">
<div id="box3">Whatever</div><input type="button" onclick="add_box(3)">
Its obviously not working because i guess i need to have an array with all the elements that contain "box" in the ID and then somehow update their numbers but i dont know how to do all that.
Thank you.
The following does what you ask, but I suspect it isn't the result you want.
<script>
// Append a new div after one with id boxn
function add_box(n) {
var el = document.getElementById('box' + n);
var div = document.createElement('div');
div.id = 'box' + ++n;
div.appendChild(document.createTextNode('New box ' + n));
el.parentNode.insertBefore(div, el.nextSibling);
renumberDivs(div, n);
}
// Renumber all sibling divs after el
function renumberDivs(el, n) {
// Note assignment, not equality
while (el = el.nextSibling) {
if (el.tagName && el.tagName.toLowerCase() == 'div'){
el.id = 'box' + ++n;
}
}
}
</script>
<div id="box1">Whatever</div><input type="button" value="add below 1" onclick="add_box(1)">
<div id="box2">Whatever</div><input type="button" value="add below 2" onclick="add_box(2)">
<div id="box3">Whatever</div><input type="button" value="add below 3" onclick="add_box(3)">
Note that in the above, numbers are passed as arguments that are treated as numbers but also implicitly converted to strings when used for the ID value. That sort of type conversion isn't really liked, consider using a more explicit method.
After a few clicks, you may end up with something like:
<div id="box1">Whatever</div>
<div id="box2">New box 2</div>
<div id="box3">New box 3</div>
<div id="box4">New box 4</div>
<div id="box5">New box 4</div>
<div id="box6">New box 4</div>
<div id="box7">New box 2</div><input type="button" value="add a box" onclick="add_box(1)">
<div id="box8">Whatever</div><input type="button" value="add a box" onclick="add_box(2)">
<div id="box9">Whatever</div><input type="button" value="add a box" onclick="add_box(3)">

Execution order inside for loop - jQuery

I am generating a dynamic div using a for loop and I was surprised by the output. The code looks as follows:
for(continent in CityList)
{
$('<div id="'+continent+'Display"><div class="row top-buffer">').appendTo('#Display');
currentcontinent = CityList[continent];
for(city in currentcontinent) {
$('<div class="col-md-4"><div class="thumbnail"><div class="caption"><h3>'+CityList[continent][city]['EngName']+'</h3><a data-name="'+city+'" href="#'+city+'"> <img src="'+CityList[continent][city]['src']+'" style="min-height:250px;height:250px;"/></a></div></div></div>').appendTo('#Display');
}
$('</div></div>').appendTo('#Display');
}
The output html using
alert($("div#Display").clone().html());
is:
<div id="AmericaDisplay"><div class="row top-buffer"></div></div><div class="col-md-4"><div class="thumbnail"><div class="caption"><h3>Boston</h3><a data-name="Boston" href="#Boston"> <img src="undefined" style="min-height:250px;height:250px;"></a></div></div></div>...
As you can see there are two </div></div> after the first append, but I expect those to be at the end of the html since I call them last in the for loop. Is there any reason for the loop to behave like this?
when you parse a tag with jQuery it creates a DOM object, which includes closing tags as well. If you want $('<div class="col-md-4"><div class="thumbnail">... to go inside $('<div id="'+continent+'Display"><div class="row top-buffer">') you need to append it to '#' + continent + 'Display' like so:
$('<div class="col-md-4"><div class="thumbnail"><div class="caption"><h3>'+CityList[continent][city]['EngName']+'</h3><a data-name="'+city+'" href="#'+city+'"> <img src="'+CityList[continent][city]['src']+'" style="min-height:250px;height:250px;"/></a></div></div></div>').appendTo('#' + continent + 'Display');
also, get rid of $('</div></div>').appendTo('#Display');, it serves no purpose when parsing elements with jQuery.
The code $('<div id="Display"><div class="row top-buffer">') will create jquery object so if you append it, the html will look like this
<div id="Display">
<div class="row top-buffer">
</div>
</div>
if you want to append the </div></div> in the end then save all the html in a variable and append it in the end
for(continent in CityList){
var data = '<div id="'+continent+'Display"><div class="row top-buffer">';
currentcontinent = CityList[continent];
for(city in currentcontinent) {
data += '<div class="col-md-4"><div class="thumbnail"><div class="caption"><h3>'+CityList[continent][city]['EngName']+'</h3><a data-name="'+city+'" href="#'+city+'"> <img src="'+CityList[continent][city]['src']+'" style="min-height:250px;height:250px;"/></a></div></div></div>'
}
data += '</div></div>';
$(data).appendTo('#Display'); // or ('#Display').append(data);
}

Categories

Resources