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/
Related
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 function in a javascript file that adds a link to a paragraph that I created in the HTML file. I want to call a function that is defined in the javascript file when the user clicks the link.
My HTML:
<p id="para"></p>
My JavaScript:
var paraHTML = document.getElementById("para");
function addLink(id) {
paraHTML.innerHTML += '<a id="' + id + '" onclick="clickedTest(); return false;">Click me!</a>'
}
function clickedTest() {
console.log('here');
}
I have also tried using href e.g.
paraHTML.innerHTML += '<a id="' + id + '" href="javascricpt:clickedTest();">Click me!</a>'
But both ways give me an error saying: ReferenceError: clickedTest is not defined
I have tried using the following code from this question but the number of links is constantly changing whilst my code is running which makes it difficult to use:
var elements = document.getElementsByTagName('a');
for(var i = 0, len = elements.length; i < len; i++) {
elements[i].onclick = function () {
console.log('here')
}
}
The addLink() function is called elsewhere in my javascript program several times
Using innerHTML to create content is usually slow and is usually discouraged, a more organic approach will be to create the element pragmatically and then adding event listener to that element. For example,
var elem = document.createElement('a');
elem.addEventListener('click', myClickHandler);
elem.innerText = 'My Tag';
paraHTML.appendChild(elem)
function myClickHandler(e) {
console.log('a is clicked')
}
This will not only fix your problem but will make your code more manageable
You can do something like this:
function callMe(){
}
var newLink = document.createElement('a');
newLink.href="javascript:callMe();";
newLink.innerHTML="this is a link";
paraHTML.appendChild(newLink);
I want to take a click event from 2nd page . 1st page have a link for 2nd page, there have a button when click the button it add a HTML row on 1st page. I am trying to use localStorage for passing data. My code don't work, take a look below:
1st Page.html
HTML
<div id="content">
</div>
JS
var output = document.getElementById('content');
addEvent(window, 'storage', function (event) {
if (event.key == 'StorageName') {
output.innerHTML = event.newValue;
}
});
2nd Page.html
HTML
<input id="data" type="button" value="+" onclick="addRow()">
JS
addEvent(dataInput, 'keyup', function () {
localStorage.setItem('StorageName', this.value);
});
var dataInput = dataInput = document.getElementById('data');
object.onclick = function(){
addRow() {
var div = document.createElement('div');
div.className = 'row';
div.innerHTML = '<button>GO</button>';
document.getElementById('content').appendChild(div);
}
};
You haven't defined your addRow() function properly. A function's name is defined with the keyword function, not inside of the function body. Your code:
object.onclick = function(){
addRow() {
var div = document.createElement('div');
div.className = 'row';
div.innerHTML = '<button>GO</button>';
document.getElementById('content').appendChild(div);
}
};
Should be changed to:
function addRow() {
var div = document.createElement('div');
div.className = 'row';
div.innerHTML = '<button>GO</button>';
document.getElementById('content').appendChild(div);
}
object.onclick = addRow;
I agree with skyline3000's answer the addRow() should be defined. Also there are a few other things that could/should change:
define dataInput before attaching an event to it
object.onclick should be dataInput.onclick since thats the element being clicked. (is click event what you really want? maybe onkeyup?)
when you set the localStorage you want to set the function definition being passed to Page 1 which appears to be addRow(). Simply remove the parenthesis to pass just the definition.(Should also be defined before using)
If you want to just pass the function you shouldn't set the onclick event on Page 2. What you should probably do is record how many times you want it to run when you go to Page 1.
You dont need to pass the function everytime if it isnt changing; Just set it once and record the number of times it was clicked.
page 1 can catch the load event and the check localStorage for the function definition and number of times it was run. Then it can loop and perform the function.
the code you have doesn't add a link back to page 2 if thats what you are looking for but you can add that into the addrow function when you know the file name and path.
Page 1
var output = document.getElementById('content');
addEvent(window, 'load', function (event) {
if (localStorage.getItem('StorageName') && localStorage.getItem('rowsToAdd')) {
for(var i = 0; i > rowsToAdd;i++){
var addNewRow = localStorage.getItem('StorageName');
addNewRow();
}
}
});
Page 2
var dataInput = document.getElementById('data');
function addRow() {
var div = document.createElement('div');
div.className = 'row';
div.innerHTML = '<button>GO</button>';
document.getElementById('content').appendChild(div);
};
localStorage.setItem('StorageName', addRow);
dataInput.onclick = function() {
if(localStorage.getItem('rowsToAdd')){
localStorage.setItem('rowsToAdd', localStorage.getItem('rowsToAdd') + 1);
}else{
localStorage.setItem('rowsToAdd',1);
}
}
I didn't test this code so it may not work copy+pasted but something pretty close hopefully.
I also answered this with the best understanding of what you wanted that I could manage but I dont fully see the desired result of what you seemed to be doing.
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);
}
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");
}
});