1/* ========================================================================== 2 Project: TWD CMS 7 - Blog 3 Date: 05/18/20 - File created 4 Created by: Third Wave Digital (www.thirdwavedigital.com) 5 ========================================================================== */ 6 7 var cmsBlog = function() { 8 var $blogList = $(".cms-blog-list"), 9 $blogCategories = $(".cms-blog-categories"), 10 $blogTags = $(".cms-blog-tags"), 11 $blogPost = $(".cms-blog-post"), 12 $blogSettings = $(".cms-blog-settings"), 13 $blogMasonry = $(".cms-blog-masonry"); 14 15 /* ========================================================================== 16 Blog List 17 ========================================================================== */ 18 19 if ($blogList.length) { 20 // Delete 21 $blogList.find(".btn-delete").on("click",function(e) { 22 var id = $(this).data('blog_pk'); 23 bootbox.confirm({ 24 message: "Are you sure you want to delete this post?", 25 buttons: { 26 confirm: { 27 label: "Yes" 28 }, 29 cancel: { 30 label: "No", 31 className: "btn-secondary" 32 } 33 }, 34 callback: function (result) { 35 if( result ) { 36 window.location.assign( 'index.cms?delete_id='+id ); 37 } 38 } 39 }) 40 }) 41 42 // Delete comment 43 $blogList.find(".btn-delete-comment").on("click",function(e) { 44 e.preventDefault(); 45 var elm = $(this); 46 bootbox.confirm({ 47 message: "Are you sure you want to delete this comment?", 48 buttons: { 49 confirm: { 50 label: "Yes" 51 }, 52 cancel: { 53 label: "No", 54 className: "btn-secondary" 55 } 56 }, 57 callback: function (result) { 58 if( result ) { 59 window.location.assign( elm.attr('href') ); 60 } 61 } 62 }) 63 }) 64 65 // Approve All 66 $blogList.find(".btn-approve-all").on("click",function(e) { 67 bootbox.confirm({ 68 message: "Are you sure you want to approve all these comments?", 69 buttons: { 70 confirm: { label: "Yes" }, 71 cancel: { label: "No", className: "btn-secondary" } 72 }, 73 callback: function (result) { 74 if( result ) { 75 window.location.assign( 'index.cms?approveAll=1' ); 76 } 77 } 78 }) 79 }) 80 81 // Delete All Unapproved 82 $blogList.find(".btn-delete-all-unapproved").on("click",function(e) { 83 bootbox.confirm({ 84 message: "Are you sure you want to delete all these comments?", 85 buttons: { 86 confirm: { label: "Yes" }, 87 cancel: { label: "No", className: "btn-secondary" } 88 }, 89 callback: function (result) { 90 if( result ) { 91 window.location.assign( 'index.cms?deleteAllUnapproved=1' ); 92 } 93 } 94 }) 95 }) 96 97 // Unapprove All 98 $blogList.find(".btn-unapprove-all").on("click",function(e) { 99 bootbox.confirm({ 100 message: "Are you sure you want to Unapprove all these comments?", 101 buttons: { 102 confirm: { label: "Yes" }, 103 cancel: { label: "No", className: "btn-secondary" } 104 }, 105 callback: function (result) { 106 if( result ) { 107 window.location.assign( 'index.cms?unapproveAll=1' ); 108 } 109 } 110 }) 111 }) 112 113 // Delete All Approved 114 $blogList.find(".btn-delete-all-approved").on("click",function(e) { 115 bootbox.confirm({ 116 message: "Are you sure you want to delete all these comments?", 117 buttons: { 118 confirm: { label: "Yes" }, 119 cancel: { label: "No", className: "btn-secondary" } 120 }, 121 callback: function (result) { 122 if( result ) { 123 window.location.assign( 'index.cms?deleteAllApproved=1' ); 124 } 125 } 126 }) 127 }) 128 129 // Querystring? 130 if (getParameterByName("category") != "") { 131 localStorage.removeItem("cms-blog-tab"); 132 var $blogTable = $blogList.find("table").dataTable(); 133 $blogTable.fnFilter(getParameterByName("category")); 134 } 135 136 if (getParameterByName("published") != "") { 137 localStorage.removeItem("cms-blog-tab"); 138 var tab = getParameterByName("published") == "1" ? "blog-published" : "blog-unpublished"; 139 $blogList.find(".nav-link").removeClass("active").end() 140 .find(".tab-pane").removeClass("show active").end() 141 .find(".cms-nav-tabs a[href='#" + tab + "']").tab("show"); 142 } 143 144 145 // Retain Tab State 146 var activeTab = localStorage.getItem("cms-blog-tab"); 147 148 $blogList.find("a[data-toggle='tab']").on("show.bs.tab", function(e) { 149 localStorage.setItem("cms-blog-tab", $(e.target).attr("href")); 150 }) 151 152 if(activeTab) { 153 $blogList.find(".nav-link").removeClass("active").end() 154 .find(".tab-pane").removeClass("show active").end() 155 .find(".cms-nav-tabs a[href='" + activeTab + "']").tab("show"); 156 } 157 158 // Datatables 159 $blogList.find(".blog-published, .blog-unpublished").dataTable( { 160 "aaSorting": [[2,"desc"]], 161 "aoColumns" : [null,null,null,{"bSortable":false}], 162 "columnDefs": [ 163 { "type": "date", "targets":2 } 164 ], 165 "aLengthMenu": [[20, 100, -1], [20, 100, "All"]], 166 "iDisplayLength" : 20 167 }) 168 $blogList.find(".blog-comments").dataTable( { 169 "aaSorting": [[1,"desc"]], 170 "aoColumns" : [{"bSortable":false},null,{"bSortable":false}], 171 "aLengthMenu": [[20, 100, -1], [20, 100, "All"]], 172 "iDisplayLength" : 20 173 }) 174 175 } 176 177 /* ========================================================================== 178 Blog Categories 179 ========================================================================== */ 180 181 if ($blogCategories.length) { 182 // Feature 183 $blogCategories.find(".btn-feature").on("click",function(e) { 184 //$blogCategories.find(".btn-feature span").removeClass("fas text-primary").addClass("far text-muted"); 185 var elm = $(this).find("span"); 186 var cat_pk = $(this).data("cat_pk"); 187 var featured = 0; 188 if( elm.hasClass("text-muted") ) { 189 elm.removeClass("far text-muted").addClass("fas text-primary").end().tooltip("hide"); 190 featured = 1; 191 } else { 192 elm.removeClass("fas text-primary").addClass("far text-muted").end().tooltip("hide"); 193 } 194 fetch('/admin/plugins/blog/pkg/com/blogcategories.cfc?method=remoteToggleFeatured&cat_pk=' + cat_pk + '&cat_featured=' + featured) 195 .then(function (response) { 196 return response.json() 197 }) 198 .then(function (json) { 199 }) 200 .catch(function(error) { 201 callback(false) 202 }) 203 }) 204 205 // Title 206 $blogCategories.find(".btn-edit").on("click",function(e) { 207 $blogCategories.find("table .flex-row.d-none").removeClass("d-none").addClass("d-flex").end() 208 .find("table .input-group").addClass("d-none"); 209 210 $(this).parent().removeClass("d-flex").addClass("d-none").end() 211 .parent().next(".input-group").removeClass("d-none"); 212 }) 213 214 // Delete 215 $blogCategories.find(".btn-delete").on("click",function(e) { 216 var id = $(this).data('cat_pk'); 217 bootbox.confirm({ 218 message: "Are you sure you want to delete this category?", 219 buttons: { 220 confirm: { 221 label: "Yes" 222 }, 223 cancel: { 224 label: "No", 225 className: "btn-secondary" 226 } 227 }, 228 callback: function (result) { 229 if( result ) { 230 window.location.assign('categories.cms?delete_id='+id); 231 } 232 } 233 }) 234 }) 235 236 // Datatable 237 $blogCategories.find("table").dataTable( { 238 "aaSorting": [[0,"asc"]], 239 "aoColumns" : [null,null,{"bSortable":false}], 240 "aLengthMenu": [[20, 100, -1], [20, 100, "All"]], 241 "iDisplayLength" : 20 242 }) 243 } 244 245 /* ========================================================================== 246 Blog Tags 247 ========================================================================== */ 248 249 if ($blogTags.length) { 250 251 // Title 252 $blogTags.find(".btn-edit").on("click",function(e) { 253 $blogTags.find("table .flex-row.d-none").removeClass("d-none").addClass("d-flex").end() 254 .find("table .input-group").addClass("d-none"); 255 256 $(this).parent().removeClass("d-flex").addClass("d-none").end() 257 .parent().next(".input-group").removeClass("d-none"); 258 }) 259 260 // Delete 261 $blogTags.find(".btn-delete").on("click",function(e) { 262 var id = $(this).data('tag_pk'); 263 bootbox.confirm({ 264 message: "Are you sure you want to delete this tag?", 265 buttons: { 266 confirm: { 267 label: "Yes" 268 }, 269 cancel: { 270 label: "No", 271 className: "btn-secondary" 272 } 273 }, 274 callback: function (result) { 275 if( result ) { 276 window.location.assign('tags.cms?delete_id='+id); 277 } 278 } 279 }) 280 }) 281 282 // Datatable 283 $blogTags.find("table").dataTable( { 284 "aaSorting": [[0,"asc"]], 285 "aoColumns" : [null,null,{"bSortable":false}], 286 "aLengthMenu": [[20, 100, -1], [20, 100, "All"]], 287 "iDisplayLength" : 20 288 }) 289 } 290 291 /* ========================================================================== 292 Blog Post 293 ========================================================================== */ 294 295 if ($blogPost.length) { 296 // Date val(moment().format("MM-DD-YYYY")). 297 $blogPost.find(".datepicker").bootstrapMaterialDatePicker({ 298 date: true, 299 time: false, 300 format: "MM-DD-YYYY",
301 clearButton: true 302 }) 303 304 // Time val(moment().format("h:mm A")). 305 $blogPost.find(".timepicker").bootstrapMaterialDatePicker({ 306 date: false, 307 time: true, 308 shortTime: true, 309 format: "h:mm A", 310 clearButton: true 311 }) 312 313 // Maxlength 314 $blogPost.find("[minlength],[maxlength]").maxlength({ 315 alwaysShow: true, 316 warningClass: "form-text text-muted", 317 limitReachedClass: "form-text text-muted", 318 placement: "top-right-inside" 319 }) 320 321 // Ckeditor 322 var editor = CKEDITOR.replace("blog_content", { 323 on: { 324 contentDom: loadAssets 325 } 326 }) 327 328 function loadAssets(event) { 329 if (event.editor.mode != 'source') { 330 var editorHead = event.editor.document.$.head, 331 jQuery = document.createElement('script'), 332 bootstrapJs = document.createElement('script'), 333 cmstabsJs = document.createElement('script'); 334 335 jQuery.src = '/admin/assets/js/vendor/jquery-1.11.0.min.js'; 336 bootstrapJs.src = '/admin/assets/js/vendor/bootstrap/js/bootstrap.min.js'; 337 cmstabsJs.src = '/admin/assets/js/vendor/ckeditor/plugins/cmstabs/js/bootstrap.tabs.custom.js'; 338 339 editorHead.appendChild(jQuery); 340 341 jQuery.onload = function() { 342 editorHead.appendChild(bootstrapJs); 343 editorHead.appendChild(cmstabsJs); 344 } 345 } 346 }; 347 348 editor.config.forcePasteAsPlainText = true; 349 editor.config.height = 500; 350 editor.config.contentsCss = ['/admin/assets/js/vendor/bootstrap/css/bootstrap.min.css','/admin/assets/css/fontawesome/css/all.min.css','/css/main.css','/skins/cmsdefault/editor/style.css']; 351 editor.config.bodyClass = "container-fluid"; 352 editor.config.allowedContent = true; 353 //editor.config.scayt_autoStartup = true; 354 editor.config.protectedSource.push(/<span[^>]*><\/span>/g); 355 editor.config.filebrowserBrowseUrl = '/admin/assets/js/vendor/ckfinder/ckfinder.html'; 356 editor.config.filebrowserImageBrowseUrl = '/admin/assets/js/vendor/ckfinder/ckfinder.html?Type=Images'; 357 editor.config.filebrowserUploadUrl = '/admin/assets/js/vendor/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files'; 358 editor.config.filebrowserImageUploadUrl = '/admin/assets/js/vendor/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images'; 359 editor.config.magicline_everywhere = true; 360 editor.config.magicline_color = "#ccc"; 361 editor.config.extraPlugins = 'balloonpanel,a11ychecker,cmsgrid,cmstabs,cmsclasses,cmsgrid,cmsaccordion,cmslink'; 362 editor.config.removePlugins = 'link,scayt'; 363 364 // File Upload 365 $blogPost.find(".custom-file-input").on("change",function(e) { 366 if (e.target.files[0] !== undefined) { 367 $(this).parent().find(".custom-file-label").html(e.target.files[0].name); 368 $(this).valid(); 369 } 370 }) 371 372 $blogPost.find("input[name='blog_title']").on("keyup",function(e) { 373 var val = $(this).val(); 374 $blogPost.find("input[name='blog_slug']").val(formatPermalink(val)).trigger('change'); 375 }); 376 377 $blogPost.find("input[name='blog_slug']").on("input change blur focus", function(e) { 378 var val = formatPermalink($(this).val()); 379 $(this).val(val); 380 381 var val = $(this).val(); 382 // check if the slug is unique, and note the field if it's not 383 var uniqueCheckParams = { 384 method: 'isSlugUnique', 385 slug: val, 386 blog_pk: $blogPost.find('input[name="blog_pk"]').val(), 387 returnFormat: 'json' 388 }; 389 390 // this endpoint will return either true or false, true if it is unique or false otherwise 391 $.get('/admin/plugins/blog/pkg/com/blog.cfc', uniqueCheckParams, function (data, textStatus, jqXHR) { 392 var isUnique = JSON.parse(data); 393
394 var validator = $blogPost.find('form:first').validate(); 395 if( !isUnique ) { 396 validator.showErrors({ 397 "blog_slug": "Slug is not unique." 398 }); 399 } else { 400 validator.resetForm(); 401 } 402 }); 403 }) 404 405 var formatPermalink = function(val) { 406 // Create url friendly value 407 val = val.trim().replace(/[^a-zA-Z0-9-_]/g, '-'); 408 409 // account for multiple instances of - 410 var cont = val.indexOf('--'); 411 while (cont > -1) { 412 val = val.replace('--','-'); 413 cont = val.indexOf('--'); 414 } 415 // make sure the first character is not - 416 var strip = (val.charAt(0) == '-'); 417 while(strip) { 418 val = val.slice(1); 419 strip = (val.charAt(0) == '-') 420 } 421 422 // lower case the return 423 val = val.toLowerCase(); 424 425 return val; 426 } 427 428 // Validate 429 $blogPost.find("form").validate({ 430 431 }) 432 } 433 434 /* ========================================================================== 435 Blog Page - Settings 436 ========================================================================== */ 437 438 if ($blogSettings.length) { 439 $blogSettings.each(function(index,element) { 440 // Toggle 441 $(element).find("button[aria-controls]").on("click",function(e) { 442 $(element) 443 .find(".collapse").collapse("hide").end() 444 .find("button[aria-controls]").not(this).removeClass("active"); 445 }) 446 447 $(element).find(".collapse").on("show.bs.collapse", function (e) { 448 $.each(e.target.classList,function(idx,target) { 449 $(element).find("button[aria-controls="+target+"]").addClass("active"); 450 }) 451 $(element).find(".cms-blog-submit").removeClass("d-none"); 452 }) 453 454 $(element).find(".collapse").on("hide.bs.collapse", function (e) { 455 $.each(e.target.classList,function(idx,target) { 456 $(element).find("button[aria-controls="+target+"]").removeClass("active"); 457 }) 458 $(element).find(".cms-blog-submit").addClass("d-none"); 459 }) 460 461 // Blog Settings 462 $(element).find("[id*='show_categories']").on("change", function(e) { 463 $(this).is(":checked") ? $(element).next(".cms-blog").removeClass("hide-categories") : $(element).next(".cms-blog").addClass("hide-categories"); 464 }) 465 $(element).find("[id*='show_tags']").on("change", function(e) { 466 $(this).is(":checked") ? $(element).next(".cms-blog").removeClass("hide-tags") : $(element).next(".cms-blog").addClass("hide-tags"); 467 }) 468 $(element).find("[id*='show_title']").on("change", function(e) { 469 $(this).is(":checked") ? $(element).next(".cms-blog").removeClass("hide-title") : $(element).next(".cms-blog").addClass("hide-title"); 470 if (!$(element).find("[id*='show_teaser']").is(":checked")) $(element).find("[id*='show_teaser']").trigger("click"); 471 }) 472 $(element).find("[id*='show_teaser']").on("change", function(e) { 473 $(this).is(":checked") ? $(element).next(".cms-blog").removeClass("hide-teaser") : $(element).next(".cms-blog").addClass("hide-teaser"); 474 if (!$(element).find("[id*='show_title']").is(":checked")) $(element).find("[id*='show_title']").trigger("click"); 475 }) 476 $(element).find("[id*='show_author']").on("change", function(e) { 477 $(this).is(":checked") ? $(element).next(".cms-blog").removeClass("hide-author") : $(element).next(".cms-blog").addClass("hide-author"); 478 }) 479 $(element).find("[id*='show_date']").on("change", function(e) { 480 $(this).is(":checked") ? $(element).next(".cms-blog").removeClass("hide-
480date") : $(element).next(".cms-blog").addClass("hide-date"); 481 }) 482 $(element).find("input[name*='sidebar_options']").on("change", function(e) { 483 var val = $(this).val(); 484 $(element).next(".cms-blog").removeClass("cms-blog-sidebar-left cms-blog-sidebar-right hide-sidebar").addClass(val); 485 val == ("hide-sidebar") ? $(element).next(".cms-blog").find(".col-lg-9").removeClass("col-lg-9").addClass("col-12") : $(element).next(".cms-blog").find(".col-12").removeClass("col-12").addClass("col-lg-9"); 486 }) 487 488 // Datatable 489 $(element).find("table").dataTable( { 490 orderCellsTop: true, //move sorting to top header 491 "aaSorting": [[0,"asc"]], 492 "aoColumns" : [null,null,{"bSortable":false}], 493 "aLengthMenu": [[20, 100, -1], [20, 100, "All"]], 494 "iDisplayLength" : 20 495 }) 496 }) 497 498 // Validate 499 $.validator.setDefaults({ 500 highlight: function(element) { 501 if (!$(element).hasClass("custom-control-input")) { 502 $(element).addClass('is-invalid'); 503 $(element).parent().find('label').addClass('active'); 504 } 505 }, 506 unhighlight: function(element) { 507 $(element).removeClass('is-invalid'); 508 }, 509 errorElement: 'span', 510 errorClass: 'error text-danger my-1 small', 511 errorPlacement: function(error, element) { 512 if(element.parent('.place-validation-after').length) { 513 error.insertAfter(element.parent()); 514 } else if(element.parents(".place-validation-after").length){ 515 error.insertAfter(element.parents(".place-validation-after")); 516 } else { 517 error.insertAfter(element); 518 } 519 }, 520 ignore: [] 521 }) 522 $.validator.messages.required = "<span class='fas fa-exclamation-triangle' aria-hidden='true'></span> Required"; 523 $("div[class*='cms-blog-settings'] form").validate(); 524 // Manage user interaction of 'all categories' here 525 $blogSettings.find('input[name="categories_all"]').on("change", function(e) { 526 let checked = $(this).is(":checked"); 527 if( checked ) { 528 $blogSettings.find('tr.page_category_options').addClass('d-none'); 529 $blogSettings.find('input[id^="categories_picker_"]').attr('required', false); 530 } else { 531 $blogSettings.find('tr.page_category_options').removeClass('d-none'); 532 $blogSettings.find('input[id^="categories_picker_"]').attr('required', true); 533 } 534 }); 535 $blogSettings.find('input[name="categories_all"]').trigger('change'); 536 } 537 538 /* ========================================================================== 539 Blog Page - Masonry 540 ========================================================================== */ 541 542 if ($blogMasonry.length) { 543 // Masonry layout 544 var $grid = $('.cms-blog-masonry .col-lg-9 ul:first-child'); 545 546 $grid.masonry({ 547 itemSelector: '.cms-blog-item', 548 columnWidth: '.grid-sizer', 549 gutter: 0, 550 horizontalOrder: true, 551 percentPosition: true 552 }) 553 554 //Listen for lazyunveilread and trigger masonry re-draw 555 document.addEventListener("lazyunveilread", function(e) { 556 $grid.masonry("layout"); 557 }) 558} 559 560 /* ========================================================================== 561 Utils 562 ========================================================================== */ 563 564 function getParameterByName(name) { 565 name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); 566 var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), 567 results = regex.exec(location.search); 568 return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); 569 } 570 571 } 572
573 $(document).ready(function() { 574 575 cmsBlog(); 576 577 }) 578
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.