comments.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /// <reference path="../../node_modules/@types/jquery/index.d.ts"/>
  2. namespace Comments {
  3. export class Controller {
  4. public loadUrl;
  5. public postEndpointUrl;
  6. private comments: CommentsContainer = new CommentsContainer;
  7. private form: CommentForm;
  8. private renderedCount = 0;
  9. public constructor() {
  10. let showAll = $('.comments__show-all');
  11. this.renderedCount = showAll.parent().find('.comments__comment').length;
  12. this.loadUrl = showAll.data('load-url');
  13. showAll.on('click', this.loadComments.bind(this));
  14. $('.comments__add-popup-close').click(function (e) {
  15. e.preventDefault();
  16. $('.comments__add-popup').hide();
  17. $('.comments__add-back-log').hide();
  18. });
  19. this.form = new CommentForm(this);
  20. }
  21. public loadComments() {
  22. $.ajax({
  23. url: this.loadUrl,
  24. dataType: 'json'
  25. }).done((function (data) {
  26. let $button = $('.comments__show-all');
  27. for (let i = 0; i < data.length; i++) {
  28. if (data.hasOwnProperty(i) && !this.comments.hasId(data[i].id)) {
  29. let comment = new Comment(data[i]);
  30. this.comments.push(comment);
  31. comment.rendered.insertBefore($button);
  32. }
  33. }
  34. $button.remove();
  35. }).bind(this));
  36. }
  37. public pushComments(data) {
  38. for (let i = 0; i < data.length; i++) {
  39. if (data.hasOwnProperty(i)) {
  40. let comment = new Comment(data[i]);
  41. this.comments.push(comment);
  42. }
  43. }
  44. }
  45. public addComment(data) {
  46. let comment = new Comment(data);
  47. this.comments.push(comment);
  48. if (data.answeredTo)
  49. comment.rendered.insertAfter($('.comments').find('[data-comment-id=' + data.answerTo + ']'));
  50. else
  51. comment.rendered.insertBefore($('.comments__show-all'));
  52. }
  53. }
  54. class CommentsContainer {
  55. [index: number]: Comment;
  56. push(...args) {
  57. return Array.prototype.push.apply(this, args);
  58. }
  59. hasId(id) {
  60. let list = Object.keys(this);
  61. for (let i in list) {
  62. if (this.hasOwnProperty(i)) {
  63. if (this[i].id === id) {
  64. return true;
  65. }
  66. }
  67. }
  68. return false;
  69. }
  70. }
  71. class CommentForm {
  72. private owner;
  73. private form: JQuery;
  74. private formData;
  75. constructor(owner: Controller) {
  76. this.owner = owner;
  77. $('.comments__add-link').on('click', this.onAddClick.bind(this));
  78. $('.comments').on('click', '.comments__comment-reply', this.onAddClick.bind(this));
  79. this.form = $('.comments__add-popup-form');
  80. this.form.on('submit', this.submitFrom.bind(this));
  81. this.owner.postEndpointUrl = this.form.attr('action');
  82. this.formData = {};
  83. }
  84. private onAddClick(event) {
  85. event.preventDefault();
  86. $('.comments__add-error').remove();
  87. $('.comments__add-popup').show();
  88. $('.comments__add-back-log').show();
  89. let target = $(event.target);
  90. let targetId = 0;
  91. if (target.hasClass('comments__comment-reply')) {
  92. targetId = target.parents('.comments__comment').data('comment-id');
  93. }
  94. this.formData = {answerTo: targetId};
  95. }
  96. private isRulesAccepted() {
  97. return $('#acceptRules').is(':checked');
  98. }
  99. private submitFrom(e) {
  100. e.preventDefault();
  101. $('.comments__add-error').remove();
  102. if (!this.isRulesAccepted()) {
  103. this.form.prepend($('<p class="comments__add-error">Необходимо дать согласие на обработку персональных данных.</p>'));
  104. return false;
  105. }
  106. let data = this.form.serializeArray();
  107. for (let i in data) {
  108. if (data.hasOwnProperty(i)) {
  109. this.formData[data[i].name] = data[i].value;
  110. }
  111. }
  112. console.dir({UserComments: this.formData});
  113. $.ajax({
  114. url: this.owner.postEndpointUrl,
  115. data: {UserComments: this.formData},
  116. dataType: 'json',
  117. type: 'post'
  118. }).done((function (data) {
  119. console.dir(data);
  120. if (data.errors) {
  121. for (let fieldName in data.errors) {
  122. if (data.errors.hasOwnProperty(fieldName))
  123. $('<span class="comments__add-error">' + data.errors[fieldName][0] + '</span>').insertAfter(this.form.find('[name=' + fieldName + ']'));
  124. }
  125. } else {
  126. //this.form.parent().find('.comments__add-popup-close').click();
  127. this.form.html('<p>Ваш комментарий успешно отправлен. После одобрения модератором он появится на сайте.</p>');
  128. setTimeout((function () {
  129. this.form.parent().find('.comments__add-popup-close').click();
  130. }).bind(this), 3000);
  131. //this.owner.addComment(data.result);
  132. }
  133. }).bind(this)).fail((function (xhr) {
  134. console.dir(xhr.responseText);
  135. }).bind(this)).always((function () {
  136. this.formData = [];
  137. }).bind(this));
  138. return true;
  139. }
  140. }
  141. class Comment {
  142. private _template: JQuery;
  143. private _rendered: JQuery;
  144. private _text;
  145. private _userName;
  146. private _date;
  147. private _level;
  148. private _id;
  149. public answerTo = 0;
  150. constructor(data) {
  151. this.id = data.id;
  152. this.userName = data.userName;
  153. this.date = data.datetime;
  154. this.text = data.text;
  155. this.level = data.answerTo == 0 ? 1 : 2;
  156. this.answerTo = data.answerTo;
  157. }
  158. get template() {
  159. if (this._template !== undefined) return this._template;
  160. this._template = $('<div class="comments__comment"></div>');
  161. this._template.append('<div class="comments__comment-text"></div>');
  162. let info = $('<div class="comments__comment-info"></div>');
  163. info.append('<div class="comments__comment-name"></div>');
  164. info.append('<div class="comments__comment-date"></div>');
  165. info.append('<div class="comments__comment-reply">Ответить</div>');
  166. this._template.append(info);
  167. return this._template;
  168. }
  169. get rendered() {
  170. if (this._rendered !== undefined) return this._rendered;
  171. this._rendered = this.template.clone();
  172. return this._rendered;
  173. }
  174. set text(value) {
  175. this._text = value;
  176. this.rendered.find('.comments__comment-text').html(value);
  177. }
  178. set userName(value) {
  179. this._userName = value;
  180. this.rendered.find('.comments__comment-name').html(value);
  181. }
  182. set date(value) {
  183. this._date = value;
  184. let dateObject = new Date(value);
  185. this.rendered.find('.comments__comment-date').html(dateObject.toLocaleString("ru", {
  186. year: 'numeric',
  187. month: 'long',
  188. day: 'numeric',
  189. hour: '2-digit',
  190. minute: '2-digit'
  191. }).replace(' г.', ''));
  192. }
  193. set id(value) {
  194. this._id = value;
  195. this.rendered.data('comment-id', value);
  196. }
  197. get id() {
  198. return this._id;
  199. }
  200. set level(value) {
  201. this._level = value;
  202. this.rendered.addClass('comments__comment--level' + value);
  203. }
  204. }
  205. }