jQuery Append with event bind - javascript

I am trying to append a number of Div's to a div with an id "list", and each div has an event so i make an array for each div to be appended.
here is my code.
var count = Object.keys(data.results).length;
var el = [];
for(var i=1; i<=count; i++){
el[i] = $('<div id="'+i+'">data.results[i].name</div>');
$("#list").append(el[i]);
el[i].click(function(){
alert(data.results[i].name);
$('#searchbox').modal('toggle');
});
}
the data in div's was successfully appended. but as a try to alert the data in the event i bind to each div, it doesn't alert the data in the div.
what I am trying to do is append names with a div within the div with id "list" and if i click on a name, it should alert the name itself.

You can simplify the logic here by using a delegated event handler on all the appended div elements, then using the text() method to retrieve the required value. Try this:
var data = {
results: {
foo: { name: 'foo_name' },
bar: { name: 'bar_name' }
}
}
var $list = $("#list").on('click', 'div', function() {
console.log($(this).text());
//$('#searchbox').modal('toggle');
});
Object.keys(data.results).forEach(function(key, i) {
$list.append('<div id="' + i + '">' + data.results[key].name + '</div>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="list"></div>

The problem is that by the time an element is clicked i is already set to the maximum value i = count. To fix that you'll have to create a closure. Try this:
var count = Object.keys(data.results).length;
var el = [];
function closure(index){
el[index].click(function(){
alert(data.results[index].name);
$('#searchbox').modal('toggle');
});
}
for(var i=1; i<=count; i++){
el[i] = $('<div id="'+i+'">data.results[i].name</div>');
$("#list").append(el[i]);
closure(i);
}

Related

How to set a css property to an html element that i get as a string

I generate an html table using javascript and jquery.
One of the row cells has an anchor element, that I append to table as a string var deleteLink = "Delete"
I need to set an event listener to the generated element, but don't know how to select it
I can't pass deleteLink as a string like this
$(deleteLink).on("click", function () {
//call fucntion
});
I'm trying to set a unique id to the generated links, but I also need to know how to select them first. Please help
This's how I generate the html table.
Please note that each delete link should only trigger the row it belongs to.
function appendToDigitalMapTable(docId) {
tbl = document.getElementById('digitalMapTable');
var selectedDigitalMap = $("#DigitalMapTypeId option:selected").text();
var deleteButton = "<a href='#'>Delete</a>";
addRow(tbl, selectedDigitalMap, deleteButton, docId);
}
function deleteUploadedDoc(docIdAssociatedToRow) {
console.log("deleteUploadedDoc function is called. docId = " + docIdAssociatedToRow);
//ajax call to backend function
}
function addCell(tr, val) {
var td = document.createElement('td');
td.innerHTML = val;
tr.appendChild(td)
}
function addRow(tbl, val_1, val_2, docId) { 2
var tr = document.createElement('tr');
var docIdAssociatedToRow = $(tr).data("documentID", docId)
//selected digitalMapType text
addCell(tr, val_1);
//delete row
addCell(tr, val_2);
//val_3 is "<a href='#'>Delete</a>"
//attach eventListener to this element
$(val_3).on("click", function () {
deleteUploadedDoc(docIdAssociatedToRow);
});
tbl.appendChild(tr)
}
Option 1: return the row from addRow then find the delete button in that row to add the event handler:
function addRow(...) {
...
return tr;
}
var tr = addRow(...);
var delbutton = $(tr).find("a")
// not clear if you question is for css or event handler, asks both
delbutton.css("color", "red").click(function() { handleRowDeleteEvent(); });
this assumes you only have one button/anchor, mitigated using a class
var delbutton = $(tr).find("a.del-button")
(as an aside, it should be a <button type='button' not <a> as it's an action, not a link, so I've used <button> below)
Option 2: use event delegation
$("#digitalMapTable").on("click", "a", handleRowDeleteEvent);
again, assumes you have a single button for delete, not for edit etc, but this can easily be mitigated by adding a class to your buttons when you create them, eg:
var deleteLink = "<button type='button' class='delete-button'>delete</button>";
$("#digitalMapTable").on("click", "button.delete-button", handleRowDeleteEvent);
Option 3: use onclick=
var deleteLink = "<button type='button' onclick='handleRowDeleteEvent'>delete</button>";
not recommended for numerous reasons that I'll leave you to research
How to ensure your button only works on the row it needs to - use this:
function handleRowDeleteEvent() {
var btn = $(this);
var row = btn.closest("tr");
var docId = row.data("documentID");
deleteUploadedDoc(docId);
}
or, all in one line:
function handleRowDeleteEvent() {
deleteUploadedDoc($(this).closest("tr").data("documentID"));
}
You can give your anchor element an unique id and later use Jquery's # selector to select that particular element.
var counter = 1;
var deleteLink
for (var a = 0; a < 2; a++) {
deleteLink = "<a href='#' id='myLink" + counter + "'>Delete </a>";
document.body.innerHTML += deleteLink;
counter++;
}
$('#myLink1').on("click", function() {
console.log("clicked")
});
$('#myLink2').on("click", function() {
console.log("other clicked")
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

I have a problem with an id in onClick event JavaScript function

I am trying to make a little idle click game, but have a problem with my startIdle function.
I can't pass the id to which input progressbar that is needed to start counting.
I have one input field and one button foreach id from a obj.
function addRow(id) {
var div = document.createElement('div');
div.className = 'row';
div.innerHTML =
'<div class="w3-blue" name="idle" id="'+id+'" style="height:24px;width:20%"></div>\
<button onclick="startIdle('+id+')">Click me</button>';
document.getElementById('content').appendChild(div);
}
function startIdle(id) {
_counter = 1;
_timer = setInterval(function(){
document.getElementById(id).style.width = (_counter + "%");
_counter++;
if(_counter > 100) clearInterval(_timer);
}, 100);
}
function createIdles(){
for (var key in money) {
// skip loop if the property is from prototype
if (!money.hasOwnProperty(key)) continue;
var obj = money[key].id;
addRow(obj)
}
}
createIdles()
this is the console.log I get:
Uncaught ReferenceError: startIdle is not defined at HTMLButtonElement.onclick
Your problem is that startIdle is defined inside a scope. Move it out of document.ready. Unless you can call the function from console, it isn't available globally.
Alternatively, building on Andy Hoffmans solution, bind onClick programmatically inside scope of document.ready, e.g.
document.querySelectorAll('button[data-id]')
.forEach(elm => elm.addEventListener('click',
() => startIdle(elm.dataset.id)))
You can probably improve that a bit using jquery.
I removed the onclick attribute and perform binding separately. The binding and element lookup are done inside of a setTimeout to ensure the elements are present in the DOM when that code runs.
// Note: I'm using a data-id attribute on the <button> so as to not
// duplicate the id on the <div class="w-3">
function addRow(id) {
var div = document.createElement('div');
div.className = 'row';
div.innerHTML =
'<div class="w3-blue" name="idle" id="' + id + '" style="height:24px;width:20%"></div>\
<button data-id="' + id + '">Click me</button>';
document.getElementById('content').appendChild(div);
}
function startIdle() {
// Remember the data-id attribute from above?
alert('clicked ' + this.getAttribute('data-id'));
}
for (var i = 0; i < 5; i++) {
addRow(i);
}
// Bind click events in separate event loop to ensure elements are present in DOM
setTimeout(function() {
var els = document.querySelectorAll("button[data-id]");
els.forEach(function(el) {
el.addEventListener("click", startIdle);
})
});
<div id="content"></div>
http://jsfiddle.net/4mr02ktu/2/

Binding event before Creating DOM in jQuery

var thumbDom = '';
for (var i = 0; i < 10; i++) {
thumbDom = thumbDom + '<div id = "div-" ' + i + '>DIV-'+ i +'</div>';
bindEvent(i);
}
$('#parent').append(thumbDom);
function bindEvent(i){
$('#div-' + i).click(function(event) {
alert(i);
});
}
I know the code can't work , beacuse event is bind before dom append.
but is there anyway to bind the click event to many dynamically doms before appending to dom tree?
I don't wnat to use $(document).on('click, ... , I want to bind event to the child node.
Any suggest will be help , thank you~
Fiddle Here
You could try this approach:
define a <div></div>
set its id and innerHtml
bind it with an onclick event (that alerts its id)
append it to the "#parent" item
$(function() {
for (var i = 0; i < 10; i++) {
$("<div></div>")
.attr("id", "div-" + i)
.html("DIV-" + i)
.click(function() {
alert($(this).attr("id"));
})
.appendTo("#parent");
}
});

Click event on every item on populated list with jQuery

Here is how I populate my list:
function bingNetworksList(myList) {
var list = '';
for (i = 0; i < myList.length; i++) {
list += '<li>' + myList[i] + '</li>';
}
$('#myList').empty();
$('#myList').append(list);
}
Here is my html file:
<ul id="myList"></ul>
I want to add a click event for every item of list (without having separate ids):
$(function() {
$('#myList').click(function() {
var listItem = this.find('a').text();
console.log(listItem); // never logged
});
});
However, when I click at a list item, click event doesn't fire.
What am I doing wrong?
I can only assume there's a js error in your console.
I've created a working sample for you. We can use event delegation and then retrieve the DOM node that was clicked. You need to ensure you call the bingNetworksList [assume typo in here and meant binD ;)] function when the DOM ready event has fired.
function bingNetworksList(myList) {
var list = '';
for (i = 0; i < myList.length; i++) {
list += '<li>' + myList[i] + '</li>';
}
$('#myList').empty();
$('#myList').append(list);
}
$(function() {
var list = ["foo", "bar"]
bingNetworksList(list);
$('#myList').click(function(evt) {
var listItem = $(evt.target).text();
console.log(listItem); // never logged
});
});
You need to wrap this inside $ as like this:
$(function() {
$('#myList').click(function() {
var listItem = $(this).find('a').text();
console.log(listItem); // will always be logged
});
});

use JSON variable in jQuery to display more JSON variables

This is somewhat pseudo code so EDIT away. I want to make it when the user clicks on a thumb inside #placeholder DIV thumb2 is then displayed inside #imageLoad DIV. NOTE: Thumb and thumb2 are JSON items. A lot of people are saying that this can't be done with getJSON because it's an asynchronous request. If that is the case, then how can I change my script to support the request? If I am going the wrong way, please provide alternate solutions.
$.getJSON('jsonFile.json', function (data) {
var image1 = "<ul>";
for (var i in data.items) {
image1 += "<li><img src=images/items/" + data.items[i].thumb + ".jpg></li>";
}
image1 += "</ul>";
document.getElementById("placeholder").innerHTML = output;
var image2 = "<img src=images/items/" + data.items[i].thumb2 + ".jpg>";
$('li').click(function () {
document.getElementById("imageLoad").innerHTML = output;
});
});
Here is the external JSON file below (jsonFile.json):
{"items":[
{
"id":"1",
"thumb":"01_sm",
"thumb2":"01_md"
},
{
"id":"2",
"thumb":"02_sm",
"thumb2":"02_md"
}
]}
You can try something like the following:
$.getJSON('jsonFile.json', function(data)
{
$("#placeholder").html("");
var ul = $('<ul></ul>');
$('#placeholder').append(ul);
var load = $("#imageLoad");
for(var i in data.items)
{
var li = $('<li></li>');
ul.append(li);
var img = $('<img>');
img.attr("src", "images/items/" + data.items[i].thumb + ".jpg");
img.click((function(x)
{
return function()
{
load.html("<img src=images/items/" + data.items[x].thumb2 + ".jpg>");
}
})(i));
li.append(img);
}
});
Main difference is that click-handler is assigned inside the loop, so every handler receives a closure with appropriate reference to thumb2.
I think this could do the trick:
var $placeholder = $('#placeholder'),
$imageLoad = $('#imageLoad');
$.getJSON('jsonFile.json', function(data) {
var html = '<ul>';
$.each(data.items, function(i,item){
html += '<li><img src=images/items/' + item.thumb + '.jpg></li>';
});
html += '</ul>';
$placeholder.html(html);
});
$placeholder.on('click','li',function(){
$imageLoad.html($(this).html());
});
I can't understand the use of output since you are not declaring it in anyway. The eventhandler for the click event will trigger on all current and future li elements of the $placeholder which contains the DOM object with an id of placeholder.

Categories

Resources