0

Good day, first I would like to tell that I am not proud to post a whole source code. I couldn't isolate the problem in a smaller chunk.

Here is a snapshot of the file:

getRoomById : function( areaId, roomId ) {
    if ( this.hAreas.get( areaId ) !== null && this.hAreas.get( areaId )[ roomId ] !== undefined )
    {
        //I can get here...
        //alert( uneval( this.hAreas.get( areaId ) ) );
        // returns: ({'000001':{areaId:"000001", roomId:"000001", Informations:{Name:"Room 1"}}, '000002':{areaId:"000001", roomId:"000002", Informations:{Name:"Room 2"}}, '000003':{areaId:"000001", roomId:"000003", Informations:{Name:"Room 3"}}})

        //alert( roomId );
        // returns: 000003

        return this.hAreas.get( areaId )[ roomId ];
        // returns: undefined
    }
},

and the whole file is there: http://jsfiddle.net/JSWCu/2/

The problem: I have a method which tests the arguments against a JS.Hash containing an object. That if hopefully returns true but once inside, I can't get (either alert or return) the object inside that JS.Hash (an undefined is returned).

Thank you! your help is greatly appreciated. I would also appreciate tips to avoid such errors.

Edit: here is the whole codes. Sorry It's really big. It's just starting to get complex and I couldn't (for now) isolate the problems to a smaller piece of codes:

<html>
    <head>
        <style type="text/css">

        </style>
        <script type="text/javascript">
            JSCLASS_PATH = 'http://www.poc.ca/cybrix/src';
            function appendConsole( input ) {
                document.getElementById( "console" ).innerHTML += input + "<br />";
            }
        </script>
        <script type="text/javascript" src="http://www.poc.ca/cybrix/src/loader-browser.js"></script>
        <script type="text/javascript">
            JS.require('JS.Hash', 'JS.Observable', function() {
                var AreaLists = {
                    "000001" : { "Name" : "Test Area", "Loaded" : false },
                };

                var World = new JS.Class({
                    hAreas : new JS.Hash([]),

                    getAreas : function( areaId ) {
                        if ( ! this.hAreas.get( areaId ) && AreaLists[ areaId ] !== undefined )
                        {
                            //TODO: Load from external sources

                            this.hAreas.put( areaId, {
                                "000001" : new Room( areaId, "000001", { "Name" : "Room 1" } ),
                                "000002" : new Room( areaId, "000002", { "Name" : "Room 2" } ),
                                "000003" : new Room( areaId, "000003", { "Name" : "Room 3" } ),
                            });

                            AreaLists[ areaId ].Loaded = true;

                            appendConsole( "Areas #" + areaId + " : " + AreaLists[ areaId ].Name + " Created" );
                        }

                        return this.hAreas.get( areaId );
                    },
                    getRoomById : function( areaId, roomId ) {
                        if ( this.hAreas.get( areaId ) !== null && this.hAreas.get( areaId )[ roomId ] !== undefined )
                        {
                            //I can get here...
                            //alert( uneval( this.hAreas.get( areaId ) ) );
                            // returns: ({'000001':{areaId:"000001", roomId:"000001", Informations:{Name:"Room 1"}}, '000002':{areaId:"000001", roomId:"000002", Informations:{Name:"Room 2"}}, '000003':{areaId:"000001", roomId:"000003", Informations:{Name:"Room 3"}}})

                            //alert( roomId );
                            // returns: 000003

                            return this.hAreas.get( areaId )[ roomId ];
                            // returns: undefined
                        }
                    },
                    reloadAreas : function( areaId ) {
                        //Triggered by Tick only if there is no players
                    },

                    addCharacter : function( areaId, roomId, character ) {
                        if ( this.hAreas.get( areaId ) && this.hAreas.get( areaId )[ roomId ] )
                        {
                            this.hAreas.get( areaId )[ roomId ].addCharacter( character );
                        }
                    },
                    removeCharacter : function( areaId, roomId, character ) {
                        return this.hAreas.get( areaId )[ roomId ].removeCharacter( character );
                    }
                });

                var Room = new JS.Class({
                    hDoors : new JS.Hash([]),
                    hExits : new JS.Hash([]),
                    hBodies : new JS.Hash([]),
                    hObjects : new JS.Hash([]),

                    initialize : function( areaId, roomId, Informations ) {
                        this.areaId = areaId;
                        this.roomId = roomId;
                        this.Informations = Informations;

                        //TODO: Load from external sources
                        if ( areaId == "000001" && roomId == "000003" )
                        {
                            this.hObjects.put("000001", new Objects("000001", { "Name" : "A table", "Type" : 0 }) );
                            this.hObjects.put("000002", new Objects("000002", { "Name" : "A water fountain", "Type" : 1 }) );
                        }

                        appendConsole( "Room: #" + this.areaId + "-" + this.roomId + " : " + this.Informations.Name + " Created" );
                    },

                    addCharacter : function( character ) {
                        this.hBodies.put( character.characterId , character );

                        character.onArriveRoom( this );

                        if ( ! character.Informations.Stealth )
                        {
                            //TODO: Broadcast Informations to others

                            appendConsole( character.Informations.Name + " has arrived to " + this.Informations.Name );
                        }
                    },
                    removeCharacter : function( character ) {
                        var characterId = ( typeof character == "object" ) ? character.characterId : character,
                            currentCharacter = this.hBodies.remove( characterId );

                        character.onLeaveRoom( this );

                        if ( currentCharacter !== null )
                        {
                            //TODO: Broadcast Informations to others

                            appendConsole( character.Informations.Name + " has left " + this.Informations.Name );

                            return currentCharacter;
                        }

                        return undefined;
                    },

                    onArrive : function() {

                    },

                    onLeave : function() {

                    },

                    getObjects : function( objectId, hash ) {
                        if ( this.hObjects.get( objectId ) )
                        {
                            var currentObjects = this.hObjects.get( objectId );

                            if ( hash )
                            {
                                return new JS.Hash([
                                    currentObjects.objectId, currentObjects 
                                ]);
                            }

                            return currentObjects;
                        }

                        return this.hObjects;
                    },

                    toString : function( characterId ) {

                    }
                });

                var Objects = new JS.Class({
                    objectsTypes : {
                        0 : "lies",
                        1 : "stands"
                    },

                    initialize : function( objectId, Informations ) {
                        this.objectId = objectId;
                        this.Informations = Informations;

                        appendConsole( "Object: #" + this.objectId + " : " + this.Informations.Name + " Created" );
                    },

                    toString : function() {
                        return this.Informations.Name + " " + this.objectsTypes[ this.Informations.Type ] + " here.";
                    }
                });

                var Character = new JS.Class({
                    Pet : undefined,

                    initialize : function( characterId, Informations ) {
                        this.characterId = characterId;
                        this.Informations = Informations;
                        this.areaId = this.Informations.Zone.split("-")[ 0 ];
                        this.roomId = this.Informations.Zone.split("-")[ 1 ];

                        if ( this.Informations.Pet !== undefined )
                        {
                            //TODO: Load from external sources

                            if ( this.Informations.Pet === "000001" )
                            {
                                this.Pet = new Pet( "000001", { "Name" : "Molten Panther", "Zone" : this.areaId + "-" + this.roomId, "Stealth" : false } );

                                World.addCharacter( this.Pet.getArea() , this.Pet.getRoom() , this.Pet );

                                var petRoom = World.getRoomById( this.Pet.getArea() , this.Pet.getRoom() );

                                alert( petRoom ); // = undefined ????
                            }
                        }

                        appendConsole( "Character: #" + this.characterId + " : " + this.Informations.Name + " Created" );
                    },

                    onArriveRoom : function ( currentRoom ) {

                    },
                    onLeaveRoom : function( currentRoom ) {

                    },

                    onArrive : function() {

                    },
                    onLeave : function() {

                    },

                    getRoom : function() {
                        return this.roomId + "";
                    },
                    getArea : function() {
                        return this.areaId + "";
                    },
                    getInformations : function() {
                        return this.Informations;
                    },
                    hasPet : function() {
                        return ( typeof this.Pet == "object" );
                    },
                    getPet : function() {
                        return this.Pet;
                    },

                    equals : function( character ) {
                        return ( character instanceof this.klass ) && character.Informations.Name === this.Informations.Name;
                    }
                });

                var Pet = new JS.Class( Character, {

                    initialize : function( characterId, Informations ) {
                        this.callSuper();

                        appendConsole( "Pet: " + this.Informations.Name + " Created" );
                    }
                });

                //Tests
                var World = new World();
                var AreaOne = World.getAreas( "000001" );

                var Cybrix = new Character( "000001", { "Name" : "Cybrix", "Zone" : "000001-000003", "Stealth" : false, "Pet" : "000001" } );

                if ( World.getAreas( Cybrix.getArea() ) )
                {
                    World.addCharacter( Cybrix.getArea() , Cybrix.getRoom() , Cybrix );

                    //Cybrix = World.removeCharacter( Cybrix.getArea() , Cybrix.getRoom() , Cybrix );
                }
            });
        </script>
    </head>
    <body style="margin: 0; padding: 0;">
        <div id="console" style="display: block; background-color: #000; height: 100%; color: #FFF; font-family: Lucida Console;"></div>
    </body>
</html>
Cybrix
  • 3,248
  • 5
  • 42
  • 61
  • 3
    And yet, despite it being massive, please post the *entire* question here on StackOverflow. Live links are a great *adjunct* to a question, but always post the relevant code *in the question* as well. Two reasons. 1. People shouldn't have to follow a link to help you. 2. StackOverflow is meant to be a resource not just for you now, but for others having a similar issue in the future. External links can get moved, modified, deleted, etc. By making sure the relevant code is in the question, we ensure that the question (and its answers) remain useful for a reasonable period of time. – T.J. Crowder Jun 17 '11 at 23:03
  • 3
    Oh: And do keep trying to create a (much) smaller, self-contained example. :-) – T.J. Crowder Jun 17 '11 at 23:04
  • 1
    @T.J.: Cannot agree more with the second comment ;) – Felix Kling Jun 17 '11 at 23:05
  • I totally agree with you guys, and I'm sorry, I'll try to isolate the problem some more. About the small chunk of codes, I believe I've provided enough informations on the problem : how could the `if` passes when once you return the value it is undefined ? – Cybrix Jun 17 '11 at 23:09
  • Have you tried inspecting the objects? What does `alert(JSON.stringify(this.hAreas.get(areaId)));` result in? – Paul V Jun 17 '11 at 23:09
  • @T.J.: Yay! Also, as an addendum on #1, the OP will be LESS likely to get responses. That... mouse... click... is... sooo... HARD... – Jared Farrish Jun 17 '11 at 23:09
  • @Paul V - I suggest Firebug of Chrome console. :) – Jared Farrish Jun 17 '11 at 23:11
  • I've created a much smaller version, two objects and 4 methods in total and the problem is fixed. What would be my mistake? Did I loop through objects references and they got destroyed ? – Cybrix Jun 17 '11 at 23:43
  • @Paul V, here is the returned value using `JSON.stringify` : `{"000001":{"areaId":"000001","roomId":"000001","Informations":{"Name":"Room 1"}},"000002":{"areaId":"000001","roomId":"000002","Informations":{"Name":"Room 2"}},"000003":{"areaId":"000001","roomId":"000003","Informations":{"Name":"Room 3"}}}` – Cybrix Jun 17 '11 at 23:52
  • @Cybrix - I've posted an answer below which I think resolves the issue. World.getRoomById returns a ROOM object. You've overrode the Room class' toString() method and are not returning anything so it returns undefined by default. That's why when alerting(petRoom) you get undefined. – WesleyJohnson Jun 17 '11 at 23:56
  • @Jared - hah! Of course! `alert(JSON.stringify)` is easier to describe though :). – Paul V Jun 18 '11 at 15:00

3 Answers3

1

Answering your question in the comments

how could the if passes when once you return the value it is undefined

You're using the comparison this.hAreas.get( areaId )[ roomId ] !== undefined. What that will do is test that the value on the left isn't strictly equal to that specific undefined instance. If you're dealing with multiple windows/frames, it's possible to have different undefined instances (because each window has its own undefined). If that sounds really weird, it's because it is.

To guard against that, you usually see that comparison written as:

if (typeof this.hAreas.get( areaId )[ roomId ] !== "undefined")

...which tests that the type of the operand is "undefined" (note the quotes), which is reliable cross-window.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

I've been playing around with your example on jsfiddle and I'm running into some rather odd behavior. In your Character class' initialization method you're calling the World.getRoomById() method in question and assigning it to a variable called petRoom.

As your code stands, when you alert(petRoom) you do get undefined. However, if you alert(petRoom.roomId) you get 000003 as intended so my guess is it's not really returning a true undefined. If you log petRoom to chrome's console it classifies it as a constructor and not an object. I'm not really sure what's going on there, but I thought it'd give some extra direction. I'll keep playing.....

UPDATE: The issue is that you're overriding the Room class' toString() method and not returning anything. By default, alerting something cast it to a string using the object's toString() method and because you've overridden that and aren't returning a value you get undefined.

var Room = new JS.class({
        ...
        snip
        ....
        toString: function(characterId) {

        }
});
WesleyJohnson
  • 1,538
  • 1
  • 16
  • 30
  • Hmm indeed. I can also access petRoom as if it was the object itself. I'm confused right now... – Cybrix Jun 17 '11 at 23:55
  • You just need to remove the overriden toString() method in your Room class or have it return something. World.getRoomById is returning your object fine, it's not returning undefined. You're just seeing undefined when you ALERT because alert uses the object's toString() method, which you've overriden. – WesleyJohnson Jun 17 '11 at 23:58
0

Try this instead:

typeof this.hAreas.get( areaId )[ roomId ] !== "undefined"
Town
  • 14,706
  • 3
  • 48
  • 72