Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Defining and using utility functions in global scope

I'd like to define a javascript function in global context and reference it later from other functions. Unfortunately, doing so like this (SugarCube) doesn't work:
:: Image Utilities [script]
function getBackgroundImage (element) {
var url = $(element).css('background-image');
if (url == "" || url == "none") return url;
url = /^url\((['"]?)(.*)\1\)$/.exec(url);
url = url[2];//continue with only the filepath portion
var filename = url.substring(url.lastIndexOf('/', url.lastIndexOf('/') - 1) + 1);
filename = filename ? filename : "";
return filename;
}

:: PassageDone [nobr]
/% SugarCube: Runs once the passage has completely rendered. %/
<<script>>
var index = state.active.variables.index;
var passage = state.active.title;
var sectionName = state.active.variables.section;
if (!index.hasOwnProperty(passage)) { //if the passage isn't in the index, add it.
index[passage] = {};
index[passage].section = sectionName;
}
//update background image if necessary
var currentImage = getBackgroundImage(".img-anchor");
...
<</script>>
What I get is an error message each time the code in the PassageDone special passage fires, letting me know that the function getBackgroundImage() is undefined. Yet the script passage in which it is defined does fire at startup as it should, so I'm not sure why the function wouldn't be available.

What might be going on here? Is the code in either of these passages not running in global context, perhaps?

Comments

  • Javascript scope is really weird. As far as I know (without having done any digging into how it actually works) each HTML <script> tag and each [script]-tagged passage exist in a completely separate scope, so that their functions and variables just stop existing outside that specific passage. You have to explicitly say "export this function into the rest of the scope", and the way you do that is like this: change your first line there from
    function getBackgroundImage (element) {
    to
    window.getBackgroundImage = function (element) {
    , which binds that function to the window and makes it usable (as a normal function call; you don't have to do window.getBackgroundImage) anywhere else in your code.
  • Ah, I see. I didn't realize that <script> tags outside of the <head> weren't in global scope.

    Anyway, that fixed it--thanks!
  • Erik wrote:

    Ah, I see. I didn't realize that <script> tags outside of the <head> weren't in global scope.

    Anyway, that fixed it--thanks!
    Actually, they are - but Twine script passages are executed in the scope of the main() function in the engine.
Sign In or Register to comment.