var tm = {
  VERSION: "2.0.1",
  COPYRIGHT: "www.tom.com",
  fnEmpty: function() {},
  fnTrue: function() { return true; },
  fnFalse: function() { return false; }
};
function $(elem) {
  if (arguments.length > 1) {
    for (var i = 0, elems = [], length = arguments.length; i < length; i++)
      elems.push($(arguments[i]));
    return elems;
  }
  if (typeof elem == 'string') {
    return document.getElementById(elem);
  } else {
  	return elem;
  }
}
var $A = function(a) {
  var results = [];
  for (var i = 0, length = a.length; i < length; i++) {
    results.push(a[i]);
  }
  return results;
}
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}
tm.extend = function(dist) {
  var srcs = $A(arguments);
  srcs.splice(0, 1);
  for (var i = 0; i < srcs.length; i++) {
    var src = srcs[i];
    for (var p in src) {
      dist[p] = src[p];
    }
  }
  return dist;
}

tm.extend(Array.prototype, {
  contains: function(o) {
    for (var i = 0, len = this.length; i < len; i++) {
      if (this[i] == o) {
      	return true;
      }
    }
    return false;
  }
});

tm.extend(String.prototype, {
  trim: function() {
    return this.replace(/^\s+|\s+$/g, "");
  },
  startsWith: function(pf) {
  	return pf == "" ? true : this.indexOf(pf) == 0;
  },
  endsWith: function(sf) {
    return sf == "" ? true : this.lastIndexOf(sf) == this.length - String(sf).length;
  }
});

tm.Element = {
  getStyle: function(element, style) {
   var elem = typeof element == "string" ? $(element) : element;
    if (['float','cssFloat'].contains(style)) {
      style = (typeof elem.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
    }
    var value = elem.style[style];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(elem, null);
        value = css ? css[style] : null;
      } else if (elem.currentStyle) {
        value = elem.currentStyle[style];
      }
    }
    if((value == 'auto') && ['width','height'].contains(style) && (this.getStyle(elem, 'display') != 'none')) {
      value = elem['offset'+style.charAt(0).toUpperCase()+style.substring(1, style.length)] + 'px';
    }
    if (window.opera && ['left', 'top', 'right', 'bottom'].contains(style)) {
      if (this.getStyle(elem, 'position') == 'static') value = 'auto';
    }
    if(style == 'opacity') {
      if(value) return parseFloat(value);
      if(value = (elem.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
        if(value[1]) return parseFloat(value[1]) / 100;
      return 1.0;
    }
    return value == 'auto' ? null : value;
  },

  setStyle: function(element, style, value) {
    var elem = typeof element == "string" ? $(element) : element;
    if(style == 'opacity') {
      if (value == 1) {
        value = (/Gecko/.test(navigator.userAgent) &&
          !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
        if(/MSIE/.test(navigator.userAgent) && !window.opera)
          elem.style.filter = elem.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
      } else if(value === '') {
        if(/MSIE/.test(navigator.userAgent) && !window.opera)
          elem.style.filter = elem.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
      } else {
        if(value < 0.00001) value = 0;
        if(/MSIE/.test(navigator.userAgent) && !window.opera)
          elem.style.filter = elem.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
            'alpha(opacity='+value*100+')';
      }
    } else if(['float','cssFloat'].contains(name)) {
    	name = (typeof elem.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
    }
    elem.style[style] = value;
    return elem;
  },
  toggle: function(elem) {
    if (this.getStyle(elem, "display") == "none") {
      this.setStyle(elem, "display", "");    
    } else {
      this.setStyle(elem, "display", "none");  
    }
  },
  hide: function(elem) {
    $(elem).style.display = 'none';
    return elem;
  },
  show: function(elem) {
    $(elem).style.display = '';
    return elem;
  }
};
tm.Event = {
  addEvent: function(elem, name, fn, useCapture) {
    if (elem.addEventListener) {
      elem.addEventListener(name, fn, useCapture);
    } else if (elem.attachEvent) {
      elem.attachEvent('on' + name, fn);
    }
  },
  removeEvent: function(elem, name, fn, useCapture) {
    if (elem.removeEventListener) {
      elem.removeEventListener(name, fn, useCapture);
    } else if (elem.detachEvent) {
      elem.detachEvent('on' + name, fn);
    }
  },
  pointer: function(e) {
    return {x: this.pointerX(e), y: this.pointerY(e)};
  },
  pointerX: function(e) {
    return e.pageX || (e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
  },
  pointerY: function(e) {
    return e.pageY || (e.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
  },
  stop: function(e) {
    if (e.preventDefault) {
      e.preventDefault();
      e.stopPropagation();
    } else {
      e.returnValue = false;
      e.cancelBubble = true;
    }
  },
  isLeftClick: function(e) {
    return (((e.which) && (e.which == 1)) || ((e.button) && (e.button == 1)));
  },
  fixIE: function(e) {
  	e = e ? e : window.event;
  }
};
tm.Position = {
  prepare: function() {
    this.deltaX = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
    this.deltaY =  window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
  },
  realOffset: function(elem) {
    var x = 0, y = 0;
    do {
      x += elem.scrollLeft || 0; 
      y += elem.scrollTop  || 0;
      elem = elem.parentNode;
    } while (elem);
    return {left: x, top: y};
  },
  cumulativeOffset: function(elem) {
    var x = 0, y = 0;
    do {
      y += elem.offsetTop  || 0;
      x += elem.offsetLeft || 0;
      elem = elem.offsetParent;
    } while (elem);
    return {left: x, top: y};
  },
  cumulativeSize: function(elem) {
  	var w = elem.offsetWidth, h = elem.offsetHeight, bl = 0, br = 0, bt = 0, bb = 0;
  	bl = parseInt(tm.Element.getStyle(elem, "borderLeftWidth"));
  	br = parseInt(tm.Element.getStyle(elem, "borderRightWidth"));
  	bt = parseInt(tm.Element.getStyle(elem, "borderTopWidth"));
  	bb = parseInt(tm.Element.getStyle(elem, "borderBottomWidth"));
  	w += (isNaN(bl) ? 0 : bl) + (isNaN(br) ? 0 : br);
  	h += (isNaN(bt) ? 0 : bt) + (isNaN(bb) ? 0 : bb);
  	return {width: w, height: h};
  },
  within: function(elem, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(elem, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = this.cumulativeOffset(elem);
    return (y >= this.offset.top &&
            y <  this.offset.top + elem.offsetHeight &&
            x >= this.offset.left &&
            x <  this.offset.left + elem.offsetWidth);
  },
  withinIncludingScrolloffsets: function(elem, x, y) {
    var offsetcache = this.realOffset(elem);
    this.xcomp = x + offsetcache.left - this.deltaX;
    this.ycomp = y + offsetcache.top - this.deltaY;
    this.offset = this.cumulativeOffset(elem);
    return (this.ycomp >= this.offset.top &&
            this.ycomp <  this.offset.top + elem.offsetHeight &&
            this.xcomp >= this.offset.left &&
            this.xcomp <  this.offset.left + elem.offsetWidth);
  }, 
  bound: function(elem) {
  	var pos = this.cumulativeOffset(elem);
    return { x: pos.left, y: pos.top, w: elem.offsetWidth, h: elem.offsetHeight };
  },
  windowClientSize: function() {
    var w = 0, h = 0;
    if (window.innerHeight) {
      w = window.innerWidth;
      h = window.innerHeight;
    } else if (document.documentElement.clientHeight) {
      w = document.documentElement.clientWidth;
      h = document.documentElement.clientHeight;
    } else if (document.body.clientHeight) {
      w = document.body.clientWidth;
      h = document.body.clientHeight;
    } else {
      w = h = 0;
    }
	return {w: w, h: h, toString: function() { return "w=" + w + ",h=" + h}};
  },
  windowScrollBound: function() {
    var result = {x: 0, y: 0, w: 0, h: 0};
    if (window.scrollWidth) {
    	result = {x: window.scrollLeft, y: window.scrollTop, w: window.scrollWidth, h: window.scrollHeight};
    } else if (document.documentElement.scrollWidth) {
    	result = {x: document.documentElement.scrollLeft, y: document.documentElement.scrollTop, w: document.documentElement.scrollWidth, h: document.documentElement.scrollHeight};
    } else if (document.body.scrollWidth) {
    	result = {x: document.body.scrollLeft, y: document.body.scrollTop, w: document.body.scrollWidth, h: document.body.scrollHeight};
    }
    result.toString = function() {
      return this.x + "_" + this.y + "_" + this.w + "_" + this.h;
    }
	return result;
  },
  windowScrollPosition: function() {
    var result = {x: 0, y: 0};
    if (window.scrollWidth) {
    	result = {x: window.scrollLeft, y: window.scrollTop};
    } else if (document.documentElement.scrollWidth) {
    	result = {x: document.documentElement.scrollLeft, y: document.documentElement.scrollTop};
    } else if (document.body.scrollWidth) {
    	result = {x: document.body.scrollLeft, y: document.body.scrollTop};
    }
    result.toString = function() {
      return this.x + "_" + this.y;
    }
	return result;
  }
};
tm.Effect = {
  setOpacity: function(elem, val) {
    if (document.all) {
      elem.style.filter = "alpha(opacity=" + val * 100 + ")";
    } else {
      elem.style.opacity = val;
    }
  }
};

tm.Image = {
  resizeImage: function(img, mw, mh) {
    var w = img.offsetWidth;
    var h = img.offsetHeight;
    if (w / h > mw / mh) {
      if (w > mw) {
	    img.style.width = mw;
	  }
    } else {
      if (h > lh) {
        img.style.height = mh;
	  }
    }
  }
};
/**
 * package tm.util
 */
tm.util = {};
tm.util.List = Class.create();
tm.extend(tm.util.List.prototype, {
  initialize: function() {
    this._l = [];
  },
  add: function(o) { this._l.push(o); },
  addAll: function(l) {
  	var a = (l instanceof tm.util.List || l instanceof tm.util.Set) ? l._l : l;
  	for (var i = 0; i < a.length; i++) {
  	  this._l.push(a[i]);
  	}
  },
  clear: function() { this._l.length = 0; },
  contains: function(o) { return this.indexOf(o) != -1; },
  get: function(i) { return this._l[i]; },
  indexOf: function(o) {
    for(var i = 0; i < this._l.length; i++){
      if(this._l[i] === o) {
        return i;
      }
    }
    return -1;
  },
  isEmpty: function() { return this._l.length == 0; },
  remove: function(i) { return this._l.splice(i, 1); },
  removeObject: function(o) { 
    var i = this.indexOf(o);
    if (i != -1) {
      return this._l.splice(i, 1)[0]; 
    } else {
      return null;
    }
  },
  size: function() { return this._l.length; },
  toArray: function() { return [].concat(this._l); },
  dump: function() { return "[" + this._l.join(",") + "]"; },
  sort: function(fn) {
  	if (!this._l || this._l.length < 2) {
  	  return this;
  	}
  	if (fn) {
  	  this._l.sort(fn);
  	} else {
  	  this._l.sort();
  	}
  	return this;
  },
  filter: function(fnExp, fnCond) {
    return tm.util.Arrays.asList(tm.util.Arrays.filter(fnExp, this._l, fnCond));
  },
  each: function(fn) {
  	var l = this._l;
  	for (var i = 0, len = l.length; i < len; i++) {
  	  fn(l[i]);
  	}
  }
});
tm.util.Set = Class.create();
tm.extend(tm.util.Set.prototype, tm.util.List.prototype, {
  initialize: function() {
    this._l = [];
  },
  add: function(o) {
    if (this.indexOf(o) == -1) {
      this._l.push(o);
    }
  },
  addAll: function(s) {
  	var a = (s instanceof tm.util.List || s instanceof tm.util.Set) ? s._l : s;
    for (var i = 0; i < a.length; i++) {
      this.add(a[i]);
    }
  },
  filter: function(fnExp, fnCond) {
    return tm.util.Arrays.asSet(tm.util.Arrays.filter(fnExp, this._l, fnCond));
  }
});
tm.util.Map = Class.create();
tm.extend(tm.util.Map.prototype, {
  initialize: function() {
    this._m = {};
  },
  clear: function() { this._m = {}; },
  containsKey: function(k) { return this._m.hasOwnProperty("_" + k); },
  containsValue: function(v) {
    for (var k in this._m) {
      if (this._m["_" + k] === v) {
        return true;
      }
    }
    return false;
  },
  get: function(k) { return this._m["_" + k]; },
  isEmpty: function() {
    for (var k in this._m) {
      return false;
    }
    return true;
  },
  keySet: function() {
  	var set = new tm.util.Set();
    var m = this._m;
    for (var i in m) {
      set.add(i);
    }
    return set;
  },
  values: function() {
  	var a = [];
    var m = this._m;
    for (var i in m) {
      a.push(m[i]);
    }
    return tm.util.Arrays.asList(a);
  },
  put: function(k, v) { return this._m["_" + k] = v; },
  remove: function(k) {
    var v = this._m["_" + k];
    delete(this._m["_" + k]);
    return v;
  },
  size: function() {
    var c = 0;
    for (var i in this._m) {
      c++;
    }
    return c;
  },
  filter: function(fnExp, fnCond) {
    switch (typeof(fnExp)) {
      case "undefined":
        fnExp = function(k, v) { return {k: k, v: v} };
        break;
      case "function": 
        break;
      case "string":
        fnExp = new Function("k", "v", "return " + fnExp + ";");
        break;
    }
    switch (typeof(fnCond)) {
      case "undefined":
        fnCond = tm.fnTrue;
        break;
      case "function": 
        break;
      case "string":
        fnCond = new Function("k", "v", "return (" + fnCond + ");");
        break;
    }
    
	var rst = new tm.util.Map();
	var m = this._m;
	var v = null;
    var t = null;
    for (var k in m) {
      v = m[k];
      k = k.substring(1, k.length);
      if (fnCond(k, v)) {
      	t = fnExp(k, v);
        rst.put(t.k, t.v);
      }
    }
    return rst;
  },
  each: function(fnExp, fnCond) {
    switch (typeof(fnExp)) {
      case "undefined":
        fnExp = function(k, v) { return {k: k, v: v} };
        break;
      case "function": 
        break;
      case "string":
        fnExp = new Function("k", "v", "return " + fnExp + ";");
        break;
    }
    switch (typeof(fnCond)) {
      case "undefined":
        fnCond = tm.fnTrue;
        break;
      case "function": 
        break;
      case "string":
        fnCond = new Function("k", "v", "return (" + fnCond + ");");
        break;
    }
	var m = this._m;
	var v = null;
    for (var k in m) {
      v = m[k];
      k = k.substring(1, k.length);
      if (fnCond(k, v)) {
      	fnExp(k, v);
      }
    }
  }
});
tm.util.Queue = Class.create();
tm.extend(tm.util.Queue.prototype, {
  initialize: function() {
    this._q = [];
  },
  enqueue: function(o) {
    this._q.push(o);
  },
  dequeue: function() {
    return this._q.shift();
  },
  peek: function() {
    return this._q[0];
  },
  size: function() {
    return this._q.length;
  }
});

tm.util.ActiveObject = Class.create();
tm.extend(tm.util.ActiveObject.prototype, {
  initialize: function(period) {
  	this.period = period ? period : 100;
  	this.timer = null;
  	this.taskQueue = new tm.util.Queue();
  },
  start: function() {
  	var _this = this;
  	this.timer = setInterval(
  	  function() {
  	  	_this.execute();
  	  },
  	  this.period
  	)
  },
  stop: function() {
  	clearInterval(this.timer);
  },
  run: tm.fnEmpty,
  addTask: function(t) {
  	this.taskQueue.enqueue(t);
  }
});

tm.util.Arrays = {
  asList: function(a) {
    var l = new tm.util.List();
    l._l = [].concat(a);
    return l;
  },
  asSet: function(a) {
    var s = new tm.util.Set();
    for (var i = 0, len = a.length; i < len; i++) {
      s.add(a[i]);
    }
    return s;
  },
  asMap: function(a, asType) {
  	asType = asType ? asType : 0;
  	var m = new tm.util.Map();
  	for (var i = 0, len = a.length, v = null; i < len; i++) {
  	  v = a[i];
      switch (asType) {
        case 0:
          m.put(v[0], v[1]);
          break;
        case 1:
          m.put(v, a[++i]);
          break;
        case 2:
          m.put(v.k, v.v);
          break;
        default:
          break;
      }
  	}
  	return m;
  },
  filter: function(fnExp, arr, fnCond) {
    switch (typeof(fnExp)) {
      case "undefined":
        fnExp = function(o) { return o; };
        break;
      case "function": 
        break;
      case "string":
        fnExp = new Function("o", "return " + fnExp + ";");
        break;
    }
    switch (typeof(fnCond)) {
      case "undefined":
        fnCond = tm.fnTrue;
        break;
      case "function": 
        break;
      case "string":
        fnCond = new Function("o", "return (" + fnCond + ");");
        break;
    }
    var rst = [];
    var o = null;
    for (var i = 0, l = arr.length; i < l; i++) {
      o = arr[i];
      if (fnCond(o)) {
        rst.push(fnExp(o));
      }
    }
    return rst;
  }, 
  dump: function(a) {
    return a.join(",");
  }
};

