I'm super confused by my code. Let me show what it looks like:
$(document).ready(function ($) {
var customer_exists = false;
$.get(window.additional_parameters.customer_exists_url, "json")
.done(function () {
customer_exists = true;
})
.always(function () {
// Don't make request to buy clickable until we know if the customer exists
$('#request-to-buy').on('click', function(e) {
request_to_buy(customer_exists);
});
});
function request_to_buy(customer_exists) {
response = can_request_to_buy();
response.done(function (response) {
if (customer_exists) {
// Actually create the request on the server
$.post(window.additional_parameters.request_to_buy_url,
{'ticket_id': window.additional_parameters.ticket_id},
"json")
.done(function (response) {
request_to_buy_success(response);
})
.fail(function () {
var message = handle_ajax_response(response);
show_ajax_message(message);
});
} else {
show_pre_stripe_popup();
}
})
.fail(function (response) {
var error_message = handle_ajax_response(response);
show_ajax_message(error_message, 'danger');
});
}
$(document).ready(), we set a variable called customer_exists. This variable guides the path of the code afterwards and is pretty important. If the $.get AJAX request is successful, it's true, otherwise it remains it default value of false. After the AJAX response, we attach a click event to "#request-to-buy." My goal here is to create a closure and pass in the value of customer_exists that was just set. This doesn't happen.
A good portion of the time ( I had it work correctly once or twice ), when I inspect request_to_buy in the debugger, I can see that customer_exists is a jQuery click event. why ??? Shouldn't it take on the value of the customer_exists from the surrounding scope of where the function was created? Can anyone explain what is going on here?
Thank you
EDIT: Here's a little more information that describes how it works sometimes...
The first time that I click '#request-to-buy', the handler is
function(e) {
request_to_buy(customer_exists);
}
This is what we would expect. e contains the click event, customer_exists retains it's value, and everything works inside request_to_buy.
Every time I click '#request-to-buy' after the first, instead of the above function being called, request_to_buy is called directly, and instead of passing in customer_exists in the first parameter, the click event is passed in instead. I hope this helps someone.
You should be able to do this without the need for the cumbersome outer var customer_exists.
For example :
$(document).ready(function ($) {
$.get(window.additional_parameters.customer_exists_url, "json").then(function () {
// Don't make request to buy clickable until we know if the customer exists
$('#request-to-buy').on('click', request_to_buy);
}, function() {
$('#request-to-buy').on('click', show_pre_stripe_popup);
});
function request_to_buy(e) {
e.preventDefault();
can_request_to_buy().then(function(response) {
// Actually create the request on the server
$.post(window.additional_parameters.request_to_buy_url, {
'ticket_id': window.additional_parameters.ticket_id
}, "json").then(request_to_buy_success, function() {
show_ajax_message(handle_ajax_response(response));
});
}).fail(function(response) {
show_ajax_message(handle_ajax_response(response), 'danger');
});
}
}
show_pre_stripe_popup will also be passed an event and you may need to do e.preventDefault(); there too.
You will need to check that the correct parameters are passed to the various error handlers. I can't verify them.
If it still doesn't work, then you must suspect other code that's not included in the question, for example the function can_request_to_buy().
var customer_exists = false;
Declare this outside of ready block.
Related
I'm aware that this can be achieved via a Promise but I am struggling to figure out how.
jQuery('.parentDiv').on('click', '.link', function(e) {
jQuery.when(jQuery('.saveBtn').trigger('click', { 'evtData': 'link' })).then(function {
// rest of the logic that should be performed on click of .link
});
});
The click of .saveBtn calls a function named doAjax:
jQuery('.saveBtn').on('click', function() {
doAjax()
});
function doAjax() {
var ajaxCall = jQuery.ajax(ajaxObject);
ajaxCall.done(function(data, status, xhr) {
//some logic go here
});
return ajaxCall;
}
Despite this the logic inside the .then handler is getting executed first i.e before doAjax completes.
I believe I need to change the jQuery.when(jQuery('.saveBtn').trigger('click',{'evtData':'link'})) as it may not be getting the Promise state which it should and immediately getting marked as Resolved thereby executing the callback without waiting?.
I tried return doAjax in .saveBtn but that also did not make a difference.
Ideas please.
The issue is because trigger() is not an async function, so then is called immediately. It would make far more sense to just call doAjax() directly from the click of .link instead of faking DOM events. Try this:
jQuery(function($) {
$('.parentDiv').on('click', '.link', function(e) {
doAjax().then(function {
// rest of the logic that should be performed on click of .link
});
});
$('.saveBtn').on('click', function() {
doAjax()
});
function doAjax() {
var ajaxCall = $.ajax(ajaxObject);
ajaxCall.done(function(data, status, xhr) {
// some logic go here
});
return ajaxCall;
}
});
My problems seems basic, yet I have tried a lot of different ways of putting these functions on one html file to no avail. The problem is that, when the 1st function is called, the second also runs, leaving me with the results of the second function all the time. I have no idea what I am doing wrong, please help. Here is the code in question.
<script>
$(document).ready(function () { // Make sure the elements are loaded on the page
// Listen for a click event on the button
$('#buttonON').click(funct);
$('#buttonOFF').click(funct2);
});
// Now define the function
function favfunct(e) {
// Stop the page from "following" the button (ie. submitting the form)
e.preventDefault();
e.stopPropagation();
// Insert AJAX call here...
$.ajax("carstatusupd.php", {
// Pass our data to the server
data: { "username" : "sibusiso", "caron" : "1", "caroff" : "0"},
// Pass using the appropriate method
method: "POST",
// When the request is completed and successful, run this code.
success: function (response) {
// Successfully added to favorites. JS code goes here for this condition.
}
});
function funct2(e) {
// Stop the page from "following" the button (ie. submitting the form)
e.preventDefault();
e.stopPropagation();
// Insert AJAX call here...
$.ajax("carstatusupd.php", {
// Pass our data to the server
data: { "username" : "sibusiso", "caron" : "0", "caroff" : "1"},
// Pass using the appropriate method
method: "POST",
// When the request is completed and successful, run this code.
success: function (response) {
// Successfully added to favorites. JS code goes here for this condition.
}
});
}
</script>
You have omitted the closing brace from the function favfunct().
Please use this,
<script>
$(document).ready(function () {
function funOne(){
};
function funTwo(){
};
$('#buttonON').live('click',function(){
funOne();
});
$('#buttonOFF').live('click',function(){
funTwo();
});
});
NOte: initialize function before use and initialize them into document ready.
I'm trying to call a function and not the alert and I thought it was as easy as just doing something like this: FunctionsName(); and delete the alert(''); but it's not working for me :(
Can someone please look at the code I have below and tell me what is wrong ?
Thank you so much!!
<script type="text/javascript">
var comper;
function checkComper() {
var onResponse = function(comperNow) {
if (comper === undefined) {
comper = comperNow;
return;
}
if (comper !== comperNow) {
// show a message to the visitor
alert("New Info Added"); // <--*** I WANT TO TAKE THIS OUT AND CALL $("#append").click(function(e)
comper = comperNow;
}
};
$.get('getlastupdate.php', onResponse);
}
var tid = setInterval(checkComper, 2000);
$(function() {
var $table = $("table.tablesorter");
$("#append").click(function(e) {
e.preventDefault();
$.get('updatetable.php', function(data)
{
$table
.find('tbody')
.html('')
.append(data);
$table.trigger("update", [true]);
});
});
/*........ and so on.... */
</script>
What about changin that :
alert("New Info Added");
to that :
$('#append').trigger('click');
It will simulate a click and trigger the function.
One thing important to distinguish:
alert("New Info Added") is a function. Actually, alert() is a function, being passed the parameter "New Info Added".
$('#append').click(function(e) { is not a function, at least, not in the same way. $('#append') is a jQuery selector function, which selects all elements with an id of "append". $('#append').click() is a function that sets a click event on all elements returned in the selector.
What the whole syntax of $('#append').click(function(e) { means is on its own a syntax error. What you're doing is telling the elements found in the selector what their click function should be. But the function(e) { says that it's the start of the code of the function. That line of code isn't complete until the ending }) - the } closing the function declaration and the ) closing the call to click.
So, you can't simply replace alert("New Info Added"), which is a complete function call, with $('#append').click(function(e) {, because it's a syntax error - you haven't completed the function(e) declaration, nor the click function call. You can trigger the click function, as Karl's answer told you. Or, you can use the shortcut:
$('#append').click()
Note that this is a full proper sentence, and can therefore replace the alert.
I'm trying to run a function twice. Once when the page loads, and then again on click. Not sure what I'm doing wrong. Here is my code:
$('div').each(function truncate() {
$(this).addClass('closed').children().slice(0,2).show().find('.truncate').show();
});
$('.truncate').click(function() {
if ($(this).parent().hasClass('closed')) {
$(this).parent().removeClass('closed').addClass('open').children().show();
}
else if ($(this).parent().hasClass('open')) {
$(this).parent().removeClass('open').addClass('closed');
$('div').truncate();
$(this).show();
}
});
The problem is on line 13 where I call the truncate(); function a second time. Any idea why it's not working?
Edit jsFiddle here: http://jsfiddle.net/g6PLu/
That's a named function literal.
The name is only visible within the scope of the function.
Therefore, truncate doesn't exist outside of the handler.
Instead, create a normal function and pass it to each():
function truncate() { ...}
$('div').each(truncate);
What's the error message do you get?
You should create function and then call it as per requirement
Define the function
function truncate(){
$('div').each(function(){
});
}
Then call the function
truncate();
Another approach is to establish, then trigger, a custom event :
$('div').on('truncate', function() {
$(this).......;
}).trigger('truncate');
Then, wherever else you need the same action, trigger the event again.
To truncate all divs :
$('div').trigger('truncate');
Similarly you can truncate just one particular div :
$('div#myDiv').trigger('truncate');
The only prerequisite is that the custom event handler has been attached, so ...
$('p').trigger('truncate');
would do nothing because a truncate handler has not been established for p elements.
I know there's already an accepted answer, but I think the best solution would be a plugin http://jsfiddle.net/g6PLu/13/ It seems to be in the spirit of what the OP wants (to be able to call $('div').truncate). And makes for much cleaner code
(function($) {
$.fn.truncate = function() {
this.addClass('closed').children(":not('.truncate')").hide().slice(0,2).show();
};
$.fn.untruncate = function() {
this.removeClass('closed').children().show();
};
})(jQuery);
$('div').truncate();
$('.truncate').click(function() {
var $parent = $(this).parent();
if ($parent.hasClass('closed')) {
$parent.untruncate();
} else {
$parent.truncate();
}
});
I have a JavaScript file here http://www.problemio.com/js/problemio.js and I am trying to place some jQuery code into it that looks like this:
$(document).ready(function()
{
queue = new Object;
queue.login = false;
var $dialog = $('#loginpopup')
.dialog({
autoOpen: false,
title: 'Login Dialog'
});
var $problemId = $('#theProblemId', '#loginpopup');
$("#newprofile").click(function ()
{
$("#login_div").hide();
$("#newprofileform").show();
});
// Called right away after someone clicks on the vote up link
$('.vote_up').click(function()
{
var problem_id = $(this).attr("data-problem_id");
queue.voteUp = $(this).attr('problem_id');
voteUp(problem_id);
//Return false to prevent page navigation
return false;
});
var voteUp = function(problem_id)
{
alert ("In vote up function, problem_id: " + problem_id );
queue.voteUp = problem_id;
var dataString = 'problem_id=' + problem_id + '&vote=+';
if ( queue.login = false)
{
// Call the ajax to try to log in...or the dialog box to log in. requireLogin()
}
else
{
// The person is actually logged in so lets have him vote
$.ajax({
type: "POST",
url: "/problems/vote.php",
dataType: "json",
data: dataString,
success: function(data)
{
alert ("vote success, data: " + data);
// Try to update the vote count on the page
//$('p').each(function()
//{
//on each paragraph in the page:
// $(this).find('span').each()
// {
//find each span within the paragraph being iterated over
// }
//}
},
error : function(data)
{
alert ("vote error");
errorMessage = data.responseText;
if ( errorMessage == "not_logged_in" )
{
//set the current problem id to the one within the dialog
$problemId.val(problem_id);
// Try to create the popup that asks user to log in.
$dialog.dialog('open');
alert ("after dialog was open");
// prevent the default action, e.g., following a link
return false;
}
else
{
alert ("not");
}
} // End of error case
}
}); // Closing AJAX call.
};
$('.vote_down').click(function()
{
alert("down");
problem_id = $(this).attr("data-problem_id");
var dataString = 'problem_id='+ problem_id + '&vote=-';
//Return false to prevent page navigation
return false;
});
$('#loginButton', '#loginpopup').click(function()
{
alert("in login button fnction");
$.ajax({
url:'url to do the login',
success:function() {
//now call cote up
voteUp($problemId.val());
}
});
});
});
</script>
There are two reasons why I am trying to do that:
1) I am guessing this is just good practice (hopefully it will be easier to keep track of my global variables, etc.
2) More importantly, I am trying to call the voteUp(someId) function in the original code from the problemio.js file, and I am getting an error that it is an undefined function, so I figured I'd have better luck calling that function if it was in a global scope. Am I correct in my approach?
So can I just copy/paste the code I placed into this question into the problemio.js file, or do I have to remove certain parts of it like the opening/closing tags? What about the document.ready() function? Should I just have one of those in the global file? Or should I have multiple of them and that won't hurt?
Thanks!!
1) I am guessing this is just good practice (hopefully it will be
easier to keep track of my global variables, etc.
Yes and no, you now have your 'global' variables in one spot but the chances that you're going to collide with 'Global' variables (ie those defined by the browser) have increased 100% :)
For example say you decided to have a variable called location, as soon as you give that variable a value the browser decides to fly off to another URL because location is a reserved word for redirecting.
The solution to this is to use namespacing, as described here
2) More importantly, I am trying to call the voteUp(someId) function
in the original code from the problemio.js file, and I am getting an
error that it is an undefined function, so I figured I'd have better
luck calling that function if it was in a global scope. Am I correct
in my approach?
Here's an example using namespacing that will call the voteUp function:
(function($) {
var myApp = {};
$('.vote_up').click(function(e) {
e.preventDefault();
myApp.voteUp();
});
myApp.voteUp = function() {
console.log("vote!");
}
})(jQuery);
What about the document.ready() function? Should I just have one of
those in the global file? Or should I have multiple of them and that
won't hurt?
You can have as many document.ready listeners as you need, you are not overriding document.ready you are listening for that event to fire and then defining what will happen. You could even have them in separate javascript files.
Be sure your page is finding the jquery file BEFORE this file is included in the page. If jquery is not there first you will get function not defined. Otherwise, you might have other things conflicting with your jquery, I would look into jquery noConflict.
var j = jQuery.noConflict();
as seen here:
http://api.jquery.com/jQuery.noConflict/
Happy haxin
_wryteowl
Extending what KreeK has already provided: there's no need to define your "myApp" within the document ready function. Without testing, I don't know off the top of my head if doing so is a potential source for scope issues. However, I CAN say that the pattern below will not have scope problems. If this doesn't work, the undefined is possibly a script-loading issue (loading in the right order, for example) rather than scope.
var myApp = myApp || {}; // just adds extra insurance, making sure "myApp" isn't taken
myApp.voteUp = function() {
console.log("vote!");
}
$(function() { // or whatever syntax you prefer for document ready
$('.vote_up').click(function(e) {
e.preventDefault();
myApp.voteUp();
});
});