1

I was a little confused about how to access the property className of a created Node object?

 var track = {
  mod: {
    el: document.body.appendChild(document.createElement('div')),
    el.className: 'w3-container w3-teal w3-hover-green'
  }
};

This, unfortunately, provides the error:

Uncaught SyntaxError: Unexpected token .

I am trying to simply create an object within an object and modify properties of the internal object. I searched around and did not find anything specific to this level of access as I need the actual property of the DOM element 'className' to be modified and not just an assigned property of className.

goetztyler
  • 33
  • 6
  • Possible duplicate of [Adding a custom variable as JSON attribute](http://stackoverflow.com/questions/40337412/adding-a-custom-variable-as-json-attribute) – Aᴍɪʀ Nov 01 '16 at 18:04
  • 1
    > I am trying to simply create an object within an object and modify properties of the internal object - not possible directly. But you can always modify the original object. – raina77ow Nov 01 '16 at 18:05
  • 1
    You can't access the object properties while the object is still being created. You'll have to do `track.mod.el.className = 'w3-container w3-teal w3-hover-green'` later. – JJJ Nov 01 '16 at 18:10
  • Create an IIFE to create an element, and set the needed properties, then return the newly-created element. Note, that `this` can't be used in the IIFE to refer `mod`. – Teemu Nov 01 '16 at 18:10
  • So if I wanted to create a genericized track object I would have to wrap a function around the object creation to assign values after creation? – goetztyler Nov 01 '16 at 18:11
  • @goetztyler in that case, I'd suggest having a function that creates the document nodes and doing `var track = { mod: createMyElement() } };` – VLAZ Nov 01 '16 at 18:18
  • @vlaz Okay, that actually seems like a cleaner solution. I guess coming from a OO background forces me to think object creation should be contained within the object only. Thanks for the help! – goetztyler Nov 01 '16 at 18:27
  • @goetztyler well, you have to remember that a plain object in JS is not really the same as an object in Java, for example. It's more akin to a map in java, and your code would be roughly similar to trying to do doing `new Map().put("mod", new Map().put("el", new DOMNode("div"); el.setClass("w3-container")))` Yes, all in one line. And yes, including the syntax error. Even in an OO environment you'd probably won't do all of this in a single place but will have the two (or more) distinct part handled differently - creation of the container and creation of the value. – VLAZ Nov 01 '16 at 20:26

3 Answers3

1

What you're trying to do there is pretty neat but sadly JavaScript doesn't have support for it out of the box.

This is one way you can still make it work though:

var track = {
  mod: {
    el: document.body.appendChild(document.createElement('div'))
  }
};

// Add the className property here
track.mod.el.className = 'w3-container w3-teal w3-hover-green';
user3254198
  • 763
  • 6
  • 23
0

Seems like just a syntax issue...wouldn't it be:

var track = {
  mod: {
    el: document.body.appendChild(document.createElement('div')),
    el: {
        className: 'w3-container w3-teal w3-hover-green'
    }
  }
};
Phillip Chan
  • 993
  • 7
  • 17
  • This would just override the assigned value of `mod.el`. – Teemu Nov 01 '16 at 18:14
  • 1
    That doesn't seem correct - this will create and append an element on line 3, then also add it as a reference to the `el` property but the very next line will overwrite that reference. – VLAZ Nov 01 '16 at 18:15
  • That'll override the `el` object getting rid of the div element. – user3254198 Nov 01 '16 at 18:15
0

You can use an Immediately Invoked Function Expression, like so:

 var track = {
  mod: {
    el: (function () {
      var el = document.body.appendChild(document.createElement('div'));
      el.className = 'w3-container w3-teal w3-hover-green';
      return el;
    }())
  }
};

This can be done only after body exists, ofcourse. Also, this will not refer to track or track.mod in the function.

Teemu
  • 22,918
  • 7
  • 53
  • 106
  • I agree you _could_ do that and it's a fairly clean solution, overall, however, it still seems like putting too much logic in once place. I don't see a good reason to have object creation _and_ DOM manipulation done at once. It may save around a line of code, but it seems better to have them separate. – VLAZ Nov 01 '16 at 18:20
  • In this situation I am trying to create a genericized track object that I can then modify later depending on what I need. Although it is a bit of convolution it does do what I need it to do without requiring me to create and modify the track object every time I need a generic track. – goetztyler Nov 01 '16 at 18:23