JavaScript doesn't execute in flash based version

Hi everybody

I have a project where we export some data from variables in a storyline project to a google spreadsheet. I have the functionality down, based on javascript, in both Storyline, and in google apps script.

But since yesterday (oct. 26th, 2016) the export functionality has stopped working. After en extensive debugging session, I figured out that it must have something to do with flash, as the functionality works if I use the html5 version of the course. 

Any idea on how to fix this? I have tried on more than one computer, and in several different browsers.

22 Replies
Dave Cox

Hi Snorre,

I have several projects that imports variables, and they still work with no problem. I'm using the getPlayer, getVariable, and setVariable javascript methods. Are you using these to get and set your variables? If so, your project should still work fine.

Also, how are you publishing your projects? Are you publishing for the web, or local file system. What about where you are saving your data. It should match the file system where you are publishing your content. For example, if you are publishing for the web, you should save your files to the web server. If you are publishing for the local file system (For example publishing to a CD,) the you should save your data to the local file system. This is a security requirement of the flash environment, and the restrictions on where flash can save things have recently been tightened by some browsers. 

Also, if you are using javascript as I mentioned above, you can use the javascript command console.log(); command to determine what is happening with your code. For example, the command console.log("Line 1 just ran"); will echo "Line 1 just ran" to the console. To see the console, press F12 when the project first loads, and select the console tab in the browsers debug panel.

You can also use console.log to display your javascript variables. The command console.log("The value of myVar is ", myVar); will display the string "The value of myVar is 0", assuming the value of myVar was 0. For more information on the console.log command, check out this link

Snorre Rubin

It is exported, and deployed to a webserver. That is not the problem. As stated in the original post, it works fine in chrome, when using the story_html5.html, but not when using the story.html, which points me to the flash version.

I can't get the console.log() funktion to work either. The console gives me this error:

 

Uncaught ReferenceError: storyline is not defined(anonymous function) @ user.js:72
Dave Cox

Hi Snorre,

user.js sounds like the javascript file where your custom functions are located. Javascript found an error at line 72 of that file, and aborted. You now know the location of your first error, and why javascript failed to work as expected. 

What is on line 72 of that file? What precedes it? It sounds like a function was called that doesn't exist. What function was the script attempting to call? Does it exist somewhere in your javascript file?

You are on your way to locating the problem.

Snorre Rubin

OK, I have looked inside user.js. This is the 3rd scripts I am trying to run, with line72 in bold:

function Script3()
{
//DELAY SO JQUERY LIBRARY IS LOADED
setTimeout(function (){

//Export to Google
$.ajax({
url: WEB_APP_URL,
type: "POST",
data : storyline,
success: function(data)
{
console.log(data);
},
error: function(err) {
console.log('Error:', err);
}
});
return false;
}, 1000);
}

Any idea what the problem is here? 

As I said, it works fine if I use the htm5 version....

 

Here is the rest of the code, if it helps...

function Script1()
{
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = '//code.jquery.com/jquery-1.11.0.min.js';
script.type = 'text/javascript';
head.appendChild(script)
}

function Script2()
{
var player = GetPlayer();

//PLACE YOUR WEB APP URL
WEB_APP_URL = "https://script.google.com/macros/s/AKfycbyDRuE6iLvzn6C1qCtcRD5UCYEo1-HjgP033anXNsXICsyyDXbk/exec";

// STORE ARTICULATE STORYLINE VARIABLES
// "Columnname_Google_Spreadsheet" : player.GetVar("Name_Storyline_Variable")
// ATTENTION: Use a comma if you use multiple Storyline variables
storyline =
{
"date" : new Date().toJSON().slice(0,10), //STORE DATE
"email" : player.GetVar("email"),
"12Spm1a" : player.GetVar("12Spm1a"),
"12Spm1b" : player.GetVar("12Spm1b"),
"12Spm1c" : player.GetVar("12Spm1c"),
"12Spm2a" : player.GetVar("12Spm2a"),
"Bedoemmaalcore" : player.GetVar("BedoemMaalScore"),
"Quizresultat" : player.GetVar("Results.ScorePercent"),
"Dinenoter" : player.GetVar("DineNoter"),
"Feedbackkommentarer" : player.GetVar("Feedbackkommentarer"),
"Feedbackslider1" : player.GetVar("Feedbackslider1"),
"Feedbackslider2" : player.GetVar("Feedbackslider2"),
"Feedbackslider3" : player.GetVar("Feedbackslider3"),
"Feedbackslider4" : player.GetVar("Feedbackslider4"),
"Feedbackslider5" : player.GetVar("Feedbackslider5"),
"Feedbackslider6" : player.GetVar("Feedbackslider6"),
"Feedbackslider7" : player.GetVar("Feedbackslider7"),
"Feedbackslider8" : player.GetVar("Feedbackslider8"),
"Feedbackslider9" : player.GetVar("Feedbackslider9"),
"Feedbackslider10" : player.GetVar("Feedbackslider10")

};
console.log(Dinenoter);
}

function Script3()
{
//DELAY SO JQUERY LIBRARY IS LOADED
setTimeout(function (){

//Export to Google
$.ajax({
url: WEB_APP_URL,
type: "POST",
data : storyline,
success: function(data)
{
console.log(data);
},
error: function(err) {
console.log('Error:', err);
}
});
return false;
}, 1000);
}

 

Dave Cox

That is an ajax reference to the variable storyline created in script2. Just a quick look at your code suggests that it is out of scope, but I wouldn't know for sure without some more work. If you still have whoever created this code, I would go back to them to debug the code. This is beyond what I would be able to help you with here.

Snorre Rubin

I don't think that is the case. The same script works perfectly when executed in html5 (I took a look in the console, and got not errors there), and used to work perfectly fine in flash, until yesterday.

This is the console log from flash: 

user.js:72 Uncaught ReferenceError: storyline is not defined(anonymous function) @ user.js:72

And this is from HTML5:

Object {result: "success", row: 4}
result
:
"success"
row
:
4
__proto__
:
Object
__defineGetter__
:
__defineGetter__()
__defineSetter__
:
__defineSetter__()
__lookupGetter__
:
__lookupGetter__()
__lookupSetter__
:
__lookupSetter__()
constructor
:
Object()
hasOwnProperty
:
hasOwnProperty()
isPrototypeOf
:
isPrototypeOf()
propertyIsEnumerable
:
propertyIsEnumerable()
toLocaleString
:
toLocaleString()
toString
:
toString()
valueOf
:
valueOf()
get __proto__
:
__proto__()
set __proto__
:
__proto__()

 

 

Snorre Rubin

Well several of these has changed:

Yesterday morning, Storyline asked me to update flash. I did. 

I have since updated the course files online, also. 

But, and of course there is a "but", I have also tested an older version of the course, and that doesn't work either. I have tried with various browsers, on more than one computer. 

Dave Cox

OK. 

One this we know that has changed, is Chrome has changed the security restrictions. Usually the prevents a course published for the web from running on the local file system. We don't know if it has an effect with your issue, but it is possible. I do know that all of my content that share information in this way still work with no issue. Did you try to run your course in IE? What are those results.

You also say that you've updated the course files. Do you still have an older version of the course files that were published before the problem began? If so, did you re-upload those to the server to see if they still work?

I'm afraid its going to take a bit of detective work to nail the problem down. Its still possible that there is a bug in your code that the browser previously ignored, but is now stopping the script. I've seen this more than once, so I wouldn't count that out completely.

The error above tends to point in that direction. The error is telling you that it is attempting to access the variable "storyline" which is not currently defined. If the variable is defined in the function, but not before the function runs, then the variable will not be available outside of the function. In other words, the variable is local to the function, where you need it to be global. You may need to declare this variable at the beginning of your javascript to make it global.

Dave Cox

Thanks Crystal. It always feels good to help fellow developers.

Javascript can be really useful, but can also be extremely frustrating when it doesn't work and dies silently, especially if you don't know how to troubleshoot it. And I fully understand Articulate's position to not support javascript. So I try to help when and where I can.

Snorre Rubin

Thank you SO much for your help!

I think I understand what you are saying, but I don't fully understand how to solve it. 

The functionality as it goes runs in 3 different scripts, or in other words, as the browser sees it, it 3 different functions. "storyline" is defined in the second function as a number of variables, and sent to google sheets in the third.

How then, do I keep the content of "storyline"?

Dave Cox

You may have three different scripts, but they all get loaded by the browser, and combined at run time. So effectively all scripts are in memory while the browser is running.

From what I saw, it appears that the variable storyline is declared within a function. That declaration makes its scope local to the function, and it is not available after the function finishes. If you declare it outside of the function, you can then reference the variable, from within the function, and from other functions. You can still set the individual parameters within the storyline variable in the same function as before. It is just the initial declaration that may need to move.

I'm really not too familiar with posting variables to google, but this thread might be able shed some light on what you are working on.

Snorre Rubin

Thank you again for your help. I tried to put a var storyline; between the two functions in the user.js file. This made the error disappear, but now the data shows up in the spreadsheet at "undefined". 

I have tried to play around with console.log but can't figure out hot to get it to show whether the "storyline" variable is defined properly.

Dave Cox

Hi Snorre,

OK, you are on the right path. This variable is not global, so it is no longer undefined.

The storyline variable is going to show as an object, since it contains several values. You may want to try moving all declarations for this variable outside of the function. The function can still set the values, but it should already exist before the function attempts to set them. (Sorry, I may have misdirected you before.) You can display individual values of the storyline variable but calling them individually, for example storyline.myvariable.

Snorre Rubin

I'm not sure I understand. The second funtion, the one where something seems to be going wrong right now, defines var player = GetPlayer(); , the storyline variable, and 

WEB_APP_URL = "https://script.google.com/macros/s/AKfycbyDRuE6iLvzn6C1qCtcRD5UCYEo1-HjgP033anXNsXICsyyDXbk/exec";

Should I move this whole block outside the function?

storyline =
{
"date" : new Date().toJSON().slice(0,10), //STORE DATE
"email" : player.GetVar("email"),
"12Spm1a" : player.GetVar("12Spm1a"),
.........
"Feedbackslider10" : player.GetVar("2Feedbackslider10")
};

Then I would also need to move var player = GetPlayer(); outside, right?

Dave Cox

The statement var player = GetPlayer(); defines the storyline player object where the storyling variable live. It must be declared to invoke statements like player.GetVar(); You can declare the player variable once outside of functions for all of your javascript code, or once in each function. 

The problem that I see with your scripts above, is it appears like script3 is calling on variables called by script2. Variables created in script2 are not available to script3, so javascript sends you an undefined error.

I'm not sure if you should move the block above outside of the function. Calling that function loads the variables from the player variables, and that may need to happen at the correct time, when the function is invoked. 

But you may need to change is some. When you declare the storyline variable, declare all of the items that are in that variable as well. For example:

var storyline = {
"date" : new Date(),
"email" : "",
"12Spm1a" : "", };

Then in the function script2 you can load the variables by using statements like this:

storyline.email = player.GetVar("email");

When you start your project with /story.html, your project attempts to load the storyline flash project, and only loads the HTML5 version of the project if the flash player is not available. When you start your project with /story_html5.html, the flash version of your project is not attempted, and you go directly to the html5 version of your project.

Dave Cox

Hi Snorre,

I'm so glad you got it to work. 

The best way to learn javascript (or any other type of coding) is to dive in, scratch your head, experiment and ask questions. I too have spent many hours trying to figure out code that I didn't understand and some head banging until I could get something to work. 

If you are interested in learning more about javascript, W3C schools is a really great resource. Best of all, it is totally free. I've been workiing with javascript for a very long time, and I still go there when I forget how to do something.