
/*********************************************************/
/*      FORMAT DATE FUNCTION ADDED TO DATE CLASS         */
/*********************************************************/

function dateTextFormat(dateformat)
{
  self = this;
  self.format = dateformat;
  self.caseformat;
  self.mask = {
    'default':      "Y/m/d, G:i:s",
    sqldate:    "Y-m-d G:i:s",
    shortdate:      "m/d",
    mediumdate:     "Y/m/d",
    longdate:       "",
    fulldate:       "",
    shorttime:      "g:i a",
    mediumtime:     "G:i:s",
    longtime:       "g:i:s a",
    shortdatetime: "y/m/d, g:i a",
    mediumdatetime: "F j, Y, g:i a"
  };

  if(self.format == null || self.format == '')
  {
    self.format = self.mask['default'];
  }
  else
  {
    self.caseformat = self.format.toString();
    self.caseformat = self.caseformat.trim();
    if(self.caseformat == null || self.caseformat == '')
      self.format = self.mask['default'];
    else
    {
      self.caseformat = self.caseformat.toLowerCase();
      if(self.mask[self.caseformat])
        self.format = self.mask[self.caseformat];
    }
  }
  self.returnStr = '';
  self.replace = {
	shortMonths: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
	longMonths: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
	shortDays: ['Dom', 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab'],
	longDays: ['Domingo', 'Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado'],

	// dia
  d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
  D: function() { return Date.replaceChar.shortDays[this.getDay()]; },
  j: function() { return this.getDate(); },
  l: function() { return Date.replaceChar.longDays[this.getDay()]; },
  N: function() { return this.getDay() + 1; },
  S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 3 && this.getDate() != 13 ? 'rd' : 'th'))); },
  w: function() { return this.getDay(); },
  z: function() { return "\'z\' No soportado"; },  //  El día del año (comenzando en 0)	0 a 365
                                                    // var prevdate = new Date();
  // semana
  W: function() { return "\'W\' No soportado"; },  // Número de la semana del año ISO-8601, las semanas comienzan en Lunes Ejemplo: 42 (la 42va semana del año)
  // mes
  F: function() { return Date.replaceChar.longMonths[this.getMonth()]; },
  m: function() { return (this.getMonth() < 9 ? '0' : '') + (this.getMonth() + 1); },
  M: function() { return Date.replaceChar.shortMonths[this.getMonth()]; },
  n: function() { return this.getMonth() + 1; },
  t: function() { return "\'t\' No soportado"; },
  // año
  L: function() { return "\'L\' No soportado"; },
  o: function() { return "\'o\' No soportado"; },
  Y: function() { return this.getFullYear(); },
  y: function() { return ('' + this.getFullYear()).substr(2); },
  // hora
  a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
  A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
  B: function() { return "\'B\' No soportado"; },
  g: function() { return this.getHours() == 0 ? 12 : (this.getHours() > 12 ? this.getHours() - 12 : this.getHours()); },
  G: function() { return this.getHours(); },
  h: function() { return (this.getHours() < 10 || (12 < this.getHours() < 22) ? '0' : '') + (this.getHours() < 10 ? this.getHours() + 1 : this.getHours() - 12); },
  H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
  i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
  s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },
  // zonahoraria
  e: function() { return "\'e\' No soportado"; },
  I: function() { return "\'I\' No soportado"; },
  O: function() { return (this.getTimezoneOffset() < 0 ? '-' : '+') + (this.getTimezoneOffset() / 60 < 10 ? '0' : '') + (this.getTimezoneOffset() / 60) + '00'; },
  T: function() { return "\'T\' No soportado"; },
  Z: function() { return this.getTimezoneOffset() * 60; },
  // fecha y hora completa
  c: function() { return "\'c\' No soportado"; },
  r: function() { return this.toString(); },
  U: function() { return this.getTime() / 1000; }
};
  for (var i = 0; i < self.format.length; i++)
  {
    var curChar = self.format.charAt(i);
		if (self.replace[curChar])
			self.returnStr += self.replace[curChar].call(self);
		else
			self.returnStr += curChar;
	}
	self.format = dateTextFormat;
	return self.returnStr;
}
Date.prototype.format = dateTextFormat;

function prettyDate( time ){
	var date = new Date((time || "").replace(/-/g,"/").replace(/[TZ]/g," ")),
		diff = (((new Date()).getTime() - date.getTime()) / 1000),
		day_diff = Math.floor(diff / 86400);
			
	if ( isNaN(day_diff) || day_diff < 0 )
  {
    var aux = new Date(time);
    diff = (((new Date()).getTime() - aux.getTime()) / 1000);
		day_diff = Math.floor(diff / 86400);
  }
  else if ( day_diff >= 31)
  {
    return "Hace más de un mes";
  }
	return day_diff == 0 && (
			diff < 60 && "Justo ahora" ||
			diff < 120 && "Hace un minuto" ||
			diff < 3600 && "Hace " + Math.floor( diff / 60 ) + " minutos" ||
			diff < 7200 && "Hace una hora" ||
			diff < 86400 && "Hace " + Math.floor( diff / 3600 ) + " horas") ||
      day_diff == 1 && "Ayer" ||
      day_diff < 7 && "Hace " + day_diff + " dias" ||
      day_diff < 31 && "Hace " + Math.ceil( day_diff / 7 ) + " semanas";
}

function createElement( type, attr, cont, html )
{
  try{
    var ne = document.createElement( type );
    if (!ne)  {  return false;  }
    for (var a in attr)
    {
      if (typeof attr[ a ] === "object")  {  for (var sa in attr[ a ])  {  ne[ a ][ sa ] = attr[ a ][ sa ];  }  }
      else  {  ne[ a ] = attr[ a ];  }
    }
    if ( (typeof cont === "string" || typeof cont === "number" ) && !html)  {  ne.appendChild( document.createTextNode( cont + "" ) );  }
    else if ( typeof cont  === "string" && html ) {  ne.innerHTML = cont + "";  }
    else if ( typeof  cont === "object" )  {  ne.appendChild( cont );  }
    return ne;
  }catch ( error )
  {
    throw new Error( "createElement() ::: " + error.message );
    return false;
  }
}

function copyValue( val )
{
  return val;
}

function Interface( name, methods )
{
  /* validator */
  if(arguments.length != 2)
  {
    throw new Error("Interface constructor called with " + arguments.length + "arguments, but expected exactly 2.");
  }
  var self = this;
  /**
  * constructor
  **/
  this.name = name;
  this.methods = [];
  for(var i = 0, len = methods.length; i < len; i++)
  {
    if(typeof methods[i] !== 'string')
    {
      throw new Error("Interface constructor expects method names to be " + "passed in as a string.");
    }
    this.methods.push(methods[i]);
  }
}
Interface.ensureImplements = function(object)  {
  if ( arguments.length < 2 )
  {
    throw new Error( "Function Interface.ensureImplements called with " + arguments.length  + "arguments, but expected at least 2." );
  }
  for ( var i = 1, len = arguments.length; i < len; i++ )
  {
    var interface = arguments[i];
    if ( interface.constructor !== Interface )
    {
      throw new Error("Function Interface.ensureImplements expects arguments" + "two and above to be instances of Interface.");
    }
    for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++)
    {
      var method = interface.methods[j];
      if(!object[method] || typeof object[method] !== 'function')
      {
        throw new Error( "Function Interface.ensureImplements: object " + "does not implement the :: " + interface.name + " ::  interface. Method [" + method + "()] was not found." );
      }
    }
  }
}

var IDB = new Interface( "IDB", [ "createTable", "updateTable", "deleteTable", "insertRecord", "deleteRecord", "updateRecord" ] );
var ITable = new Interface( "ITable", [ "insert", "remove", "update", "setLink", "removeLink", "getLinks", "getRecord"] );

var PTable = (function(){
  return function( tablename, records ){
  var self = this;
  function insert( key, rec )
  {
    //console.log("haciendo insert");
    if (key && valueIs( key, "number") && typeof rec === "object")
    {
      self.records[key] = rec;
    }
    else if ( !key && rec && typeof rec === "object" && !isArray( rec ) )
    {
      for ( var i in rec )
      { 
        self.records[i] = rec[i];
      }
    }
    else
    {
      throw new Error("PTable :: insert :: Error al hacer la incercion en la tabla ||" + self.tablename + "|| \n" );
      return false;
    }
    return true;
  }
  this.insert = insert;

  function remove()
  {
    delete self.records[ key ];
    return true;
  }
  this.remove = remove;

  function update( key, record )
  {
    self.records[ key ] = record;
    return true;
  }
  this.update = update;

  function setLink( name, link )
  {
    self.__links[ name ] = link;
    return true;
  }
  this.setLink = setLink;

  function removeLink( name )
  {
    delete self.__links[ name ];
    return true;
  }
  this.removeLink = removeLink;
  
  function getRecord( key )
  {
    if ( key )
    { 
      return self.records[key];
    }
    else
    { 
      return self.records;
    }
  }
  this.getRecord = getRecord;

  function getLinks(){  return self.__links;  }
  this.getLinks = getLinks;

  /*  constructor  */
  this.records = records || {};
  this.__links = {};
  this.tablename = tablename;
  Interface.ensureImplements( self, ITable );
  };
})();

var PDB = (function(){
  var Super = this;
  Super._DB_ = {};
  return function( dbname ){
    var self = this;
    if ( Super._DB_[ dbname ] )  {  return Super._DB_[ dbname ];  }
    function createTable( tablename , records )
    {
      if (!tablename && typeof tablename !== "string"){  return false;  }
      if (Super._DB_[ self.dbname ][ tablename ])
      {
        throw new Error( "PDB :: insertTable :: la tabla ya ha sido insertada =( " );
        return false;
        return Super._DB_[ self.dbname ][ tablename ];
      }
      else
      {
        return Super._DB_[ self.dbname ][ tablename ] = new PTable( tablename, records );
      }
    }
    this.createTable = createTable;

    function updateTable( name, table )
    {
      if (Super._DB_[ self.dbname ][ name ])
      {
        Super._DB_[ self.dbname ][ name ] = table;
        /* refresh all references */
        executeFunction( self.dbname, null, "refresh" );
        return true;
      }
      else
      {
        throw new Error( "PDB :: updateTable :: la tabla [" + name + "] no existe =( " );
        return false;
      }
    }
    this.updateTable = updateTable;

    function deleteTable( name )
    {
      /* delte all references */
      executeFunction( name, null, "stop" );
      /* finish */
      delete Super._DB_[ self.dbname ][ name ];
    }
    this.deleteTable = deleteTable;

    function insertRecord( tablename, key, record )
    {
      if (!Super._DB_[ tablename ]){  throw new Error( "PDB :: insertRecord :: la tabla no existe =( " );  }
      Super._DB_[ self.dbname ][ name ]
    }
    this.insertRecord = insertRecord;

    function deleteRecord( tablename, key )
    {

    }
    this.deleteRecord = deleteRecord;

    function updateRecord( table, record ){}
    this.updateRecord = updateRecord;

    function executeFunction( tn, rn, fn )
    {
      var tablename = copyValue( tn );
      var recordname = copyValue( rn );
      var functionname = copyValue( fn );
      if ( !Super._DB_[ tablename ] ){  throw new Error( "PDB :: executeFunction :: la tabla [" + tablename + "] no existe =( " );  }
      for ( var objname in Super._DB_[ tablename ].__link )
      {
        if ( typeof Super._DB_[ tablename ].__link[ objname ][ functionname ] === "function" )
        {
          Super._DB_[ tablename ].__link[ objname ][ functionname ]();
        }
      }
    }
    /**
    * constructor
    **/
    /* interface */
    Interface.ensureImplements( self, IDB );
    this.dbname = copyValue( dbname );
    Super._DB_[ this.dbname ] = {};
    /**
    * Super._DB_ = [table1, table2, ...];
    *   table1 = {record1, record2, ..., __tableinfo};
    *   __tableinfo = {ref, };
    **/
    return this;
  };
})();

var IPTwitter =  new Interface( "IPTwitter", ["start", "stop", "doSearch", "createBackground", "doRequest"]);
var PTwitter = (function(){
  var Super = this;
  return function( idnodetwitts, usage, options ){
    /* validators */
    var self = this;
    if ( !$( idnodetwitts ) )
    {
      throw new Error( "PTwitter ::: No existe en nodo donde se mostraran los resultados .... =( " );
    }

    function start( opt )
    {
      try{
      /*self.debug = document.createElement("div");
      self.debug.style.display = "none";
      window.onload = function(){ document.body.appendChild( self.debug ); };*/
      self.setOptions(opt);
      self.createBackground();
      self.createLoading( options.loadMSG, options.imgName ); // show loading message
      self.createURL();
      self.doRequest(1);
      //if(timer!=undefined&&!running) self.temporizador();
      }catch(err){
      //self.debug.innerHTML += ( err.message + "<br />" );
      //console.log(err.message);
      }
    }
    this.start = start;
    
    function doSearch()
    {
    }
    this.doSearch = doSearch;
    function createBackground()
    {
      self.parent.className = self.css + "";
      self.ele.main = createElement("div",{ "className" : "main" } );
      self.parent.appendChild(self.ele.main);
      self.ele.twits = createElement("div",{ "className" : "messages" } );
      self.parent.appendChild(self.ele.twits);
      self.ele.footer = createElement("div",{ "className" : "footer" } );
      self.parent.appendChild(self.ele.footer);
    }
    this.createBackground = createBackground;
    
    function stop()
    {
    }
    this.stop = stop;
    function createSearchForm()
    {
      var SF = self.ele.searchform = createElement( "form", { "id" : self.id + "_searchForm" } ); // alias SF
      self.ele.SF_fieldset = createElement( "fieldset", { "id" : self.id });
      self.ele.SF_label = createElement( "label", { "id" : SF.id + "_label" }  );
      self.ele.SF_field = createElement( "input", { "type": "text", "id" : SF.id + "_input" } );
      self.ele.SF_submit = createElement( "input", { "type": "submit", "id" : SF.id + "_submit" } );
    }
    this.createSearchForm = createSearchForm;
    
    function createURL()
    {
      var url = "";
      var param = "";
      var users = options.users;
      var languaje = ( options.lang.length > 0 ) ? ( "&lang=" + options.lang ) : ""; 
      url = apiSEARCH + "";
      if ( users && typeof users === "string" )
      {
        users += "";
        var nousers = users.search(/,/);
        if( nousers > 0 )
        {
          users = users.replace(/,/g,"+from%3A");
        }
        users = "&ors=from%3A" + users;
      }
      else
      {
        users = "";
      }
      if (options.param && typeof options.param === "string" )
      {
        param = self.validatetofind( options.param );
      }
      url += (param + users + languaje);
      url += "&rpp=" + options.numMSG;
      //console.log(url + " ::: " + param + "->" + users);
      self.url = url + "";
      return url + "";
    }
    this.createURL = createURL;
    
    function setOptions( opt )
    {
    
      if ( !opt || typeof opt !== "object" )
      {
        throw new Error("no hay datos suficientes.");
        return false;
      }
      options.param = opt.searchObject || null;
      options.users = opt.username || null;
      options.timer = opt.live;
      options.lang = opt.lang ? opt.lang : "";
      options.contDiv = opt.placeHolder ? opt.placeHolder : options.containerDiv;
      options.loadMSG = opt.loadMSG ? opt.loadMSG : options.loadMSG;
      options.gifName = opt.imgName ? opt.imgName : options.imgName;
      options.numMSG = opt.numMSG ? opt.numMSG : options.numMSG;
      options.readMore = opt.readMore ? opt.readMore: options.readMore;
      options.fromID = opt.nameUser ? opt.nameUser: options.nameUser;
      options.filterWords = opt.filter;
      options.openLink = opt.openExternalLinks ? "target='_blank'":"";
      options.showreadmore = opt.showreadmore || false;
      options.showavatar = opt.showavatar || false;
      options.showtime = opt.showtime || false;
    }
    this.setOptions = setOptions;

    function validatetofind( text )
    { 
      var regExpHash =  /[\#]/gi;
      var regExpArroba =  /[\@]/gi;
      var regExpWhite =  /[\ ]/gi;
      var regExpSimbolA =  /[\?]/gi;
      var regExpComa =  /[\,]/gi;
      text = text.replace(regExpHash, "%23");
      text = text.replace(regExpArroba, "%40");
      text = text.replace(regExpWhite, "+");
      text = text.replace(regExpSimbolA, "%3F");
      text = text.replace(regExpComa, "%2C");
      return text + "";
    }
    this.validatetofind = validatetofind;
    
		function update()
    {
			self.doRequest(2);		
			if(timer!=undefined) this.temporizador();
		}
    this.update = update;
    
		function createLoading( msg, src )
    {
      var ele = null;
      if ( msg === "<img>")
      {
        ele = createElement("img", { "id" : "loaging_image", "src" : src + "" });
      }
      else
      {
        ele = document.createTextNode( msg + "" );
      }
      self.ele.twits.appendChild( ele );
		}
    this.createLoading = createLoading;
    
		function delRegister()
    {
			// remove the oldest entry on the tweets list
			if ( msgNb >= numMSG )
      {
				$(".twittLI").each(
					function(o,elemLI){
						if(o>=numMSG) $(this).hide("slow");													  
					}
				);
			}	
		}
    
		function doRequest(e) // conectaTwitter
    {
			// query the twitter api and create the tweets list
			jQuery.ajax({
				url: self.url,
				type: 'GET',
				dataType: 'jsonp',
				timeout: 1000,
				error: self.errorRequest,
				success: self.response
			});
		}
    this.doRequest = doRequest; // conectaTwitter
    
    function errorRequest()
    {
    
    }
    this.errorRequest = errorRequest;
    
    function response( json )
    {
    try{
      var res = json.results;
      var ul = createElement("ul");
      self.ele.twits.innerHTML = "";
      self.ele.twits.appendChild(ul);
      for (var i in res )
      {
        if (!res[i].text)
        {
          continue;
        }
        var text = res[i].text || "";
        var fechita = prettyDate( res[i].created_at + "" );
        var link =  "http://twitter.com/"+res[i].from_user+"/status/"+res[i].id;
        text = self.filter( text );
        var content = "";
        if ( options.showavatar )
        {
          content += "<a href='http://www.twitter.com/" + res[i].from_user + "'><img src='" + res[i].profile_image_url + "' alt='" + res[i].from_user + "' class='avatar'/></a>";
        }
        content += self.textFormat(text);
        if ( options.showtime )
        {
          content += "<br /><br /><span class='time'>" + fechita + "</span>";
        }
        if ( options.showreadmore )
        {
          content += "<a href='" + link + "' class='readmore' " + options.openLink + ">" + options.readMore + "</a>";
        }
        var li = createElement("li", null, content, true);
        ul.appendChild(li);
      }
    }catch(err){
     /*self.debug.innerHTML += ( ":::" + err.message + " ### " + err.description + "<br />" );
     self.debug.innerHTML += ( ":::->>" + json.results + "<br />" );
     self.debug.innerHTML += ( ":::->>" + options + "<br />" );*/
     //alert( err.message + " ### " + err.description );
     //console.log(err.message);
    }
      return;
    }
    this.response = response;
    
		function filter(s)
    {
			if(filterWords){
				searchWords = filterWords.split(",");				
				if(searchWords.length>0)
        {
					cleanHTML=s;
          for (var i = 0; i < searchWords.length; i++ )
          {
            var item = searchWords[i];
						var sW = item.split("->").length>0 ? item.split("->")[0] : item;
						var rW = item.split("->").length>0 ? item.split("->")[1] : "";
            regExp = eval('/'+sW+'/gi');
            cleanHTML = cleanHTML.replace(regExp, rW);
          }
				} else cleanHTML = s;			
				return cleanHTML;
			} else return s;
		}
    this.filter = filter;
    
		function textFormat(texto)
    {
			//make links
			var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
			texto = texto.replace(exp,"<a href='$1' class='extLink' " + options.openLink + ">$1</a>"); 
			var exp = /[\@]+([A-Za-z0-9-_]+)/ig;
			texto = texto.replace(exp,"<a href='http://twitter.com/$1' class='profileLink' " + options.openLink + ">@$1</a>"); 
			var exp = /[\#]+([A-Za-z0-9-_]+)/ig;
			texto = texto.replace(exp,"<a href='http://twitter.com/search?q=$1' class='hashLink' " + options.openLink + ">#$1</a>");
			// make it bold
			if( mode === "searchWord" && options.param && typeof options.param === "string" )
      {
				tempParam = options.param.replace(/&ors=/,"");
				arrParam = tempParam.split("+");
        for (var i in arrParam )
        {
          if ( arrParam[i] && typeof arrParam[i] === "string" )
          {
            var find = arrParam[i];
            regExp = eval( '/' + find + '/gi' );
            newString = ' <strong style="color: red;">' + arrParam[i] + '</strong> ';
            texto = texto.replace(regExp, newString);
          }
        }
			}
			return texto;
		}
    this.textFormat = textFormat;
    
		function temporizador()
    {
			// live mode timer
			running = true;
			/*aTim = timer.split("-");
			if(aTim[0]=="live" && aTim[1].length>0){
				tempo = aTim[1] * 1000;
				setTimeout("self.update()",tempo);
			}*/
		}
    this.temporizador = temporizador;

    /* Extras Functions */
    function _addEM( ev, elem, fun )
    {
      on(ev, elem, fun, false);
      self.eventManager.push({event: ev, el : elem,  fn : fun});
      return;
    }
    this._addEM = _addEM;

    function _stopEM()
    {
      for ( var i = 0; i < self.eventManager.length; i++ )
      {
        if (typeof self.eventManager[i] === "object" && self.eventManager[i].ev)
        {
          off(self.eventManager[i].event, self.eventManager[i].el, self.eventManager[i].fn, false);
          self.eventManager.remove(i);
        }
      }
      return;
    }
    this._stopEM = _stopEM;
    /* interface */
    Interface.ensureImplements( self, IPTwitter );

    /*  Constructor */
	
		// some global vars
		var param,time,lang,contDiv,loadMSG,gifName,readMore,fromID,ultID,filterWords;
		var running=false;
    
		// Twitter API Urls
		var apiUSER = "http://search.twitter.com/search.json?q=from%3A";
		var apiSEARCH = "http://search.twitter.com/search.json?q=";
    var options = options || {};
		options.numMSG = 20; //set the number of messages to be show
		options.loadMSG = "Cargando mensajes..."; // Loading message, if you want to show an image, fill it with "image/gif" and go to the next variable to set which image you want to use on
		options.imgName = "/pics/loader.gif"; // Loading image, to enable it, go to the loadMSG var above and change it to "image/gif"
		options.readMore = "Leelo en Twitter"; // read more message to be show after the tweet content
		options.nameUser = "image"; // insert "image" to show avatar of "text" to show the name of the user that sent the tweet
		options.live = "live-20"; //optional, disabled by default, the number after "live-" indicates the time in seconds to wait before request the Twitter API for updates, I do not recommend to use less than 60 seconds.
    options.lang = "";
    options.users = options.username || null;
    options.showreadmore = true;
    options.showavatar = true;
    options.showtime = true;
    var mode = "searchWord";
    
    var DB = new PDB( "db_twitter" );

    this.parentid = idnodetwitts; // //Set a place holder ELEMENT which will receive the list of tweets, preferece DIV
    this.id = idnodetwitts + "_PTwitter";
    this.parent = $( this.parentid );
    this.ele = {"main" : null, "form" : null, "twits" :  null , "footer" : null};
    this.url = "#";
   
    
    /* this css couldbe changed only pass the names of the new classes like are instanced here */
    this.css = options.css || "twitter_msg";
    /* event manager controller now */
    this.eventManager = new Array();
    
    return self;
  };
})();

