Howdy, Stranger!

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

Writing object variable (property) through JavaScript in SugarCube 2 fails

edited January 2017 in Help! with 2.0
Hey,

I'm using the latest SugarCube 2 and Twine 2 versions.
I ran into a read-only error when passing my object from SugarCube to JavaScript and try to write it's property.

Here's what I did:

Start Passage:
<<set $mydir = {
    "mydirectory" : "Get info from JavaScript and store current work directory here."
}>>>

<<findcwd $mydir>>

JavaScript:
macro.findcwd = {
    handler : function (place, macroName, params, parser) {
          var mydir = params[0];
         // I snagged this from stackoverflow to get the cwd
         var loc = window.location.pathname;
         var dir = loc.substring(0, loc.lastIndexOf('/'));

         // Twine starts to complain here about 
         // "mydirectory of  "Get info from JavaScript and store current work directory here.""
         // being a read-only property
         mydir.mydirectory = dir;
         }
}

So, what did I want to accomplish? I wanted to code a work around for my project to detect whether I am in development or published mode and specify where my GIF and JPG files are located accordingly, so Twine can find them when I'm using relative paths in HTML.
I've sort of accomplished this since I could get access the cwd and do my checks. Then I wondered if I could pass SugarCube2 objects per reference and whether I could store the gained information in a property (member).
Now, unfortunately this fails. It appears that SugarCube creates read-only properties for its objects.
Then I tried something like "mynumber" : 1 and increment it in JavaScript. That for some reason worked.
After that I tried adding writable : true to $mydir in SugarCube but the code still failed to write the property of the object.

I finally found a way to write the value in JavaScript by invoking a SugarCube macro:
new Wikifier(place, "CWD is indeed: <<set $mydir.mydirectory is \"" + dir + "\">>

I remember escaping a couple of quotations. But the code worked.

This begs the question:
What is going on? How, can I set my object property inside a macro without telling SugarCube to do it? Why does this work on numbers but fails on strings? Do I need to dig through SugarCube's macro implementation when problems like these occur?

Thank you for your explanation and help in advance
Br,
Disane

Comments

  • edited January 2017
    You are unlikely to have received the actual error you've claimed to for more reasons than I care to get into. It's fairly obvious that you made some mistake that you've managed to gloss over here, so I can't even begin to speculate as to what it was.

    As far as your object being read-only. No. SugarCube does not modify the property descriptors of your objects at all. If you actually saw an error to that effect, you obtained it doing something incorrectly—what that was, I haven't the foggiest.

    That you're trying to do this as a macro at all is odd. There's no need for that as far as I've understood your explanation. You could simply run the code once at start up. /shrug

    Regardless. Here are correct versions of what you were trying to do. Both will return an error if you pass them anything other than an object.


    If you intend to use the legacy Twine 1 vanilla story format macro API, then you need to spell it correctly—it's macros not macro. For example:
    macros.findcwd = {
    	handler : function (place, macroName, params, parser) {
    		var mydir = params[0];
    
    		if (typeof mydir !== 'object') {
    			return throwError(place, '<<findcwd>>: given value is not an object');
    		}
    
    		var loc = window.location.pathname;
    		mydir.mydirectory = loc.substring(0, loc.lastIndexOf('/'));
    	}
    };
    


    Or the same using SugarCube v2's native macro API:
    Macro.add('findcwd', {
    	handler : function () {
    		var mydir = this.args[0];
    
    		if (typeof mydir !== 'object') {
    			return this.error('given value is not an object');
    		}
    
    		var loc = window.location.pathname;
    		mydir.mydirectory = loc.substring(0, loc.lastIndexOf('/'));
    	}
    });
    
  • edited January 2017
    Well, that's nice to hear. I'll try it out once I get home.

    I see you like defensive programming and like to check what is actually passed through the arguments. I really like that. Too bad, I only started out with JS not a long time ago, but I'll pick it up fast. Regardless, It's nice to see good code practices.

    About running the code once: Yeah, true. There's no need for a macro in that case. I was merely experimenting. What would you say would be the best area to put this kind of code in? Right inside the start passage?

    About SugarCube 1.x and 2.x: Thanks, I took the code from a guy who made tutorials on YouTube (VegetarianZombie) from 2015. He was using Sugarcube 1.x indeed. I guess, I was using the legacy code in SugarCube 2.0, which could also be a cause of the problem. To be honest the documentation for SugarCube is just too dry for me and not enough for a beginner to start working on anything in my opinion. I had real issues figuring out what macros and passages were (and what they were made for), until I saw them in action in Zombie's videos. Now, the documentation is starting to make sense.

    The error does actually happen and reading your answer, I assume it must be my "user error" interfering. It will be a treat to find out why it was thrown at me. I'll let you know once I figured it out.

    Anyways, thank you for the help!
  • Well, I've found the problem: I was passing $mydir.mydirectory to findcwd. My bad...
Sign In or Register to comment.