We're trying to upgrade our jquery using jquery migrate.
We get the "JQMIGRATE: Global events are undocumented and deprecated" on this code (a wrapper for jquery.ajax):
ajaxPost: function (url, jsonData, successCallback, async) {
if (async == null) {
async = true;
}
var ajaxSettings = {
url: url,
type: 'POST',
async: async,
data: JSON.stringify(jsonData),
contentType: 'application/json; charset=UTF-8',
success: function (data, code, xht) {
successCallback(data, code, xht);
},
error: function (xht, errorType, exception) {
console.log(...);
}
};
$.ajax(ajaxSettings);
}
The "error" occurs for this line:
successCallback(data, code, xht);
We're not sure how to fix it?!
This is a piece of code from JQMIGRATE responsible for warning
// Turn global events into document-triggered events
jQuery.event.trigger = function( event, data, elem, onlyHandlers ){
if ( !elem && !rajaxEvent.test( event ) ) {
migrateWarn( "Global events are undocumented and deprecated" );
}
return eventTrigger.call( this, event, data, elem || document, onlyHandlers );
};
Looks like this warning is popping on trigger() calls in two cases:
1) no element is specified as trigger context
2) event is global ajax event
Global ajax event example:
$(document).bind("ajaxSend", function(){
$("#loading").show();
}).bind("ajaxComplete", function(){
$("#loading").hide();
});
But if you say you had disabled global events by setting jQuery.ajaxSetup({global: false}), then
problem could be caused by case 1, but i dont see any code releavant to it in the provided fragment.
Probably you need to check implementation of method successCallback for case 1.
Related
I am working on a web application for debtor management and I am refactoring the code and try to adhere to the principle of separation of concerns. But the async nature of AJAX is giving me headaches.
From a jQuery dialog the user can set a flag for a debtor which is then stored in a database. If that succeeds, the dialog shows a notification. Until now I handled everything inside the jQuery Ajax success callback function: validating input, doing the ajax request and updating the content of the dialog.
Of course this lead to spaghetti code.
Thus I created a class AjaxHandler with a static method for setting the flag, which is invoked by the dialog. I thought that the dialog could update itself according the the return value of the AjaxHandler but I did not have the asynchronity in mind.
The following question was helpful in tackling the return values.
How do I return the response from an asynchronous call?
But how can I update the dialog without violating the SoC principle?
EDIT
$("#button").on("click", function() {
var returnValue = AjaxHandler.setFlag();
if(returnValue) { $("#div").html("Flag set"); }
else { $('#div").html("Error setting flag");
});
class AjaxHandler {
static setFlag(){
$.ajax({
type: "POST",
url: "ajax/set_flag.php",
success: function(returndata){
return returndata; //I know this does not work because of
//ASYNC,but that is not the main point.
}
}
})
There is many ways to handle async responses, but the jQuery way is slightly different, so when you are already using jQuery, handle it this way:
$('#button').on('click', AjaxHandler.setFlag)
class AjaxHandler {
static setFlag () {
this.loading = true
this
.asyncReq('ajax/set_flag.php')
.done(function () {
$('#div').html('Flag set')
})
.fail(function (err) {
$('#div').html('Error setting flag. Reason: ' + err)
})
.always(function () {
this.loading = false
})
}
asyncReq (url) {
return $.ajax({
type: 'POST',
url: url
})
}
})
Consider using events perhaps here?
$("#button").on("click", function() {
$('body').trigger('getdata', ["", $('#div')]);
});
$('body').on('getdata', function(event, datasent, myelement) {
var attach = event.delegateTarget;// the body here
var getAjax = $.ajax({
type: "POST",
url: "ajax/set_flag.php",
data: datasent // in case you need to send something
})
.done(function(data) {
$(attach).trigger('gotdata', [data, myelement]);
});
getAjax.fail(function() {});
})
.on('gotdata', function(event, datathing, myelement) {
myelement.html(!!datathing ? "Flag set", "Error setting flag");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
Note that inside those event handlers you could also call some function, pass a namespace for the function, basically do it as you please for your design.
I have a text field with keypress event handler jsfiddle. And when I type something in this field and press "Enter" 2 times, 2 requests will be send. I want to turn off all events, while ajax request in progress. One option is to call .off() function before ajax call, and then bind event handler again. Any other options?
use the callback handlers from your ajax call and a boolean used as flag. By setting the ajaxLoading boolean to false in the "always" callback, you can be sure that other, future requests can be made independent from whether the current ajax call throws an error or not.
var ajaxLoading = false;
if(!ajaxloading){
ajaxloading=true;
$.ajax({
url: 'your url',
type: 'GET',
dataType: 'JSON'
})
.done(function(data) {
console.log("success");
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
ajaxloading=false;
});
}
I use 2 boolean flags, like:
var is_requesting = false, should_request = false;
function onkeydown() {
if (is_requesting) {
should_request = true;
return;
}
is_requesting = true;
$.ajax({}, function () {
is_requesting = false;
if (should_request) {
onkeydown();
}
});
}
Is there a good reason for you not to use the jQuery .off() function?
If so then you could simply disable the control prior to making the ajax request and re-enable it once the request is complete. This would also stop the user from thinking he/she could change the result by changing the text value during the request.
//Disable the input
$('#myresult').prop('disabled', true);
$('#myresult').append('<br>'+$(this).val());
$.ajax({
type: "POST",
beforeSend: function() {},
complete: function() {
//Re-Enable the input
$('#myresult').prop('disabled', false);
},
url: "/echo/json/",
data: { delay : 3 },
success: function(){},
error: function() {},
dataType: 'json'
});
Let's say I have a bunch of links that share a click event:
Click me
Click me
Click me
Click me
and in the $('.do-stuff').click function I execute a JQuery ajax POST request that updates the database with stuff and I get a successful response. After the ajax is completed, I simply want to change the value of the link text to be whatever I send back from the server...
$('.do-stuff').click(function () {
$.ajax({
type: "POST",
url: "MyWebService.asmx/DoSomething",
data: '{CurrentLinkText: "'+ $(this).text() +'"}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
$(this).text(result.d);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
});
});
This invoked just fine and I verified that "result.d" is indeed the text from the server but the text is not changing. I think that the $(this) element is no longer accessible after the AJAX post? What can I do to work around this?
In general when you lose context like that, you can save a reference to the object. Like this:
function clickHandler() {
var that = this;
$.ajax( { url: '#',
success: function (result) {
$(that).text(result.d);
}
);
}
See here:
$(this) inside of AJAX success not working
You can set the context option:
This object will be made the context of all Ajax-related callbacks. By default, the context is an object that represents the ajax settings used in the call ($.ajaxSettings merged with the settings passed to $.ajax). (...)
Example:
$.ajax({
//...
context: this,
success: function(json) {
//...
}
});
or use $.proxy:
$.ajax({
//...
success: $.proxy(function(json) {
//...
}, this)
});
Try:
success: $.proxy(function(result) {
//...
}, this)
There are lots of ways to do this, as you can see from the answers here. Personally, I prefer to construct a function bound to the current value of this:
success: (function(target) {
return function(result) {
$(target).text(result.d);
}
})(this)
It's neat, clean, and $(this) will remain the same as it is in the outer context; i.e. it will be the element that raised the event.
jQuery('#youridvalue').html(result.d);
jQuery('.yourclassvalue').html(result.d);
Use it
I'm trying to add a callback to a pre existing function in the jquery plugin nitelite https://github.com/premasagar/nitelite - The callback works fine http://jsfiddle.net/HPc4e/2/ - unless I have ajax in the callback?
Appropriate section of close function:
// Blah blah ...
else {
showFlash();
this.overlay.remove();
this.container
.empty()
.remove();
$(this).triggerHandler('close');
// Add callback
if (typeof callback == "function") {
callback();
}
}
return this;
Callback:
lb.close(undefined, 'click', function() {
$.ajax({
type: 'POST',
url: url,
data: {submit: $(this).val()},
dataType: 'json',
success: function(data) {
lightbox('Lightbox 2', '<p>Oh hi</p>', 'lightbox2');
}
});
});
Thanks
I suspect that your callback is throwing an exception.
What is the value of this supposed to be when it's invoked? Are you sure it's pointing at a jQuery compatible element that has a .val() method?
Is there any way to pause mousemove event until task complete?
$( document ).bind( 'mousemove', function ( e )
{
// mousemove: please wait and stop moving
document.removeEventListener('mousemove');
// I am the task
$.ajax( {
url: '/getData',
type: 'POST',
success: function ( result ){}
} )
.done(function()
{
// I am done, start moving...
document.addEventListener('mousemove');
});
} );
What I want:
mousemove event fired and stopped as
soon as it is fired.
Function inside it executes.
When function done executing,
mousemove event starts again firing
What this does is pause the mouse
move event until task is done or
fails.
First of all, why do you mix raw DOM/event access with jQuery? Don't do that.
To achieve what you want simple make your function a non-anonymous one and use $(document).one('mousemove', yourFunction); to bind it - both somewhere outside and in your done() function.
function handleMouseMove(e)
{
// I am the task
$.ajax({
url: '/getData',
type: 'POST',
success: function ( result ){}
})
.done(function() {
$(document).one('mousemove', handleMouseMove);
});
}
$(document).one('mousemove', handleMouseMove);
If your task time is small.
You can use a bool flag to keep a lock on mousemove functionality.
This will call the function on mousemove though, but return without doing anything
until you release the lock.
var moveFlag = true;
$( document ).bind( 'mousemove', function ( e )
{
if(moveFlag == false)
return;
moveFlag = false;
// I am the task
$.ajax( {
url: '/getData',
type: 'POST',
success: function ( result ){}
} )
.done(function()
{
// I am done, start moving...
moveFlag = true;
});
} );
Use a flag to disable/enable it like this:
$(document).data('enableMyMouseMove',true).bind('mousemove',function (e) {
if($(document).data('enableMyMouseMove')) {
$(document).data('enableMyMouseMove',false);
$.ajax( {
url: '/getData',
type: 'POST',
success: function (result) {},
complete: function (){ $(document).data('enableMyMouseMove',true); }
});
}
});
Notice that I have moved your 'done' function into the complete eventHandler on the ajax call, since imo, that is cleaner, but you can keep the done function if your wish, the logic is the same.
Try to avoid binding/unbinding event handlers all the time, since it is a very easy way to create memleaks unless you know what you are doing, especially in ie.
The reason for this is that ie has separate garbage collection for js and DOM objects, and if there is a cyclic reference between the two, garbage collection will not occur. Creating cyclic dependencies between js and DOM happens very easily when you bind eventHandlers