I have requirement to remove some element and get it back when required. I have red about the .detach() which do almost I required but the things is I have to done it with javascript.
<div id="get">a</div>
document.getElementById("get").addEventListener('click',function(){
alert(0)
})
If you need to keep the binding on the node as maybe you are appending it later on why not store the node with its event bindings?
http://jsfiddle.net/w4699vm8/
var myDiv = document.getElementById("get"),
wrapper = document.getElementById("wrapper");
myDiv.addEventListener('click',function(){
alert(0);
});
wrapper.removeChild(myDiv);
wrapper.appendChild(myDiv); //myDiv still has listener
Related
Beginner to all of this, playing around with Firebase. Basically, I want to retrieve text entries from Firebase and have an "Approve" button next to it. When the button is clicked, I want that specific text entry to be pushed to a new Firebase location and the text removed from the page. I am creating the button and the text dynamically and I am having some trouble with selecting the button and the divs I created. I know I have to use on() but I'm unsure of how to use it.
Thanks!
approveRef.on('child_added', function(snapshot) {
var posts = snapshot.val();
$('<div id="post">').text(posts.text).append('<button style ="button" id="approve">Approve</button>').appendTo($('#feed'));
});
$('#approve').on("click", function(){
var text = $('#post').val();
postsRef.push({'text':text});
$('#post').remove();
});
You have to bind .on() on a container of your dynamically added element that is already on the page when you load it, and have it like this:
$('#yourContainer').on('click', '#approve', function(){
//your code here..
});
Your .on() didn't work, because you are adding the button dynamically. You can't find the dynamically added elements directly using that elements id selector like $('#approve'). So you should
bind .on() with $(document) selector. This will always contain your dynamically added elements.
$(document).on( eventName, selector, function(){} );
$(document).on('click','#approve',function(){
//your code here
});
I find a quick dip into the DOM, and then running back into jQuery very handy for this problem:
// Construct some new DOM element.
$(whatever).html('... id="mynewthing"...');
// This won't work...
$("#mynewthing")...
// But this will...
$(document.getElementById("mynewthing"))...
This works by turning the DOM object directly into a selector. I like it because the approach is transparent in operation/intent.
Another alternative, simpler to understand, less powerful, also perfectly valid, is to simply bind the event while you create the element:
approveRef.on('child_added', function(snapshot) {
var posts = snapshot.val();
var $button = $('<button style ="button" id="approve">Approve</button>');
$button.on("click", function(){
var text = $('#post').val();
postsRef.push({'text':text});
$('#post').remove();
});
$('<div id="post">').text(posts.text).append($button).appendTo($('#feed'));
});
Another problem you are going to run into, assuming there will be more than one of these on a page, is that you are using IDs in the records. They're going to clash if they aren't unique.
A great alternative is to refer to these items with data-* tags or other identifying characteristics, such as css tags. But in your case, you don't need them at all!
approveRef.on('child_added', function(snapshot) {
var posts = snapshot.val();
var id = snapshot.name();
var $button = $('<button style="button">Approve</button>');
$button.on("click", function(){
// use parent.closest(...) in place of an ID here!
var text = $(this).parent().closest('textarea').val();
postsRef.push({'text':text});
$(this).parent().remove();
});
/* just an example of how to use a data-* tag; I could now refer to this element using:
$('#feed').find('[data-record="'+id+'"]') if I needed to find it */
$('<div data-record="'+id+'">').text(posts.text).append($button).appendTo($('#feed'));
});
I don't sure exactly what are you looking for. You can use .find() to select dynamically elements. I think .find() will look at the html structure again to get needed elements.
$("#button").click(function(e){
$(".parentContainer").find(".dynamically-child-element").html("Hello world");
});
Or
$(".parentContainer").find(".dynamically-child-element").html("Hello world"); // not in click event
So this is my demo
I am writing a todo app using vanilla JavaScript to learn the language without using a library.
In the app, you can add a task, complete task or un-complete task, edit and delete task. I have sample tasks that show the functionality in HTML.
I have a function that adds a task to incomplete tasks section—each task item is wrapped in an li tag and has a checkbox, edit and delete buttons. The addTask function works perfectly.
The problem I am having is in the selectbox part. The app is designed in a way that when checkbox of a task is selected, it indicates a task is completed and thus the item is shown in the completed tasks section. The function works for the items available on the page but not the ones added using the add functionality. How do I make the new task work? Thanks. Here is my HTML Code:
<h3>Todo</h3>
<ul id="incomplete-tasks">
<li><input type="checkbox"><label>Pay Bills</label><button>Edit</button><button>Delete</button></li>
</ul>
<h3>Completed</h3>
<ul id="completed-tasks">
<li><input type="checkbox" checked></input><label>See Doctor</label><button>Edit</button><button>Delete</button></li>
And here is my JS code:
var incompleteTasksHolder = document.getElementById("incomplete-tasks");
var completedTasksHolder = document.getElementById("competed-tasks");
var incompleteTextboxes = incompleteTasksHolder.querySelectorAll("input[type=checkbox]");
for (var i = 0; i < incompleteTextboxes.length; i++) {
incompleteTextboxes[i].onfocus = function() {
var item = this.parentNode;
this.setAttribute("checked", "checked");
completedTasksHolder.appendChild(item);
}
}
You are probably using some event listeners to mark the task as completed when the checkbox changes value.
I think that you just forgot the bind this listener to the new item that you created via Javascript.
When creating your new element bind your listener to it:
taskCB.addEventListener('change', toggleCompleted);
Where taskCB is the checkbox element and toggleCompleted is the name of the function that is fired when a task checkbox is checked or unchecked.
This probably happens because the incompleteTextboxes variable only gets assigned a collection of DOM nodes once. Each time you add a new task, that ends up inside incompleteTasksHolder you should also re-assign an updated collection by re-running the assignment: incompleteTextboxes = incompleteTasksHolder.querySelectorAll("input[type=checkbox]");.
That could look something like this:
var incompleteTasksHolder = document.getElementById("incomplete-tasks"),
completedTasksHolder = document.getElementById("competed-tasks");
// Initialize variable, but create a function for the assignment:
var incompleteTextboxes;
// This function searches the DOM for all checkboxes inside incompleteTasksHolder, and assigns the collection of found elements to incompleteTextboxes:
function refreshIncompleteTasksCollection() {
incompleteTextboxes = incompleteTasksHolder.querySelectorAll("input[type=checkbox]");
}
// You can now re-assign all currently existing checkboxes by calling this function:
refreshIncompleteTasksCollection();
Now, each time there are new elements inside incompletetextboxes, you can run that function to add those to your collection. Note, you'll probably want to re-run your for-loop as well, for binding the focus event handler to your new elements.
A whole different (and in my opinion cleaner) approach would be to use event delegation for your onfocus handlers. Since incompletetextboxes only contains checkboxes inside #incomplete-tasks (by the way you set up your variables), you could use that element to delegate the event handling to. This can be done with addEventListener. You can read more about that here: https://davidwalsh.name/event-delegate.
The main reason I bring this up is because this would solve the problem of missing event handlers for your new elements. What event delegation basically means is, instead of saying:
listen at each incompleteTextbox for a focus event (which means that, when you add new elements you have to say that again for each new element)
you now say:
listen at incompleteTasksHolder for a focus event, and then determine whether that event was fired by a incompleteTextbox. That is possible because your checkboxes live INSIDE #incomplete-tasks. That could look something like this:
incompleteTasksHolder.addEventListener("focus", function(eventObject) {
if (eventObject.target && eventObject.target.matches("input[type=checkbox]")) {
// eventObject.target is the checkbox you want to work with
var checkbox = eventObject.target;
// YOUR CODE:
var item = checkbox.parentNode;
checkbox.setAttribute("checked", "checked");
completedTasksHolder.appendChild(item);
}
});
That means only one listener, that will always work, even for incompleteTextboxes that are inserted after that listener was set.
I have a html div and I clone it using Jquery. That div contains labels and text fields. ids of all of them generated and assigned dynamically. I have no problem with that.
A java script is assigned to a text field of original div. The cloned text fields does not have the javascript assigned to it.
the script I need to assign:
<script>
$(function() {
$("#datepick_onBooking,#datepick_Pay1,#datepick_Pay2,#datepick_totPay,#datepick_deedFees").datepicker();
});
</script>
the script I use to make clones:
<script>
var i = 3;
//When DOM loaded we attach click event to button
$(document).ready(function() {
$('#addAnotherPayment').click(function() {
var cloned = $('.PayDiv0').first().clone();
var noOfDivs = $('.PayDiv0').length+2;
cloned.insertBefore("#totPayForm");
// append count to the ids
cloned.attr('id', 'PayDiv' + noOfDivs);
cloned.find('label').attr('id', 'PayLbl' + noOfDivs);
cloned.find('input[type="text"]').attr('id', 'datepick_Pay'+ noOfDivs);
cloned.find('input[type="number"]').attr('id', 'amount_Pay'+ noOfDivs);
cloned.find('.PayLbl2').html("Payment No " + i++ + ':');
});
});
</script>
datepick_Pay1, datepick_Pay2, datepick_totPay, datepick_deedFees are static elements and they have been assigned to the script. I create text fields using cloning as datepick_Pay3,datepick_Pay4, and so on.
I cannot figure out how to dynamically assign the script to that newly created elements.How can I do that?
A Boolean indicating whether event handlers and data should be copied along with the elements.
change this line.
var cloned = $('.PayDiv0').first().clone(true);
when you clone something especially elements which having events
use parameter as
clone(true)
But this will be harmfull based on how event is attached on the actual element when copying the events to the cloned element may affect the actual.
You need to clone with events. http://api.jquery.com/clone/
var cloned = $('.PayDiv0').first().clone(true);
Then your script needs to be changed to work for dynamic elements. Here as soon as input elements gets focus, asssign the datepicker based on wild card id selector, if it doesn't already have one.
$(function() {
$('body').on('focus',"input[id^=datepick_]", function(){
if(!$(this).hasClass('.hasdatepicker'))
{
$(this).datepicker();
}
});
});
I have this html code:
<b class = "edit" id = "foo1">FOO</b>
<b class = "edit" id = "foo2">FOO2</b>
<b class = "edit" id = "foo3">FOO3</b>
And I have this code in jQuery:
$('b.edit').click(function(){
//GET THE ID OF THE b.edit: e.g foo1, foo2, foo3
$('.editP').focus();
});
How can I get the id value of the b.edit, as there are multiple instances of b.edit, and I want to get the specific id of the one clicked? How can I do this?
Thanks, Sorry, I am pretty new to javascript.
I'm assuming from your sample code that you're using jQuery? If so you can get the id as follows:
$('b.edit').click(function(){
this.id;
});
EDIT:
The direct reference to the attribute is indeed more efficient if all that is required is simply the id.
Also can be obtained from the jQuery object:
$('b.edit').click(function(){
$(this).attr('id');
});
Sample fiddle: http://jsfiddle.net/5bQQT/
Try with this:
$('b.edit').click(function(e){ //When you use an event is better
//send the event variable to the
//binding function.
var id = e.target.id; //get the id of the clicked element.
/*do your stuff*/
$('.editP').focus();
});
try this. You can use keyword "this" to retrieve the attr ID...
$('b.edit').click(function(){
alert($(this).attr("id"));
});
$('.edit').click(function(){
var theId = $(this).attr('id');
}
This will get you the ID of anything clicked with a class of .edit
$('.edit').live('click', function() {
alert( this.id );
});
Sample
http://jsfiddle.net/ck2Xk/
When passing a click handler in JQuery, you actually have a reference to something called an event object. This event object has a property called target, which is a reference to the element that was clicked.
$('b.edit').click(function(eventObject){
eventObject.target // this is the element that was clicked.
});
Since you have a reference to the target element, you can do whatever you like. In this case, you could just access eventObject.target.id.
Since nobody has shown the simplest method yet that doesn't even need jQuery to get the id:
$('.edit').click(function() {
alert(this.id);
});
I never understand why people use jQuery for getting simple attributes which involves two jQuery function calls (and a bunch of overhead to create a jQuery object) instead of one direct attribute reference.
something like this:
var id = $(this).attr('id');
More clearly:
$('b.edit').live('click', function(){
var id = $(this).attr('id');
// in this scope this.id works too
// var id = this.id;
});
This is called event delegation in Javascript. More info can be found in Zakas blog http://www.nczonline.net/blog/2009/06/30/event-delegation-in-javascript/
The idea in few words is you attache the event to a parent node and then waiting for some event on the child node. In the example below I attach the onclick event to the document itself. Then inside the event handler you will write a switch statement to check the clicked element id, then do what you want to do for that element
document.onclick = function(event){
//IE doesn't pass in the event object
event = event || window.event;
//IE uses srcElement as the target
var target = event.target || event.srcElement;
switch(target.id){
case "foo1":
foo1();
break;
case "foo2":
foo2();
break;
case "foo3":
foo3();
break;
//others?
}
};
//some dummy handlers
var foo1 = function(){
alert("You clicked foo1");
};
var foo2 = function(){
alert("You clicked foo2");
};
var foo3 = function(){
alert("You clicked foo3");
};
For how to implement event delegation in jQuery you can check http://api.jquery.com/on/#direct-and-delegated-events
Even though this is not a real answer to your question. I will try to explain why what your asking is not the way to go. Since you are new especially, since learing bad practices could be hard to unlearn. Allways try to search for an ID before finding an element by its Class. Also try to avoid giving every element the same class (and in this case ID to), just give it an encapsulating parent.
Furthermore, the id of an element is really specific and should preferably used to find / select / bind events to. An id should usually be unique for this to work, so in your case a couple of things could be optimized, lets say like:
<div id="foo">
<b id="1">Foo</b>
<b id="2">Other foo</b>
<b id="3">Some foo</b>
</div>
Now if you want to know which was clicked there are multiple ways to accomplish it, but a nice one is simply binding a parent its children (i.e <div id="foo"> .. </div>). This way you can alter the structure of your pretty fast, without changing all the classes and id's.
With jQuery you can get the attribute id using the .attr() function. However I told you the id was pretty specific and thus has its own rights in javascript world. An id can also be directly targeted ('DOMelement.id', but this would be too much to explain for now)
In two ways the <b> can be targetted:
Example a)
var b_elements = $("#foo").children();
Example b)
var b_elements = $("#foo").find('b');
We can add jQuery (or javascript events) to these found elements. The nice thing about jQuery is that it simplifies alot of work. So in your case if you would like to know an id of a certain clicked <b> field you could use a very verbose way:
b_elements.click(function()
{
var clicked_element = $(this);
alert(clicked_element.attr('id'));
});
Verbose because you can do it much much shorter, but who cares about a few bytes when your learning and this makes remembering functions and events alot easier. Say you wanted to get the class edit by finding the where you knew the id that was clicked:
b_elements.click(function()
{
var clicked_element = $(this);
alert(clicked_element.attr('class'));
});
And to conclude, the id of an element is ment to be unique because it makes searching through big documents alot faster. Also don't forget to look and learn plain javascript, as it helps coding in jQuery alot too, but not the other way around. Your given question would require a for loop in plain javascript since it cannot do a lookup by class nor id nor have they have a common parent.
Good luck with learning :)
If hovering over an element injects something into the DOM, can I still reference it?
Or do I have to use the live plugin?
I'm using jQuery 1.3.2
i.e. can I do
$("#someItem").attr("src", "htt...")
on it?
I am trying to do it, but I think its not working b/c its a newly added item to the DOM.
Yes, an element that has been added to the DOM can be selected and referenced.
Or, if you already had a reference to it that you used when you added it to the DOM, you can continue to use that reference after it has been added as well.
Using this example, you can see that you can both use a current reference to a newly created element, as well as make a new reference to it.
http://jsfiddle.net/Czuvx/
HTML:
<div id='button'>hover me</div>
jQuery:
$('#button').hover(function() {
$('#newElement').remove();
var $myNewElement = $('<div id="newElement">new Element</div>');
$('body').append($myNewElement);
$myNewElement.css({color:'red'});
},
function() {
// This function has completely different namespace
// from the one that created and inserted #newElement
// and I can get a reference to it just like any other element
var $newReferenceToElement = $('#newElement');
$newReferenceToElement.css({color:'blue'});
});
Showing a bit more of your code would be helpful, but I think I get the general idea.
If you're just looking to add events or something to that item, you can do it before you append the item.
(function($){
$(function(){
$("#link").hover(
function(){
var $div = $("<div class='inserted_div'></div>").bind("click",function(){ ... });
$("body").append($div);
}),
function(){
});
});
})(jQuery);
So just bind the events or attributes at the time of creation, before you append it.