miniTab.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /**
  2. * date:2020/02/27
  3. * author:Mr.Chung
  4. * version:2.0
  5. * description:layuimini tab框架扩展
  6. */
  7. define(["jquery"], function ($) {
  8. var element = layui.element,
  9. $ = layui.$;
  10. var miniTab = {
  11. /**
  12. * 初始化tab
  13. * @param options
  14. */
  15. render: function (options) {
  16. options.filter = options.filter || null;
  17. options.multiModule = options.multiModule || false;
  18. options.urlHashLocation = options.urlHashLocation || false;
  19. options.maxTabNum = options.maxTabNum || 20;
  20. options.menuList = options.menuList || []; // todo 后期菜单想改为不操作dom, 而是直接操作初始化传过来的数据
  21. options.homeInfo = options.homeInfo || {};
  22. options.listenSwichCallback = options.listenSwichCallback || function () {
  23. };
  24. miniTab.listen(options);
  25. miniTab.listenRoll();
  26. miniTab.listenSwitch(options);
  27. miniTab.listenHash(options);
  28. },
  29. /**
  30. * 新建tab窗口
  31. * @param options.tabId
  32. * @param options.href
  33. * @param options.title
  34. * @param options.isIframe
  35. * @param options.maxTabNum
  36. */
  37. create: function (options) {
  38. options.tabId = options.tabId || null;
  39. options.href = options.href || null;
  40. options.title = options.title || null;
  41. options.isIframe = options.isIframe || false;
  42. options.maxTabNum = options.maxTabNum || 20;
  43. if ($(".layuimini-tab .layui-tab-title li").length >= options.maxTabNum) {
  44. layer.msg('Tab窗口已达到限定数量,请先关闭部分Tab');
  45. return false;
  46. }
  47. var ele = element;
  48. if (options.isIframe) ele = parent.layui.element;
  49. ele.tabAdd('layuiminiTab', {
  50. title: '<span class="layuimini-tab-active"></span><span>' + options.title + '</span><i class="layui-icon layui-unselect layui-tab-close">ဆ</i>' //用于演示
  51. , content: '<iframe width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" src="' + options.href + '"></iframe>'
  52. , id: options.tabId
  53. });
  54. $('.layuimini-menu-left').attr('layuimini-tab-tag', 'add');
  55. sessionStorage.setItem('layuiminimenu_' + options.tabId, options.title);
  56. },
  57. /**
  58. * 切换选项卡
  59. * @param tabId
  60. */
  61. change: function (tabId) {
  62. element.tabChange('layuiminiTab', tabId);
  63. },
  64. /**
  65. * 删除tab窗口
  66. * @param tabId
  67. * @param isParent
  68. */
  69. delete: function (tabId, isParent) {
  70. // todo 未知BUG,不知道是不是layui问题,必须先删除元素
  71. $(".layuimini-tab .layui-tab-title .layui-unselect.layui-tab-bar").remove();
  72. if (isParent === true) {
  73. parent.layui.element.tabDelete('layuiminiTab', tabId);
  74. } else {
  75. element.tabDelete('layuiminiTab', tabId);
  76. }
  77. },
  78. /**
  79. * 在iframe层打开新tab方法
  80. */
  81. openNewTabByIframe: function (options) {
  82. options.href = options.href || null;
  83. options.title = options.title || null;
  84. var loading = parent.layer.load(0, {shade: false, time: 2 * 1000});
  85. if (options.href === null || options.href === undefined) options.href = new Date().getTime();
  86. var checkTab = miniTab.check(options.href, true);
  87. if (!checkTab) {
  88. miniTab.create({
  89. tabId: options.href,
  90. href: options.href,
  91. title: options.title,
  92. isIframe: true,
  93. });
  94. }
  95. parent.layui.element.tabChange('layuiminiTab', options.href);
  96. parent.layer.close(loading);
  97. },
  98. /**
  99. * 在iframe层关闭当前tab方法
  100. */
  101. deleteCurrentByIframe: function () {
  102. var ele = $(".layuimini-tab .layui-tab-title li.layui-this", parent.document);
  103. if (ele.length > 0) {
  104. var layId = $(ele[0]).attr('lay-id');
  105. miniTab.delete(layId, true);
  106. }
  107. },
  108. /**
  109. * 判断tab窗口
  110. */
  111. check: function (tabId, isIframe) {
  112. // 判断选项卡上是否有
  113. var checkTab = false;
  114. if (isIframe === undefined || isIframe === false) {
  115. $(".layui-tab-title li").each(function () {
  116. var checkTabId = $(this).attr('lay-id');
  117. if (checkTabId != null && checkTabId === tabId) {
  118. checkTab = true;
  119. }
  120. });
  121. } else {
  122. parent.layui.$(".layui-tab-title li").each(function () {
  123. var checkTabId = $(this).attr('lay-id');
  124. if (checkTabId != null && checkTabId === tabId) {
  125. checkTab = true;
  126. }
  127. });
  128. }
  129. return checkTab;
  130. },
  131. /**
  132. * 开启tab右键菜单
  133. * @param tabId
  134. * @param left
  135. */
  136. openTabRignMenu: function (tabId, left) {
  137. miniTab.closeTabRignMenu();
  138. var menuHtml = '<div class="layui-unselect layui-form-select layui-form-selected layuimini-tab-mousedown layui-show" data-tab-id="' + tabId + '" style="left: ' + left + 'px!important">\n' +
  139. '<dl>\n' +
  140. '<dd><a href="javascript:;" layuimini-tab-menu-close="current">关 闭 当 前</a></dd>\n' +
  141. '<dd><a href="javascript:;" layuimini-tab-menu-close="other">关 闭 其 他</a></dd>\n' +
  142. '<dd><a href="javascript:;" layuimini-tab-menu-close="all">关 闭 全 部</a></dd>\n' +
  143. '</dl>\n' +
  144. '</div>';
  145. var makeHtml = '<div class="layuimini-tab-make"></div>';
  146. $('.layuimini-tab .layui-tab-title').after(menuHtml);
  147. $('.layuimini-tab .layui-tab-content').after(makeHtml);
  148. },
  149. /**
  150. * 关闭tab右键菜单
  151. */
  152. closeTabRignMenu: function () {
  153. $('.layuimini-tab-mousedown').remove();
  154. $('.layuimini-tab-make').remove();
  155. },
  156. /**
  157. * 查询菜单信息
  158. * @param href
  159. * @param menuList
  160. */
  161. searchMenu: function (href, menuList) {
  162. var menu;
  163. for (key in menuList) {
  164. var item = menuList[key];
  165. if (item.href === href) {
  166. menu = item;
  167. break;
  168. }
  169. if (item.child) {
  170. newMenu = miniTab.searchMenu(href, item.child);
  171. if (newMenu) {
  172. menu = newMenu;
  173. break;
  174. }
  175. }
  176. }
  177. return menu;
  178. },
  179. /**
  180. * 监听
  181. * @param options
  182. */
  183. listen: function (options) {
  184. options = options || {};
  185. options.maxTabNum = options.maxTabNum || 20;
  186. /**
  187. * 打开新窗口
  188. */
  189. $('body').on('click', '[layuimini-href]', function () {
  190. var loading = layer.load(0, {shade: false, time: 2 * 1000});
  191. var tabId = $(this).attr('layuimini-href'),
  192. href = $(this).attr('layuimini-href'),
  193. title = $(this).text(),
  194. target = $(this).attr('target');
  195. var el = $("[layuimini-href='" + href + "']", ".layuimini-menu-left");
  196. layer.close(window.openTips);
  197. if (el.length) {
  198. $(el).closest(".layui-nav-tree").find(".layui-this").removeClass("layui-this");
  199. $(el).parent().addClass("layui-this");
  200. }
  201. if (target === '_blank') {
  202. layer.close(loading);
  203. window.open(href, "_blank");
  204. return false;
  205. }
  206. if (tabId === null || tabId === undefined) tabId = new Date().getTime();
  207. var checkTab = miniTab.check(tabId);
  208. if (!checkTab) {
  209. miniTab.create({
  210. tabId: tabId,
  211. href: href,
  212. title: title,
  213. isIframe: false,
  214. maxTabNum: options.maxTabNum,
  215. });
  216. }
  217. element.tabChange('layuiminiTab', tabId);
  218. layer.close(loading);
  219. });
  220. /**
  221. * 在iframe子菜单上打开新窗口
  222. */
  223. $('body').on('click', '[layuimini-content-href]', function () {
  224. var loading = parent.layer.load(0, {shade: false, time: 2 * 1000});
  225. var tabId = $(this).attr('layuimini-content-href'),
  226. href = $(this).attr('layuimini-content-href'),
  227. title = $(this).attr('data-title'),
  228. target = $(this).attr('target');
  229. if (target === '_blank') {
  230. parent.layer.close(loading);
  231. window.open(href, "_blank");
  232. return false;
  233. }
  234. if (tabId === null || tabId === undefined) tabId = new Date().getTime();
  235. var checkTab = miniTab.check(tabId, true);
  236. if (!checkTab) {
  237. miniTab.create({
  238. tabId: tabId,
  239. href: href,
  240. title: title,
  241. isIframe: true,
  242. maxTabNum: options.maxTabNum,
  243. });
  244. }
  245. parent.layui.element.tabChange('layuiminiTab', tabId);
  246. parent.layer.close(loading);
  247. });
  248. /**
  249. * 关闭选项卡
  250. **/
  251. $('body').on('click', '.layuimini-tab .layui-tab-title .layui-tab-close', function () {
  252. var loading = layer.load(0, {shade: false, time: 2 * 1000});
  253. var $parent = $(this).parent();
  254. var tabId = $parent.attr('lay-id');
  255. if (tabId !== undefined || tabId !== null) {
  256. miniTab.delete(tabId);
  257. }
  258. layer.close(loading);
  259. });
  260. /**
  261. * 选项卡操作
  262. */
  263. $('body').on('click', '[layuimini-tab-close]', function () {
  264. var loading = layer.load(0, {shade: false, time: 2 * 1000});
  265. var closeType = $(this).attr('layuimini-tab-close');
  266. $(".layuimini-tab .layui-tab-title li").each(function () {
  267. var tabId = $(this).attr('lay-id');
  268. var id = $(this).attr('id');
  269. var isCurrent = $(this).hasClass('layui-this');
  270. if (id !== 'layuiminiHomeTabId') {
  271. if (closeType === 'all') {
  272. miniTab.delete(tabId);
  273. } else {
  274. if (closeType === 'current' && isCurrent) {
  275. miniTab.delete(tabId);
  276. } else if (closeType === 'other' && !isCurrent) {
  277. miniTab.delete(tabId);
  278. }
  279. }
  280. }
  281. });
  282. layer.close(loading);
  283. });
  284. /**
  285. * 禁用网页右键
  286. */
  287. $(".layuimini-tab .layui-tab-title").unbind("mousedown").bind("contextmenu", function (e) {
  288. e.preventDefault();
  289. return false;
  290. });
  291. /**
  292. * 注册鼠标右键
  293. */
  294. $('body').on('mousedown', '.layuimini-tab .layui-tab-title li', function (e) {
  295. var left = $(this).offset().left - $('.layuimini-tab ').offset().left + ($(this).width() / 2),
  296. tabId = $(this).attr('lay-id');
  297. if (e.which === 3) {
  298. miniTab.openTabRignMenu(tabId, left);
  299. }
  300. });
  301. /**
  302. * 关闭tab右键菜单
  303. */
  304. $('body').on('click', '.layui-body,.layui-header,.layuimini-menu-left,.layuimini-tab-make', function () {
  305. miniTab.closeTabRignMenu();
  306. });
  307. /**
  308. * tab右键选项卡操作
  309. */
  310. $('body').on('click', '[layuimini-tab-menu-close]', function () {
  311. var loading = layer.load(0, {shade: false, time: 2 * 1000});
  312. var closeType = $(this).attr('layuimini-tab-menu-close'),
  313. currentTabId = $('.layuimini-tab-mousedown').attr('data-tab-id');
  314. $(".layuimini-tab .layui-tab-title li").each(function () {
  315. var tabId = $(this).attr('lay-id');
  316. var id = $(this).attr('id');
  317. if (id !== 'layuiminiHomeTabId') {
  318. if (closeType === 'all') {
  319. miniTab.delete(tabId);
  320. } else {
  321. if (closeType === 'current' && currentTabId === tabId) {
  322. miniTab.delete(tabId);
  323. } else if (closeType === 'other' && currentTabId !== tabId) {
  324. miniTab.delete(tabId);
  325. }
  326. }
  327. }
  328. });
  329. miniTab.closeTabRignMenu();
  330. layer.close(loading);
  331. });
  332. },
  333. /**
  334. * 监听tab切换
  335. * @param options
  336. */
  337. listenSwitch: function (options) {
  338. options.filter = options.filter || null;
  339. options.multiModule = options.multiModule || false;
  340. options.urlHashLocation = options.urlHashLocation || false;
  341. options.listenSwichCallback = options.listenSwichCallback || function () {
  342. };
  343. element.on('tab(' + options.filter + ')', function (data) {
  344. var tabId = $(this).attr('lay-id');
  345. if (options.urlHashLocation) {
  346. location.hash = tabId;
  347. }
  348. if (typeof options.listenSwichCallback === 'function') {
  349. options.listenSwichCallback();
  350. }
  351. // 判断是否为新增窗口
  352. if ($('.layuimini-menu-left').attr('layuimini-tab-tag') === 'add') {
  353. $('.layuimini-menu-left').attr('layuimini-tab-tag', 'no')
  354. } else {
  355. $("[layuimini-href]").parent().removeClass('layui-this');
  356. if (options.multiModule) {
  357. miniTab.listenSwitchMultiModule(tabId);
  358. } else {
  359. miniTab.listenSwitchSingleModule(tabId);
  360. }
  361. }
  362. miniTab.rollPosition();
  363. });
  364. },
  365. /**
  366. * 监听hash变化
  367. * @param options
  368. * @returns {boolean}
  369. */
  370. listenHash: function (options) {
  371. options.urlHashLocation = options.urlHashLocation || false;
  372. options.maxTabNum = options.maxTabNum || 20;
  373. options.homeInfo = options.homeInfo || {};
  374. options.menuList = options.menuList || [];
  375. if (!options.urlHashLocation) return false;
  376. var tabId = location.hash.replace(/^#/, '');
  377. if (tabId === null || tabId === undefined || tabId ==='') return false;
  378. // 判断是否为首页
  379. if(tabId ===options.homeInfo.href) return false;
  380. // 判断是否为右侧菜单
  381. var menu = miniTab.searchMenu(tabId, options.menuList);
  382. if (menu !== undefined) {
  383. miniTab.create({
  384. tabId: tabId,
  385. href: tabId,
  386. title: menu.title,
  387. isIframe: false,
  388. maxTabNum: options.maxTabNum,
  389. });
  390. $('.layuimini-menu-left').attr('layuimini-tab-tag', 'no');
  391. element.tabChange('layuiminiTab', tabId);
  392. return false;
  393. }
  394. // 判断是否为快捷菜单
  395. var isSearchMenu = false;
  396. $("[layuimini-content-href]").each(function () {
  397. if ($(this).attr("layuimini-content-href") === tabId) {
  398. var title = $(this).attr("data-title");
  399. miniTab.create({
  400. tabId: tabId,
  401. href: tabId,
  402. title: title,
  403. isIframe: false,
  404. maxTabNum: options.maxTabNum,
  405. });
  406. $('.layuimini-menu-left').attr('layuimini-tab-tag', 'no');
  407. element.tabChange('layuiminiTab', tabId);
  408. isSearchMenu = true;
  409. return false;
  410. }
  411. });
  412. if (isSearchMenu) return false;
  413. // 既不是右侧菜单、快捷菜单,就直接打开
  414. var title = sessionStorage.getItem('layuiminimenu_' + tabId) === null ? tabId : sessionStorage.getItem('layuiminimenu_' + tabId);
  415. miniTab.create({
  416. tabId: tabId,
  417. href: tabId,
  418. title: title,
  419. isIframe: false,
  420. maxTabNum: options.maxTabNum,
  421. });
  422. element.tabChange('layuiminiTab', tabId);
  423. return false;
  424. },
  425. /**
  426. * 监听滚动
  427. */
  428. listenRoll: function () {
  429. $(".layuimini-tab-roll-left").click(function () {
  430. miniTab.rollClick("left");
  431. });
  432. $(".layuimini-tab-roll-right").click(function () {
  433. miniTab.rollClick("right");
  434. });
  435. },
  436. /**
  437. * 单模块切换
  438. * @param tabId
  439. */
  440. listenSwitchSingleModule: function (tabId) {
  441. $("[layuimini-href]").each(function () {
  442. if ($(this).attr("layuimini-href") === tabId) {
  443. // 自动展开菜单栏
  444. var addMenuClass = function ($element, type) {
  445. if (type === 1) {
  446. $element.addClass('layui-this');
  447. if ($element.hasClass('layui-nav-item') && $element.hasClass('layui-this')) {
  448. $(".layuimini-header-menu li").attr('class', 'layui-nav-item');
  449. } else {
  450. addMenuClass($element.parent().parent(), 2);
  451. }
  452. } else {
  453. $element.addClass('layui-nav-itemed');
  454. if ($element.hasClass('layui-nav-item') && $element.hasClass('layui-nav-itemed')) {
  455. $(".layuimini-header-menu li").attr('class', 'layui-nav-item');
  456. } else {
  457. addMenuClass($element.parent().parent(), 2);
  458. }
  459. }
  460. };
  461. addMenuClass($(this).parent(), 1);
  462. return false;
  463. }
  464. });
  465. },
  466. /**
  467. * 多模块切换
  468. * @param tabId
  469. */
  470. listenSwitchMultiModule: function (tabId) {
  471. $("[layuimini-href]").each(function () {
  472. if ($(this).attr("layuimini-href") === tabId) {
  473. // 自动展开菜单栏
  474. var addMenuClass = function ($element, type) {
  475. if (type === 1) {
  476. $element.addClass('layui-this');
  477. if ($element.hasClass('layui-nav-item') && $element.hasClass('layui-this')) {
  478. var moduleId = $element.parent().attr('id');
  479. $(".layuimini-header-menu li").attr('class', 'layui-nav-item');
  480. $("#" + moduleId + "HeaderId").addClass("layui-this");
  481. $(".layuimini-menu-left .layui-nav.layui-nav-tree").attr('class', 'layui-nav layui-nav-tree layui-hide');
  482. $("#" + moduleId).attr('class', 'layui-nav layui-nav-tree layui-this');
  483. } else {
  484. addMenuClass($element.parent().parent(), 2);
  485. }
  486. } else {
  487. $element.addClass('layui-nav-itemed');
  488. if ($element.hasClass('layui-nav-item') && $element.hasClass('layui-nav-itemed')) {
  489. var moduleId = $element.parent().attr('id');
  490. $(".layuimini-header-menu li").attr('class', 'layui-nav-item');
  491. $("#" + moduleId + "HeaderId").addClass("layui-this");
  492. $(".layuimini-menu-left .layui-nav.layui-nav-tree").attr('class', 'layui-nav layui-nav-tree layui-hide');
  493. $("#" + moduleId).attr('class', 'layui-nav layui-nav-tree layui-this');
  494. } else {
  495. addMenuClass($element.parent().parent(), 2);
  496. }
  497. }
  498. };
  499. addMenuClass($(this).parent(), 1);
  500. return false;
  501. }
  502. });
  503. },
  504. /**
  505. * 自动定位
  506. */
  507. rollPosition: function () {
  508. var $tabTitle = $('.layuimini-tab .layui-tab-title');
  509. var autoLeft = 0;
  510. $tabTitle.children("li").each(function () {
  511. if ($(this).hasClass('layui-this')) {
  512. return false;
  513. } else {
  514. autoLeft += $(this).outerWidth();
  515. }
  516. });
  517. $tabTitle.animate({
  518. scrollLeft: autoLeft - $tabTitle.width() / 3
  519. }, 200);
  520. },
  521. /**
  522. * 点击滚动
  523. * @param direction
  524. */
  525. rollClick: function (direction) {
  526. var $tabTitle = $('.layuimini-tab .layui-tab-title');
  527. var left = $tabTitle.scrollLeft();
  528. if ('left' === direction) {
  529. $tabTitle.animate({
  530. scrollLeft: left - 450
  531. }, 200);
  532. } else {
  533. $tabTitle.animate({
  534. scrollLeft: left + 450
  535. }, 200);
  536. }
  537. }
  538. };
  539. return miniTab;
  540. });