I have an script that uses jquery, but i have a problem in the next part:
$("#botonAgregar").click(function() {
$.ajax({
type: "GET",
url: $(this).attr('href'),
success: function(html) {
$("#dialogDiv").html(html);
$("#dialogDiv").dialog('open');
}
});
alert();
$("a[type='submit']").click(function() {
var formName = $(this).attr("nombreform");
var formSelector = "form#" + formName;
$(formSelector).submit();
});
return false;
});
It works as it is, but if i remove the "alert();" line it doesnt add the click event to $("a[type='submit']") objects. What could be wrong?
it doesnt add the click event to $("a[type='submit']") objects
Yes it does. However, if more of those elements are being added during the AJAX call then you'll need to re-add the handler to those new elements after those are added to the DOM. Currently you're not doing that because the code after your call to .ajax() is happening before the AJAX call completes. This is because AJAX is, by definition, asynchronous. It's possible for the AJAX call to complete before later code is executed, but it is not guaranteed. (And in the case of code that's immediately after it, it's highly unlikely.)
Your success handler is called when the AJAX call completes, so that would be an opportune time to do this:
$("#dialogDiv").html(html);
$("#dialogDiv").dialog('open');
$("a[type='submit']").click(function() {
var formName = $(this).attr("nombreform");
var formSelector = "form#" + formName;
$(formSelector).submit();
});
However, there is a much better way to do this.
One of the problems with the approach you have is that you're going to re-add the handler to the same elements over and over. You're also adding the same handler to many elements, when you really only need one. Take a look at the jQuery .on() function. Essentially what it does is add a single handler to a common parent element of the target elements, and then filter the events based on the target element selector. So you only need to add the handler once:
$(function () {
$(document).on('click', 'a[type=submit]', function () {
var formName = $(this).attr('nombreform');
var formSelector = 'form#' + formName;
$(formSelector).submit();
});
});
In this case I'm using document as the common parent, though any other parent will work. (The body tag, a div which contains all of the target elements, etc. It just needs to be a common parent element which doesn't change throughout the life of the DOM.)
Related
i have got a little problem here. I have to trigger an event which contains $.post() to load a form and assign it to a DOM. After this is done, i have edit the fields of the form.
I tried:
$.when(function(){
$('#type_rank_field').trigger('change'); //calls the $.post() to load the form
})
.done(function(){
$('#quest_'+questions[i].split('|')[1]).children('option[value="'+questions[i].split('|')[0]+'"]').attr('selected',true);
});
Unfortunately this doesnt work and if i leave it just like that:
$('#type_rank_field').trigger('change');
$('#quest_'+questions[i].split('|')[1]).children('option[value="'+questions[i].split('|')[0]+'"]').attr('selected',true);
The change even looks like this:
$('#type_rank_field').live('change',function(){
var id = $(this).children('option:selected').attr('id');
var id_edited = get_id_from_id(id);
$.post('ajax/load_questions_of_rank.ajax.php',{id: id_edited},function(data){
//alert(data);
$('#rank_fields').html(data);
});
});
Then the form editation is executed before the form is properly loaded and attached to DOM. This might be a stupid question for JavaScript guys, but i am mainly a PHP guy so dont be cruel :-)
Thanks
Can separate out your change handler code? Something like this:
$('#type_rank_field').on('change',function(){
handleChange($(this));
});
function handleChange(elem, callback) {
var id = elem.children('option:selected').attr('id');
var id_edited = get_id_from_id(id);
$.post('ajax/load_questions_of_rank.ajax.php',{id: id_edited},function(data){
//alert(data);
$('#rank_fields').html(data);
if (typeof callback === "function") {
callback(data);
}
});
};
Then instead of triggering the change you can just call handleChange passing a callback to execute when the AJAX call is complete:
handleChange($("#type_rank_field"), function(data) {
$('#quest_'+questions[i].split('|')[1])
.children('option[value="'+questions[i].split('|')[0]+'"]')
.attr('selected',true);
});
Return the promise object from your event handler:
$(document).on('change','#type_rank_field',function(){
var id = $(this).children('option:selected').attr('id');
var id_edited = get_id_from_id(id);
return $.post('ajax/load_questions_of_rank.ajax.php',{id: id_edited},function(data){
//alert(data);
$('#rank_fields').html(data);
});
});
and then use triggerHandler() instead.
var promise = $('#type_rank_field').triggerHandler('change');
promise && promise.done(function(){
// do stuff
});
Here's a simple example showing the functionality being used: http://jsfiddle.net/WQPXt/
I think we have to add callback after posted
$('#type_rank_field').on('change', function(ev, cb){
var id = $(this).children('option:selected').attr('id');
var id_edited = get_id_from_id(id);
$.post('ajax/load_questions_of_rank.ajax.php',{id: id_edited},function(data){
//alert(data);
$('#rank_fields').html(data);
// add after callback to make sure that html is inserted
if(typeof cb == "function"){
cb.apply($(this)) // this apply with the jq object context or another context u want
}
});
the trigger change will look like this
$('#type_rank_field').trigger('change', [function(){
$('#quest_'+questions[i].split('|')[1]).children('option[value="'+questions[i].split('|')[0]+'"]').attr('selected',true);
}]);
.live has been deprecated in jQuery since v1.7, and has been removed in v1.9.
You should replace it with .on().
.on has 2 signatures for binding elements, whereas .live only had 1.
If the element exists at the time you are binding, you do it like this:
$('.element').on('click', function(){
.......
});
You can even use the shorthand:
$('.element').click(function(){
.........
});
If the element does not exist at the time, or new ones will be added (which is what .live was normally used for), you need to use "event delegation":
$(document).on('click', '.element', function(){
........
});
NOTE: You want to bind to the closest static element, not always document.
In the meantime, the jQuery Migrate plugin can be used to restore the .live() functionality if you upgrade your jQuery to the newest version.
I have this little function :
$('.chrnumberpickerDiv select').change(function(){
var sel = $(this),
value = sel.closest('.chrnumberpickerDiv').find('.chrnumberpickerDivText');
value.text(sel.find(':selected').text());
}).one('change');
My problem is that I also need to trigger it on DOM load. I have tried .trigger('change') instead of .one('change') but it seems like it goes in a loop and never stops refreshing my page. So what could I be doing to trigger the event on DOM but without causing any damages to other events or whatever makes the function go in a loop ?
If I understood your question, you need to trigger a function when the select changes, as well as programmatically trigger it when the page loads to populate an initial value:
// define the handler
var changeHandler = function() {
var sel = $(this),
value = sel.closest('.chrnumberpickerDiv').find('.chrnumberpickerDivText');
value.text(sel.find(':selected').text());
};
// bind the handler
$('.chrnumberpickerDiv select').change(changeHandler);
$(document).ready(function () {
// execute the handler on page load
// use proxy to change what "this" means in the handler
// (jQuery does this for you when you bind a handler through jQuery)
$.proxy(changeHandler, $('.chrnumberpickerDiv select')[0]));
});
Documentation for proxy
Try this, instead of your code
$(document).ready(function() {
$('.chrnumberpickerDiv select').change(function(){
var sel = $(this),
value = sel.closest('.chrnumberpickerDiv').find('.chrnumberpickerDivText');
value.text(sel.find(':selected').text());
}).one('change');
});
you have be careful not to assign multiple change functions. Otherwise all of them are called when the change event happens.
I am using the following code to load two underscore.js templates. Once the first link is clicked, the skeleton template is loaded. The first trigger executes the find bind, which executes the loadBookmarks function correctly, but the 'loaded' trigger never fires and the loadFriendBookmarks never executes. Why is this? Is there another way to make this happen?
$('#bookmarks-link').click(function() {
$('#bookmarks-count').text("0");
var skeleton = modalTemplate();
$('#bookmarks').append(skeleton);
$('#bookmarks').trigger('skeleton');
});
$('#bookmarks').bind('skeleton', function() {
$('#bookmarks .thumbnails').loadBookmarks( getBookmarksUrl(1) );
// If I add an alert('hi') here, it works perfectly.
$('#bookmarks').trigger('loaded');
});
$('#bookmarks').bind('loaded', function() {
$('#bookmarks .thumbnails a').each(function() {
$(this).bind('click', function() {
$('#bookmarks .bookmarks-table tbody').empty();
$('#bookmarks .bookmarks-table tbody').loadFriendBookmarks(
getFriendBookmarksUrl($(this).attr('data-item'))
);
});
});
});
So interesting enough, the triggers do work correctly: If I stick an alert in between loadBookmarks and trigger, everything works fine. If I take it out, then it doesn't. Any idea why?
Based on your description and common sense, it sounds like loadBookmarks() loads data from a remote source, such as an ajax call. This means that trigger('loaded') can fire before loadBookmarks() has received the data. You can add a callback argument to loadBookmarks() and trigger the event there:
$('#bookmarks .thumbnails').loadBookmarks( getBookmarksUrl(1) , function() {
$('#bookmarks').trigger('loaded');
});
But this requires your loadBookmarks to know to call this function after it receives the data and creates the needed HTML - I can't demonstrate this without seeing the actual code you have in loadBookmarks.
Additional suggestion: don't bind handlers this way, use event delegation instead:
$('#bookmarks').on('click', '.thumbnails a', function(e) {
e.preventDefault(); // don't want the link to actually be followed, do we
var url = getFriendBookmarksUrl($(this).attr('data-item'));
if(url) { // in case it's clicked before the data attribute is set
var $tbody = $('#bookmarks .bookmarks-table tbody');
$tbody.empty();
$tbody.loadFriendBookmarks(url);
}
});
This means that all elements matching the selector '#bookmarks .thumbnails a' will call this click handler, even if they were added to the document after you called on. Meaning you can delegate these events even before calling loadBookmarks, removing the need for the loaded event at all. Plus, this way you only have one copy of the handler function in memory, as opposed to your bind which created a separate copy of the function for each a node.
the problem is else where in your code. probably some js error in loadBookmarks* functions.
see:
http://jsfiddle.net/BBESV/
triggers work perfectly
I load a form and dynamically populate a select via AJAX from a PHP file. Before implementing the dynamic AJAX populated select, my change function works (it just shows another input when a user selects 'other'). Now the change function does not work.
I know the ready function is firing because the jStepper functions run. I have tried this with the change function in and outside the ready function. I have a feeling the change function loads before the AJAX get is finished, but does that really matter?
var types = "<select name='ve_categoryNo' id='ve_categoryNo'>";
var d = new Date();
$.get('scripts/vehicle_category_feed.php?date=' + d.getTime(), function ($type)
{
$($type).find('type').each(function ()
{
types += "<option value='" + $(this).attr("categoryno") + "'>" + $(this).attr("category") + "</option>";
});
types += "<option value='other'>Other(Specify)</option></select>";
$('#ve_categoryNo_td').html(types);
});
$(document).ready(function ()
{
$('input[type=text]').click(function ()
{
$(this).select();
});
$('#vehicle_entry').ajaxForm(function ()
{
showMessage('vehicle_information_added');
});
$('#ve_ariNo').jStepper({minValue: 1, maxValue: 99999999});
$('#ve_fleetNo').jStepper({minValue: 1, maxValue: 999999999});
$('#ve_vehicleYear').jStepper();
$('#ve_purchasePrice').jStepper({minValue: 0});
$('#ve_categoryNo').change(function ()
{
if ((this.value) == "other")
{
$('#otherCategory').show();
$('#otherCategory input[type=text]').focus();
} else
{
$('#otherCategory').hide();
}
});
});
modify this:
$('#ve_categoryNo').change(function() {
to
$(document).on('change', '#ve_categoryNo', function() {
EDIT3: This would perform the best after an examination of your code more closely:
$('#ve_categoryNo_td').on('change', '#ve_categoryNo', function() {
as it binds closest to the element in question.
You should also put the ajax call inside the ready script I would think.
The reason this is occuring is that there is nothing in the DOM to bind to when it is instantiated. Using the .on in this manner binds it to the document instead. If you had another "fixed" element that wraps it, it might be better to bind to that using that in place of "document" as it would likely perform better.
EDIT: Note that you COULD also add the change event management after you inject the element as part of the ajax call completion, but if you do this more than once, you should unbind it first in that case.
EDIT2: since there are questions/comments:
FROM THE DOCUMENTATION: http://api.jquery.com/on/
Attaching many delegated event handlers near the top of the document
tree can degrade performance. Each time the event occurs, jQuery must
compare all selectors of all attached events of that type to every
element in the path from the event target up to the top of the
document. For best performance, attach delegated events at a document
location as close as possible to the target elements. Avoid excessive
use of document or document.body for delegated events on large
documents.
I think the element you are binding to in the line:
$('#ve_categoryNo').change(function() { ...
does not yet exist in the DOM, so the event does not get bound.
Try using the .live function:
$('#ve_categoryNo').live('change', function() { ... });
Or make sure that your DOM elements exist before you try to bind events to them.
Worked from document ready to change works Ajax functionality
$(document).change(function(){
$("#next").click(function() {
var questionid = $('#question').val();
var assementid = $('#assement').val();
var userid = $('#user').val();
if($('.ansradio').is(':checked')) {
var answer = $('input[name=ans]:checked', '#questionajax').val();
$.ajax({
type: "POST",
url: "answer/",
data: "q_id="+questionid+"&a_id="+assementid+"&answer="+answer+"&user_id="+userid,
success: function(html){
$("#questionajax").html(html).show();
}
});
}
else{
alert("Please answer the questions");
}
});
});
I need my script to do something on the first time an element is clicked and continue to do something different on click 2,3,4 and so on
$('selector').click(function() {
//I would realy like this variable to be updated
var click = 0;
if (click === 0) {
do this
var click = 1;
} else {
do this
}
});//end click
really I think it should rely on the variables but I can't think of how to update the variable from here on out any help would be awesome.
Have a look at jQuery's .data() method. Consider your example:
$('selector').click(function() {
var $this = $(this),
clickNum = $this.data('clickNum');
if (!clickNum) clickNum = 1;
alert(clickNum);
$this.data('clickNum', ++clickNum);
});
See a working example here: http://jsfiddle.net/uaaft/
Use data to persist your state with the element.
In your click handler,
use
$(this).data('number_of_clicks')
to retrieve the value and
$(this).data('number_of_clicks',some_value)
to set it.
Note: $(this).data('number_of_clicks') will return false if it hasn't been set yet
Edit: fixed link
Another alternative might be to have two functions, and bind one using the one function in $(document).ready() (or wherever you are binding your handlers), and in that function, bind the second function to be run for all subsequent clicks using bind or click.
e.g.
function FirstTime(element) {
// do stuff the first time round here
$(element.target).click(AllOtherTimes);
}
function AllOtherTimes(element) {
// do stuff all subsequent times here
}
$(function() {
$('selector').one('click', FirstTime);
});
This is super easy in vanilla Js. This is using proper, different click handlers
const onNextTimes = function(e) {
// Do this after all but first click
};
node.addEventListener("click", function onFirstTime(e) {
node.addEventListener("click", onNextTimes);
}, {once : true});
Documentation, CanIUse
If you just need sequences of fixed behaviors, you can do this:
$('selector').toggle(function(){...}, function(){...}, function(){...},...);
Event handlers in the toggle method will be called orderly.
$('#foo').one('click', function() {
alert('This will be displayed only once.');
});
this would bind click event to Corresponding Html element once and unbind it automatically after first event rendering.
Or alternatively u could the following:
$("#foo").bind('click',function(){
// Some activity
$("#foo").unbind("click");
// bind it to some other event handler.
});