$(this) selector issue jquery - javascript

i have this simple jquery function here.Clicking over a button i want to alert its own class before ajax and again upon succession..but the selector "$(this)" in the last situation is not working and the alert returns "undefined"..
why?
$(".button").live("click",function(){
alert($(this).attr('class')); //returns "button"
$.ajax({
type: "POST",
url: myUrl,
data: myData,
cache: false,
success: function(html)
{
alert($(this).attr('class')); //returns undefined
}
});

I would do it like this, store $(this) in a variable so you can use it throughout the function without having to perform a jQuery lookup every time, and you also will not have to depend on the scope to provide the correct element for $(this)
$(".button").live("click",function(){
var button = $(this);
alert(button.attr('class')); //returns "button"
$.ajax({
type: "POST",
url: myUrl,
data: myData,
cache: false,
success: function(html)
{
alert(button.attr('class')); //should also return "button"
}
});
});
wrapping this only once also is a performance enhancement

This will make it work:
$(".button").live("click", function() {
var button = this;
$.ajax({
type: "POST",
url: myUrl,
data: myData,
cache: false,
success: function(html) {
alert($(button).attr('class'));
}
});
});
You cannot use the this reference inside nested functions. The success function is a nested function and it has its own this value. If you need the reference to the button inside that nested function, you have to declare a local variable (like button).
function clickHandler() {
// this == element that was clicked
function ajaxHandler() {
// this != element that was clicked
}
}

Try adding var self = $(this); when you declare the function, and then use self instead of $(this)
So your code looks like this:
$(".button").live("click",function(){
var self = $(this);
alert($(this).attr('class')); //returns "button"
$.ajax({
type: "POST",
url: myUrl,
data: myData,
cache: false,
success: function(html)
{
alert(self.attr('class')); //returns undefined
}
});

Lots of people have posted the solution for this so I won't post the code. Just wanted to mention the reason is because since the success method is a callback your context of $(this) isn't valid anymore. So you need to assign it to a variable and store it for your own use.

$(this) only exists when referencing an HTML object in the DOM. Since you've tried using in the success function of the AJAX call, $(this) has no reference. So for example, in the following code $(this) refers to the item to returned by the jQuery selector:
$('.button').each(function() {
alert($(this));
});
You will need to use a selector to return the item in global scope, and then pass this to the success function in the AJAX call:
var myButton = $('.button');
$.ajax({
type: "POST",
url: myUrl,
data: myData,
cache: false,
success: function(html) { alert(myButton.attr('class')); /* returns button */ }
});

Take a look at the context section here. Basically, what seems to be happening in your code is that the reference to this no longer applies. Makes sense, given that the context of the code has moved on while the AJAX callback is being handled asynchronously. Explicitly setting the context to a particular object in the .ajax() call will carry a reference to the context into the callback function.

You can either add a context: this property to the hash that is passed to the $.ajax call, that way the success handle will it's context set properly, or you can also do something like:
success: $.proxy(function(html) { // using $.proxy will bind the function scope to this
alert($(this).attr('class'));
}, this);
or, another technique I've seen:
$(".button").live("click",function(){
var self = this;
alert($(self).attr('class')); //returns "button"
$.ajax({
type: "POST",
url: myUrl,
data: myData,
cache: false,
success: function(html)
{
alert($(self).attr('class')); //returns undefined
}
});

Related

How to lock / set / block variable inside .on jquery

So, I have a jQuery AJAX call that gets data from the server (some text, some links).
Inside AJAX success callback function I got a .on that is bind to <a> that load for me next page and get me the text of the clicked link (let's say stackoverflow.com).
The problem starts here because in the newly loaded page I got anchors...
After every click on anchor links I got new .text() value.
$.ajax({
url: url,
type: type,
dataType: dataType,
success: function(data){
$('.container').append(data);
$('.container').on('click', 'a', function(e){
e.preventDefault();
var clickLinkName = $(this).text();
console.log(clickLinkName);
$('.container').load($(this).attr('href'));
});
}
});
I would like to know how to lock clickLinkName variable. OR any other way to save only first hit.
I think this would do the trick:
$.ajax({
url: url,
type: type,
dataType: dataType,
success: function(data) {
$(".container").append(data);
var clickLinkName; // Declared here.
$(".container").on("click", "a", function(e) {
e.preventDefault();
// If not initialized, initialize.
if(!clickLinkName) {
clickLinkName = $(this).text();
}
console.log(clickLinkName);
$(".container").load($(this).attr("href"));
});
}
});
That would save only the first value in the variable clickLinkName. This answers your question, but I'm sure there are better ways of doing this.

Using this.setAttribute in an Ajax call [duplicate]

It seems that i cannot access $(this) inside jquery ajax success function. please see below code.
$.ajax({
type: 'post',
url: '<?php echo site_url('user/accept_deny_friendship_request')?>',
data: 'action='+$action+'&user_id='+$user_id,
success: function(response){
//cannot access $(this) here $(this).parent().remove();
}
});
What should $(this) be? If you have a reference to it outside that function, you can just store it into a variable.
$('#someLink').click(function() {
var $t = $(this);
$.ajax( ... , function() {
$t.parent().remove();
});
}
Check out the context option - works perfectly for me:
$.ajax({
context: this,
type: 'post',
url: '<?php echo site_url('user/accept_deny_friendship_request')?>',
data: 'action='+$action+'&user_id='+$user_id,
success: function(response){
//can access this now!
}
});
If you want this to be this in the context of your ajax call, you can also use .bind() like the following:
$.ajax({
url: 'some_url'
success: function(data) {
// do something 'this'
}.bind(this)
})
It binds the value of this inside the success callback to this outside.
Try calling $.proxy, to change the scope of this inside the function:
$.ajax({
success: $.proxy(function(response) { $(this).parent().bla(); }, $(this));
});
I can't see $(this) referencing anything but easier way would be to give the element a class or id and reference that from jquery:
Instead of:
$(this).parent().remove();
You could do:
$('#element_id').parent().remove();
Note: Here I assume that you are dealing with one element/iteration.
Now, you can simply achieve it using ES6 arrow function. You can convert the anonymous function to arrow function expression as below:
$.ajax({
..,
success: (response) => {
// access this outside of this function scope by using `this`
}
});
Make sure to use transpiler such as babel to provide support for older browsers.

Scope variables in javascript,jquery

I am trying to access variable 'dimensions' in my ajax response but not able to get it. I dont want to make this variable global. Following is my code
$(document).ready(function(){
$('#submittext').click(function(){
var dimensions;
$.ajax({
type: "GET",
url: "bin/getcontentsize.php",
data: findContentsize,
success: function(response){
//want to access dimensions here to assign response and some calculation(but not able to access it)
}
});
//so i can use here
});
});
In this case you can access the dimensions variable from both the ajax call back and the code immediately after starting the ajax request. The variable is accessible in both of these contexts.
What is most likely causing the problem though is the timing. The success method will run asynchronously after the ajax request is completed. It's best to view this as executing later. However the code immediately after the $.ajax call will execute immediately. Hence you won't see any effects from the success handler on the dimensions variable when it runs.
If there is code you want to run with the value of dimensions as calculated by the success method you need to call that code from the success callback. For example
$('#submittext').click(function(){
var handleNewDimensions = function (dimensions) {
// Code that used to be after the $.ajax line
}
$.ajax({
type: "GET",
url: "bin/getcontentsize.php",
data: findContentsize,
success: function(response){
var dimensions = doTheCalculation(...);
// Call the code which needs to deal with the new dimensions
handleNewDimensions(dimensions);
}
});
Problem when you run it.
$(document).ready(function(){
$('#submittext').click(function(){
var dimensions="1";
$.ajax({
type: "GET",
url: "bin/getcontentsize.php",
data: findContentsize,
success: function(response){
dimensions = "2";
}
});
//!!!!Attention
alert(dimensions); // result is "1", not "2"
});
});
First, your code already ran. After that, your $.ajax starts to run.
Assign the dimensions variable the value, and test it again:
var dimensions="sample";
This should work:
$(document).ready(function(){
$('#submittext').click(function(){
var dimensions = 1;
$.ajax({
type: "GET",
url: "bin/getcontentsize.php",
data: findContentsize,
success: function(response){
alert(dimensions);
}
});
//so i can use here
});
});

how to pass a value to jQuery Ajax success-handler

Give the following Ajax call in jQuery:
{
.
.
.
,
getSomeData: function(args, myUrl, foo) {
$.ajax( {
type: "GET",
url: myUrl,
data: args,
async: true,
dataType: 'json',
success: myHandler
});
},
myHandler: function (data, textStatus, oHTTP, foo){ ... }
};
Can value foo be somehow appended to the arguments that are passed to success-handler myHandler? Is there any way to pass a value up to the server on the GET, and have that value come back to the client in a round-trip, reappearing in the success-handler's arguments list? I cannot change the structure of what is returned in data.
If you declare myHandler within the request, you can use a closure.
getSomeData: function(args, myUrl, foo) {
$.ajax( {
type: "GET",
url: myUrl,
data: args,
async: true,
dataType: 'json',
success: function (data, textStatus, oHTTP){ ... }
});
},
this way, foo will be available to you inside the success callback.
If you're $.ajax call is in a class and the success callback is passed a method of that class, it does not work.
EDIT: Here is the answer. Note that I am defining the function ajaxCall as a method in a class. I define this.before, this.error, and this.success as methods of ajaxCall because they can call methods from the superClass.
function main(url){
this.url = url;
this.ajaxCall = function(){
this.before = function(){
//Can call main class methods
};
this.error = function(){
//Can call main class methods
};
this.success = function(data){
//Can call main class methods
};
//This is how you pass class arguments into the success callback
var that = this;
$.ajax({
url: this.url,
type: 'GET',
dataType: 'json',
beforeSend: this.before(),
error: this.error(),
success: function(data){that.succes(data);}
});
//Run internally by calling this.ajaxCall() after it is defined
//this.ajaxCall();
}
//Or externally
var main = new main(SOME_URL);
main.ajaxCall();
#Unicron had the right answer but didn't give a good example. Check this out:
$( 'tr.onCall' ).on( 'click', function( event ) {
let pEvent = function() { return event; } // like a fly in amber...
$.ajax( {
...
success: function( data ) {
let x = pEvent(); // x now equals the event object of the on("click")
}
});
});
By declaring the pEvent function inside the anonymous function that fires on("click"), the event object is "frozen" (encapsulated) in its original context. Even when you call it in the different context of the ajax success function, it retains its original context.
More specific example: I'm going to open a modal dialog (styled Div) on click, but when the dialog is closed I want to return the focus to the element that was clicked to open it in the first place...
$( 'tr.onCall' ).on( 'click', function( event ) {
let rTarget = function() { return event.currentTarget; }
$.ajax( {
url: 'ajax_data.php',
...other settings...
success: function( data ) {
modal_dialog(
data,
{
returnTarget: rTarget(),
...other settings...
}
);
}
});
});
On success, it calls a custom function modal_dialog() (defined elsewhere), passing in an object containing various settings. The returnTarget setting contains the HTML ID attribute of the element that was clicked; so when I close the dialog I can run $(options.returnTarget).focus(); to return focus to that element.

How do I reference the calling dom element in a jquery ajax success function?

I'm trying to modify the class of an element if an ajax call based on that element is successful
<script type='text/javascript'>
$("#a.toggle").click(function(e){
$.ajax({
url: '/changeItem.php',
dataType: 'json',
type: 'POST',
success: function(data,text){
if(data.error=='')
{
if($(this).hasClass('class1'))
{
$(this).removeClass('class1');
$(this).addClass('class2');
}
else if($(this).hasClass('class2'))
{
$(this).removeClass('class2');
$(this).addClass('class1');
}
}
else(alert(data.error));
}
});
return false;
});
</script>
<a class="toggle class1" title='toggle-this'>Item</a>
My understanding of the problem is that in the success function this references the ajax object parameters, NOT the calling dom element like it does within other places of the click function. So, how do I reference the calling dom element and check / add / remove classes?
You can just store it in a variable. Example:
$("#a.toggle").click(function(e)
{
var target = $(this);
$.ajax({
url: '/changeItem.php',
dataType: 'json',
type: 'POST',
success: function(data,text)
{
if(data.error=='')
{
if(target.hasClass('class1'))
{
target
.removeClass('class1')
.addClass('class2');
}
else if(target.hasClass('class2'))
{
target
.removeClass('class2')
.addClass('class1');
}
}
else(alert(data.error));
}
});
return false;
});
jQuery passes the target of the event, along with some other information about it, to your handler function. See http://docs.jquery.com/Events_%28Guide%29 for more info about this.
In your code, it'd be referenced like $(e.target).
Better set ajax parameter : context: this. Example:
$.ajax({
url: '/changeItem.php',
dataType: 'json',
type: 'POST',
context: this,
success: function(data,text){
if(data.error=='')
{
if($(this).hasClass('class1'))
{
$(this).removeClass('class1');
$(this).addClass('class2');
}
else if($(this).hasClass('class2'))
{
$(this).removeClass('class2');
$(this).addClass('class1');
}
}
else(alert(data.error));
}
});
I know it's old but you can use the 'e' parameter from the click function.

Categories

Resources