$("#readMain").delegate("span", "click", function() {
var toSend = $(this).text();
$(this).text(function() {return "test1";});
$.post('/render/', {'word': toSend}, function(data){
$(this).text(data);
alert(data); //for testing
});
});
I'm trying to have the word clicked updated. It works fine the first time (it changes to 'test1'), but after the post call, it doesn't work anymore?
What am I doing wrong
this doesn't refers to span element in $.post() callback method, store the reference of $(this) in a variable and use it wherever required.
//Store the reference
var _this = $(this);
$.post('/render/', {'word': toSend}, function(data){
//Use it later
_this.text(data);
alert(data); //for testing
});
Additionally, delegate() is deprecated use .on()
$("#readMain").on("click", "span", function() {
//Store the reference
var _this = $(this);
var toSend = _this.text();
_this.text("test1");
$.post('/render/', {'word': toSend}, function(data){
_this.text(data);
alert(data); //for testing
});
});
This in that context refers the first time to the "span", the second time it refers to the window object.
Besides that, delegate is old jQuery, you can use '.on' now.
You'll nee to update the function like this:
$("#readMain").on("click", "span", function() {
var span = $(this);
var toSend = span.text();
$.post('/render/', {'word': toSend}, function(data){
span.text(data);
alert(data); //for testing
});
});
this is only valid in the current scope which means every function, class, closure, ..., has it's on this. Save a reference to your first this in a var to access it later.
$("#readMain").delegate("span", "click", function() {
var span = $(this);
var toSend = span.text();
span.text(function() {return "test1";});
$.post('/render/', {'word': toSend}, function(data){
span.text(data);
alert(data); //for testing
});
});
The context in $.post callback will be changed. You can declare a variable and set the context. See the code below.
$("#readMain").on("span", "click", function() {
var self = $(this),
toSend = self.text();
self.text(function() {return "test1";});
$.post('/render/', {'word': toSend}, function(data){
self.text(data);
alert(data); //for testing
});
});
Related
Sorry if that title is confusing. Basically, I had to rewrite my code to implement the history api. Below is the before and after. You can see how before, the this keywords worked fine relative to .post-link. However, in the after, the this keywords don't work anymore since there is no relative point. How do I make sure that the correct links are targeted in the after function all relative to .post-link which is now a separate function?
Before: Everything worked fine with this in relation to .post-link.
$('#content').on('click', '.post-link', function(e) {
e.preventDefault();
var post_id = $(this).data('id'),
projectTitle = $(this).data('title'),
projectSlug = $(this).data('slug'),
ajaxURL = site.ajaxurl;
$('<span class="loading-icon"></span>').insertBefore(this);
$(this).closest('article.project').addClass('active');
$.ajax({
type: 'POST',
url: ajaxURL,
context: this,
data: {'action': 'load-content', post_id: post_id },
success: function(response) {
$('.loading-icon').remove();
$(this).closest('article.project').removeClass('active');
$('#project-container').html(response);
return false;
}
});
});
After: Now the relative link (.post-link) is gone, so all the this keywords aren't functioning properly (marked as comments below).
(function($) {
function openProject() {
var post_id = $(this).data('id'), // this
ajaxURL = site.ajaxurl;
$('<span class="loading-icon"></span>').insertBefore(this); // this
$(this).closest('article.project').addClass('active'); // this
$.ajax({
type: 'POST',
url: ajaxURL,
context: this, // added this
data: {'action': 'load-content', post_id: post_id },
success: function(response) {
$('.loading-icon').remove();
$(this).closest('article.project').removeClass('active'); // this
$('#project-container').html(response)
return false;
}
});
}
// User event
$('#content').on('click', '.post-link', function(e) {
e.preventDefault();
// Variables
var projectTitle = $(this).data('title'),
projectSlug = $(this).data('slug');
var newData = { project_page: site.url + '/projects/' + projectSlug };
History.pushState(newData, projectTitle + ' | Site Title', site.url + '/projects/' + projectSlug);
openProject();
});
// History event
History.Adapter.bind(window, 'statechange', function(){
var State = History.getState();
$('#content').load(State.data.project_page);
});
})(jQuery);
The easiest way here would be to call the function openProject(); with this as parameter:
openProject(this);
function openProject(el){
// do stuff with $(el);
}
However the more advanced way is to bind the function to the this-context or call the function in a specific context:
// binds the function to the object given.
// Whenever you call the function now `this` will refer to the given object
openProject.bind(this);
openProject.apply(this); // Calls the function in the context of the given Object
openProject.call(this); // same here
Now the openProject-function is called in the context of the given this in your case that what you wanted.
You can improve that with binding $(this) instead to avoid calling jquery all the time you use this
Edit:
I missed the this in the ajax-callback. This this is not the same as in the openProject-function becaue the callback is called in another context.
In openProject you would do this:
var _this = this;
$.ajax({
// Parameter and stuff
success: function(){
// use _this here
}
})
You should read about the use of this and how to handle it: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
I have a variety of .img-drop-zones and upon drop a file is read, I wish to display it on top of the specific drop zone it was placed on, but how do I get it? $(this) does not work because of scope, how can I pass it through?
$('.img-drop-zone').on('drop', function(e){
var files = e.originalEvent.dataTransfer.files;
$.each(files, function(index, file){
p.file.read(file, function(content) {
//how can I get the img-drop zone here?
});
})
});
Just declare an additional variable in the outer scope that you can refer to within the $.each closure:
var $this = $(this);
$.each(..., function() {
// use $this here to refer to the img-drop-zone
});
When referring to an object to something that isn't a jQuery object it's more common to use self or that.
$(this) is what you need
$('.img-drop-zone').on('drop', function(e){
var files = e.originalEvent.dataTransfer.files;
var dropJone = $(this);
$.each(files, function(index, file){
p.file.read(file, function(content) {
//how can I get the img-drop zone here?
//use dropJone here
});
})
});
I'm builing a simple "like" service on my website. I'd like users to be able to click on link to like something, get the total likes (returned from php script)
I have problem getting the data from script to update div. This is what I have:
<div id="112" class="like">Like it</div>
<div id="113" class="like">Like it</div>
<div id="114" class="like">Like it</div>
<script>
$(".like" ).click(function() {
var idl = $(this).attr("id");
$.ajax({type:"POST", data: likeid=idl, url:"ajax/publike.php",
success: function(data){
$(this).html(data);
},
error: function(){
alert ("Error");
}
});
return false;
});
</script>
I just would like to update the div with content I get from (data) but no update. If I change to $(".like").html(data); it works, but I have many class like, I only when to have the clicked div to update.
Thanks
Do this:
<script>
$(".like" ).click(function()
{
var idl = $(this).attr("id");
var link = $(this);
$.ajax({type:"POST", data: likeid=idl, url:"ajax/publike.php",
success: function(data)
{
link.html(data);
},
error: function()
{
alert ("Error");
}});
return false;
});
</script>
try this
<script>
$(".like" ).click(function() {
var idl = $(this).attr("id");
$.ajax({type:"POST", data: likeid=idl, url:"ajax/publike.php",
success: function(data){
$('#'+idl).html(data);
},
error: function(){
alert ("Error");
}
});
return false;
});
</script>
By the time the AJAX callback runs, this is no longer in scope as the element which triggered the event. You need to hold a reference to it:
$(".like" ).click(function() {
var likedElement = $(this);
var idl = $(this).attr("id");
$.ajax({type:"POST", data: likeid=idl, url:"ajax/publike.php",
success: function(data){
likedElement.html(data);
},
error: function(){
alert ("Error");
}
});
return false;
});
Set the context to the element when you make the ajax call. This is safer than just relying on a scope variable. If a second div is clicked before the first ajax call is returned, only the last divs html would get updated. This method will update both divs correctly.
<script>
$(".like" ).click(function() {
var div$ = $(this);
$.ajax({type:"POST", data: likeid=div$.attr("id"), url:"ajax/publike.php", context: div$,
success: function(data){
this.html(data);
},
error: function(){
alert ("Error");
}
});
return false;
});
</script>
http://jsfiddle.net/MwQbE/
i have the jQuery Below but i cant get the variables to pass to the second function
$("img").hover(function(){
var $image = $(this);
var $imageNowWidth = $image.width();
},function() {
// get variable value for $image and $imageNowWidth
});
When testing on jsFiddle it doesn't work, what can I do to pass the variable to the second function?
Simply define those 2 variables outside .hover and then you can use them inside mouseleave function. See below,
var $image, $imageNowWidth;
$("img").hover(function(){ //mouseenter
$image = $(this);
$imageNowWidth = $image.width();
},function() { //mouseleave
//$image and $imageNowWidth is accessible HERE
});
Just want to clarify that this will be available inside mouseleave function so you can do the same or more w.e you are doing inside mouseenter
Define getter and setter for image and imageNoWidth as below,
var getImage, getImageNoWidth;
$("img").hover(function(){
$image = $(this);
$imageNowWidth = $image.width();
getImage = function(){
return $image;
};
getImageNoWidth = function(){
return $imageNowWidth;
};
},function() {
// get variable value for $image (getImage()) and $imageNowWidth (getImageNoWidth())
}
Declare the variable outside, so it is accessible in both functions.
var image;
var imageNowWidth;
$("img").hover(function(){
image = $(this);
imageNowWidth = $image.width();
},function() {
// get variable value for $image and $imageNowWidth
});
Store the variable directly on the jquery object using the jquery 'data' method :
$("img").hover(function(){
var $image = $(this);
$image.data('imageNowWidth',$image.width());
},function() {
var previousImageWidth = $(this).data('imageNowWidth');
// do whatever you want to do with the width
});
I have the following jQuery code:
$('.active #search').on('mouseout', function () {
$('#search_box #search').not('.active').each(function(){
this.value = $('.active #search')[0].value;
})
});
It works, but I have to call $('.active #search') twice. How can I refer to the $('.active #search') array from within my inner function?
P/S: I know I'll be complained about giving multiple elements same ID, but this seem to be generated by Rails automatically (text_field_tag).
I think this is what you're looking for:
$('.active #search').on('mouseout', function () {
var val = $(this)[0].value; //cache value of $('.active #search').
$('#search_box #search').not('.active').each(function () {
this.value = val;
})
});
You can do something like below. I added self = $(this)
$('.active #search').on('mouseout', function () {
var self = $(this);
$('#search_box #search').not('.active').each(function(){
this.value = self[0].value;
});
});
Here is a link to very good explanation of 'this' keyword, explained by Jeffrey Way
tutsplus.com/lesson/the-this-keyword
Therese several ways of achieving this:
var activeSearch = $('.active #search');
activeSearch.on('mouseout', function () {
$('#search_box #search').not('.active').each(function(){
this.value = activeSearch.val();
})
});
notice that since this is an id you are querying for you should have only one element so you can replace activeSearch[0].value with activeSearch.val();
second way:
$('.active #search').on('mouseout', function () {
var activeSearch = $(this);
$('#search_box #search').not('.active').each(function(){
this.value = activeSearch.val();
})
});
when in an event handler $(this) will give you a jquery object of the event sender. you can further simplify it by ignoring jquery and just using plain elements by doing the following:
$('.active #search').on('mouseout', function () {
var activeSearch = this;
$('#search_box #search').not('.active').each(function(){
this.value = activeSearch.value;
})
});
this is the same as above but you arent dealing with jquery objects.
What you end up using depends on you but the final code snippet would be my preferred way.
You can use $(this) instead of using the $('.active #search')