site.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
  2. // for details on configuring this project to bundle and minify static web assets.
  3. // Write your JavaScript code.
  4. $(function () {
  5. // 사이드 바 토글 유지
  6. aside.applyInitialMode();
  7. // 사이드바 스크롤 위치 복원
  8. const savedAsideScroll = sessionStorage.getItem("aside-scroll");
  9. if (savedAsideScroll) {
  10. document.getElementById("aside").scrollTop = parseInt(savedAsideScroll);
  11. }
  12. // 메인 콘텐츠 스크롤 위치 복원
  13. const savedMainScroll = sessionStorage.getItem("main-scroll");
  14. if (savedMainScroll) {
  15. document.getElementById("main").scrollTop = parseInt(savedMainScroll);
  16. }
  17. });
  18. // 페이지 이동 전 스크롤 위치 저장
  19. window.addEventListener("beforeunload", function () {
  20. sessionStorage.setItem("aside-scroll", document.getElementById("aside").scrollTop);
  21. sessionStorage.setItem("main-scroll", document.getElementById("main").scrollTop);
  22. });
  23. // 좌측 메뉴 처리
  24. // 모드: "expanded" (기본 펼침) | "collapsed" (아이콘만, 데스크탑) | "hidden" (모바일 완전 숨김)
  25. class Aside {
  26. constructor() {
  27. this.body = document.body;
  28. this.aside = document.getElementById("aside");
  29. this.btnAsideToggle = document.getElementById("btnAsideToggle");
  30. }
  31. isMobile() {
  32. return window.innerWidth <= 768;
  33. }
  34. getStoredMode() {
  35. let mode = getCookie("aside-mode");
  36. if (mode === "collapsed" || mode === "expanded" || mode === "hidden") {
  37. return mode;
  38. }
  39. return null;
  40. }
  41. applyMode(mode) {
  42. this.body.classList.remove("collapsed-aside", "hidden-aside");
  43. if (mode === "collapsed") {
  44. this.body.classList.add("collapsed-aside");
  45. this.setIcon(true);
  46. } else if (mode === "hidden") {
  47. this.body.classList.add("hidden-aside");
  48. this.setIcon(true);
  49. } else {
  50. this.setIcon(false);
  51. }
  52. }
  53. applyInitialMode() {
  54. const stored = this.getStoredMode();
  55. if (this.isMobile()) {
  56. this.applyMode("hidden");
  57. return;
  58. }
  59. if (stored === "collapsed") {
  60. this.applyMode("collapsed");
  61. } else if (stored === "hidden") {
  62. this.applyMode("collapsed");
  63. setCookie("aside-mode", "collapsed", 7);
  64. } else {
  65. this.applyMode("expanded");
  66. }
  67. }
  68. toggleAside() {
  69. if (this.isMobile()) {
  70. const hidden = this.body.classList.contains("hidden-aside");
  71. const next = hidden ? "expanded" : "hidden";
  72. this.applyMode(next);
  73. setCookie("aside-mode", next, 7);
  74. } else {
  75. const collapsed = this.body.classList.contains("collapsed-aside");
  76. const next = collapsed ? "expanded" : "collapsed";
  77. this.applyMode(next);
  78. setCookie("aside-mode", next, 7);
  79. }
  80. }
  81. setIcon(pointRight) {
  82. const icon = this.btnAsideToggle.querySelector("i");
  83. if (!icon) {
  84. return;
  85. }
  86. if (pointRight) {
  87. icon.classList.remove("bi-arrow-left");
  88. icon.classList.add("bi-arrow-right");
  89. } else {
  90. icon.classList.remove("bi-arrow-right");
  91. icon.classList.add("bi-arrow-left");
  92. }
  93. }
  94. expandFromCollapsed() {
  95. if (this.body.classList.contains("collapsed-aside")) {
  96. this.applyMode("expanded");
  97. setCookie("aside-mode", "expanded", 7);
  98. }
  99. }
  100. }
  101. const aside = new Aside();
  102. document.getElementById("btnAsideToggle").addEventListener("click", () => aside.toggleAside());
  103. // collapsed 상태에서 자식 있는 부모 메뉴 클릭 시 자동 expand
  104. document.querySelectorAll("#aside .nav-link[data-bs-toggle='collapse']").forEach(el => {
  105. el.addEventListener("click", function (e) {
  106. if (document.body.classList.contains("collapsed-aside")) {
  107. e.preventDefault();
  108. e.stopPropagation();
  109. aside.expandFromCollapsed();
  110. }
  111. }, true);
  112. });
  113. window.addEventListener("resize", function () {
  114. if (aside.isMobile()) {
  115. if (!document.body.classList.contains("hidden-aside")) {
  116. aside.applyMode("hidden");
  117. }
  118. } else {
  119. if (document.body.classList.contains("hidden-aside")) {
  120. const stored = aside.getStoredMode();
  121. aside.applyMode(stored === "collapsed" ? "collapsed" : "expanded");
  122. }
  123. }
  124. });
  125. // 메뉴 토글 유지
  126. document.querySelectorAll(".collapse").forEach(e => {
  127. const collapseID = e.id;
  128. const collapseState = getCookie(collapseID);
  129. const instance = bootstrap.Collapse.getOrCreateInstance(e, {
  130. toggle: false
  131. });
  132. if (collapseState === "open") {
  133. instance.show();
  134. } else {
  135. instance.hide();
  136. }
  137. e.addEventListener("show.bs.collapse", () => {
  138. setCookie(collapseID, "open", 7);
  139. });
  140. e.addEventListener("hide.bs.collapse", () => {
  141. setCookie(collapseID, "closed", 7);
  142. });
  143. });
  144. // 드롭박스 적용
  145. const dropdownList = [...document.querySelectorAll('.dropdown-toggle')].map(e => new bootstrap.Dropdown(e));
  146. function GetCheckedBoxIDs() {
  147. return Array.from(document.querySelectorAll('input[type="checkbox"].list-check-box:checked')).map(c => c.value);
  148. }
  149. // 목록 버튼상자
  150. class ActionButtons {
  151. constructor() {
  152. this.form = document.getElementById("fAdminList");
  153. }
  154. validate() {
  155. let checked = $("input:checkbox.list-check-box:checked");
  156. if (checked.length < 1) {
  157. alert("항목을 하나 이상 선택하세요.");
  158. return false;
  159. }
  160. return true;
  161. }
  162. checkout(e, action)
  163. {
  164. let handler = "";
  165. switch (action) {
  166. case "Restore":
  167. handler = "?handler=Restore";
  168. break;
  169. case "Delete":
  170. handler = "?handler=Delete";
  171. break;
  172. case "Update":
  173. handler = "?handler=Update";
  174. break;
  175. }
  176. if (handler) {
  177. this.form.action = handler;
  178. }
  179. this.form.submit();
  180. }
  181. Update(e) {
  182. if (!this.validate()) {
  183. return false;
  184. }
  185. if (confirm("선택한 항목을 정말 수정 하시겠습니까?")) {
  186. this.checkout(e, "Update");
  187. }
  188. }
  189. Delete(e) {
  190. let ids = GetCheckedBoxIDs();
  191. if (ids.length > 1) {
  192. if (confirm(`${ids.length}건의 항목을 정말 삭제 하시겠습니까?`)) {
  193. if (!this.validate()) {
  194. return false;
  195. }
  196. }
  197. } else {
  198. if (!confirm("선택한 항목을 정말 삭제 하시겠습니까?")) {
  199. return false;
  200. }
  201. let id = e.target.dataset.id;
  202. if (id) {
  203. this.form.elements[`ids_${id}`].checked = true;
  204. }
  205. }
  206. setTimeout(() => this.checkout(e, "Delete"), 100);
  207. }
  208. Restore(e) {
  209. if (!this.validate()) {
  210. return false;
  211. }
  212. if (confirm("선택한 항목을 정말 복원 하시겠습니까?")) {
  213. this.checkout(e, "Restore");
  214. }
  215. }
  216. checkedAll(e) {
  217. let chk = document.getElementsByClassName("list-check-box");
  218. for (let i = 0; i < chk.length; i++) {
  219. let targetFormName = (e.target.getAttribute("form") || e.target.form.id);
  220. let chkFormName = (chk[i].getAttribute("form") || chk[i].form.id);
  221. if (targetFormName == chkFormName) {
  222. chk[i].checked = e.target.checked;
  223. }
  224. }
  225. this.toggleDisabled();
  226. }
  227. toggleDisabled() {
  228. let checked = $("input:checkbox.list-check-box:checked");
  229. if (checked.length > 0) {
  230. $('button[form="fAdminList"]').prop("disabled", false);
  231. } else {
  232. $('button[form="fAdminList"]').prop("disabled", true);
  233. }
  234. }
  235. }
  236. const actionButtons = new ActionButtons();
  237. $(document).on("click", "#btnListUpdate", (e) => actionButtons.Update(e));
  238. $(document).on("click", "#btnListDelete", (e) => actionButtons.Delete(e));
  239. $(document).on("click", "#btnListRestore", (e) => actionButtons.Restore(e));
  240. $(document).on("click", "#btnListExecute", (e) => actionButtons.Execute(e));
  241. $(document).on("click", ".btn-row-delete", (e) => actionButtons.Delete(e));
  242. $(document).on("click", "#checkedAll", (e) => actionButtons.checkedAll(e));
  243. $(document).on("change", "input.list-check-box", actionButtons.toggleDisabled);