I am building a site which allows the user to download files from a folder on the server.
The files are pulled from a database and stored in a HTML table. Each row has a download button. I know i cant just put id='download'.
What would be the best way to handle a JavaScript function when the button is clicked.
Should i set something like download-214124
and then just put ("download-*") as the selector in jQuery?
As you said you can't use a common ID to all element since ID must be unique.
Instead you can use a common class to all the elements, then use a data-* attribute to store the id like
<button class="download" data-id="1235">Download</button>
then
$('.download').click(function(){
var id = $(this).data('id');
//do download code for id here
})
Note: If you are dealing with dynamic elements, then you will have to use event delegation to register the handlers like
$(document).on('click', '.download', function() {
var id = $(this).data('id');
//do download code for id here
})
Event binding on dynamically created elements?
HTML5 offers data-attribute that allows you to store data respective to the DOM element. This makes life super easy to hook up with JavaScript. jQuery has data() function to access data-attribute of the element.
You can do something like below.
HTML
<table>
<tr><td>
<p>file with id 1</p>
<button data-id="1">download</button>
</td></tr>
<tr><td>
<p>file with id 2</p>
<button data-id="2">download</button>
</td></tr>
<tr><td>
<p>file with id 3</p>
<button data-id="2">download</button>
</td></tr>
</table>
Javascript
$('button').on('click', function(e){
e.preventDefault();
var id = $(this).data('id');
alert('Do ajax request to download file with id ' + id);
});
Here is the jsfiddle for that.
If JavaScript is being used to build the HTML table, you can attach the event handlers at runtime without needing any IDs.
A good example of this would be when you're building an HTML structure by looping through an array of results via JavaScript. In such a case, you can use closures to maintain references to the result data that corresponds to particular HTML elements, and use that data when event handlers are invoked.
In the example below, the event handler that is attached to each button is able to directly call up the value property of a corresponding object in an array; we didn't need to add anything to the button element (neither an ID nor a data- attribute) to maintain that reference.
var dataResults = [{title:"One",value:1}, {title:"Two",value:2}, {title:"Three",value:3}, {title:"Four",value:4}];
var output = document.getElementById("output");
for (var i = 0, len = dataResults.length; i < len; i++) { // 1. Loop through results
var btn = document.createElement("button"); // 2. Create your HTML element(s)
btn.value = dataResults[i].title; // 3. Set HTML based on result values
btn.innerHTML = dataResults[i].title;
(function(result) { // 4. Use a closure to capture the current result item
btn.addEventListener("click",function() {
alert("You clicked button " + result.value);
}); // 5. Add an event handler that references the result item.
})(dataResults[i]); // (Pass the current result item into the function expression as a parameter)
output.appendChild(btn); // 6. Add your HTML to the page.
}
<div id="output"></div>
Of course, none of that is relevant if JavaScript isn't responsible for building the HTML in your application!
Related
I use jquery and es6 template strings to create a checkbox with a label:
function createCheckBx(id, text) {
return $(`<div>
<input id ="${id}" type="checkbox"/>
<label for="${id}">${text}</label>
</div>`);
}
Now I would like to attach an eventlistener to the checkbox
checkBox = createCheckBx("42", "Answer");
cb.???.addEventListener("change", (evt) => {
// do smth. when toggled
})
but the div is not attached to the dom yet so I can't use document.getElementById (or jquery's $("#...") and I don't want to access it by any kind of index like cb.childNodes[0], since the caller can't know the index and the html structure may change. Any help?
kindly regards, AJ
Just because the element doesn't yet exist in the DOM doesn't mean you can't attach an event handler to it. The only issue in your example is the syntax you're using as you're mixing jQuery and plain JS methods. You should stick to one or the other.
As you're including jQuery in the page, here's how to make your example work:
let createCheckBox = text => $(`<div><label><input type="checkbox" />${text}</label></div>`);
let $checkBox = createCheckBox("Answer");
$checkBox.on('change', e => {
console.log(`Checkbox checked? ${e.target.checked}`);
});
// add the checkbox to the DOM at some point:
$('body').append($checkBox);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
Note that I removed the id attribute from the function which creates the element and also the HTML it generates. This is because creating id at runtime is an anti-pattern and should be avoided. Use common classes instead.
Also note that you may be better served by creating a single delegated event handler to handle all your dynamically appended content, instead of attaching an event as you create the new elements. Here's an example of how to do this:
let createCheckBox = text => $(`<div><label><input type="checkbox" />${text}</label></div>`);
let $container = $('.checkbox-container');
$('button').on('click', e => $container.append(createCheckBox("Answer")));
$container.on('change', ':checkbox', e => {
console.log(`Checkbox checked? ${e.target.checked}`);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<button type="button">Add</button>
<div class="checkbox-container"></div>
I have some <tr> elements with unique IDs.
<tr id="683535">some code</tr>
<tr id="683536">some code</tr>
<tr id="683537">some code</tr>
I want users to click on <tr>, after what a js function will be called. And I need to get this ID inside of current function without using events like <tr onclick="". Is this even possible?
You could do
$('tr').on('click',function(){
var id = $(this).attr('id');
});
In your event listener you should have a variable for the event.
Example:
$("body").on("click", "tr", function(e){
var row = $(this);
console.debug(row); //Should print clicked TR
console.info(row.attr("id")); //Should print the ID
});
If you don't want events, than your only way to interact with browser is classic hyperlink with <a> tag, where you can also include js functions like do stuff with your uid so you can simply generate such hrefs for each row inside your row generator.
<tr>
<td colspan="2">
<div>
<table id="dataTable">
<tbody>
<tr></tr>
<tr id="row_1"></tr>
<tr id="row_2"></tr>
<tr id="row_3"></tr>
</tbody>
</table>
</div>
</td>
</tr>
How can I get the value of a id in tr using jQuery? I have tried .attr but failed.
var row = jQuery('<tr>').attr("id", "row_" + item.autoID);
row.append(jQuery('<td>').append(jQuery('<input>').attr('type', 'checkbox', 'javascript:deleteChecked(' + item.autoID + ');').attr('id', 'check_id_')));
<input type="button" value="Delete" id="delete_check" disabled onclick="deleteChecked()"/>
I'm trying to get the tr attribute 'row_' + id. I have a checkbox. If you select the checkbox and then hit delete. It should delete the row with the specific id or all the checked rows.
So far I have got:
jQuery(document).on('click', '#check_id_', function(id){
jQuery('#delete_check').attr("disabled",!jQuery('#check_id_').is(":checked"));
//var row = jQuery(this).closest('tbody').find('tr').attr('id');
// console.log(row); //doesn't work
});
function deleteChecked(id){
//grab the checked row ids
}
Any help appreciated.
If I understand your requirement correctly, I would suggest approaching this problem in a slightly different way.
You simple cannot have duplicate IDs in your HTML. ID lookups use a fast lookup dictionary that can only store one element per id value so only the first is ever found.
Avoid using inline event handlers (like onclick="") at all costs in jQuery. It separates the handler registration from the handler response for no benefit and does not allow some of the additional cool event features jQuery provides (e.g. multiple handlers).
Use delegated event handler for your delete operations. This simplifies the HTML and allows for dynamic elements/rows in a far simpler way.
The way your question reads, it seems odd to use checkboxes instead of buttons for the delete. Use buttons instead unless you have good reason not to.
The rows do not need ID's unless those IDs are used for some other purpose. Just delete the row closest to the delete button that is clicked.
Use the $('<htmltag>', {'prop': 'value', 'prop2', 'value2'}) syntax to create new elements with properties. It is shorter and easier to read.
So, putting all that together, you get the following to create a new row:
var row = $('<tr>', {
"id": "row_" + item.autoID,
text: "NEW ROW"
});
row.append($('<td>').append($('<input>', {
'type': 'button',
'value': 'X',
'class': 'deleteme'
})));
$('#dataTable').append(row);
and this simple code to delete the row that has its deleteme 'X' button pressed:
$('#dataTable').on('click', '.deleteme', function(){
$(this).closest('tr').remove();
});
This is a delegated event handler. It delegates responsibility for listening for the click event to a non-changing ancestor element. When a click event bubble up to that element, it then applies the jQuery selector (in this case the class deleteme) and then runs your callback function against any matching elements that caused the event in the first place. The upshot is that the deleteme buttons only need to exist at event time for this to work.
Clean and simple.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/k5rh82cz/
Now if you actual aim is different, you need to explain how you want it to appear too :)
To iterate the rows with checked checkboxes in them and fetch their ID's, something like this should do the trick:
$('#dataTable')
.find('input[type="checkbox"]:checked')
.closest('tr')
.each(function(ind, ele){
var id = $(ele).attr('id');
//do something with the id here
});
See this demo fiddle
HTH,
-Ted
I need the id(and other attributes such as value) of a span i previously created on an ajax event.
Is there a way to do this?
This is how the span is created on php post:
echo "<span class='non-skin-symptom-choice disease_option' ".
"onclick='showinfo(".$var[0].");' id=".$var[0].">"
.$var[1]." -- ".number_format($var[3]*100, 2, '.', '')."%</span>";
and I want to get its id whenever a checkbox is clicked.
$(".chb").click(function(){
var id= $(this).attr('id');
var list=[];
$('.disease_option').each(function (){
alert("this.val=="+ $(this).attr("val")); //i need the value here
var str= $(this).attr("value").split(" -- ")[1];
alert(str);
str=str.slice(0,str.length - 1);
if(parseFloat(str) >=support)
list.push(id) //i need the id here
});
the checkbox is not dynamically created, so $(".chb").click(function(){} works.
somehow, $(this).attr("id") works but $(this).attr("val") returns undefined... i also tried $(this).attr("value") but same results. $(this).val returns empty.
use
$(document).on('click','.chb',function(){
var id = $(".non-skin-symptom-choice").attr("id");
})
as this have a high level event attachment and it can get the elements who have been created on a runtime
Try this
alert($(".non-skin-symptom-choice").attr("id"));
The click() binding you're using is called a "direct" binding which will only attach the handler to elements that already exist. It won't get bound to elements created in the future. To do that, you'll have create a "delegated" binding by using on()
$(document).on('click','.chb',function(){
var id = $(".non-skin-symptom-choice").attr("id");
})
possible duplicate: Click event doesn't work on dynamically generated elements
If your DOM node did not exist when the page loaded (ie. it was added to the page via AJAX after the page loaded), jQuery cannot see it if you try to update it or read it with jQuery methods. One way to overcome this is to set up your jQuery function to reference the class or ID of the parent of the node you want to target (assuming the parent class is loaded into the page on page load), along with the class of the node you want to target. For example:
$(".chb").click(function(){
var id = $(".your-parent-class .non-skin-symptom-choice").attr("id");
}
}
I'm quite new to javascript and JQuery programming. Usually, to access elements I give them an id, so I can get them like $("#"+id).blabla().
But now I need to dynamically create a div, and access elements inside it.
Something like
<div id="automaticallyGeneratedId">
<div ???></div> <!-- first div -->
<div ???></div> <!-- second div -->
</div>
What are the best practices to access and identify each of the inner divs?
I generate another id for them?
Or what?
I don't have the theory of selectors fully clear.
edit: modified the question from identifying a single inner div to identifying divs amongs many of them
You can maintain a pattern when you're generating id. For example:
if you always generate id like: myid1, myid2,myid3...
<div id="myid1">
<div></div>
</div>
<div id="myid2">
<div></div>
</div>
......
then you can try:
$('div[id^=myid]').find('div').foo();
OR
$('div[id^=myid] div').foo();
Here, ^= is start with selector, so div[id^=myid] will select div whose id start with myid.
You can also use Contain word selector which is ~= and use like $('div[id~=myid]'). This will select div with id contains word myid.
Instead of id if you want to use other attribute eg. name then change selector like:
$('div[name^=myid]') or $('div[name~=myid]').
It's usually a good practice that if you already have a reference to that outer div to just search from there using find.
You can give it an id, or if you want to use a more general approach you can use classes.
<div class="subdiv">...
$('#automaticallyGeneratedId').find('div.subdiv')
Usually, when you create them, you can assign event handlers and the likes straight on them. Like this:
var div = $( '<div></div>' );
div.on( 'click', function() {
// Do something when the generated div is clicked
});
// Then, add it to the DOM
$( 'body' ).append( div );
You don't need to bother selecting them with ID or classes, they're already available in your code.
Another way is to use event bubbling to handle newly created elements of the same class. A good link about this is this one: http://beneverard.co.uk/blog/understanding-event-delegation/
Many ways you can create an element and give him an Id or Class, or use the DOM to access it..
$("html").prepend('<div id="foo"></div>');
$("#foo").doSomething();
another way
$("#automaticallyGeneratedId").find("div").doSomething();
To access the div in the element with the id:
$("#automaticallyGeneratedId div").whatever
If you cache the divs you could use something like:
var myDiv1Child = $('div', myDiv1);
Create a delegated listener and within the listener you can find the element by doing this
//If a div inside the parent is clicked then execute the function within
$('.PARENT_CLASS').click("div", function(){
//This variable holds all the elements within the div
var rows = document.querySelector('.PARENT_CLASS').getElementsByTagName('div');
for (i = 0; i < rows.length; i++) {
rows[i].onclick = function() {
console.log(this); //The element you wish to manipulate
}
}
});