v1.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /**
  2. * @type {string[]}
  3. */
  4. const allMainNavbarItemNames = [];
  5. /**
  6. * @type {Map<string, any>}
  7. */
  8. const allMainNavbarItemMap = new Map();
  9. window.initPageMainNavbar = function(items)
  10. {
  11. if(!items) return;
  12. allMainNavbarItemNames.length = 0;
  13. allMainNavbarItemMap.clear();
  14. for(const item of items)
  15. {
  16. allMainNavbarItemNames.push(item['data-id']);
  17. allMainNavbarItemMap.set(item['data-id'], item);
  18. }
  19. };
  20. /**
  21. * Get current main navbar items data.
  22. *
  23. * @returns {Array<{name: string; order: number;}>}
  24. */
  25. function getCurrentMainNavbarItems()
  26. {
  27. const items = [];
  28. const $nav = $('#mainNavbar .nav');
  29. $nav.children().each(
  30. function(index, element)
  31. {
  32. const $elm = $(element);
  33. $a = $elm.find('a');
  34. const menuItem = {};
  35. menuItem.name = $a.attr('data-id'),
  36. menuItem.order = index * 5;
  37. if(typeof $elm.data('hidden') != 'undefined') menuItem.hidden = true;
  38. items.push(menuItem);
  39. }
  40. );
  41. return items;
  42. }
  43. /**
  44. * Generate main menu nav items to be added.
  45. *
  46. * @param {Cash} $item
  47. * @param {(name: string) => void} onClick
  48. * @returns {Array<{text: string; onClick: () => void;}>}
  49. */
  50. function generateAddMainNavbarItems($item, onClick)
  51. {
  52. const items = [];
  53. const allMainNavbarItemIDSet = new Set(allMainNavbarItemMap.keys());
  54. const curMainNavbarItems = getCurrentMainNavbarItems();
  55. for(const {name} of curMainNavbarItems)
  56. {
  57. allMainNavbarItemIDSet.delete(name);
  58. }
  59. if(allMainNavbarItemIDSet.size === 0) return items;
  60. for(const name of allMainNavbarItemIDSet)
  61. {
  62. const item = allMainNavbarItemMap.get(name);
  63. items.push(
  64. {
  65. text: item.text,
  66. onClick: () => {
  67. onClick(name),
  68. saveMainNavbarToServer($item, {onSuccess: () => loadCurrentPage('#mainNavbar')});
  69. }
  70. }
  71. );
  72. }
  73. return items;
  74. }
  75. /**
  76. * Checks whether the current navbar item can be hidden.
  77. *
  78. * @param {Cash} $item
  79. * @returns {boolean}
  80. */
  81. function canHideCurrentNavbar($item)
  82. {
  83. if($item.is('.active')) return false;
  84. const $navbarActiveItem = $('#navbar .nav .active');
  85. if($item.attr('href').includes($navbarActiveItem.attr('href'))) return false;
  86. return true;
  87. }
  88. window.handleMainNavbarContextmenu = function(event, element)
  89. {
  90. const $item = $(element);
  91. const $nav = $('#mainNavbar .nav');
  92. const isMoving = $nav.is('[z-use-sortable]');
  93. const hideDisabled = !canHideCurrentNavbar($item);
  94. const $li = $item.closest('li');
  95. const itemsToAdded = generateAddMainNavbarItems($item, (name) => {
  96. const item = allMainNavbarItemMap.get(name);
  97. const $a = $('<a></a>')
  98. .attr('href', item.url)
  99. .attr('data-id', item['data-id'])
  100. .attr('data-app', item['data-app'])
  101. .append(`<span class="text">${item.text}</span>`);
  102. if(item.badge)
  103. {
  104. $a.append(`<span class="${item.badge.class}">${item.badge.text}</span>`);
  105. }
  106. const $navItem = $('<li class="nav-item item"></li>');
  107. $navItem.append($a);
  108. $li.after($navItem);
  109. });
  110. const items = [
  111. isMoving
  112. ? {
  113. text: langData.save,
  114. onClick: () => {
  115. $item.closest('.nav').zui().destroy();
  116. saveMainNavbarToServer($item);
  117. }
  118. }
  119. : {
  120. text: langData.sort,
  121. onClick: () => {
  122. const sortable = new zui.Sortable(
  123. '#mainNavbar .nav',
  124. {
  125. animation: 150,
  126. ghostClass: 'bg-primary-pale',
  127. onSort: () => {
  128. saveMainNavbarToServer($item);
  129. }
  130. }
  131. );
  132. }
  133. },
  134. {
  135. text: langData.hide,
  136. disabled: hideDisabled,
  137. onClick: hideDisabled
  138. ? null
  139. : () => {
  140. $li.hide().attr('data-hidden', '1');
  141. saveMainNavbarToServer($item);
  142. }
  143. },
  144. itemsToAdded.length === 0
  145. ? {
  146. text: langData.add,
  147. disabled: true,
  148. }
  149. : {
  150. text: langData.add,
  151. items: itemsToAdded,
  152. },
  153. {
  154. text: langData.restore,
  155. onClick: () => {
  156. restoreMainNavbarToServer($item, {
  157. onSuccess() {
  158. loadCurrentPage('#mainNavbar');
  159. }
  160. });
  161. }
  162. }
  163. ];
  164. if(window.customNavbarContextMenu) window.customNavbarContextMenu.hide();
  165. window.customNavbarContextMenu = zui.ContextMenu.show(
  166. {
  167. element: $item[0],
  168. placement: 'bottom-start',
  169. items: items,
  170. event: event,
  171. onClickItem: (info) => info.event.preventDefault(),
  172. onHide: () => window.customNavbarContextMenu = null,
  173. $optionsFromDataset: false,
  174. }
  175. );
  176. event.preventDefault();
  177. }
  178. function saveMainNavbarToServer($item, options = {})
  179. {
  180. const items = getCurrentMainNavbarItems();
  181. const menu = $item.data('group');
  182. const url = $.createLink('custom', 'ajaxSetMenu');
  183. $.ajaxSubmit({url, data: {menu, items: JSON.stringify(items)}, ...options});
  184. }
  185. function restoreMainNavbarToServer($item, options = {})
  186. {
  187. const url = $.createLink('custom', 'ajaxRestoreMenu');
  188. const menu = $item.data('group');
  189. $.ajaxSubmit({url, data: {menu}, ...options});
  190. }