I'm trying to use AJAX loading a set of sucessive pages in a main page, as I show you in the next picture:
I learned (thanks to this community!) to call other pages' content, by assigning the load() function to the onclick event of a button, like this:
$(document).ready(function() {
$('#btn').click(function() {
$('#result').load('./poi-data-no-heading.html');
});
});
But what if I have one button with id="btn" on every page? The functionality of any button with that id will be the same always, because (I think) the document.ready is not triggered when I use the load() method, so it's never replaced with new functionality.
E.g. initial functionality should be navigate from page 1 to page 2, and when page 2 is loaded, the functionality should be to navigate from page 2 to page 3.
As Js developer, I would do the following:
<!-- In the HTML file -->
<button id="btn" onclick="loadContent()">Load</button>
<div id="result"></div>
/* In the JS file */
function loadContent(){
/*the code to retrieve content*/
$('#result').load('http://fiddle.jshell.net/webdevem/JfcJp/show/');
}
This way I could assign the functionality to every button, no matter what's the ID or if the document.ready is triggered. But mixing Js with JQuery is not an option... So, how do you think I should manage to do something similar with JQuery?
Thanks in advance.
P/d: Here is a useful fiddle I used to try ideas: http://jsfiddle.net/gal007/vkcug7t7/1/
You could use the on() event from jQuery, which can listen for events on elements dynamically rendered (you can't do that with the click() method). So in this case you have to listen to the event on a parent element, one that doesn't change with the load method. On that button, use an HTML5 data-* attribute to define the id that you wish to load.
HTML:
<btn id="result" data-load-id="1">Load</btn>
Javascript:
$('#container').on('click', '#result', function() {
var id_to_load = $(this).data('load-id');
load('/url?' + id_to_load);
});
I've updated your fiddle : jsfiddle
Related
I've created simple button:
<button type="button" class="btn btn-success link-accept" data-id="16">Accept</button>
with corresponding listener:
$(document).ready(function() {
$('.link-accept').on('click', function(event){
console.log('accepted');
});
});
Everything works okay.
Then I introduced AJAX-based dynamic (refreshless, you name it) navigation on my page using this function:
function ajaxLoadContent(pageurl){
$('#content').addClass("grey");
$.ajax({url:pageurl+'?rel=tab',success: function(data){
var title=$(data).filter('title').text();
var keywords=$(data).filter('meta[name=keywords]').attr('content');
var description=$(data).filter('meta[name=description]').attr('content');
var mdlTitle=$(data).find('.mdl-layout-title').html();
var content=$(data).find('#content').html();
var scripts=$(data).filter('#scripts').html();
document.title = title;
$('meta[name=keywords]').attr('content', keywords);
$('meta[name=description]').attr('content', description);
$('.mdl-layout-title').html(mdlTitle);
$('#content').html(content);
$('#scripts').html(scripts);
$('#content').removeClass("grey");
window.scrollTo(0, 0);
$(document).trigger("content-refreshed");
console.log('triggered content-refresh');
}});
}
And now my listener isn't working. I guess it's something about that dynamic refresh.
I've tried:
Listening to content-refreshed event - it fires, but isn't caught by my listener inside dynamically loaded page
Moved content of my $(document).ready anonymous function to separete function and called it at the bottom of the page - function is not defined.
Extracted content of my $('.link-accept').on('click') to separate function and called it with <button onclick="function()"> - function is not defined
I'm out of ideas now... It looks like it doesn't execute that code at all if loaded dynamically. What should I do? I guess eval is not an option here...
EDIT
I'm sure that dynamically loaded javascript isn't ran at all. Pure console.log at the top of <script> section doesn't work either. So I guess my primary task is to evaluate that code first - then it should work just right.
Change first snippet to:
$(document).on('click', '.link-accept', function(event){
console.log('accepted');
});
It will work then.
Otherwise it will just search for all .link-accept items first and then attach the handler once to the found objects. Nothing will update after your ajax request.
In my code snippets it is more dynamic. It binds the click to the document. If you click on any object on the document it will check if it is a .link-accept element. More dynamic and better performance.
I'm using underscore to create some elements and appending them to a div with jQuery.
At the bottom of the page I'm using jQuery's .on() to respond to clicks on the elements.
$('.pickup').on('click',
function(e) {
alert("hello");
}
);
Via some user interaction (in Google maps), I've got to add more elements to the div and want them to respond to clicks as well. For some reason they do not. I've pared it all down on jsfiddle:
http://jsfiddle.net/thunderrabbit/3GvPX/
When the page loads, note that clicking on the lines in output will alert('hello') via jQuery.
But click the [add] button and the new lines do not respond to clicks.
My HTML
<div id="unit_2225" class="pickup">
<span>Click me; I was here first</span>
</div>
<script type="text/template" id="unit-template">
<div class="unit-item">
<span class="pickup">
<span>click us (<%= unit_id %>) via underscore</span>
</span>
</div>
</script>
<div id="divID">
</div>
<button>add</button>
My Javascript
var addUnitToDiv = function(key,val) {
console.log(val);
var template = _.template($('#unit-template').html(),val);
$('#divID').append(template);
}
var unit_ids = [{unit_id:'hello'},
{unit_id:'click'},
{unit_id:'us'},
{unit_id:'too'},
{unit_id:112}];
$.each(unit_ids, addUnitToDiv);
var unit_pids = [{unit_id:'we'},
{unit_id:'wont'},
{unit_id:'respond'},
{unit_id:'to'},
{unit_id:'clicks'},
{unit_id:358}];
createMore = function() {
$.each(unit_pids, addUnitToDiv);
}
$('.pickup').on('click','span',function() {
alert("hello");
});
$('button').click(createMore);
I found a similarly worded question but couldn't figure out how to apply its answer here.
Instead of binding events directly to the elements, bind one event to their container element, and delegate it:
$("#divID").on("click", ".pickup", function () {
// Your event handler code
});
DEMO: http://jsfiddle.net/3GvPX/3/
In this case, the event handler is only executed for elements inside of the container #divID that have the class "pickup".
And in your scenario, the elements are being added to the element with an id of "divID". Thus, where the two selectors came from.
This is handy because, as you've found out, dynamically adding elements doesn't magically bind event handlers; event handlers bound normally with .on() are only executed (bound) on those present at the time of binding.
It could even help if you change the delegated selector to "span.pickup" (if you know the elements will always be a <span> like in your template), so that the DOM is filtered by the tag name first.
Reference:
http://api.jquery.com/on/#direct-and-delegated-events
Working demo http://jsfiddle.net/u2KjJ/
http://api.jquery.com/on/
The .on() method attaches event handlers to the currently selected set of elements in the jQuery object. You can attach the handler on the document level.
Hope it fits the need, :)
code try the code changed below
$(document).on('click','.pickup',function() {
alert("hello");
});
I have very simple jQuery Accordion, it is working fine, now the issues are if i load the accordion content dynamically either from DB or from JSON to page, It is not working, because there is no information to DOM to understand the class or ID which newly injected. so i am trying to use Jquery ON instead live or delegate to capture the injected elements. my sample code is..
jQuery("#header").on("click", function () {
.... my accordion code here
});
but jquery "on" will trigger on any event like click or something, so how to process the accordion html content to keep open in initial level and do further click.
How is this possible? i couldn't fine any solution
Check this: http://jsfiddle.net/RMBpt/
What i added:
var isActive = $(this).is('.on');
if(!isActive) { .. if active, it shouldn't collapse? }
//First element should be active, needs to be after the hide()
$('.accordionButton:first').addClass('on').next().slideDown('normal');
Try using it like this:
$("#wrapper").on("click", ".accordionButton", function(event){
//Your accordian code here
});
i am modifying the inner html through javascript, and the inner html involves a button
but when i put in the jquery code to run on the button click event it fails to do so ..
sorry but im a newb when it comes to javascript
content im adding into the html ..
function add()
{
var val=document.getElementById("ans").value;
document.getElementById("answers").innerHTML+="<tr><td>"+val+"<br/><p align=\"right\"><button class=\"replyb\">replies</button></p>"+"</td></tr>";
document.getElementById("ans").value="";
}
jquery code ...
enter code here
At a guess, because we don't have your jQuery, I would say you need to use .live() instead of .click() when you change the HTML the button will be NEW to the DOM.
When you apply your jQuery code, it adds any calls like .click() to any DOM item, when the page loads. So any NEW element doesn't have a .click() handler added to them.
Do solve this, you can change your .click():
$('#someitem').click(function() {
.....
});
To something like this:
$('#someitem').live('click', function() {
.....
}
Add the following in your page at some place and it will handle clicks to all .replyb buttons whether you add them with javascript at any time, or not.
$(function(){
$('button.replyb').live('click', function(){
alert('clicked on button');
});
});
have a look at jquery .live() method
I am trying to achieve this task using MooTools.
Description:
I attached an event listener to myButton link. A click on this link initiates an AJAX request and updates myDiv content based on the response text.
During this request a POST variable is being sent to "button.php", but it's not used at the moment.. (i wish to use it later)
OK, as a result, myDiv gets exactly the same link with the same ID (myButton) + a random number, so that we could see that each click generates a new number.
The problem:
After the first click on myButton, myDiv updates correctly, showing a random number. When I click myButton for the second time (this time in newly updated div), the div does not refresh anymore.
Please note that I need myButton to be inside myDiv, and myDiv must be updated (refreshed) after each click without having to refresh the entire page.
Can somebody show me how to achieve this task based on this simplified code example?
index.html
<html>
<head>
<script type="text/javascript" src="mootools-1.2.4-core-nc.js"></script>
<script>
window.addEvent('domready', function() {
$('myButton').addEvent('click', function(e) {
e.stop();
var myRequest = new Request({
method: 'post',
url: 'button.php',
data: {
action : 'test'
},
onRequest: function() {
$('myDiv').innerHTML = '<img src="images/loading.gif" />';
},
onComplete: function(response) {
$('myDiv').innerHTML = response;
}
});
myRequest.send();
$('myButton').removeEvent('click');
});
});
</script>
</head>
<body>
<div id="myDiv">
<a id="myButton" href="#">Button</a>
</div>
</body>
</html>
button.php
<a id="myButton" href="#">Button</a> clicked <?php echo rand(1,100); ?>
Look at Element.Delegation to setup the event on the myDiv container one time, so you don't have to re-attach handlers each time the contents are updated. You need to include this MooTools-More extension in your scripts as it's not part of core yet, but will be starting from version 1.3.
$("myDiv").addEvent("click:relay(a)", function() {
...
);
If you have multiple <a> links inside, and you only want to delegate a specific subset of those, add a class or some other property to distinguish them. You can use almost any selector inside relay(..). Let's say all links had a class updateTrigger added to them:
<a class="updateTrigger" id="myButton" href="#">Button</a>
the syntax would then be:
$("myDiv").addEvent("click:relay(a.updateTrigger)", function() {
...
});
See this working example where links are replaced every 5 seconds. There is only one event setup on the myDiv container and it handles all clicks to all <a>s, even the dynamic ones.
you are attaching an event to an element that you are replacing. the dom has no way of knowing that to you, the old and the new button are identical. The old button is deleted (and the event listener with it) and the new button created. So you need to re-attach the event to the new button.
That said: why does the button have to be inside the div? The mind boggles. You can always update the button text from javascript, there's no need to replace it and keep creating new listener objects.