dwz.navTab.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /**
  2. * @author ZhangHuihua@msn.com
  3. *
  4. */
  5. var navTab = {
  6. componentBox: null, // tab component. contain tabBox, prevBut, nextBut, panelBox
  7. _tabBox: null,
  8. _prevBut: null,
  9. _nextBut: null,
  10. _panelBox: null,
  11. _moreBut:null,
  12. _moreBox:null,
  13. _currentIndex: 0,
  14. _op: {id:"navTab", stTabBox:".navTab-tab", stPanelBox:".navTab-panel", mainTabId:"main", close$:"a.close", prevClass:"tabsLeft", nextClass:"tabsRight", stMore:".tabsMore", stMoreLi:"ul.tabsMoreList"},
  15. init: function(options){
  16. if ($.History) $.History.init("#container");
  17. var $this = this;
  18. $.extend(this._op, options);
  19. this.componentBox = $("#"+this._op.id);
  20. this._tabBox = this.componentBox.find(this._op.stTabBox);
  21. this._panelBox = this.componentBox.find(this._op.stPanelBox);
  22. this._prevBut = this.componentBox.find("."+this._op.prevClass);
  23. this._nextBut = this.componentBox.find("."+this._op.nextClass);
  24. this._moreBut = this.componentBox.find(this._op.stMore);
  25. this._moreBox = this.componentBox.find(this._op.stMoreLi);
  26. this._prevBut.click(function(event) {$this._scrollPrev()});
  27. this._nextBut.click(function(event) {$this._scrollNext()});
  28. this._moreBut.click(function(){
  29. $this._moreBox.show();
  30. return false;
  31. });
  32. $(document).click(function(){$this._moreBox.hide()});
  33. this._contextmenu(this._tabBox);
  34. this._contextmenu(this._getTabs());
  35. this._init();
  36. this._ctrlScrollBut();
  37. },
  38. _init: function(){
  39. var $this = this;
  40. this._getTabs().each(function(iTabIndex){
  41. $(this).unbind("click").click(function(event){
  42. $this._switchTab(iTabIndex);
  43. });
  44. $(this).find(navTab._op.close$).unbind("click").click(function(){
  45. $this._closeTab(iTabIndex);
  46. });
  47. });
  48. this._getMoreLi().each(function(iTabIndex){
  49. $(this).find(">a").unbind("click").click(function(event){
  50. $this._switchTab(iTabIndex);
  51. });
  52. });
  53. this._switchTab(this._currentIndex);
  54. },
  55. _contextmenu:function($obj){ // navTab右键菜单
  56. var $this = this;
  57. $obj.contextMenu('navTabCM', {
  58. bindings:{
  59. reload:function(t,m){
  60. $this._reload(t, true);
  61. },
  62. closeCurrent:function(t,m){
  63. var tabId = t.attr("tabid");
  64. if (tabId) $this.closeTab(tabId);
  65. else $this.closeCurrentTab();
  66. },
  67. closeOther:function(t,m){
  68. var index = $this._indexTabId(t.attr("tabid"));
  69. $this._closeOtherTab(index > 0 ? index : $this._currentIndex);
  70. },
  71. closeAll:function(t,m){
  72. $this.closeAllTab();
  73. }
  74. },
  75. ctrSub:function(t,m){
  76. var mReload = m.find("[rel='reload']");
  77. var mCur = m.find("[rel='closeCurrent']");
  78. var mOther = m.find("[rel='closeOther']");
  79. var mAll = m.find("[rel='closeAll']");
  80. var $tabLi = $this._getTabs();
  81. if ($tabLi.size() < 2) {
  82. mCur.addClass("disabled");
  83. mOther.addClass("disabled");
  84. mAll.addClass("disabled");
  85. }
  86. if ($this._currentIndex == 0 || t.attr("tabid") == $this._op.mainTabId) {
  87. mCur.addClass("disabled");
  88. mReload.addClass("disabled");
  89. } else if ($tabLi.size() == 2) {
  90. mOther.addClass("disabled");
  91. }
  92. }
  93. });
  94. },
  95. _getTabs: function(){
  96. return this._tabBox.find("> li");
  97. },
  98. _getPanels: function(){
  99. return this._panelBox.find("> div");
  100. },
  101. _getMoreLi: function(){
  102. return this._moreBox.find("> li");
  103. },
  104. _getTab: function(tabid){
  105. var index = this._indexTabId(tabid);
  106. if (index >= 0) return this._getTabs().eq(index);
  107. },
  108. getPanel: function(tabid){
  109. var index = this._indexTabId(tabid);
  110. if (index >= 0) return this._getPanels().eq(index);
  111. },
  112. _getTabsW: function(iStart, iEnd){
  113. return this._tabsW(this._getTabs().slice(iStart, iEnd));
  114. },
  115. _tabsW:function($tabs){
  116. var iW = 0;
  117. $tabs.each(function(){
  118. iW += $(this).outerWidth(true);
  119. });
  120. return iW;
  121. },
  122. _indexTabId: function(tabid){
  123. if (!tabid) return -1;
  124. var iOpenIndex = -1;
  125. this._getTabs().each(function(index){
  126. if ($(this).attr("tabid") == tabid){iOpenIndex = index; return;}
  127. });
  128. return iOpenIndex;
  129. },
  130. _getLeft: function(){
  131. return this._tabBox.position().left;
  132. },
  133. _getScrollBarW: function(){
  134. return this.componentBox.width()-55;
  135. },
  136. _visibleStart: function(){
  137. var iLeft = this._getLeft(), iW = 0;
  138. var $tabs = this._getTabs();
  139. for (var i=0; i<$tabs.size(); i++){
  140. if (iW + iLeft >= 0) return i;
  141. iW += $tabs.eq(i).outerWidth(true);
  142. }
  143. return 0;
  144. },
  145. _visibleEnd: function(){
  146. var iLeft = this._getLeft(), iW = 0;
  147. var $tabs = this._getTabs();
  148. for (var i=0; i<$tabs.size(); i++){
  149. iW += $tabs.eq(i).outerWidth(true);
  150. if (iW + iLeft > this._getScrollBarW()) return i;
  151. }
  152. return $tabs.size();
  153. },
  154. _scrollPrev: function(){
  155. var iStart = this._visibleStart();
  156. if (iStart > 0){
  157. this._scrollTab(-this._getTabsW(0, iStart-1));
  158. }
  159. },
  160. _scrollNext: function(){
  161. var iEnd = this._visibleEnd();
  162. if (iEnd < this._getTabs().size()){
  163. this._scrollTab(-this._getTabsW(0, iEnd+1) + this._getScrollBarW());
  164. }
  165. },
  166. _scrollTab: function(iLeft, isNext){
  167. var $this = this;
  168. this._tabBox.animate({ left: iLeft+'px' }, 200, function(){$this._ctrlScrollBut();});
  169. },
  170. _scrollCurrent: function(){ // auto scroll current tab
  171. var iW = this._tabsW(this._getTabs());
  172. if (iW <= this._getScrollBarW()){
  173. this._scrollTab(0);
  174. } else if (this._getLeft() < this._getScrollBarW() - iW){
  175. this._scrollTab(this._getScrollBarW()-iW);
  176. } else if (this._currentIndex < this._visibleStart()) {
  177. this._scrollTab(-this._getTabsW(0, this._currentIndex));
  178. } else if (this._currentIndex >= this._visibleEnd()) {
  179. this._scrollTab(this._getScrollBarW() - this._getTabs().eq(this._currentIndex).outerWidth(true) - this._getTabsW(0, this._currentIndex));
  180. }
  181. },
  182. _ctrlScrollBut: function(){
  183. var iW = this._tabsW(this._getTabs());
  184. if (this._getScrollBarW() > iW){
  185. this._prevBut.hide();
  186. this._nextBut.hide();
  187. this._tabBox.parent().removeClass("tabsPageHeaderMargin");
  188. } else {
  189. this._prevBut.show().removeClass("tabsLeftDisabled");
  190. this._nextBut.show().removeClass("tabsRightDisabled");
  191. this._tabBox.parent().addClass("tabsPageHeaderMargin");
  192. if (this._getLeft() >= 0){
  193. this._prevBut.addClass("tabsLeftDisabled");
  194. } else if (this._getLeft() <= this._getScrollBarW() - iW) {
  195. this._nextBut.addClass("tabsRightDisabled");
  196. }
  197. }
  198. },
  199. _switchTab: function(iTabIndex){
  200. var $tab = this._getTabs().removeClass("selected").eq(iTabIndex).addClass("selected");
  201. if (DWZ.ui.hideMode == 'offsets') {
  202. this._getPanels().css({position: 'absolute', top:'-100000px', left:'-100000px'}).eq(iTabIndex).css({position: '', top:'', left:''});
  203. } else {
  204. this._getPanels().hide().eq(iTabIndex).show();
  205. }
  206. this._getMoreLi().removeClass("selected").eq(iTabIndex).addClass("selected");
  207. this._currentIndex = iTabIndex;
  208. this._scrollCurrent();
  209. this._reload($tab);
  210. },
  211. _closeTab: function(index, openTabid){
  212. this._getTabs().eq(index).remove();
  213. this._getPanels().eq(index).trigger(DWZ.eventType.pageClear).remove();
  214. this._getMoreLi().eq(index).remove();
  215. if (this._currentIndex >= index) this._currentIndex--;
  216. if (openTabid) {
  217. var openIndex = this._indexTabId(openTabid);
  218. if (openIndex > 0) this._currentIndex = openIndex;
  219. }
  220. this._init();
  221. this._scrollCurrent();
  222. this._reload(this._getTabs().eq(this._currentIndex));
  223. },
  224. closeTab: function(tabid){
  225. var index = this._indexTabId(tabid);
  226. if (index > 0) { this._closeTab(index); }
  227. },
  228. closeCurrentTab: function(openTabid){ //openTabid 可以为空,默认关闭当前tab后,打开最后一个tab
  229. if (this._currentIndex > 0) {this._closeTab(this._currentIndex, openTabid);}
  230. },
  231. closeAllTab: function(){
  232. this._getTabs().filter(":gt(0)").remove();
  233. this._getPanels().filter(":gt(0)").trigger(DWZ.eventType.pageClear).remove();
  234. this._getMoreLi().filter(":gt(0)").remove();
  235. this._currentIndex = 0;
  236. this._init();
  237. this._scrollCurrent();
  238. },
  239. _closeOtherTab: function(index){
  240. index = index || this._currentIndex;
  241. if (index > 0) {
  242. var str$ = ":eq("+index+")";
  243. this._getTabs().not(str$).filter(":gt(0)").remove();
  244. this._getPanels().not(str$).filter(":gt(0)").trigger(DWZ.eventType.pageClear).remove();
  245. this._getMoreLi().not(str$).filter(":gt(0)").remove();
  246. this._currentIndex = 1;
  247. this._init();
  248. this._scrollCurrent();
  249. } else {
  250. this.closeAllTab();
  251. }
  252. },
  253. _loadUrlCallback: function($panel){
  254. $panel.find("[layoutH]").layoutH();
  255. $panel.find(":button.close").click(function(){
  256. navTab.closeCurrentTab();
  257. });
  258. },
  259. _reload: function($tab, flag){
  260. flag = flag || $tab.data("reloadFlag");
  261. var url = $tab.attr("url");
  262. if (flag && url) {
  263. $tab.data("reloadFlag", null);
  264. var $panel = this.getPanel($tab.attr("tabid"));
  265. if ($tab.hasClass("external")){
  266. navTab.openExternal(url, $panel);
  267. }else {
  268. //获取pagerForm参数
  269. var $pagerForm = $("#pagerForm", $panel);
  270. var args = $pagerForm.size()>0 ? $pagerForm.serializeArray() : {}
  271. $panel.loadUrl(url, args, function(){navTab._loadUrlCallback($panel);});
  272. }
  273. }
  274. },
  275. reloadFlag: function(tabid){
  276. var $tab = this._getTab(tabid);
  277. if ($tab){
  278. if (this._indexTabId(tabid) == this._currentIndex) this._reload($tab, true);
  279. else $tab.data("reloadFlag", 1);
  280. }
  281. },
  282. reload: function(url, options){
  283. var op = $.extend({data:{}, navTabId:"", callback:null}, options);
  284. var $tab = op.navTabId ? this._getTab(op.navTabId) : this._getTabs().eq(this._currentIndex);
  285. var $panel = op.navTabId ? this.getPanel(op.navTabId) : this._getPanels().eq(this._currentIndex);
  286. if ($panel){
  287. if (!url) {
  288. url = $tab.attr("url");
  289. }
  290. if (url) {
  291. if ($tab.hasClass("external")) {
  292. navTab.openExternal(url, $panel);
  293. } else {
  294. if ($.isEmptyObject(op.data)) { //获取pagerForm参数
  295. var $pagerForm = $("#pagerForm", $panel);
  296. op.data = $pagerForm.size()>0 ? $pagerForm.serializeArray() : {}
  297. }
  298. $panel.ajaxUrl({
  299. type:"POST", url:url, data:op.data, callback:function(response){
  300. navTab._loadUrlCallback($panel);
  301. if ($.isFunction(op.callback)) op.callback(response);
  302. }
  303. });
  304. }
  305. }
  306. }
  307. },
  308. getCurrentPanel: function() {
  309. return this._getPanels().eq(this._currentIndex);
  310. },
  311. checkTimeout:function(){
  312. var json = DWZ.jsonEval(this.getCurrentPanel().html());
  313. if (json && json[DWZ.keys.statusCode] == DWZ.statusCode.timeout) this.closeCurrentTab();
  314. },
  315. openExternal:function(url, $panel){
  316. var ih = navTab._panelBox.height();
  317. $panel.html(DWZ.frag["externalFrag"].replaceAll("{url}", url).replaceAll("{height}", ih+"px"));
  318. },
  319. /**
  320. *
  321. * @param {Object} tabid
  322. * @param {Object} url
  323. * @param {Object} params: title, data, fresh
  324. */
  325. openTab: function(tabid, url, options){ //if found tabid replace tab, else create a new tab.
  326. var op = $.extend({title:"New Tab", type:"GET", data:{}, fresh:true, external:false}, options);
  327. var iOpenIndex = this._indexTabId(tabid);
  328. if (iOpenIndex >= 0){
  329. var $tab = this._getTabs().eq(iOpenIndex);
  330. var span$ = $tab.attr("tabid") == this._op.mainTabId ? "> span > span" : "> span";
  331. $tab.find(">a").attr("title", op.title).find(span$).html(op.title);
  332. var $panel = this._getPanels().eq(iOpenIndex);
  333. if(op.fresh || $tab.attr("url") != url) {
  334. $tab.attr("url", url);
  335. if (op.external || url.isExternalUrl()) {
  336. $tab.addClass("external");
  337. navTab.openExternal(url, $panel);
  338. } else {
  339. $tab.removeClass("external");
  340. $panel.ajaxUrl({
  341. type:op.type, url:url, data:op.data, callback:function(){
  342. navTab._loadUrlCallback($panel);
  343. }
  344. });
  345. }
  346. }
  347. this._currentIndex = iOpenIndex;
  348. } else {
  349. var tabFrag = '<li tabid="#tabid#"><a href="javascript:" title="#title#" class="#tabid#"><span>#title#</span></a><a href="javascript:;" class="close">close</a></li>';
  350. this._tabBox.append(tabFrag.replaceAll("#tabid#", tabid).replaceAll("#title#", op.title));
  351. this._panelBox.append('<div class="page unitBox"></div>');
  352. this._moreBox.append('<li><a href="javascript:" title="#title#">#title#</a></li>'.replaceAll("#title#", op.title));
  353. var $tabs = this._getTabs();
  354. var $tab = $tabs.filter(":last");
  355. var $panel = this._getPanels().filter(":last");
  356. if (op.external || url.isExternalUrl()) {
  357. $tab.addClass("external");
  358. navTab.openExternal(url, $panel);
  359. } else {
  360. $tab.removeClass("external");
  361. $panel.ajaxUrl({
  362. type:op.type, url:url, data:op.data, callback:function(){
  363. navTab._loadUrlCallback($panel);
  364. }
  365. });
  366. }
  367. if ($.History) {
  368. setTimeout(function(){
  369. $.History.addHistory(tabid, function(tabid){
  370. var i = navTab._indexTabId(tabid);
  371. if (i >= 0) navTab._switchTab(i);
  372. }, tabid);
  373. }, 10);
  374. }
  375. this._currentIndex = $tabs.size() - 1;
  376. this._contextmenu($tabs.filter(":last").hoverClass("hover"));
  377. }
  378. this._init();
  379. this._scrollCurrent();
  380. this._getTabs().eq(this._currentIndex).attr("url", url);
  381. }
  382. };