post.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. $(function() {
  2. Post.init();
  3. });
  4. const Post =
  5. {
  6. listURL: "",
  7. editURL: "",
  8. deleteURL: "",
  9. callback: "",
  10. code: "",
  11. bid: null,
  12. pid: null,
  13. uid: null,
  14. init: function() {
  15. const form = (
  16. document.getElementById("fPostView") ||
  17. document.getElementById("fPostWrite") ||
  18. document.getElementById("fPostEdit")
  19. );
  20. this.code = form.elements["code"].value;
  21. this.bid = form.elements["bid"].value;
  22. this.pid = form.elements["pid"].value;
  23. if(form.elements.hasOwnProperty("uid")) {
  24. this.uid = form.elements["uid"].value;
  25. }
  26. if(form.elements.hasOwnProperty("list_url")) {
  27. this.listURL = form.elements["list_url"].value;
  28. }
  29. if(form.elements.hasOwnProperty("edit_url")) {
  30. this.editURL = form.elements["edit_url"].value;
  31. }
  32. if(form.elements.hasOwnProperty("delete_url")) {
  33. this.deleteURL = form.elements["delete_url"].value;
  34. }
  35. this.callback = (this.listURL + "/" + String(this.pid));
  36. let captcha = document.querySelector('a[href="//captcha.org/captcha.html?laravel"]');
  37. if(captcha) {
  38. captcha.remove();
  39. }
  40. Post.setInitEditor();
  41. },
  42. // 첨부파일 입력란 아래에 파일 크기를 표시
  43. displayFileSize: function (object) {
  44. $(object).next().children().text(formatBytes(uploadFileSize(object)));
  45. },
  46. // 첨부한 파일의 크기 표시를 삭제
  47. removeFileSize: function (object) {
  48. $(object).next().children().text("0");
  49. },
  50. // tinyMCE 게시판 에디터로 커서 이동
  51. focusContent: function (id) {
  52. tinymce.execCommand('mceFocus', false, id);
  53. },
  54. // 입력 내용의 문자 통계 반환
  55. getStats: function (id) {
  56. let body = tinymce.get(id).getBody(), text = tinymce.trim(body.innerText || body.textContent);
  57. return {
  58. chars: text.length,
  59. words: text.split(/[\w\u2019\'-]+/).length
  60. };
  61. },
  62. // 금지 단어 확인
  63. filterSpamKeyword: function (subject, content) {
  64. let ret = {
  65. "subject": null,
  66. "content": null
  67. };
  68. $.ajax({
  69. headers: {'X-CSRF-TOKEN': CSRF},
  70. url: (BASE_URL + "/api/filterSpamKeyword"),
  71. type: "post",
  72. dataType: "json",
  73. async: false,
  74. cache: false,
  75. data: {subject: subject, content: content},
  76. success: function (res) {
  77. ret.subject = res.subject;
  78. ret.content = res.content;
  79. }
  80. });
  81. return ret;
  82. },
  83. // 등록/수정
  84. submit: function(e)
  85. {
  86. let form = document.getElementById(e.dataset.form);
  87. $(form).validate({
  88. onkeyup: false,
  89. onclick: false,
  90. onfocusout: false,
  91. showErrors: function (errorMap, errorList) {
  92. if (this.numberOfInvalids() && errorList.length > 0) {
  93. alert(errorList[0].message);
  94. $(errorList[0].element).focus();
  95. }
  96. },
  97. rules: {
  98. is_speaker: {number: true},
  99. is_notice: {number: true},
  100. is_secret: {number: true},
  101. category: {required: function(e) {
  102. return (document.getElementById("category") && !$("#isSpeaker").is("checked") && !$("#isNotice").is("checked") && e.dataset.categoryRequired === "1");
  103. }, number: true}, // 게시판 분류
  104. username: {required: "#username:enabled", minlength: 2, maxlength: 10},
  105. password: {required: "#password:enabled", minlength: 3, maxlength: 10},
  106. subject: {required: true},
  107. content: {"required_tinymce": true},
  108. captcha: {required: "#captcha:enabled"}, // Captcha 사용 여부
  109. // 게시판 Tag
  110. // submitHandler 처리
  111. // 게시판 Link
  112. // submitHandler 처리
  113. // 게시판 File
  114. // submitHandler 처리
  115. },
  116. messages: {
  117. is_speaker: {number: "전체공지 값은 숫자여야 합니다."},
  118. is_notice: {number: "공지 값은 숫자여야 합니다."},
  119. is_secret: {number: "비밀글 값은 숫자여야 합니다."},
  120. category: {required: "분류를 선택하세요.", number: "분류 값은 숫자여야 합니다."},
  121. username: {required: "이름을 입력하세요.", minlength: "이름을 두 글자 이상 입력하세요.", maxlength: "이름은 10자까지 입력 가능합니다."},
  122. password: {required: "비밀번호를 입력하세요.", minlength: "비밀번호는 3자 이상 입력하세요.", maxlength: "비밀번호는 10자까지 입력 가능합니다."},
  123. subject: {required: "제목을 입력하세요."},
  124. captcha: {required: "자동등록방지 문자를 입력하세요.", captchaKey: "자동등록방지 문자가 잘못되었습니다."},
  125. },
  126. submitHandler: function(form) {
  127. let subjectMinLength = Number(form.elements["subject_min_length"].value);
  128. let subjectMaxLength = Number(form.elements["subject_max_length"].value);
  129. let contentMinLength = Number(form.elements["content_min_length"].value);
  130. let contentMaxLength = Number(form.elements["content_max_length"].value);
  131. let uploadFileMaxSize = Number(form.elements["upload_file_max_size"].value);
  132. let inSubjectLength = Number(form.elements["subject"].value.length);
  133. let inContentLength = (tinymce.editors.length > 0 ? Number(Post.getStats("content").chars) : form.content.value.length);
  134. try
  135. {
  136. let error = function(e) {throw new Error(e);};
  137. // 제목, 내용 길이 확인
  138. if (subjectMinLength > 0 && inSubjectLength < subjectMinLength) {
  139. form.subject.focus();
  140. error("제목은 최소 " + subjectMinLength + "글자 이상 입력해야 합니다.");
  141. }else if (subjectMaxLength > 0 && inSubjectLength > subjectMaxLength) {
  142. form.subject.focus();
  143. error("제목은 최대 " + subjectMaxLength + "글자 이하 입력 가능합니다.");
  144. }
  145. if (contentMinLength > 0 && inContentLength < contentMinLength) {
  146. Post.focusContent("content");
  147. error("내용은 최소 " + contentMinLength + "글자 입력해야 합니다.");
  148. }else if (contentMaxLength > 0 && inContentLength > contentMaxLength) {
  149. Post.focusContent("content");
  150. error("내용은 최대 " + contentMaxLength + "글자 입력 가능합니다.");
  151. }
  152. let spamKeywords = Post.filterSpamKeyword(form.subject.value, form.content.value);
  153. if (spamKeywords.subject) {
  154. form.subject.focus();
  155. error("제목에 금지단어 ('" + spamKeywords.subject + "')가 포함 되어있습니다.");
  156. }
  157. if (spamKeywords.content) {
  158. form.content.focus();
  159. error("내용에 금지단어 ('" + spamKeywords.content + "')가 포함 되어있습니다.");
  160. }
  161. // Tag 개수 확인
  162. let tags = document.getElementById("tags");
  163. if(tags) {
  164. if(tags.value.split(',').length > 10) {
  165. alert("Tag 는 최대 10개 입력 가능합니다.");
  166. return false;
  167. }
  168. }
  169. // Link URL 형식인지 확인
  170. let links = form.getElementsByClassName("form-control-url");
  171. if(links.length > 0) {
  172. for(let j in links) {
  173. let link = links[j];
  174. if(link.value && !isValidURL(link.value)) {
  175. link.focus();
  176. error("URL 형식이 잘못되었습니다.");
  177. break;
  178. }
  179. }
  180. }
  181. // 첨부파일 크기 확인
  182. if(uploadFileMaxSize > 0) {
  183. let files = form.getElementsByClassName("form-control-file");
  184. let byte = (uploadFileMaxSize * 1024 * 1024);
  185. for(let i in files) {
  186. let file = files[i];
  187. if(file.value) {
  188. let size = uploadFileSize(file);
  189. if (size > byte) {
  190. file.value = null;
  191. Post.removeFileSize(file);
  192. error("첨부 가능한 파일의 최대 크기는 " + uploadFileMaxSize + "MB 입니다.");
  193. break;
  194. }
  195. }
  196. }
  197. }
  198. showLoading();
  199. return true;
  200. }catch(err) {
  201. alert(err.message);
  202. return false;
  203. }
  204. }
  205. });
  206. $(form).submit();
  207. },
  208. // 복사
  209. copy: function(e) {
  210. if (copyToClipboard(e.href)) {
  211. alert("게시글 주소가 복사 되었습니다.\n주소를 Ctrl + C 하여, 붙여 넣을 곳에 Ctrl + V 하세요.");
  212. }
  213. return false;
  214. },
  215. // 즐겨찾기
  216. bookmark: function(e)
  217. {
  218. const isActive = e.classList.contains("active");
  219. $.ajax({
  220. url: (this.callback + "/bookmark"),
  221. type: "post",
  222. cache: false,
  223. async: false,
  224. data: {bid: this.bid, pid: this.pid},
  225. dataType: "json",
  226. beforeSend: function (xhr) {
  227. if (!loginCheck()) {
  228. return xhr.abort();
  229. }
  230. const message = (isActive ? "즐겨찾기 해제 하시겠습니까?" : "즐겨찾기 등록 하시겠습니까?");
  231. if (!confirm(message)) {
  232. return false;
  233. }
  234. },
  235. success: function (res) {
  236. if (res.success) {
  237. if (!isActive) {
  238. alert("즐겨찾기 등록되었습니다.");
  239. e.classList.add("active");
  240. } else {
  241. alert("즐겨찾기 해제되었습니다.");
  242. e.classList.remove("active");
  243. }
  244. } else {
  245. alert(res.message || "처리 중 오류가 발생하였습니다. 관리자에게 문의하십시오.");
  246. }
  247. },
  248. error: function (xhr, status, err) {
  249. procErrorEvent(xhr, status, err);
  250. }
  251. });
  252. e.blur();
  253. },
  254. // 신고
  255. blame: function(e)
  256. {
  257. e.blur();
  258. if(!loginCheck()) {
  259. return false;
  260. }
  261. // 신고 접수 유효성
  262. $("#fPostBlame").validate({
  263. onkeyup: false,
  264. onclick: false,
  265. onfocusout: false,
  266. rules: {
  267. type: {required: true, contains: ['1', '2', '3', '4', '5', '6', '7', '8', '9']},
  268. reason: {required: true, normalizer: function (value) {return $.trim(value);}, maxlength: 1000}
  269. },
  270. messages: {
  271. type: {required: "신고 유형을 선택해주세요.", contains: "잘못된 요청입니다."},
  272. reason: {required: "신고 내용을 입력해주세요.", maxlength: "신고 내용은 {0}자까지 입력 가능합니다."}
  273. },
  274. showErrors: function (errorMap, errorList) {
  275. if (this.numberOfInvalids()) {
  276. alert(errorList[0].message);
  277. errorList[0].element.focus();
  278. }
  279. },
  280. submitHandler: function (form) {
  281. if (confirm("신고를 접수하시겠습니까?")) {
  282. let formData = new FormData(form);
  283. formData.append("bid", Post.bid);
  284. formData.append("pid", Post.pid);
  285. $.ajax({
  286. url: (Post.callback + "/blame"),
  287. type: "post",
  288. cache: false,
  289. async: false,
  290. contentType: false,
  291. processData: false,
  292. data: formData,
  293. dataType: "json",
  294. beforeSend: function (xhr) {
  295. if (!loginCheck()) {
  296. xhr.abort();
  297. }
  298. },
  299. success: function (res) {
  300. if (res.success) {
  301. alert("감사합니다. 신고가 접수되었습니다. 이용 규칙을 위반한 것으로 확인되면 게시글이 삭제됩니다.");
  302. } else {
  303. alert(res.message || "처리 중 오류가 발생하였습니다. 관리자에게 문의하십시오.");
  304. }
  305. },
  306. error: function (xhr, status, err) {
  307. procErrorEvent(xhr, status, err);
  308. },
  309. complete : function() {
  310. $("#postBlameModal").modal('hide');
  311. }
  312. });
  313. }
  314. }
  315. });
  316. },
  317. // 수정
  318. edit: function(e)
  319. {
  320. e.blur();
  321. let href = this.editURL;
  322. if(!this.uid) { // 권한 확인
  323. const passwd = prompt("게시글 비밀번호 확인이 필요합니다.\n비밀번호를 입력해주세요.");
  324. if(!passwd) {
  325. return false;
  326. }
  327. href += "?passwd=" + encodeURIComponent(passwd.trim());
  328. }else{
  329. if (!loginCheck()) {
  330. return false;
  331. }
  332. }
  333. location.href = href;
  334. },
  335. // 삭제
  336. delete: function(e)
  337. {
  338. e.blur();
  339. $.ajax({
  340. url: this.deleteURL,
  341. type: "delete",
  342. data: {bid: this.bid, pid: this.pid, _method: "delete"},
  343. dataType: "json",
  344. beforeSend: function (xhr) {
  345. if (!Post.uid) { // 권한 확인
  346. const passwd = prompt("게시글 비밀번호 확인이 필요합니다.\n비밀번호를 입력해주세요.");
  347. if (!passwd) {
  348. return false;
  349. }
  350. this.url += ("?passwd=" + encodeURIComponent(passwd.trim()));
  351. } else {
  352. if (!loginCheck()) {
  353. return xhr.abort();
  354. }
  355. }
  356. if (!confirm("게시글을 삭제하시겠습니까?")) {
  357. return false;
  358. }
  359. },
  360. success: function (res) {
  361. if (res.success) {
  362. alert("게시글이 삭제되었습니다.");
  363. location.replace(Post.listURL);
  364. } else {
  365. alert(res.message);
  366. }
  367. },
  368. error: function (xhr, status, err) {
  369. procErrorEvent(xhr, status, err);
  370. }
  371. });
  372. },
  373. // 인쇄
  374. print: function()
  375. {
  376. let $container = $("#boardView").clone();
  377. let cssText = "";
  378. let cssLink = "";
  379. let style = document.getElementsByTagName("style");
  380. let link = document.getElementsByTagName("link");
  381. for (let i in style) {
  382. if(typeof style[i].innerHTML !== "undefined") {
  383. cssText += style[i].innerHTML;
  384. }
  385. }
  386. for (let i in link) {
  387. if(typeof link[i].outerHTML !== "undefined") {
  388. cssLink += link[i].outerHTML;
  389. }
  390. }
  391. let popupWindow = popupCenter(null, "_blank", 900, 680);
  392. if (popupWindow.focus) {
  393. popupWindow.focus();
  394. }
  395. let printHtml = '<!DOCTYPE html>' +
  396. '<html lang="ko">' +
  397. '<head>' +
  398. cssLink +
  399. '<style>' + cssText + '</style>' +
  400. '</head>' +
  401. '<body>' +
  402. '<div id="boardView" class="container-fluid">' + $container.get(0).innerHTML + '</div>' +
  403. '</body>' +
  404. '</html>';
  405. popupWindow.document.write(printHtml);
  406. // 프린트 전
  407. popupWindow.onbeforeprint = function () {
  408. printHtml = popupWindow.document.body;
  409. printHtml.style.backgroundColor = "#fff";
  410. printHtml.style.padding = "0";
  411. printHtml.style.height = "initial";
  412. printHtml.style.width = "100%";
  413. printHtml.style.minWidth = "auto";
  414. printHtml.style.maxWidth = "initial";
  415. printHtml.parentNode.style.padding = "0";
  416. printHtml.parentNode.style.maxWidth = "initial";
  417. printHtml.getElementsByTagName("nav")[0].remove();
  418. printHtml.getElementsByTagName("blockquote")[0].style.border = "none";
  419. printHtml.getElementsByClassName("foot")[0].remove();
  420. popupWindow.document.body.innerHTML = printHtml.innerHTML;
  421. };
  422. // 프린트 후
  423. popupWindow.onafterprint = function () {
  424. popupWindow.document.body.innerHTML = "";
  425. popupWindow.document.write("");
  426. };
  427. popupWindow.document.close();
  428. popupWindow.focus();
  429. setTimeout(function () {
  430. popupWindow.print();
  431. popupWindow.close();
  432. }, 300);
  433. return false;
  434. },
  435. // 좋아요
  436. like: function(e)
  437. {
  438. e.blur();
  439. let bid = this.bid;
  440. let pid = this.pid;
  441. let type = e.value;
  442. $.ajax({
  443. url: (this.callback + "/like"),
  444. type: "post",
  445. cache: false,
  446. async: false,
  447. data: {bid: bid, pid: pid, type: type},
  448. dataType: "json",
  449. beforeSend: function (xhr) {
  450. if (!loginCheck()) {
  451. xhr.abort();
  452. }
  453. },
  454. success: function (res) {
  455. if (res.success) {
  456. Post.toggleLike(1, !Number(e.dataset.active));
  457. } else {
  458. alert(res.message || "처리 중 오류가 발생하였습니다. 관리자에게 문의하십시오.");
  459. }
  460. },
  461. error: function (xhr, status, err) {
  462. procErrorEvent(xhr, status, err);
  463. }
  464. });
  465. },
  466. // 싫어요
  467. dislike: function(e)
  468. {
  469. e.blur();
  470. let bid = this.bid;
  471. let pid = this.pid;
  472. let type = e.value;
  473. $.ajax({
  474. url: (this.callback + "/dislike"),
  475. type: "post",
  476. cache: false,
  477. async: false,
  478. data: {bid: bid, pid: pid, type: type},
  479. dataType: "json",
  480. beforeSend: function (xhr) {
  481. if (!loginCheck()) {
  482. xhr.abort();
  483. }
  484. },
  485. success: function (res) {
  486. if (res.success) {
  487. Post.toggleLike(2, !Number(e.dataset.active));
  488. } else {
  489. alert(res.message || "처리 중 오류가 발생하였습니다. 관리자에게 문의하십시오.");
  490. }
  491. },
  492. error: function (xhr, status, err) {
  493. procErrorEvent(xhr, status, err);
  494. }
  495. });
  496. },
  497. // 다운로드
  498. download: function (e)
  499. {
  500. let action = (this.callback + "/download");
  501. if(!this.uid) { // 권한 확인
  502. const passwd = prompt("게시글 비밀번호 확인이 필요합니다.\n비밀번호를 입력해주세요.");
  503. if(!passwd) {
  504. return false;
  505. }
  506. action += "?passwd=" + encodeURIComponent(passwd.trim());
  507. }else{
  508. if (!loginCheck()) {
  509. return false;
  510. }
  511. }
  512. let form = document.createElement("form");
  513. let inputHidden_1 = document.createElement("input");
  514. let inputHidden_2 = document.createElement("input");
  515. let inputHidden_3 = document.createElement("input");
  516. let inputHidden_4 = document.createElement("input");
  517. let iframe = document.createElement("iframe");
  518. iframe.setAttribute("name", "fr_an_post");
  519. iframe.setAttribute("width", "0");
  520. iframe.setAttribute("height", "0");
  521. iframe.setAttribute("hidden", "hidden");
  522. iframe.src = ("data:text/html;charset=utf-8," + encodeURI(""));
  523. form.method = "post";
  524. form.action = action;
  525. form.target = "fr_an_post";
  526. inputHidden_1.type = "hidden";
  527. inputHidden_1.name = "bid";
  528. inputHidden_1.value = this.bid;
  529. inputHidden_2.type = "hidden";
  530. inputHidden_2.name = "pid";
  531. inputHidden_2.value = this.pid;
  532. inputHidden_3.type = "hidden";
  533. inputHidden_3.name = "fid";
  534. inputHidden_3.value = e.dataset.fid;
  535. inputHidden_4.type = "hidden";
  536. inputHidden_4.name = "_token";
  537. inputHidden_4.value = CSRF;
  538. form.appendChild(inputHidden_1);
  539. form.appendChild(inputHidden_2);
  540. form.appendChild(inputHidden_3);
  541. form.appendChild(inputHidden_4);
  542. document.body.appendChild(iframe);
  543. document.body.appendChild(form);
  544. form.submit();
  545. return false;
  546. },
  547. // Link 이동
  548. link: function (e)
  549. {
  550. $.ajax({
  551. url: (this.callback + "/link"),
  552. type: "post",
  553. cache: false,
  554. async: false,
  555. data: {bid: this.bid, pid: this.pid, lid: e.dataset.lid},
  556. dataType: "json",
  557. success: function (res) {
  558. let a = document.createElement('a');
  559. a.href = res.href;
  560. a.target = "_blank";
  561. a.click();
  562. },
  563. error: function (xhr, status, err) {
  564. procErrorEvent(xhr, status, err);
  565. }
  566. });
  567. return false;
  568. },
  569. // 좋아요/싫어요 처리
  570. toggleLike: function(type, active) {
  571. let btnPostLike = document.getElementById("btnPostLike");
  572. let btnPostDisLike = document.getElementById("btnPostDislike");
  573. if(type === 1) {
  574. this.setLike(active);
  575. if(Number(btnPostDisLike.dataset.active)) {
  576. this.setDislike(false);
  577. }
  578. }else if(type === 2) {
  579. this.setDislike(active);
  580. if(Number(btnPostLike.dataset.active)) {
  581. this.setLike(false);
  582. }
  583. }
  584. },
  585. // 좋아요 갱신
  586. setLike: function(active) {
  587. let button = document.getElementById("btnPostLike");
  588. let rows = Number(button.dataset.rows);
  589. if (active) {
  590. rows = (rows + 1);
  591. button.innerHTML = '<i class="fas fa-thumbs-up"></i><span> ' + String(rows) + '</span>';
  592. button.dataset.active = "1";
  593. }else{
  594. rows = (rows > 0 ? rows - 1 : rows);
  595. button.innerHTML = '<i class="far fa-thumbs-up"></i><span> ' + String(rows) + '</span>';
  596. button.dataset.active = "0";
  597. }
  598. button.dataset.rows = rows;
  599. document.getElementById("txtPostLikeCnt").innerText = rows;
  600. },
  601. // 싫어요 갱신
  602. setDislike: function(active) {
  603. let button = document.getElementById("btnPostDislike");
  604. let rows = Number(button.dataset.rows);
  605. if (active) {
  606. rows = (rows + 1);
  607. button.innerHTML = '<i class="fas fa-thumbs-down"></i><span> ' + String(rows) + '</span>';
  608. button.dataset.active = "1";
  609. }else{
  610. rows = (rows > 0 ? rows - 1 : rows);
  611. button.innerHTML = '<i class="far fa-thumbs-down"></i><span> ' + String(rows) + '</span>';
  612. button.dataset.active = "0";
  613. }
  614. button.dataset.rows = rows;
  615. document.getElementById("txtPostDislikeCnt").innerText = rows;
  616. },
  617. // 게시글 QR 보기
  618. qrcode: function(e) {
  619. let $modalQRCode = $("#modalQRCode");
  620. $modalQRCode.find(".modal-header .modal-title").html(e.dataset.title);
  621. $modalQRCode.find(".modal-body").html('<br/><img src="https://chart.googleapis.com/chart?cht=qr&chld=H|2&chs=100&chl=' + encodeURIComponent(e.href) + '"/><br/><br/>QR Code를 스캔하시면 게시글을 확인하실 수 있습니다.');
  622. $modalQRCode.modal('toggle');
  623. return false;
  624. },
  625. // SNS 북 공유하기
  626. sns: function(e) {console.log(1);
  627. let linkURL = window.location.href;
  628. switch(e.dataset.target) {
  629. case "1":
  630. popupCenter( 'http://www.facebook.com/sharer.php?u=' + encodeURIComponent(linkURL), "Facebook share", 400, 500);
  631. break;
  632. case "2": // 트위터 공유하기
  633. let sendText = "Twitter share";
  634. popupCenter("https://twitter.com/intent/tweet?text=" + sendText + "&url=" + linkURL, "Twitter share", 550, 600);
  635. break;
  636. case "3": // 레딧 공유하기
  637. popupCenter("https://www.reddit.com/submit?url=" + encodeURIComponent(linkURL), "Reddit share", 700, 800);
  638. break;
  639. }
  640. },
  641. /*
  642. * 게시글 에디터 옵션 변경
  643. */
  644. setInitEditor: function () {
  645. if(tinyMCE.activeEditor) {
  646. let tinyMCEExtendSetting = {
  647. file_browser_url: (BASE_URL + "/board/" + this.code + "/uploader"),
  648. };
  649. tinymce.init(Object.assign(tinyMCE.activeEditor.settings, tinyMCEExtendSetting));
  650. }
  651. },
  652. };
  653. // 게시글 등록/수정 실행
  654. $(document).on("click", "#btnPostSubmit", function() {
  655. Post.submit(this);
  656. });
  657. // 파일 용량 확인
  658. $(document).on("change", "input.form-control-file", function() {
  659. Post.displayFileSize(this);
  660. });
  661. // 전체공지, 공지 둘중 하나만 체크
  662. $(document).on("change", "input#isSpeaker, input#isNotice", function() {
  663. let $all = $("#isSpeaker");
  664. let $one = $("#isNotice");
  665. if (this.id === "isNotice" && $all.is(":checked")) {
  666. $all.prop("checked", false);
  667. } else if (this.id === "isSpeaker" && $one.is(":checked")) {
  668. $one.prop("checked", false);
  669. }
  670. });
  671. // QR-CODE 보기
  672. $(document).on("click", "a#btnPostQRCode, a.btn-qr-code", function () {
  673. return Post.qrcode(this);
  674. });
  675. // 게시글 인쇄
  676. $(document).on("click", "a#btnPostPrint", function () {
  677. return Post.print(this);
  678. });
  679. // 게시글 주소 복사
  680. $(document).on("click", "a#btnPostCopy", function() {
  681. return Post.copy(this);
  682. });
  683. // 게시글 SNS 공유
  684. $(document).on("click", "li.btn-post-sns", function() {
  685. Post.sns(this);
  686. });
  687. // 게시글 즐겨찾기
  688. $(document).on("click", "#btnPostBookmark", function() {
  689. Post.bookmark(this);
  690. });
  691. // 게시글 신고
  692. $(document).on("click", "#btnPostBlame", function() {
  693. Post.blame(this);
  694. });
  695. // 게시글 수정
  696. $(document).on("click", "#btnPostEdit", function() {
  697. Post.edit(this);
  698. });
  699. // 게시글 삭제
  700. $(document).on("click", "#btnPostDelete", function() {
  701. Post.delete(this);
  702. });
  703. // 게시글 좋아요
  704. $(document).on("click", "#btnPostLike", function () {
  705. Post.like(this);
  706. });
  707. // 게시글 싫어요
  708. $(document).on("click", "#btnPostDislike", function () {
  709. Post.dislike(this);
  710. });
  711. // 게시글 다운로드
  712. $(document).on("click", "a.btn-file-download", function () {
  713. return Post.download(this);
  714. });
  715. // 게시글 Link 이동
  716. $(document).on("click", "a.btn-site-url", function () {
  717. return Post.link(this);
  718. });
  719. // 게시글 신고 모달 열리면 초기화
  720. $(document).on("show.bs.modal", "#postBlameModal", function(e) {
  721. let form = e.currentTarget.getElementsByTagName("form")[0];
  722. form.elements["type"].selectedIndex = 0;
  723. form.elements["reason"].value = "";
  724. if(!IS_USER) {
  725. return false;
  726. }
  727. });
  728. // 공지, 전체공지일 경우 문의 유형은 무시된다.
  729. $(document).on("change", "#isSpeaker, #isNotice", function () {
  730. document.getElementById("categoryBox").style.display = (this.checked ? "none" : "table-row");
  731. });