jQuery parents() selector failing - javascript

I have an anchor, and I have attached an onClick callback to it, so once it is clicked, an AJAX request is fired which calls a view that deletes the image from the database. It should also remove <div class="image-preview"> altogether, too, however that is not happening for some reason.
When I tested div removal code in JSFiddle, it works. The image is successfully getting removed from the database and delete_view is involved in the process. I have also tried to console.log from inside the success callback and I can see a debug message. console.log($(this).parents('.image-preview')); returns Object { length: 0, prevObject: Object(1) }, thus I think the selector is failing.
What could be the reason?
HTML:
<div id="information">
<div class="image-previews">
<div class="image-preview">
<img src="/media/tmp/None/IMG_20190507_144128.jpg" width="80" height="54">
<p><a id="115" class="delete-temp-image-link">delete</a></p>
<label><input type="radio" name="main" value="IMG_20190507_144128.jpg">main</label>
</div>
</div>
<div id="div0">
<div>Name: IMG_20190507_144128.jpg</div>
<div>Size: 3.03MB</div>
<div>Type: image/jpeg</div>
<div class="progressNumber">100%</div>
</div>
</div>
jQuery:
var $deleteClicked = function(event) {
var url = Urls.deleteTempImage(event.target.id);
$.ajax({
url: url,
data: {
'id': event.target.id
},
success: function (data) {
console.log('spam');
$(this).parents('.image-preview').remove();
}
});
}
$(document).on('click', '.delete-temp-image-link', $deleteClicked);
view:
def delete_view(request, id):
img = get_object_or_404(TemporaryImage, id=id)
img.delete()
return HttpResponse('successfull')

$(this) isn't available to your named click callback function. One way to make your code more explicit would be to store $(this), as others have said - or, simply use the id that you're already passing anyway. For example:
var $deleteClicked = function(event) {
var url = Urls.deleteTempImage(event.target.id);
$.ajax({
url: url,
data: {
'id': event.target.id
},
success: function (data) {
console.log('spam');
$("#"+event.target.id).closest('.image-preview').remove();
}
});
}
$(document).on('click', '.delete-temp-image-link', $deleteClicked);
Also, note that I used jQuery .closest() instead of .parents(). From the jQuery docs, .closest() does the following:
For each element in the set, get the first element that matches the
selector by testing the element itself and traversing up through its
ancestors in the DOM tree.
Check out the docs page for a description of the differences between .closest() and .parents(). The main difference is that .closest() only traverses up the DOM tree until it finds a match, rather than traversing all the way up to the root element. I doubt there are huge performance implications, but since you're selecting only one <div>, it's slightly more precise code.

You have to store $(this) before run $.ajax because you are using it in a wrong context.
var $deleteClicked = function(event) {
var url = Urls.deleteTempImage(event.target.id);
var storedThis = $(this);
$.ajax({
url: url,
data: {
'id': event.target.id
},
success: function (data) {
console.log('spam');
storedThis.parents('.image-preview').remove();
}
});
}
$(document).on('click', '.delete-temp-image-link', $deleteClicked);
This should work as expected.

Try this code for jQuery.
var $deleteClicked = function(event) {
var url = Urls.deleteTempImage($(this).attr('id'));
$.ajax({
url: url,
data: {
'id': $(this).attr('id')
},
success: function (data) {
console.log('spam');
$(this).parents('.image-preview').remove();
}
});
}
$('.delete-temp-image-link').on('click', $deleteClicked);

Same problem occur to me as well.
Actually '$(this)' is tricky as it may seem.
'$(this)' cannot be used in success function as it lost it scope in success function.
Try to define '$(this)' outside the success(ie, before ajax),eg
const element = $(this)
And then in your success function:
element.parents('.image-preview').remove();
This should definitely solve your problem.
Hope this helps!

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.

Get id of the <a> tag from one function to another

I am very new in javascript/jQuery so please bear with me if my question will be too easy for you and too difficult for me.
This is from a function, I just don't post the complete codes since it will be too long.
And I have another function which also have an ajax and I want to pass get the ID of the <a> tag:
function someName() {
jQuery.ajax({
type: 'POST',
url: 'thisisprivate.aspx',
data: {
action: 'MyAction',
word: 'Wednesday',
count: '4',
page: '1'
},
success: function(data) {
var json = jQuery.parseJSON(data);
var htmlInfo = '';
for (i = 0; i < json.length; i++) {
var htmlCode = '';
htmlInfo = htmlInfo + htmlCode;
}
jQuery('#WMVideoxx').html(htmlInfo);
}
});
}
and
function VideoDiv() {
jQuery.ajax({
type: 'POST',
url: 'thisisprivate.aspx',
data: {
action: 'actionNameHere',
idorname: id //I Want to pass the ID here
});
}
What you are doing is:
jQuery('a').click(function() {
VideoDiv(jQuery(this).attr('id'));
});
This will not work because of the nature of <a> tag being dynamically generated and the event doesn't get registered. Consider delegating the event (see Understanding Event Delegation for more information):
jQuery(document).on("click", 'a', function() {
VideoDiv(jQuery(this).attr('id'));
});
The above code works, but will delegate for all the <a> inside the document. Instead, add a class or something that uniquely identifies that. And call it this way:
jQuery(document).on("click", 'a.class', function() {
VideoDiv(jQuery(this).attr('id'));
});
Another thing about the above delegation of code is, it is better to use a closest static parent instead of document. Since I don't know the HTML structure, I have used document. :)
Also, as Ismael Miguel says, it is better to get the id using this.id:
jQuery(".static-parent").on("click", '.class', function () {
VideoDiv(this.id);
});
The above would be the best code.
Also, it has been pointed out again, for better performance, you may replace the code with:
setTimeout(
(function () {
VideoDiv(this.id);
}).bind(this), 10
);
This will let jQuery handle the next even handler, and will execute this code on the next 10ms (when available).
use onclick="function();" with your anchor and pass arguments that you want in your function
Your htmlcode should be like this
Your VideoDiv function
function VideoDiv(id)
{
//your ajax goes here
}
Try this : you can put onclick call to a tag while creating it and pass this object which is nothing but the a tag element, see below code
var htmlCode = '';
Now make following changes in your javascript function
function VideoDiv(anchor)
{
jQuery.ajax({
type: 'POST',
url: 'thisisprivate.aspx',
data: {
action: 'actionNameHere',
idorname: anchor.id //pass id here from anchor object
}
});
}
NOTE: your data attribute in above ajax call is incomplete, please correct it.

jQuery function doesn't work after after loading dynamic content

I'm using below code. This is bootstrap 3 delete conformation message.
$(document).ready(function(){
$('a.btnDelete').on('click', function (e) {
e.preventDefault();
var id = $(this).closest('div').data('id');
$('#myModal').data('id', id).modal('show');
});
$('#btnDelteYes').click(function () {
var id = $('#myModal').data('id');
var dataString = 'id='+ id ;
$('[data-id=' + id + ']').parent().remove();
$('#myModal').modal('hide');
//ajax
$.ajax({
type: "POST",
url: "delete.php",
data: dataString,
cache: false,
success: function(html)
{
//$(".fav-count").html(html);
$("#output").html(html);
}
});
//ajax ends
});
});
This is the trigger element that I'm using
<div data-id="MYID"><a class="btnDelete" href="#">Delete</a></div>
And I'm using the same HTML element dynamically to trigger delete and it doesn't work.
Can someone point me the correct way to do it?
You have to use event delegation
$(document).on("click" , '#btnDelteYes' ,function () {
Pretty much: bind the click higher up to something that exists when the script is run, and when that something is clicked, tell it to pass the click event to the #btnDelteYes element instead
I cant understand what exactly you are doing on your code due to missing information, but the answer is: you should use event delegation on the dynamically inserted content
you can try
$('[data-id=MYID]').on('click','.btnDelteYes',function({
e.preventDefault();
var id = $(this).closest('div').data('id');
$('#myModal').data('id', id).modal('show');
});
here <div data-id="MYID"> should be a hard coded html content and The idea is to delegate the events to that wrapper, instead of binding handlers directly on the dynamic elements.

Jquery - can't target the right element with $(this) [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
$(this) doesn't work in a function
Im having a problem targeting the right element in my code. I have a list of thumbnails on my page, and when you click on a "I dislike this" icon the targeted video change for another one.
Here's the HTML
<li class="videoBox recommended">
<div class="spacer" style="display: block;"></div>
<div class="features">
<div>
<a class="dislike_black" title="I dislike this" onclick="ThumbsDown(30835, 'relevance', '1');"></a>
</div>
</div>
<a href="...">
<h1>...</h1>
<div class="information">...</div>
</li>
Ajax is:
function ThumbsDown(id,sort,page) {
$.ajax({
url: "/change/videos/"+id+"/thumbsdown/",
type: "POST",
data: {
"sort": sort?sort:"",
"page": page?page:""
},
success: function(data) {
//$("#content .videoList ul li.videoBox").html(data); // THIS IS WORKING, but replaces ALL the divs
$(this).parent("li.videoBox").html(data); // Cant get this to work!
}
});
What Iam doing wrong? even $(this).css("border","1px solid red") is not "working". (I tried with background color, and color too) I dont see anything.
$(This) refers to the "a" tag where the function is called right? So im searching for his parent named videobox... Help?
So can I target
You should not use onclick, you should bind it to an event, especially as you could easily make this degrade well if the user does not have ajax.
Change your <a> tags to this:
<a href="/change/videos/1/thumbsdown/"
data-sort="sort"
data-page="page"
class="dislike_black"
title="I dislike this"></a>
jQuery event:
$('.dislike_black').click(function(e) {
e.preventDefault(); // Prevent link from clicking
var $aTag = $(this); // I use $aTag to denote a jq object
$.ajax({
url: $aTag.attr('href'),
type: "POST",
data: {
"sort": $aTag.data('sort'), // data-sort attr value
"page": $aTag.data('page') // data-page attr value
},
success: function(response) {
$aTag.closest(".videoBox").html(response);
}
});
});
Now it works without javascript, and you're not using nasty onclick! Untested/no warranty.
Almost. In order to make this work, you need to pass in the context to the .ajax() call.
Like
$.ajax({
url: "/change/videos/"+id+"/thumbsdown/",
type: "POST",
context: document.body, // for instance
data: {
"sort": sort?sort:"",
"page": page?page:""
},
success: function(data) {
//$("#content .videoList ul li.videoBox").html(data); // THIS IS WORKING, but replaces ALL the divs
$(this).parent("li.videoBox").html(data); // Cant get this to work!
}
});
The above code would cause that all ajax handlers will have this pointing to document.body. So you would need to replace the document.body with the element you are looking for. So, if you for instance call your function in some kind of a click handler you could just call context: this and the magic is done.
See jQuery Ajax Doc section "context" for more details.
I believe all you needed to change in your original code was to get the reference to this outside of the success function, like this:
function ThumbsDown(id,sort,page) {
var self = this
$.ajax({
url: "/change/videos/"+id+"/thumbsdown/",
type: "POST",
data: {
"sort": sort?sort:"",
"page": page?page:""
},
success: function(data) {
//$("#content .videoList ul li.videoBox").html(data); // THIS IS WORKING, but replaces ALL the divs
$(self).parent("li.videoBox").html(data); // Cant get this to work!
}
});

Jquery UI sortable have no e.target on children

I have a sortable list of folders using JQuery UI.
The thing is that the folders have a child-element that is a delete button. I try to get that element and with jquery get the name of that folder. But I found out that the sortable function destroys all e.target. Below is the code of deleting a folder
<script>
function deleteFolder(){
var name = $(this).siblings('.name').html();//this is undefined
var folder = $(this).parents('.folders');
$.ajax({
url: 'serverScripts/home/deleteFolder.php',
data: {name: name},
success: function(text){
if(text == 'success'){
folder.remove();
}
}
});
};
</script>
<div class='folder>
<div class='name'>Hello</div>
<div class='deleteBtn' onclick='deleteFolder()'>Delete</div>
</div>
You'll be much better off using jQuery to bind your event handler instead of an "onclick" attribute:
<script>
$(function() {
$('.folder .deleteBtn').click(function() {
var name = $(this).siblings('.name').html();//this is undefined
var folder = $(this).parents('.folders');
$.ajax({
url: 'serverScripts/home/deleteFolder.php',
data: {name: name},
success: function(text){
if(text == 'success'){
folder.remove();
}
}
});
});
});
</script>
When you bind the event handler with an old-fashioned "onclick" attribute, jQuery can't help you. When you do something like the above, then the library can normalize the "event" object, establish this properly, etc. If you want the event object, you can declare an argument to the handler:
$('.folder .deleteBtn').click(function(event) {
$(this) is not what you think it is.
The onClick event is bound to the <div class="deleteBtn">, this is the <div class="deleteBtn"> actually the window object and not the <div class="folder"> which is why the selector is not finding any siblings() with the .name class.

Categories

Resources