I am writing code for my e-commerce prototype website. I need to create a dynamic drop-down in one of pages in which it will receive drop-down values (like color here) from database and then I have to create drop-down using that.
I have written following code so far for this.
//Json object retrieved from database
var tmp = {"category_id":4,"product_available_quantity":20,"product_color":["Red","Blue","Yellow"],"product_condition":"new","product_description":"Branded Metal Body 4 Star","product_discount":0,"product_id":1,"product_img_url":"http://localhost:5224/ebaytester/images/s-l1600.jpg","product_name":"Motorola Cover","product_price":250,"product_shipping":"free","product_sold_quantity":10,"sub_category_id":7};
//dropdown code for color
var col_div = document.createElement('div');
col_div.className = "dropdown";
var col_btn = document.createElement('button');
var col_span = document.createElement("span");
col_span.className = "caret";
col_btn.className = "btn dropdown-toggle";
col_btn.setAttribute("type","button");
col_btn.setAttribute("data-toggle","dropdown");
text_node = document.createTextNode("Select");
col_btn.appendChild(text_node);
col_btn.appendChild(col_span);
col_div.appendChild(col_btn);
var ulst = document.createElement('UL');
ulst.className = "dropdown-menu";
var color = tmp['product_color'];
document.write(tmp['product_color'].length);
for(var i=0;i<tmp['product_color'].length;i++)
{
var list = createElement('li');
var anc = createElement('a');
text_node = createTextNode(tmp['product_color'][i]);
anc.setAttribute('href','#');
anc.appendChild(text_node);
list.appendChild(anc);
ulst.appendChild(list);
document.write(tmp['product_color'][i]);
}
col_div.appendChild(ulst);
document.getElementById("second").appendChild(col_div);
After tracking I finds out the problem is in for loop. As soon as it executes first createElement method it came out from loop abruptly. I have cross check all the syntax several times but all seems fine. I am using DOM(Document Object Model) first time so excuse me for mistakes and please tell me if I am doing something wrong.
Thanks
As soon as it executes first createElement method it came out from
loop abruptly.
Unless you have your own custom createElement method, your browser is likely to throw an error (check your dev-console) indicating that createElement method is undefined.
Replace it with document.createElement
or create your own createElement method as
function createElement( name )
{
return document.createElement( name );
}
your could be like this . if you want. problem with your create element method. this approach you can follow with appending with your class name etc.
var tmp = { "category_id": 4, "product_available_quantity": 20, "product_color": ["Red", "Blue", "Yellow"], "product_condition": "new", "product_description": "Branded Metal Body 4 Star", "product_discount": 0, "product_id": 1, "product_img_url": "http://localhost:5224/ebaytester/images/s-l1600.jpg", "product_name": "Motorola Cover", "product_price": 250, "product_shipping": "free", "product_sold_quantity": 10, "sub_category_id": 7 };
window.onload = function () {
//dropdown code for color
var div = document.querySelector("#container"),
frag = document.createDocumentFragment(),
select = document.createElement("select");
var options = tmp.product_color;
select.options.add(new Option("--Select--", "-1", true, true));
for (var i = 1; i < options.length;i++)
select.options.add(new Option(options[i], options[i]));
frag.appendChild(select);
div.appendChild(frag);
}
<div id="container">
</div>
Related
I have a json file with an items category that lists items that are currently listed via an array. This item list is updated every few hours.
ex:
{
"items": [
{
"name": "Blueberry",
"img": "website.com/blueberry.png"
},
{
"name": "Raspberry",
"img": "website.com/raspberry.png"
}
]
}
Each item in the array is given an image and description. What I want to do is for every item, create an <img src='(item image url)'> element for the image that is listed inside the item, and create a <p> element for every item for the description that is listed.
You can achieve this with JQuery with a for loop, and create the elements dynamically using the JQuery function $(...) (Tutorial here)
In the end, You'll probably end up with something like this:
// fetch the items from the url
$.getJSON("your url").then(function(response){
//cycle through all the items in the array
for(var i = 0; i < response.items.length; i++){
// create image
var image = $('<img>').attr("src", response.items[i].img);
// make sure to set the attribute using the "attr" function
// to avoid Cross Site Scripting (see the link below)
// create text element
var text = $('<p>').text(response.items[i].name);
// append the items to the container
$("container element").append(image).append(text);
}
});
About Cross Site Scripting
To dinamically create elements in Pure JavaScript you can use the document.createElement
var imagesContainer = document.createElement('div')
for(var i = 0; i < array.length; i++){
var img = document.createElement('img'),
p = document.createElement('p');
img.setAttribute("src", array[i].img);
p.appendChild(document.createTextNode(array[i].name));
imagesContainer.appendChild(img);
imagesContainer.appendChild(p);
}
i think is this you are looking for :)
I hate my life. I'm trying to complete a simple tutorial that takes an empty div and adds a bunch of cat images to it. The details of the cats are contained within arrays, which are applied to each instance of a cat while iterating through a simple numeric array.
At the bottom of the script, you'll see that I'm alerting the innerHTML of the main container div which all of these images and header tags are supposed to be appended to. While the alert dialogue shows the correct HTML, the divs that are being generated lack the img and h1 elements, despite my attempts to get them to append properly. All that seems to be getting passed through are the h1 text nodes.
Can anyone please explain why I'm not getting the results I'm looking for here:
var cats_array = [1,2,3,4,5];
var cats_names = ['Jim','Joe','Jon','Larry','Mike'];
var cats_urls = [
'https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-senior-landing-hero.ashx',
'http://i2.mirror.co.uk/incoming/article6745691.ece/ALTERNATES/s615b/Black-cat.jpg',
'https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-breed-landing-hero.ashx',
'https://www.royalcanin.com/~/media/Royal-Canin/Subpage-Hero-Images/150327_Hero_kit.ashx',
'https://s-media-cache-ak0.pinimg.com/736x/a7/92/d8/a792d8ec74bbcc819bb65c7bad1f8dee.jpg'
];
for (cat in cats_array) {
var catgame_div = document.getElementById('catgame');
var num_div = document.createElement('DIV');
var img_el = document.createElement('IMG');
var h1_el = document.createElement('H1');
var current_cats_name = cats_names[cat];
var h1_text_node = document.createTextNode(current_cats_name);
h1_el.appendChild(h1_text_node);
img_el.src = cats_urls[cat];
num_div.appendChild(img_el);
var img_parent = img_el.parentNode;
img_parent.insertBefore(h1_el, img_el);
alert(img_parent.innerHTML);
catgame_div.appendChild(num_div);
}
<div id="catgame"></div>
Thank you
I am working on the scripting a ToDo list webapp, and I am trying to take the contents of 4 text boxes to create the content of the ToDo item.
Currently, when I try to connect the elements generated from the form, I get the error TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at HTMLButtonElement.document.getElementsByClassName.onclick
I am currently using a function to create the element that I want to append to the body of the ToDo item, and I believe I am returning an element from my function. The code is posted below.
document.getElementsByClassName('modal-accept-button')[0].onclick = function () {
var formVals = {
what: document.getElementById('todo-input-what').value,
where: document.getElementById('todo-input-where').value,
when: document.getElementById('todo-input-when').value,
who: document.getElementById('todo-input-who').value,
details: document.getElementById('todo-input-details').value
};
document.getElementsByTagName('main')[0].appendChild(function () {
var fields = ["where", "when", "who", "details"];
var root = document.createElement("SECTION").className = "todo";
var title = document.createElement("H2").value = formVals.what;
var body = document.createElement("DIV").className = "todo-body"
for (var i = 0; i < fields.length; i++) {
var currentField = fields[i];
var currentVal = formVals.currentField;
body.appendChild(function () {
var p = document.createElement("P").className = "indent-wrapped";
var span = document.createElement("SPAN").class = currentField;
var text = document.createTextNode(currentVal);
span.value = currentField + ": ";
p.appendChild(span);
p.appendChild(text);
return p;
});
}
root.appendChild(title);
root.appendChild(body);
return root;
});
resetModal();
}
The variable p is not an item (HTML "Node"); it is a string.
That is, because you assigned it a string, using a sequence assignment (the last value goes all the way back) - "indent-wrapped" goes into className and then className goes into p.
Separate the item creation from the class assignment:
var p = document.createElement("P")
p.className = "indent-wrapped"
Same goes for root, title and span. They all are being assigned strings the same way.
You assign the string indent-wrapped to p, as you can see in the following snippet. So you try to call appendChild on a string instead of a node. Split the assignment, so you will first assign the node to p, and in the next statement set its classname. The same goes for the other elements (root, title, body, etc) where you try to create the element and set one of their properties in the same statement.
var p = document.createElement("P").className = "indent-wrapped";
console.log(p);
i am trying to use jQuery.data() and save an Object to my HTML-Elements. Everytime i add an list-Element to my unordered List it only saves the last object to the specific li-Element. Every other li-Elements saved data gets thrown away!
I've built a little Example. JSBin-Example
On the left, i create a List with an Object saved to it. On the right i am trying to show the data related to the Object.
Why does it only show the Object related to the last HTML-Element?
Working example:
JSBin-Example
That's because you are modifying innerHTML property of the wrapper element. What happens is in each iteration the elements are regenerated, the current elements are removed and the new elements don't have any stored data. Using innerHTML property is the worst way of modifying element contents. You just need to create a li element and append it to the wrapper element:
var random = 0;
// var testObject = [];
function addNewItem(){
random += 1;
var id = "testId" + random;
var text = "This is my " + random + ". text";
var data = {id: id, text: text};
// testObject.push(data);
// You can pass an object as the second argument
// to jQuery constructor and it calls the
// corresponding methods as setter
$('<li></li>', {
text: text + JSON.stringify(data),
id: id,
data: data
}).appendTo('#listId');
}
// bind and trigger click event
$("#add").on('click', addNewItem).click();
I changed
for(var i = 0; i < testObject.length; i++){
var listItem = "";
var id = testObject[i].id;
listItem += liStart + id + liStart2;
listItem += testObject[i].text;
listItem += liEnd;
unorderedList.innerHTML += listItem;
$("#"+id).data(testObject[i]);
}
to this in your updatelist function
//for(var i = 0; i < testObject.length; i++){
var id = testObject[testObject.length-1].id;
listItems += liStart + id+"savedData" + liStart2;
listItems += JSON.stringify($("#"+id).data());
listItems += liEnd;
//}
savedData.innerHTML += listItems;
and it fixed the issue
To help you understand my comment on the question I thought it best I'd give an example of what I meant.
I didn't have enough time to fully go through the solution but wanted to give an example of what I'd call more readable code.
I've added all variables at the top of the function. This will allow you to read and find items much quicker if you needed to alter them.
I've also merged a lot of the string values that you had into an object, namely the li element.
I've never used $.data() as an object before so wasn't really aware how I could use it to set the values in the updateSavedData() $('li'), although the console.log() does show the correct key / values.
$(document).ready(function(){
var uID = 0;
var testObject = [];
var unorderedList = $("#listId");
var savedList = $("#savedData");
var TOL = 0; //TestObjectLength
var textTemplate = "This is my [0] text!";
function addNewItem(){
uID++;
testObject.push({id: uID, text: textTemplate.replace("[0]", uID)});
TOL = testObject.length-1;
updateList();
}
function updateList(){
var li = $('<li>', { id: testObject[TOL].id, data: testObject[TOL], text: testObject[TOL].text });
li.appendTo(unorderedList);
updateSavedData(li.data());
}
function updateSavedData(li){
console.log(JSON.stringify(li));
$('<li>', JSON.stringify(li)).appendTo(savedList);
}
addNewItem();
$("#add").on('click', addNewItem);
});
Working Example
http://jsbin.com/ralizazahe/1/edit?js,console,output
Anyone that wants to progress on that please do as I'd also like to see how this could be progressed more.
Update
Taken it a step more and refactored to this
$(document).ready(function(){
var $displayList = $("#listId");
var $savedList = $("#savedData");
var textTemplate = "This is my {0} text!";
var uID = 0; //Unique ID
var data = { id: null, text: null }; //Gives a reference
function init(){
uID++;
data = { id: uID, text: textTemplate.replace("{0}", uID) };
}
function addNewItem(){
init();
$('<li>', data).appendTo($displayList);
updateSavedData(data);
}
function updateSavedData(li){
$('<li>', li).appendTo($savedList);
}
addNewItem();
$("#add").on('click', addNewItem);
});
http://jsbin.com/bajekagoli/1/edit?js,console,output
I created some buttons dynamically based on loop over an array of names, then I want to add rollover actions on these buttons, but the alert() in this code always prints the name of the last item (black).
I tried using eval() on that alert() part but it didn't make any difference.
I expect it to return red, green or black depending on which button I hover the mouse.
<div id="channels_buttons_container">
</div>
<script>
channels_array = ["red", "green", "black"];
for(var i = 0; i < channels_array.length; i++) {
loop_channel_name = channels_array[i];
// append an element inside the container
var new_button_element = document.createElement("span");
new_button_element.id = 'channel_button_'+loop_channel_name;
new_button_element.innerHTML = '<br>BLA BLA';
document.getElementById('channels_buttons_container').appendChild(new_button_element);
// try to add rollover actions on the new button
document.getElementById('channel_button_'+loop_channel_name).onmouseover = function(){
alert('Rollover '+loop_channel_name);
}
}
</script>
the code it's ok but when you use "loop_channel_name" take the last element of array. You must pass the actual element (this):
document.getElementById('channel_button_'+loop_channel_name).onmouseover = function(){
alert('Rollover '+this.id);
}
Example
loop_channel_name is initialized as a global variable because you didn't use the var keyword. Try var loop_channel_name instead of just loop_channel_name. When you initialize loop_channel_name on the first iteration of the for loop you are creating it as a global variable and on subsequent iterations you are just updating that instead of creating a new reference. By referring to loop_channel_name in the alert you are referencing the global variable which was updated to black on the last iteration of the loop, hence it always alerting black.
Example
<div id="channels_buttons_container">
</div>
<script>
channels_array = ["red", "green", "black"];
for(var i = 0; i < channels_array.length; i++) {
var loop_channel_name = channels_array[i];
var new_button_element = document.createElement("span");
new_button_element.id = 'channel_button_'+loop_channel_name;
new_button_element.innerHTML = '<br>BLA BLA';
document.getElementById('channels_buttons_container').appendChild(new_button_element);
document.getElementById('channel_button_'+loop_channel_name).onmouseover = function(){
alert('Rollover '+loop_channel_name);
/*You could also do*/
alert('Rollover '+ channels_array[i]);
}
//
}
</script>