function get(p){ return document.getElementById(p); } // TODO: to del
function gt(p){ return document.getElementById(p); } // TODO: to del

// clone any object
function clone(o)
{
  if(!o || 'object'!==(typeof o))
    return o;

  var c='function'===(typeof o.pop)?[]:{};
  var p,v;
  for(p in o)
  {
    if(o.hasOwnProperty(p))
    {
      v=o[p];
      if(v && 'object'===(typeof v))
        c[p]=clone(v);
      else
        c[p]=v;
    }
  }
  return c;
}
//~

// message system
var msg={
  _data:{
    'main':{
      'CLOSE':'close',
      'FEEDBACK':'Feedback'
    }
  },
  _parse:function(code){
    var pCode=code.split('.',2);
    if(pCode.length<2)
      pCode.unshift('main');
    return pCode;
  },
  set:function(codeMass){
    for(k in codeMass){
      var pk_=this._parse(k);
      if(!$chk(this._data[pk_[0]]))
        this._data[pk_[0]]={};
      this._data[pk_[0]][pk_[1]]=codeMass[k];
    }
  },
  v:function(code){
    var pCode=this._parse(code);
    if($chk(this._data[pCode[0]]) && $chk(this._data[pCode[0]][pCode[1]]))
      return this._data[pCode[0]][pCode[1]];
    else
      return null;
  },
  w:function(code){
    var value=this.v(code);
    if($chk(value))
      value=value.substring(0,1).toUpperCase()+value.substring(1);
    return value;
  }
}
//~

// observer pattern
function Observer(){
  this.fns=[];
}
Observer.prototype={
  subscribe:function(fn){
    this.fns.push(fn);
  },
  unsubscribe:function(fn){
    this.fns=this.fns.filter(
      function(el){
        if(el!==fn){
          return el;
        }
      }
    );
  },
  fire:function(o,thisObj){
    var scope=thisObj||window;
    this.fns.forEach(
      function(el){
        el.call(scope,o);
      }
    );
  }
};
//~