Guest User

Untitled

a guest
Mar 3rd, 2018
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.39 KB | None | 0 0
  1. /* global $ store api moment */
  2. 'use strict';
  3.  
  4. const noteful = (function () {
  5.  
  6. function showSuccessMessage(message) {
  7. const el = $('.js-success-message');
  8. el.text(message).show();
  9. setTimeout(() => el.fadeOut('slow'), 3000);
  10. }
  11.  
  12. function showFailureMessage(message) {
  13. const el = $('.js-error-message');
  14. el.text(message).show();
  15. setTimeout(() => el.fadeOut('slow'), 3000);
  16. }
  17.  
  18. function handleErrors(err) {
  19. if (err.status === 401) {
  20. store.authorized = false;
  21. noteful.render();
  22. }
  23. showFailureMessage(err.responseJSON.message);
  24. }
  25.  
  26. function render() {
  27.  
  28. $('.signup-login').toggle(!store.authorized);
  29.  
  30. const notesList = generateNotesList(store.notes, store.currentNote);
  31. $('.js-notes-list').html(notesList);
  32.  
  33. const folderList = generateFolderList(store.folders, store.currentQuery);
  34. $('.js-folders-list').html(folderList);
  35.  
  36. const folderSelect = generateFolderSelect(store.folders);
  37. $('.js-note-folder-entry').html(folderSelect);
  38.  
  39. const tagsList = generateTagsList(store.tags, store.currentQuery);
  40. $('.js-tags-list').html(tagsList);
  41.  
  42. const tagsSelect = generateTagsSelect(store.tags);
  43. $('.js-note-tags-entry').html(tagsSelect);
  44.  
  45. const editForm = $('.js-note-edit-form');
  46. editForm.find('.js-note-title-entry').val(store.currentNote.title);
  47. editForm.find('.js-note-content-entry').val(store.currentNote.content);
  48. editForm.find('.js-note-folder-entry').val(store.currentNote.folderId);
  49.  
  50. editForm.find('.js-note-tags-entry').val(() => {
  51. if (store.currentNote.tags) {
  52. return store.currentNote.tags.map(tag => tag.id);
  53. }
  54. });
  55. }
  56.  
  57. /**
  58. * GENERATE HTML FUNCTIONS
  59. */
  60. function generateNotesList(list, currNote) {
  61. const listItems = list.map(item => `
  62. <li data-id="${item.id}" class="js-note-element ${currNote.id === item.id ? 'active' : ''}">
  63. <a href="#" class="name js-note-link">${item.title}</a>
  64. <button class="removeBtn js-note-delete-button">X</button>
  65. <div class="metadata">
  66. <div class="date">${moment(item.created).calendar()}</div>
  67. <div class="tags">${getTagsCommaSeparated(item.tags)}</div>
  68. </div>
  69. </li>`);
  70. return listItems.join('');
  71. }
  72.  
  73. function generateFolderList(list, currQuery) {
  74. const showAllItem = `
  75. <li data-id="" class="js-folder-item ${!currQuery.folderId ? 'active' : ''}">
  76. <a href="#" class="name js-folder-link">All</a>
  77. </li>`;
  78.  
  79. const listItems = list.map(item => `
  80. <li data-id="${item.id}" class="js-folder-item ${currQuery.folderId === item.id ? 'active' : ''}">
  81. <a href="#" class="name js-folder-link">${item.name}</a>
  82. <button class="removeBtn js-folder-delete">X</button>
  83. </li>`);
  84.  
  85. return [showAllItem, ...listItems].join('');
  86. }
  87.  
  88. function generateFolderSelect(list) {
  89. const notes = list.map(item => `<option value="${item.id}">${item.name}</option>`);
  90. return '<option value="">Select Folder:</option>' + notes.join('');
  91. }
  92.  
  93. function generateTagsList(list, currQuery) {
  94. const showAllItem = `
  95. <li data-id="" class="js-tag-item ${!currQuery.tagId ? 'active' : ''}">
  96. <a href="#" class="name js-tag-link">All</a>
  97. </li>`;
  98.  
  99. const listItems = list.map(item => `
  100. <li data-id="${item.id}" class="js-tag-item ${currQuery.tagId === item.id ? 'active' : ''}">
  101. <a href="#" class="name js-tag-link">${item.name}</a>
  102. <button class="removeBtn js-tag-delete">X</button>
  103. </li>`);
  104. return [showAllItem, ...listItems].join('');
  105. }
  106.  
  107. function generateTagsSelect(list) {
  108. const notes = list.map(item => `<option value="${item.id}">${item.name}</option>`);
  109. return notes.join('');
  110. }
  111.  
  112. /**
  113. * HELPERS
  114. */
  115. function getNoteIdFromElement(item) {
  116. const id = $(item).closest('.js-note-element').data('id');
  117. return id;
  118. }
  119.  
  120. function getFolderIdFromElement(item) {
  121. const id = $(item).closest('.js-folder-item').data('id');
  122. return id;
  123. }
  124.  
  125. function getTagIdFromElement(item) {
  126. const id = $(item).closest('.js-tag-item').data('id');
  127. return id;
  128. }
  129.  
  130. function getTagsCommaSeparated(tags) {
  131. return tags ? tags.map(tag => tag.name).join(', ') : '';
  132. }
  133.  
  134. /**
  135. * NOTES EVENT LISTENERS AND HANDLERS
  136. */
  137. function handleNoteItemClick() {
  138. $('.js-notes-list').on('click', '.js-note-link', event => {
  139. event.preventDefault();
  140.  
  141. const noteId = getNoteIdFromElement(event.currentTarget);
  142.  
  143. api.details(`/v3/notes/${noteId}`)
  144. .then((response) => {
  145. store.currentNote = response;
  146. render();
  147. })
  148. .catch(handleErrors);
  149. });
  150. }
  151.  
  152. function handleNoteSearchSubmit() {
  153. $('.js-notes-search-form').on('submit', event => {
  154. event.preventDefault();
  155.  
  156. store.currentQuery.searchTerm = $(event.currentTarget).find('input').val();
  157.  
  158. api.search('/v3/notes', store.currentQuery)
  159. .then(response => {
  160. store.notes = response;
  161. render();
  162. })
  163. .catch(handleErrors);
  164. });
  165. }
  166.  
  167.  
  168. function handleNoteFormSubmit() {
  169. $('.js-note-edit-form').on('submit', function (event) {
  170. event.preventDefault();
  171.  
  172. const editForm = $(event.currentTarget);
  173. const noteObj = {
  174. id: store.currentNote.id,
  175. title: editForm.find('.js-note-title-entry').val(),
  176. content: editForm.find('.js-note-content-entry').val(),
  177. folderId: editForm.find('.js-note-folder-entry').val(),
  178. tags: editForm.find('.js-note-tags-entry').val()
  179. };
  180.  
  181. if (store.currentNote.id) {
  182. api.update(`/v3/notes/${noteObj.id}`, noteObj)
  183. .then(updateResponse => {
  184. store.currentNote = updateResponse;
  185. return api.search('/v3/notes', store.currentQuery);
  186. })
  187. .then(response => {
  188. store.notes = response;
  189. render();
  190. })
  191. .catch(handleErrors);
  192. } else {
  193. api.create('/v3/notes', noteObj)
  194. .then(createResponse => {
  195. store.currentNote = createResponse;
  196. return api.search('/v3/notes', store.currentQuery);
  197. })
  198. .then(response => {
  199. store.notes = response;
  200. render();
  201. })
  202. .catch(handleErrors);
  203. }
  204. });
  205. }
  206.  
  207. function handleNoteStartNewSubmit() {
  208. $('.js-start-new-note-form').on('submit', event => {
  209. event.preventDefault();
  210. store.currentNote = {};
  211. render();
  212. });
  213. }
  214.  
  215. function handleNoteDeleteClick() {
  216. $('.js-notes-list').on('click', '.js-note-delete-button', event => {
  217. event.preventDefault();
  218. const noteId = getNoteIdFromElement(event.currentTarget);
  219.  
  220. api.remove(`/v3/notes/${noteId}`)
  221. .then(() => {
  222. if (noteId === store.currentNote.id) {
  223. store.currentNote = {};
  224. }
  225. return api.search('/v3/notes', store.currentQuery);
  226. })
  227. .then(response => {
  228. store.notes = response;
  229. render();
  230. })
  231. .catch(handleErrors);
  232. });
  233. }
  234.  
  235. /**
  236. * FOLDERS EVENT LISTENERS AND HANDLERS
  237. */
  238. function handleFolderClick() {
  239. $('.js-folders-list').on('click', '.js-folder-link', event => {
  240. event.preventDefault();
  241.  
  242. const folderId = getFolderIdFromElement(event.currentTarget);
  243. store.currentQuery.folderId = folderId;
  244. if (folderId !== store.currentNote.folderId) {
  245. store.currentNote = {};
  246. }
  247.  
  248. api.search('/v3/notes', store.currentQuery)
  249. .then(response => {
  250. store.notes = response;
  251. render();
  252. })
  253. .catch(handleErrors);
  254. });
  255. }
  256.  
  257. function handleNewFolderSubmit() {
  258. $('.js-new-folder-form').on('submit', event => {
  259. event.preventDefault();
  260.  
  261. const newFolderName = $('.js-new-folder-entry').val();
  262. api.create('/v3/folders', { name: newFolderName })
  263. .then(() => {
  264. $('.js-new-folder-entry').val();
  265. return api.search('/v3/folders');
  266. })
  267. .then(response => {
  268. store.folders = response;
  269. render();
  270. })
  271. .catch(handleErrors);
  272. });
  273. }
  274.  
  275. function handleFolderDeleteClick() {
  276. $('.js-folders-list').on('click', '.js-folder-delete', event => {
  277. event.preventDefault();
  278. const folderId = getFolderIdFromElement(event.currentTarget);
  279.  
  280. if (folderId === store.currentQuery.folderId) {
  281. store.currentQuery.folderId = null;
  282. }
  283. if (folderId === store.currentNote.folderId) {
  284. store.currentNote = {};
  285. }
  286.  
  287. api.remove(`/v3/folders/${folderId}`)
  288. .then(() => {
  289. const notesPromise = api.search('/v3/notes');
  290. const folderPromise = api.search('/v3/folders');
  291. return Promise.all([notesPromise, folderPromise]);
  292. })
  293. .then(([notes, folders]) => {
  294. store.notes = notes;
  295. store.folders = folders;
  296. render();
  297. })
  298. .catch(handleErrors);
  299. });
  300. }
  301.  
  302. /**
  303. * TAGS EVENT LISTENERS AND HANDLERS
  304. */
  305. function handleTagClick() {
  306. $('.js-tags-list').on('click', '.js-tag-link', event => {
  307. event.preventDefault();
  308.  
  309. const tagId = getTagIdFromElement(event.currentTarget);
  310. store.currentQuery.tagId = tagId;
  311.  
  312. store.currentNote = {};
  313.  
  314. api.search('/v3/notes', store.currentQuery)
  315. .then(response => {
  316. store.notes = response;
  317. render();
  318. })
  319. .catch(handleErrors);
  320. });
  321. }
  322.  
  323. function handleNewTagSubmit() {
  324. $('.js-new-tag-form').on('submit', event => {
  325. event.preventDefault();
  326.  
  327. const newTagName = $('.js-new-tag-entry').val();
  328. api.create('/v3/tags', { name: newTagName })
  329. .then(() => {
  330. return api.search('/v3/tags');
  331. })
  332. .then(response => {
  333. store.tags = response;
  334. render();
  335. })
  336. .catch(handleErrors);
  337. });
  338. }
  339.  
  340. function handleTagDeleteClick() {
  341. $('.js-tags-list').on('click', '.js-tag-delete', event => {
  342. event.preventDefault();
  343. const tagId = getTagIdFromElement(event.currentTarget);
  344.  
  345. if (tagId === store.currentQuery.tagId) {
  346. store.currentQuery.tagId = null;
  347. }
  348.  
  349. store.currentNote = {};
  350.  
  351. api.remove(`/v3/tags/${tagId}`)
  352. .then(() => {
  353. return api.search('/v3/tags');
  354. })
  355. .then(response => {
  356. store.tags = response;
  357. return api.search('/v3/notes', store.currentQuery);
  358. })
  359. .then(response => {
  360. store.notes = response;
  361. render();
  362. })
  363. .catch(handleErrors);
  364. });
  365. }
  366.  
  367. function handleSignupSubmit() {
  368. $('.js-signup-from').on('submit', event => {
  369. event.preventDefault();
  370.  
  371. const signupForm = $(event.currentTarget);
  372. const newUser = {
  373. fullname: signupForm.find('.js-fullname-entry').val(),
  374. username: signupForm.find('.js-username-entry').val(),
  375. password: signupForm.find('.js-password-entry').val()
  376. };
  377.  
  378. api.create('/v3/users', newUser)
  379. .then(response => {
  380. signupForm[0].reset();
  381. showSuccessMessage(`Thank you, ${response.fullname || response.username} for signing up!`);
  382. })
  383. .catch(handleErrors);
  384. });
  385. }
  386.  
  387. function handleLoginSubmit() {
  388. $('.js-login-form').on('submit', event => {
  389. event.preventDefault();
  390.  
  391. const loginForm = $(event.currentTarget);
  392. const loginUser = {
  393. username: loginForm.find('.js-username-entry').val(),
  394. password: loginForm.find('.js-password-entry').val()
  395. };
  396.  
  397. api.create('/v3/login', loginUser)
  398. .then(response => {
  399. store.authorized = true;
  400. loginForm[0].reset();
  401.  
  402. store.currentUser = response;
  403.  
  404. return Promise.all([
  405. api.search('/v3/notes'),
  406. api.search('/v3/folders'),
  407. api.search('/v3/tags')
  408. ]);
  409. })
  410. .then(([notes, folders, tags]) => {
  411. store.notes = notes;
  412. store.folders = folders;
  413. store.tags = tags;
  414. render();
  415. })
  416. .catch(handleErrors);
  417. });
  418. }
  419.  
  420. function bindEventListeners() {
  421. handleNoteItemClick();
  422. handleNoteSearchSubmit();
  423.  
  424. handleNoteFormSubmit();
  425. handleNoteStartNewSubmit();
  426. handleNoteDeleteClick();
  427.  
  428. handleFolderClick();
  429. handleNewFolderSubmit();
  430. handleFolderDeleteClick();
  431. handleTagClick();
  432. handleNewTagSubmit();
  433. handleTagDeleteClick();
  434.  
  435. handleSignupSubmit();
  436. handleLoginSubmit();
  437. }
  438.  
  439. // This object contains the only exposed methods from this module:
  440. return {
  441. render: render,
  442. bindEventListeners: bindEventListeners,
  443. };
  444.  
  445. }());
Add Comment
Please, Sign In to add comment