menu.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. layui.define(['table', 'jquery', 'element'], function (exports) {
  2. "use strict";
  3. var MOD_NAME = 'menu',
  4. $ = layui.jquery,
  5. element = layui.element;
  6. var pearMenu = function (opt) {
  7. this.option = opt;
  8. };
  9. pearMenu.prototype.render = function (opt) {
  10. var option = {
  11. elem: opt.elem,
  12. async: opt.async,
  13. parseData: opt.parseData,
  14. url: opt.url,
  15. method: opt.method ? opt.method : "GET",
  16. defaultOpen: opt.defaultOpen,
  17. defaultSelect: opt.defaultSelect,
  18. control: opt.control,
  19. controlWidth: opt.controlWidth ? opt.controlWidth : "auto",
  20. defaultMenu: opt.defaultMenu,
  21. accordion: opt.accordion,
  22. height: opt.height,
  23. theme: opt.theme,
  24. data: opt.data ? opt.data : [],
  25. change: opt.change ? opt.change : function () { },
  26. done: opt.done ? opt.done : function () { }
  27. }
  28. var tempDone = option.done;
  29. option.done = function(){
  30. if (option.control) {
  31. rationalizeHeaderControlWidthAuto(option);
  32. }
  33. tempDone();
  34. }
  35. if (option.async) {
  36. if (option.method === "GET") {
  37. getData(option.url).then(function (data) {
  38. option.data = data.data; //变更
  39. renderMenu(option);
  40. });
  41. } else {
  42. postData(option.url).then(function (data) {
  43. option.data = data.data; //变更
  44. renderMenu(option);
  45. });
  46. }
  47. } else {
  48. // 延时返回,和 javascript 执行时序关联
  49. window.setTimeout(function () { renderMenu(option); }, 500);
  50. }
  51. // 处理高度
  52. $("#" + opt.elem).height(option.height)
  53. setTimeout(function () {
  54. $("#" + opt.control + " .control").on("mousewheel DOMMouseScroll", function (event) {
  55. var delta = (event.originalEvent.wheelDelta && (event.originalEvent.wheelDelta > 0 ? 1 : -1)) || // chrome & ie
  56. (event.originalEvent.detail && (event.originalEvent.detail > 0 ? -1 : 1)); // firefox
  57. if (delta > 0) {
  58. for (var num = 1; num < 20; num++) {
  59. setTimeout(function () {
  60. if ($("#" + opt.control + " .control ul").css('left').replace("px", "") < 0) {
  61. $("#" + opt.control + " .control ul").css("left", "+=2px");
  62. }
  63. }, 10)
  64. }
  65. } else if (delta < 0) {
  66. if (((Number)($("#" + opt.control + " .control ul").css("left").replace("px", "")) + ($("#" + opt.control + " .control ul").width() - $("#" + opt.control + " .control").width())) > 0) {
  67. for (var num = 1; num < 20; num++) {
  68. setTimeout(function () {
  69. $("#" + opt.control + " .control ul").css("left", "-=2px");
  70. }, 10)
  71. }
  72. }
  73. }
  74. });
  75. }, 1000)
  76. return new pearMenu(option);
  77. }
  78. pearMenu.prototype.click = function (clickEvent) {
  79. var _this = this;
  80. $("body").on("click", "#" + _this.option.elem + " .site-demo-active", function () {
  81. var dom = $(this);
  82. var data = {
  83. menuId: dom.attr("menu-id"),
  84. menuTitle: dom.attr("menu-title"),
  85. menuPath: dom.attr("menu-title"),
  86. menuIcon: dom.attr("menu-icon"),
  87. menuUrl: dom.attr("menu-url"),
  88. openType: dom.attr("open-type")
  89. };
  90. var doms = hash(dom);
  91. if (doms != null) {
  92. if (doms.text() != '') {
  93. data['menuPath'] = doms.find("span").text() + " / " + data['menuPath'];
  94. }
  95. }
  96. if (doms != null) {
  97. var domss = hash(doms);
  98. if (domss != null) {
  99. if (domss.text() != '') {
  100. data['menuPath'] = domss.find("span").text() + " / " + data['menuPath'];
  101. }
  102. }
  103. }
  104. if (domss != null) {
  105. var domsss = hash(domss);
  106. if (domsss != null) {
  107. if (domsss.text() != '') {
  108. data['menuPath'] = domsss.find("span").text() + " / " + data['menuPath'];
  109. }
  110. }
  111. }
  112. if ($("#" + _this.option.elem).is(".pear-nav-mini")) {
  113. if (_this.option.accordion) {
  114. activeMenus = $(this).parent().parent().parent().children("a");
  115. } else {
  116. activeMenus.push($(this).parent().parent().parent().children("a"));
  117. }
  118. }
  119. clickEvent(dom, data);
  120. })
  121. }
  122. function hash(dom) {
  123. var d = dom.parent().parent().prev();
  124. if (d.prop("tagName") === "UL") {
  125. return null;
  126. }
  127. return d;
  128. }
  129. pearMenu.prototype.skin = function (skin) {
  130. var menu = $(".pear-nav-tree[lay-filter='" + this.option.elem + "']").parent();
  131. menu.removeClass("dark-theme");
  132. menu.removeClass("light-theme");
  133. menu.addClass(skin);
  134. }
  135. pearMenu.prototype.selectItem = function (pearId) {
  136. if (this.option.control != false) {
  137. $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents(".layui-side-scroll ").find("ul").css({
  138. display: "none"
  139. });
  140. $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents(".layui-side-scroll ").find(".layui-this").removeClass(
  141. "layui-this");
  142. $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents("ul").css({
  143. display: "block"
  144. });
  145. var controlId = $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents("ul").attr("pear-id");
  146. if (controlId != undefined) {
  147. $("#" + this.option.control).find(".layui-this").removeClass("layui-this");
  148. $("#" + this.option.control).find("[pear-id='" + controlId + "']").addClass("layui-this");
  149. }
  150. }
  151. $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents(".pear-nav-tree").find(".layui-this").removeClass(
  152. "layui-this");
  153. if (!$("#" + this.option.elem).is(".pear-nav-mini")) {
  154. var openEle = null;
  155. var openEleHeight = 0;
  156. $($("#" + this.option.elem + " a[menu-id='" + pearId + "']").parents('.layui-nav-child').get().reverse()).each(function () {
  157. if (!$(this).parent().is('.layui-nav-itemed')) {
  158. if (openEleHeight == 0) {
  159. openEle = $(this);
  160. } else {
  161. $(this).parent().addClass('layui-nav-itemed');
  162. $(this).css({
  163. height: 'auto',
  164. });
  165. }
  166. openEleHeight += $(this).children("dd").length * 48;
  167. }
  168. });
  169. if (this.option.accordion) {
  170. if (openEleHeight > 0) {
  171. var currentDom = openEle.parent().siblings('.layui-nav-itemed').children(".layui-nav-child");
  172. currentDom.animate({
  173. height: "0px"
  174. }, 240, function () {
  175. currentDom.css({
  176. height: "auto"
  177. });
  178. $(this).parent().removeClass("layui-nav-itemed");
  179. $(this).find('.layui-nav-itemed').removeClass("layui-nav-itemed");
  180. });
  181. }
  182. }
  183. if (openEleHeight > 0) {
  184. openEle.parent().addClass("layui-nav-itemed");
  185. openEle.height(0);
  186. openEle.animate({
  187. height: openEleHeight + "px"
  188. }, 240, function () {
  189. $(this).css({ height: 'auto' });
  190. });
  191. }
  192. }
  193. $("#" + this.option.elem + " a[menu-id='" + pearId + "']").parent().addClass("layui-this");
  194. }
  195. var activeMenus;
  196. pearMenu.prototype.collapse = function (time) {
  197. var elem = this.option.elem;
  198. var config = this.option;
  199. if ($("#" + this.option.elem).is(".pear-nav-mini")) {
  200. $.each(activeMenus, function (i, item) {
  201. $("#" + elem + " a[menu-id='" + $(this).attr("menu-id") + "']").parent().addClass("layui-nav-itemed");
  202. })
  203. $("#" + this.option.elem).removeClass("pear-nav-mini");
  204. $("#" + this.option.elem).animate({
  205. width: "220px"
  206. }, 180);
  207. isHoverMenu(false, config);
  208. var that = this;
  209. $("#" + this.option.elem)
  210. .promise()
  211. .done(function () {
  212. if (that.option.control) {
  213. rationalizeHeaderControlWidth(that.option);
  214. }
  215. })
  216. } else {
  217. activeMenus = $("#" + this.option.elem).find(".layui-nav-itemed>a");
  218. $("#" + this.option.elem).find(".layui-nav-itemed").removeClass("layui-nav-itemed");
  219. $("#" + this.option.elem).addClass("pear-nav-mini");
  220. $("#" + this.option.elem).animate({
  221. width: "60px"
  222. }, 400);
  223. var that = this;
  224. $("#" + this.option.elem)
  225. .promise()
  226. .done(function () {
  227. isHoverMenu(true, config);
  228. if (that.option.control) {
  229. rationalizeHeaderControlWidth(that.option);
  230. }
  231. })
  232. }
  233. }
  234. function getData(url) {
  235. var defer = $.Deferred();
  236. var symbol = url.indexOf('?') !== -1 ? '&' : '?';
  237. $.get(url + symbol + "fresh=" + Math.random(), function (result) {
  238. defer.resolve(result)
  239. });
  240. return defer.promise();
  241. }
  242. function postData(url) {
  243. var defer = $.Deferred();
  244. var symbol = url.indexOf('?') !== -1 ? '&' : '?';
  245. $.post(url + symbol + "fresh=" + Math.random(), function (result) {
  246. defer.resolve(result)
  247. }, "json");
  248. return defer.promise();
  249. }
  250. function renderMenu(option) {
  251. if (option.parseData != false) {
  252. option.parseData(option.data);
  253. }
  254. if (option.data.length > 0) {
  255. if (option.control != false) {
  256. createMenuAndControl(option);
  257. } else {
  258. createMenu(option);
  259. }
  260. }
  261. element.init();
  262. downShow(option);
  263. option.done();
  264. }
  265. function createMenu(option) {
  266. var menuHtml = '<div style="height:100%!important;" class="pear-side-scroll layui-side-scroll ' + option.theme + '"><ul lay-filter="' + option.elem +
  267. '" class="layui-nav arrow pear-menu layui-nav-tree pear-nav-tree">'
  268. $.each(option.data, function (i, item) {
  269. var content = '<li class="layui-nav-item" >';
  270. if (i == option.defaultOpen) {
  271. content = '<li class="layui-nav-item layui-nav-itemed" >';
  272. }
  273. var href = "javascript:;";
  274. var target = "";
  275. var className = "site-demo-active"
  276. if (item.openType == "_blank" && item.type == 1) {
  277. href = item.href;
  278. target = "target='_blank'";
  279. className = "";
  280. }
  281. if (item.type == 0) {
  282. // 创 建 目 录 结 构
  283. content += '<a href="javascript:;" menu-type="' + item.type + '" menu-id="' + item.id + '" href="' + href +
  284. '" ' + target + '><i class="' + item.icon + '"></i><span>' + item.title +
  285. '</span></a>';
  286. } else if (item.type == 1) {
  287. content += '<a class="' + className + '" menu-type="' + item.type + '" menu-url="' + item.href + '" menu-id="' +
  288. item.id +
  289. '" menu-title="' + item.title + '" href="' + href + '" ' + target + '><i class="' + item.icon +
  290. '"></i><span>' + item.title + '</span></a>';
  291. }
  292. // 调 用 递 归 方 法 加 载 无 限 层 级 的 子 菜 单
  293. content += loadchild(item);
  294. // 结 束 一 个 根 菜 单 项
  295. content += '</li>';
  296. menuHtml += content;
  297. });
  298. // 结 束 菜 单 结 构 的 初 始 化
  299. menuHtml += "</ul></div>";
  300. // 将 菜 单 拼 接 到 初 始 化 容 器 中
  301. $("#" + option.elem).html(menuHtml);
  302. }
  303. function createMenuAndControl(option) {
  304. var control = '<div style="white-space: nowrap;overflow-x: scroll;overflow: hidden;" class="control"><ul class="layui-nav pear-nav-control pc layui-hide-xs" style="width: fit-content;">';
  305. var controlPe = '<ul class="layui-nav pear-nav-control layui-hide-sm">';
  306. // 声 明 头 部
  307. var menu = '<div class="layui-side-scroll ' + option.theme + '">'
  308. // 开 启 同 步 操 作
  309. var index = 0;
  310. var controlItemPe = '<dl class="layui-nav-child">';
  311. $.each(option.data, function (i, item) {
  312. var menuItem = '';
  313. var controlItem = '';
  314. if (i === option.defaultMenu) {
  315. controlItem = '<li pear-href="' + item.href + '" pear-title="' + item.title + '" pear-id="' + item.id +
  316. '" class="layui-this layui-nav-item"><a href="#">' + item.title + '</a></li>';
  317. menuItem = '<ul pear-id="' + item.id + '" lay-filter="' + option.elem +
  318. '" class="layui-nav arrow layui-nav-tree pear-nav-tree">';
  319. controlPe += '<li class="layui-nav-item"><a class="pe-title" href="javascript:;" >' + item.title + '</a>';
  320. controlItemPe += '<dd pear-href="' + item.href + '" pear-title="' + item.title + '" pear-id="' + item.id +
  321. '"><a href="javascript:void(0);">' + item.title + '</a></dd>';
  322. } else {
  323. controlItem = '<li pear-href="' + item.href + '" pear-title="' + item.title + '" pear-id="' + item.id +
  324. '" class="layui-nav-item"><a href="#">' + item.title + '</a></li>';
  325. menuItem = '<ul style="display:none" pear-id="' + item.id + '" lay-filter="' + option.elem +
  326. '" class="layui-nav arrow layui-nav-tree pear-nav-tree">';
  327. controlItemPe += '<dd pear-href="' + item.href + '" pear-title="' + item.title + '" pear-id="' + item.id +
  328. '"><a href="javascript:void(0);">' + item.title + '</a></dd>';
  329. }
  330. index++;
  331. $.each(item.children, function (i, note) {
  332. // 创 建 每 一 个 菜 单 项
  333. var content = '<li class="layui-nav-item" >';
  334. var href = "javascript:;";
  335. var target = "";
  336. var className = "site-demo-active";
  337. if (note.openType == "_blank" && note.type == 1) {
  338. href = note.href;
  339. target = "target='_blank'";
  340. className = "";
  341. }
  342. // 判 断 菜 单 类 型 0 是 不可跳转的目录 1 是 可 点 击 跳 转 的 菜 单
  343. if (note.type == 0) {
  344. // 创 建 目 录 结 构
  345. content += '<a href="' + href + '" ' + target + ' menu-type="' + note.type + '" menu-id="' + note.id +
  346. '" ><i class="' + note.icon + '"></i><span>' + note.title +
  347. '</span></a>';
  348. } else if (note.type == 1) {
  349. // 创 建 菜 单 结 构
  350. content += '<a ' + target + ' class="' + className + '" menu-type="' + note.type + '" menu-url="' + note.href +
  351. '" menu-id="' + note.id +
  352. '" menu-title="' + note.title + '" href="' + href + '"><i class="' + note.icon +
  353. '"></i><span>' + note.title + '</span></a>';
  354. }
  355. content += loadchild(note);
  356. content += '</li>';
  357. menuItem += content;
  358. })
  359. menu += menuItem + '</ul>';
  360. control += controlItem;
  361. })
  362. controlItemPe += "</li></dl></ul>"
  363. controlPe += controlItemPe;
  364. $("#" + option.control).html(control + "</div>");
  365. $("#" + option.control).append(controlPe);
  366. $("#" + option.elem).html(menu);
  367. $("#" + option.control + " .pear-nav-control").on("click", "[pear-id]", function () {
  368. $("#" + option.elem).find(".pear-nav-tree").css({
  369. display: 'none'
  370. });
  371. $("#" + option.elem).find(".pear-nav-tree[pear-id='" + $(this).attr("pear-id") + "']").css({
  372. display: 'block'
  373. });
  374. $("#" + option.control).find(".pe-title").html($(this).attr("pear-title"));
  375. $("#" + option.control).find("")
  376. option.change($(this).attr("pear-id"), $(this).attr("pear-title"), $(this).attr("pear-href"))
  377. })
  378. }
  379. /** 加载子菜单 (递归)*/
  380. function loadchild(obj) {
  381. // 判 单 是 否 是 菜 单, 如 果 是 菜 单 直 接 返 回
  382. if (obj.type == 1) {
  383. return "";
  384. }
  385. // 创 建 子 菜 单 结 构
  386. var content = '<dl class="layui-nav-child">';
  387. // 如 果 嵌 套 不 等 于 空
  388. if (obj.children != null && obj.children.length > 0) {
  389. // 遍 历 子 项 目
  390. $.each(obj.children, function (i, note) {
  391. // 创 建 子 项 结 构
  392. content += '<dd>';
  393. var href = "javascript:;";
  394. var target = "";
  395. var className = "site-demo-active";
  396. if (note.openType == "_blank" && note.type == 1) {
  397. href = note.href;
  398. target = "target='_blank'";
  399. className = "";
  400. }
  401. // 判 断 子 项 类 型
  402. if (note.type == 0) {
  403. // 创 建 目 录 结 构
  404. content += '<a ' + target + ' href="' + href + '" menu-type="' + note.type + '" menu-id="' + note.id +
  405. '"><i class="' + note.icon + '"></i><span>' + note.title + '</span></a>';
  406. } else if (note.type == 1) {
  407. // 创 建 菜 单 结 构
  408. content += '<a ' + target + ' class="' + className + '" menu-type="' + note.type + '" menu-url="' + note.href +
  409. '" menu-id="' + note.id + '" menu-title="' + note.title + '" menu-icon="' + note.icon + '" href="' + href +
  410. '" ><i class="' + note.icon + '"></i><span>' + note.title + '</span></a>';
  411. }
  412. // 加 载 子 项 目 录
  413. content += loadchild(note);
  414. // 结 束 当 前 子 菜 单
  415. content += '</dd>';
  416. });
  417. // 封 装
  418. } else {
  419. content += '<dd style="background-color: transparent!important;"><a style="background-color: transparent!important;margin-left: 26px">目录为空</a></dd>';
  420. }
  421. content += '</dl>';
  422. return content;
  423. }
  424. function downShow(option) {
  425. $("body #" + option.elem).on("click", "a[menu-type='0']", function () {
  426. if (!$("#" + option.elem).is(".pear-nav-mini")) {
  427. var superEle = $(this).parent();
  428. var ele = $(this).next('.layui-nav-child');
  429. var heights = ele.children("dd").length * 48;
  430. if ($(this).parent().is(".layui-nav-itemed")) {
  431. if (option.accordion) {
  432. var currentDom = $(this).parent().siblings('.layui-nav-itemed').children('.layui-nav-child');
  433. currentDom.animate({
  434. height: '0px'
  435. }, 240, function () {
  436. currentDom.css({
  437. height: "auto",
  438. });
  439. $(this).parent().removeClass("layui-nav-itemed");
  440. $(this).find('.layui-nav-itemed').removeClass("layui-nav-itemed");
  441. });
  442. }
  443. ele.height(0);
  444. ele.animate({
  445. height: heights + "px"
  446. }, 240, function () {
  447. ele.css({
  448. height: "auto"
  449. });
  450. });
  451. } else {
  452. $(this).parent().addClass("layui-nav-itemed");
  453. ele.animate({
  454. height: "0px"
  455. }, 240, function () {
  456. ele.css({
  457. height: "auto"
  458. });
  459. $(this).parent().removeClass("layui-nav-itemed");
  460. });
  461. }
  462. }
  463. })
  464. }
  465. /** 二 级 悬 浮 菜 单*/
  466. function isHoverMenu(b, option) {
  467. if (b) {
  468. var navItem = "#" + option.elem + ".pear-nav-mini .layui-nav-item";
  469. var navChildDl = navItem + " .layui-nav-child>dl";
  470. var navChildDd = navItem + " .layui-nav-child>dd";
  471. $(navItem + "," + navChildDd).mouseenter(function () {
  472. var _this = $(this);
  473. _this.siblings().find(".layui-nav-child")
  474. .removeClass("layui-nav-hover").css({
  475. left: 0,
  476. top: 0
  477. });
  478. _this.children(".layui-nav-child").addClass("layui-nav-hover");
  479. var height = $(window).height();
  480. var topLength = _this.offset().top;
  481. var thisHeight = _this.children(".layui-nav-child").height();
  482. if ((thisHeight + topLength) > height) {
  483. topLength = height - thisHeight - 10;
  484. }
  485. var left = _this.offset().left + 60;
  486. if (!_this.hasClass("layui-nav-item")) {
  487. left = _this.offset().left + _this.width();
  488. }
  489. _this.children(".layui-nav-child").offset({
  490. top: topLength,
  491. left: left
  492. });
  493. });
  494. $(navItem + "," + navChildDl).mouseleave(function () {
  495. var _this = $(this);
  496. _this.closest('.layui-nav-item')
  497. .find(".layui-nav-child")
  498. .removeClass("layui-nav-hover")
  499. .css({
  500. left: 0,
  501. top: 0
  502. });
  503. });
  504. } else {
  505. $("#" + option.elem + " .layui-nav-item").off('mouseenter').unbind('mouseleave');
  506. $("#" + option.elem + " dd").off('mouseenter').unbind('mouseleave');
  507. }
  508. }
  509. function rationalizeHeaderControlWidth(option) {
  510. var $headerControl = $("#" + option.control);
  511. var $nextEl = $headerControl.next();
  512. var rationalizeWidth;
  513. if ($nextEl.length) {
  514. rationalizeWidth = $nextEl.position().left - $headerControl.position().left;
  515. } else {
  516. rationalizeWidth = $headerControl.parent().innerWidth() - $headerControl.position().left;
  517. }
  518. if (option.controlWidth && rationalizeWidth >= option.controlWidth) {
  519. rationalizeWidth = option.controlWidth;
  520. }
  521. $("#" + option.control + " .control").css({ "width": rationalizeWidth, "transition": "width .15s" });
  522. }
  523. function rationalizeHeaderControlWidthAuto(option){
  524. $(window).on('resize', function () {
  525. rationalizeHeaderControlWidth(option);
  526. })
  527. $(document).ready(function () {
  528. rationalizeHeaderControlWidth(option);
  529. });
  530. }
  531. exports(MOD_NAME, new pearMenu());
  532. })