miniTab.js 23 KB

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