//Global JS functions for adding events and ajax cross browser function addEvent(obj, evType, fn, useCapture){ if (obj.addEventListener){ obj.addEventListener(evType, fn, useCapture); return true; }else if(obj.attachEvent){ var r = obj.attachEvent("on"+evType, fn); return r; }else{ //error } } function createRequestObject() { var ro; var browser = navigator.appName; if(browser == "Microsoft Internet Explorer"){ ro = new ActiveXObject("Microsoft.XMLHTTP"); }else{ ro = new XMLHttpRequest(); } return ro; } function nocache(){ var d = new Date(); return ((d.getTime())*1) } function is_child(parent_name, child_ele){ if (child_ele.tagName != 'BODY'){ if (child_ele.id == parent_name){ return true; }else{ return is_child(parent_name, child_ele.parentNode); } }else{ return false; } } //end global functions // Delete contents of a text box function del_contents(ele, text){ if (ele.value == text){ ele.value = ""; } } // ... then add them back in function add_contents(ele, text){ if (ele.value == ""){ ele.value = text; } } function search_hide(){ document.getElementById('search_results_container').style.display = 'none'; document.getElementById('search_results').innerHTML = ' '; } //end ajax search function toggle_filters(){ if(document.getElementById('filter_block').style.display=='block'){ document.getElementById('filter_block').style.display='none'; document.getElementById('toggle_filter_html').innerHTML='Show Refine your results'; }else{ document.getElementById('filter_block').style.display='block'; document.getElementById('toggle_filter_html').innerHTML='Hide Refine your results'; } } var overlay_obj = createRequestObject(); var overlay_sent = 0; function overlay_show(lurl){ overlay_obj.abort(); if (lurl.indexOf('?') > 0){ overlay_obj.open('get', PATH + 'olay/' + lurl + '&nocache=' + nocache()); }else{ overlay_obj.open('get', PATH + 'olay/' + lurl + '?nocache=' + nocache()); } overlay_obj.onreadystatechange = overlay_show_response; overlay_obj.send(null); return false; } function overlay_show_response(){ if(overlay_obj.readyState == 4){ if(overlay_obj.status == 200){ document.getElementById('olay_content').innerHTML = overlay_obj.responseText; document.getElementById('olay').style.display = 'block'; $('#selectbox').select2(); $('html, body').animate({ scrollTop: ($('#olay_box_container').offset().top - 20) }, 1200); } } } function overlay_hide(e=false){ if(e != false && $(e).closest('#olay').hasClass('newsletter-olay')) { $(e).closest('#olay').removeClass('newsletter-olay'); _self.util.createCookie('nlsuvc', '1', 365, ''); } document.getElementById('olay').style.display = 'none'; } function toggle_sub_cats(ele_id, bg_class){ if(document.getElementById('js_container_block_' + ele_id).style.display=='none'){ document.getElementById('js_container_block_' + ele_id).style.display = 'block'; if(bg_class){ document.getElementById('js_top_cat_' + ele_id).className = bg_class + ' js_cat_menu_open'; } document.getElementById('js_top_cat_' + ele_id).title = 'Click (-) to hide this section'; }else{ document.getElementById('js_container_block_' + ele_id).style.display = 'none'; if(bg_class){ document.getElementById('js_top_cat_' + ele_id).className = bg_class + ' js_cat_toggle'; } document.getElementById('js_top_cat_' + ele_id).title = 'Click (+) to expand this section'; } } function toggle_sub_lists(ele_id, bg_class){ if(document.getElementById('js_list_container_block_' + ele_id).style.display=='none'){ document.getElementById('js_list_container_block_' + ele_id).style.display = 'block'; if(bg_class){ document.getElementById('js_top_cat_' + ele_id).className = bg_class + ' js_cat_menu_open'; } document.getElementById('js_top_cat_' + ele_id).title = 'Click (-) to hide this section'; }else{ document.getElementById('js_list_container_block_' + ele_id).style.display = 'none'; if(bg_class){ document.getElementById('js_top_cat_' + ele_id).className = bg_class + ' js_cat_toggle'; } document.getElementById('js_top_cat_' + ele_id).title = 'Click (+) to expand this section'; } } //product list - adjust row heights function height_correct(container){ var height_max = 0; var height_cur = 0; var rowele = new Array(); var z = 0; var cont = document.getElementById(container); for(var x=0; x < cont.childNodes.length; x++){ for(var y=0; y < cont.childNodes[x].childNodes.length; y++){ var curele = cont.childNodes[x].childNodes[y] if (curele.nodeName == 'DIV'){ if (curele.className.indexOf('prod_text') > -1){ rowele[z] = curele; z++; height_cur = parseInt(curele.offsetHeight); if (height_cur > height_max){ height_max = height_cur; } } } } var curele = cont.childNodes[x]; if (curele.nodeName == 'DIV'){ if (curele.className.indexOf('clear') > -1){ for(z=0; z < rowele.length; z++){ rowele[z].style.height = height_max + 'px'; } height_max = 0; z = 0; var rowele = new Array(); } } } } function height_correct_class(className){ var highest = 0; var height = 0; $(className).each(function(){ height = $(this).height(); if(height > highest){ highest = height; } }); $(className).height(highest); } function isScrolledIntoView(elem, type, offset) { var $elem = jQuery(elem); var $window = jQuery(window); var docViewTop = $window.scrollTop(); var docViewBottom = docViewTop + $window.height(); var elemTop = $elem.offset().top + (offset || 0); var elemBottom = elemTop + $elem.height() + (offset || 0); if (type == 1) { // top in view return (elemTop >= docViewTop) && (elemTop <= docViewBottom); } else if (type == 2) { // partly in view (top or bottom) return ((elemTop >= docViewTop) && (elemTop <= docViewBottom)) || ((elemBottom >= docViewTop) && (elemBottom <= docViewBottom)); } else if (type == 3) { // bottom in view return (elemBottom >= docViewTop) && (elemBottom <= docViewBottom); } else if (type == 4) { // past top return (elemTop <= docViewBottom); } else if (type == 5) { // past bottom return (elemBottom <= docViewBottom); } else { // whole element in view return (elemBottom <= docViewBottom) && (elemTop >= docViewTop); } } function pageRequest(ele, catID, manuID, pageNum, filters, cb) { var $ = jQuery; var params = $.param({ cat_id: catID, manu_id: manuID, p: pageNum }); if (filters) { params = params + '&' + filters; } var $spinner = $('
'); var $prodContainer = $(ele); $.ajax({ type: 'GET', url: '/ajax/ajax_lazy_cat.php', data: params, dataType: 'html', beforeSend: function() { $prodContainer.append($spinner.fadeIn()); }, error: function () { $spinner.remove(); }, success: function (data) { var $html = $('
').html(data); var products = $html.find('.product-grid').html(); $spinner.remove(); $(products).appendTo($prodContainer).imagesLoaded().then(function () { if (typeof cb == 'function') { cb(); } }); } }); } var pagePosition = (function () { var pageInView = 0; var listingInView = 0; return function () { var highestPage = 0; var firstListing = 0; $('.prod_item').each(function () { var $this = jQuery(this); var page = $this.data('page') || 1; var optID = $this.data('list'); if (isScrolledIntoView(this, 2)) { if (page > highestPage) { highestPage = page; } if (isScrolledIntoView(this, 1)) { if (!firstListing) { firstListing = optID; } } } }); pageInView = highestPage || pageInView; listingInView = firstListing || listingInView; window.location.hash = pageInView + '-' + listingInView; }; })(); function positionPage(position) { var pagePosition = jQuery('.prod_item[data-list="' + position + '"]'); if (pagePosition[0]) { var offset = pagePosition.offset().top; jQuery(window).scrollTop(offset - 100); } } function requestPageState(startPage, endPage, param, cb) { pageRequest(param.container, param.catID, param.manuID, (startPage + 1), param.urlFilters, function () { startPage++; if (startPage < endPage) { requestPageState(startPage, endPage, param, cb); } else if (typeof cb == 'function') { cb(startPage); } }); } function loadPageState(startPage, total, param, cb) { var hash = window.location.hash.replace('#', ''); if (typeof cb != 'function') { cb = function(){}; } if (hash) { var hashArr = hash.split('-'); var page = hashArr[0]; var position = hashArr[1]; if (page && startPage < page) { page = (page > total) ? total : page; requestPageState(startPage, page, param, function (finalPage) { cb(finalPage); positionPage(position); }); } else { cb(); positionPage(position); } } else { cb(); } } var delay = (function () { var timer = 0; return function (callback, ms) { clearTimeout(timer); timer = setTimeout(callback, ms); }; })(); var searchAjaxXHR; function searchAjax(ele) { var q = ele.value; searchSync(q, ele); if (q.length > 2) { delay(function () { if (searchAjaxXHR && searchAjaxXHR.readystate != 4) { searchAjaxXHR.abort(); } searchAjaxXHR = jQuery.ajax({ type: 'GET', url: '/ajax/ajax_full_search.php', data : { q: q }, dataType: 'html', success: function (data) { jQuery('main').html(data); updateSearchURL(q); //Uncomment if using ajax filters //searchFilterSetup(q); //Uncomment if using pagination //searchPagination(q); } }); }, 250); } } function searchAjaxFilter(q, params) { jQuery.ajax({ type: 'GET', url: '/ajax/ajax_full_search.php' + params, dataType: 'html', success: function (data) { jQuery('main').html(data); updateSearchURL(q, params); //Uncomment if using ajax filters //searchFilterSetup(q); //Uncomment if using pagination //searchPagination(q); } }); } function searchFilterSetup(q) { jQuery('.filter li a').on('click', function (e) { e.preventDefault(); var filterUrl = jQuery(this).attr('href'); searchAjaxFilter(q, filterUrl); }); } function searchSync(query, ele) { var searchMain = document.getElementById('search-main'); var searchSecondary = document.getElementById('search-secondary'); if (searchMain && (!ele || (ele && ele != searchMain))) { searchMain.value = query; } if (searchSecondary && (!ele || (ele && ele != searchSecondary))) { searchSecondary.value = query; } } function searchRequest(ele, q, pageNum, filters, cb) { var $ = jQuery; var params = $.param({ q: q, p: pageNum }); if (filters) { params = params + '&' + filters; } var $spinner = $('
'); var $prodContainer = $(ele); $.ajax({ type: 'GET', url: '/ajax/ajax_full_search.php', data: params, dataType: 'html', beforeSend: function() { $prodContainer.append($spinner.fadeIn()); }, error: function () { $spinner.remove(); }, success: function (data) { var $html = $('
').html(data); var products = $html.find('.product-grid').html(); $spinner.remove(); $(products).appendTo($prodContainer).imagesLoaded().then(function () { if (typeof cb == 'function') { cb(); } }); } }); } function requestSearchState(startPage, endPage, param, cb) { searchRequest(param.container, param.q, (startPage + 1), param.urlFilters, function () { startPage++; if (startPage < endPage) { requestSearchState(startPage, endPage, param, cb); } else if (typeof cb == 'function') { cb(startPage); } }); } function loadSearchState(startPage, total, param, cb) { var hash = window.location.hash.replace('#', ''); if (typeof cb != 'function') { cb = function(){}; } if (hash) { var hashArr = hash.split('-'); var page = parseInt(hashArr[0], 10); var position = parseInt(hashArr[1], 10); if (page && startPage < page) { page = (page > total) ? total : page; requestSearchState(startPage, page, param, function (finalPage) { cb(finalPage); positionPage(position); }); } else { cb(); positionPage(position); } } else { cb(); } } function searchPagination(q) { var data = $.parseJSON($("#json_data").html()); var pagination = $('#page_numbers'); destroySearchPagination(); if (pagination[0]) { window.lazyPagination = { currPage: data.currPage, ttlPages: data.ttlPages, requestedPage: data.currPage, urlFilters: data.urlFilters, container: '#prod_container_ajax', loadingPage: false, pagination: pagination, q: q } pagination.empty(); $(window).on('scroll', searchPaginationScroll); } } function destroySearchPagination() { delete window.lazyPagination; $(window).off('scroll', searchPaginationScroll); } function searchPaginationScroll() { var lazy = lazyPagination; if (!lazy.loadingPage && (lazy.currPage != lazy.ttlPages) && isScrolledIntoView(lazy.pagination) && (lazy.requestedPage == lazy.currPage)) { lazyPagination.requestedPage = lazy.currPage + 1; searchRequest(lazy.container, lazy.q, lazy.requestedPage, lazy.urlFilters, function () { lazyPagination.currPage++; heightCorrect(); }); } pagePosition(); } function updateSearchURL(q, params) { var searchTitle = 'Search Results for: ' + q, searchUrl = '/search.php' + ((params) ? params : '?q=' + q); if (history.replaceState) { history.replaceState({}, searchTitle, searchUrl); } document.title = searchTitle; } // https://stackoverflow.com/questions/4774746/jquery-ajax-wait-until-all-images-are-loaded $.fn.imagesLoaded = function () { // get all the images (excluding those with no src attribute) var $imgs = this.find('img[src!=""]'); // if there's no images, just return an already resolved promise if (!$imgs.length) {return $.Deferred().resolve().promise();} // for each image, add a deferred object to the array which resolves when the image is loaded (or if loading fails) var dfds = []; $imgs.each(function(){ var dfd = $.Deferred(); dfds.push(dfd); var img = new Image(); img.onload = function(){dfd.resolve();} img.onerror = function(){dfd.resolve();} img.src = this.src; }); // return a master promise object which will resolve when all the deferred objects have resolved // IE - when all the images are loaded return $.when.apply($,dfds); } /* Dropdowns e.g. FAQ page */ function ddHideAll(){ for(var x=0; x < ddblocks; x++){ var ddtext = $('#ddtext_' + x); ddtext.hide(); } ddUpdate(); } function ddUpdate(){ for(var x=0; x < ddblocks; x++){ var ddtext = $('#ddtext_' + x), ddtitle = $('#ddtitle_' + x) ddblock = $('#ddblock_' + x); if (ddtext.css('display') == 'none'){ ddtitle.removeClass('dd-open'); ddblock.removeClass('open'); }else{ ddtitle.addClass('dd-open'); ddblock.addClass('open'); } } } function ddToggle(q, hideall){ var ddtext = $('#ddtext_' + q), ddtextClass = $('.dd-text'); if (hideall) { ddtextClass.not(ddtext).stop().slideUp(300, function() { ddUpdate(); }); } if (ddtext.css('display') == 'none'){ ddtext.stop().slideDown(300, function() { ddUpdate(); }); }else{; ddtext.stop().slideUp(300, function() { ddUpdate(); }); } } function notify_up(){ document.getElementById('msg_layer').style.display = "block"; setTimeout(function() { notify_down(); }, 4000); } function notify_down(){ $('#msg_layer').fadeOut(); } /* Smart resize and scroll */ function debounce(a,b,c){var d;return function(){var e=this,f=arguments;clearTimeout(d),d=setTimeout(function(){d=null,c||a.apply(e,f)},b),c&&!d&&a.apply(e,f)}} jQuery.fn.smartresize = function(fn){ return fn ? this.bind('resize', debounce(fn, 100)) : this.trigger(smartresize); }; jQuery.fn.smartscroll = function(fn){ return fn ? this.bind('scroll', debounce(fn, 100)) : this.trigger(smartscroll); }; //START NEW FUNCTIONS var opt_sel = {}; function option_update(container, submitcount, no_html){ option_update_selected(container); console.log(container); if(!no_html){ $(".options-loading").show(); } $.ajax({ url: '/ajax/ajax_options.php', data: { clid: $('#listing_' + submitcount).val(), sel: JSON.stringify(opt_sel), sub_dow: JSON.stringify($(container + ' #subscription_del_preferred').val()), sub_period: $(container + ' #subscription_del_period').val(), increment: submitcount, opt_limit: $('#opt_limit').val() }, dataType: 'json', error: function(e) { $(".options-loading").hide(); }, success: function(data) { if(!no_html){ $(container).html(data.html); } $("#options_" + submitcount).val(JSON.stringify(opt_sel)); //Reinitialise some things that require container context //Re-init select2 and dropdown borders core.form.select2($(container + ' .select_input')); $(container + ".checkout-form--select-input, .checkout-form--text-input").bind({ "open focus change select2:open": function(event) { core.checkout.addInputFocus($(event.target)); }, "close blur change select2:close": function(event) { core.checkout.removeInputFocus($(event.target)); } }); $(container + " .checkout-form--text-input").trigger('change'); $(':focus').focus(); //overlay_process_dropdownchecklist(); option_addevents(container, submitcount); $.each(data.runFirst,function(key, value){ eval(value); }); $.each(data.replace,function(key, values){ $.each(values,function(unused, value){ if (typeof value.attr !== 'undefined'){ $(key).attr(value.attr,value.value); //console.log('Attr: ', key, value.attr, value.value); }else if(typeof value.html !== 'undefined'){ $(key).html(value.html); //console.log('HTML: ', key, value.html); }else if(typeof value.prop !== 'undefined'){ $(key).prop(value.prop,value.value); //console.log('Prop: ', key, value.prop, value.value); } }); }); $.each(data.run,function(key, value){ //console.log('Eval: ', key, value); eval(value); }); $(".options-loading").fadeOut(); } }); } function option_key(name){ var parts = name.split("_"); parts.shift(); return parts; } function option_push(name, value, qty, extra){ var parts = option_key(name); opt_sel = option_create_object(parts,value,qty,opt_sel,extra); } function option_create_object(remaining, value, qty, tomerge, extra){ var v = remaining.shift(); if (!tomerge){ var tomerge = {}; } if (remaining.length > 0){ tomerge[v] = option_create_object(remaining, value, qty, tomerge[v], extra); }else{ var merge_obj = {'sel':value, 'qty': qty}; for(i in extra){ merge_obj[i] = extra[i]; } tomerge[v] = merge_obj; } return tomerge; } function option_update_selected(container){ opt_sel = {}; var option_selectors, option_extras, option_extra_data_arr; var option_selectors_arr = [ container + ' input[type=radio]:checked.opt_radio', container + ' input[type=hidden].opt_hidden', container + ' select.opt_dd', container + ' .opt_swatch.sel', container + ' .option-input' ]; var option_extras_arr = [ container + ' input[type=checkbox]:checked', container + ' input[type=radio]:checked', container + ' input[type=date]', container + ' input[type=datetime]', container + ' input[type=hidden]', container + ' input[type=month]', container + ' input[type=number]', container + ' input[type=range]', container + ' input[type=tel]', container + ' input[type=time]', container + ' input[type=url]', container + ' input[type=week]', container + ' select', container + ' .option_input_extra' ]; option_selectors = option_selectors_arr.join(); option_extras = option_extras_arr.join(); option_extra_data_arr = []; $(option_extras).each(function(index, element) { var name = (typeof($(this).data('name')) == 'undefined' ? this.name : $(this).data('name')); var value = (typeof($(this).data('value')) == 'undefined' ? this.value : $(this).data('value')); var name_split = name.split('_'); var name_parts = [name_split.shift(), name_split.join('_')]; var type = name_parts[0]; var id_tree = name_parts[1]; if(!option_extra_data_arr[id_tree]){ option_extra_data_arr[id_tree] = []; } if(type != 'option'){ option_extra_data_arr[id_tree][type] = value; } }); $(option_selectors).each(function(index, element) { var name = (typeof($(this).data('name')) == 'undefined' ? this.name : $(this).data('name')); var value = (typeof($(this).data('value')) == 'undefined' ? this.value : $(this).data('value')); var name_split = name.split('_'); var name_parts = [name_split.shift(), name_split.join('_')]; var type = name_parts[0]; var id_tree = name_parts[1]; var extra_data = {}; var qty; if(!option_extra_data_arr[id_tree]){ option_extra_data_arr[id_tree] = []; } if(option_extra_data_arr[id_tree]){ for(i in option_extra_data_arr[id_tree]){ if(i != 'qty'){ extra_data[i] = option_extra_data_arr[id_tree][i]; } } } if(option_extra_data_arr[id_tree]['qty']){ qty = parseInt(option_extra_data_arr[id_tree]['qty']); } var value_valid = false; if(parseInt(value) == value){ if(value > 0){ value_valid = true; } } else { if(typeof value == 'string'){ if(value != ''){ value_valid = true; } } } if(value_valid && type == 'option'){ option_push(name, value, qty, extra_data); } }); } function option_addevents(container, submitcount){ $(container + ' .opt_dd').on('change',function() { $(container + ' .input-qty').remove(); option_update(container, submitcount); }); $(container + ' input[type=radio]').on('change',function(){ $(container + ' .input-qty').remove(); option_update(container, submitcount); }); $(container + ' input[type=checkbox]').on('change',function(){ $(container + ' .input-qty').remove(); option_update(container, submitcount); }); //event listener for swatches $(container + ' .opt_swatch').on('click', function(){ $(container + ' .input-qty').remove(); var $this = $(this); $this.siblings().removeClass('sel'); $this.addClass('sel'); option_update(container, submitcount); }); //Update options on quantity change $(container + ' .opt_qty').on('change',function() { option_update(container, submitcount); }); //Update options when editable inputs change $(container + ' .option-input').on('blur',function() { if($(this).data('current_val') != $(this).val()){ option_update(container, submitcount, true); $(this).data('current_val', $(this).val()); } }); var inputChangeTimeout; $(container + ' .option-input').on('keyup',function() { $this = $(this); clearTimeout(inputChangeTimeout); inputChangeTimeout = setTimeout(function(){ if($this.data('current_val') != $this.val()){ option_update(container, submitcount, true); $this.data('current_val', $this.val()); } }, 500); }); $('#submit_' + submitcount + ', #subscribe_' + submitcount + ', #compare_' + submitcount + ', #wishlist_' + submitcount + ', .listing-notify').on('click', function(){ var opt_validate = option_validate(submitcount); if(opt_validate){ option_update_selected(container); $('#options_' + submitcount).val(JSON.stringify(opt_sel)); $('#options_' + submitcount + ', #stocknotify-options').val(JSON.stringify(opt_sel)); } else { return false; } }); } function option_validate(increment){ var $required = $('#form_options_' + increment).find('.opt-required'); var error = false; $required.each(function(index, element) { var $element = $(element); if($element.val() == -1 || $element.val() == null){ option_validate_trigger($element, increment, false); error = true; } else { option_validate_trigger($element, increment, true); } }); if(error){ return false; } else { return true; } } function option_validate_trigger(element, increment, trigger){ if(trigger){ //Hide the error element.removeClass('validate-border'); element.next().find('.select2-basic--container').removeClass('validate-border'); } else { //Show the error $('#form_options_' + increment).data('option-required-error', 1); $('#form_options_' + increment).find('.listing-options-required').show(); element.addClass('validate-border'); element.next().find('.select2-basic--container').addClass('validate-border'); } } $.fn.isOnScreen = function(offset){ var win = $(window); var viewport = { top : win.scrollTop(), left : win.scrollLeft() }; var offset = (offset) ? offset : 0; viewport.right = viewport.left + win.width(); viewport.bottom = viewport.top + win.height(); var bounds = this.offset(); bounds.right = bounds.left + this.outerWidth(); bounds.bottom = bounds.top + (this.outerHeight() - offset); bounds.top = (bounds.top + offset); return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom)); }; $(document).ready(function() { $(".header-catalogue-link").on("click", function() { var $createOverlay = core.overlay.ajaxOverlay({ url: "/olay/catalogue.php", data: {} }); $createOverlay.done(function (data) { $('main').append(data); var $modal = $('.modal'); $modal.on('click', '.modal--backdrop, .modal--close', function () { $modal.remove(); }); }); }) }); function uuidv4() { return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); }