Javascript JQuery append does not work - javascript

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.

Related

Get id in jQuery and use it

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>

Loop through json received from wikipedia api using .each()

Trying to loop through json received from wikipedia api using .each(), but it returns undefined on everything. What have I missed?
Here is codepen: https://codepen.io/ekilja01/pen/pRerpb
Here is my HTML:
<script src="https://use.fontawesome.com/43f8201759.js">
</script>
<body>
<h2 class="headertext">WIKIPEDIA <br> VIEWER </h2>
<div class="row">
<div class="col-10-md">
<input class="searchRequest blink_me" id="cursor" type="text" placeholder="__"></input>
</div>
<div class="searchIcon col-2-md"> </div>
</div>
<div class="results">
</div>
</body>
Here is jQuery:
$(document).ready(function() {
var icon = "<i class='fa fa-search fa-2x'></i>";
$('#cursor').on("keydown", function() {
$(this).removeClass("blink_me");
var searchIcon = $(".searchIcon");
searchIcon.empty();
if ($(".searchRequest").val().length > 0) {
searchIcon.append(icon);
}
searchIcon.on("click", function() {
console.log("clicked!");
var search = $(".searchRequest").val();
var url = "https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=" + search + "&format=json&callback=?";
$.ajax({
dataType: "jsonp",
url: url,
success: function(data) {
$("ul").empty();
$.each(data[1], function(value, index) {
$(".results").append("<ul><li><h3>" + data[1][index] + "</h3><p>" + data[2][index] + " Read More...</p></li></ul>");
});
searchIcon.empty();
}
});
});
});
});
in $.each(data[1], function(value, index) you've to switch value to index and viceversa like this $.each(data[1], function(index, value)
For reference: jQuery.each()
I have gone through your code. Please change
$.each(data[1], function(value, index) to
$.each(data[1], function(index, value)
This is a bit of a crude way of going about this but one way I verify that the information is what it should be is to iterate with a nested for loop.
It may not solve the immediate problem, but its a way to go to understand how this thing is working.
for(var i = 0; i < data.length; i++)
{
///alert(data[i]); //See what data you're passing to WIKIPEDIA's API
for(var j = 0; j < data[i].length; j++)
{
//See what data WIKIPEDIA's API is passing to you
//From here, you can determin which value (j) to us (e.g. j = 0 is the Title)
//Once you hav that, you can use it to append to you 'results' class
alert('i = ' + i + '| j = ' + j);
alert('data = ' + data[i][j]);
///////////
//$(".results").append("<ul><li><h3>" + data[i][j] + "</h3><p>"
//+ data[i][j] + "<a href=\"" + data[i][j]
//+ "\"> Read More...</a></p></li></ul>");
///////////
}
While this is not a fix for your problem (fixed by Roberto Russo), there is something else going on that's probably not intended: you register searchIcon.on("click") callback inside $('#cursor').on("keydown") callback. What this means is that every time keydown event fires on the $(#cursor) element, a new listener will be added to searchIcon.on("click"). That's why you see "clicked!" printed multiple times for just one click. Also, if you check the network log, you'll see multiple requests sent to the wiki api for the same reason.
I'd suggest moving searchIcon.on("click") outside $('#cursor').on("keydown").
You need to swap value and index to this:
$.each(data[1], function(index, value)
Make sure whenever you call $.each() function, you cannot change the order of the arguments.
Example : $.each(arryName, function(index, value)
index = The index associates with arryName
value = The value associates with the index

JQuery removing buttons dynamically

I am adding buttons based on an array. The problem I am having is that every time I add another name to the array, it prints out all the buttons not just the one I added. I am wondering how would I erase all the old buttons before I add the array of buttons.
Here is my code
socket.on('usernames', function(data){
console.log(data);
for(i=0; i <data.length; i++){
// html += data[i] + "<br/>";
$input = $('<input type="button"/></br>');
$input.val(data[i]);
$input.appendTo($("#contentWrap"));
}
// $users.html(html);
});
Below is an image. Test is the name of the first button and every time I add a new button it prints the entire array again. Is there a way to delete the old buttons?
Use the empty() method before you loop:
socket.on('usernames', function(data){
var $contentWrap = $("#contentWrap").empty();
for (i = 0; i < data.length; i++) {
$input = $('<input type="button"/></br>');
$input.val(data[i]);
$input.appendTo($contentWrap);
}
});
Also note that you can improve performance and tidy the code by creating a single HTML string and setting the html() property to only require one DOM call. Try this:
socket.on('usernames', function(data){
var html = data.map(function(value) {
return '<input type="button" value="' + value + '"/></br>'
}).join('');
$('#contentWrap').html(html);
});
You can call .empty() on the parent element before appending the elements again.
$("#contentWrap").empty();
for(i=0; i <data.length; i++){
// html += data[i] + "<br/>";
$input = $('<input type="button"/></br>');
$input.val(data[i]);
$input.appendTo($("#contentWrap"));
}

Display dynamic number of Divs inside another Div using Jquery

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);

Jquery-Mobile: Append the data to the non-native select option menu

I have a problem with adding the data to non-native select option menu on Jquery Mobile. Here's my code :
in html :
<select id="my-select" data-native-menu="false"></select>
in javascript :
var len = results.rows.length;
var s = '';
for (var i=0; i<len; i++){
$('#my-select')
.html($("<option></option>")
.attr("value",results.rows.item(i).id)
.text(results.rows.item(i).name));
}
So, if i delete the "data-native-menu="false"", that code is works perfectly. Whats wrong with my code ?
Thank you
You need to tell jQM to refresh/rebuild the widget any time you change the options within the selectmenu:
http://api.jquerymobile.com/selectmenu/#method-refresh
$('#my-select').selectmenu( "refresh", true );
FYI. by using html($("")...) within the for loop, you are overwriting the all options each time. Instead, use .empty() to clear existing options before the loop, and use append() to add the new ones.
To make it more efficient, create a string of all options and append them to the DOM once after the loop:
var opts = '';
for (var i=0; i<len; i++){
opts += '<option value="' + results.rows.item(i).id + '">' + results.rows.item(i).name + '</option>';
}
$('#my-select').empty().append(opts).selectmenu( "refresh", true );

Categories