1(function ($) { 2 "use strict"; 3 4 function appendOwnerActions() { 5 const currentUserId = Habersoft.user ? Habersoft.user.id : null; 6 if (!currentUserId) { 7 return; 8 } 9 10 $(".comment-item, .comment-answer").each(function () { 11 const $comment = $(this); 12 const commentUserId = $comment.data("user-id"); 13 const commentId = $comment.data("comment-id"); 14 15 if (currentUserId === commentUserId) { 16 const updateUrlTemplate = 17 Habersoft.routes.ajax.comment["update"]; 18 const deleteUrlTemplate = 19 Habersoft.routes.ajax.comment["destroy"]; 20 21 if (updateUrlTemplate && deleteUrlTemplate) { 22 const updateUrl = updateUrlTemplate.replace( 23 "COMMENT_ID_PLACEHOLDER", 24 commentId 25 ); 26 const deleteUrl = deleteUrlTemplate.replace( 27 "COMMENT_ID_PLACEHOLDER", 28 commentId 29 ); 30 31 const dropdownHtml = ` 32 <div class="dropdown"> 33 <button class="btn btn-sm btn-link text-secondary p-0" type="button" data-bs-toggle="dropdown" aria-expanded="false" style="line-height: 1;"> 34 <i class="fa fa-ellipsis-v" style="color: #000;font-size: 19px !important;" aria-hidden="true"></i> 35 </button> 36 <ul class="dropdown-menu dropdown-menu-end"> 37 <li> 38 <button class="dropdown-item text-secondary btn-edit-comment" data-id="${commentId}" data-url="${updateUrl}"> 39 <i class="icofont-edit fs-16" title="${__('common.edit')}" style="color:#8e8e8e;"></i> 40 ${__('common.edit')} 41 </button> 42 </li> 43 <li> 44 <button class="dropdown-item text-danger btn-delete-comment" data-id="${commentId}" data-url="${deleteUrl}"> 45 <i class="icofont-ui-delete fs-16" title="${__('common.delete')}" style="color:#c30000d9;"></i> 46 ${__('common.delete')} 47 </button> 48 </li> 49 </ul> 50 </div> 51 `; 52 53 if ($comment.find(".comment-owner-actions .dropdown").length === 0) { 54 $comment.find(".comment-owner-actions").first().html(dropdownHtml); 55 } 56 } 57 } 58 }); 59 } 60 61 function handleVoteAction(commentId, $element, likeDislike) { 62 if (!Habersoft.routes.ajax.comment["vote"]) { 63 console.error("Comment vote route is not defined in Habersoft object."); 64 return; 65 } 66 67 $.ajax({
68 type: "POST", 69 url: Habersoft.routes.ajax.comment["vote"], 70 dataType: "json", 71 data: { 72 commentid: commentId, 73 like_dislike: likeDislike, 74 }, 75 success: function (response) { 76 const $actionsContainer = $element.closest(".comment-actions, .ps-3"); 77 $actionsContainer 78 .find(`.like_count${commentId}`) 79 .text(response.like_count); 80 $actionsContainer 81 .find(`.dislike_count${commentId}`) 82 .text(response.dislike_count); 83 84 $actionsContainer 85 .find(".like_button, .dislike_button") 86 .removeClass("active"); 87 if (response.action !== "removed") { 88 $element.addClass("active"); 89 } 90 }, 91 }); 92 } 93 94 function loadComments($container, page) { 95 if ($container.data('isLoading')) return; 96 $container.data('isLoading', true); 97 98 const $loadMoreBtn = $container.find(".load-more-comments-btn"); 99 const $commentsListInner = $container.find(".comments-list-inner"); 100 const $loadMoreContainer = $container.find(".load-more-container"); 101 102 const routeName = $container.data('route'); 103 const routeParams = $container.data('params') || {}; 104 const commentsPerPage = $container.data("count") || 10; 105 106 let url = Habersoft.routes.ajax.comment[routeName]; 107 108 if (!url) { 109 console.error(`Comment route '${routeName}' not found.`); 110 $container.data('isLoading', false); 111 return; 112 } 113 114 if (routeParams.user_id) { 115 url = url.replace('USER_ID_PLACEHOLDER', routeParams.user_id); 116 } 117 118 const requestData = { 119 ...routeParams, 120 page: page, 121 count: commentsPerPage, 122 }; 123 124 if (page === 1) { 125 $commentsListInner.html(`<div class="text-center p-5"><i class="fa fa-spinner fa-spin fa-2x"></i></div>`); 126 } else { 127 $loadMoreBtn.prop('disabled', true).html(`<div class="d-flex align-items-center justify-content-center"><i class="fa fa-spinner fa-spin me-1"></i> ${__('comments.loading_more')}</div>`); 128 } 129 130 $.ajax({
131 url: url, 132 method: "GET", 133 data: requestData, 134 success: function (response) { 135 if (response.status) { 136 if (page === 1) { 137 $commentsListInner.empty(); 138 } 139 140 if (response.html && response.html.trim() !== "") { 141 $commentsListInner.append(response.html); 142 appendOwnerActions(); 143 } else if (page === 1) { 144 const noCommentMessage = $container.data('no-comment-message') || __("comments.no_comments"); 145 $commentsListInner.html(` 146 <div class="py-3 no-comment-message"> 147 <div class="fs-13 text-darkestgray-2 text-center family-regular"> 148 * ${noCommentMessage} * 149 </div> 150 </div>`); 151 } 152 153 if (response.hasMorePages) { 154 $loadMoreContainer.removeClass("d-none"); 155 } else { 156 $loadMoreContainer.addClass("d-none"); 157 } 158 } else { 159 $commentsListInner.html( 160 `<div class="py-3 text-danger text-center">${__( 161 "comments.error" 162 )}</div>` 163 ); 164 } 165 }, 166 error: function () { 167 $commentsListInner.html( 168 `<div class="py-3 text-danger text-center">${__( 169 "comments.error" 170 )}</div>` 171 ); 172 }, 173 complete: function () { 174 $container.data('isLoading', false); 175 const originalButtonText = `<div class="d-flex align-items-center justify-content-center"><i class="fa fa-commenting-o me-1 fs-20" aria-hidden="true"></i> ${__('comments.load_more')}</div>`; 176 $loadMoreBtn.prop('disabled', false).html(originalButtonText); 177 } 178 }); 179 } 180 181 window.initializeCommentSections = function () { 182 $('.comments-box').each(function () { 183 const $container = $(this); 184 if ($container.data('initialized')) return; 185 $container.data('initialized', true); 186 $container.data('currentPage', 1); 187 188 loadComments($container, 1); 189 }); 190 }; 191 192 $(document).ready(function () { 193 initializeCommentSections(); 194 195 $(document).on("click", ".load-more-comments-btn", function () { 196 const $btn = $(this); 197 const $container = $btn.closest(".comments-box"); 198 199 if ($container.data('isLoading')) return; 200 201 let currentPage = $container.data("currentPage") || 1; 202 currentPage++; 203 $container.data("currentPage", currentPage); 204 205 loadComments($container, currentPage); 206 }); 207 208 $(document).on("click", ".answer-submit", function () { 209 const $this = $(this); 210 const $commentContainer = $this.closest(".comments-cont"); 211 const commentId = $this.data("comment-id"); 212 const commentUsername = $this.data("comment-name"); 213 214 $("html, body").animate( 215 { 216 scrollTop: $commentContainer.offset().top, 217 }, 218 100 219 ); 220 221 $commentContainer 222 .find(".parent-comment-id") 223 .html(`<input type='hidden' name='parent_id' value='${commentId}'>`); 224 $commentContainer 225 .find(".comment-textarea") 226 .val(`@${commentUsername} `) 227 .focus(); 228 }); 229 230 $(document).on("click", ".like_button", function () { 231 handleVoteAction($(this).data("value"), $(this), "0"); 232 }); 233 234 $(document).on("click", ".dislike_button", function () { 235 handleVoteAction($(this).data("value"), $(this), "1"); 236 }); 237 238 $(document).on("submit", "#postAjaxCommentForm", function (e) { 239 e.preventDefault(); 240 const $form = $(this); 241 const $submitBtn = $form.find("button.user-comment-button"); 242 const $captchaElements = $form.find("[data-recaptcha]"); 243 244 if ($submitBtn.prop("disabled")) { 245 return false; 246 } 247 248 if (Boolean($captchaElements.length)) { 249 let captchaResult = parseInt($captchaElements.find('input[name="captchaResult"]').val(), 10); 250 let userAnswer = parseInt($captchaElements.find('input[type="text"]').val(), 10); 251 252 if (isNaN(userAnswer) || userAnswer !== captchaResult) { 253 showToast("danger", __("comments.captcha_failed")); 254 return false; 255 } 256 } 257 258 $submitBtn.prop("disabled", true); 259 showToast("info", __("comments.sending")); 260 261 $.ajax({
262 url: Habersoft.routes.ajax.comment["sent"], 263 type: "POST", 264 data: $form.serialize(), 265 dataType: "json", 266 success: function (response) { 267 268 if (response.toast?.message) { 269 showToast(response.toast.type, response.toast.message); 270 } 271 272 if (response.success) { 273 $form.trigger("reset"); 274 $form.find(".parent-comment-id").empty(); 275 276 const $commentsContainer = $form.closest(".comments-cont").find(".comments-box"); 277 $commentsContainer.data("currentPage", 1); 278 loadComments($commentsContainer, 1); 279 } 280 }, 281 error: function (xhr) { 282 const errorMsg = xhr.responseJSON?.message || xhr.statusText; 283 showToast("danger", __("comments.sending_error").replace(":message", errorMsg)); 284 }, 285 complete: function () { 286 $submitBtn.prop("disabled", false); 287 }, 288 }); 289 }); 290 291 $(document).on("click", ".btn-delete-comment", function () { 292 const $btn = $(this); 293 const url = $btn.data("url"); 294 const commentId = $btn.data("id"); 295 296 if (!confirm(__("comments.confirm_delete"))) { 297 return; 298 } 299 300 $.ajax({
301 url: url, 302 type: "DELETE", 303 dataType: "json", 304 success: function (response) { 305 if (response.success) { 306 const $commentItem = $btn.closest(".comment-item, .comment-answer"); 307 $commentItem.slideUp(300, function () { 308 $(this).remove(); 309 }); 310 } 311 312 if(response.toast){ 313 showToast(response.toast.type, response.toast.message); 314 } else{ 315 showToast(response.success ? 'success' : 'danger', response.message); 316 } 317 }, 318 error: function (xhr) { 319 const errorMsg = xhr.responseJSON?.message || "Bir hata oluÅtu."; 320 showToast("danger", errorMsg); 321 }, 322 }); 323 }); 324 325 $(document).on("click", ".btn-edit-comment", function () { 326 const $btn = $(this); 327 const commentId = $btn.data("id"); 328 const url = $btn.data("url"); 329 const $commentTextDiv = $(`#comment-text-${commentId}`); 330 331 // EÄer baÅka bir yorum zaten düzenleme modundaysa, onu iptal et. 332 $('.btn-cancel-edit').click(); 333 334 const currentText = $commentTextDiv.find("p").text(); 335 336 if ($commentTextDiv.find("textarea").length > 0) { 337 return; 338 } 339 340 const editFormHtml = ` 341 <div class="comment-edit-form my-2"> 342 <textarea class="form-control" rows="3">${currentText}</textarea> 343 <div class="d-flex justify-content-end mt-2"> 344 <button class="btn btn-sm btn-secondary btn-cancel-edit me-2">İptal</button> 345 <button class="btn btn-sm btn-primary btn-save-comment" data-url="${url}">Kaydet</button> 346 </div> 347 </div> 348 `; 349 350 $commentTextDiv.find("p").hide(); 351 $commentTextDiv.append(editFormHtml); 352 353 const $textarea = $commentTextDiv.find("textarea"); 354 const textareaElement = $textarea.get(0); 355 356 textareaElement.focus(); 357 358 const textLength = textareaElement.value.length; 359 textareaElement.setSelectionRange(textLength, textLength); 360 }); 361 362 $(document).on("click", ".btn-cancel-edit", function () { 363 const $form = $(this).closest(".comment-edit-form"); 364 const $commentTextDiv = $form.closest(".comment-text"); 365 366 $commentTextDiv.find("p").show(); 367 $form.remove(); 368 }); 369 370 $(document).on("click", ".btn-save-comment", function () { 371 const $btn = $(this); 372 const url = $btn.data("url"); 373 const $form = $btn.closest(".comment-edit-form"); 374 const $commentTextDiv = $form.closest(".comment-text"); 375 const newText = $form.find("textarea").val(); 376 377 if (newText.trim() === "") { 378 showToast("warning", "Yorum boÅ olamaz."); 379 return; 380 } 381 382 $btn.prop("disabled", true).text("Kaydediliyor..."); 383 384 $.ajax({
385 url: url, 386 type: "PUT", 387 dataType: "json", 388 data: { 389 comment: newText, 390 }, 391 success: function (response) { 392 if (response.success) { 393 $commentTextDiv.find("p").text(newText).show(); 394 $form.remove(); 395 } 396 397 if(response.toast){ 398 showToast(response.toast.type, response.toast.message); 399 } else{ 400 showToast(response.success ? 'success' : 'danger', response.message); 401 } 402 403 }, 404 error: function (xhr) { 405 const errorMsg = xhr.responseJSON?.message || "Bir hata oluÅtu."; 406 showToast("danger", errorMsg); 407 $btn.prop("disabled", false).text("Kaydet"); 408 }, 409 }); 410 }); 411 }); 412})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.