Changing CSS class dynamically - javascript

I have an indicator on a page which is either a red or green circle.
<div class="publicBm changeState" currentstate="1" statusid="56" title="This is Public"></div> <!-- green -->
<div class="privateBm changeState" currentstate="1" statusid="57" title="This is Private"></div> <!-- red -->
When a user clicks the circle (which is a div with class changeState as shown above) an AJAX call is made to update the database to the opposite of what the item currently is, public or private. Then it returns the opposite class.
All works perfectly but I want to change the class on the circle clicked to reflect that the update has been successful.
Here's what I'm trying - as I said, the actual database call within the php file is perfect it's just that the div is not having it's class changed.
NOTE - there can be multiple lines on each page so I can't simply give the DIV an id
$('.changeState').click(function() {
var bm_id = $(this).attr('statusID');
var current = $(this).attr('currentState');
$.ajax({
type: "POST",
url: '/ajax/actions/editStateBm.php?bm_id='+bm_id+'&current='+current,
success:
function(data) {
$(this).removeAttr('class').attr('class', data + ' changeState');
}
});
});

Your issue is this. this is not the DOM element inside the ajax success callback. Instead set the context as that of the element so that this inside the callback now refers to the element and not jqXhr object.
$.ajax({
type: "POST",
url: '/ajax/actions/editStateBm.php?bm_id='+bm_id+'&current='+current,
context: this, //<-- Here
success:
function(data) {
this.className = data + ' changeState';
}
});
or use a cached context.
...
var self = this;
$.ajax({
type: "POST",
url: '/ajax/actions/editStateBm.php?bm_id='+bm_id+'&current='+current,
success:
function(data) {
self.className = data + ' changeState';
}
});
...
BTW what are you posting? you need to use GET?
$.ajax({
type: "GET",
....

Use .addClass()
success: function (data) {
$(this).removeAttr('class').addClass(data + ' changeState');
}
and removeProp
success: function (data) {
$(this).removeProp('class').addClass(data + ' changeState');
}

This should be something like:
$(this).removeClass('class').addClass(data + ' changeState');

Related

jquery ajax data is not printing in parent element

my problem is when i try to show a value by ajax calling,it shows the value to "generic" class but when i try to show it on the parent row it is not showing anything.
here is my ajax code
$.ajax({
type: 'POST',
url: 'http://localhost/medical/index.php/purchase/test',
data: 'data=' + pid,
success: function() {
$.get('http://localhost/medical/index.php/purchase/test', function(data) {
$(this).parents('tr').find('.generic').html(data); // doesn't show the value
$( ".generic" ).html(); // this show the value but in all table row
});
}});
Thanks in Advance
The problem is called scope. this in context of the anonymous function means something else than it means outside. You can do it like this
var that = this;
$.ajax({
...
success: function() {
$.get(..., function(data) {
$(that).parents('tr').find('.generic').html(data);
});
}
});

Checking text of individual divs and changing content

I have repeats of the same code multiple times because of my PHP echoing the content out, and I want to interact with each div separately. It's hard for me to explain, but here's an example of the code repeated just twice. Hopefully it fully represents what I actually have...
<form id="favorite"><div id="images"><input type="submit" style="background-image: url(grey.png);" onclick="submit" value="" /></div></form>
<form id="favorite"><div id="images"><input type="submit" style="background-image: url(grey.png);" onclick="submit" value="" /></div></form>
javascript:
$('#favorite').submit(function() {
var url = document.URL;
if(document.getElementById("images").innerHTML.indexOf("grey") != -1) {
$.ajax({
type: "POST",
url: url,
data: $("#favorite").serialize(),
success: function(data)
{
$('#images').html("<input type=\"submit\" style=\"background-image: url(red.png);\" onclick=\"submit\" value=\"\" />");
}
});
} else {
$.ajax({
type: "POST",
url: url,
data: $("#favorite").serialize(),
success: function(data)
{
$('#images').html("<input type=\"submit\" style=\"background-image: url(grey.png);\" onclick=\"submit\" value=\"\" />");
}
});
}
return false;
});
So, if I were to click the image for the top form, it works perfectly. It will run the PHP and it will change the image without refreshing. If I click the bottom image, it will run the PHP, but it will refresh the page and it won't change the image. So it seems like if I click the bottom one, it doesn't like the Javascript. I don't know if it's because it's looking at both of the forms since they have the same ID (which I can't fix since it could possibly have hundreds), or something else, which I don't see any problems. I'm guessing there's some way to do it using "this", but I'm unsure of how to use it.
Thank you!
You need to change a few things. Your selector to bind the event only matches the first occurrence of #favourite as id's should be unique. You get around this by using an attribute equals selector.
In addition, ensure you select each sub-element in the context of the current form, similar to this:
$('[id=favorite]').submit(function () {
var $form = $(this); // the current form
var $image = $('#images', $form) // get images element in the context of current form
var url = document.URL;
if ($image.html().indexOf("grey") != -1) {
$.ajax({
type: "POST",
url: url,
data: $form.serialize(), // use current form, don't re-select
success: function (data) {
$image.html("<input type=\"submit\" style=\"background-image: url(red.png);\" onclick=\"submit\" value=\"\" />");
}
});
} else {
$.ajax({
type: "POST",
url: url,
data: $form.serialize(), // use current form, don't re-select
success: function (data) {
$image.html("<input type=\"submit\" style=\"background-image: url(grey.png);\" onclick=\"submit\" value=\"\" />");
}
});
}
return false;
});

Why do I get undefined when displaying value in a global variable?

I just don't get it, obviously. I've tried setters and getters, self invoking functions, you name it. It's like the click handler is returning a value but there's no way for me to keep it?
This is my code in the first file request.js
var testId = (function (inId) {
var citeId = inId;
return citeId;
})();
function mainAjax() {
return $.ajax({
type: 'GET',
url: 'https://www.sciencebase.gov/catalog/items?parentId=504108e5e4b07a90c5ec62d4&max=60&offset=0&format=jsonp',
jsonpCallback: 'getSBJSON',
contentType: "application/json",
dataType: 'jsonp'
});
}
var promise = mainAjax();
this is the code in my second file requestMain.js,
promise.done(function (json) {
var linkBase = "http://www.sciencebase.gov/catalog/item/";
var link = "";
var itemId = "";
var urlId = "";
$.each(json.items, function(i,item) {
link = linkBase + this.id;
$('#sbItems').append('<li><b>' + this.title + ' - </b>' + this.summary + '</li>');
});
$('#sbItems a').on('click', function (e) {
e.preventDefault();
var str = $(this).attr('id');
if (str.length == 7) {
itemId = str.slice(5,6);
}
else if (str.length == 8) {
itemId = str.slice(5,7);
}
testId = json.items[itemId].id;
alert(testId);
}); // END Click event
}).fail(function() {
alert("Ajax call failed!");
});
This webpage displays a list of links. A link could have some more information that I want displayed on a second webpage or it could have nothing. So when a link is clicked I need to store/save/keep the id from the link so that I can use it in the url to make another ajax request, because until I get the id the ajax request for the next page will have no idea what information to ask for.
For now I'm simply doing this
alert(testId);
But what I'm trying to do is this,
$.ajax({
type: 'GET',
url: 'https://www.sciencebase.gov/catalog/itemLink/' + testId + '?format=jsonp',
jsonpCallback: 'getSBJSON',
contentType: "application/json",
dataType: 'jsonp',
// Then doing something with json.something
testId would be used in the url and it would change depending on the link that was clicked on the previous page. The ajax call is totally dependent on the click event and is displayed on a separate webpage with new information.
And this would be in my third file requestCitation.js which currently gives me a big undefined when doing
alert(testId);
I think this is a scope issue, but how can I store the value returned from a click??? So that I can then use it globally? It seems like the value disappears outside of the scope as if there was never a click at all even thought I'm storing it in a variable?
the html for the first page has script tags for request.js and requestMain.js and the second page has script tags for request.js and requestCitation.js, so they can both see the variable testId.
Thanks for the help!
Here's the jsfiddle
These are the links and when a link is clicked
Your testId is holding the value retuned by the function you're calling, and since the function returns its argument and you've called it without arguments, it will be undefined:
var testId = (function (inId) {
var citeId = inId;
return citeId; //returns the argument
})(); // called with no argument
I'm not entirely sure what you're trying to do but if you're trying to keep the data returned from the AJAX request as a global variable, I would have thought it was done using something similar to the below.
E.g.
var promise = '';
$.ajax({
type: 'GET',
url: 'https://www.sciencebase.gov/catalog/items?parentId=504108e5e4b07a90c5ec62d4&max=60&offset=0&format=jsonp',
jsonpCallback: 'getSBJSON',
contentType: "application/json",
dataType: 'jsonp'
data: '';
success: function(data){
promise = data;
}
});
But as I said I'm not understanding fully so I could be very wrong with my answer.

My function only works with an alert after my ajax call

I'm populating a table with values from my database. I have included a delete icon in rows which can be deleted. The image has an onclick='deleteCat(id);' property, the id is taken from a json array trough a loop like so:
string = "<td align='center'><a href=''><img border='0' src='../images/Bullet-Delete.png' alt='delete' onclick='deleteCat("+json[i]['id']+");'/></a></td>";
This is my deleteCat function:
function deleteCat(id){
var dataString = "catId=" + id;
$.ajax({
type: "POST",
url: "../ajax/categorie_verwijderen.php",
data: dataString,
success: function(data) {
//$("#allecat").find("tr:gt(0)").remove();
//update_table();
}
});
//alert(id);
}
My function works when I put an alert after the ajax. The table refreshes and the row is removed from my db. However when I remove the alert my function does not work, the table is refreshed and the row is still present in the table and db.
Thanks in advance.
You need to prevent the default event for the click - ie the page is being reloaded each time you click on the image
function deleteCat(id){
var dataString = "catId=" + id;
$.ajax({
type: "POST",
url: "../ajax/categorie_verwijderen.php",
data: dataString,
success: function(data) {
$("#allecat").find("tr:gt(0)").remove();
update_table();
}
});
return false; // prevent the browser following the href
}
You will also need to change your html :
onclick='return deleteCat("+json[i]['id']+");
The alert() helps because that delays the processing of the remaining javascript in that function. The ajax send data asynchronously. async key is Default: true and should change it to false in your call till the client wait for end of ajax call.
e.g.:
$.ajax({
async:false,
url: "test.html",
.
.
});

Setting data-content and displaying popover

I'm trying to get data from a resource with jquery's ajax and then I try to use this data to populate a bootstrap popover, like this:
$('.myclass').popover({"trigger": "manual", "html":"true"});
$('.myclass').click(get_data_for_popover_and_display);
and the function for retrieving data is:
get_data_for_popover_and_display = function() {
var _data = $(this).attr('alt');
$.ajax({
type: 'GET',
url: '/myresource',
data: _data,
dataType: 'html',
success: function(data) {
$(this).attr('data-content', data);
$(this).popover('show');
}
});
}
What is happening is that the popover is NOT showing when I click, but if I hover the element later it will display the popover, but without the content (the data-content attribute). If I put an alert() inside the success callback it will display returned data.
Any idea why is happening this? Thanks!
In your success callback, this is no longer bound to the same value as in the rest of get_data_for_popover_and_display().
Don't worry! The this keyword is hairy; misinterpreting its value is a common mistake in JavaScript.
You can solve this by keeping a reference to this by assigning it to a variable:
get_data_for_popover_and_display = function() {
var el = $(this);
var _data = el.attr('alt');
$.ajax({
type: 'GET',
url: '/myresource',
data: _data,
dataType: 'html',
success: function(data) {
el.attr('data-content', data);
el.popover('show');
}
});
}
Alternatively you could write var that = this; and use $(that) everywhere. More solutions and background here.
In addition to the answer above, don't forget that according to $.ajax() documentation you can use the context parameter to achieve the same result without the extra variable declaration as such:
get_data_for_popover_and_display = function() {
$.ajax({
type: 'GET',
url: '/myresource',
data: $(this).attr('alt'),
dataType: 'html',
context: this,
success: function(data) {
$(this).attr('data-content', data);
$(this).popover('show');
}
});
}

Categories

Resources