Unable to get the class value out side the getJSON scope. Alert declared inside displays value but outside doesn't.
// Getting classes based on classID
var ClassID = {"ClassID": item.ClassId};
var Class="";
$.getJSON('#Url.Action("GetClassesByID","Catalogue")', ClassID, function (Val) {
Class=Val;
alert("Inside Value " +Class);
});
html= html+'<div class="col-xs-7 col-sm-7 col-md-7 dvpadding isbnnum"><p><b>CLASS - ('+Class+')</b></p></div>';
I just want to update the Class mentioned in above html from the value got from ajax call
.getJSON is asynchronous. You're calling alert outside of it which is synchronous. You need to call a function once .getJson is successful like:
// Getting classes based on classID
var ClassID = {
"ClassID": item.ClassId
};
var Class = "";
$.getJSON('#Url.Action("GetClassesByID","Catalogue")', ClassID, logData(val));
function logData(val) {
Class = Val;
alert("Outside Value " + Class);
}
The reason you are getting an empty string is because of the way javascript and callbacks work.
This is what you are expecting to happen:
class = ""
$getJSON
Class = val
alert(Class)
This is what is happening though:
class = ""
$getJSON
alert(Class)
Class = val
The reason beeing that 'Class = val" is inside a callback which is basicly just an action that is supposed to happen once $getJSON is done.
However since $getJSON could take a few seconds, whatever is below $getJSON will be run first.
You can think of $getJSON as an assignment that happens. That line of code will execute VERY fast, just as fast as any other line of code. But because you provided a callback, the callback part of the line will only be executed once the JSON was actually fetched which could be at any time.
Edit: I misread the scope completely. Sorry.
Related
On a button click, I'm calling a function in client side JavaScript.
doIt("TEST");
"TEST" is just the ID of label on my XPage.
In the function, I want to use the variable I passed as an ID. Something like:
function doIt(item){
alert(dojo.query("[id$=':item']").innerHTML);
}
OR
function doIt(item){
val = XSP.getElementById("#{id:item}").innerHTML;
alert(val);
}
I have also tried using this, which gives undefined:
val = dojo.query("[id$=':" + item + "']").innerHTML;
alert(val);
If I hard code the ID name like so, then I get the correct innerHTML of the element with the ID "TEST":
val = XSP.getElementById("#{id:TEST}").innerHTML;
alert(val);
Where is my syntax wrong when trying to write this very simple line of code used the passed variable?
The easiest way is to call your function with the complete id:
doIt("#{id:Test}")
and to use it in your function
function doIt(item){
alert(dojo.byId(item).innerHTML);
}
In the "onclick" client-event in the button, (inside XPage or CC), the client Ids can be computed, so you should put there something like this:
doIt("#{id:Test}"); // << "#{id:Test}" is computed in the server-side and the final client ID is sent to the browser
Then, in your cjs library (cjs libraries are not "evaluated" before sending to the client, so here you cannot use "#{id:Test}" expressions) you should have something like:
function doIt(idElement) {
var domElem = dojo.byId(idElement); // << here you get the element
}
I am just starting to get into JavaScript and couldn't find an exact scenario like this yet on SO, so I'm going to try my luck. I have two functions in an external JS file which create video feeds on our website:
function getVideos() {
//gets a list of videos
}
//callback function automatically called by getVideos()
function response(jsonData) { //can't change this line
var resp = document.getElementById("resp"); //can change this line and any subsequent lines
//parses data and populates resp
}
Then, from the HTML side, we just call getVideos() and the video feed will be created and populated.
However, I want to be able to pass any element ID I want into response() so that we can create multiple video feeds in different places on the same page. The thing is I can't change the function declaration of response() to include another parameter. Or at least I'm not led to believe I can by the company hosting our videos.
I've tried wrapping response() with getVideos() and passing an element ID from there, but then response() doesn't get called, and the only solution I can think of is resorting to storing an element ID in a global variable, which I know is a no-no in general in JavaScript.
My question is: Do I just bite the bullet and use a global variable, or is there another way?
For more info, here is our JS code as it stands now (with the closure): http://www.thebearrocks.com/Other/js/videoFeed/createVideoFeed.js
And here is the tutorial on response() we're following from the host of our videos: http://support.brightcove.com/en/video-cloud/docs/making-media-api-calls-dynamic-script-tags
may be you can use arguments? like so:
function response(jsonData) { //callback function automatically called by getVideos()
var elemId = arguments.length<2 ? "resp" : arguments[1]+"";
var resp = document.getElementById(elemId);
//parses data and populates resp
}
or, declare second argument what has default value like this:
function response(jsonData, elemId) {
elemId = elemId || "resp";
var resp = document.getElementById(elemId);
//parses data and populates resp
}
in this case function can be called as with one or two arguments
I've tried wrapping response() with getVideos() and passing an element ID from there, but then response() doesn't get called, and the only solution I can think of is resorting to storing an element ID in a global variable, which I know is a no-no in general in JavaScript.
My question is: Do I just bite the bullet and use a global variable, or is there another way?
No. Not the id variable needs to become global, but your local response function needs to for getting called back from the JSONP script - you're going to create a closure.
You can "export" it by calling
window.response = mylocalResponseFunction; // you did name that local var "response"
I've been at this for an hour and I need help. This is kind of baffling me. Consider this explicit setup of an object in my code:
WORKING CASE:
var terms={};
terms[0]={};
terms[1]={"label":"bag","cell_src":"images/bag.jpg","clue_type":"audio","clue_src":"/audio/bus.wav"};
terms[2]={"label":"crayon","cell_src":"images/crayon.jpg","clue_type":"audio","clue_src":"/audio/car.wav"};
terms[3]={"label":"pen","cell_src":"images/pen.jpg","clue_type":"audio","clue_src":"/audio/car.wav"};
terms[4]={"label":"pencil","cell_src":"images/pencil.jpg","clue_src":"/audio/boat.wav"};
terms[5]={"label":"pencil_case","cell_src":"images/pencil_case.jpg","clue_src":"/audio/train.wav"};
terms[6]={"label":"rubber","cell_src":"images/rubber.jpg","clue_src":"/audio/taxi.wav"};
terms[7]={"label":"ruler","cell_src":"images/ruler.jpg","clue_src":"/audio/plane.wav"};
terms[8]={"label":"sharpener","cell_src":"images/sharpener.jpg","clue_src":"/audio/taxi.wav"};
window.terms= terms;
window.terms= terms; // for using globaly
if I do a console.log(window.terms[1]); I get "bag". Thats what I want.
NOT WORKING CASE
If instead of explicitly defining the values of term{}, I read in the contents from a json file and assign them to each enumerated index like this:
var terms={};
terms[0]={};
$.getJSON('content.json', function(data){
$.each(data,function(i){
//terms[i]={"label":"bag","cell_src":"images/bag.jpg","clue_type":"audio","clue_src":"/audio/bus.wav"};
terms[i+1]={"label":data[i].headword,"cell_src":data[i].image,"clue_type":"audio","clue_src":data[i].audio};
});
window.terms=terms;
});
if I do a console.log(window.terms[1]); I get an error "Uncaught TypeError: Cannot read property '1' of undefined" Note that I have an alternate attempt commented out where I eliminate the possibility that theres something weird going on with the values I am trying to pull in and I explicitly assign the same static value to all the indexes. That produces the same error.
Any ideas how this could be??
$.getJSON does not block when performing an AJAX call. You have to keep the callback chain a live.
I think you want to define terms as an array of objects. Currently you have it defined as an object with properties 1, 2, 3, etc. Syntax like var terms = {} means terms is an object and when you assign terms[1] = {"label": "bag"} you're saying "the property named 1 of object terms is {"label": "bag"}. Just change your terms declaration to this:
var terms = [];
Also, if you want to see the label property of one of the objects the log statement would looks like this:
console.log(terms[2].label);
The $.getJSON() function is just a shorthand for a call to $.ajax() to load a JSON file. Since the AJAX call is asynchronous, the execution of $.getJSON() completes, and any code after it is executed, before the data has been loaded and stored in your variable.
If you want to work with terms do so inside the success callback function that you're passing to $.getJSON().
If your code looks like this:
var terms={};
terms[0]={};
$.getJSON('content.json', function(data){
$.each(data,function(i){
//terms[i]={"label":"bag","cell_src":"images/bag.jpg","clue_type":"audio","clue_src":"/audio/bus.wav"};
terms[i+1]={"label":data[i].headword,"cell_src":data[i].image,"clue_type":"audio","clue_src":data[i].audio};
});
window.terms=terms;
});
// use window.terms here
Then it won't work, because the // use window.terms here part executes before the AJAX call has finished. You'll need to move that to a separate function and call that from the success callback:
function workWithTerms() {
// use window.terms here
}
var terms={};
terms[0]={};
$.getJSON('content.json', function(data){
$.each(data,function(i){
//terms[i]={"label":"bag","cell_src":"images/bag.jpg","clue_type":"audio","clue_src":"/audio/bus.wav"};
terms[i+1]={"label":data[i].headword,"cell_src":data[i].image,"clue_type":"audio","clue_src":data[i].audio};
});
window.terms=terms;
workWithTerms();
});
I want to pass the name of a function "testMath" as a string into a wrapper function called "runTest" as a parameter. Then inside 'runTest' I would call the function that was passed. The reason I'm doing this is because we have a set of generic data that will populate into variables regardless of the test, then a specific test can be called, based on whatever the user wants to test. I am trying to do this using javascript/jquery. In reality the function is much more complex including some ajax calls, but this scenario highlights the basic challenge.
//This is the wrapper that will trigger all the tests to be ran
function performMytests(){
runTest("testMath"); //This is the area that I'm not sure is possible
runTest("someOtherTestFunction");
runTest("someOtherTestFunctionA");
runTest("someOtherTestFunctionB");
}
//This is the reusable function that will load generic data and call the function
function runTest(myFunction){
var testQuery = "ABC";
var testResult = "EFG";
myFunction(testQuery, testResult); //This is the area that I'm not sure is possible
}
//each project will have unique tests that they can configure using the standardized data
function testMath(strTestA, strTestB){
//perform some test
}
Do you need the function names as string? If not, you can just pass the function like this:
runTheTest(yourFunction);
function runTheTest(f)
{
f();
}
Otherwise, you can call
window[f]();
This works, because everything in the 'global' scope is actually part of the window object.
Inside runTests, use something like this:
window[functionName]();
Make sure testMath in the global scope, though.
I preffer to use apply/call approach when passing params:
...
myFunction.call(this, testQuery, testResult);
...
More info here.
I'm learning jQuery and saw this chunk of code.
myJqueryFile.js
(function($, undefined) {
function Calendar(element, options, eventSources) {
var t = this;
t.incrementDate = incrementDate;
....some code here
function incrementDate(years) {
if (years !== undefined) {
addYears(date, years);
}
renderView();
}
}
})(jQuery);
In my html, I am referencing the js above externally and want to call incrementDate() but I'm keep getting "increment is not function".
But I think incrementDate() is not private function so I should be able to call it from outside. Is it really possible?
I'm calling incrementDate like below:
<a href="" onclick="incrementDate();" />
Oops, I totally missed the surrounding jQuery bracket!
Yes, you can call it. You might have to call it using the apply which allows you to define this and arguments.
There is some docs here as well.
If you need some code:
var result = Calendar.prototype.incrementDate.apply(mycalendarObj, myArguments);
UPDATE
OK, it seems all you need is:
calObject.incrementDate(1,1,1); // adds one year + one month + one day
You can only call it on an instance of Calendar.
var cal = new Calendar(element, options, eventSources);
cal.incrementDate();
And Calendar is scoped to anonymous function you wrap the whole thing is. So that code can only appear inside that function (unless you do something to expose it).