Dynamic button click doesn't work in Jquery - javascript

I want to develop dynamic presentation content in HTML5 presentation from
http://www.script-tutorials.com/creating-an-attractive-presentation-with-html5/
This tutorial is ok for static content . But I want to write dynamic content with jquery as the following:
$(document).ready(function(){
$.getJSON(url, function (data) {
for(var i in data)
{
output=" <button title='Next' id='nav-next' class='nav-next'>Click</button>";
}
$("#placeholder").append(output);
});
});
When click on button , I want to go next slide. But this event does not work. I want to call next function on javascript file. Please help.

You said "When click on button" and that is the answer use jQuery.on() method.
$('#nav-next').on('click',(function () {
// click code.
});
and then when you created DOM with id defined in .on will have click event dynamically attached.

You're not attaching an event to the new button, this can be done using the jQuery click method.
Also some other problems:
the loop seems to be redundant, you're not actually using anything in data.
output is being defined as a global variable in your example, use var to keep it in function scope.
Code:
$(document).ready(function() {
$.getJSON(url, function (data) {
// use var, your output was a global variable
var output = " <button title='Next' id='nav-next' class='nav-next'>Click</button>";
$("#placeholder").append(output);
// attach the click event to the new button
$('#nav-next').click(function () {
// TODO: Implement click method
});
});
});
Since you're not using data you can remove the call to getJSON safely currently. I assume you put it in for some reason though.

Related

jQuery get attribute of clicked element when content is dynamically generated

I am working on a site where a lot of content is generated dynamically using AngularJS. I need to get the attribute of an element that is dynamically generated using jQuery, but I am having trouble doing so. I have already figured out that I need to use the .on method to click rather than .click. My issue is finding the equivalent of $(this) within the .on method.
Here is my code:
$(document.body).on('click', 'a.card-topic-link' ,function(e) {
e.preventDefault(); // Prevent default action - this works
console.log('The click works!'); // This fires and works just fine
var cardTopicLink = $(this).attr('data-topic-link'); // This is where the problem lies
console.log(cardTopicLink); // This is undefined
}); // End on click
As I stated before, this does not work as the .click does not work for dynamic content:
$('a.card-topic-link').click(function(e) {
e.preventDefault(); // Prevent default action
var cardTopicLink = $(this).attr('data-topic-link');
console.log(cardTopicLink);
});
I feel like there is a simple solution to this problem that I am having trouble finding. The key to this issue is that this is dealing with dynamic content.
Let me know if you have any ideas.
use e.currentTarget, instead of var cardTopicLink = $(this).attr('data-topic-link');, try var cardTopicLink = angular.element(e.currentTarget).attr('data-topic-link');
$(document).ready(function () {
$(document.body).on('click', 'a.card-topic-link' ,function(e) {
e.preventDefault(); // Prevent default action - this works
console.log('The click works!'); // This fires and works just fine
var cardTopicLink = $(e.currentTarget).attr('data-topic-link'); // This is where the problem lies
console.log(cardTopicLink);
}); // End on click
});
plunker with similar code, firing on async loaded content - http://plnkr.co/edit/02rqCrbBVwXiIYff8ktC?p=preview
It turns out that AngularJS was stripping out the attribute data-topic-link as it was parsed. This was happening because the HTML that contained the data-topic-link was passed as a part of the response that Angular was printing in an ng-repeat.
I updated the code so that the HTML with this attribute did not need to be served by AngularJS.

how to handle click event on dynamic content?

i have this HTML code on a page when my page loaded:
<div class="divmain">Add
<span class="spn">123</span>
</div>
when you click on that span it will create another span and show hi alert to you,
when the page loaded for the first time it works fine and write another span on that dive as the same the old span but after that if you click on the new span it works not.
i did some test and found if i add this code :
$('.spn').on("click", function (e) {
showalert(this);
});
on the "spanwriter" function it will works , i mean if that function be like this:
function spanwriter(master) {
var rows = '<span class=\'spn\'>123</span>';
$('.divmain').html(rows);
<------- this event must be add here until it --------------->
$('.spn').on("click", function (e) { works
showalert(this);
});
}
why i should add click event at the end of wrote content until span can get that event and works?
i used jquery-1.10.2.js on my sample
my all codes are:
$(function () {
$('.divmain').on("click", function (e) {
spanwriter(this);
});
$('.spn').on("click", function (e) {
showalert(this);
});
});
function spanwriter(master) {
var rows = '<span class=\'spn\'>123</span>';
$('.divmain').html(rows);
}
function showalert(master) {
alert("hi");
}
you have to do the same but with document.on("click")
$(document).on("click", ".buttonClass", function() { console.log("inside"); });
$('.divmain').on("click" make a kind of binding when document is loaded, so when you add dynamix elements to the dom it is noit catched. Whith the use od document.on, it works even if you add dynamic content to the document.
The simplest and best solution to your problem is to attach the event listener to a parent element in the dom and pass the second parameter of the on() method as described in the jQuery documentation (http://api.jquery.com/on/)
In other words you should have something along the lines of:
$('body').on("click", ".spn", function (e) {
showalert(this);
spanwriter(this);
});
and then have the spanwriter() add the new span to the parent of the element it's been called upon.
I hope this is what you were looking for and answers your question.

How to pass dynamic values to event listener

I am using a server side technology (JSP) to render my views. Therefore I have a for loop that loops through a list. Now, I want to bind a click listener to a button that is rendered for each item in the list. The code in the click listener needs the item ID, which I don't understand how to pass to the JavaScript code.
I also use requirejs, if that matter to the solution.
Maybe you just don't need to pass the html ID to your javascript. You can use a css class to retrieve your buttons in your DOM. The javascript code depends of what framework you use.
In native javascript, you can retrieve your buttons like this :
var buttons = document.querySelectorAll('button.my_class');
Just replace my_class by what you want.
You can access a button id by doing this :
var button_id = buttons[0].id
If you want to attach the item id to the button, you can use a data attribute. For example :
<button id="my_button" data-id="item_id" />
In the javascript, you can access to data_id like this :
var item_id = buttons[0].getAttribute('data-id');
In most event handlers, this is the DOM node that triggered the event, so something like this works:
button.onclick = function() {
alert(this.id);
}
Here is the live example
If you were using jQuery and requirejs this would be like this:
require(['jQuery'], function ($) {
$('.container_element').on('click', '.button_class', function () {
console.log('You have clicked button with id ', $(this).attr('id'));
})
})

jQuery: Get reference to click event and trigger it later?

I want to wrap an existing click event in some extra code.
Basically I have a multi part form in an accordion and I want to trigger validation on the accordion header click. The accordion code is used elsewhere and I don't want to change it.
Here's what I've tried:
//Take the click events off the accordion elements and wrap them to trigger validation
$('.accordion h1').each(function (index, value) {
var currentAccordion = $(value);
//Get reference to original click
var originalClick = currentAccordion.click;
//unbind original click
currentAccordion.unbind('click');
//bind new event
currentAccordion.click(function () {
//Trigger validation
if ($('#aspnetForm').valid()) {
current = parseInt($(this).next().find('.calculate-step').attr('data-step'));
//Call original click.
originalClick();
}
});
});
jQuery throws an error because it's trying to do this.trigger inside the originalClick function and I don't think this is what jQuery expects it to be.
EDIT: Updated code. This works but it is a bit ugly!
//Take the click events off the accordion elements and wrap them to trigger validation
$('.accordion h1').each(function (index, value) {
var currentAccordion = $(value);
var originalClick = currentAccordion.data("events")['click'][0].handler;
currentAccordion.unbind('click');
currentAccordion.click(function (e) {
if ($('#aspnetForm').valid()) {
current = parseInt($(this).next().find('.calculate-step').attr('data-step'));
$.proxy(originalClick, currentAccordion)(e);
}
});
});
I think this:
var originalClick = currentAccordion.click;
Isn't actually doing what you think it is - you're capturing a reference to the jQuery click function, rather than event handler you added, so when you call originalClick() it's equivalent to: $(value).click()
I finally came up with something reliable:
$(".remove").each(function(){
// get all our click events and store them
var x = $._data($(this)[0], "events");
var y = {}
for(i in x.click)
{
if(x.click[i].handler)
{
y[i] = x.click[i].handler;
}
}
// stop our click event from running
$(this).off("click")
// re-add our click event with a confirmation
$(this).click(function(){
if(confirm("Are you sure?"))
{
// if they click yes, run click events!
for(i in y)
{
y[i]()
}
return true;
}
// if they click cancel, return false
return false;
})
})
This may seem a bit weird (why do we store the click events in the variable "y"?)
Originally I tried to run the handlers in x.click, but they seem to be destroyed when we call .off("click"). Creating a copy of the handlers in a separate variable "y" worked. Sorry I don't have an in depth explanation, but I believe the .off("click") method removes the click event from our document, along with the handlers.
http://www.frankforte.ca/blog/32/unbind-a-click-event-store-it-and-re-add-the-event-later-with-jquery/
I'm not a jQuery user, but in Javascript, you can set the context of the this keyword.
In jQuery, you use the $.proxy() method to do this.
$.proxy(originalClick, value);
originalClick();
Personally, I'd look at creating callback hooks in your Accordion, or making use of existing callbacks (if they exist) that trigger when opening or closing an accordion pane.
Hope that helps :)
currentAccordion.click is a jQuery function, not the actual event.
Starting with a brute-force approach, what you'd need to do is:
Save references to all the currently bound handlers
Unbind them
Add your own handler, and fire the saved ones when needed
Make sure new handlers bound to click are catched too
This looks like a job for an event filter plugin, but I couldn't find one. If the last point is not required in your application, then it's a bit simpler.
Edit: After some research, the bindIf function shown here looks to be what you'd need (or at least give a general direction)

How to elegantly disable/enable all jQuery UI buttons?

I currently have several action buttons in different pages, and each button performs some AJAX call when clicked. In another word, I have code like this all over the places:-
$("#searchButton")
.button()
.click(function() {
...
$.get(url, { data: ...}, function(data) { ... });
...
});
After doing some testing, it seems like some AJAX calls take at least more than a few seconds to process before the callback function is being called.
My plan is to disable the button when the AJAX call is made and enable it back when the AJAX call is completed. This is to prevent user from clicking the button too many times when the request is being processed. One solution I found is to utilize the unbind() and bind() functions. After modifying my code, it looks like this now:-
var searchButtonClickHandler = function() {
...
$.get(url, { data: ...}, function(data) { ... });
...
};
$("#searchButton")
.button()
.ajaxStart(function() {
$(this).button("disable").unbind("click");
})
.ajaxStop(function() {
$(this).button("enable").bind("click", searchButtonClickHandler);
})
.click(searchButtonClickHandler);
This code works fine. Basically, it removes the click handler when the AJAX call is made and addes the click handler back when the AJAX call is completed.
My question is... is it possible to generalize the button disabling/enabling so that I don't have to implement ajaxStart() and ajaxStop on all UI buttons?
Ideally, I would like to use my earlier code snippet to register only the click event handler on the button, and then enable/disable all buttons using the .ui-button selector, something like this...
$(".ui-button")
.ajaxStart(function() {
$(this).button("disable").unbind("click");
})
.ajaxStop(function() {
// not sure how to bind the handler here
$(this).button("enable").bind("click", ?? );
});
... but, this doesn't work and I run into trouble in binding the click handler here.
The more I think about it, it almost seems like I need to create a button builder function to do this, for example:-
var createButton = function(selectorName, clickHandler) {
$(selectorName)
.button()
.ajaxStart(function() {
$(this).button("disable").unbind("click");
})
.ajaxStop(function() {
$(this).button("enable").bind("click", clickHandler);
})
.click(clickHandler);
};
// create button like this
createButton("#searchButton", function() {
...
$.get(url, { data: ...}, function(data) { ... });
...
});
... but this approach will only disable/enable the selected button, and I want to apply that to all UI buttons.
Do anyone has a better approach in disabling/enabling all the buttons in the page?
Thanks.
Different approach, according to this answer you should be able to get a reference to your previous event handler via .data("events");
Putting that together with your sample it should look like this:
$(".ui-button")
.ajaxStart(function() {
var events = $(this).data("events");
$(this).data("oldEvent", events.click[0]);
$(this).button("disable").unbind("click", events.click[0]);
})
.ajaxStop(function() {
var oldClick = $(this).data("oldEvent");
$(this).button("enable").bind("click", oldClick.handler);
});
Not sure if this will work completely yet, still messing around on jsfiddle.
Update
This should work, example on jsfiddle.
you can use $('input[type=button]').attr('disabled','disable'); to disable all buttons instead of binding and unbinding click event to the buttons... also you can use deferred jquery object, here is an example
Maybe you could attach your handler to the parent element of your buttons with delegate? That way there's only one handler function to bind/unbind.
Yahoo hosts a getElementByClass function, and you could assign a class such as "disableMe" to all your UI buttons. Then use getElementByClass('disableMe') to return an array of all the elements you want to disable.
The link: http://developer.yahoo.com/yui/dom/
You can use
$("button").each(function(){
//your code here
});

Categories

Resources