Skip to content

Instantly share code, notes, and snippets.

@melanke
Created June 19, 2012 20:53
Show Gist options
  • Save melanke/2956493 to your computer and use it in GitHub Desktop.
Save melanke/2956493 to your computer and use it in GitHub Desktop.
MultiGetSet.JS - Quickly generate getters and setters for multiple attributes

MultiGetSet.JS 1.1.0

About

Quickly generate getters and setters for multiple attributes. Using the "Observable" plugin will work for the same purpose of WatchJS, but working on all browsers. The "Observable" plugin let you know everytime some object change its value.

##Generating default Getters and Setters

var MyClass = function(){
  var public = this;
  var private = {};
  var secret = {};

  public.aPublicAttr = "im am public";
  private.aPrivateAttr = "im private but will have a getter and setter";
  secret.aPrivateWithoutGetterOrSetter = "no one can access me!";

  MultiGetSet({
    public: public,
    private: private
  });
};

var myObj = new MyClass();
var thatPrivate = myObj.get("aPrivateAttr");
myObj.set("aPrivateAttr", thatPrivate+". works!");

alert(myObj.get("aPrivateAttr"));

Try out

##Generating observable setters and default getter

var MyClass = function(){
  var public = this;
  var private = {};
  var secret = {}

  public.aPublicAttr = "im am public";
  private.aPrivateAttr = "im private but will have a getter and setter";
  secret.aPrivateWithoutGetterOrSetter = "no one can access me!";

  MultiGetSet({
    public: public,
    private: private,
    handler: Observable
  });
};

var myObj = new MyClass();
var thatPrivate = myObj.get("aPrivateAttr");

myObj.listen("aPrivateAttr", function(opt){
   alert(JSON.stringify(opt));
});

myObj.set("aPrivateAttr", thatPrivate+". works!"); //will trigger the listener declared above​

Try out

##Generating custom getter and empty setter

var MyClass = function(){
  var public = this;
  var private = {};
  var secret = {}

  public.aPublicAttr = "im am public";
  private.aPrivateAttr = "im private but will have a getter and setter";
  secret.aPrivateWithoutGetterOrSetter = "no one can access me!";

  MultiGetSet({
    public: public,
    private: private,
    handler: {
        init: function(){},
        setter: function(){}, //i dont want a setter (if setter is null will be a default setter that works just link atr = new value
        getter: function(opt){ 
            return opt.private[opt.paramName] + " Hey you!";
        }
    }
  });
};

var myObj = new MyClass();
var thatPrivate = myObj.get("aPrivateAttr");alert(thatPrivate);

Try out

##Using the Add method for arrays

var MyClass = function(){
  var public = this;
  var private = {};
  var secret = {}

  public.aPublicAttr = "im am public";
  private.aPrivateAttr = ["old one"];
  secret.aPrivateWithoutGetterOrSetter = "no one can access me!";

  MultiGetSet({
    public: public,
    private: private,
    handler: Observable
  });
};

var myObj = new MyClass();
var thatPrivate = myObj.get("aPrivateAttr");

myObj.listen("aPrivateAttr", function(opt){
   alert(JSON.stringify(opt));
});

myObj.add("aPrivateAttr", "new one!"); //will trigger the listener declared above​​

Try out

var MultiGetSet = function(opt){
var getType = function(o) {
return ({}).toString.call(o).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
};
if(!opt.public || !opt.private)
return opt.public;
if(opt.handler && opt.handler.init)
opt.handler.init(opt);
if(!opt.handler || !opt.handler.setter){
opt.public.set = function(paramName, newValue){
opt.private[paramName] = newValue;
};
}else{
opt.public.set = function(paramName, newValue){
return opt.handler.setter({
public: opt.public,
private: opt.private,
paramName: paramName,
newValue: newValue,
caller: arguments.callee.caller
});
};
}
if(!opt.handler || !opt.handler.getter){
opt.public.get = function(paramName){
return opt.private[paramName];
};
}else{
opt.public.get = function(paramName){
return opt.handler.getter({
public: opt.public,
private: opt.private,
paramName: paramName,
caller: arguments.callee.caller
});
};
}
if(!opt.handler || !opt.handler.adder){
opt.public.add = function(paramName, newValue){
if(getType(opt.private[paramName])==="array")
opt.private[paramName].push(newValue);
};
}else{
opt.public.add = function(paramName, newValue){
if(getType(opt.private[paramName])==="array")
return opt.handler.adder({
public: opt.public,
private: opt.private,
paramName: paramName,
newValue: newValue,
caller: arguments.callee.caller
});
};
}
return opt.public;
};
var Observable = {
clone: function(o){
if(o == null || typeof(o) != 'object')
return o;
var temp = o.constructor(); // changed
for(var key in o)
temp[key] = Observable.clone(o[key]);
return temp;
},
init: function(opt){
opt.public.listeners = {};
opt.public.listen = function(paramName, callback){
if(Object.prototype.toString.call(paramName) === '[object Array]')
for(var p in paramName){
opt.public.listenOne(paramName[p], callback);
}
else
opt.public.listenOne(paramName, callback);
};
opt.public.listenOne = function(paramName, callback){
if(!opt.public.listeners[paramName])
opt.public.listeners[paramName] = [];
opt.public.listeners[paramName].push(callback);
};
},
setter: function(opt){
if(opt.private[opt.paramName] == opt.newValue)
return;
opt.oldValue = Observable.clone(opt.private[opt.paramName]);
opt.private[opt.paramName] = opt.newValue;
for(var listener in opt.public.listeners[opt.paramName]){
if(opt.caller != opt.public.listeners[opt.paramName][listener])
opt.public.listeners[opt.paramName][listener](opt);
}
},
adder: function(opt){
if(opt.private[opt.paramName] == opt.newValue || !opt.private[opt.paramName].push)
return;
opt.oldValue = Observable.clone(opt.private[opt.paramName]);
opt.private[opt.paramName].push(opt.newValue);
opt.newValue = opt.private[opt.paramName];
for(var listener in opt.public.listeners[opt.paramName]){
if(opt.caller != opt.public.listeners[opt.paramName][listener])
opt.public.listeners[opt.paramName][listener](opt);
}
}
};
@melanke
Copy link
Author

melanke commented Jun 20, 2012

issues for next versions:

  • "add" method for array attributes
  • option to do it recursively inside private objects

@melanke
Copy link
Author

melanke commented Jun 22, 2012

add method was included, but I`ve changed my mind about the recursively option.

Here is a way to do that:

var MyClass = function(){
  var public = this;
  var private = {};
  var secret = {}

  public.aPublicAttr = "im am public";
  private.aPrivateAttr = "im private but will have a getter and setter";
  secret.aPrivateWithoutGetterOrSetter = "no one can access me!";

//this way you will erase the public data of the "private" object and add the required getters and setters
private = MultiGetSet({
    public: {},
    private: private,
    handler: Observable
  });

  MultiGetSet({
    public: public,
    private: private,
    handler: Observable
  });
};

@mistic100
Copy link

both great functions !

I added two shortcuts to MultiGetSet for increment and decrement a variable as I use for a queue manager :

    opt.public.increment = function(paramName, add) {
      if (add == null) add = 1;
      opt.public.set(paramName, opt.public.get(paramName)+add);
    };

    opt.public.decrement = function(paramName, rem) {
      if (rem == null) rem = 1;
      opt.public.increment(paramName, -rem);
    };

@melanke
Copy link
Author

melanke commented Jul 30, 2012

@mistic100 great idea! This could be part of a plugin of Math operations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment