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

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.

Related

Jquery - Pass re-assigned Global variable to function

So i have been working on this 'public chat' system for a while... I've succeeded with appending submitted message into the text box. But when it came to 'RECEIVING' other peoples messages, I failed.
The problem: I'm not able to use the re-assigned global variable inside a function.
I've assigned the global variable "global_msg_id" to an empty value in order to be able to re-assign it later inside ajax.
I want to pass the re-assigned variable (from ajax) to the function "message_receiver()"
var global_msg_id = "";
$(document).ready(function(){
$("#txtarea_msgsender").keydown(function(e){
if(e.keyCode == 13 && !e.shiftKey) {
e.preventDefault();
var url = "/pages/pmsg_sr.php";
$.ajax({
type: "POST",
url: url,
data: $("#msgbox_form").serialize(),
dataType: "json",
success: function(data) {
global_msg_id = data['id'];
$('#rec_sen').append('<div class="new_msg_box"><div class="new_msg_holder"><b>'+data['user']+': </b>'+data['message'].replace(/\\/g, '')+'</div></div>');
$('#txtarea_msgsender').val("");
$("#rec_sen").scrollTop($("#rec_sen")[0].scrollHeight - $("#rec_sen").height());
}
});
}
});
/* ############ Message receiver ############## */
setInterval(receive_message, 10000)
function receive_message() {
alert(global_msg_id); // RETURNS empty value
}
});

I need to get a variable between jQuery function and AJAX

I have two buttons on the form I'm getting, this first piece of coce allow me to know which was the button clicked by getting the id of it.
var button;
var form = $('.register_ajax');
$('#vote_up, #vote_down').on("click",function(e) {
e.preventDefault();
button = $(this).attr("id");
});
and this other send the form data through AJAX using the info already obtained from the button using the script above.
form.bind('submit',function () {
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
cache: false,
dataType: 'json',
data: form.serialize() + '&' + encodeURI(button.attr('name')) + '=' + encodeURI(button.attr('value')) ,
beforeSend: function() {
//$("#validation-errors").hide().empty();
},
success: function(data) {
if(data.message == 0){
$("#fave").attr('src','interactions/favorite.png');
$("#favorite").attr('value',1);
console.log(data.errors);
}
if(data.message == 1)
{
$("#fave").attr('src','interactions/favorite_active.png');
$("#favorite").attr('value',0);
}
if(data.message == "plus")
{
$("#vote_up").attr('class','options options-hover');
$("#vote_down").attr('class','options');
console.log(data.message);
}
if(data.message == "sub")
{
$("#vote_down").attr('class','options options-hover');
$("#vote_up").attr('class','options');
console.log("sub");
}
},
error: function(xhr, textStatus, thrownError) {
console.log(data.message);
}
});
return false;
});
The problem is that the data is not being passed to the ajax function, the button info is being saved on the button var, but it's not being obtained at time on the ajax call to work with it (or at least that is what I think). I'd like to know what can I do to make this work, any help appreciated.
1st edit: If I get the button data directly like button = $('#vote_up'); it doesn't work either, it only works if I get the button directly like this but without using the function.
2nd edit: I found the solution, I posted below.
var button is in the scope of the .on('event', function(){})
You need to declare the variable in the shared scope, then you can modify the value inside the event callback, i.e.
var button,
form = $('.register_ajax');
$('#vote_up, #vote_down').on("click",function(e) {
e.preventDefault();
button = $(this).attr("id");
});
You are being victim of a clousure. Just as adam_bear said you need to declare the variable outside of the function where you are setting it, but you are going to keep hitting these kind of walls constantly unless you dedicate some hours to learn the Good Parts :D, javascript is full of these type of things, here is a good book for you and you can also learn more from the author at http://www.crockford.com/.
I Found the solution, I just changed a little bit the click function like this:
var button;
var form = $('.register_ajax');
var data = form.serializeArray();
$('#vote_up, #vote_down').on("click",function(e) {
e.preventDefault();
button = $(this).attr("id");
data.push({name: encodeURI($(this).attr('name')), value: encodeURI($(this).attr('value'))});
form.submit();
});
using e.preventDefault(); and form.submit(); to send the form. also I changed the data.serialize to serializeArray(); because it's more effective to push data into the serializeArray(). in the second script I just changed the data.serialize() and used the data variable that I already filled with the serializeArray() and the data.push():
form.bind('submit',function () {
alert(button);
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
cache: false,
dataType: 'json',
data: data,
//here goes the rest of the code
//...
});
return false;
});
it worked for me, it solved the problem between the click and submit event that wasn't allowing me to send the function through ajax.

Changing CSS class dynamically

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');

Automatically create listview items with an anchor tag in it

I am making a webapp with Jquery Mobile. I got my data back from a webservice function.
Now to get this data in my web page I am using a ajax call.
$('[data-role=page]').live('pageshow', function () {
var userId = $("#userId").val();
$.ajax({
url: "~SYSTEM.URL~~CAMPAIGN.URL~/SelligentMobile/Webservice/WebService.asmx/getNieuwtjes",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{'userId':'" + userId + "'}",
success: function (response) {
var nieuwtjes = response.d;
if (nieuwtjes.length > 0) {
$.each(nieuwtjes, function (i, entity) {
$('#nieuwtjesList').append(
//Here come's the data from web function
});
}
}
});
});
Now in #nieuwtjesList should come all the data that I get back from the server. These data is a newsTopic. And it should show it like this.
<li>~ITEM.ONDERWERP~ </li>
My question is, how can I create the line above for every record I got back from my webservice function.
Kind Regards.
Stef
You can use this code to create the HTML to append for each line
$("<li/>").append($("<a/>")
.attr("href", <HREF FROM YOUR DATA>)
.text(<TEXT FROM YOUR DATA>)
);
You can use jQuery.tmpl to easily implement this.
var nieuwtjes = response.d;
if (nieuwtjes.length > 0) {
var html ='';
$.each(nieuwtjes, function (i, entity) {
html += '<li>'+ i.ONODERWERP+'</li>';
});
$('#nieuwtjesList').append($(html));
}

js how to make my array be visible by other functions

my first alert shows the list of items but the second is not. I've never done anything in ajax/js before so i don't know how to return my array so it would be visible by other functions.
var mycarousel_itemList = [];
$(document).ready(function () {
$.ajax({
type: "GET",
url: "xml/images.xml",
dataType: "xml",
success: function (xml) {
$(xml).find('image').each(function () {
var id = $(this).attr('id');
var url = $(this).find('url').text();
mycarousel_itemList.push('{url:"' + url + '",' + 'id:"' + id + '"}');
alert(mycarousel_itemList);
});
}
});
alert(mycarousel_itemList);
});
This is how my xml looks like
<images>
<image id="1">
<title>item</title>
<url>images/image.gif</url>
<desc>description of an item</desc>
</image>
<image id="2">
<title>anotheritem</title>
<url>images/images.gif</url>
<desc>description of an item</desc>
</image>
</images>
The mycarousel_itemList array is not declared within a function and thus is global. You should be able to access the array in your success event function.
There's something borked with your specific example (e.g., the success function isn't getting hit because the server doesn't respond).
If I copy and paste your code and simply replaced the server-side component with a JSONP service (just so I can do AJAX across domains), I have no problem accessing the array:
var mycarousel_itemList = [];
$(document).ready(function () {
var url = "http://github.com/api/v2/json/user/show/yui";
$.ajax({
type: "GET",
url: url,
dataType: "jsonp",
success: function (data) {
mycarousel_itemList.push(data.user.company + ' - ' + data.user.blog);
alert(mycarousel_itemList[0]);
}
});
});
You can test it out here.
To answer the direct question: it's not possible to make the array populated when the second alert is called because by that time the AJAX call didn't have time to complete.
What function exactly need that array?
Just call it from within the success method after you populate the array and it will work just fine.

Categories

Resources