1

I have a JavaScript object, and I need some of the properties to reference values of other properties. Namely, I have a button that I want to sit relative to the parent panels position at all times, this is what I tried:

var main_panel_obj = {
  id: 'mainPanel',
  component: 'Window',
  draggable: false,
  padding: 4,
  position: { x: 0, y: 0 },
  width: gW*.04,
  height: gH,
  layout: [1, 3],
  children: [
    {
      id: 'btnWater',
      component: 'Button',
      skin: 'bluebutton',
      position: { x: this.position.x, y: this.position.y+20 },  // x,y from line 6
      width: gW * 0.03,
      height: gH * 0.03
    }
  ]
};

How do I get the child button's position to refer to the parent's panel pos?

Kedkedders
  • 13
  • 2

2 Answers2

1

Either hard-code them again (since this is all one statement in the code anyway so they can't have changed):

position: { x: 0, y: 20 }

Or declare them first with variables and then use the variables:

var startX = 0;
var startY = 0;
var main_panel_obj = {
    //...
    position: { x: startX, y: startY },
    //...
    children: [
    {
        //...
        position: { x: startX, y: startY + 20 },
        //...
    }]
};

An object has no knowledge of another object which holds a reference to it. After all, what would happen if multiple objects held a reference to it?

David
  • 208,112
  • 36
  • 198
  • 279
  • makes sense, thank you! I searched google, and when I typed the question all the suggestions didn't have the answer either, but as soon as you ask, there's the duplicate. :D anyways, I read your answer and the others, and it makes sense now, thanks! I went with this: position: { x: function(){return this.position.x;}, y: function(){return this.position.y+20;}}, – Kedkedders Sep 01 '16 at 19:27
  • @Kedkedders: I don't necessarily agree that the linked duplicate really *is* a duplicate. That's asking about referencing members of the same object, whereas you're asking about referencing members of the containing object. Either way, glad I could help! – David Sep 01 '16 at 19:29
  • 1
    Thought I would mention that this only copies the value of the startX and startY when the object and its children are created. I would presume that you would want to retrieve the position of the children relative to the parent, even if the parent object is moved. Therefore I would user getter with a reference to the parent. – ArkTekniK Sep 02 '16 at 16:39
0

Have the children use getters for the position, which are functions that are instantiated after creation. Couple this with the children holding reference to their parent and you can calculate the relative position whenever you attempt to get the child's position.

The reason this works is that when you attempt to get the position on the child, a function is invoked and the live value can be obtained.

Edit: Adding code example;

var main_panel_obj = {
  id: 'mainPanel',
  component: 'Window',
  draggable: false,
  padding: 4,
  position: { x: 0, y: 0 },
  width: gW*.04,
  height: gH,
  layout: [1, 3],
  children: []
};

// Add children to the parent as needed
main_panel_obj.children.push({
  id: 'btnWater',
  parent: main_panel_obj, // this is the reference to the parent
  component: 'Button',
  skin: 'bluebutton',
  offsets: {x:0, y:20},
  get position(){ // property getter will always return latest relative position
    return {
      x: this.parent.position.x+this.offsets.x, 
      y: this.parent.position.y+this.offsets.y 
    };
  },
  width: gW * 0.03,
  height: gH * 0.03
});
// Example Usage
// Getters aren't used with function syntax and so won't break 
// compatibility with anything trying to read the position property
console.log(main_panel_obj.children[0].position); 
ArkTekniK
  • 196
  • 2
  • 11
  • Yeah I think I understand what you are saying. I need to study get/set a little more to fully get it, but it's a good path you've put me on, thanks! – Kedkedders Sep 01 '16 at 19:30
  • @Kedkedders I decided it was a good idea to demonstrate the code so added an example – ArkTekniK Sep 02 '16 at 16:52