1 2/* 3 * Define console and console.log if not defined 4 */ 5 6if (!window.console) window.console = {}; 7if (!window.console.log) window.console.log = function () { }; 8/* 9 * Events that require the window to be loaded first 10 */ 11window.addEventListener("load", function(e) { 12 /* 13 * Wrap jquery event 14 */ 15 (function($) { 16 /* 17 * Document ready functions 18 */ 19 $(document).ready(function() { 20 21 22 // Init the mlMenu in the side bar 23 doMenuInit(); 24 25 // Init the tooltip 26 doTooltipInit(); 27 28 // Bind events regarding the page blocker 29 bindPageBlock(); 30 31 // Bind shipping functions on order review page 32 bindShippingFunctions(); 33 34 // Bind on click functions that use specific classes to trigger actions 35 bindGenericFunctions(); 36 37 }); 38 /* 39 * End document ready functions 40 */ 41 42 $('#checkoutForm').submit(function(e) { 43 proceedToCheckout({ e: e }); 44 }); 45 46 })(jQuery); 47 /* 48 * End jquery functions 49 */ 50}); 51/* 52 * End events that require the window to be loaded first 53 */ 54 55function ajax(data, callback) { 56 return new Promise(function(resolve, reject) { 57 getJson(data,callback); 58 59 resolve(true); 60 }); 61} 62 63 64 65 66 67/******** DEBUG ********/ 68//@header 69 70// Debug function to identify function usage for key functions 71function report() { 72 alert('nutrisail.js'); 73 console.trace(); 74} 75 76// Keeping for now to see if anything breaks 77/* 78function formatCurrency(amount) { 79 var i = parseFloat(amount); 80 if(isNaN(i)) { i = 0.00; } 81 var minus = ''; 82 if(i < 0) { minus = '-'; } 83 i = Math.abs(i); 84 i = parseInt((i + .005) * 100); 85 i = i / 100; 86 s = new String(i); 87 if(s.indexOf('.') < 0) { s += '.00'; } 88 if(s.indexOf('.') == (s.length - 2)) { s += '0'; } 89 s = minus + s; 90 return '$' + s; 91} 92*/ 93 94 95/******** DEBUG ********/ 96 97 98/* START EVENTS */ 99 100 101/******** Commonly Used Functions and callbacks ********/ 102/* 103 * Standard replace content callback 104 * This function will place the content of the response into the content-block element 105 */ 106function replaceContent(content, target) { 107 if (target === undefined) { 108 target = $('#content-block'); 109 } 110 111 // convert to string if not already 112 if (typeof content == 'string') { 113 content = $.parseJSON(content); 114 } 115 116 117 target.html(content.content); 118} 119 120function appendContent(content, target) { 121 if (target === undefined) 122 target = $('#content-block'); 123 124 if (typeof content == 'string') 125 content = $.parseJSON(content); 126 127 target.append(content.content); 128} 129 130 131 132 133 134// Function written to bridge the gap between existing ajaxLoader template 135// todo : refactor and remove 136function ajaxReplaceContent(content, target) 137{ 138 target.replaceWith(content.content); 139 140 if (content.new_ajax == true) 141 142 for (var key in content) 143 $('#ajax-holder-' + key).append(content.key); 144} 145 146function loadMessages(content) 147{ 148 $('#messages').html(content.messages); 149} 150 151function loadSpinner(el) { 152 $(el).html(getLoadingSpinner()); 153} 154 155function displayModal(content) { 156 if ($('.modal-instance').length) { 157 displayStackModal(content); 158 } else { 159 $('#modal').html(content.content); 160 $('#modal').modal(); 161 } 162} 163 164function displayStackModal(content) { 165 // convert to string if not already 166 if (typeof content == 'string') { 167 content = $.parseJSON(content); 168 } 169 170 if (content.content) { 171 $('.modal-container').last().html(content.content); 172 $('.modal-instance').find('.modal-trigger').click(); 173 } else { 174 console.log('Request to display empty modal detected, but no content found. Please use Controller Ajax in the controller.'); 175 } 176} 177 178function closeModal() 179{ 180 $('#modal').modal('hide'); 181 $('.modal-container').removeClass('modal-active'); 182} 183 184function getURL(params) 185{ 186 var replicatedSiteName = window.location.pathname.split('/')[1]; 187 return window.location.origin + '/' + replicatedSiteName + '/' + params.action.split('_').join('/'); 188} 189 190/******** Commonly Used Functions and callbacks ********/ 191 192/******** TREE FUNCTIONS ********/ 193 194function viewUserDetails(elem, e) 195{ 196 e.preventDefault(); 197 198 blockPage(); 199 getJSON({ 200 url: elem.attr('data-path'), 201 data:{ 202 user_id : elem.attr('user-id'), 203 } 204 }, function(results) { 205 displayStackModal($.parseJSON(results)); 206 unblockPage(); 207 }); 208 209} 210 211 212function initTreeAction(elem, e) { 213 switch(elem.attr('data-control')) { 214 case 'bookmark': 215 addToTreeBookmarks(elem, e); 216 break; 217 case 'pin': 218 pinToTreeTop(elem, e); 219 break; 220 default: 221 alert('action not set!'); 222 } 223} 224 225 226function pinToTreeTop(elem, e) { 227 e.preventDefault(); 228 229 var top_level_user = elem.closest('.tree-item').attr('user-name'); 230 231 if (!top_level_user) { 232 var top_level_user = elem.attr('user-name'); 233 } 234 235 getJSON({ 236 url: '/Bliteworks/Backoffice/Tree/TreeGrid', 237 data:{ 238 top_level_user : top_level_user 239 } 240 }, function(results) { 241 replaceContent( 242 $.parseJSON(results) 243 ); 244 245 getJson({ 246 url : '/Bliteworks/Backoffice/Tree/Buttons', 247 data : { 248 user : top_level_user 249 } 250 }, function(results) { 251 replaceContent( 252 results, 253 $('.binary-tree-buttons') 254 ); 255 }); 256 }); 257} 258 259 260function addToTreeBookmarks(elem, e) { 261 e.preventDefault(); 262 263 var user_id = elem.closest('.tree-item').attr('user-id'); 264 if (!user_id) { 265 user_id = elem.attr('user-id'); 266 } 267 268 getJSON({
269 url: '/Bliteworks/Backoffice/Tree/AddToBookmarks', 270 data:{ 271 user_id: user_id, 272 } 273 }); 274} 275 276function toggleFavorite(elem, e) { 277 e.preventDefault(); 278 279 if (elem.hasClass('in-favorite')) { 280 removeProductFromFavorites(elem, e); 281 elem.removeClass('in-favorite'); 282 } else { 283 addProductToFavorites(elem, e); 284 elem.addClass('in-favorite'); 285 } 286 287} 288 289function addProductToFavorites(elem, e) { 290 e.preventDefault(); 291 292 getJSON({ 293 url: elem.attr('data-url'), 294 data: { 295 entity_id: elem.attr('data-id') 296 } 297 }); 298 299 300} 301 302function removeProductFromFavorites(elem, e) { 303 e.preventDefault(); 304 305 getJSON({ 306 url: elem.attr('data-url-remove'), 307 data: { 308 entity_id: elem.attr('data-id') 309 } 310 }); 311} 312 313function viewTreeFavorites(elem, e) 314{ 315 e.preventDefault(); 316 getJSON({ 317 url: elem.attr('data-path'), 318 data: { 319 user_id: elem.attr('data-id') 320 } 321 }, function(results) { 322 launchSidebar($.parseJSON(results)); 323 }); 324} 325 326 327 328 329function initCharLimit() { 330 331 function checkChars() { 332 var elements = $('.char-limit'); 333 $.each(elements, function(index,value){ 334 var elem = elements.eq(index); 335 var parentBoxWidth = elem.parent()[0].clientWidth; 336 var text = elem.text(); 337 338 elem.attr('data-original-string', text); 339 if (parentBoxWidth<250) { 340 if (!text.includes('..')) { 341 text = text.substring(0,10) + '..'; 342 elem.text(text); 343 } 344 } else { 345 if (text.includes('..')) { 346 elem.text(elem.attr('data-original-string')); 347 } 348 } 349 }); 350 } 351 352 $( window ).resize(function() { 353 checkChars(); 354 }); 355 checkChars(); 356 357} 358 359 360 361 362 363 364/* GET JSON */ 365function getJSON(data, callback) { 366 return getJson(data, callback); 367} 368 369function getJson(data, callback) { 370 if (data.data instanceof FormData) { 371 $.ajax({ 372 url: data.url, 373 data: data.data, 374 processData: false, 375 contentType: false, 376 type: 'POST', 377 success: function(results){ 378 if (callback) { 379 callback(results); 380 } else { 381 processAjaxCallback(results); 382 } 383 } 384 }); 385 386 } else { 387 388 $.post(data.url, data.data, function(results) { 389 if (callback) { 390 callback(results); 391 } else { 392 processAjaxCallback(results); 393 } 394 }); 395 396 } 397 398 399 400} 401 402/* GET JSON */ 403function processAjaxCallback(data) { 404 var data = $.parseJSON(data); 405 406 // redirect 407 if (data.redirect && data.redirect.url) { 408 window.location.assign(data.redirect.url); 409 return; 410 } 411 412 // callbacks 413 if (data.callback && data.callback.length > 0) { 414 data.callback.forEach(function(item){ 415 $('body').append('<script>' + item.function + '</script>'); 416 }) 417 } 418 419 // reload 420 if (data.reload && data.reload.url) { 421 // update the content 422 loadContent(data.reload.url); 423 } 424 425 if (data.warning && data.warning.length > 0) { 426 data.warning.forEach(function(item) { 427 swal({ 428 title : item.header, 429 text : item.message, 430 icon : 'warning', 431 button : 'Continue' 432 }); 433 }); 434 } 435 436 437 // display error 438 if (data.error && data.error.length > 0) { 439 data.error.forEach(function(item) { 440 swal({ 441 title : item.header, 442 text: item.message, 443 icon: "error", 444 button: "Continue", 445 }); 446 }); 447 } 448 449 // display success 450 if (data.success && data.success.length > 0) { 451 data.success.forEach(function(item) { 452 swal({ 453 title : item.header, 454 text: item.message, 455 icon: "success", 456 button: "Continue", 457 }); 458 }); 459 } 460} 461 462 463 464 465/* LOAD CONTENT */ 466function loadContent(url) 467{ 468 report(); 469 // update address bar 470 history.pushState({}, {} , url.replace('/Ajax', '').toLowerCase()); 471 472 getJSON({ 473 url: url, 474 }, function(results) { 475 replaceContent(results, $('#view')); 476 }); 477} 478 479 480/* GET JSON */ 481function submitForm(elem, e, options) { 482 e.preventDefault(); 483 var data = elem.serialize(); 484 485 var postUrl = elem.attr('action'); 486 487 elem.parent().prepend(getLoadingSpinner()); 488 elem.hide(); 489 490 getJson({ 491 url: postUrl, 492 data: data, 493 }, function(results) { 494 elem.show(); 495 getLoadingSpinner().remove(); 496 processAjaxCallback(results); 497 498 // if the modal is in the DOM tree of this form, close it 499 closeModal(); 500 }); 501} 502 503function submitFormAndClear(elem, e) { 504 submitForm(elem, e); 505 elem.find('.form-control').val(''); 506 $('html, body').animate({ scrollTop: 0 }, 'fast'); 507} 508 509// New feature planned 510function viewNotificationsDetails(elem, e) 511{ 512 e.preventDefault(); 513 var notification_id = elem.closest('.notification-item').attr('data-id'); 514 getJSON({ 515 url: '/Bliteworks/Notifications/Details', 516 data: { 517 notification_id: notification_id 518 }, 519 }, function(results){ 520 launchModal(results); 521 }); 522} 523 524/* FACEBOOK API */ 525function getFacebookData(postUrl) { 526 FB.api('/me?fields=id,email,name', function(user) { 527 528 getJSON({ 529 url: postUrl, 530 data: { 531 fb_action : 'connect' , 532 fb_data : user 533 } 534 }); 535 }); 536} 537 538 539 540function loginWithFacebook(e) { 541 e.preventDefault(); 542 FB.login(function(response) { 543 getFacebookData('/Bliteworks/User/Signup/Action/LoginWithFacebook'); 544 }, { scope: 'public_profile,email' }); 545} 546 547 548function launchBrandProWizard(el) { 549 getJson({ 550 url : el.attr('data-url') 551 }, function(results) { 552 launchCodebaseModal(results); 553 }); 554} 555 556function launchCodebaseModal(content) { 557 if (typeof content == 'string') { 558 content = $.parseJSON(content); 559 } 560 561 if (content.content) {
562 $('#modal-normal .modal-content').html(content.content); 563 $('#modal-normal').modal(true); 564 } else { 565 console.log('Request to display empty modal detected, but no content found. Please use Controller Ajax in the controller.'); 566 } 567} 568 569function goUrl(el) { 570 var url = el.attr('data-url'); 571 572 window.location.replace(url); 573} 574 575 576/*** Dealing with sticky menu when transparent ***/ 577$.fn.isInViewport = function() { 578 var elementTop = $(this).offset().top; 579 var elementBottom = elementTop + $(this).outerHeight(); 580 var viewportTop = $(window).scrollTop(); 581 var viewportBottom = viewportTop + $(window).height(); 582 return elementBottom > viewportTop && elementTop < viewportBottom; 583}; 584 585$.fn.copyToClipboard = function() { 586 $(this).focus(); 587 $(this).select() 588 589 document.execCommand('copy'); 590 591 swal({ 592 title : 'Content copied', 593 text: $(this).val(), 594 icon: "success", 595 button: "Continue", 596 }); 597}; 598 599$.fn.loadContent = function() { 600 // Get ajax url 601 var url = $(this).attr('data-url'); 602 603 // Get target to place content into 604 if ($(this).attr('data-target')) 605 var target = $($(this).attr('data-target')); 606 else 607 var target = $(this); 608 609 // Get target to show spinner in 610 if ($(this).attr('data-spinner-target')) 611 var spinnertarget = $($(this).attr('data-spinner-target')) 612 else 613 var spinnertarget = $(this); 614 615 // Option to not show spinner at all 616 if (!$(this).attr('data-spinner-dontshow')) 617 spinnertarget.html(getLoadingSpinner()); 618 619 // Person json communication 620 getJson({ 621 url : url 622 }, function(results) { 623 processAjaxCallback(results); 624 replaceContent(results, target); 625 }); 626}; 627 628$.fn.loadModal = function() { 629 var url = $(this).attr('data-url'); 630 631 getJson({ 632 url : url 633 }, function(results) { 634 processAjaxCallback(results); 635 launchModal(results); 636 }); 637}; 638 639$.fn.doAjax = function() { 640 var url = $(this).attr('data-url'); 641 642 // Get target to place content into 643 if ($(this).attr('data-target')) 644 var target = $($(this).attr('data-target')); 645 else 646 var target = $(this); 647 648 // Get target to show spinner in 649 if ($(this).attr('data-spinner-target')) 650 var spinnertarget = $($(this).attr('data-spinner-target')) 651 else 652 var spinnertarget = $(this); 653 654 // Option to not show spinner at all 655 if (!$(this).attr('data-spinner-dontshow')) 656 spinnertarget.html(getLoadingSpinner()); 657 658 // Person json communication 659 getJson({ 660 url : url 661 }, function(results) { 662 processAjaxCallback(results); 663 }); 664 665 666}; 667 668 669$(window).on('resize scroll', function() { 670 if ($('body').hasClass('transparent-header') && $('.transparent-trigger').length) { 671 $('#page-header').toggleClass('transparent', $('.transparent-trigger').isInViewport()); 672 } 673}); 674/*** Dealing with sticky menu when transparent ***/ 675 676function launchLoginSidebar() 677{ 678 getJson({ 679 url : '/Bliteworks/Home/Login' 680 }, function(results) { 681 processAjaxCallback(results); 682 launchSidebar(results); 683 }); 684} 685 686function showFacebookForm(elem, e) { 687 688 var status = $('.email-form').css('display'); 689 690 if (status == 'none') { 691 $('.facebook-form').slideDown();
692 $('.bf-information').slideUp(); 693 elem.attr('data-status', 'open'); 694 $('.facebook-btn').fadeOut(); 695 } else { 696 $('.facebook-form').slideUp(); 697 $('.bf-information').slideDown(); 698 elem.attr('data-status', 'closed'); 699 $('.facebook-btn').fadeIn(); 700 } 701} 702 703 704function showEmailForm(elem, e) { 705 $('.email-form').slideToggle(); 706 $('.bf-information').slideToggle(); 707 708 var main = $('.email-signup-btn'); 709 if (main.attr('data-toggle')=='true') { 710 $('.buttons .btn-facebook').fadeIn(); 711 $('.go-back-btn').hide() 712 713 main.removeClass('hide'); 714 main.attr('data-toggle', false); 715 main.attr('onclick', 'showEmailForm($(this), event)'); 716 main.text('Signup with Email') 717 } else { 718 main.addClass('hide'); 719 $('.bf-information').slideUp(); 720 $('.buttons .btn-facebook').fadeOut(); 721 $('.facebook-form').fadeOut(); 722 $('.go-back-btn').fadeIn() 723 main.attr('data-toggle', true); 724 main.text('Continue') 725 main.attr('onclick','$(".brand-fan-form").submit()') 726 } 727 728} 729 730 731function bindFormEvents() 732{ 733 $('form.submitForm').on('submit.form', function(event) { 734 event.preventDefault(); 735 submitForm($(this), event); 736 }); 737} 738 739function unbindFormEvents() 740{ 741 $('form.submitForm').off('submit.form'); 742} 743 744function bindPasswordEvents() { 745 746 var strength = { 747 contains_number: false, 748 contains_uppercase: false, 749 contains_min_max: false, 750 }; 751 752 $('.new-password').bind('input.password propertychange.password', function (e) { 753 // does password contain one number 754 strength.contains_number = (/\d/.test($(this).val()) ? true : false ); 755 strength.contains_uppercase = (($(this).val().match(/[a-z]/g) !== null && $(this).val().match(/[A-Z]/g) !== null) ? true : false ); 756 strength.contains_min_max = ($(this).val().length >= 8 && $(this).val().length <= 36 ? true : false ); 757 758 if (strength.contains_number) { 759 $('.contains_number').addClass('text-success') 760 .find('i').attr('class', 'fa fa-check-square'); 761 } else { 762 $('.contains_number').removeClass('text-success') 763 .find('i').attr('class', 'fa fa-check-square-o'); 764 } 765 766 if (strength.contains_uppercase) { 767 $('.contains_uppercase').addClass('text-success') 768 .find('i').attr('class', 'fa fa-check-square'); 769 } else { 770 $('.contains_uppercase').removeClass('text-success') 771 .find('i').attr('class', 'fa fa-check-square-o'); 772 } 773 774 if (strength.contains_min_max) { 775 $('.contains_min_max').addClass('text-success') 776 .find('i').attr('class', 'fa fa-check-square'); 777 } else { 778 $('.contains_min_max').removeClass('text-success') 779 .find('i').attr('class', 'fa fa-check-square-o'); 780 } 781 }); 782 783 $('.new-password-confirm').bind('input.password propertychange.password', function (e) { 784 if ($(this).val() == $('.new-password').val()) { 785 $('.pw-match').addClass('text-success') 786 .find('i').attr('class', 'fa fa-check-square'); 787 } else { 788 $('.pw-match').removeClass('text-success') 789 .find('i').attr('class', 'fa fa-check-square-o'); 790 } 791 }); 792} 793 794function unbindPasswordEvents() { 795 $('.new-password').off('input.password propertychange.password'); 796 797 $('.new-password-confirm').off('input.password propertychange.password'); 798} 799 800function checkPassword(elem, event) { 801 event.preventDefault(); 802 803 804 if(elem.find('.password-strength li.check').not('.text-success').length) { 805 swal( 806 'Double check the password requirements' 807 ); 808 } else { 809 submitForm(elem, event); 810 } 811} 812 813 814$(document).ajaxComplete(function() { 815 unbindFormEvents(); 816 bindFormEvents(); 817 818 unbindPasswordEvents(); 819 bindPasswordEvents(); 820 821 unbindSidebarEvents(); 822 bindSidebarEvents(); 823 824 unbindGenericFunctions(); 825 bindGenericFunctions(); 826 $('[data-toggle="tooltip"]').tooltip() 827 828}); 829 830function bindSidebarEvents() 831{ 832 $('#sidebar-close').on('click.sidebar', function(e) { 833 closeSidebar(); 834 }); 835} 836 837function unbindSidebarEvents() 838{ 839 $('#sidebar-close').off('click.sidebar'); 840} 841 842function closeSidebar() 843{ 844 var sidebar = $('.main-sidebar'); 845 846 sidebar.toggle(false) 847 848 $('body').removeClass('sidebar-open'); 849} 850 851 852 853function goSidebar(elem, event) { 854 event.preventDefault(); 855 856 var url = elem.attr('data-url'); 857 858 getJson({ 859 url : url 860 }, function(results) { 861 processAjaxCallback(results); 862 launchSidebar(results); 863 }); 864} 865 866function blockPage() { 867 $('body').addClass('sidebar-open').addClass('show-loader'); 868 $('body', window.parent.document).addClass('sidebar-open').addClass('show-loader'); 869} 870 871function unblockPage() { 872 $('body').removeClass('sidebar-open').removeClass('show-loader'); 873 $('body', window.parent.document).removeClass('sidebar-open').removeClass('show-loader'); 874} 875 876 877bindFormEvents(); 878bindPasswordEvents(); 879bindSidebarEvents(); 880 881 882 883// Moveable element 884// Make the DIV element draggable: 885 886if (document.getElementById('dragme')) 887 dragElement(document.getElementById("dragme")); 888 889function dragElement(elmnt) { 890 var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; 891 if (document.getElementById(elmnt.id + "header")) { 892 // if present, the header is where you move the DIV from: 893 document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown; 894 } else { 895 // otherwise, move the DIV from anywhere inside the DIV: 896 elmnt.onmousedown = dragMouseDown; 897 } 898 899 function dragMouseDown(e) { 900 e = e || window.event; 901 e.preventDefault();
902 // get the mouse cursor position at startup: 903 pos3 = e.clientX; 904 pos4 = e.clientY; 905 document.onmouseup = closeDragElement; 906 // call a function whenever the cursor moves: 907 document.onmousemove = elementDrag; 908 } 909 910 function elementDrag(e) { 911 e = e || window.event; 912 e.preventDefault(); 913 // calculate the new cursor position: 914 pos1 = pos3 - e.clientX; 915 pos2 = pos4 - e.clientY; 916 pos3 = e.clientX; 917 pos4 = e.clientY; 918 // set the element's new position: 919 elmnt.style.top = (elmnt.offsetTop - pos2) + "px"; 920 elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; 921 } 922 923 function closeDragElement() { 924 // stop moving when mouse button is released: 925 document.onmouseup = null; 926 document.onmousemove = null; 927 } 928} 929 930/********* MLMENU ********/ 931// @header 932/* 933 * Required menu initialization functions 934 */ 935function doMenuInit() { 936 /* mlMenu declaration */ 937 var menuEl = document.getElementById('ml-menu'); 938 939 if (menuEl) { 940 941 mlmenu = new MLMenu(menuEl, { 942 // breadcrumbsCtrl : true, // show breadcrumbs 943 // initialBreadcrumb : 'all', // initial breadcrumb text 944 backCtrl : false, // show back button 945 // itemsDelayInterval : 60, // delay between each menu item sliding animation 946 }); 947 948 // mobile menu toggle 949 var openMenuCtrl = document.querySelector('.action--open'), 950 closeMenuCtrl = document.querySelector('.action--close'); 951 952 openMenuCtrl.addEventListener('click', openMenu); 953 closeMenuCtrl.addEventListener('click', closeMenu); 954 955 function openMenu() { 956 classie.add(menuEl, 'menu--open'); 957 } 958 959 function closeMenu() { 960 classie.remove(menuEl, 'menu--open'); 961 } 962 } 963} 964/********* MLMENU ********/ 965 966 967 968 969 970/******** TOOLTIP ******/ 971// @header 972function doTooltipInit() { 973 $('[data-toggle="tooltip"]').tooltip() 974} 975/******** TOOLTIP ******/ 976 977 978 979 980 981 982 983 984 985/******** PAGE BLOCK ********/ 986// @header 987function bindPageBlock() { 988 989 // If page is blocked and showing the sidebar, close the sidebar if the user attempts to get out of the block 990 $('.page-blocker').on('click', function(event) { 991 closeSidebar(); 992 }); 993 994} 995/******** PAGE BLOCK ********/ 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015/******** Generic functions to bind to elements with specific classes ********/ 1016// @header 1017function unbindGenericFunctions() { 1018 $('.swal-confirm').off('click.generic'); 1019 $('.button-load').off('click.generic'); 1020 $('form.ajax-submit button[type="submit"]').off('click.generic'); 1021 $('.modal-load-ajax').off('click.generic'); 1022} 1023function bindGenericFunctions() { 1024 $('.modal-load-ajax').on('click.generic', function() { 1025 blockPage(); 1026 1027 var url = $(this).attr('data-url'); 1028 1029 getJson({ 1030 url : url 1031 }, function(results) { 1032 displayModal(results); 1033 unblockPage(); 1034 }); 1035 }); 1036 1037 $('.swal-confirm').bind('click.generic', function(e) { 1038 var id = $(this).attr('data-id'); 1039 var url = $(this).attr('data-url'); 1040 1041 Swal({ 1042 title: 'Are you sure?', 1043 text: "You won't be able to revert this!", 1044 type: 'warning', 1045 showCancelButton: true, 1046 confirmButtonColor: '#3085d6', 1047 cancelButtonColor: '#d33', 1048 confirmButtonText: 'Contine' 1049 }).then(function(result) { 1050 if (result.value) { 1051 blockPage(); 1052 getJson({ 1053 url : url, 1054 data : { 1055 id : id 1056 } 1057 }, function(results) { 1058 unblockPage(); 1059 processAjaxCallback(results); 1060 }); 1061 } 1062 }) 1063 }); 1064 1065 1066 /* 1067 * class : button-load 1068 * data-group : The group that will be used when searching for data to be posted 1069 * data-target : Element to place returned content into, attempts to work for admin panel if this attribute does not exists 1070 * Also works if no content is retunred 1071 * data-callback : Will attemp to execute a callback and pass the results to the callback if this attribute exists 1072 * 1073 * 1074 * Submits data in the same data-group to a url and replaces content 1075 */ 1076 $('.button-load').bind('click.generic', function(e) { 1077 blockPage(); 1078 var datagroup = $(this).attr('data-group'); 1079 var data = $('input[data-group="' + datagroup + '"]*[name]'); 1080 var ref = $(this); 1081 1082 if ($(this).is('[data-target]')) { 1083 var target = $($(this).attr('data-target')); 1084 } else { 1085 var target = $(this).closest('.portlet-body').find('.data-content'); 1086 } 1087 1088 1089 getJson({ 1090 url : $(this).attr('data-url'),
1091 data : data.serialize() 1092 }, function(results) { 1093 1094 1095 processAjaxCallback(results); 1096 1097 1098 if (ref.is('[data-callback]')) { 1099 var callback = ref.attr('data-callback'); 1100 window[callback](results); 1101 } 1102 replaceContent(results, target); 1103 unblockPage(); 1104 }); 1105 }); 1106 1107 /* 1108 * Ajax submit forms 1109 * Add class .ajax-submit to submit button 1110 * Define ajax-submit-url on parent form 1111 * Define callback function in ajax-submit-success on parent form 1112 */ 1113 $('form.ajax-submit button[type="submit"]').on('click.generic', function(e) { 1114 e.preventDefault(); 1115 1116 var ref = $(this); 1117 1118 $.ajax({ 1119 url : $(this).parents('form').attr('ajax-submit-url'), 1120 type : 'post', 1121 data : $(this).parents('form').serialize() + '&ajax=true' 1122 }).done(function(data) { 1123 processAjaxCallback(data); 1124 var d = $.parseJSON(data); 1125 1126 if (d.redirectnow) 1127 window.location.assign(d.redirectnow); 1128 1129 if (d.formKey) 1130 $('input[name="formKey"]').val(d.formKey); 1131 1132 if (d.error) { 1133 $('#message-wrapper').html(d.messages); 1134 1135 return; 1136 } 1137 1138 1139 1140 1141 func = ref.parents('form').attr('ajax-submit-success'); 1142 eval(func); 1143 }); 1144 }); 1145 /* 1146 * End ajax submit function 1147 */ 1148} 1149/******** Generic functions to bind to elements with specific classes ********/ 1150 1151 1152 1153 1154 1155 1156/******** MODAL FUNCTIONS ********/ 1157// @header 1158 1159// Launch a frontend modal with content 1160function launchModal(content) { 1161 displayStackModal(content); 1162} 1163 1164// Launch a full screen modal 1165// Under review 1166function launchFullScreenModal(content) { 1167 report(); 1168 1169 var trigger = $('.modal-trigger'); 1170 var container = trigger.closest('.modal-instance'); 1171 1172 container.addClass('menu-fullscreen'); 1173 trigger.click(); 1174 displayStackModal(content); 1175} 1176 1177// Launch the sidebar 1178function launchSidebar(content) { 1179 // convert to string if not already 1180 if (typeof content == 'string') { 1181 content = $.parseJSON(content); 1182 } 1183 1184 var sidebar = $('.main-sidebar'); 1185 sidebar.toggle(true); 1186 sidebar.find('#sidebar-content').html(content.content); 1187 1188 $('body').addClass('sidebar-open'); 1189} 1190 1191// Launch the top alert bar 1192function launchAlertBar(content) { 1193 var sidebar = $('.alertbar'); 1194 sidebar.toggle() 1195 sidebar.find('.content').html(content.content); 1196} 1197 1198/******** MODAL FUNCTIONS ********/ 1199 1200/******** PAGE BLOCKING AND LOADING FUNCTIONS ********/ 1201// @header 1202// Room for improvement using theme element blocking 1203 1204 1205 1206 1207 1208// Show a loading spinner 1209// Use this for loading in the sidebar 1210function getLoadingSpinner() { 1211 if ($('.loading-spinner').length>0) 1212 return $('.loading-spinner'); 1213 1214 return '<div class="loading-spinner clearfix"><i class="fa fa-spinner fa-spin"></i></div>'; 1215} 1216 1217 1218 1219 1220/******** PAGE BLOCKING AND LOADING FUNCTIONS ********/ 1221 1222/******** ECOMMERCE FUNCTIONS ********/ 1223// @header 1224 1225 1226 1227// *** PRODUCT FUNCTIONS *** // 1228 1229// Add configurable product to cart 1230function addConfigurableToCart(elem, e) { 1231 e.preventDefault(); 1232 1233 getJSON({ 1234 url : elem.attr('data-url'), 1235 data : $('#addToCartForm').serialize() 1236 }, function(results) { 1237 content = $.parseJSON(results); 1238 updateCartElements(results); 1239 processAjaxCallback(results); 1240 }); 1241} 1242 1243 1244 1245// Add simple product to cart 1246function addToCart(elem , e) { 1247 e.preventDefault(); 1248 1249 if ($('#qty').length) 1250 quantity = $('#qty').val(); 1251 else 1252 quantity = 1; 1253 1254 getJSON({ 1255 url: elem.attr('data-url'), 1256 data: { 1257 product_id : elem.attr('data-id'), 1258 quantity : quantity 1259 } 1260 }, function(results){ 1261 content = $.parseJSON(results); 1262 updateCartElements(results); 1263 processAjaxCallback(results) 1264 }); 1265} 1266 1267// Toggle product in autoship cart 1268function toggleAutoshipCart(elem, e) { 1269 e.preventDefault(); 1270 1271 if (elem.hasClass('in-autoship')) { 1272 removeFromAutoshipCart(elem, e); 1273 1274 elem.removeClass('in-autoship'); 1275 } else { 1276 addToAutoshipCart(elem, e); 1277 1278 elem.addClass('in-autoship'); 1279 } 1280 1281 // Get the autoship cart and show in sidebar 1282 1283 getJson({ 1284 url : elem.attr('data-autoship') 1285 }, function(results) { 1286 launchSidebar($.parseJSON(results)); 1287 }); 1288 1289} 1290 1291// Remove a product from autoship cart 1292function removeFromAutoshipCart(elem, e) { 1293 e.preventDefault(); 1294 1295 getJson({ 1296 url : elem.attr('data-url-remove'), 1297 data : { 1298 product_id : elem.attr('data-id') 1299 } 1300 }, function(results) { 1301 processAjaxCallback(results); 1302 }); 1303} 1304 1305// Add a product to autoship cart 1306function addToAutoshipCart(elem, e) { 1307 e.preventDefault(); 1308 1309 getJSON({ 1310 url : elem.attr('data-url'), 1311 data : { 1312 product_id : elem.attr('data-id') 1313 } 1314 }, function(results) { 1315 processAjaxCallback(results); 1316 }); 1317 1318 getJson({ 1319 url : elem.attr('data-autoship') 1320 }, function(results) { 1321 launchSidebar($.parseJSON(results)); 1322 }); 1323} 1324 1325// Remove product from cart 1326function removeProductFromCart(elem, e) 1327{ 1328 e.preventDefault(); 1329 1330 swal({ 1331 title: 'Are you sure?', 1332 text: "You won't be able to revert this!", 1333 icon: 'warning', 1334 buttons: { 1335 cancel: { 1336 text: "Cancel", 1337 value: null, 1338 visible: false, 1339 className: "", 1340 closeModal: true, 1341 }, 1342 confirm: { 1343 text: "Remove From Cart", 1344 value: true, 1345 visible: true, 1346 className: "", 1347 closeModal: true 1348 } 1349 } 1350 }).then(function(result) { 1351 if (result) { 1352 1353 getJSON({ 1354 url: elem.attr('href') 1355 }, function(results){ 1356 updateCartElements(results); 1357 processAjaxCallback(results); 1358 }); 1359 elem.closest('.product').hide('fast'); 1360 1361 swal( 1362 'Deleted!', 1363 'This product has been removed.', 1364 'success' 1365 ) 1366 1367 //update the cart page 1368 getJson({
1369 url : getURL({ 1370 action : 'Home_Checkout_OnePage_CartUpdate' 1371 }) 1372 }, function (results) { 1373 replaceContent(results, $('#main-container')); 1374 }); 1375 } 1376 }); 1377} 1378 1379// *** PRODUCT FUNCTIONS *** // 1380 1381 1382 1383// *** CHECKOUT FLOW FUNCTIONS *** // 1384 1385// @review functionality in work here 1386function proceedToCheckout(data) { 1387 1388 var elem = $('#cart-checkout-form'); 1389 if (data.e) { 1390 data.e.preventDefault(); 1391 } 1392 if (data.redirect) { 1393 var append = '&redirect=' + data.redirect; 1394 } else { 1395 var append = ''; 1396 } 1397 //var action = $('#checkoutForm input[name=action]').val(); 1398 var url = elem.attr('action'); //+ '?action=' + action + append; 1399 1400 1401 window.location.href = url; 1402} 1403 1404 1405// Update the minicart 1406function updateCartElements(content) { 1407 getJson({ 1408 url: getURL({ 1409 action : 'Home_Store_CartDropdown' 1410 }) 1411 }, function(result) { 1412 replaceContent(result, $('#minicart')); 1413 }); 1414 1415 content = $.parseJSON(content); 1416 1417 if (content.data.count==0) { 1418 window.location.assign(getURL({ 1419 action:'Home_Store' 1420 })) 1421 } 1422} 1423 1424// Update product quantity from the cart page 1425function updateQuantity(elem, e) 1426{ 1427 e.preventDefault(); 1428 e.stopPropagation(); 1429 var postUrl = getURL({ 1430 action: 'Home_Checkout_Update_Product' 1431 }) + '/pid/' + elem.attr('name') + '/stocktag/' 1432 + elem.attr('data-stocktag') 1433 + '/qty/' 1434 + elem.val(); 1435 1436 getJSON({ 1437 url: postUrl 1438 }, function(results) { 1439 updateCartElements(results); 1440 processAjaxCallback(results); 1441 1442 getJson({ 1443 url : getURL({ 1444 action : 'Home_Checkout_OnePage_CartUpdate' 1445 }) 1446 }, function (results) { 1447 replaceContent(results, $('#main-container')); 1448 }); 1449 }); 1450 1451} 1452 1453// Update the cart total on order review 1454function updateCartTotal() { 1455 var shipMethod = $("input[name=shipping-method]:checked").val(); 1456 1457 var shipping = shippingJson[shipMethod]; 1458 1459 var subTotal = $('#subtotal').attr('data-subtotal'); 1460 var discounts = $('.discount'); 1461 1462 var discountAmount = 0; 1463 1464 1465 discounts.each(function(index) { 1466 discountAmount = discountAmount + parseFloat($(this).attr('data-discount')); 1467 }); 1468 1469 1470 var tax = 0; 1471 var orderTotal = ((subTotal*1) + (shipping*1) + (tax*1) + (discountAmount*1)); 1472 1473 orderTotal = orderTotal.toFixed(2); 1474 1475 $('.orderTotal').html('$'+orderTotal); 1476 return true; 1477} 1478 1479// Update the shipping method used on the order review page 1480function updateShippingOption(value) { 1481 $('input[name="shipMethod"]').val(value);; 1482} 1483 1484/******** Shipping functions on order review page ********/ 1485function bindShippingFunctions() { 1486 // Order review admin custom shipping 1487 // @todo correct documentation 1488 $('.shipping-options-item [for="admin_custom"] input[type="number"]').on('input', function() { 1489 var shipping = $(this).val(); 1490 var subTotal = $('#subtotal').attr('data-subtotal'); 1491 var discounts = $('.discount'); 1492 1493 var discountAmount = 0; 1494 1495 discounts.each(function(index) { 1496 discountAmount = discountAmount + parseFloat($(this).attr('data-discount')); 1497 }); 1498 1499 var tax = 0; 1500 var orderTotal = ((subTotal*1) + (shipping*1) + (tax*1) + (discountAmount*1)); 1501 1502 orderTotal = orderTotal.toFixed(2); 1503 $('#orderTotal').html('$'+orderTotal); 1504 return true; 1505 }); 1506} 1507/******** Shipping functions on order review page ********/ 1508 1509// Update values when shipping method is changed in checkout 1510function updateShippingValues(elem,e) { 1511 e.preventDefault(); 1512 var addNewButton = '<i class="fa fa-plus"></i> Add New'; 1513 var canelAddNew = '<i class="fa fa-caret-up"></i> Close'; 1514 var formToggleButton = $('.add-new'); 1515 /* detect type */ 1516 var shippingID = elem.attr('shipping-profile-id'); 1517 1518 clearAllCheckboxes(elem); 1519 updateCheckbox(elem, e); 1520 1521 1522 // remove active class from all 1523 $('.shipping-profile-item').removeClass('active'); 1524 1525 if (shippingID=='new') {
1526 /* Update Form Toggle text */ 1527 if (elem.attr('data-toggle')==='closed') { 1528 formToggleButton.find('.cta-text').html(canelAddNew); 1529 formToggleButton.attr('data-toggle','open'); 1530 } else { 1531 formToggleButton.find('.cta-text').html(addNewButton); 1532 formToggleButton.attr('data-toggle','closed'); 1533 } 1534 1535 // Set New Card Icon as Checked 1536 $('.card-panel').eq(1).find('.check i').addClass('fa-check-square-o').removeClass('fa-square-o'); 1537 1538 /* Toggle Form */ 1539 $('#newShipping').toggleClass('hide'); 1540 $('.saved-item').slideToggle(); 1541 } else { 1542 1543 // add active class 1544 elem.addClass('active'); 1545 1546 /* Toggle Form */ 1547 $('#newShipping').addClass('hide'); 1548 } 1549 1550 /* update shipping value */ 1551 $("#shippingProfileInput").val(shippingID); 1552} 1553 1554// Update values when payment method is changed in checkout 1555function updatePaymentValues(elem,e) { 1556 e.preventDefault(); 1557 1558 var addNewButton = '<i class="fa fa-plus"></i> Add New'; 1559 var canelAddNew = '<i class="fa fa-caret-up"></i> Close'; 1560 var formToggleButton = $('.add-new'); 1561 /* detect type */ 1562 var paymentID = elem.attr('data-id'); 1563 var paymentType = elem.attr('data-payment-type'); 1564 1565 // console.log(paymentID); 1566 1567 $('.payment-method-item').removeClass('active'); 1568 elem.addClass('active'); 1569 1570 1571 clearAllCheckboxes(elem); 1572 updateCheckbox(elem, e); 1573 1574 if (paymentID=='cash') { 1575 $('#newShipping').addClass('hide'); 1576 $('.saved-items').slideUp(); 1577 $('.embedded-checkout').addClass('hide'); 1578 } 1579 1580 // if (paymentID=='new') { 1581 // 1582 // $('.embedded-checkout').toggleClass('hide'); 1583 // 1584 // /* TOGGLE the ADD NEW FORM */ 1585 // if (elem.attr('data-toggle')==='closed') { 1586 // elem.find('.cta-text').html(canelAddNew); 1587 // elem.attr('data-toggle','open'); 1588 // } else { 1589 // elem.find('.cta-text').html(addNewButton); 1590 // elem.attr('data-toggle','closed'); 1591 // } 1592 // $('#newShipping').toggleClass('hide'); 1593 // $('.saved-items').slideToggle(); 1594 // } else { 1595 // $('#newShipping').addClass('hide'); 1596 // } 1597 1598 if (paymentID == "paytrace-new") { 1599 1600 $('.paytrace-embedded').toggleClass('hide'); 1601 $('.paytrace-vaulted-cards').toggleClass('hide'); 1602 if (elem.attr('data-toggle') === 'closed') { 1603 $('.paytrace-vaulted-payment-methods .cta-text').html(canelAddNew); 1604 elem.attr('data-toggle', 'open'); 1605 } else { 1606 $('.paytrace-vaulted-payment-methods .cta-text').html(addNewButton); 1607 elem.attr('data-toggle', 'closed'); 1608 } 1609 } 1610 1611 $('#vaulted-payment-method').val(paymentID); 1612 $('#vaulted-payment-type').val(paymentType); 1613} 1614 1615function updateShippingMethod(elem, e) { 1616 1617 clearAllCheckboxes(elem); 1618 updateCheckbox(elem, e); 1619 updateCartTotal(); 1620 1621} 1622 1623// Show additional credit card forms 1624// Bake in a way to redirect to an external service for completing payment 1625function toggleCreditCardForms() { 1626 var paymentMethod = $('input[name="payment-type"]:checked').val(); 1627 if (paymentMethod in payment_config['urls'] && 'next' in payment_config['urls'][paymentMethod]){ 1628 $('.checkout').checkout.nextUrl = payment_config['urls'][paymentMethod]['next']; 1629 } 1630} 1631 1632// Wrapper function for some reason 1633function selectShippingProfile(elem, e) 1634{ 1635 updateShippingValues(elem, e) 1636} 1637 1638 1639 1640// *** CHECKOUT FLOW FUNCTIONS *** // 1641 1642 1643/******** ECOMMERCE FUNCTIONS ********/ 1644 1645 1646 1647 1648/******** ELEMENT ACTIONS ********/ 1649 1650// @header 1651 1652function jumpTo(el, offset) { 1653 $('html,body').unbind().animate({scrollTop: (el).offset().top - offset},'slow'); 1654 1655} 1656 1657 1658// Update icon 1659// @review 1660function updateIcon(elem) { 1661 $('.checkbox-icon .fa').removeClass('fa-check-square-o'); 1662 $('.checkbox-icon .fa').addClass('fa-square-o'); 1663 1664 var thisButton = elem.find('.fa'); 1665 thisButton.addClass('fa-check-square-o'); 1666 thisButton.removeClass('fa-square-o'); 1667 return elem; 1668} 1669 1670// Clear all the checkboxes in a container element 1671// @review 1672function clearAllCheckboxes(container_elem) { 1673 var classes = ''; 1674 1675 // select all classes 1676 $.each(container_elem.attr('class').trim().split(' '), function(index, value){ 1677 value = value.trim(); 1678 if (value && value != '' && value !== null) { 1679 classes = classes + '.' + value; 1680 } 1681 }); 1682 1683 // uncheck classes 1684 var allCheckboxes = $( classes + ' input'); 1685 $.each(allCheckboxes, function(i, value){ 1686 allCheckboxes.eq(i)[0].checked = false 1687 }); 1688} 1689 1690// Clean form inputs 1691function cleanInputs() { 1692 var inputs = $('#brandfan-signup-form, #customer-signup-form'); 1693 $.each(inputs,function(index, value){ 1694 $.each($(value).find('.form-control'), function(i,input){ 1695 var name = $(input).attr('name'); 1696 if (name == 'firstname' 1697 || name == 'lastname' 1698 // || name == 'phone' 1699 || name == 'email' 1700 || name == 'username' 1701 || name == 'password') 1702 { 1703 // attach event handler 1704 $(this).keyup(function(){ 1705 var newValue = $(this).val().replace(/\s+/g, '') 1706 $(this).val(newValue); 1707 }); 1708 } else { 1709 } 1710 }); 1711 }); 1712} 1713 1714function updateCheckbox(elem, e) { 1715 e.preventDefault(); 1716 if (input = elem.find('input')) { 1717 if (input[0] !==undefined ) { 1718 if (!input[0].checked) { 1719 input[0].checked = true; 1720 } else { 1721 input[0].checked = false;
1722 } 1723 } 1724 } else { 1725 console.log('the attached function element does not have a checkbox inside of parent') 1726 } 1727} 1728/******** ELEMENT ACTIONS ********/ 1729 1730$(function () { 1731 $('[data-toggle="tooltip"]').tooltip() 1732})
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.