jquery actions firing once, but not again - javascript

forgive the code being bulkier than necessary, will tidy it up in due course.
everything seems to be working and yet, when you click a link after it's content has already been 'active' nothing happens.
i'm sure it's something simple but i can't see it.
EDIT: the following code now works in FF and Chrome, but does not work in IE8. Any ideas?
$(function(){
//initialize active link to not have a link on ready.
var linkId = $('#pricing_body div.active').attr('id');
var activeLink = $('#pricing_nav ul li#'+linkId+' a'); //just the link itself.
activeLink.parent().addClass('activeSection');
//var activeLinkContents = activeLink.parent().html(); //the link contained in the the list item and it's contents.
//alert(activeLinkContents);
var linkContents = activeLink.html(); //text content of the link.
activeLink.parent().html(linkContents);
//when link is clicked, store it's text for assignment after <a> is stripped out.
$('#pricing_nav ul li a').live('click',function(){
var clickedId = $(this).parent().attr('id');
var clickedLinkContents = $(this).html();
$(this).parent().addClass('activeSection');
$(this).parent().html(clickedLinkContents); //replaces <a><span>name</span></a> with just the span and text.
//fadeOut active div and give it inactive class. get list item with same id as div we are fading out.
$('#pricing_body div.active').fadeOut('500',function(){
$(this).removeClass('active').addClass('inactive');
var divId = $(this).attr('id');
var sisterLink = $('#pricing_nav ul li#'+divId);
sisterLink.removeClass('activeSection');
sisterLink.html(''+sisterLink.html()+''); //put link in between <li>.
//fadeIn the div with id of the link that has been clicked.
$('#pricing_body div#'+clickedId).fadeIn('500',function(){
$(this).addClass('active').removeClass('inactive');
var newActive = $('#pricing_nav ul li#'+clickedId);
});
});
});
});

Use live method to attach events to the elements. Here is the documentation.

Try:
$('#pricing_nav ul li a').live('click', function(){
---------
---------
---------
});
EDIT:
In reply of comment.
.live()
The .live() method is able to affect
elements that have not yet been added
to the DOM through the use of event
delegation: a handler bound to an
ancestor element is responsible for
events that are triggered on its
descendants.
.bind()
The .bind() method is the primary
means of attaching behavior to a
document. All JavaScript event types,
such as focus, mouseover, and resize,
are allowed for eventType.
Here is SO Question on this difference.

Related

SetAttribute Class of a dynamically created element - Javascript

I'm creating a hyperlink element dynamically and set its attribute class so when it is clicked it will trigger a function.
Here is the code for dynamically creating the hyperlink element:
editLink = document.createElement("a");
editLink.setAttribute("class", "edit-button");
This is what should happen when the link was clicked:
$(document).ready(function(){
$('.edit-button').click(function(event){
event.preventDefault();
var docHeight = $(document).height();
var scrollTop = $(window).scrollTop();
$('.overlay').show().css({'top': scrollTop + 'px'});
});
});
But nothing happens when it is clicked. Thank you in advance :)
Not sure if you are appending the created element with body. I make this changes and it is working fine
var editLink = document.createElement("a");
editLink.setAttribute("class", "edit-button");
editLink.innerHTML = "Click"; // added text for testing
window.document.body.appendChild(editLink); // Appending to body
$(document).ready(function(){
$('.edit-button').click(function(event){
event.preventDefault();
alert('1')
var docHeight = $(document).height();
var scrollTop = $(window).scrollTop();
$('.overlay').show().css({'top': scrollTop + 'px'});
});
});
jsfiddle
try this
var editLink = document.createElement("a");
editLink.setAttribute("class", "edit-button");
editLink.innerHTML = 'click';
document.body.appendChild(editLink);
$(function() {
$('.edit-button').on('click',function(event){
alert('clicked');
event.preventDefault();
var docHeight = $(document).height();
var scrollTop = $(window).scrollTop();
$('.overlay').show().css({'top': scrollTop + 'px'});
});
});
https://jsfiddle.net/s718ay3g/1/
Event Delegation is the way to do it.
When you add event to .edit-button directly, at the time of loading the document, browser attaches that event listener to only the currently existing .edit-button elements. It doesn't get executed automatically for the newly created elements with the same class.
What you could do is put your event biding and listener code in a function and call it each time you add a new element to the DOM. But that's considered a bad practice.
Welcome, Event Delegation.
The idea is to attach the event to a parent/ancestor element which is not dynamic and trigger the event only when the event target is your specified element( matched with some sort of selector like class or ID).
In your case, the updated event binding code would look like this.
$(document.body).on("click", ".edit-button", function(){
//whatever you want to do in here.
});
and then, you can continue to add classes to newly created elements like you did...
var editLink = document.createElement("a");
editLink.setAttribute("class", "edit-button");
The event would still work.
This way you only attach the event once.
If your buttons/links are going to be contained in a container div or something similar, attach the event to that container instead of body.
$(".class-of-the-container").on("click", ".edit-button", function(){
//whatever you want to do in here.
});

Append Div Class to Hyperlink Class — then Clone & Append Hyperlink To Container on Click

I want to append a div class ('.link-cloner') to a hyperlink class ('.link') when you hover over any hyperlink (that has the '.link' class).
Then when you click on the appended (.link-cloner) class, I want to clone the hyperlink it was appended to, and append that (link) to #container.
I'm almost there, I just can't make the last part work.
Codepen:
http://codepen.io/StrengthandFreedom/pen/JXEEQP/
I tried using find(), closest() & $(this) in various combinations, but I can't make it just clone the hyperlink (not the linkCloner) and append it to the #container.
jQuery:
$(document).ready(function(e) {
/* ------------------------
Part 1 — WORKS
--------------------------*/
// Store link-cloner div in variable
var linkCloner = $('<div class="link-cloner">Cloner</div>');
// When mouse hover over any hyperlink
$('.link').on('mouseover', function() {
// Append the link-cloner class to the hyperlink
$(this).append(linkCloner);
}).mouseleave(function() {
//on mouse leave, remove link-cloner
$(linkCloner).remove();
});
/* ------------------------
Part 2 — DOESN'T WORK
--------------------------*/
//Then when you click on the appended linkCloner,
clone the hyperlink and append it to the #container
$(linkCloner).on('click', function() {
// This code is wrong....
event.preventDefault();
$('.link').clone().append('<li></li>').appendTo('#container');
});
});
Can someone lead me in the right direction? JavaScript or jQuery, either is fine by me (I'm learning both) :-)
You have done just small mistake. Replace your PART 2 with below code :
$('.link').on('click', function(event) {
// This code is wrong....
event.preventDefault();
$(this).clone().append('<li></li>').appendTo('#container');
});
Try to use
$().drag();
for the clone that link to div check jquery documentations
Hope Help

jquery on click with not selector

I have data which is loaded via ajax and I would like to disable a click event on li element which has a class active, the below is what I tried. can someone help me out?
$('body').on("click", 'li *:not(.active)', function (e) {
//do something
}); //this doesn't work
You are targeting all non-active descendants of list items.
Remove the universal selector
Remove the descendant combinator
Such:
'li:not(.active)'
If the active class is on the li then remove the space and * (which targets all descendant elements that do not have the active class)
$('body').on("click", 'li:not(.active)', function (e) {
//do something
}); //this doesn't work
Um, that code is not looking at an li element, thatmselector is looking for a child of an li element. Get rid of the space and * and it will check the li.
li:not(.active)

click function within another click function is called multiple times

i am in touch with jquery for the first time and ran into this: I am trying to create a dynamic input-form. A click function creates a new list-item with another click function nested into it (to provide a remove function for the clicked item).
When i execute the nested click function it appears to be called the number of instances that have been created of it.
Here is the code (i tried to remove as much as possible, but i am not quite sure where the error is - so i guess i left to much stuff in - sorry).
$("#addIngredient").click(function(e){
e.preventDefault();
var prefix = "form-"
var last = $("#IngredientForm ul li").last().html();
$("#IngredientForm ul").append("<li>"+last+"</li>");
var name = $("#IngredientForm ul li:last input").attr("name");
name = name.replace(prefix,'');
var count = parseInt(name[0]);
count += 1;
$("#IngredientForm ul li:last input").attr("name",prefix+count+"-weight")
$("#IngredientForm ul li:last select").attr("name",prefix+count+"-ingredient")
$("#IngredientForm ul li:last input").attr("id","id_"+prefix+count+"-weight")
$("#IngredientForm ul li:last select").attr("id","id_"+prefix+count+"-ingredient")
$("#id_form-TOTAL_FORMS").val(count+1);
$(".deleteIngredient").click(function(e){
e.preventDefault();
var aktuell = $(this).closest('li');
var formCount;
name = aktuell.children('input').attr("name");
name = name.replace(prefix,'');
counter = name.replace("-weight",'');
formCount = parseInt($("#id_form-TOTAL_FORMS").val());
aktuell.remove();
--formCount;
$("#id_form-TOTAL_FORMS").val(formCount);
for (var i = parseInt(counter); i<formCount; i++){
var newName = "form-"+(i);
$("#id_form-"+(i+1)+"-weight").attr("name",newName+"-weight");
$("#id_form-"+(i+1)+"-ingredient").attr("name",newName+"-ingredient");
}
});
});
This block
$(".deleteIngredient").click(function(e){...
attaches a clickevent to all .deleteIngredient elements, also those created before.
You have to put this block outsite the click event of #addIngredient. You can make the delete event to be attached also to every element added in the future.
$("#addIngredient").click(function(e){
// ...
});
$(document).on("click", ".deleteIngredient", function(e){
// ...
});
As the other answers have noted, the click handler is adding a click handler to every .deleteIngredient element every time you run it, which adds multiple handlers to all the previous elements.
When you add a new item to the list, you don't have to add a click handler to it. You can use delegation to create a handler one time that will apply to dynamically-added elements:
$("#IngredientForm").on("click", ".deleteIngredient", function(e) {
...
});
See Event binding on dynamically created elements? for more information.
Every time that outer "click" event happens, you're adding another "click" handler for the ".deleteIngredient" element(s). The .click function does not remove previously-assigned event handlers.
You can get rid of old handlers with .unbind or, preferably with new versions of jQuery, .off:
$('.deleteIngredient').unbind('click').click(function(event) {
// ...
});
No, the thing is, here I think you probably want to bind to the .deleteIngredient button that you're adding for the new ingredient. The code you've got — based on the reference to $('.deleteIngredient') — will affect all of the elements on the page with that class. My guess here is that you're adding a button or something for each <li>. Thus, what you should probably be doing is finding the button inside the newly-added structure:
$('#IngredientForm ul li:last .deleteIngredient').click(function(event) {
// ...
});
Use this format instead
$("#addIngredient").on('click', function() {
$(this).off();
});

Writing this jQuery click function in JavaScript

I am slowly making my way from jQuery to vanilla JS, but I am struggling with wanting to write the following in JavaScript, would I have to setup a 'for' loop for each element? How would I target the child elements an an ID?
Here's what I would want to understand:
$('#id li').click(function(){
$(this).addClass('active');
});
I understand document getElementById to grab the '#id' but how would I achieve getting the child <li> elements? And how would I get the 'onclick' function to work for ANY list element clicked? Would I have to setup a 'for' loop for each element? Any help much appreciated!
Here is a JSFiddle that does what you want:
http://jsfiddle.net/digitalzebra/ZMXGC/10/
(function() {
var wrapper = document.getElementById("id");
var clickFunc = function(event) {
var target = event.originalTarget || event.target;
target.className = "active";
};
wrapper.addEventListener("click",clickFunc);
})();
A little bit of an explanation is in order...
First, I'm using a self executing function to fetch the wrapper div, using getElementById(). This is equivalent to using an id selector in jQuery: $('#id')
Next, I'm attaching a click handler to the element using the function addEventListener() and passing in an event type of click.
This binds the click handler function to the div element, the same as jQuery's click() would do. I'm using something called event bubbling, where a click event on any of the children of the wrapper will call the click handler attached to the wrapper.
Once the user clicks on the element, our function is called. originalTarget or target is the element that the user actually clicked in to, which in this case will always be an li. I'm then setting the class on that element to active.
Here is example for above question
http://jsfiddle.net/G3ADG/2/
(function() {
var id = document.getElementById("id");
var liele = id.getElementsByTagName("li");
for (var i = 0; i < liele.length; i++) {
liele[i].addEventListener("click", function () {
this.className = "active";
})
}
})();
Well I really liked Polaris878 solution as he is not using any loop inside it. In my solution first get HTML node information using document.getElementById this works similarly to $("#id"). than in next step I am fetching all tag type of "li" which are children of "id", than on this li tag array adding event listener to listen click functionality
className is one of attribute that allow to add class on that Node
I have tested above code in mozilla and chrome
This will work (IE >= 10), not want to search classList.add() replacement for IE<10,
var elems = document.querySelectorAll('#id li');
for (var i = 0; i < elems.length; i++) {
var elem=elems[i];
elem.addEventListener("click", function (e) {
this.classList.add('active');
});
}
fiddle

Categories

Resources