I'm using the Modaal library and want to dynamically load the content of the modal via Ajax, which requires sending the ID for each clicked item through to the callback.
I think I need to bind the clicked element to the modaal function, but am not sure how. I think that jQuery's on method.
Without binding, the popup works (but data is not updated for each item):
var info_popup = $('.info-popup');
info_popup.modaal({
after_open: function(ev){
console.log(info_popup.data('unique_id'));
}
});
When I bind the function, it returns the data, but a second click is required to launch the modal:
$('.info-popup').on('click', function() {
var unique_id = $(this).data('unique_id');
return $(this).modaal({
after_open: function(ev){
console.log(unique_id);
}
});
});
So I'm thinking I need to somehow forward the clicked status to Modaal, but not sure how.
Update
I can achieve this by setting the start_open parameter in Modaal to true, but not sure if this is an elegant approach, and would like to see how it would be done from outside of Modaal.
Related
I have AJAX calls attached in multiple places (unfortunately not only buttons, but also links, forms and other stuff), I know how to handle this manually (find every place I do an AJAX call and then block / overlay the button during first call), I'm wondering if there's a way to do it more automagically?
If we're talking jQuery - maybe a plugin? Something that will just work? :)
It'd be perfect to have something like:
if clicked element has .ajax class
block all ajax requests if the current one is still live
I'd then add .ajax class to every button/link/whatever triggering the request and voila. Does anything like this exist?
You can to create a global variable:
loadingAjax = false;
whenever an event triggers, you turn this variable to TRUE by using:
$("selector").click(function(){
if(!loadingAjax){
loadingAjax = true;
$.ajax(options)..
}
});
And you should turn loadingAjax back into false when the ajax stops:
$( document ).ajaxStop(function() {
loadingAjax = false
});
I have looked high and low and can't seem to find this anywhere. Does anyone know how to get the value of a row tapped in a listview? This can be anything from the name to the index in the object. Right now I have a function that handles the tap. I need to be able to pass a value to the new page I am loading when it transitions. I thought I could do it here:
$('#taskListTable').delegate('li', 'tap', function () {
console.log('clicked');
//Insert code here to pull a value from either an index or a name and save it
});
I thought maybe it would be good to do it in the hash? I am not sure what the standard practice is here on the web coming from native iOS dev though. Anyone have any pointers? Thanks.
This is how I am populating my listview:
$.each(tasks, function(index, task) {
$taskList.append("<li><a href='taskDetails.html'> <h3>"+task.name+"</h3><p>"+task.description+"</p></a></li>");
});
taskDetails.html needs the index of the task so I can pull the details down from the server. What is the standard practice for doing that?
To get the index of the taped list-item you can do this:
$('#taskListTable').delegate('li', 'tap', function () {
console.log('clicked');
var index = $(this).index();
});
Yup, that's it. Although this assumes that the <li> element are all siblings.
Docs for .index(): http://api.jquery.com/index
If you want to then transition to the new page:
$('#taskListTable').delegate('li', 'tap', function () {
console.log('clicked');
$.mobile.changePage($(this).find('a').attr('href'), {
data : { selectedIndex : $(this).index() }
});
});
This will get the new page and attach the selectedIndex variable as a query string parameter that is set to the index of the tapped list-item.
Also, to be able to prevent the default behavior of clicking on the link in the list-item, I would attach this event handler to the link elements:
$('#taskListTable').delegate('a', 'tap', function (event) {
event.preventDefault();
console.log('link clicked');
$.mobile.changePage($(this).attr('href'), {
data : { selectedIndex : $(this).closest('li').index() }
});
});
The "delegate" method is deprecated on new versions of jQuery.
Consider using this instead:
$('#taskListTable').on('tap', 'a', function (event) {
}
Here is another method of getting an id, especially useful if you have a database enabled app and the id you are searching for is the database's id, not the row index:
When filling the table consider this:
<ul id="taskListTable">
<li id="task400" class="tasks">Task with db id 400</li>
<li id="task295" class="tasks">Task with db id 295</li>
</ul>
$('#taskListTable').on('tap', 'li', function (event) {
variable = $(this).attr('id').substr(4);
}
That will get the database id which you can pass on to your other pages.
To get the name out, you could do:
$(this).find('h3').html()
Alternatively, you can use something in the markup like the id or a data attribute to provide a better handle than the name.
What about this approach?
$taskList.append("<li><a href='taskDetails.html?id=" + task.id + "'></a><h3>" + task.name + "</h3>...</li>");
And then retreive id parameter.
Jasper's solution is good, but if you have any other code in your event handler that edits the DOM, the "this" keyword could be pointed somewhere entirely different by the time it gets used in your code.
I've cracked my head on my keyboard a number of times because my users said "I click on item one, but that always opens the edit screen for the last item in the list." So somehow using 'this' was not the right way to go.
Also, when I tried event.target, event.currentTarget or event.originalTarget, those didn't work either. They all pointed to the jQueryMobile "page" that was visible by the time the code got to run (which wasn't even the same page where the table was located).
The safe and/or intended approach is to:
use event.originalEvent.srcElement instead of 'this'
not use .delegate(), but use .on()
bind the event using $(document).on(), not $('#table').on()
So that would result in:
$(document).on('tap','#taskListTable li',function(event){
//The properties of 'event' relate to $(document), not to '#taskListTable li',
//so avoid .currentTarget, .target etc.
//But fortunately 'event' does have one property that refers to the original
//user event.
var theOriginalTapEvent = event.originalEvent;
var theRealClickedElement = theOriginalTapEvent.srcElement;
//Note that the clicked element could be a sub-element of the li
//whose index you want. So just referencing theRealClickedItem could
//could still be getting you bad results.
var theRelevantListItem = $(theRealClickedElement).parents('li');
//Now you're ready to get the item's index or whatever.
})
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)
I am writing an Ajax application which uses a callback function to add a card to a players hand. the object is created correctly and the menu for each object is also created correctly.
when created the DOM object, in the callback function i use to add the object, i have some code like this:
$("#card"+cardNum).live('click',function(){
$('#cardDiag'+cardNum).dialog('open');
}));
it works when the first card is created, but after i draw the second card, clicking on the first one causes it to now open up the menu for the second card. and after the second card is played (and i delete its menu) clicking on any card does nothing until a new card is drawn once again.
this basically is what i am doing in the callback handler for ajax.
function displayDrawnCardInHand(data){
var newCard = document.createElement('div');
//set some stuff on newCard
//and then add the cardyourHand = document.getElementById('hand'); yourHand.appendChild(newCard);
var cardMenu = document.createElement('div'); cardMenu.id= 'cardDiag' + data[cardNum];
//and then add the cardMenu to the DOM and call the click hander
Edit
Now I see your problem: cardNum will always be evaluated for each click event, so it will be the same for each card no matter what the value was when you first assigned the click event. You'll have to store it in the #card as a data value:
$("#card"+cardNum).live('click',function(){
num = $(this).data("num");
$('#cardDiag'+num).dialog('open');
})).data("num", cardNum);
Provide more code
Use Firebug (your HTML may be getting borked)
Also, I would recommend doing something like binding the event outside the $.ajax call:
$("div[id^=card]").live('click', function() { /* do binding */ });
I'm trying to stop the browser from following certain links, rather I want to unhide some Divs when they are clicked.
I'm having trouble just getting the links to not be followed though.
Here's what I have:
var titles = $('a.highlight');
jquery.each(titles, function(){
this.click(function(){
return false;
});
});
It seems like the click handler is not being assigned. What am I missing?
Try
this.click(function(e){ e.preventDefault(); }
Actually, it looks like you might need to use the jQuery constructor on this:
$(this).click(function(){ return false; }
You could also try using parameters on the each function instead of using this:
jQuery.each( titles, function(index, elem) { $(elem).click( function() { return false; } ) } );
Personally, I would just do titles.each( ... though. In that instance you can use this to bind the click handler. I am not sure off the top of my head what this binds to with jQuery.each
Or just calling click on titles:
titles.click( function() { return false; } )
That will bind click to every element in titles. You don't need to loop through them.
You can compress that jquery a bit:
$('a.highlight').click(function() { return false; });
You should also make sure that:
There are no other click handlers registered for those elements later on.
The code you have is attaching after the elements have loaded. If they're not completely loaded, they won't be found in the $('a.highlight') selector. The easiest way to do this is to put your code in a $(document).ready(function() { *** code here *** }); block.
Edit: As per other responses - the problem was that this represents a DOM object, while $(this) is a jquery object. To use the .click function to attach a handler, you need a jquery object.
In short, using this inside the each loop won't work with what you're trying to do. You'll need to get a jquery representation by using $(this) instead.