Alternatives to global variables? - javascript

I'm trying to wrap my head around alternatives for global variables.
Case in question is one where I need to find values in one XML and compare against another XML (or more). Since the XML JQuery is, itself, a function and the operations beneath that are functions inside of a function (ugh) I can't get a value from 2 functions deep and use it globally.
So it's presently not possible for me to get an XML value from 1 file and use it filter another XML file, and that's where I need help.
I've been handed 3 XML files.
File 1 - categories.xml - contains a mapping of categories
ex...
<CAT>
<OA1>True</OA1>
<OA2>False</OA2>
<OA3>True</OA3>
<EP1>True</EP1>
<EP2>False</EP2>
<EP3>False</EP3>
</CAT>
File 2 = oa.xml - contains the values of each OA record
ex...
<OA>
<Name>Name 1</Name>
<City>City</City>
<State>ST</State>
</OA>
and so on...
File 3 = EP.xml - contains the values of each EP record
Copy code
<EP>
<object 1></object1>
<object 2></object2>
<object 3></object3>
</EP>
Now, what I thought I could do when I started was to allow the user to select a category, and based upon that selection return 2 tables containing the values that mapped to that category.
My problem is that when JQuery starts parsing XML it does it in a function (in all examples I've seen) so I have no idea how to set a variable inside of one function and use it inside of the next function used to open the 2nd file, or the 3rd.
Here is what I have now:
Copy code
<script>
var catid = ""; // I thought this, being outside of the function would be a global varaible
OA1 = ""; // I tried it with and without var in front
var OAid = "";
$(document).ready(function(){ //When opening an XML we do it in a function
$.ajax({
type: "GET",
url: "xml/categories.xml",
dataType: "xml",
success: function(xml) {
$(xml).find('Cat').each(function(){
//Next 2 rows don't matter b/c I can't use their values outside
//of the function
var catid = $(this).find('Catid').text();
var OA1 = $(this).find('OA1').text();
$('<div class="page-wrap"></div>').html('<table><tr><td>' + catid +'</td><td>OA1 '+ OA1 +'</td></tr></table></div>').appendTo('#page-wrap');
});
}
});
});
//The only way I know how to open up the next XML, start all over again
$(document).ready(function(){
$.ajax({
type: "GET",
url: "xml/OA.xml",
dataType: "xml",
success: function(xml) {
$(xml).find('OAData').each(function(){
var OAid = $(this).find('OAid').text();
$('<div class="page-wrap"></div>').html('<table><tr><td>OA ID is '+ OAid +'</td></tr></table></div>').appendTo('#page-wrap');
});
}
});
});
</script>
//Somebody shoot me
ANY ADVICE would be most appreciated - I haven't been able to even consider the compare operation b/c of the variable issue.
Is there a way to compare 2 XML files and I'm just missing it, or can you recommend a solution using some sort of temporary location?

So taking the suggestion of #Kevin B and enhancing it a bit, you can pass values to your different success handler functions easily if you factor those functions out into separate functions.
<script>
var catid = ""; // I thought this, being outside of the function would be a global varaible
OA1 = ""; // I tried it with and without var in front
var OAid = "";
$(document).ready(function(){ //When opening an XML we do it in a function
$.ajax({
type: "GET",
url: "xml/categories.xml",
dataType: "xml",
success: function(xml) {
$(xml).find('Cat').each(function(){
//Next 2 rows don't matter b/c I can't use their values outside
//of the function
var catid = $(this).find('Catid').text();
var OA1 = $(this).find('OA1').text();
$('<div class="page-wrap"></div>').html('<table><tr><td>' + catid +'</td><td>OA1 '+ OA1 +'</td></tr></table></div>').appendTo('#page-wrap');
});
$.ajax({
type: "GET",
url: "xml/OA.xml",
dataType: "xml",
success: function(xml) { getCategoriesSuccess(xml, catid, OA1, OAid); }
});
}
});
});
function getCategoriesSuccess(xml, catid, OA1, OAid) {
$(xml).find('Cat').each(function(){
//Next 2 rows don't matter b/c I can't use their values outside
//of the function
var catid = $(this).find('Catid').text();
var OA1 = $(this).find('OA1').text();
$('<div class="page-wrap"></div>').html('<table><tr><td>' + catid +'</td><td>OA1 '+ OA1 +'</td></tr></table></div>').appendTo('#page-wrap');
});
$.ajax({
type: "GET",
url: "xml/OA.xml",
dataType: "xml",
success: function(xml) { getOASuccess(xml, OAid); }
});
});
}
function getOASuccess(xml, OAid){
$(xml).find('OAData').each(function(){
var OAid = $(this).find('OAid').text();
$('<div class="page-wrap"></div>').html('<table><tr><td>OA ID is '+ OAid +'</td></tr></table></div>').appendTo('#page-wrap');
});
}
</script>
So inside your $(document).ready()'s ajax call's success handler, you make a second ajax call as #Kevin B suggested. You can pass additional data to this by wrapping a function call inside your success handler. And I'll pass the data that a second nested function call (inside getCategoriesSuccess) needs in that first call so that it's available for the second call. So that's why I pass OAid in the first nested function call because it's needed inside of getOASuccess.
I'm sure there are other ways to do this, but this gives you a bit of flexiblity with your success handlers.
I hope this helps. Let me know if there are additional questions and I'll update my answer accordingly. Good luck!

Related

making variable global by window method does not work

After looking for other answers to make a variable global I am struggeling for some time now, it looks quite simple but it just doesn't seem to work.
My code is getting data from a CSV file and returning a variable called 'chart' containing an Array. This Array variable is to be used outside the function in a Highchart graph. (The local returned Array is correct)
I am trying to make the variable inside the function "global" by attaching it as a property of the window. Like this: turn javascript local variable into global variable
But in my code this doesn't work out:
$(document).ready(function() {
$.ajax({
type: "GET",
url: "data/data.csv",
async: false,
dataType: "text",
success: function(data) {processData(data);}
});
});
function processData(data) {
var table = data.split("\n").map(line => line.split(","));
var categories = table[0].slice(2).map(e=>e*1);
data = table.slice(1).map(a => ({"name": a[0], "id": parseInt(a[1]), "data": a.slice(2).slice(0).map(e=>e*1)}));
var lengthdata = data.length - 1;
var chart = data.splice(0, lengthdata);
window.chartglobal = chart;
console.log(chart);
};
console.log(chartglobal);
What am I missing here or are there better ways than the window option for mmy specific situation?
EDIT:
The code is used in leaflet where the data is connected to leaflet markers using map.on and a marker id. That way is doesn't matter that the call ajax request is a pseudo ready event which is fired after trying to get the global value. I don't know what changing the async to 'true' alters but it works either way.
The variable is used in a map.on like this:
map.on('popupopen', function(e) {
var marker = e.popup._source.feature.id;
var search = function(name) {
for(var key in chartglobal) {
if(chartglobal[key].id === name) {
return chartglobal[key];
}}};
var outputhighchart = search(marker);
var chartdef = [];
chartdef.push(outputhighchart);});
The console.log was not logging because of the ajax call, the problem was somewhere in the map.on, which I overlooked because focusing on the global variable. Thanks for helping me out and directing in the right way.
why dont you declare your variable outside your function and give a dummy val
var chartglobal = "dummy";
$(document).ready(function() {
$.ajax({
type: "GET",
url: "data/data.csv",
async: false,
dataType: "text",
success: function(data) {processData(data);}
});
});
function processData(data) {
var table = data.split("\n").map(line => line.split(","));
var categories = table[0].slice(2).map(e=>e*1);
data = table.slice(1).map(a => ({"name": a[0], "id": parseInt(a[1]), "data": a.slice(2).slice(0).map(e=>e*1)}));
var lengthdata = data.length - 1;
var chart = data.splice(0, lengthdata);
chartglobal = chart;
console.log(chart);
};
//as #Artur Filipiak sais at this point variable is not setted yet. so should print "dummy"
console.log(chartglobal);

JavaScript Saving data from an ajax request

Challenge:
While on URL1(random wikipedia page), make an ajax request to URL2(100 most common words wikipedia page), format a list out of the returned data to be used later.
I have to run this from the console while on "URL1"
example:
Navigate to URL1
Open Console
paste code
hit enter
So far I have been able to grab the entire html source while on URL1 with the following:
$.ajax({
url: 'https://en.wikipedia.org/wiki/Most_common_words_in_English',
type: 'GET',
dataType: 'html',
success: function (response) {
console.log(response); // works as expected (returns all html)
}
});
I can see in the console the entire HTML source -- I then went to URL2 to figure out how to grab and format what I needed, which I was able to do with:
var array = $.map($('.wikitable tr'),function(val,i){
var obj = {};
obj[$(val).find('td:first').text()] = $(val).find('td:last').text();
return obj;
});
console.log(JSON.stringify(array));
Now this is where my issue is -- combining the two
$.ajax({
url:'https://en.wikipedia.org/wiki/Most_common_words_in_English',
type:'GET',
dataType:'html',
success: function(data){
// returns correct table data from URL2 while on URL2 -- issue while running from URL1
var array = $.map($('.wikitable tr'),function(val,i){
var obj = {};
obj[$(val).find('td:first').text()] = $(val).find('td:last').text();
return obj;
});
console.log(JSON.stringify(array));
};
});
Im guessing this is due to the HTML I want to map is now a string, and my array is looking for HTML elements on the current page which it of course would not find.
Thanks
Simple fix here! You're exactly right, it's not parsing the html you return, so just tell jQuery to convert it into an object it can use $(data) and use that to find what you need.
In essence, your 'document' now becomes $(data) which you will use as the source of all your queries.
$.ajax({
url: 'https://en.wikipedia.org/wiki/Most_common_words_in_English',
type: 'GET',
dataType: 'html',
success: function(data) {
var myVar = data;
Names = $.map($(myVar).find('.wikitable tr'), function(el, index) {
return $(el).find('td:last').text()
});
console.log(Names);
}
});

What am i doing wrong with this dynamic query?

i've never used AJAX or JQuery before, but here's my attempt at dynamic loading(pulled from various examples here at stackoverflow)
this is the script i have in my view:(edited to comply with mayabelle's code.) doesn't throw either alert, and the breakpoint on DRequest never trips, but drequest produces results if called directly.
<script type="text/javascript">
$(document).ready(function () {
alert("testing123");
$response = DRequest;
alert("good at response");
$.ajax({
url: "request/drequest"
type: "GET",
dataType: "json",
success: function ($response) {
alert("I am an alert box2!");
// Do something with your response
var $tr = $('<tr>').append(
$('<td>').text($response.NeededByDate),
$('<td>').text($response.RequestedBy),
$('<td>').text($response.Username),
$('<td>').text($response.RequestedPCID),
$('<td>').text($response.RequestType_ID),
$('<td>').text($response.Division_ID),
$('<td>').text($response.ReqTypeIcon)
).appendTo('#requestTable');
console.log($tr.wrap('<p>').html());
}
});
setInterval(function () {
var url = '#';
$('body').load(url);
}, 300000);
});
</script>
is supposed to dynamically append one row at a time (until there are no more rows to add) from the DRequest JsonResult (this is producing results when called directly by way of the addressbar). this should reload the whole page every 5 minutes(300000 seconds).
the JsonResult looks like this
Public Function DRequest() As JsonResult
Dim Reqs = _db.dRequestGetAll
Return Json(Reqs, JsonRequestBehavior.AllowGet)
End Function
where "_db.dRequestGetAll" returns a collection of dRequest rows like so:
Public Function dRequestGetAll() As IEnumerable(Of DRequest)
Return From r In _PITcontext.Requests Where r.CompletedDate Is Nothing Select r
End Function
so. what did i miss?
EDIT: i replaced the javascript from the original post with the most current version since comments can't handle more than 600 characters.
Try like this:
$(document).ready(function () {
$.ajax({
url: url to your controller action,
type: "GET",
dataType: "json",
success: function (response) {
// Do something with your response
}
});
}
Also, in your code above you are calling your variable $response but then in your each loop you are trying to access response (no $ prefix).
I think you should be using $.map() instead of $.each(). It returns an array of your elements. Differences are discussed here.

returning part of a json file as a variable in jquery

I am attempting to create a glossary tooltip for a website that finds keywords from a json file that is being created by sitecore. I need to get the "Text:" parts from the json file and make then a variable in my jquery so they are the keywords that are found and wrapped with the appropriate tags. I had it working to the point where i could get console to log that there were 2 entries in my json file but that's it.
Here is my sample json code:
[{"Id":"ef339eaa-78e1-4f9e-911e- 096a1920f0b6","Name":"Glossary","DisplayName":"Glossary","TemplateId":"b27d2588-3d02-4f5f-8064-2ee3b7b8eb39","TemplateName":"Glossary","Url":"/Global-Content/Glossary/Glossary","Version":1,"Created":"\/Date(1343987220000)\/","CreatedBy":"sitecore\\rgoodman","Revision":"ae8b3ae0-d0ca-4c4a-9f27-a542a31ab233","Updated":"\/Date(1348137810133)\/","UpdatedBy":"sitecore\\admin","Text":"Glossary","Content":"A bit of test content for the glossary"},{"Id":"3fa51ad4-cfb6-4ff1-a9b5-5276914b2c23","Name":"Abraham","DisplayName":"Abraham","TemplateId":"b27d2588-3d02-4f5f-8064-2ee3b7b8eb39","TemplateName":"Glossary","Url":"/Global-Content/Glossary/A/Abraham","Version":1,"Created":"\/Date(1348148640000)\/","CreatedBy":"sitecore\\admin","Revision":"231284ec-9fb9-4502-ad79-a5806479ecba","Updated":"\/Date(1348148779656)\/","UpdatedBy":"sitecore\\admin","Text":"Abraham","Content":"This is a lincoln person"}]
But I suppose this is not of any use as it is just the "Text:" part i am looking to return.
Here is my jquery:
function getData(url) {
var data;
$.ajax({
async: false,
url: '/_assets/js/glossary.json',
dataType: 'json',
success: function(data.Text){
data.Text = response;
}
return(response);
});
}
function HighlightKeywords(keywords)
{
var el = $("body");
$(keywords).each(function()
{
var pattern = new RegExp("(" +this+ ")", ["gi"]);
var rs = "<mark href='#' class='tooltip'>$1</mark>";
el.html(el.html().replace(pattern, rs));
});
}
HighlightKeywords(data.Text);
Essentially i need to return the "Text:" bit of json where data is on the HighlightKerywords function. Where am i going wrong?
Any help would be much appreciated. Thanks
Your function is not syntactically formatted properly. Your return must go inside of the success function in the synchronous example, and not randomly placed in the ajax object..
function getData() {
$.ajax({
async: false,
url: '/_assets/js/glossary.json',
dataType: 'json',
success: function(data){
//HighlightKeywords(data.Text);
//or
return(data.Text);
}
});
}
Ajax is Asynchronous communication, you can't insert its response into a global variable and expect to be able to work with it.
You need to do all the work on the data.text in the success function.
success: function(response){
HighlightKeywords(response.Text);
}

howto "submit" a part of a form using jQuery

I'm got a form laid out like a spreadsheet. When the user leaves a row, I want to submit fields from that row to the server using jQuery Ajax. The page is one large form, so this isn't really a javascript clicking the submit button scenario - the form is huge and I only want to send a small portion of the content for reasons of speed.
I've got the code written that identifies the row and iterates through the fields in the row. My issue is how to build the dat object in order to submit something comprehensible I can disassemble and store at the server end.
At the moment my code looks like this
var dat=[];
$("#" + finalrow).find("input").each(function () {
var o = $(this).attr("name");
var v = $(this).val();
dat.push({ o: v });
});
$.ajax({
url: 'UpdateRowAjax',
dataType: 'json',
type: 'POST',
data: dat ,
success: function (data) {
renderAjaxResponse(data);
}
});
The assembling of dat doesn't work at all. So how should I build that dat object in order for it to "look" as much like a form submission as possible.
You can add the elements that contain the data you want to send to a jQuery collection, and then call the serialize method on that object. It will return a parameter string that you can send off to the server.
var params = $("#" + finalrow).find("input").serialize();
$.ajax({
url: 'UpdateRowAjax',
type: 'POST',
data: params ,
success: function (data) {
renderAjaxResponse(data);
}
});
You can use $.param() to serialize a list of elements. For example, in your code:
var dat= $.param($("input", "#finalrow"));
$.ajax({
url: 'UpdateRowAjax',
dataType: 'json',
type: 'POST',
data: dat ,
success: function (data) {
renderAjaxResponse(data);
}
});
Example of $.param(): http://jsfiddle.net/2nsTr/
serialize() maps to this function, so calling it this way should be slightly more efficient.
$.ajax 'data' parameter expects a map of key/value pairs (or a string), rather than an array of objects. Try this:
var dat = {};
$("#" + finalrow).find("input").each(function () {
dat[$(this).attr('name')] = $(this).val();
});

Categories