We have an unordered list with id #some-list. In our Backbone implementation, when certain data is returned, list entries are rendered and appended to the list and the list is displayed.
We want to detect when such change is completed using JQuery. We used $(#some-list).ready() and $(#some-list).load(), but it looks like they are not working.
What are some ways to capture such change? Could anyone shed some lights here?
Well you didn't post any code so it's really hard to see guess where you fail.
But in general what i would do is trigger a custom event on the ajax callback (you do use ajax to get the content and appending it to the list right?).
for example:
loadData(){
// invoke the ajax request
var def = $.get(...);
def.then(function(result){
// $(#ul) append(result) ...
// now trigger the custom event
$(document).trigger('listRendred');
});
}
Now on a different place or script you can listen to it:
$(document).on('listRendred', function(e){ // do what ever... })
Since you are using BackboneJS you could try to listen to its events.
To find out which events you could use, try following code (replace my * placeholders first) and have a look inside your browser's console.
*backboneobject*.on("all", function(e) {
console.log(e)
});
Afterwards just listen for the event by using
*backboneobject*.on("*yourevent*", function() {
doStuff();
});
Related
I am not great at javascript/jquery for the most part but I know how to get some software to work. But my issue is that I have a whole bunch of
$("body").on("click", "button#thisid", function(event) {
//do stuff here
});
There are alot of the on clicks that use jquery post and get functions but they all have tiny and simple differences that i need to have get sent through. I dont want every single button to have an onclick event but I am not sure how to bind the event to a large list of items that need to have it attached to.
I have been trying to come up with some way to slim all these down but I want to have the best approach instead a whole bunch of crash and fails. So I am reaching out to people who know more than me in order to lead me in the correct path.
Please help
Considering your elements are dynamically injected, you will need to apply the click handler to an element that always exist on page load:
$(document).ready(function() {
$(document).on("click", "button.target", function() {
console.log($(this)[0].id);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="1" class="target">One</button>
<button id="2" class="target">Two</button>
In the above example, the click handler is applied to document, and triggers whenever a button element with the class of target is clicked, running the code inside the function.
To combine the .get() and .post() functions, you'll have to find synonymous data. Keep in mind that you have access to $(this), so you can extract the relevant ID if need be :)
Hope this helps!
I dont exactly get what you want to do...
But the $("body") is the jquery selector which defines on which elements your listener will be bound to.
So if you want to create a listener for more different elements the probably easiest solution is creating a class like "listenedElement" which you give to every element you want the listener to react to and write write the selector like this
$('.listenedElement').on( "click", function() {});
If you just look for click listeners this one looks pretty nice as well:
https://api.jquery.com/click/
A nice way I find is having a one line for each button like so:
$('#model').on('click', openModel());
$('#openDropdown').on('click', openDropdown());
$('#shoppingCart').on('click', shoppingCart());
And then defining each of these functions:
function openModel() {
// Stuff here
}
function openDropdown() {
// Stuff here
}
function shoppingCart() {
// Stuff here
}
So instead of writing the function as a parameter, I find it neater to just do it separately and call it like above.
With jQuery, is it possible to add elements to a previously defined event handler? I realize the right way to do this would be to define the handler using on() so that dynamically inserted elements will be included, but the issue is the handler I'm trying to extend is defined by code on a server that I don't have access to. The server outputs code like this at the top of the file:
$('#wrapper .block h2').click(function() {
//do stuff
});
Then, towards the bottom of the page, I've added some custom javascript code that inserts another #wrapper .block h2 element. I'm wondering if there is any way for me to include this new element in the event handler that was defined by the code at the top of the page where the click handler was registered.
Or, is there any way for me to programmatically access the callback function that was defined for that event handler? That way I could recreate it myself using the on() method.
To achieve this you need to access internal event handles stored by jQuery. In previous versions (prior to 1.8) you could do it using Data API, like $('.some').data('events'). However it's no longer available. However you can still access element data object with $._data method. Then you would do something like this:
var events = $._data($(selector)[0], 'events'),
click = events && events.click;
if (click) $el.on('click', click[0].handler);
However be aware that $._data is a private property, and there is no guarantee that it will not change one day (like previously you could access element data with $.cache, but it's gone now).
Demo: http://jsfiddle.net/dfsq/e94hau62/
It should be possible for you just to write a new event handler on the same action, it should replace the old one and leave the action to your new one.
Try it out in the console or commandline.
The simplest way is, you define the handle in server side, it will be like,
var yourhandler = function() {
//do stuff
});
Then after you load your new elements, you can hood the "yourhandler" to them, like,
$( document ).ready(function() {
$('#wrapper .block h2').click(yourhandler);
});
So i have a page in my site that has a with class name 'mainContent' that automatically updates with new data every like 1 minute using AJAX .ajax(). Content in this requires some JavaScript for some functionalities. The problem now is that JavaScript does not work on the new data loaded into the DOM without whole page refresh. I have searched and found using .on() to bind the data to the DOM should work, like so:
$(document).on('click', '.mainContent',function(){
expand();
});
where expand is a JS function.
However, it only works fully on the new data but not on the data that had been added in the previous AJAX call...
You're almost there, it's just your logic. This is how this jQuery function works:
You set a container. This is the element that will hold the AJAX-crated items that you want to bind. The more specific, the better. Otherwise, you'll wire an event for your whole page, which is bad
The event. What are you listening to?
Who will fire the handler. A selector to form the phrase: when these guys inside this big guy fire this event, run this code.
Let's suppose that your mainContent gets filled with hyperlinks (I'm not sure because your question lacks on details):
$('.mainContent').on('click', 'a', function () {
//do your magic
//$(this) is the clicked link
});
This way, our phrase is: when links inside .mainContent are clicked, run this.
UPDATE
Based on the comments, I think that your problem may be on the expand function.
Let's give a try:
$('.mainContent').on('click', 'a', function () {
$(this).simpleexpand();
});
Have you try to apply your binding on the callback of the ajax function that load your new datas ?
Something like that :
$.ajax({
url: url...//Classic ajax call
}).done(function ( data ) {
//Apply your 'on' here
});
Alright, so I'm making a Facebook-style chat. But that doesn't really matter.
See here:
http://jsfiddle.net/SkHme/7/
Nice and pretty, right? Well, there's a problem. Notice this line:
<div class="conversation EmperorCuzco" onclick="setActive('EmperorCuzco')">
See the onclick attribute? Well, it's not working. However, I have confirmed that the function itself DOES work. (if you run it just like that in the JavaScript, it runs like a dream) I have further confirmed that the function is not the problem by attempting to replace the onclick value with a simple alert('blah'), but that doesn't work either.
So, what's up? I'm guessing that something in my JavaScript is somehow disabling something, but I have absolutely no idea what it could be, nor how I could go about fixing it. I did some web searching, but couldn't find anything that helps.
What's going on?
Your setActive function is defined inside the scope of the $(document).ready handler. Move the function outside that function so that it is in the global scope.
Right now it looks like this:
$(document).ready(function()
{
// ...
function setActive(new_conversation)
{
// ...
}
});
Now change that to:
$(document).ready(function()
{
// ...
});
function setActive(new_conversation)
{
// ...
}
Really though, you should separate your content from your interactions and bind those event handlers in your script itself. Something like:
// Refers to the last clicked conversation *button*
// Initialize to empty jQuery object
var $active_conversation = $([]);
// Binding on #chat, targeting click events on .conversation_button children
$("#chat").on("click", ".conversation_button", function() {
// Hide currently active conversation
$active_conversation.hide();
$active_conversation.siblings('.conversation_button').removeClass("selected");
// Set as currently active conversation button
// Note: this refers to the clicked <div class="conversation_button">
var $this = $(this);
$active_conversation = $this.siblings('.conversation');
// Show this conversation
$active_conversation.show();
$this.removeClass("alert").addClass("selected");
});
Some advantages of this approach:
You don't need different classes for different conversations. By storing the actual conversation DOM element (as a jQuery object) in $active_conversation, the conversation can be identified without any extra processing.
You can add and remove whole list items with a conversation without assigning new event handlers. In the sample above, the event handler for all .conversation_button elements is defined at the level of #chat. For more about this binding mechanism, read up on .on (or .delegate for pre-1.7).
Here, have an updated fiddle! :-)
If all you say is really true (bad mistakes happen), the only thing that can make this is that an other event handler which takes your event before uses stopPropagation() or return false;
A quick check that can do is replace onclick with onmousedown or onmouseup, and see if you alert become visible.
I have some code in which I am creating an dijit.Dialog with an Ajax call(href property) to populate the contents.
I what to parse the returned content to dojo.connect a click event to the links in the returned content.
But when I do a dojo.query("a",this.current_popup.domNode) I get an empty array back
Does anybody know how can get can attach a onclick to all the returned content?
Paul
It is less expensive to just bind an event handler to the DOM node of the Dialog widget, and use event delegation to capture any "a" clicks. This way, you can avoid any event handler cleanup, particularly if the contents of the Dialog change frequently. You can avoid the event handler cleanup if you use the widget's connect method to do the work.
So, if you are doing the connect inside a method in the dijit.Dialog, you could use something like:
this.connect("onclick", function(evt){
var node = evt.target;
if("a" == node.nodeName.toLowerCase()){
//node is an a tag, do what you want with it,
//for example, read node.href to get the URL attached to it.
//If you want to prevent following that URL and prevent further
//event bubbling, stop the event:
dojo.stopEvent(evt);
}
});
If you are doing this connection work outside the widget instance, instead of using this.connect, use widgetInstance.connect(), assuming widgetInstance is a variable that refers to the dijit.Dialog instance.
By using that version of connect, the widget will automatically unregister the event handler when the Dialog widget is destroyed, keeping the memory profile in check.
One way I found to do this was to add a delayed connect to the widget
dojo.connect(this.current_popup, "onDownloadEnd", function(){
dojo.query("a.popup",this.current_popup).forEach(function(node) {
// add your function add here
});
});
This runs after the ajax call is complete so you can now find the objects in the DOM