I have developed following javascript code,
for (var x = 0; x < address.length; x++) {
var dynamic_address = "<div class='col-lg-6 col-md-6 col-sm-6 col-xs-12 mob-no-pad'>" +
"<div class='address-blk'><span>1</span><p class='store-name'>" + storename[x] + ",</p>" +
"<address>" + address[x] + "</address>" +
"<p>Sent to : <a href=''>Email</a> | <a href=''>Text</a> | <a href=''>Get directions</a></p> </div></div>";
$("#location-address").html(dynamic_address);
}
<div id="location-address"></div>
My question is when I run this code final address of the address array and final value of the storename array are displayed in location-address div (only one div). Address.length has dynamic value. How can I display all three(any number) divs, Not just one div?
The issue is because you're using the html() method which will overwrite any previous value in the element, hence only the last element of the loop is shown. You need to use append() instead:
$("#location-address").append(dynamic_address);
If needed, you may also need to use empty() to clear the content of #location-address before running through the loop to update the content.
var dynamic_address="";
for (var x = 0; x < address.length; x++) {
dynamic_address += "<div class='col-lg-6 col-md-6 col-sm-6 col-xs-12 mob-no-pad'>" +
"<div class='address-blk'><span>1</span><p class='store-name'>" + storename[x] + ",</p>" +
"<address>" + address[x] + "</address>" +
"<p>Sent to : <a href=''>Email</a> | <a href=''>Text</a> | <a href=''>Get directions</a></p> </div></div>";
}
$("#location-address").html(dynamic_address);
Related
I generate with a loop for every section on my html site a list element.
<section class="page1" id="name1"></section>
<section class="page2" id="name2"></section>
<section class="page3" id="name3"></section>`
In my jQuery function, see below, I create for every section a link.
for( var i = 0; i < sections.length; i++){
_addClass(sections[i], "ops-section")
sections[i].dataset.index = i + 1;
sections[i].id=document.getElementById(sections[i].id);
if(settings.pagination == true) {
paginationList += '<li><a data-index="'
+ (i + 1) + '" href="#' + (i + 1)
+ '"></a><p class="lead">'
+ sections[i].id + '</p></li>';
}
with sections[i].id=document.getElementById(sections[i].id); I want to read out the text behind id, for example: name1. name2, name3 and so on. I want to add the id-name then as text between the p-tag, so that I get the following list element:
<li><a data-index="1" href="#1" class="active"></a><p class="lead">name1</p></li>
but actually I get this:
<li><a data-index="1" href="#1" class="active"></a><p class="lead">[object HTMLElement]</p></li>
Where is my mistake? What's wrong?
I think you are going about this the wrong way and making the code harder to follow in the process. Your issue is that you are concatenating an entire DOM node, rather than a value of one of the attributes of that node because of this line:
sections[i].id = document.getElementById(sections[i].id)
.getElementById() returns a DOM node so later, when you use:
sections[i].id
You aren't referring to the id at all, you are referring to the entire element returned from:
document.getElementById(sections[i].id)
You don't really even need any of that entire line anyway.
If you use a .forEach() loop to enumerate the section elements, you won't have to set up or manage a counter.
If you create the elements via the DOM API (instead of building a string), you can configure each element much more simply and get out of concatenation hell.
Look at the solution below, it's a little more overall code than your solution, but it is so much cleaner and easier to follow.
// Get the section elements into an array
var theSections = Array.prototype.slice.call(document.querySelectorAll("section[class^='page']"));
// Loop over the elements in the array
theSections.forEach(function(section, index){
// Create li, a and p elements
var li = document.createElement("li");
var a = document.createElement("a");
var p = document.createElement("p");
// Configure each new element
a.setAttribute("data-index", index + 1);
a.href = index + 1;
a.classList.add("active");
p.classList.add("lead");
p.textContent = section.id;
// Inject new elements into the DOM
li.appendChild(a);
li.appendChild(p);
document.body.appendChild(li);
// Just for testing
console.log(a, p);
});
<section class="page1" id="name1"></section>
<section class="page2" id="name2"></section>
<section class="page3" id="name3"></section>
Why is it not working?
First, document.getElementById retrieves an HTML element. Then, you are overriding the id in sections[i].id with the HTML element, resulting in [object HTMLElement].
Solution
As suggested by Liora Haydont, simply remove the line sections[i].id=document.getElementById(sections[i].id);.
for( var i = 0; i < sections.length; i++){
_addClass(sections[i], "ops-section")
sections[i].dataset.index = i + 1;
if(settings.pagination == true) {
paginationList += '<li><a data-index="'
+ (i + 1) + '" href="#' + (i + 1)
+ '"></a><p class="lead">'
+ sections[i].id + '</p></li>';
}
In your code you're attaching an entire HTML element to the section id which is why you're getting that error. Scott just beat me with his answer, but I'm in agreement with him. Using forEach will allow you to make your life a little easier.
In this example I'm also using template literals to create the HTML. YMMV, however.
const sections = document.querySelectorAll('section');
const out = document.getElementById('out');
const settings = {
pagination: true
}
sections.forEach((section, i) => {
const index = i + 1;
const id = section.id;
section.classList.add('ops-section');
section.dataset.index = index;
if (settings.pagination) {
const para = `<p class="lead">${id}</p>`;
const li = `<li><a data-index="${index}" href="#${index}" class="active">test</a>${para}</li>`;
out.insertAdjacentHTML('beforeend', li);
}
});
<section class="page1" id="name1">section1</section>
<section class="page2" id="name2">section2</section>
<section class="page3" id="name3">section3</section>
<ul id="out"></ul>
Why not using JQuery ? This is a small demo on how you can get the id attribute of your section and use it in the JQuery code:
$(document).ready(function() {
$('section').each(function( key, value ) {
// alert($(this).attr('id') + " - " + key + ": " + value );
$('pagination').append("<p class='lead'>* <a data-index='"+ key +"' href=#></a>" + $(this).attr('id') + '</p>');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="page1" id="name1"></section>
<section class="page2" id="name2"></section>
<section class="page3" id="name3"></section>
<pagination></pagination>
I have multiple buttons that when clicked, should copy the text from a specific div. However, because the divs have IDs that are repeated on the page several times (due to being in a loop), I am unable to make sure the text that is copied is from the closest div with that ID.
I am using Clipboard.js, but it is not a requirement if I can get the same functionality with a normal function.
My HTML code looks like this so far... but remember, it's in a dynamically-generated loop. so "shortcodesTable" and each "shortcode1" div will be repeated.
<div id="shortcodesTable">
<h4>Short Codes</h4>
<div>
<h5>Shortcode 1</h5>
<button class="copy-btn" data-clipboard-target="#shortcode1">Copy</button>
<div id="shortcode1"><pre><code> ... ... ... </code></pre></div>
</div>
<div>
<h5>Shortcode 2</h5>
<button class="copy-btn" data-clipboard-target="#shortcode2">Copy</button>
<div id="shortcode2"><pre><code> ... ... ... </code></pre></div>
</div>
and my JS is the basic function from the clipboard.js documentation:
var clipboard = new Clipboard('.copy-btn');
clipboard.on('success', function(e) {
console.info('Copied Text:', e.text);
e.clearSelection();
});
clipboard.on('error', function(e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
});
For more clarification, my code is looping through an api of credit cards and populating content for each one. This table that needs the copy functionality is within that loop. It looks like this
for (var i = 0; i < arrayLength; i++) {
var 1 = blah;
var 2 = blah2;
$('<div>'+
'<div>'+
var 1 +
'</div>' +
'<div>'+
var 2 +
'</div>' +
'<div id="shortcodesTable">'+
'<h4>Short Codes</h4>'+
'<div>'+
'<h5>Shortcode 1</h5>'+
'<button class="copy-btn" data-clipboard-target="#shortcode1">Copy</button>'+
'<div id="shortcode1"><pre><code> ... ... ... </code></pre></div>'+
'</div>'+
'<div>'+
'<h5>Shortcode 2</h5>'+
'<button class="copy-btn" data-clipboard-target="#shortcode2">Copy</button>'+
'<div id="shortcode2"><pre><code> ... ... ... </code></pre></div>'+
'</div>'+
'</div>'+
'</div>').appendTo('.some-div');
}
You could use a counter variable or simply the index of your loop to give your elements unique ids.
As the W3 states:
The value must be unique amongst all the IDs in the element's home subtree and must contain at least one character. The value must not contain any space characters.
https://www.w3.org/TR/html5/dom.html#the-id-attribute
Working example using template strings
function createShortcodeTables(iterations, root) {
let html = ''
for (let i = 0; i < iterations; i++) {
html += `
<div id="shortcodesTable-${i}">
<h4>Short Codes</h4>
<div>
<h5>Shortcode 1</h5>
<button class="copy-btn" data-clipboard-target="#shortcode-${i}">Copy</button>
<div id="shortcode-${i}"><pre><code> Text of shortcode #${i} </code></pre></div>
</div>
<div>
<h5>Shortcode 2</h5>
<button class="copy-btn" data-clipboard-target="#shortcode-${i}-${i}">Copy</button>
<div id="shortcode-${i}-${i}"><pre><code> Text of shortcode #${i}-${i} </code></pre></div>
</div>
</div>
`
}
root.innerHTML = html
}
const rootElement = document.querySelector('.root')
createShortcodeTables(10, rootElement)
const clipboard = new Clipboard('.copy-btn');
clipboard.on('success', function(e) {
console.info('Copied Text:', e.text);
e.clearSelection();
});
clipboard.on('error', function(e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
});
Example on JSFiddle
Edit:
... +
'<button class="copy-btn" data-clipboard-target="#shortcode1">Copy</button>' +
'<div id="shortcode1"><pre><code> ... ... ... </code></pre></div>' + ...
in your data-clipboard-target and the corresponding id attributes you have to add your index variable i. To do that you have to close your string and concatenate your index variable to it, otherwise it would print you the literal character i.
... +
'<button class="copy-btn" data-clipboard-target="#shortcode-' + i + '">Copy</button>' +
'<div id="shortcode-' + i + '"><pre><code> ... ... ... </code></pre></div>' + ...
Note the single quotes I've added inside your HTML attributes to close the string literal.
More conceptual example:
var arr = [1, 2, 3, 4, 5];
for (var index = 0; index < arr.length; index++) {
console.log('<div id="some-id-' + index + '"></div>');
}
Working JSFiddle with string concatenation.
I am attempting to dynamically add some content to some content that was just dynamically added. I want to put a bunch of OPTION items into a SELECT that I just added. The SELECT is added along with some code from an external .php file (see below). This div appears just fine. However, the contents that I attempt to add inside the SELECT does not appear. My SELECT is simply empty. I get no errors. The console output in the code below checks out and prints what I expect it to.
Here is the Javascript code:
$.get("test-new-product-modal.php", function(data){
$(".modal-body").html(data);
});
$divSelect = $("#product-list");
for(var i = 0; i<(arrayProductTypes.length); i++){
$divOption = $("option", {'value' : i});
$divOption.html(arrayProductTypes[i][0]);
$divSelect.append($divOption);
console.log("Product ID at "+i+" is: "+arrayProductTypes[i][0]);
}
Here is the .php file that I add HTML from:
<div class="container-fluid no-padding">
<div class="col-sm-6 col-md-6 col-lg-6">
<h4>Välj en produkt.</h4>
<select id="product-list" class="form-control">
<!-- <option>DRA</option>
<option>DRB</option> -->
</select>
<div class="divider-line"></div>
</div>
<div class="col-sm-6 col-md-6 col-lg-6">
<p class="product-add-description">Text.</p>
</div>
</div>
Try jQuery add() method
$.get("test-new-product-modal.php", function(data){
$(".modal-body").html(data);
});
$divSelect = $("#product-list");
for(var i = 0; i<(arrayProductTypes.length); i++){
$divOption = $("option", {'value' : i});
$divOption.html(arrayProductTypes[i][0]);
$divSelect.add($divOption);
console.log("Product ID at "+i+" is: "+arrayProductTypes[i][0]);
}
you can find the doc here
Working jsFiddle of something similar to what you are expecting:
It's a lot simpler to add in a HTML element like this:
.append('<option value="' + array[i] + '">' + array[i] + '</option>');
I believe its how you declare your option object try this:
$divOption = $("<option>").attr('value',i);
You are not adding options correctly. If you want to add options like jquery object you can do this
for (var i = 0; i < (arrayProductTypes.length) ; i++) {
$divOption = $('<option></option>').val(i).html(arrayProductTypes[i][0])
$divSelect.append($divOption);
console.log("Product ID at " + i + " is: " + arrayProductTypes[i][0]);
}
This line $divOption = $("option", {'value' : i}); doesn't return the option object instead it is returning an empty array so you need to use
$('<option></option>').val(i).html("somehtml") to return an option.
The first item in my list group has it's '< /a>' removed upon insertion into the page and my question is why and how do I fix this? If I console the html generated before and after the insertion the missing tag is there.
Here is the generator code:
function ObjMatched(item1, item2) {
this.item1 = item1;
this.item2 = item2;
}
var obj_list = '<div class="list-group>';
for (var i = 0; i < Obj.length;i++) {
if (Obj[i].item1 == selection) {
ObjMatched.item1 = Obj[i].item1;
ObjMatched.item2 = Obj[i].item2;
obj_list += '<a href="#" class="list-group-item" data-item1="' + ObjMatched.item1 + '" data-item2="' + ObjMatched.item2 + '" >' + ObjMatched.item1 + ', ' + ObjMatched.item2 + '</a>';
}
}
obj_list += '</div>';
$("#obj_block").append(obj_list);
Here is the HTML output:
<div id="obj_block">
<div class="list_group">
<a href="#" class="list-group-item" data-item1="mary" data-item2="smith">mary, smith
tom, jones
dirty, harry
</div>
</div>
As a consequence the first item does not appear as part of the list within the web browser and is not clickable. I have tried replacing append() with html() to no avail.
I have tested this in Chrome, Safari and Firefox all with the same result.
What am I doing wrong?
You're not closing the quotes on your first div:
var obj_list = '<div class="list-group>';
Change it to:
var obj_list = '<div class="list-group">';
And it will work. It's happening because the first apostrophe is closing this div and making the anchor tag invalid.
<div id="tagTree1" class="span-6 border" style='width:280px;height:400px;overflow:auto;float:left;margin:10px; '>
<a class="tabheader" style="font-size:large">Data Type</a><br />
<div class="pane">Refine search by Data Type</div>
</div>
Above div(tagTree1) is present in a division ad.
<div id="newtagTree1" class="span-6 border" style='width:200px;height:400px;overflow:auto;float:left'>
<a class="tabheader"><strong>Geographic Location</strong></a><br />
<div class="pane"><strong>Refine search by geographic location</strong></div>
</div>
newTagTree1 division is present in another division search. But both have the same functionality to generate children divisions within them, which is written in a js file. All the children division generated dynamically in js file. Both of them uses same function to generate children divs. I am facing problem when i am using them in same page. If one works fine then the other doesn't. Can any one say me about the mistake i am doing in this?
Thanks in advance.
$.getJSON('/api/TagsApi/Children?id=800002', function (data) {
//$(tagDiv).empty();
$.each(data, function (i, item) {
$("#tagTree1").append(tagTabBuilder(item));
});
$("#tagTree1").tabs("#tagTree1 div.pane", { api: true, tabs: 'a', effect: 'slide', onClick: buildChildren, initialIndex: 0 });
});
function tagTabBuilder(tagData) {
var str = "<input type='checkbox' name='tagchkbox[]' value='" + tagData.ID + "' onClick='startQuery()' /><a class='tabheader '>" + tagData.NAME;
if (tagData.count == 0) {
str += " (<span class='el_count' id='t" + tagData.ID + "'>" + tagData.count + "</span>)" + "</a><br/>";
} else {
str += " (<span class='el_count' id='t" + tagData.ID + "'><strong>" + tagData.count + "</strong></span>)" + "</a><br/>";
}
str += "<div id='tid-" + tagData.ID + "' class='pane tag'><!--Loading subtags. . .<img src='/assets/modules/gaiaModule/shared/images/load-small.gif' />--></div>";
return str;
}
My guess would be that when they generate child divs, they're generating them with the same ID scheme. Thus, either of them can generate child divs just fine by itself, but when both of them are included, there is ID collision. The answer is to modify the child generation code to, for example, include the id of the parent div as the first portion of the id of the child div.
Alternately, if you dont' need them for other portions of the javascript, leave the child div ids out entirely. In general, I find that it's better to avoid the id attribute in generated nodes, and instead use classes or the like.