javascript : my appendChild only works once - javascript

I have a <div id="incontent"></div> in which I am generating elements using javascript... here is my script :
var lastId = 0; // initialise ID
function MyFunction( var1, var2, var3) {
const incontent = document.getElementById('incontent');
incontent.innerHTML+= var1 + var2 + (var3 ? ' (var3=' + var3 + ')' : '');
if (var3 === 'descforalink') {
incontent.innerHTML += `<div class="contentLink"><p>a link</p></div></div>`;
}
}
//manages the click on possible
document.getElementById('incontent').addEventListener('click', function (e) {
lastId++ ; // for a different ID
});
// element in which to instantiate the contentDATA for another rendering...
const contentDATA = document.getElementById('contentDATA');
// contentDATA content is received
contentDATA.addEventListener(MyMouv.Descperso, ({ data }) => {
var divques1 = '<div class="contentDesc col-12"><p>';
var divques2 = '</p>';
var divques3 = '</div>';
var contentallbtns = '';
var contentbtnsbefore = '<div class="col-12 contentLink">';
var contentbtnsafter = '</div></div>';
MyFunction('', divques1 + data.text + divques2 , data.var3, divques3);
// if actions buttons/links
if (data.actions) {
var btns = '';
for (var i = 0; i < data.actions.length; i++) { if (i> 0) {btns += ' ';}
let act = data.actions[i];
btns += '<a class="mybtn"' + ' data-val="' + act.value + '">' + act.title + '</a>';
contentallbtns = contentbtnsbefore + btns + contentbtnsafter;
}
MyFunction('',contentallbtns);
}
//building tags
var startB = document.createElement('section');
var myiddesc = 'iddesc-'+lastId ;
startB.setAttribute('id', myiddesc );
startB.setAttribute('class', 'thesection');
document.getElementById('incontent').appendChild(startB);
var startB2 = document.createElement('div');
startB2.setAttribute('class', 'container');
startB.appendChild(startB2);
var startB3 = document.createElement('div');
startB3.setAttribute('class', 'row MyRow');
startB2.appendChild(startB3);
document.querySelector('div.MyRow').appendChild(document.querySelector('div.contentDesc'));
document.querySelector('div.MyRow').appendChild(document.querySelector('div.contentLink'));
});
This generates the first time a structure of this type:
<section id="iddesc-0" class="thesection">
<div class="container">
<div class="row MyRow">
<div class="contentDesc">
<p>Hello World</p>(var3=descforalink)
</div>
<div class="contentLink">
<p>a link</p>
</div>
</div>
</div>
</section>
This is what I want ... but when another section is created, with actions, this structure appears:
<section id="iddesc-0" class="thesection">
<div class="container">
<div class="row MyRow">
<div class="contentDesc">
<p>Hello World</p>(var3=descforalink)
</div>
<div class="contentLink">
<p>a link</p>
</div>
</div>
</div>
</section>
<div class="contentDesc">
<p>Hello World</p>(var3=descforalink)
</div>
<div class="contentLink">
<a class="mybtn" data-val="banana">banana</a><a class="mybtn" data-val="orange">orange</a>
</div>
<section id="iddesc-1" class="thesection">
<div class="container">
<div class="row MyRow">
</div>
</div>
</section>
so the appendchild() on document.querySelector('div.MyRow').appendChild(document.querySelector('div.contentDesc')); document.querySelector('div.MyRow').appendChild(document.querySelector('div.contentLink'));only works once ... how can i change that? Always place my div div class="contentDesc" and class="contentLink" in the div class="row MyRow" ? Thank you for your help...

If you use appendChild on an element that's already in the DOM, it moves the element from where it is to the new location. It doesn't make a copy of it.
If you want to make a copy and then append the copy, use cloneNode(true):
document.querySelector('div.MyRow').appendChild(
document.querySelector('div.contentDesc').cloneNode(true)
);
document.querySelector('div.MyRow').appendChild(
document.querySelector('div.contentLink').cloneNode(true)
);
but, I'm not sure you really want to do that. You're creating a new section which you're referencing a startB but then you aren't appending startB to anything. Perhaps you meant to append it instead of one of the above.

Related

How to load data from two separate XML files?

I'm trying to load XML data from two separate files. On page load, I want to show data of one file by default. There would be a button on the page to display data from next file.
After load XML files, I need to combine all popup boxes with looping. But my code does not support to loop that popups. how can I implement the below code? Please help.
Here is my code.
$(document).ready(function(){
$.ajax({
type:"GET",
url:"contact.xml",
dataType:"xml",
success:xmlParser2
});
});
function xmlParser2(xml){
var items = $(xml).children().children();
items.sort(function() { return 0.5 - Math.random() });
xml = $(xml).children();
let i = 0;
let total = $(xml).children().length;
items.each(function (idx,index,item) {
let expireArray = $(this).attr('expires').split('/');
const expireDate = `${expireArray[2]}${expireArray[1]}${expireArray[0]}`;
const now = new Date(),
nowDate = `${now.getFullYear()}${(now.getMonth()+1) <10 ? '0'+(now.getMonth()+1): (now.getMonth()+1)}${now.getDate()}`;
if (nowDate > expireDate) {
return;
}
let tag = $(this).prop("tagName")+index;
let nextIdx = idx + 1;
let prevIdx = idx - 1;
//to make cyclic
nextIdx = nextIdx == total ? 0 : nextIdx;
prevIdx = prevIdx == -1 ? (total -1) : prevIdx;
let image = '<img style="background-image:url(' + $(this).find("image").text() + ')"' + '" />';
let image2 = '<div><img src="' + $(this).find("image").text() + '" width="100%" alt="' + '" />' + '</div>';
let head = '<div>' + $(this).find("head").text() + '</div>';
let html = `<div class="col-sm-4 random" id="random">
<div class="thumbnail randomdiv3" id="border" >
<a href="#${tag + idx}" id="openModalBtn">
<div>${image}</div>
<h5>${head}</h5>
</a>
</div>
</div>`;
let popup = `<div id="${tag + idx}" class="overlay">
<div class="popup">
‹
›
<h6>${head}</h6>
<a class="close" href="#">×</a>
<div>${image2}</div>
</div>
</div>`;
i++;
if(i <= 3) {
$("#xmldata").append(html);
$("#image_boxes").append(html);
}
else{
$("#rest_image_boxes").append(html);
}
$("#popup").append(popup);
});
var hash = window.location.hash;
if(hash != ""){
$("a[href='"+hash+"']").find("h5").click();
}
$("a[id='openModalBtn']").click(function(){
window.location.hash = $(this).attr("href");
});
}
function xmlParser3(xml){
var items = $(xml).children().children();
items.sort(function() { return 0.5 - Math.random() });
xml = $(xml).children();
let i = 0;
let total = $(xml).children().length;
items.each(function (idx,index,item) {
let expireArray = $(this).attr('expires').split('/');
const expireDate = `${expireArray[2]}${expireArray[1]}${expireArray[0]}`;
const now = new Date(),
nowDate = `${now.getFullYear()}${(now.getMonth()+1) <10 ? '0'+(now.getMonth()+1): (now.getMonth()+1)}${now.getDate()}`;
if (nowDate > expireDate) {
return;
}
let tag = $(this).prop("tagName")+index;
let nextIdx = idx + 1;
let prevIdx = idx - 1;
//to make cyclic
nextIdx = nextIdx == total ? 0 : nextIdx;
prevIdx = prevIdx == -1 ? (total -1) : prevIdx;
let image = '<img style="background-image:url(' + $(this).find("image").text() + ')"' + '" />';
let image2 = '<div><img src="' + $(this).find("image").text() + '" width="100%" alt="' + '" />' + '</div>';
let head = '<div>' + $(this).find("head").text() + '</div>';
let html = `<div class="col-sm-4 random" id="random">
<div class="thumbnail randomdiv3" id="border" >
<a href="#${tag + idx}" id="openModalBtn">
<div>${image}</div>
<h5>${head}</h5>
</a>
</div>
</div>`;
let popup = `<div id="${tag + idx}" class="overlay">
<div class="popup">
‹
›
<h6>${head}</h6>
<a class="close" href="#">×</a>
<div>${image2}</div>
</div>
</div>`;
$("#rest_image_boxes").append(html);
$("#popup").append(popup);
});
var hash = window.location.hash;
if(hash != ""){
$("a[href='"+hash+"']").find("h5").click();
}
$("a[id='openModalBtn']").click(function(){
window.location.hash = $(this).attr("href");
});
}
$('#myButton1').click(function(e){
e.preventDefault();
$.ajax({
type:"GET",
url:"data.xml",
dataType:"xml",
success:xmlParser3
});
});
<div class="row" id="xmldata"></div>
<section>
<div class="container">
<input type="button" value="View All" id="myButton1" class="reveal" style="float: right;" onclick="toggler('toggle_container');">
<div id="toggle_container" class='hide'>
<div class="block">
<div class="row" id="rest_image_boxes"></div>
</div>
</div>
</div>
</section>
<section id="popup"></section>
Plunker

How to get the ID of a panel when clicked, when panel ID is dynamically generated

I am building panels using Razor(the number of many items returned varies), and then when a panel is clicked, I need the clicked panelID so I can get more data about that panel clicked. New to jquery/javascript. I have captured panelID so I know that this is being assigned to the panel, as well to paneltextID.
Below is the div containing the panels and the javascript:
#for (int i = 0; i < #rows; i++)
{
<div class="row">
#for (int j = 0; j < #cols; j++)
{ if(panelCount <= totalCount){
sqlCommand = "SELECT FullDescription AS Description FROM shmr.RemoteSQLDatabases WHERE DBID1 = " + #panelCount + " ORDER BY DBName";
//<p>#sqlCommand</p>
//This grid contains the information for the specific database of this panel
var Grid2 = new WebGrid(DB.Query(sqlCommand));
//var DBName = DB.Query(sqlCommand);
DBName = DB.QueryValue("SELECT DBName FROM shmr.RemoteSQLDatabases WHERE DBID1 = " + #panelCount + " ORDER BY DBName");
string panelID =null;
panelID = "panel" + panelCount.ToString();
// <p>Panel is #panelID</p>
<div class="col-md-3">
<div id= #panelID class='panel panel-success', style="display: inline-block">
<div class='panel-heading text-center'><b>#DBName </b><img src="~/Images/Doctor (2).png" align="left" width="30" height="30" /></div>
<div class="panel-body m200">
#if(Grid2 !=null)
{
<text> #Grid2.GetHtml(columns:Grid2.Columns(Grid2.Column("Description")))</text>
<input type="hidden" name="paneltextID" value=#panelCount>
<p>PanelID = #panelID</p>
}
else{
<text>No data was found to display!</text>
}
</div>
<div class="panel-footer text-center">
Database status as of #DT
</div>
</div>
</div>
panelCount = panelCount + 1;
}
}
</div>
}
</div>
$(".panel").click(function () {
var panelID = $('#panelID').val();
if (panelID != null) {
alert("Panel " + panelID + " clicked! :)");
} else {
alert("PanelID is null :(");
}
});
You don't have to make it an id. Just do this:
<div class="panel panel-success" data-id=#panelId ...>
Then in your jquery you can do this:
$(".panel").click(function () {
var panelID = $(this).data('id');
if (panelID != null) {
alert("Panel " + panelID + " clicked! :)");
} else {
alert("PanelID is null :(");
}
});
The actual mistake in your code is where you look up #panelId (which shouldn't exist) in the javascript.
try setting ClientIDMode = Static of your Panel properties.

div's innerhtml content replacing the content of a div

I have a div that its content is pulled from innerhtml as shown
var users = '';
for (var i = 0; i < json.length; i++) {
users += '<strong>' + json[i].name + '</strong><br/>';
}
users_container.innerHTML = users;
}
this is the div that the innerhtml replaces its content. The content of the div only displays for some seconds and disappears.
<div id="users-container" class="inner-container">
<h3>Active users</h3>
</div>
Please how can I retain the content of the div as a header while the innerhtml contents is displayed as well. Kindly assist!
html
<div id="users-container" class="inner-container">
<h3>Active users</h3>
<div id="usersList"></div>
</div>
script
var users = '';
for (var i = 0; i < json.length; i++) {
users += '<strong>' + json[i].name + '</strong><br/>';
}
usersList.innerHTML = users;
}
You can use a specific div for the users content and keep the original content of your div.
JavaScript:
var users_div = document.getElementById("users_div");
var users = '';
for (var i = 0; i < json.length; i++) {
users += '<strong>' + json[i].name + '</strong><br/>';
}
users_div.innerHTML = users;
}
HTML:
<div id="users-container" class="inner-container">
<h3>Active users</h3>
<div id="users_div">
</div>
</div>

How to prevent auto tag closure in jQuery append()?

Because of formatting reasons I'm trying to nest every third result from my json file to be nested in a div class "row".
I figured this would be an easy thing to do but everytime I try jQuery closes my tags.
Proper layout should be
<div class="row">
<div class="four columns"></div>
<div class="four columns"></div>
<div class="four columns"></div>
</div>
Here is my code:
var sexIcon = '';
var typeIcon = '';
var divClassRow = ' <div class="row"> ';
var divClassRowEnd = ' </div><div class="row"> ';
$(document).ready(function(){
$.getJSON("scripts/pets.json", function(jsonData){
$.each(jsonData, function(object, value){
if (value.sex=='female'){
sexIcon = 'images/female-active.png';
}
else {
sexIcon = 'images/male-active.png';
};
if (value.type=='dog'){
typeIcon = 'images/dog-sm.png';
}
else {
typeIcon = 'images/cat.png';
}
$('.columns:first-child').before(divClassRow);
$.each($('.columns:nth-child(4n)'), function(){
$(this).after(divClassRowEnd);
});
$(".cards").append(
'<div class="four columns '+ value.type +' '+ value.sex +' '+ value.size +'">'+
'<div class="card-header"><h3>'+value.name+'</h3><img src="'+typeIcon+'" alt=""><img src="'+sexIcon+'" alt=""></div>'+
'<div class="card-content">'+
'<img src="'+value.photo+'" alt="">'+
'<p><b>Breed:</b> '+value.breed+'</p>'+
'<p><b>Sex:</b> '+value.sex+'</p>'+
'<p><b>Age:</b> '+value.age+'</p>'+
'<p><b>Time at Rescue:</b> '+value.time+'</p>'+
'<p> '+value.about+'</p>'+
'<br>'+
'<button class="button-primary u-full-width">Find Out more!</button>'+
'</div></div>'
); /*END APPEND*/
});/*END EACH*/
});/*END GETJSON*/
}); /* Document Ready */
Any ideas on what I can do? Or perhaps how to do this better.
Use wrapAll()
var list=$('.four');
for(var i = 0; i < list.length; i+=4) {
list.slice(i, i+4).wrapAll("<div class='row'></div>");
}
demo

Creating and Adding content dynamically

I'm creating some ul and span tags dynamically. Now, I'm trying to add content dynamically as well through a click function. The tags gets created inside a ul but the content doesn't get inserted. Here is the code for it:
<div class="main"></div>
<div class="content-list"><ul class="information"> </ul></div>
Here's the Javascript with the function and the listener:
var $contentHandler = $(".content-list");
var $mainHandler = $(".main");
var $infoHandler = $(".information");
var circleCounter = 1;
$mainHandler.click(function() {
var htmlString = "<li class='" + circleCounter + "'> <span class='circle-color'> var color = <div class='circle-color-input' contentEditable autocorrect='off'> type a color</div> ; </span> <br> <span class='circle-radius'> This is supposed to change </span> <br> <span class='circle'> This is supposed to change </span> </li>"
$infoHandler.append(htmlString);
updateList();
circleCounter++;
});
function updateList() {
var listItems = $('.information').find('li#' + circleCounter);
var len = circleCounter;
for (var i = 0; i < len; i++) {
//We create one reference. This makes looking for one element more effective. Unless we need to search for a particular element
var currentItem = circles[i];
var updateStringRadius = "var radius = " + circleCounter + ";";
var updateStringCircle = "circle (" + circleCounter + " ," + circleCounter + ", radius)";
//This is the div Item for the particular div of each element
var divItem = $(listItems[i]);
var radiusItem = divItem.find("span.circle-radius");
var circleItem = divItem.find("span.circle");
radiusItem.text(updateStringRadius);
circleItem.text(updateStringCircle);
// divItem.text(updateString);
var $circleRadiusHandler = $(".circle-radius");
}
}
Any suggestions in how to make it work. Here's a JSFiddle for that:
http://jsfiddle.net/mauricioSanchez/wL6Np/1/
Thank you kindly,
You just need to change:
var listItems = $('.information').find('li#' + circleCounter);//this searches by id
//To:
var listItems = $('.information').find('li.' + circleCounter);//this searches by class`
//And remove:
var currentItem = circles[i];
Why are you trying to edit your HTML after you've defined it? Why not use a template like this:
var listItemClass = 'someclass',
typeOfColor = 'somecolor',
radiusOne = 'someradius',
radiusTwo = 'anotherradius';
var listItem = "<li class='{0}'> \
<span class='circle-color'> var color = \
<div class='circle-color-input' contentEditable autocorrect='off'> {1}</div> ; \
</span> \
<br> \
<span class='circle-radius'>{2}</span> \
<br> \
<span class='circle'>{3}</span> \
</li>";
listItem.format(listItemClass, typeOfColor, radiusOne, radiusTwo);
With the following format definition:
String.prototype.format = String.prototype.f = function () {
var s = this,
i = arguments.length;
while (i--) {
s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
}
return s;
};
This way, you don't have to worry about finding certain elements within your predefined structure after the fact. You're just replacing certain parts with whatever you specify.

Categories

Resources