if (typeof(tm) == "undefined") {
  throw new Error("tm.app Require tm");
}
tm.blog = {};
tm.blog.app = {};
tm.blog.app.blog = {};

tm.blog.ModuleUtils = {
  CLASS_NAME_MAP: {
  	//以下是内建模块
    1: "userinfo",
    2: "calendar",
    3: "article",
    4: "comment",
    5: "catalog",
    6: "link",
    7: "counter",
    8: "musicbox",
    9: "clock",
    10: "search",
	11: 'link',
	//以下是扩展模块
	129: 'visitor',
	130: 'recentUpdate',    //    最近更新列表（recentUpdate）
	131: 'attention',    //我的关注（attention）
	132: 'voiceBlogger'    //语音博友（voiceBlogger）
  },
  getJsModuleId: function(id) {
    return "mod_" + id;
  },
  getJsModuleTitleId: function(id) {
    return "mod_title_" + id;
  },
  getJsModuleContentId: function(id) {
    return "mod_content_" + id;
  },
  getClassName: function(type) {
    return this.CLASS_NAME_MAP[type];
  },
  getFullClassName: function(type) {
  	return "mod " + this.getClassName(type);
  },
  revealModuleId: function(s) {
  	return ("" + s).replace(/^.+?(\d+)$/gi, "$1");
  }
};

var LAYOUT_ID_NAME_MAP = tm.util.Arrays.asMap([
    1, "layout_1_1",
    2, "layout_2_01",
    3, "layout_2_10",
    4, "layout_3_001",
    5, "layout_3_010",
    6, "layout_3_100"
  ], 1);

var THEME_ID_NAME_MAP = tm.util.Arrays.asMap([
    1, "default",
    2, "bw1",
    3, "bw2",
    4, "bw3",
    5, "bw4",
    6, "bw5",
    7, "bw6",
    8, "bw7",
    9, "bw8",
    10, "bw9",
    11, "bw10",
    12, "bw11",
    13, "bw12",
    14, "bw13",
    15, "bw14",
    16, "bw15",
    17, "bw16",
    18, "bw17",
    19, "bw18",
    20, "bw19",
    21, "bw20",
    22, "bw21",
    23, "bw22",
    24, "bw23",
    26, "white",
    27, "black",
	28, "bw29",
	29, "bw30",
	30, "tom01",
	31, "tom04",
	32, "tom05",
	33, "tom03",
	34, "tom02",
	35, "tom06",
	36, "tom07",
	37, "tom08",
	38, "tom09",
	39, "tom10",
	40, "tom11",
	41, "tom12",
	42, "tom13",
	43, "tom14",
	44, "tom15",
	45, "tom16",
	46, "tom17",
	47, "tom18",
	48, "tom19",
	49, "tom20",
	50, "tom21",
	51, "tom22",
	52, "tom23",
	53, "tom24",
	54, "tom25",
	55, "tom26",
	56, "tom27",
	57, "tom28",
	58, "tom29",
	59, "tom30"
  ], 1);
/**
 * package blog
 * class Module
 * extends tm.dnd.Draggable
 */
tm.blog.Module = Class.create();
tm.extend(tm.blog.Module.prototype, tm.dnd.Draggable.prototype, {
  initialize: function(id, params) {
	params = params ? params : {};
    var fields = {
      id: id,
      mid: 0,
      type: 0,
      name: "", 
      column: 1, 
      index: 1, 
      isLoad: 1,
      columnObject: null,
      content: null
    };
    tm.extend(fields, params);
    //Call super.
    tm.dnd.Draggable.prototype.initialize.apply(this, [id, fields]);
    
    this.content = this.content ? $(this.content) : $(tm.blog.ModuleUtils.getJsModuleContentId(this.mid));
  },
  setColumnObject: function(col) {
  	this.columnObject = col;
  },
  getColumnObject: function() {
  	return this.columnObject;
  },
  resizeContentWidth: function() {
  	this.columnObject = this.droppable || this.columnObject;
  	var width = window.MODULE_CONTENT_WIDTH[LABELS.getCurrent().formatID][this.columnObject.data.column];
  	this.content.style.width = width + "px";
  },
  onDragEnd: function(e) {
  	this.resizeContentWidth();
  	try {
  	  app.saveModulePosFrame.show();
  	} catch (e) {
	  alert(e);
  	}
  }
});

tm.blog.ModuleWithoutDrag = Class.create();
tm.extend(tm.blog.ModuleWithoutDrag.prototype, {
  initialize: function(id, params) {
	params = params ? params : {};
    var fields = {
      id: id,
      mid: 0,
      type: 0,
      name: "", 
      column: 1, 
      index: 1, 
      isLoad: 1,
      columnObject: null,
      content: null
    };
    tm.extend(this, fields, params);
    
    this.content = this.content ? $(this.content) : $(tm.blog.ModuleUtils.getJsModuleContentId(this.mid));
  },
  setColumnObject: function(col) {
  	this.columnObject = col;
  },
  getColumnObject: function() {
  	return this.columnObject;
  },
  resizeContentWidth: function() {
  	this.columnObject = this.droppable || this.columnObject;
  	var width = window.MODULE_CONTENT_WIDTH[LABELS.getCurrent().formatID][this.columnObject.data.column];
  	this.content.style.width = width + "px";
  },
  onDragEnd: function(e) {
  	this.resizeContentWidth();
  }
});

/**
 * package tm.blog
 * class Column
 * extends tm.dnd.Droppable
 */
tm.blog.Column = Class.create();
tm.extend(tm.blog.Column.prototype, tm.dnd.Droppable.prototype, {
  initialize: function(id, params) {
	params = params ? params : {};
    var fields = {
      data: {
        name: "column1",
        column: 1
      }
    };
    tm.extend(fields, params);
    tm.dnd.Droppable.prototype.initialize.apply(this, [id, fields]);
    tm.dnd.Droppables.add(this);
  },
  addModule: function(m) {
  	m.setColumnObject(this);
  	this.addDraggable(m);
  },
  addModuleObject: function(m) {
  	m.setColumnObject(this);
  	this.draggables.add(m);
  },
  getModules: function() {
  	return this.draggables;
  },
  removeModule: function(m) {
  	m.setColumnObject(null);
  	this.removeDraggable(m);
  },
  removeAllModule: function() {
  	var _this = this;
  	this.getModules().filter().each(function(o) {
  	  _this.removeModule(o);
  	});
  },
  hasModule: function(m) {
  	return this.hasDraggable(m);
  }
});

/**
 * package tm.blog.app
 * class Blog
 * desc: app for blog page
 */
tm.blog.app.Blog = Class.create();
tm.extend(tm.blog.app.Blog.prototype, {
  initialize: function(bloggerId) {
    var fields = {
      ids: {
      	pageSetupBtn: "pageSetup",
      	pageSetupMenuId: "pageSetupMenu",
      	formatSetupBtn: "formatSetup",
      	themeSetupBtn: "themeSetup",
      	moduleSetupBtn: "moduleSetup",
      	
      	layoutWindow: "dragLayout",
      	themeWindow: "dragTheme",
      	moduleSetupWindow: "dragMod",
      	
      	layoutLinkId: "linkLayout"
      }
    }
    tm.extend(this, fields);
  },
  bindSetup: function() {
  	
  	var layoutWin = new tm.blog.app.blog.LayoutSetupWindow(this.ids.layoutWindow, {blogInfo: BLOG_INFO, columns: COLUMNS, labels: LABELS, isModal: true});
  	layoutWin.bind();
  	
  	var themeWin = new tm.blog.app.blog.ThemeSetupWindow(this.ids.themeWindow, {blogInfo: BLOG_INFO, totalCount: 15});
  	themeWin.bind();
  	
  	var moduleWin = new tm.blog.app.blog.ModuleSetupWindow(this.ids.moduleSetupWindow, {blogInfo: BLOG_INFO, canDrag: false, loadedModuleMap: MODULES, labels: LABELS, columns: COLUMNS, isModal: true});
  	moduleWin.bind();
  	
  	layoutWin.moduleWin = moduleWin;
  	
  	var saveModulePosFrame = new tm.blog.app.SaveModulePosFrame("saveModulePosFrame", {});
  	saveModulePosFrame.bind();
  	saveModulePosFrame.moduleWin = moduleWin;
  	this.saveModulePosFrame = saveModulePosFrame;
  	
  	
  	var psMenu = new tm.widget.Menu(this.ids.pageSetupMenuId);
    var fsMi = new tm.widget.MenuItem(this.ids.formatSetupBtn, {onClick: function(e) {
      e = e ? e : window.event;
      layoutWin.show();
      layoutWin.setCenter();
      tm.Event.stop(e)
      return false;
    }});
    var tsMi = new tm.widget.MenuItem(this.ids.themeSetupBtn, {onClick: function(e) {
      e = e ? e : window.event;
      themeWin.show();
      themeWin.setCenter();
      tm.Event.stop(e)
      return false;
    }});
    var msMi = new tm.widget.MenuItem(this.ids.moduleSetupBtn, {onClick: function(e) {
      e = e ? e : window.event;
      moduleWin.show();
      moduleWin.setCenter();
      tm.Event.stop(e)
      return false;
    }});
    psMenu.addMenuItem(fsMi);
    psMenu.addMenuItem(tsMi);
    psMenu.addMenuItem(msMi);
    $(this.ids.pageSetupBtn).onclick = function(e) {
      e = e ? e : window.event;
      psMenu.showOnPointer(e);
      tm.Event.stop(e);
      return false;
    }
  }
});

/**
 * package tm.blog.app.blog
 * class LayoutSetupWindow
 * extends tm.widget.Window
 */
tm.blog.app.blog.LayoutSetupWindow = Class.create();
tm.extend(tm.blog.app.blog.LayoutSetupWindow.prototype, tm.widget.Window.prototype, {
  initialize: function(id, params) {
    params = params ? params : {};
    var fields = {
      handle: "dragLayout_title",
      btnClose: "dragLayout_close",
      btnMinimum: "dragLayout_min",
      btnOk: "dragLayout_ok",
      linkLayout: "linkLayout",
      btnLayouts: "dragLayout_layouts",
      blogInfo: null,
      currentLayoutId: 0,
      lastLayoutId: 0,
      columns: null,
      labels: null,
      lastColumns: tm.util.Arrays.asMap([[1, new tm.util.Set()], [2, new tm.util.Set()], [3, new tm.util.Set()]]),
      moduleWin: null
    };
    tm.extend(fields, params);
    //Call super.
    tm.widget.Window.prototype.initialize.apply(this, [id, fields]);
    this.btnOk = $(this.btnOk);
    this.btnLayouts = $(this.btnLayouts);
  },
  bind: function() {
    var _w = this;
    //ok
    this.btnOk.onclick = function(e) {
  	  e = e ? e : window.event;
  	  // 更新lastLayoutId和LABELS.getCurrent().formatID
  	  _w.lastLayoutId = _w.currentLayoutId;
  	  _w.labels.getCurrent().formatID = _w.currentLayoutId;
  	  _w.hide();
  	  
  	  //保存模块设置
	  var saveResult = _w.moduleWin.saveModules();
	  var saveModResult = saveResult.json.code == 0;
  	  
  	  //保存layout设置
      var url = "/doSetupBlog.php";
  	  var method = "GET";
  	  var options = {text: true, json: true};
  	  var vars = new XHConn.Parameter()
  	    .append("opt", "setupLayout")
  	    .append("bloggerID", _w.blogInfo.bloggerID)
  	    .append("labelID", _w.labels.getCurrent().id)
  	    .append("formatID", _w.currentLayoutId)
  	    .append("rdm", new Date().getTime())
  	    .stringValue();
  	  var result = new XHConn().connectSync(url, method, vars, options);
  	  if (result.json.code == 0 && saveModResult) {
		tm.widget.Information("保存成功", 1500);
  	  } else {
		tm.widget.Alert("保存失败" + result.text, "ERROR");
  	  }
  	  tm.Event.stop(e);
  	  return false;
  	}
  	
  	var los = this.btnLayouts.getElementsByTagName("A");
    for (var i = 0; i < los.length; i++) {
      //切换layout
      los[i].onclick = function(e) {
  	    e = e ? e : window.event;
  	    var cssId = this.id.replace(/^btnLayout_/, "");
  	    var cssName = LAYOUT_ID_NAME_MAP.get(cssId);
  	    $(_w.linkLayout).href = "/themes/" + _w.blogInfo.getThemeName() + "/layout/" + cssName + ".css?rdm=" + new Date().getTime();
  	    _w.currentLayoutId = cssId;
  	    _w.labels.getCurrent().formatID = _w.currentLayoutId;
  	    
  	    if (_w.lastLayoutId >=4 && _w.currentLayoutId < 4) {
		  for (var i = 0, len = _w.columns.get(3).draggables.size(); i < len; i++) {
		  	var m = _w.columns.get(3).draggables.get(0);
		  	_w.columns.get(3).removeModule(m);
		  	_w.columns.get(1).addModule(m);
		  }
  	    } 
        if (_w.lastLayoutId >=2 && _w.currentLayoutId < 2) {
		  for (var i = 0, len = _w.columns.get(2).draggables.size(); i < len; i++) {
		  	var m = _w.columns.get(2).draggables.get(0);
		  	_w.columns.get(2).removeModule(m);
		  	_w.columns.get(1).addModule(m);
		  }
  	    }
  	    
  	    var largeCol = null;
  	    switch (cssId) {
  	      case "1":
  	      case "3":
  	      case "6":
  	        largeCol = _w.columns.get(1);
  	        break;
  	      case "2":
  	      case "5":
  	        largeCol = _w.columns.get(2);
  	        break;
  	      case "4":
  	        largeCol = _w.columns.get(3);
  	        break;
  	    }
  	    var lc = largeCol.getModules().filter("o", "o.element.className.endsWith('article')");
  	    if (lc.size() == 0) {
  	      var ma = null;
  	      if (_w.columns.get(1) != largeCol) {
  	      	var lc1 = _w.columns.get(1).getModules().filter("o", "o.element.className.endsWith('article')");
  	      	if (lc1.size() == 1) {
  	      	  ma = lc1.get(0);
  	      	}
  	      }
  	      if (_w.columns.get(2) != largeCol) {
  	      	var lc2 = _w.columns.get(2).getModules().filter("o", "o.element.className.endsWith('article')");
  	      	if (lc2.size() == 1) {
  	      	  ma = lc2.get(0);
  	      	}
  	      }
  	      if (_w.columns.get(3) != largeCol) {
  	      	var lc3 = _w.columns.get(3).getModules().filter("o", "o.element.className.endsWith('article')");
  	      	if (lc3.size() == 1) {
  	      	  ma = lc3.get(0);
  	      	}
  	      }
  	      ma.getColumnObject().removeModule(ma);
  	      largeCol.addModule(ma);
  	    }
  	    
  	    _w.resizeAllModuleWidth();
  	    
  	    tm.Event.stop(e);
  	    return false;
      }
    }
  },
  show: function() {
  	tm.widget.Window.prototype.show.apply(this);
  	
  	//模块在column中排序
  	var _this = this;
  	this.lastColumns.each(function(k, v) {
  	  v.clear();
  	  v.addAll(_this.columns.get(k).getModules().sort(tm.blog.app.blog.ModuleSetupWindow.fnModuleSort));
  	});

  	this.lastLayoutId = LABELS.getCurrent().formatID;
  	this.currentLayoutId = this.lastLayoutId;
  },
  onClose: function(e) {
  	//恢复当前formatID
  	LABELS.getCurrent().formatID = this.lastLayoutId;
  	if (this.currentLayoutId != this.lastLayoutId) {
  	  $(this.linkLayout).href = "/themes/" + this.blogInfo.getThemeName() + "/layout/" + LAYOUT_ID_NAME_MAP.get(this.lastLayoutId) + ".css?rdm=" + new Date().getTime();
  	}

	var _cols = this.columns;
	this.lastColumns.each(function(k, v) {
      _cols.get(k).removeAllModule();
      v.each(function(o) {
      	_cols.get(k).addModule(o);
      });
	});

	this.resizeAllModuleWidth();
  	return true;
  },
  resizeAllModuleWidth: function() {
    this.columns.each(function(k, v) {
      v.getModules().each(function(o) {
      	o.resizeContentWidth();
      });
    });
  }
});

/**
 * package tm.blog.app.blog
 * class ThemeSetupWindow
 * extends tm.widget.Window
 */
tm.blog.app.blog.ThemeSetupWindow = Class.create();
tm.extend(tm.blog.app.blog.ThemeSetupWindow.prototype, tm.widget.Window.prototype, {
  initialize: function(id, params) {
    params = params ? params : {};
    var fields = {
      handle: "dragTheme_title",
      btnClose: "dragTheme_close",
      btnMinimum: "dragTheme_min",
      btnOk: "dragTheme_ok",
      linkTheme: "linkTheme",
      scriptThemeConfig: "scriptThemeConfig",
      btnThemes: "dragTheme_themes",
      aThemePages: "themePage",
      blogInfo: null,
      lastThemeId: 0,
      curThemeId: 0,
      themes: null,
      totalCount: 12,
      perPageCount: 12,
      currentPage: 1,
      prevPage: "theme_prev_page",
      nextPage: "theme_next_page"
    };
    tm.extend(fields, params);
    //Call super.
    tm.widget.Window.prototype.initialize.apply(this, [id, fields]);
    this.btnOk = $(this.btnOk);
    this.btnThemes = $(this.btnThemes);
    this.aThemePages = $(this.aThemePages);
    this.themes = this.btnThemes.getElementsByTagName("LI");
    this.prevPage = $(this.prevPage);
    this.nextPage = $(this.nextPage);
    this.totalCount = this.themes.length;
  },
  bind: function() {
    var _w = this;
    var _this = this;
    this.btnOk.onclick = function(e) {
  	  // TODO 更新lastLayoutId和LABELS.getCurrent().formatID
  	  _w.blogInfo.setThemeID(_w.curThemeId);
  	  var themeName = THEME_ID_NAME_MAP.get(_w.curThemeId);
  	  _w.blogInfo.setThemeName(themeName);
  	  _w.hide();
  	  
  	  var url = "/doSetupBlog.php";
  	  var method = "GET";
  	  var options = {text: true, json: true};
  	  var vars = new XHConn.Parameter()
  	    .append("opt", "setupTheme")
  	    .append("bloggerID", _w.blogInfo.bloggerID)
  	    .append("themeID", _w.curThemeId)
  	    .append("rdm", new Date().getTime())
  	    .stringValue();
  	  var result = new XHConn().connectSync(url, method, vars, options);
  	  if (result.json.code == 0) {
  	  	tm.widget.Information("保存成功", 1500);
  	  } else {
  	  	tm.widget.Alert("保存失败" + result.text, "ERROR");
  	  }
  	  
  	  tm.Event.stop(e || window.event);
  	  return false;
  	}
    var ts = this.btnThemes.getElementsByTagName("A");
    for (var i = 0; i < ts.length; i++) {
      //修改主题事件
      ts[i].onclick = function(e) {
      	var themeId = this.id.replace(/^btnTheme_|_\w+$/g, "");
      	if (_w.curThemeId != themeId) {
      	  _w.curThemeId = themeId;
  	      var themeName = THEME_ID_NAME_MAP.get(themeId);
  	      $(_w.linkTheme).href = "/themes/" + themeName + "/theme.css?rdm=" + new Date().getTime();
  	      
  	      //加载themes/config.js
  	      var url = "/themes/" + themeName + "/config.js";
  	  	  var method = "GET";
	  	  var options = {text: true, json: false};
	  	  var vars = new XHConn.Parameter()
	  	    .append("rdm", new Date().getTime())
	  	    .stringValue();
	  	  var result = new XHConn().connectSync(url, method, vars, options);
	  	  //重新加载config.js，resize module width
		  eval(result.text);
  	      MODULES.each(
  	        function(k, v) {
  	      	  v.resizeContentWidth();
  	        }
  	      );
      	}
  	    tm.Event.stop(e || window.event);
  	    return false;
      }
    }
    this.prevPage.onclick = function(e) {
      _this.resetPageSep(parseInt(this.title));
      return false;
    }
    this.nextPage.onclick = function(e) {
      _this.resetPageSep(parseInt(this.title));
      return false;
    }
  },
  show: function() {
    tm.widget.Window.prototype.show.apply(this);
    
  	this.lastThemeId = this.blogInfo.getThemeID();
  	this.curThemeId = this.lastThemeId;
  	this.resetPageSep(1);
  },
  onClose: function(e) {
  	if (this.curThemeId != this.lastThemeId) {
  	  $(this.linkTheme).href = "/themes/" + THEME_ID_NAME_MAP.get(this.lastThemeId) + "/theme.css?rdm=" + new Date().getTime();
  	}
    return true;
  },
  resizeModuleWidth: function() {
    var url = "/themes/" + THEME_ID_NAME_MAP.get(this.lastThemeId) + "/config.js";
    var method = "GET";
    var options = {text: true, json: false};
    var vars = new XHConn.Parameter()
      .append("rdm", new Date().getTime())
      .stringValue();
    var result = new XHConn().connectSync(url, method, vars, options);
    eval(result.text);
    MODULES.each(
      function(k, v) {
  	    v.resizeContentWidth();
      }
    );
  },
  resetPageSep: function(pageNum) {
    /*
      totalCount: 12,
      perPageCount: 12,
      currentPage: 1
      aThemePages: "themePage",
     */
    var _this = this;
    var pageCount = Math.ceil(this.totalCount / this.perPageCount);
    
    var prevPageNum = pageNum - 1 == 0 ? 1 : pageNum - 1;
    var nextPageNum = pageNum + 1 > pageCount ? pageCount : pageNum + 1;
    
    this.prevPage.title = prevPageNum;
    this.nextPage.title = nextPageNum;
    
    this.aThemePages.innerHTML = "";
    for (var i = 1; i <= pageCount; i++) {
      if (i != pageNum) {
      	var page = document.createElement("A");
      	page.innerHTML = i + "&nbsp;";
      	page.title = i;
      	page.onclick = function(e) {
      	  _this.resetPageSep(parseInt(this.title));
      	  return false;
      	}
      	this.aThemePages.appendChild(page);
      } else {
      	var page = document.createElement("STRONG");
      	page.innerHTML = i + "&nbsp;";
      	this.aThemePages.appendChild(page);
      }
    }
    
    for (var i = 1; i <= this.themes.length; i++) {
      if (i > (pageNum - 1) * this.perPageCount && i <= pageNum * this.perPageCount) {
      	this.themes[i - 1].style.display = "block";
      } else {
        this.themes[i - 1].style.display = "none";
      }
    }
  }
});

/**
 * package tm.blog.app.blog
 * class ModuleSetupWindow
 * extends tm.widget.Window
 */
tm.blog.app.blog.ModuleSetupWindow = Class.create();
tm.extend(tm.blog.app.blog.ModuleSetupWindow.prototype, tm.widget.Window.prototype, {
  initialize: function(id, params) {
    params = params ? params : {};
    var fields = {
      handle: "dragMod_title",
      btnClose: "dragMod_close",
      btnMinimum: "dragMod_min",
      btnOk: "dragMod_ok",
      chkMods: "modSetupChks",
      blogInfo: null,
      loadedModuleMap: null,
      labels: null,
      columns: null,
      lastColumns: tm.util.Arrays.asMap([[1, new tm.util.Set()], [2, new tm.util.Set()], [3, new tm.util.Set()]])
    };
    tm.extend(fields, params);
    //Call super.
    tm.widget.Window.prototype.initialize.apply(this, [id, fields]);
    this.btnOk = $(this.btnOk);
    this.chkMods = tm.util.Arrays.filter("o", $(this.chkMods).getElementsByTagName("INPUT"), "o.id");
  },
  bind: function() {
    var _w = this;
    // ok event
    this.btnOk.onclick = function(e) {
      //保存模块设置
	  var saveResult = _w.saveModules();
	  if (saveResult.json.code == 0) {
	    tm.widget.Information("保存成功", 1500);
	  } else {
	  	tm.widget.Alert("保存失败" + data.text, "ERROR");
	  }
  	  _w.hide();
  	  tm.Event.stop(e || window.event);
  	  return false;
  	}
  	
  	for (var i = 0; i < this.chkMods.length; i++) {
  	  //bind onclick event
  	  this.chkMods[i].onclick = function(e) {
  	  	var match = this.id.match(/modSetupChk_(\d+)_(\d+)/);
  	  	var id = match[2];
  	    var type = match[1];
  	    
  	    var m = _w.loadedModuleMap.get(id);
  	    if (m) {
  	      //已加载模块，从MODULES取
  	      if (this.checked) {
  	      	m.isLoad = 1;
  	      	_w.columns.get(1).addModule(m);
  	      	m.resizeContentWidth();
  	      } else {
  	      	m.isLoad = 0;
  	      	m.getColumnObject().removeModule(m);
  	      }
        } else {
  	      //未加载模块，从server取
  	      if (this.checked) {
  	        var url = "/lazyload/lz.module.php";
	  	    var method = "GET";
	  	    var vars = new XHConn.Parameter()
	  	      .append("bloggerID", _w.blogInfo.bloggerID)
	  	      .append("moduleID", id)
	          .append("rdm", new Date().getTime())
	          .stringValue();
	        var options = {text: true, json: true};
	  	    var data = new XHConn().connectSync(url, method, vars, options);
	  	    
  	        if (data.json.code == 0) {
  	          //成功，添加模块，构造内容
  	          var elem = document.createElement("DIV");
  	          elem.id = tm.blog.ModuleUtils.getJsModuleId(id);
  	          elem.className = tm.blog.ModuleUtils.getFullClassName(type);
  	          _w.columns.get(1).element.appendChild(elem);
  	          elem.innerHTML = data.json.content.items;
  	          
			  var timer = setInterval(function() {
			    if ($(tm.blog.ModuleUtils.getJsModuleTitleId(id))) {
			    	clearInterval(timer);
			  	    var m = data.json.content;
			    	var mname = tm.blog.ModuleUtils.getJsModuleId(id);
			    	var handle = tm.blog.ModuleUtils.getJsModuleTitleId(id);
                    var module = new tm.blog.Module(mname, {mid: m.id, type: m.type, name: m.name, column: 1, index: m.index, isLoad: 1, revert:true, handle: handle, columnObject: COLUMNS.get(1), canDrop: true});
			    	_w.loadedModuleMap.put(m.id, module);
			    	_w.columns.get(1).addModule(module);
			    	module.resizeContentWidth();
			    	
					switch (parseInt(m.type)) {
		            case 2:
		              var calendar = new tm.blog.Calendar('', {bloggerID: _w.blogInfo.bloggerID});
//		              calendar.setDate("<?= date('Y-m-d', time()) ?>");
		              calendar.redraw();
		              break;
		            case 8:
		              var player = new tm.blog.MediaPlayer("player", {url: "MermaidSong.mp3"});
		              player.play();
		              break;
		            default: 
		              break;
			        }
			    }
			  }, 10);
  	        } else {
  	          //失败
  	        }
  	      }
  	    }
  	  }
  	}
  },
  show: function() {
  	tm.widget.Window.prototype.show.apply(this);
  	
    for (var i = 0; i < this.chkMods.length; i++) {
      var match = this.chkMods[i].id.match(/modSetupChk_(\d+)_(\d+)/);
  	  var id = match[2];
  	  var type = match[1];
      var m = this.loadedModuleMap.get(id);
      if (m && m.isLoad == 1) {
      	this.chkMods[i].checked = true;
      } else {
        this.chkMods[i].checked = false;
      }
    }
    
    //保存当前columns中的module设置到lastColumns
    this.saveLastModules();
  },
  saveModules: function() {
  	var _w = this;
  	var _this = this;
	  //计算模块的位置，保存到MODULES
	  _w.columns.each(function(k, v) {
	  	var i = 1;
	  	v.getModules().sort(tm.blog.app.blog.ModuleSetupWindow.fnModuleSort).each(function(o) {
	  	  o.column = k;
	  	  o.index = i++;
	  	  _w.loadedModuleMap.get(o.mid).isLoad = o.isLoad;
	  	  _w.loadedModuleMap.get(o.mid).column = o.column;
	  	  _w.loadedModuleMap.get(o.mid).index = o.index;
	  	});
	  });
	  
	  //构造json字符串传到后台保存设置
	  var moduleString = "[\n";
	  i = 0;
	  _w.labels.getCurrent().modules.each(function(k, v) {
	  	if (i++ > 0) {
	  	  moduleString += ",\n";
	  	}
	  	var m = _w.loadedModuleMap.get(k);
		if (m) {
		  moduleString += '  {"id":"' + m.mid + '", "type":"' + m.type + '", "column":"' + m.column + '", "index":"' + m.index + '", "isLoad":"' + m.isLoad + '"}';
		} else {
		  moduleString += '  {"id":"' + v.id + '", "type":"' + v.type + '", "column":"' + v.column + '", "index":"' + v.index + '", "isLoad":"' + v.isLoad + '"}';
		}     	
	  });
	  moduleString += "\n]";
	  var url = "/doSetupBlog.php";
	  var method = "POST";
	  var vars = new XHConn.Parameter()
	    .append("opt", "setupModule")
	    .append("bloggerID", _w.blogInfo.bloggerID)
	    .append("labelID", _w.labels.getCurrent().id)
	    .append("moduleString", moduleString)
	    .append("rdm", new Date().getTime())
	    .stringValue();
	  var options = {text: true, json: true};
	  var data = new XHConn().connectSync(url, method, vars, options);
	  
	  if (data.json.code == 0) {
	    _w.labels.getCurrent().modules.each(function(k, v) {
	      if (_w.loadedModuleMap.get(k)) {
	    	v.isLoad = _w.loadedModuleMap.get(k).isLoad;
	  	  }
	    });
	  }
	  return data;
  },
  onClose: function() {
	var _cols = this.columns;
	var _lmm = this.loadedModuleMap;

	_lmm.each(function(k, v) {
	  v.isLoad = 0;
	});

	this.lastColumns.each(function(k, v) {
      _cols.get(k).removeAllModule();
      v.each(function(o) {
      	var m = _lmm.get(o.id);
      	m.isLoad = 1;
      	_cols.get(k).addModule(_lmm.get(o.id));
      });
	});
  	return true;
  },
  saveLastModules: function() {
    //保存当前columns中的module设置到lastColumns
	var lcs = this.lastColumns;
	var cs = this.columns;
	var m = null;
  	lcs.each(function(k, v) {
  	  v.clear();
  	  cs.get(k).getModules().sort(tm.blog.app.blog.ModuleSetupWindow.fnModuleSort).each(function(o) {
  	  	v.add({id: o.mid, isLoad: o.isLoad, columnObject: o.columnObject});
  	  });
  	});
  }
});
tm.blog.app.blog.ModuleSetupWindow.fnModuleSort = function(a, b) {
  return tm.Position.cumulativeOffset(a.element).top - tm.Position.cumulativeOffset(b.element).top;
}
/*
tm.blog.app.blog.PageSetupMenu = Class.create();
tm.extend(tm.blog.app.blog.PageSetupMenu.prototype, {
  initialize: function(params) {

  	var fields = {
      pageSetupBtn: "pageSetup",
  	  pageSetupMenuId: "pageSetupMenu",
  	  formatSetupBtn: "formatSetup",
      themeSetupBtn: "themeSetup",
      moduleSetupBtn: "moduleSetup"
  	};
  	tm.extend(this, fields);
  	
  }
});
*/


/**
 * 
 */
tm.blog.Calendar = Class.create();
tm.extend(tm.blog.Calendar.prototype, {
  initialize: function(id, params) {
  	params = params || {};
  	var fields = {
  	  bloggerID: '',
      date: new Date(),
  	  today: new Date(),
      prevYear: "c_prevyear",
      prevMonth: "c_prevmonth",
      nextYear: "c_nextyear",
      nextMonth: "c_nextmonth",
      year: "c_year",
      month: "c_month",
      tbDates: "c_dates",
      divDatas: "c_datas",
      datas: new tm.util.Map(),
      _dataElems: [],
      _dateTds: [],
      fn: tm.fnFalse,
      lastFocus: null
  	}
  	tm.extend(this, fields, params);
  	
  	this.prevYear = $(this.prevYear);
  	this.prevMonth = $(this.prevMonth);
  	this.nextYear = $(this.nextYear);
  	this.nextMonth = $(this.nextMonth);
  	this.year = $(this.year);
  	this.month = $(this.month);
  	this.tbDates = $(this.tbDates);
  	this.divDatas = $(this.divDatas);
  	
  	var _c = this;
    this.prevYear.href = this.nextYear.href = this.prevMonth.href = this.nextMonth.href = "#";
    this.prevYear.onclick = function() {
      var st = new Date().getTime();
      _c.date.setDate(1);
      _c.date.setYear(_c.date.getFullYear() - 1);
      _c.reloadDatas();
      _c.redrawYear();
      _c.redrawDates();
      return false;
    };
    this.nextYear.onclick = function() {
      _c.date.setDate(1);
      _c.date.setYear(_c.date.getFullYear() + 1);
      _c.reloadDatas();
      _c.redrawYear();
      _c.redrawDates();
      return false;
    };
    this.prevMonth.onclick = function() {
      _c.date.setDate(1);
      _c.date.setMonth(_c.date.getMonth() - 1);
      _c.reloadDatas();
      _c.redrawMonth();
      _c.redrawYear();
      _c.redrawDates();
      return false;
    };
    this.nextMonth.onclick = function() {
      _c.date.setDate(1);
      _c.date.setMonth(_c.date.getMonth() + 1);
      _c.reloadDatas();
      _c.redrawMonth();
      _c.redrawYear();
      _c.redrawDates();
      return false;
    };
    this._dateTds = $A($(this.tbDates).getElementsByTagName("TD"));
    
    var dataJson = eval("(" + this.divDatas.innerHTML.trim() + ")");
    this.datas.put(dataJson.year + "_" + dataJson.month, dataJson.days.split(","));
    
    var _this = this;
    this.fn = function(e) {
	  var bloggerID = _this.bloggerID;
      var year = _this.date.getFullYear();
      var month = _this.date.getMonth() + 1;
      var day = this.innerHTML.trim();
      var pageNo = 1;
      tm.blog.ArticleList.goPageCalendar(bloggerID, pageNo, year, month, day);
      if (_this.lastFocus) {
      	_this.lastFocus.parentNode.className = "";
      }
      this.parentNode.className = "data";
      _this.lastFocus = this;
      return false;
    }
  },
  setDate:function(d) {
    /(\d{4})\-(\d{1,2})\-(\d{1,2})/g.test(d);
    this.date.setYear(RegExp.$1);
    this.date.setMonth(RegExp.$2 - 1);
    this.date.setDate(1);
  },
  setToday: function(td) {
  	/(\d{4})\-(\d{1,2})\-(\d{1,2})/g.test(td);
  	this.today.setYear(RegExp.$1);
    this.today.setMonth(RegExp.$2 - 1);
    this.today.setDate(RegExp.$3);
  },
  redrawYear: function() {
    this.year.innerHTML = this.date.getFullYear();
  },
  redrawMonth: function() {
    this.month.innerHTML = this.date.getMonth() + 1;
  },
  redrawDates: function() {
  	this.lastFocus = null;
  	
  	var ty = this.today.getFullYear();
    var tm = this.today.getMonth() + 1;
    var td = this.today.getDate();
    
    var y = this.date.getFullYear();
    var m = this.date.getMonth() + 1;
    var isLeapYear = y % 400 == 0 || y % 4 == 0 && y % 100 != 0;
    var maxDate = 0;
    switch (m) {
      case 2:
        maxDate = isLeapYear ? 29 : 28;
        break;
      case 4:
      case 6:
      case 9:
      case 11:
        maxDate = 30;
        break;
      default:
        maxDate = 31;
    }
    var startDay = this.date.getDay();
    
    var dates = this.datas.get(y + "_" + m);
    if (!dates) {
      dates = [];
      this.datas.put(y + "_" + m, dates);
    }
    
    for (var i = 0; i < 42; i++) {
      if (this._dateTds[i].className == "today" || this._dateTds[i].className == "data") {
      	this._dateTds[i].className = "";
      }
      if (i + 1 > startDay && i + 1 <= maxDate + startDay) {
        if (ty == y && tm == m && i - startDay + 1 == td) {
          this._dateTds[i].className = "today";
        }
      	if (dates.contains(i + 1 - startDay)) {
      	  this._dateTds[i].innerHTML = "";
      	  var a = document.createElement("A");
          a.href = "#";
          a.onclick = this.fn;
          a.innerHTML = i + 1 - startDay;
          this._dateTds[i].appendChild(a);
      	} else {
      	  this._dateTds[i].innerHTML = i + 1 - startDay;
      	}
      } else {
        this._dateTds[i].innerHTML = "&nbsp;";
      }
    }
  },
  reloadDatas: function() {
  	var url = "/doSetupBlog.php";
  	var method = "GET";
  	var vars = new XHConn.Parameter()
  	  .append("opt", "getCalendarData")
  	  .append("bloggerID", this.bloggerID)
  	  .append("year", this.date.getFullYear())
      .append("month", this.date.getMonth() + 1)
      .append("rdm", new Date().getTime())
      .stringValue();
      
    var options = {text: true, json: true};
  	var data = new XHConn().connectSync(url, method, vars, options);
  	this.date.setYear(data.json.year);
  	this.date.setMonth(data.json.month - 1);
  	this.datas.put(data.json.year + "_" + data.json.month, data.json.days.split(","));
  },
  redraw: function() {
    this.redrawYear();
    this.redrawMonth();
    this.redrawDates();
  }
});

tm.blog.MediaPlayer = Class.create();
tm.extend(tm.blog.MediaPlayer.prototype, {
  initialize: function(id, params) {
  	param = params ? params : {};
  	var fields = {
  	  title: null,
  	  _isMute: false,
  	  btnPlay: "player_play",
  	  btnStop: "player_stop",
  	  btnMute: "player_mute",
  	  btnVoice: "player_voice",
  	  url: "",
  	  element: null,
  	  _isIE: false
  	};
  	tm.extend(this, fields, params);
  	this.id = id;
  	this.element = $(id);
  	this.title = $(this.title);
  	this.btnPlay = $(this.btnPlay);
  	this.btnStop = $(this.btnStop);
  	this.btnMute = $(this.btnMute);
  	this.btnVoice = $(this.btnVoice);

	var player = document.createElement('OBJECT');
	this.player = player;
	player.id = this.id + "_object";
	player.classid= "clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6";
	player.style.display = "none";
	if(typeof(player.settings) == "undefined") {
	  this.element.innerHTML = ''
        + '<embed src="' + this.url + '" '
        + '  align="baseline" border="0" width="180" height="68" '
		+ '	 type="application/x-mplayer2"                                                                                                      '
		+ '	 pluginspage=""                                                                                                                     '
		+ '	 showcontrols="1" '
		+ '  showpositioncontrols="0"                                                                      '
		+ '	 showaudiocontrols="1" '
		+ '  showtracker="1" '
		+ '  showdisplay="0"                                                                              '
		+ '	 showstatusbar="1"                                                                                                                  '
		+ '	 autosize="1" loop="255"                                                                                                                   '
		+ '	 showgotobar="0" showcaptioning="0" autostart="1" autorewind="1"                                                                    '
		+ '	 animationatstart="0" transparentatstart="0" allowscan="1"                                                                          '
		+ '	 enablecontextmenu="0" clicktoplay="0"                                                                                              '
		+ '	 defaultframe="datawindow" invokeurls="0">                                                                                          '
		+ '</embed>                                                                                                                            ';
	} else {
	  this._isIE = true;
      player.settings.invokeURLs = false;
	  player.settings.playCount = 255;
	  player.settings.autoStart = false;
	  player.enableContextMenu = false;
	  player.uiMode = "none" ;
	  this.element.appendChild(player);
	  //bind events
	  this.bind();
	  this.setURL(this.url);
	}
  },
  bind: function() {
  	var _this = this;
  	this.btnPlay.onclick = function(e) {
  	  switch (_this.getState()) {
        case 3:
          _this.pause();
          break;
        default:
          _this.play();
          break;
  	  }
  	  return false;
  	};
  	this.btnStop.onclick = function(e) {
  	  if (_this.getState() == 3) {
  	    _this.stop();
  	  }
      return false;
  	};
  	this.btnMute.onclick = function(e) {
  	  if (_this.isMute()) {
  	    _this.setMute(false);
  	    _this.btnMute.className = "pnormal";
  	  } else {
  	    _this.setMute(true);
  	    _this.btnMute.className = "pmute";
  	  }
  	  return false;
  	}
  	this.btnVoice.onclick = function(e) {
  	  e = e || window.event;
  	  var ox = e.offsetX;
  	  var x = 0, y = 0;
  	  x = parseInt(-205 + Math.floor(ox / 3) * 3 + 1);
  	  y = -37 + (10 - Math.floor(ox / 3));
  	  _this.btnVoice.style.backgroundPosition = x + "px " + y + "px";
  	  _this.setVolume((ox / 29) * 100);
  	  return false;
  	}
  },
  getPlayer: function() {
  	return this.player;
  },
  setTitle: function(s) {
  	this.title.innerHTML = s;
  },
  setURL: function(url) {
	try {
	  this.getPlayer().URL = url;
	} catch(e) {
	  this.getPlayer().URL ='';
	}
  } ,
  play: function() {
  	if (this._isIE) {
	  try {
	    this.getPlayer().controls.play();
	    this.btnPlay.className = "ppause";
	  } catch (e) {
	    alert(e.message);
	  }
  	}
  },
  pause: function() {
	try {
	  this.getPlayer().controls.pause();
	  this.btnPlay.className = "pplay";
	} catch (e) {
	  alert(e.message);
	}
  },
  stop: function() {
	try {
	  this.getPlayer().controls.stop();
	  this.btnPlay.className = "pplay";
	} catch (e) {
	  alert(e.message);
	}
  },
  /*
setVolume:function(volume){
	var musicPlayer=this.getMO();
	if(volume<0)
		volume=0;
	if(volume>100)
		volume=100;
	if(musicPlayer&&musicPlayer.settings)
	musicPlayer.settings.volume=volume;
},
   */
  setVolume: function(v){
    var p = this.getPlayer();
    v = v < 0 ? 0 : (v > 100 ? 100 : v);
    try {
	  this.getPlayer().settings.volume = v;
	} catch (e) {
	  alert(e.message);
	}
  },
  setMute: function(m) {
	try {
	  this.getPlayer().settings.Mute = m;
	  this._isMute = m;
	} catch (e) {
	  alert(e.message);
	}
  },
  isMute: function() {
    return this._isMute;
  },
	// 	getState : 播放器的状态 
	/* from msdn
		0 Undefined
		1 Stopped
		2 Paused
		3 Playing
		4 ScanForward
		5 ScanReverse
		6 Buffering
		7 Waiting
		8 MediaEnded
		9 Transitioning
		10 Ready
		11 Reconnecting
	*/
  getState: function(){
    return this.getPlayer().PlayState;
  },
  statusStringMap: tm.util.Arrays.asMap([
    0, "无媒体",
    1, "已停止",
    2, "已暂停",
    3, "正在播放",
    4, "正在快进",
    5, "正在快退",
    6, "缓冲",
    7, "等待",
    8, "结束",
    9, "连接中",
    10, "准备就绪",
    11, "重新连接"
  ], 1),
  getMediaName: function(){
    try {
	  return this.getPlayer().currentMedia.name;
	} catch (e) {
	  alert(e.message);
	  return "";
	}
  }
});

tm.blog.ArticleList = {
  /*
   * 1:all / 2:catalog / 3:calendar
   */
  listShowType: 1,
  curCatalog: 1,
  curDate: {},
  deleteArticle: function(bloggerID, articleID) {
  	tm.widget.Confirm(
  	  "确认要删除这篇日志吗？",
  	  function(e) {
  	  	var url = "/doDeleteArticle.php";
	  	var method = "GET";
	  	var vars = new XHConn.Parameter()
	  	  .append("bloggerID", bloggerID)
	      .append("articleID", articleID)
	      .append("rdm", new Date().getTime())
	      .stringValue();
	    var options = {text: true, json: true};
	  	var data = new XHConn().connectSync(url, method, vars, options);
	  	if (data.json.code == 0) {
	  		tm.widget.Information("日志删除成功", 1500, 
	  		  function() {
		  		switch (tm.blog.ArticleList.listShowType) {
		  		  case 1:
		  		    tm.blog.ArticleList.goPageAll(bloggerID, 1);
		  		    break;
		  		  case 2:
		  		    tm.blog.ArticleList.goPageCatalog(bloggerID, 1, tm.blog.ArticleList.curCatalog);
		  		    break;
		  		  case 3:
		  		    tm.blog.ArticleList.goPageCalendar(bloggerID, 1, tm.blog.ArticleList.curDate.year, tm.blog.ArticleList.curDate.month, tm.blog.ArticleList.curDate.day);
		  		    break;
		  		  default:
		  		    break;
		  		}
	  		  }
	  		);
	  	} else {
	  		tm.widget.Alert("删除失败" + data.text, "ERROR");
	  	}
  	  },
  	  tm.fnTrue,
  	  "删除确认"
  	);
  },
  goPageAll: function(bloggerID, pageNo) {
  	var url = "/lazyload/lz.articlelist.php";
  	var method = "GET";
  	var vars = new XHConn.Parameter()
  	  .append("opt", "getArticlesAll")
  	  .append("bloggerID", bloggerID)
      .append("pageNo", pageNo)
      .append("articleShowType", BLOG_INFO.articleShowType)
      .append("rdm", new Date().getTime())
      .stringValue();
    var options = {text: true};
  	var data = new XHConn().connectSync(url, method, vars, options);
  	if (typeof(MODULES) != "undefined") {
  	  var ms = MODULES.values().filter("o", 'o.type==3');
  	  if (ms.size() == 1) {
  	  	var m = ms.get(0);
  	  	$(tm.blog.ModuleUtils.getJsModuleContentId(m.mid)).innerHTML = data.text;
  	  }
  	} else {
  	  $('article_content').innerHTML = data.text;
  	}
    tm.blog.ArticleList.listShowType = 1;
    try {
      pv_img();
    } catch (err) { }
  },
  goPageCatalog: function(bloggerID, pageNo, catalogID) {
  	var url = "/lazyload/lz.articlelist.php";
  	var method = "GET";
  	var vars = new XHConn.Parameter()
  	  .append("opt", "getArticlesByCatalog")
  	  .append("bloggerID", bloggerID)
      .append("pageNo", pageNo)
      .append("catalogID", catalogID)
      .append("articleShowType", BLOG_INFO.articleShowType)
      .append("rdm", new Date().getTime())
      .stringValue();
    var options = {text: true};
  	var data = new XHConn().connectSync(url, method, vars, options);
  	if (typeof(MODULES) != "undefined") {
  	  var ms = MODULES.values().filter("o", 'o.type==3');
  	  if (ms.size() == 1) {
  	  	var m = ms.get(0);
  	  	$(tm.blog.ModuleUtils.getJsModuleContentId(m.mid)).innerHTML = data.text;
  	  }
  	} else {
  	  $('article_content').innerHTML = data.text;
  	}
  	tm.blog.ArticleList.listShowType = 2;
  	tm.blog.ArticleList.curCatalog = catalogID;
    try {
      pv_img();
    } catch (err) { }
  },
  goPageCalendar: function(bloggerID, pageNo, year, month, day) {
  	var url = "/lazyload/lz.articlelist.php";
  	var method = "GET";
  	var vars = new XHConn.Parameter()
  	  .append("opt", "getArticlesCalendar")
  	  .append("bloggerID", bloggerID)
      .append("pageNo", pageNo)
      .append("year", year)
      .append("month", month)
      .append("day", day)
      .append("articleShowType", BLOG_INFO.articleShowType)
      .append("rdm", new Date().getTime())
      .stringValue();
    var options = {text: true};
  	var data = new XHConn().connectSync(url, method, vars, options);
  	if (typeof(MODULES) != "undefined") {
  	  var ms = MODULES.values().filter("o", 'o.type==3');
  	  if (ms.size() == 1) {
  	  	var m = ms.get(0);
  	  	$(tm.blog.ModuleUtils.getJsModuleContentId(m.mid)).innerHTML = data.text;
  	  }
  	} else {
  	  $('article_content').innerHTML = data.text;
  	}
  	tm.blog.ArticleList.listShowType = 3;
  	tm.blog.ArticleList.curDate = {year: year, month: month, day: day};
    try {
      pv_img();
    } catch (err) { }
  }
};

tm.blog.app.SaveModulePosFrame = Class.create();
tm.extend(tm.blog.app.SaveModulePosFrame.prototype, tm.widget.Component.prototype, {
  initialize: function(id, params) {
  	var fields = {
  	  btnOk: "saveModulePosOk",
  	  btnCancel: "saveModulePosCancel",
  	  timer: null
  	};
  	tm.extend(fields, params || {});
  	//Call super.
    tm.widget.Component.prototype.initialize.apply(this, [id, fields]);
  },
  bind: function() {
  	var _this = this;
  	this.btnOk = $(this.btnOk);
  	this.btnOk.onclick = function(e) {
  	  var saveResult = _this.moduleWin.saveModules();
  	  if (saveResult.json.code == 0) {
	    tm.widget.Information("保存成功", 1500, 
	      function() {
	    	_this.hide();
	      }
	    );
	  } else {
	  	tm.widget.Alert("保存失败" + data.text, "ERROR");
	  }
  	}
  	this.btnCancel = $(this.btnCancel);
  	this.btnCancel.onclick = function(e) {
  	  _this.hide();
  	}
  	
  },
  show: function() {
    this.setWidth(tm.Position.windowClientSize().w - 20);
  	this.setVisible(true);
  	this.startTimer();
  },
  hide: function() {
  	this.setVisible(false);
  	this.stopTimer();
  },
  startTimer: function() {
  	var _this = this;
  	this.timer = setInterval(function() { _this.setTop(window.scrollTop || document.documentElement.scrollTop || document.body.scrollTop) }, 200);
  },
  stopTimer: function() {
  	clearInterval(this.timer);
  }
});

/*
function jsonEncode(o) {
  var s = "{";
  var v = null;
  var j = 0;
  for (var i in o) {
  	if (j++ > 0) {
  	  s += ","
  	}
  	v = o[i];
  	if (v instanceof Array) {
  	  s += '"' + i.replace(/"/g, '\"') + '": [';
  	  for (var l = 0; l < v.length; l++) {
  	  	if (l > 0) {
  	  	  s += ",";
  	  	}
  	  	s += jsonEncode(v[l]);
  	  }
  	  s += "]";
  	} else if (!(v instanceof Function)) {
  	  s += '"' + i + '": "' + ("" + v).replace(/"/g, '\\"') + '"';
  	} else {
  	  continue;
  	}
  }
  s += "}";
  return s;
}
*/