15
\$\begingroup\$

I have been trying to wrap my head around all the new options in ECMAscript 6 and to do this I tried to develop a simple setup which would allow me to place absolutely positioned <div>s on the page.

main.js:

import {Screen} from './objects/screen';
import {Position} from './objects/position';

var welcomeScreen = new Screen("Hello World");
welcomeScreen.title = "Hello World2";
welcomeScreen.position = new Position(100,100);
//Make sure the following does work if you have any advices, because there is a simple mistake which breaks this:
console.log(welcomeScreen.position.x);

var secondScreen = new Screen("Second screen", new Position(200,200));

objects/baseobject.js:

export class BaseObject{
    on(eventname,func){
        if(typeof this.listeners == "undefined"){
            this.listeners = {};
        }
        if(typeof this.listeners[eventname] == "undefined"){
            this.listeners[eventname] = [];
        }
        this.listeners[eventname].push(func);
        return this;
    }
    trigger(eventname){
        if(this.listeners && this.listeners[eventname]){
            for(let func of this.listeners[eventname]){
                func.call(this);
            }
        }
    }
}

objects/screen.js:

import {BaseObject} from './baseobject';
// private properties:
var pp = {
    position: Symbol(),
    title: Symbol()
};
export class Screen extends BaseObject{
    constructor(title,position = new Position(0,0)){
        this.element = document.createElement("div");
        this.element.classList.add("screen");
        this.title = title;
        this.position = position;
        document.body.appendChild(this.element);
    }
    reposition(){
        this.element.style.left = this.position.x + "px";
        this.element.style.top = this.position.y + "px";
    }
    set position(position){
        var that = this;
        this[pp.position] = position;
        this[pp.position].on("positionchange",function(){
            that.reposition();
        }).trigger("positionchange");
    }
    get position(){
        return this[pp.position];
    }
    set title(value){
        this[pp.title] = value;
        this.element.textContent = value;
    }
    get title(){
        return this[pp.title];
    }
}

objects/position.js:

import {BaseObject} from './baseobject';
// private properties:
var pp = {
    x: Symbol(),
    y: Symbol()
};
export class Position extends BaseObject{
    constructor(x,y){
        this[pp.x]=x;
        this[pp.y]=y;
    }
    set x(value){
        this[pp.x]=x;
        super.trigger("positionchange");
    }
    get x(){
        return this[pp.x];
    }
    set y(value){
        this[pp.y]=y;
        super.trigger("positionchange");
    }
    get y(){
        return this[pp.y];
    }
}

You can transpile ES6 to ES3 (I think it is 3) using (Google) Traceur.

Points of interest:

  • Are there nice ES6 language features I am forgetting?
  • Is there a nicer way to handle the 'set triggers' (-> private property construction)?
  • Should I be using modules? Combine classes into the same files? etc.
\$\endgroup\$
  • \$\begingroup\$ Traceur does not support private in class bodies.. github.com/google/traceur-compiler/issues/57 That's a bit of a let down. \$\endgroup\$ – konijn Mar 5 '14 at 16:26
  • \$\begingroup\$ Have been reading the spec now for the last half hour and for the life of me, I can't figure out how private properties are 'supposed' to work (regardless of Traceur). \$\endgroup\$ – David Mulder Mar 5 '14 at 18:38
  • \$\begingroup\$ I looked at wiki.ecmascript.org/doku.php?id=harmony:classes#class_body -> check out the constructor. \$\endgroup\$ – konijn Mar 5 '14 at 18:55
  • \$\begingroup\$ That one is old and superseded by wiki.ecmascript.org/… \$\endgroup\$ – David Mulder Mar 5 '14 at 19:01
  • \$\begingroup\$ And yeah, I would have loved it if they could have agreed on that one. I thought you were talking about the new Name() stuff which I can't figure out. \$\endgroup\$ – David Mulder Mar 5 '14 at 19:02
13
\$\begingroup\$

Most interesting,

  • In BaseObject, you should really have a constructor that builds this.listeners, it would make your code much cleaner afterwards
  • I am not sure why your listeners are not private in BaseObject ?
  • I am not sure what is more important to you, learn EC6 or position divs efficiently, if the latter is more important, than this code is massive overkill ;)

If you want to avoid having a constructor for BaseObject, then I would re-write on like this:

on(eventname,func){
    this.listeners = this.listeners || [];
    this.listeners[eventname] = this.listeners[eventname] || [];
    this.listeners[eventname].push(func);
    return this;
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ To point 1 I did this because this way a user doesn't need to call the super constructor on each and every object he constructs. To point 2, you are absolutely right, I forgot entirely. And lastly to point 3: It is to learn EC6 whilst making a mobile app framework slowly (this was just me trying to figure out the setup). \$\endgroup\$ – David Mulder Mar 5 '14 at 18:29
  • \$\begingroup\$ Great suggestion btw@on :D \$\endgroup\$ – David Mulder Mar 5 '14 at 19:44
8
\$\begingroup\$

So, going to 'answer' my own question here with a nice thing I discovered since then. Might expand my answer if I discover more stuff.

In ECMAscript 6 rather than

var that = this;
something.on("positionchange",function(){
     that.reposition();
});

You can do

something.on("positionchange",() => {
     this.reposition();
});

As the this scope doesn't change.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ It's exciting though? Already with the latest additions I have stopped using typical javascript libraries for most my projects and with ES6 I can get rid of a couple I occasionally use again :D \$\endgroup\$ – David Mulder Mar 6 '14 at 23:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.