> 16) + amt;
if ( r > 255 ) r = 255;
else if (r < 0) r = 0;
var b = ((num >> 8) & 0x00FF) + amt;
if ( b > 255 ) b = 255;
else if (b < 0) b = 0;
var g = (num & 0x0000FF) + amt;
if ( g > 255 ) g = 255;
else if ( g < 0 ) g = 0;
return ('#') + (g | (b << 8) | (r << 16)).toString(16);
}
theme.horizontalScroller = function(selector, config)
{
const _this = this;
const elem = document.querySelector(selector);
config = config || {};
if( !elem )
{
return false;
}
if( !config.enableNav && !elem.classList.contains('horizontal-scroller') )
{
elem.classList.add('horizontal-scroller');
}
const parent = elem.parentNode;
this.elem = elem;
this.isScrolling = false;
this.scrollTimes = 0;
this.lastPosition = 0;
this.scrollByAmount = 0;
let direction = null;
this.isScrollable = function()
{
return elem.scrollWidth > elem.clientWidth;
}
parent.classList.add('horizontal-scroller-start');
function clearDirection(){ direction = null; console.log('****************** CLEARED DIRECTION ******************'); }
let directionTimeout = setTimeout(clearDirection, 1000);
this.throttleTimer = function()
{
setTimeout( function() { this.isScrolling = false; console.log('throttle'); }.bind(this), 30);
}
this.scrollHandler = function(e)
{
// if( Math.abs(elem.scrollLeft) === elem.scrollWidth - elem.clientWidth )
// {
// parent.classList.add('horizontal-scroller-end');
// }
// else if( elem.scrollLeft === 0 )
// {
// parent.classList.add('horizontal-scroller-start');
// }
// else
// {
// parent.classList.remove('horizontal-scroller-start');
// parent.classList.remove('horizontal-scroller-end');
// }
_this.revalidate();
};
this.wheelHandler = function(e)
{
// theme.log('dY: '+ e.deltaY);
// theme.log('dX: '+ e.deltaX);
//e.preventDefault();
//if( (e.deltaX !== 0 && e.deltaY === 0) || this.isScrolling)
if( !this.isScrollable() )
{
return;
}
if( this.isScrolling)
{
e.preventDefault();
return;
}
function preventDefault()
{
console.log('PreventDefault');
e.preventDefault();
}
if( !direction || direction === 'y' )
{
preventDefault();
}
this.scrollTimes = Math.min(1.5, Math.max(1, this.scrollTimes+0.25));
if( elem.scrollLeft === this.lastScrollLeft )
{
this.scrollTimes = 1;
}
//theme.log('this.scrollTimes: '+this.scrollTimes);
let frames = 0;
clearTimeout(directionTimeout);
directionTimeout = setTimeout(clearDirection, 100);
let interval = setInterval( function()
{
let deltaPos;
if( !direction )
{
if( Math.abs(e.deltaX) > Math.abs(e.deltaY) )
{
//console.log("dX > dY: "+e.deltaX+ " / "+e.deltaY);
//deltaPos = e.deltaX;
direction = 'x';
//clearInterval(interval);
return;
}
else
{
//deltaPos = e.deltaY;
direction = 'y';
}
}
e.preventDefault();
deltaPos = direction === 'x' ? e.deltaX : e.deltaY;
if( deltaPos === 0 )
{
console.log('not moving');
// Not moving?
clearInterval(interval);
return;
}
console.log(direction);
//this.scrollByAmount = Math.max(1, Math.min(5, Math.abs(e.deltaY))) * this.scrollTimes;
this.scrollByAmount = Math.max(1, Math.min(5, Math.abs(deltaPos))) * this.scrollTimes;
//elem.scrollLeft = e.deltaY < 0 ? (elem.scrollLeft - this.scrollByAmount) : (elem.scrollLeft + this.scrollByAmount);
elem.scrollLeft = deltaPos < 0 ? (elem.scrollLeft - this.scrollByAmount) : (elem.scrollLeft + this.scrollByAmount);
let maxFrames = 20;
maxFrames = Math.max(5, Math.min(20, (this.scrollByAmount * 4)));
//console.log(this.scrollByAmount + ' / ' + maxFrames );
frames++;
if( frames >= maxFrames )
{
this.lastScrollLeft = elem.scrollLeft;
clearInterval(interval);
return;
}
}.bind(this), 5);
this.isScrolling = true;
this.throttleTimer();
};
this.revalidate = function()
{
theme.log('horizontalScroller.revalidate() '+selector);
if( _this.isScrollable() )
{
parent.classList.add('is-scrollable');
parent.classList.remove('not-scrollable');
if( Math.abs(elem.scrollLeft) === elem.scrollWidth - elem.clientWidth )
{
theme.log('scroller = end');
parent.classList.add('horizontal-scroller-end');
parent.classList.remove('horizontal-scroller-start');
}
else if( elem.scrollLeft === 0 )
{
theme.log('scroller = start');
parent.classList.add('horizontal-scroller-start');
parent.classList.remove('horizontal-scroller-end');
}
else
{
theme.log('scroller = in betwen?');
parent.classList.remove('horizontal-scroller-start');
parent.classList.remove('horizontal-scroller-end');
}
}
else
{
parent.classList.remove('is-scrollable');
parent.classList.add('not-scrollable');
parent.classList.remove('horizontal-scroller-start');
parent.classList.remove('horizontal-scroller-end');
}
};
if( config.observer )
{
var observer = new MutationObserver(function(mutations, observer)
{
_this.revalidate();
});
observer.observe(this.elem, {
childList: true
});
}
function enableNav()
{
const moveAmount = Math.round(elem.clientWidth / 2);
let leftElem, rightElem;
if( !config.navigation )
{
leftElem = document.createElement('i');
leftElem.classList.add('icon-angle-left', 'horizontal-scroll-icon', 'horizontal-scroll-icon-left');
rightElem = document.createElement('i');
rightElem.classList.add('icon-angle-right', 'horizontal-scroll-icon', 'horizontal-scroll-icon-right');
elem.parentNode.appendChild(leftElem);
elem.parentNode.appendChild(rightElem);
}
else
{
leftElem = $qs(config.navigation.left);
rightElem = $qs(config.navigation.right);
}
leftElem.addEventListener('click', function()
{
elem.style.scrollBehavior = "smooth";
elem.scrollLeft -= moveAmount;
elem.style.scrollBehavior = "auto";
});
rightElem.addEventListener('click', function()
{
elem.style.scrollBehavior = "smooth";
elem.scrollLeft += moveAmount;
elem.style.scrollBehavior = "auto";
});
elem.classList.add('horizontal-scroller-with-nav');
}
elem.addEventListener("wheel", this.wheelHandler.bind(this));
// if( config.enableNav === true && elem.scrollWidth > elem.clientWidth ) // && window.innerWidth > 767 )
// {
// enableNav();
// elem.addEventListener("scroll", this.scrollHandler.bind(this));
// }
if( config.enableNav === true ) // && window.innerWidth > 767 )
{
enableNav();
}
elem.addEventListener("scroll", this.scrollHandler.bind(this));
let checkResize;
window.addEventListener('resize', function()
{
clearTimeout(checkResize);
checkResize = setTimeout(_this.revalidate, 250);
});
this.revalidate();
if( true )
{
let pos = { top: 0, left: 0, x: 0, y: 0 };
const mouseMoveHandler = function (e) {
console.log('MM!');
// How far the mouse has been moved
const dx = e.clientX - pos.x;
const dy = e.clientY - pos.y;
console.log(dx);
if( Math.abs(dx) > 2 )
{
elem.classList.add('horizontal-scroller-is-dragging');
}
// Scroll the element
elem.scrollTop = pos.top - dy;
elem.scrollLeft = pos.left - dx;
};
const mouseUpHandler = function () {
console.log('MU!');
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
elem.style.cursor = 'grab';
elem.style.removeProperty('user-select');
elem.classList.remove('horizontal-scroller-is-dragging');
};
const mouseDownHandler = function (e) {
console.log('MD!');
elem.style.cursor = 'grabbing';
elem.style.userSelect = 'none';
pos = {
// The current scroll
left: elem.scrollLeft,
top: elem.scrollTop,
// Get the current mouse position
x: e.clientX,
y: e.clientY,
};
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
};
elem.addEventListener('mousedown', mouseDownHandler);
}
}
theme.hooks = {};
theme.events = {
fire: function(eventName, detail)
{
detail = detail || null;
if( false ) //isIE?
{
this[eventName] = document.createEvent(eventName);
this[eventName].initCustomEvent(eventName, false, false, {
detail: detail
});
}
else
{
this[eventName] = new CustomEvent(eventName, {
detail: detail
});
}
theme.logGroup('Dispatching customEvent '+eventName+' with detail:', true);
theme.log(detail);
theme.logGroupEnd();
window.dispatchEvent(this[eventName]);
},
handlers: {
onThemeCollectionChanged: function(e)
{
console.log('theme.events.handlers.onThemeCollectionChanged()');
theme.events.handlers.onProductGridChanged(e);
if( typeof parseCountdownProducts !== 'undefined' )
{
parseCountdownProducts();
}
// if( typeof initPriceSlider !== 'undefined' )
// {
// initPriceSlider();
// }
theme.helpers.initPriceSlider();
},
onProductGridChanged: function(e)
{
console.log('theme.events.handlers.onProductGridChanged()');
theme.lazyLoad();
theme.productHandler.intersectProductBlocks();
}
},
init: function()
{
window.addEventListener('themeCollectionChanged', theme.events.handlers.onThemeCollectionChanged);
window.addEventListener('themeProductGridChanged', theme.events.handlers.onProductGridChanged);
}
}
//=============================================
// Message parser
//=============================================
theme.message = function(message)
{
// Default values
this.type = 'info';
this.icon = 'icon-check';
this.classes = ''; //msg classes from gui
this.msgIndex = Math.floor((Math.random() * 1000) + 1);
this.messageHtml = message || '';
}
theme.message.prototype.append = function()
{
if( !this.messageHtml )
{
console.log('* Calling theme.message.render() but no message HTML found *');
return;
}
var element = $('');
$('#theme-messages').prepend(element);
element.animate({'right':'0px', 'opacity': 1}, 300);
setTimeout( function()
{
element.animate({'right':'-500px', 'opacity': 0}, 300, function()
{
element.remove();
});
}, 6000);
$('#theme-messages .theme-message:not(:first-child)').animate({'right':'-500px', 'opacity': 0}, 300, function()
{
$(this).remove();
});
};
theme.message.prototype.wasAddedToCart = function()
{
return this.messageText.includes( theme.text.cart.toLowerCase() ) || this.classes.includes('success');
}
theme.message.prototype.fromHtml = function(html)
{
let messageHolder = $(html).find('[class*="messages"] ul');
if( messageHolder.length )
{
this.messageHtml = messageHolder.first('li').html();
this.messageText = messageHolder.first('li').text();
// To string instead of array so we can compare loosely (e.g. 'success' also includes gui-success).
let classes = messageHolder[0].classList.toString();
this.classes = classes;
if( classes.includes('error') )
{
this.type = 'error';
this.icon = 'icon-x';
}
else if( this.messageText.includes( theme.text.cart.toLowerCase() ) || classes.includes('success'))
{
this.type = 'success';
this.icon = 'icon-check';
}
else
{
this.type = 'info';
this.icon = 'icon-question-l';
}
}
}
//=============================================
// Quickshop parser
//=============================================
theme.quickshop =
{
swiper: null,
hydrate: function(product)
{
$('#quickshop-modal .stock').html( theme.productHandler.parseStockStatus( theme.productHandler.getStockStatus(product.stock)) );
$('#qs-title').html(product.title);
$('#quickshop-modal .description').append(''+product.description+'
');
if( product.brand != false && theme.settings.show_product_brands )
{
$('#quickshop-modal .brand').html(product.brand.title);
}
$('#qs-view-product').attr('href', theme.url.gotoProduct+product.id);
$('#qs-view-product').html(theme.text.view+' ');
if( product.custom )
{
$('#qs-view-product').html(theme.text.customizeProduct+' ');
}
if( product.price.price_old > 0 )
{
$('#qs-price-holder').append(''+theme.helpers.parsePrice(product.price.price_old)+' ');
}
$('#qs-price-holder').append(''+theme.helpers.parsePrice(product.price.price_incl)+' ');
$('#qs-price-holder').append(''+theme.helpers.parsePrice(product.price.price_excl)+' ');
$('#qs-price-holder').append(' '+theme.text.tax+' ');
$('#qs-form').attr('action', theme.url.addToCart+product.vid+'/');
theme.log('Product data:');
theme.log(product);
if( product.variants )
{
$('#qs-variants').append(' ');
for( var vid in product.variants )
{
var variant = product.variants[vid]
var selected = (product.vid == vid) ? ' selected' : '';
let availAble = theme.productHandler.getStockStatus(variant.stock);
$('#qs-variant-select').append(''+variant.title+' - '+theme.helpers.parsePrice(variant.price.price)+' ('+(theme.shop.b2b || (theme.settings.b2b_enabled && theme.settings.b2b_default_pricing == 'excl') ? theme.text.exclVAT : theme.text.inclVAT)+')'+(!variant.stock.available ? ' - ' + theme.text.outOfStock : '')+' ');
}
$('#qs-variant-select').off().on('change', function()
{
let selected = $(this).find('option:selected');
$('#qs-form').attr('action', theme.url.addToCart + selected.val()+'/');
$('#quickshop-modal .price-incl').html(theme.helpers.parsePrice(selected.attr('data-price-incl')));
$('#quickshop-modal .price-excl').html(theme.helpers.parsePrice(selected.attr('data-price-excl')));
$('#quickshop-modal .stock').html( theme.productHandler.parseStockStatus( theme.productHandler.getStockStatus(JSON.parse(selected.attr('data-stock'))) ) );
});
}
this.swiper = new Swiper('#swiper-quickimage',
{
navigation: {
nextEl: '#qs-swiper-next',
prevEl: '#qs-swiper-prev'
},
updateOnImagesReady: true,
spaceBetween:0,
});
for( var i = 0; i < product.images.length; i++)
{
this.swiper.appendSlide('');
}
this.swiper.update();
theme.events.fire('themeQuickshopHydrated', {
product: product,
});
},
show: function()
{
$('body').addClass('modal-active');
$('#quickshop-holder').addClass('modal-active');
theme.events.fire('themeQuickshopHydrated');
},
close: function()
{
$('#quickshop-holder').removeClass('modal-active');
$('body').removeClass('modal-active');
theme.events.fire('themeQuickshopClosed');
setTimeout(function()
{
theme.quickshop.clear();
theme.events.fire('themeQuickshopCleared');
}, 300);
},
clear: function()
{
if( this.swiper )
{
this.swiper.destroy();
this.swiper = null;
}
$('#quickshop-modal .swiper-wrapper').html('');
$('#quickshop-modal .brand').html('');
$('#qs-title').html('');
$('#qs-variants').html('');
$('#quickshop-modal .description').html('');
$('#quickshop-modal .stock').html('');
$('#qs-price-holder').html('');
}
};
//=============================================
// Products
//=============================================
theme.productHandler =
{
storage: [],
getJsonData: function(jsonUrl, elem)
{
$.get(jsonUrl).done( function(data)
{
theme.log(' - retrieved pid '+data.product.id);
theme.productHandler.storeData( data.product )
theme.productHandler.hydrateElements(elem, data.product);
theme.events.fire('themeProductBlockLoaded', {
product: data.product,
element: elem
});
});
},
getStockStatus: function(stockData)
{
if( !stockData.track || (stockData.available && stockData.on_stock) )
{
return 'in-stock';
}
if( stockData.available && !stockData.on_stock )
{
return 'backorder';
}
return 'out-of-stock';
},
generateStockText: function(status, withIcon, disableMarkup)
{
let text;
let icon;
switch(status)
{
case 'out-of-stock':
icon = ' ';
text = theme.text.outOfStock;
break;
case 'backorder':
icon = ' ';
text = theme.text.backorder;
break;
default:
icon = ' ';
text = theme.text.inStock;
break;
}
if( !withIcon )
icon = '';
if( disableMarkup )
return icon+text;
return ''+icon+''+text+'
';
},
parseStockStatus: function(status, textOnly)
{
let text;
let icon;
switch(status)
{
case 'out-of-stock':
icon = ' ';
text = theme.text.outOfStock;
break;
case 'backorder':
icon = ' ';
text = theme.text.backorder;
break;
default:
icon = ' ';
text = theme.text.inStock;
break;
}
if( textOnly )
return text;
return ''+icon+' '+text+'
';
},
storeData: function(product)
{
return this.storage[ product.id ] = product;
},
getDataPromise: function(jsonUrl, pid)
{
theme.log('* Fired getDataPromise for '+jsonUrl+' *')
let productData = this.getData(pid);
return new Promise( function(resolve, reject)
{
if( productData )
{
theme.log(' - Already available for pid '+pid);
resolve( productData );
return;
}
$.get(jsonUrl).done( function(data)
{
theme.log(' - Resolved by AJAX '+pid);
resolve( data.product );
})
.fail( function()
{
theme.log(' - Failed AJAX resolve '+pid);
reject('Failed AJAX retrieval for '+pid);
});
});
},
getData: function(pid)
{
return this.storage[pid] || false;
},
hydrateElements: function(elem, product)
{
let element = $(elem);
let stock = '';
let deliveryTime = product.stock.delivery ? product.stock.delivery.title : false;
let stockStatus = this.getStockStatus(product.stock)
const cardType = elem.classList.contains('product-list') ? 'list' : 'grid';
theme.logGroup('hydrateElements() for '+product.title, true);
theme.log(elem);
//--------------------------------------------------
// Check if any variant is in stock
//--------------------------------------------------
if( product.variants != false )
{
for(let vid in product.variants)
{
let variant = product.variants[vid];
stock = this.generateStockText( this.getStockStatus(variant.stock) );
deliveryTime = variant.stock.delivery ? variant.stock.delivery.title : false;
// If any is in stock, mark as in stock and bail
if( stock.includes(theme.text.inStock) )
{
stockStatus = this.getStockStatus(variant.stock)
break;
}
}
}
else if( product.variants == false || stock == '' )
{
// console.log('no variants or use default stock');
stock = this.generateStockText( stockStatus );
}
theme.log('stockStatus: '+stockStatus);
const quickOrderElem = elem.querySelector('.quick-order');
if( quickOrderElem )
{
quickOrderElem.setAttribute('data-stock', stockStatus);
if( !product.variants )
quickOrderElem.setAttribute('data-is-single-product', true);
if( stockStatus === 'out-of-stock' )
quickOrderElem.innerHTML = '';
}
element.find('.product-col-stock').html(stock).addClass('loaded');
// Set delivery text if applicable
if( theme.settings.show_delivery_time == 'custom' || (theme.settings.show_delivery_time == 'custom_if_stock' && stockStatus === 'in-stock') || (theme.settings.show_delivery_time == 'custom_if_stock_condition' && deliveryTime && stockStatus === 'in-stock') )
{
//if( (theme.settings.show_delivery_time == 'custom_if_stock' && stockStatus === 'in-stock') )
if( cardType === 'grid' && stockStatus !== 'in-stock' )
{
element.find('.product-col-delivery').html(stock).addClass('loaded').addClass(stockStatus);
}
else
{
element.find('.product-col-delivery').html(theme.settings.delivery_time_text).addClass('loaded').addClass(stockStatus);
}
}
else if( deliveryTime )
{
element.find('.product-col-delivery').html(deliveryTime).addClass('loaded').addClass(stockStatus);
}
if( product.images[1] && theme.settings.grid_second_image_hover && window.innerWidth > 767 )
{
let src = getProductImage(product.images[1], theme.images.imageSize)
let img = new Image();
img.fetchPriority = 'low'; //experimental browser feature
img.src = src;
img.classList.add('product-grid-img');
img.classList.add('product-grid-hover-img');
let imgHolder = element.find('.product-grid-img-holder');
theme.log(imgHolder);
imgHolder.append(img);
}
theme.logGroupEnd();
},
intersectProductBlocks: function()
{
let productBlockObserver = new IntersectionObserver(function(entries, observer)
{
entries.forEach(function(entry)
{
if (entry.isIntersecting)
{
let productBlock = entry.target;
// console.log(' START getJsonData ');
theme.productHandler.getJsonData(productBlock.getAttribute('data-json'), productBlock);
// console.log(' END getJsoNData ');
productBlock.classList.remove('product-intersect-json');
productBlockObserver.unobserve(productBlock);
}
});
});
document.querySelectorAll('.product-intersect-json').forEach(function(productBlockElem)
{
productBlockObserver.observe(productBlockElem);
});
}
};
theme.dynamicProducts = function(elem)
{
const url = elem.getAttribute('data-products-url');
const dynamicProduct = this;
// Callbacks
this.onComplete = null;
this.onSuccess = null;
this.onError = null;
function dispatchOnComplete()
{
if( this.onComplete)
{
this.onComplete();
}
}
this.showError = function( error)
{
const onErrorMessage = elem.getAttribute('data-on-error');
const originalHeight = elem.clientHeight;
const message = onErrorMessage || ''+error+' '+url.substring(0, url.indexOf('?'))+'
';
elem.outerHTML = ''+message+'
';
};
this.hydrateElement = function(html)
{
elem.innerHTML = html;
elem.classList.remove('col-loading'); //remove styling
const onCompleteEvent = elem.getAttribute('data-event-complete');
if( onCompleteEvent )
{
theme.events.fire(onCompleteEvent);
}
if( this.onComplete )
{
theme.log('dynamicProduct.onComplete() for '+url);
this.onComplete();
}
else if( this.onSuccess )
{
theme.log('dynamicProduct.onSuccess() for '+url);
this.onSuccess();
}
};
this.run = function()
{
theme.log('run theme.dynamicProducts.run() for: '+url);
theme.log(elem);
if( !url )
{
theme.log('No url found, no dynamic products, just consider complete and bail');
if( this.onComplete)
{
this.onComplete();
}
return;
}
if( elem.classList.contains('dy-needs-addons') && (!window.dyapps || (window.dyapps && !window.dyapps.addons)) )
{
elem.outerHTML = '
Missing DyApps Theme Addons plugin ';
return;
}
if( 'fetch' in window )
{
// Stupid ajax and session messing when calling any html page
// Use fetch instead and omit credentials (all cookies), so LS cannot alter our session
// Mainly for breadcrumbs but also for templatebar
fetch(url, { credentials: 'omit' }).then(function (response)
{
if( !response.ok )
{
throw new Error('Could not load products ('+response.status+')');
}
return response.text();
}).then(function (html) {
// This is the JSON from our response
console.log('Got response text, now hydrating');
dynamicProduct.hydrateElement(html);
}).catch(function (message) {
// There was an error
console.log('fetch exception:');
console.log(message);
dynamicProduct.showError(message);
if( this.onComplete )
{
theme.log('dynamicProduct.onComplete() (error!) for '+url);
this.onComplete();
}
else if( this.onError )
{
theme.log('dynamicProduct.onError() for '+url);
this.onError();
}
});
}
else
{
if( typeof _t_p === 'function' )
{
console.log(".dynamic-products not loaded because template bar is active");
elem.outerHTML = '
Dynamic-products not loaded because template bar is active ';
return;
}
$.get( url, function(data)
{
dynamicProduct.hydrateElement(data);
}).fail( function()
{
dynamicProduct.showError('Could not load products')
});
}
};
}
// theme.dynamicProducts = {
// showError: function(elem, error, url)
// {
// const onErrorMessage = elem.getAttribute('data-on-error');
// const originalHeight = elem.clientHeight;
// const message = onErrorMessage || ''+error+' '+url.substring(0, url.indexOf('?'))+'
';
// elem.outerHTML = ''+message+'
';
// },
// hydrateElement: function(elem, html)
// {
// elem.innerHTML = html;
// elem.classList.remove('col-loading'); //remove styling
// const onCompleteEvent = elem.getAttribute('data-event-complete');
// if( onCompleteEvent )
// {
// theme.events.fire(onCompleteEvent);
// }
// },
// parseElement: function(elem)
// {
// const url = elem.getAttribute('data-products-url');
// theme.log('theme.dynamicProducts.parseElement() for: '+url);
// theme.log(elem);
// if( elem.classList.contains('dy-needs-addons') && (!window.dyApps || (window.dyApps && !window.dyApps.addons)) )
// {
// elem.outerHTML = '
Missing DyApps Theme Addons plugin ';
// return;
// }
// if( 'fetch' in window )
// {
// // Stupid ajax and session messing when calling any html page
// // Use fetch instead and omit credentials (all cookies), so LS cannot alter our session
// // Mainly for breadcrumbs but also for templatebar
// fetch(url, { credentials: 'omit' }).then(function (response) {
// console.log(response);
// if( !response.ok )
// {
// throw new Error('Could not load products ('+response.status+')');
// }
// return response.text();
// }).then(function (html) {
// // This is the JSON from our response
// console.log('Got response text, now hydrating');
// theme.dynamicProducts.hydrateElement(elem, html);
// }).catch(function (message) {
// // There was an error
// console.log('fetch exception:');
// console.log(message);
// theme.dynamicProducts.showError(elem, message, url);
// });
// }
// else
// {
// if( typeof _t_p === 'function' )
// {
// console.log(".dynamic-products not loaded because template bar is active");
// elem.outerHTML = '
Dynamic-products not loaded because template bar is active ';
// return;
// }
// $.get( url, function(data)
// {
// theme.dynamicProducts.hydrateElement(elem, data);
// }).fail( function()
// {
// theme.dynamicProducts.showError(elem, 'Could not load products', url)
// });
// }
// },
// init: function()
// {
// const observer = new IntersectionObserver(function(entries)
// {
// entries.forEach( function(entry)
// {
// if (entry.isIntersecting)
// {
// theme.dynamicProducts.parseElement(entry.target);
// observer.unobserve(entry.target);
// }
// });
// }, {
// rootMargin: '150px'
// });
// $qsa('.dynamic-products').forEach( function(elem)
// {
// observer.observe(elem);
// });
// }
// };
theme.cartHandler = {
getData: function(jsonUrl, elem)
{
console.log(elem);
$.get(jsonUrl).done( function(product)
{
theme.log(' - retrieved pid '+product.id);
theme.cartHandler.hydrateElements(elem, product);
// theme.events.fire('themeProductBlockLoaded', {
// product: data.product,
// element: elem
// });
});
},
hydrateElements: function(elem, product)
{
let element = $(elem);
const qty = parseInt(element.find('.qty-input').val());
console.log(product);
if( product.price.price_old && !elem.getAttribute('data-has-discount') )
{
if( theme.settings.vat_switcher_enabled )
{
element.find('.cart-col-price-base').prepend(''+product.price.price_old_incl_money+' '+product.price.price_old_excl_money+' ');
element.find('.cart-col-price-total').prepend(''+theme.helpers.parsePrice(product.price.price_old_incl * qty)+' '+theme.helpers.parsePrice(product.price.price_old_excl * qty)+' ');
}
else
{
element.find('.cart-col-price-base').prepend(''+product.price.price_old_money+' ');
element.find('.cart-col-price-total').prepend(''+theme.helpers.parsePrice(product.price.price_old * qty)+' ');
}
}
},
intersectProducts: function()
{
var cartItems = $qsa(".cart-item");
let cartItemObserver = new IntersectionObserver(function(entries, observer)
{
entries.forEach(function(entry)
{
if (entry.isIntersecting && entry.target.getAttribute('data-json'))
{
let cartItem = entry.target;
theme.cartHandler.getData(cartItem.getAttribute('data-json'), cartItem);
// productBlock.classList.remove('product-preload');
cartItemObserver.unobserve(cartItem);
}
});
});
cartItems.forEach(function(cartItem)
{
cartItemObserver.observe(cartItem);
});
},
};
theme.cartHandler.intersectProducts();
//=============================================
// Lazyload
//=============================================
theme.lazyLoad = function()
{
let lazyImageObserver = new IntersectionObserver(function(lazyImageEntries, observer)
{
lazyImageEntries.forEach(function(entry)
{
if (entry.isIntersecting)
{
let element = entry.target;
let src = element.getAttribute('data-src');
theme.log('lazy intersecting #'+element.id+' ('+src+')');
// Is img or div?
if( element instanceof HTMLImageElement )
{
if( element.classList.contains('product-grid-img') )
{
element.addEventListener('load', function()
{
element.classList.remove('lazy');
});
element.src = src;
}
else
{
element.src = src;
element.classList.remove('lazy')
}
}
else if(element instanceof HTMLSourceElement)
{
element.srcset = element.getAttribute('data-srcset');
element.classList.remove('lazy');
theme.log('Lazy SRCSET: '+src+ ' @ '+ Date.now() + ' / ' + performance.now() );
}
lazyImageObserver.unobserve(element);
}
});
},
{
rootMargin: '100px'
});
$qsa('.lazy').forEach( function(lazyImageElement)
{
lazyImageObserver.observe(lazyImageElement);
});
}
theme.headerScroll = {
isScrolling: false,
lastScroll: 0,
isSticky: false,
lastScrollDirection: false,
scheduledAnimationFrame: false,
elems: {
headerHolder: $('#header-holder'),
header: $('#header-holder')
},
checkFrame: function()
{
let currentScroll = window.pageYOffset;
// theme.log('headerscroll/checkframe() '+currentScroll+ ' / '+theme.headerScroll.lastScroll+' / ('+theme.headerScroll.isScrolling+')');
if( theme.headerScroll.isScrolling != 'down' && theme.headerScroll.lastScroll <= currentScroll )
{
theme.headerScroll.isScrolling = 'down';
theme.log(' -scroll DOWN');
}
else if( theme.headerScroll.isScrolling != 'up' && theme.headerScroll.lastScroll > currentScroll )
{
theme.headerScroll.isScrolling = 'up';
theme.log(' -scroll UP');
}
if( currentScroll >= 50 )
{
if( !theme.headerScroll.isSticky )
{
theme.headerScroll.isSticky = true;
theme.headerScroll.elems.header.addClass('headerscrolled');
if( theme.settings.navbar_sticky && theme.settings.navigation_mode == 'menubar' && window.innerWidth > 991 )
{
$('#header').after($('#navbar-holder').clone().addClass('navscrolled'));
}
}
}
else
{
if( theme.headerScroll.isSticky )
{
theme.headerScroll.isSticky = false;
theme.headerScroll.isScrolling = false;
theme.headerScroll.elems.header.removeClass('headerscrolled');
$('.navscrolled').remove();
}
}
// if( !theme.headerScroll.isScrolling )
// {
// theme.headerScroll.elems.header.addClass('headerscrolled');
// if( theme.settings.navbar_sticky === true && theme.settings.navigation_mode == 'menubar' )
// {
// $('#header').after($('#navbar').clone().addClass('navscrolled'));
// }
// if( theme.headerScroll.isScrolling != 'down' && theme.headerScroll.lastScroll <= currentScroll )
// {
// theme.headerScroll.isScrolling = 'down';
// }
// else if( theme.headerScroll.isScrolling != 'up' )
// {
// theme.headerScroll.isScrolling = 'up';
// }
// }
// else if( theme.headerScroll.isScrolling )
// {
// console.log('Is scrolling set ('+theme.headerScroll.isScrolling+')');
// theme.headerScroll.elems.header.removeClass('headerscrolled');
// $('.navscrolled').remove();
// theme.headerScroll.isScrolling = false;
// }
theme.headerScroll.lastScroll = currentScroll;
theme.headerScroll.scheduledAnimationFrame = false;
},
check: function()
{
// Prevent multiple rAF callbacks
if( theme.headerScroll.scheduledAnimationFrame )
return;
theme.headerScroll.scheduledAnimationFrame = true;
window.requestAnimationFrame(this.checkFrame);
}
}
theme.Throttle = function(name, delay)
{
const throttle = this;
const timeout = delay || 300;
this.name = name;
this.throttled = false;
this.isThrottled = function()
{
return this.throttled;
};
this.run = function(callback)
{
theme.log('Throttle RUN');
throttle.throttled = true;
clearTimeout(this.timer);
this.timer = setTimeout( function()
{
throttle.throttled = false;
theme.log('Cleared throttle for '+throttle.name+', running callback');
callback();
}, timeout);
}
}
theme.liveSearch = new (function ()
{
const maxResults = 6;
const searchInput = $id('header-search-input');
const formElement = $id('header-search');
const resultElement = $id('search-results');
let initiated = false;
const throttle = new theme.Throttle('liveSearch');
function process(q)
{
const searchUrl = theme.url.search + q.replace('/', '') + '/page1.html?limit='+maxResults+'&request_type=ajax&request_action=search';
if (q.length < 3)
{
resultElement.classList.remove('active');
return;
}
if (throttle.isThrottled())
{
theme.log('Throttling - LiveSearch!');
return;
}
theme.log('Search keyup: '+q);
formElement.classList.add('active');
$.get(searchUrl, function (htmlResponse)
{
if( htmlResponse )
{
resultElement.innerHTML = htmlResponse;
resultElement.classList.add('active');
}
});
}
function bindListeners()
{
searchInput.addEventListener('keyup', function (e)
{
const value = this.value;
if( e.key === "Escape" )
{
return;
}
throttle.run(function ()
{
process(value)
});
});
formElement.addEventListener('keyup', function(e)
{
theme.log('theme.liveSearch() - pressed key');
if( e.key === "Escape" || searchInput.value == '' )
{
theme.log('Pressed esc todo refactor? Already listening to formElement instead of document');
theme.liveSearch.clear();
}
});
formElement.addEventListener('click', function(e)
{
theme.log('theme.liveSearch() - clicked formElement');
if( e.target == formElement )
{
theme.log('Clicked on FORM elem (backdrop), not results or search input. Clear!');
theme.liveSearch.clear(false);
}
});
}
this.init = function()
{
if( !searchInput )
{
theme.log('liveSearch::init - no search input element found, bail..');
return;
};
searchInput.addEventListener('focus', function (e)
{
if( formElement.classList.contains('is-dummy') )
{
return;
}
if( this.value.trim() )
{
resultElement.classList.add('active');
formElement.classList.add('active');
}
if( !initiated )
{
theme.log('liveSearch bind listeners');
bindListeners();
initiated = true;
}
});
};
this.clear = function(keepSearchInput)
{
formElement.classList.remove('active');
resultElement.classList.remove('active');
if( keepSearchInput !== false )
{
searchInput.value = '';
resultElement.innerHTML = '';
}
};
});
theme.mobileNav = {
loaded: false,
holderElem: null,
parsedNavItems: [],
activeSubCount: function()
{
return document.querySelectorAll('.mobile-sub-active').length;
},
parseNavItems: function(mainCategory, level)
{
const isRoot = (level === 0 );
// Check for duplicate custom links
if( !isRoot && mainCategory.type !== 'category' )
{
if( theme.mobileNav.parsedNavItems.includes( mainCategory.url ) )
{
return '';
}
theme.mobileNav.parsedNavItems.push( mainCategory.url );
}
const hasSubs = (mainCategory.subs && mainCategory.subs.length);
const categories = hasSubs ? mainCategory.subs : mainCategory;
let html = '';
if( !isRoot )
{
html += '
'+mainCategory.title+' ';
if( mainCategory.image && theme.settings.mobile_nav_sub_header_enabled )
{
html += '
';
}
html += '';
html += ''+theme.text.viewAll+' ';
html += ' ';
}
categories.forEach( function(category)
{
html += '';
if( isRoot && category.type == 'category' && theme.settings.mobile_nav_main_images_enabled )
{
html += ' ';
}
html += '';
html += category.title;
html += ' ';
if( category.subs.length )
{
html += theme.mobileNav.parseNavItems(category, (level+1));
html += ' ';
}
html += ' ';
});
html += ' ';
return html;
},
init: function() // todo split into bind Listeners and separate functions
{
$('#mobilenav').click(function (e)
{
let touchStartX = 0; // Keep track of swiping back in subnav
if( theme.mobileNav.loaded )
{
return;
}
theme.log('First run for mobileNav');
theme.mobileNav.holderElem = $('#mobile-nav-holder');
let html = '';
const navContent = $id('mobile-nav-content');
const elemWidth = navContent.clientWidth;
navContent.innerHTML = theme.mobileNav.parseNavItems(theme.navigation, 0);
$qsa('[data-toggle-sub]').forEach( function(elem)
{
elem.addEventListener('click', function(e)
{
e.preventDefault();
const elem = e.currentTarget;
const targetId = elem.getAttribute('data-toggle-sub');
const subItemsHolder = elem.parentNode.querySelector('[data-parent-id]');
//const closestParent = elem.closest('.mobile-nav-sub');
const closestParent = elem.closest('ul');
console.log(elem);
console.log('Clicking id '+targetId);
console.log(subItemsHolder);
subItemsHolder.classList.add('mobile-sub-active');
//location.hash = 'cat-'+targetId;
if( closestParent )
{
closestParent.classList.add('mobile-nav-has-child-open');
subItemsHolder.style.top = closestParent.scrollTop+'px';
}
});
});
//
$qsa('.mobile-nav-back-item').forEach( function(elem)
{
elem.addEventListener('click', function(e)
{
e.preventDefault();
console.log('pressed back item in nav');
const elem = e.currentTarget;
console.log(elem);
elem.parentNode.classList.remove('mobile-sub-active');
elem.parentNode.style.top = 'auto';
//const closestParent = elem.parentNode.parentNode.closest('.mobile-nav-sub');
const closestParent = elem.parentNode.parentNode.closest('ul');
console.log(closestParent);
closestParent.classList.remove('mobile-nav-has-child-open');
});
});
$('#mobile-lang-switcher').on('click', function()
{
theme.fancyHandler.closeAllAndClear();
theme.scrollTo( $id('mobile-lang-footer'), -100 );
});
// $('[data-toggle-sub]').on('click', function(e)
// {
// e.preventDefault();
// const offsetTop = navContent.getBoundingClientRect().top;
// const subMenu = $(this).siblings('.mobile-nav-sub');
// if( parseInt(subMenu.attr('data-level')) === 1 )
// {
// subMenu.css('top', offsetTop+'px');
// }
// else
// {
// const parentSubmenu = $(this).closest('.mobile-nav-sub');
// const scrollTop = parentSubmenu.scrollTop;
// $(this).find('.mobile-nav-sub').css('top', scrollTop+'px');
// parentSubmenu.addClass('mobile-nav-has-child-open');
// }
// subMenu.addClass('mobile-sub-active');
// $('#mobile-nav-holder').addClass('sub-active');
// });
// $('.mobile-nav-back-item').on('click', function(e)
// {
// e.preventDefault();
// theme.log('Clicked mobile nav sub back button');
// $(this).closest('.mobile-nav-sub').removeClass('transition-none');
// $(this).closest('.mobile-nav-sub').removeClass('mobile-sub-active');
// if( theme.mobileNav.activeSubCount() < 1 )
// {
// theme.mobileNav.holderElem.removeClass('sub-active');
// }
// });
$('.mobile-nav-sub').on('touchstart', function(e)
{
theme.log('start:');
theme.log(e);
theme.log(e.originalEvent);
theme.log(e.target);
theme.log(e.currentTarget);
if (e.originalEvent.changedTouches[0].clientX < 25 ) //|| e.pageX < window.innerWidth - 10)
{
e.preventDefault();
}
touchStartX = e.originalEvent.changedTouches[0].clientX;
//e.currentTarget.classList.add('transition-none');
});
if('ontouchstart' in window)
{
$('.mobile-nav-sub').on('touchend', function(e)
{
const elem = e.currentTarget;
const posX = e.originalEvent.changedTouches[0].clientX;
const deltaX = posX - touchStartX;
if( elem.classList.contains('dragging') )
{
elem.classList.remove('dragging');
elem.classList.remove('transition-none');
elem.style.removeProperty("transform");
if( deltaX > 50 )
{
elem.classList.remove('mobile-sub-active');
}
if( theme.mobileNav.activeSubCount() < 1 )
{
theme.mobileNav.holderElem.removeClass('sub-active');
}
}
});
$('.mobile-nav-sub').on('touchmove', function(e)
{
const elem = e.currentTarget;
const posX = e.originalEvent.changedTouches[0].clientX;
const deltaX = posX - touchStartX;
const transformX = Math.round(elemWidth-deltaX);
const isDraggable = (elem.classList.contains('mobile-sub-active') && !elem.querySelector('.mobile-sub-active'));
theme.log('moved '+posX + ' Dx: '+deltaX + ' transformX: '+transformX);
if( isDraggable && deltaX > 1 && deltaX <= elemWidth )
{
elem.classList.add('transition-none');
elem.classList.add('dragging');
elem.style.transform = 'translateX(-'+transformX+'px)';
}
});
}
theme.mobileNav.loaded = true;
});
}
};
theme.lazyLoad();
//=============================================
// Get ready for the launch
//=============================================
document.addEventListener('DOMContentLoaded', function()
{
//console.log(theme);
// // Init
// theme.events.init(); // bind global listeners for specific theme events
// theme.lazyLoad(); // load up initial dom elements lazy loading
// theme.productHandler.intersectProductBlocks(); // load up initial dom elements lazy loading
// theme.headerScroll.check(); // initial page load checking header/scroll position
theme.mobileNav.init();
if( theme.settings.live_search_enabled )
{
theme.liveSearch.init();
}
switch( theme.shop.template )
{
case 'pages/product.rain':
theme.helpers.responsiveVideos( document.querySelectorAll('#product-content iframe') );
theme.helpers.bindShareButton('.share-button');
break;
case 'pages/blog.rain':
//theme.helpers.responsiveVideos( document.querySelectorAll('#article-content iframe') );
break;
case 'pages/article.rain':
theme.helpers.bindShareButton('.share-button');
theme.helpers.responsiveVideos( document.querySelectorAll('#article-content iframe') );
break;
case 'pages/collection.rain':
theme.helpers.initPriceSlider();
break;
}
// Process dynamic product grids/elements
// Todo, only homepage and productpage (related) ?
//theme.dynamicProducts.init();
const observer = new IntersectionObserver(function(entries)
{
entries.forEach( function(entry)
{
if (entry.isIntersecting)
{
//theme.dynamicProducts.parseElement(entry.target);
(new theme.dynamicProducts( entry.target )).run();
observer.unobserve(entry.target);
}
});
}, {
rootMargin: '150px'
});
$qsa('.dynamic-products').forEach( function(elem)
{
observer.observe(elem);
});
$('[data-scrollview-id]').on('click', function(e)
{
console.log('data-scrollview-id clicked')
e.preventDefault();
const scrollOffset = $(this).attr('data-scrollview-offset') || -100;
const elemId = $(this).attr('data-scrollview-id');
theme.scrollTo( $id(elemId), parseInt(scrollOffset), 'smooth');
});
// $('[data-tooltip]').tooltip()
$('input:checkbox:not(.fancy-checkbox, .vat-switcher-checkbox)').addClass('fancy-checkbox');
$('input:radio:not(.fancy-radio, [class^="gui-"])').addClass('fancy-radio');
$('select:not(.fancy-select)').addClass('fancy-select');
/*********************************************************************************
// START scroll handling
*********************************************************************************/
window.addEventListener('scroll', function()
{
theme.headerScroll.check();
}, {
'passive': true
});
//Fire first on load
// theme.headerScroll.check();
/*********************************************************************************
// END scroll handling
*********************************************************************************/
// $(document).on('click', '.dropdown-content', function (e) {
// e.stopPropagation();
// });
/*********************************************************************************
// START theme pop hints
*********************************************************************************/
if( !localStorage.getItem('pop_navbar') )
{
$('.nav-pop').fadeIn();
}
if( !localStorage.getItem('pop_collection') )
{
$('.collection-pop').fadeIn();
}
$('[data-pop-close]').on('click', function()
{
var closeTarget = $(this).attr('data-pop-close');
var closeTargetCookieName = 'pop_'+closeTarget;
$('[data-pop="'+closeTarget+'"]').fadeOut();
localStorage.setItem(closeTargetCookieName, true);
});
/*********************************************************************************
// END theme pop hints
*********************************************************************************/
/*********************************************************************************
// START SWIPER SLIDERS
*********************************************************************************/
//----------------------------------------------
// USP bar
//----------------------------------------------
// theme.swiperTopUsps = new Swiper('.usps-header',
theme.swiperTopUsps = new Swiper('.usp-carousel',
{
slidesPerView: theme.settings.subheader_usp_default_amount,
breakpoints: {
1400: {
slidesPerView: theme.settings.subheader_usp_default_amount
},
1200: {
slidesPerView: (theme.settings.subheader_usp_default_amount - 1)
},
991: {
slidesPerView: 2
},
767: {
slidesPerView: (theme.settings.hallmark == 'disabled' ? 2 : 1)
}
},
autoplay: {
delay:4000,
},
roundLengths : true
});
/*********************************************************************************************
// Process JS for homepage specific features
*********************************************************************************************/
if( theme.shop.template == 'pages/index.rain' )
{
//----------------------------------------------
// Homepage slider
//----------------------------------------------
if( theme.settings.slidesActive > 1 )
{
var swiperHomeSlider = new Swiper('#home-slider', {
slidesPerView: 1,
autoplay: {
delay: theme.settings.sliderTimeout
},
navigation:
{
prevEl: '#home-slide-prev',
nextEl: '#home-slide-next'
},
pagination: {
el: '.swiper-pagination',
type: 'bullets',
},
});
}
if( theme.settings.home_categories_type == 'default' )
{
window.homepageCategoriesScroller = new theme.horizontalScroller('#homepage-categories-default');
}
else if( theme.settings.home_categories_type == 'grid' )
{
if( window.innerWidth < 768 )
{
window.homepageCategoriesScroller = new theme.horizontalScroller('#homepage-categories-grid');
}
}
else if ( theme.settings.home_categories_type == 'catalog' )
{
window.homepageCategoriesScroller = new theme.horizontalScroller('#home-category-scroller-catalog',
{
enableNav: true,
navigation: {
left: '#catalog-scroll-icon-left',
right: '#catalog-scroll-icon-right'
}
});
}
else if( theme.settings.home_categories_type == 'circles' )
{
let slideSpaceBetween = theme.pageData.index.featuredCategoriesCount < 4 ? 50 : 30;
var swiperHomepageCats = new Swiper('#home-categories-circles', {
slidesPerView: 6,
spaceBetween: slideSpaceBetween,
navigation:
{
prevEl: '#home-cat-prev',
nextEl: '#home-cat-next'
},
breakpoints: {
1200: {
slidesPerView: 6,
spaceBetween: slideSpaceBetween,
},
991: {
slidesPerView: 5.5,
spaceBetween: (slideSpaceBetween-10),
},
768: {
slidesPerView: 4.5,
spaceBetween: 15,
},
548: {
slidesPerView: 2.6,
spaceBetween: 10,
}
},
on: {
init: function () {
this.centerSlides();
this.checkScrollbars();
},
resize: function () {
this.centerSlides();
this.checkScrollbars();
}
}
});
}
var swiperHomeBrands = new Swiper('#home-brands', {
slidesPerView: 7,
spaceBetween: 50,
breakpoints: {
1400: {
slidesPerView: 7,
spaceBetween: 50,
},
991: {
slidesPerView: 6,
spaceBetween: 50,
},
768: {
slidesPerView: 4,
spaceBetween: 30,
},
480: {
slidesPerView: 3,
spaceBetween: 30,
}
},
pagination: false,
autoplay: {
delay: 2000
},
on: {
init: function () {
this.centerSlides();
},
resize: function () {
this.centerSlides();
}
}
// loop:true,
});
let homepageProductSlidersObserver = new IntersectionObserver(function(entries, observer)
{
entries.forEach(function(entry)
{
if (entry.isIntersecting)
{
let productSlider = entry.target;
theme.log('INTERSECTING PRODUCTSLIDER');
theme.log(productSlider);
let swiperMainProducts = new Swiper(productSlider, {
observeParents: true,
observer: true,
slidesPerView: 4.4,
breakpoints: {
1600: {
slidesPerView: 4.3,
spaceBetween: 25,
},
1300: {
slidesPerView: 4.3,
spaceBetween: 25,
},
1050: {
slidesPerView: 3.2,
spaceBetween: 15,
},
991: {
slidesPerView: 2.8,
spaceBetween: 15,
},
768: {
slidesPerView: 2.2,
spaceBetween: 15,
},
600: {
// slidesPerView: 2.05,
slidesPerView: 1.8,
spaceBetween: 10,
}
},
spaceBetween: 25,
navigation: {
nextEl: '.swiper-home-main-next',
prevEl: '.swiper-home-main-prev',
},
slidesPerGroup: 1
});
homepageProductSlidersObserver.unobserve(productSlider);
}
});
}, {
rootMargin: '200px 0px 200px 0px'
});
$qsa('.homepage-product-slider').forEach(function(homepageProductSlider)
{
homepageProductSlidersObserver.observe(homepageProductSlider);
});
}
/*============================================================================================
+ END SWIPER SLIDERS
=============================================================================================*/
if( theme.settings.navigation_mode == 'button' )
{
$('.nav-main-item').mouseover(function()
{
var ulHeight = $(this).find('ul.nav-main-sub').outerHeight();
console.log('Set subnav height: '+ulHeight);
$('ul.nav-main').css('height', ulHeight+'px');
})
.mouseout(function() {
$('ul.nav-main').css('height', 'auto');
});
// $('#main-categories-button, #scroll-nav').on('click', function(e)
$('#main-categories-button').on('click', function(e)
{
console.log('Clicked main categories button');
theme.log(e);
theme.log(this.id);
$(this).find('.nav-icon').toggleClass('change');
$(this).toggleClass('active');
$('.subheader-nav .nav-main-holder').toggleClass('active');
$('#subnav-dimmed').toggleClass('active');
if( this.id == "scroll-nav" )
{
// $('.nav-main-holder').addClass('scrolled');
}
});
$('#scroll-nav').on('click', function()
{
let button = $(this);
console.log('Clicked scrolled categories button '+button.attr("class"));
if( button.hasClass('active') )
{
button.toggleClass('active');
$('.categories-button .nav-icon').removeClass('change');
// $('#scroll-nav .nav-main-holder').fadeOut().remove();
$('.headerscrolled .nav-main-holder').fadeOut().remove();
// $('#subnav-dimmed').fadeToggle().toggleClass('active');
$('#subnav-dimmed').toggleClass('active');
}
else
{
button.toggleClass('active');
button.find('.nav-icon').toggleClass('change');
// $('.subheader-nav').find('.nav-main-holder').clone(true).appendTo('#scroll-nav');
// $('.subheader-nav').find('.nav-main-holder').clone(true).appendTo('.headerscrolled #header-left');
var clonedElem = $('.subheader-nav').find('.nav-main-holder').clone(true).addClass('scrolled').appendTo('#header-left');
theme.log(clonedElem);
// setTimeout(function(){ $('#scroll-nav .nav-main-holder').addClass('active'); }, 10);
setTimeout(function(){ $('.headerscrolled .nav-main-holder').addClass('active'); }, 10);
$('#subnav-dimmed').addClass('active');
}
});
$('#subnav-dimmed').on('click', function()
{
$('#main-categories-button').removeClass('active');
$('#main-categories-button .nav-icon').removeClass('change');
$('#scroll-nav').removeClass('active');
$('.headerscrolled .nav-main-holder').fadeOut().remove();
// $('.nav-main-holder').removeClass('scrolled');
$('.nav-main-holder').removeClass('active');
// $(this).fadeToggle().removeClass('active');
$(this).removeClass('active');
// $('body').removeClass('flyout-nav-active');
});
}
if( theme.settings.navigation_mode == 'menubar' )
{
// console.log('Hook navigation events: MENUBAR');
// $('.categories-button.scroll').on('click', function(e)
// {
// console.log('Clicked horizontal scroll nav');
// if( $('.navscrolled').length > 0 )
// {
// $(this).removeClass('active');
// $(this).find('.nav-icon').removeClass('change');
// $('.navscrolled').slideUp(300, function()
// {
// $('.navscrolled').remove();
// });
// }
// else
// {
// $(this).addClass('active');
// $(this).find('.nav-icon').addClass('change');
// $('.headerscrolled').after($('#navbar').clone(true).hide().css('position', 'fixed').css('top', '70px').css('width', '100%').addClass('navscrolled').fadeIn());
// }
// e.preventDefault();
// });
}
$('#mobilesearch').on('click', function(e)
{
if( $('.mobilesearchform').length > 0 )
{
$('.mobilesearchform').remove();
}
else
{
if( $('.headerscrolled').length > 0 )
{
$('.headerscrolled').append('');
}
else
{
$('#header-holder').after('');
}
}
$('#mobilesearchinput').focus();
e.preventDefault();
});
if( theme.shop.template == 'pages/index.rain' )
{
$('.look-holder').each(function( index )
{
const look = $(this);
const lookModule = look.attr('data-promo-type'); // a or b
$.get(look.attr('data-json'), function(data)
{
var product = data.product;
theme.log('HomeLook Data 01:');
theme.log(getDataFeature('bundle', product.data_01));
theme.log(product.data_01);
if( product.bundles.length > 0 && getDataFeature('bundle', product.data_01) ) //Todo: check if data 01 contains bundle:
{
look.find('.price').html( theme.helpers.parsePrice(product.bundles[0].price.price) );
look.find('.price-incl').html( theme.helpers.parsePrice(product.bundles[0].price.price_incl) );
look.find('.price-excl').html( theme.helpers.parsePrice(product.bundles[0].price.price_excl) );
}
else
{
look.find('.price').html( theme.helpers.parsePrice(product.price.price) );
look.find('.price-incl').html( theme.helpers.parsePrice(product.price.price_incl) );
look.find('.price-excl').html( theme.helpers.parsePrice(product.price.price_excl) );
}
if( !product.images || product.images.length == 1 )
{
look.find('.look-sub-images').remove();
look.addClass('promo-product-single-image');
}
else if (false)
{
look.find('.look-sub-images').append('
');
look.find('.look-sub-images').append('
');
}
else if( product.images.length > 1 )
{
for( var i=1; i 3 )
{
break;
}
look.find('.look-sub-images').append('');
}
if( product.images.length == 2 )
{
look.find('.look-sub-images').append('');
}
}
});
});
}
theme.liveCompare = {
toggleByLabel: function(elem)
{
//elem = $(elem);
let url = elem.getAttribute('data-url');
let checkbox = elem.previousElementSibling;
theme.log('Add compare: '+url);
$.ajax({
url: url,
}).done(function(data)
{
let html = $('
').append(data);
let listContent = html.find('#fc-list').html();
let compareCount = html.find('#compare-count').text();
$('#fc-list').html( listContent );
$('#compare-count').html( compareCount );
let msg = new theme.message();
msg.fromHtml(html)
msg.append();
if( parseInt(compareCount) > 0 )
{
$('#fc-holder').addClass('active');
}
//checkbox.prop('checked', true);
console.log(checkbox);
checkbox.checked = true
})
},
init: function()
{
$('.static-products-holder').on('click', '.compare', function(e)
{
console.log('Clicked compare');
e.preventDefault();
theme.liveCompare.toggleByLabel(this)
});
}
};
theme.liveCompare.init();
if ('ontouchstart' in document)
{
$('.product-block').on('click', function(e)
{
console.log('clicked pblock');
if( $( window ).width() < 768 )
{
var formElement = $(this).find('.quick-order');
if (!formElement.is(e.target) && formElement.has(e.target).length === 0)
{
console.log('small screen, redirect');
document.location = $(this).attr('data-json').replace('?format=json', '');
console.log('Clicked outside form');
}
else
{
console.log('Clicked INSIDE form');
}
}
});
}
/* fancy compare */
$('#fc-title').on('click', function()
{
$(this).toggleClass('active');
$('#fc-list').toggleClass('active');
});
$('.static-products-holder').on('click', '.trigger-quickshop', function(e)
{
let button = $(this);
if( button.attr('data-json') )
{
var pid = button.attr('data-pid');
var jsonUrl = button.attr('data-json');
}
else
{
var pid = button.closest('.product-block').attr('data-pid');
var jsonUrl = button.closest('.product-block').attr('data-json');
}
theme.log('quickShop clicked for product: '+pid);
if( $( window ).width() > 890 )
{
// $('#quickshop-holder').fadeIn().css('display','table');
// $('body').addClass('quickshop-active');
theme.productHandler.getDataPromise(jsonUrl, pid).then( function(productData)
{
theme.quickshop.hydrate(productData);
// theme.quickshop.show();
theme.fancyBoxes.new('quickshop-holder');
theme.fancyBoxes.box('quickshop-holder').onClear(theme.quickshop.clear);
}).
catch(function(err)
{
let alert = new theme.message(err)
alert.append();
});
e.preventDefault();
}
})
// $('.modal-close').on('click', function(e)
// {
// $('.modal-holder.modal-active').removeClass('modal-active');
// });
// $('#quickshop-holder').on('click', function(e)
// {
// if( $(e.target).hasClass('quickshop-holder') || $(e.target).hasClass('quickshop-inner') ) //|| $(e.target).hasClass('x') )
// {
// theme.quickshop.close();
// }
// });
window.clearFancyBox = function(delay)
{
delay = (typeof delay !== 'undefined') ? delay : 300
console.log('clear with: '+delay);
//Check fancy cart
if( $('html').hasClass('fancy-active') )
{
var elemHandler = $('.active[data-fancy^="fancy"]');
var activeElement = elemHandler.attr('data-fancy');
$('html').removeClass('fancy-active');
if( elemHandler.attr('data-fancy-type') == 'flyout' )
{
$('.'+activeElement).removeClass('active');
$('.'+activeElement).fadeOut(delay);
$('.dimmed.flyout').fadeOut(delay);
}
else if( elemHandler.attr('data-fancy-type') == 'hybrid' && window.innerWidth > 767 )
{
$('.'+activeElement).removeClass('active');
$('.'+activeElement).fadeOut(delay);
$('.dimmed.flyout').fadeOut(delay);
}
else
{
$('.'+activeElement).animate({"right": '-=550'}, 300);
$('.dimmed.full').fadeOut(delay);
}
elemHandler.removeClass('active');
}
}
window.clearModals = function()
{
$('.reviews-modal-holder').fadeOut();
$('.specs-modal-holder').fadeOut();
$('.quickshop-modal-holder').fadeOut();
$('.cart-popup-holder').fadeOut();
$('.sizechart-modal-holder').fadeOut();
$('.stock-modal-holder').fadeOut();
$('html').removeClass('modal-active');
$('.active[data-modal]').removeClass('active');
$('.dimmed').fadeOut();
}
window.hybridFancyBoxes = [];
// $('.fancy-box.hybrid').each( function()
// $('.fancy-box').each( function()
$('.fancy-box.hybrid').each( function()
{
hybridFancyBoxes.push( this.id );
});
theme.logGroup('hybridFancyBoxes found', true);
theme.log(hybridFancyBoxes);
theme.logGroupEnd();
var resizeId;
window.addEventListener('resize', function()
{
clearTimeout(resizeId);
resizeId = setTimeout(checkHybridFancyBoxesPosition, 500);
});
function checkHybridFancyBoxesPosition()
{
theme.logGroup('checkHybridFancyBoxesPosition()', true);
hybridFancyBoxes.forEach( function(id, index)
{
var elem = $('#'+id);
console.log(elem);
if( !elem.hasClass('pos-body') && window.innerWidth < 768 )
{
console.log('Moving #'+id+' to body');
elem.detach().appendTo(document.body).addClass('pos-body').removeClass('pos-header');
}
else if( elem.hasClass('pos-body') && window.innerWidth > 767 )
{
console.log('Moving #'+id+' to header');
elem.detach().appendTo('#header-'+id).removeClass('pos-body').addClass('pos-header');
}
});
theme.logGroupEnd();
}
checkHybridFancyBoxesPosition();
theme.fancyBox = function(elemId, triggerElem)
{
this.id = elemId;
this.elem = null;
this.type = null;
this.triggerElem = triggerElem || null;
this.backdrop = false;
this.clickEvent = null;
this.isActive = function()
{
return this.elem.classList.contains('active');
}
const box = this;
this.clickHandler = function(e)
{
console.log(e);
const element = $(box.elem);
// Prevent race condition
// Because clicking the trigger wil also immediately trigger this handler
//
if( window.getComputedStyle(box.elem).visibility == 'hidden' )
return;
// Modals can be closed by clicking bg
if( box.type === 'modal' )
{
console.log('Clicked when modal is open');
//const element = $(box.elem);
// Main Element is always bg elem, so clicking this should close it.
if (element.is(e.target) ) //&& element.has(e.target).length === 0)
{
theme.fancyBoxes.close(box.id);
}
}
else // fancybox
{
console.log((e.target));
console.log(element.has(e.target));
console.log(element.is(e.target));
if( !element.is(e.target) && element.has(e.target).length === 0 )
{
// clicked outside
theme.log('theme.fancyBox::clickHandler() clicked outside fancybox');
theme.fancyBoxes.close(box.id);
}
}
};
this.escHandler = function(e)
{
if( e.key === "Escape" )
{
theme.fancyBoxes.close(box.id);
}
};
this.transitionEndedHandler = function(e)
{
console.log('****** TRANSITION ENDED ****** ');
console.log(e);
if( e.propertyName === 'visibility' && !box.isActive() )
{
console.log(e.target);
console.log(e.currentTarget);
box.removeListeners();
// Run callback when box is hidden
if( box.onClearCallback )
{
box.onClearCallback();
}
}
}
this.onClearCallback;
this.onClear = function(callback)
{
this.onClearCallback = callback;
};
this.bindListeners = function()
{
window.addEventListener('click', this.clickHandler);
window.addEventListener('keyup', this.escHandler);
this.elem.addEventListener('transitionend', this.transitionEndedHandler);
};
this.removeListeners = function()
{
theme.log('Removed listeners for #'+this.id);
window.removeEventListener('click', this.clickHandler);
window.removeEventListener('keyup', this.escHandler);
this.elem.removeEventListener('transitionend', this.transitionEndedHandler);
};
this.showBackdrop = function()
{
$id('fancy-backdrop').classList.add('active');
}
this.hideBackdrop = function()
{
$id('fancy-backdrop').classList.remove('active');
}
this.show = function()
{
document.body.classList.add('fancy-'+this.type+'-active');
this.elem.classList.add('active');
if( this.triggerElem )
{
this.triggerElem.classList.add('active');
}
if(this.backdrop)
{
this.showBackdrop();
}
};
this.clear = function()
{
theme.log('fancyBox.clear() called for '+elemId);
this.elem.classList.remove('active');
document.body.classList.remove('fancy-'+this.type+'-active');
if( this.triggerElem )
{
this.triggerElem.classList.remove('active');
}
this.hideBackdrop();
// Removing binds is done when transition completed
};
this.init = function()
{
if( !elemId )
{
console.log('Created new fancyBox but elemId was null, did you add data-fancy-id attribute? Skipping..');
return;
}
theme.log('Inited new fancybox for #'+elemId);
this.elem = $id(elemId);
this.type = this.elem.getAttribute('data-type');
this.backdrop = (this.elem.getAttribute('data-backdrop') !== 'false' && this.type != 'modal');
this.bindListeners();
this.show();
};
this.init();
}
theme.fancyBoxes = {
boxes: [],
box: function(elemId)
{
const result = this.boxes.find(function(obj)
{
return obj.id === elemId
});
return result || null;
},
new: function(elemId)
{
this.boxes.push( new theme.fancyBox(elemId) );
},
close: function(elemId)
{
this.box(elemId).clear();
this.boxes.pop(); // hacky, just remove last
},
closeAll: function()
{
//loop throuh all and close
if( !this.boxes[0] )
return;
this.close( this.boxes[0].id );
},
activeCount: function()
{
return this.boxes.length;
// return Object.keys(this.boxes).length;
}
}
theme.fancyHandler = {
activeBox: false,
type: null,
activeButton: false,
activeTrigger: false,
mobileView: function()
{
return window.innerWidth < 768
},
closeWindow: function()
{
},
handleClick: function(e)
{
theme.log('fancyHandler::handleClick(e) called', 'background:#000; color:#fff;');
const button = this.activeButton;
let fancyBox = this.activeBox;
fancyBox = document.getElementById(this.activeBox.id);
if( !fancyBox )
{
theme.log('No activeBox, so bail');
return;
}
// If it's a modal, the outer/backdrop element is the main element, so close..
if( theme.fancyHandler.type == 'modal' && fancyBox === e.target )
{
this.closeAllAndClear();
return;
}
theme.logAll('Current ActiveBox, target:', fancyBox, e.target);
// We're not clicking inside the fancybox
if( fancyBox !== e.target && !fancyBox.contains(e.target) )
{
theme.log('Not clicking inside fancy-box,', 'background:lightblue;');
// We're not clicking the active/trigger button as well, so close all
if( button !== e.target && !button.contains(e.target) )
{
theme.log('Also not clicking the active Button', 'background:lightblue;');
this.closeAllAndClear();
}
// We ARE clicking the trigger button
else
{
theme.log('Clicking active button', 'background:orange;');
if( button.tagName === 'A' )
{
document.location = button.href;
return;
}
this.closeAll();
}
}
},
closeAllAndClear: function()
{
if( this.activeButton )
{
this.activeButton.removeAttribute('data-fancy-active')
}
this.closeAll();
},
closeAll: function()
{
theme.log('fancyHandler::closeAll() called');
// Remove active state from buttons
$('[data-trigger-fancy].active').removeClass('active');
if( this.activeButton )
{
this.activeButton.classList.remove('active');
}
// Remove active state from fancybox
$('.fancy-box').removeClass('active');
$('.fancy-modal').removeClass('active');
$('body').removeClass('fancy-active');
$('#fancy-backdrop').removeClass('active');
this.activeBox = false;
this.activeButton = false;
},
isActive: function(fancyId)
{
},
setActiveButton: function(triggerElem)
{
// Native DOM element
this.activeButton = triggerElem[0];
this.activeButton.classList.add('active');
this.activeButton.setAttribute('data-fancy-active', 'true');
},
setActiveBox: function(fancyElem)
{
// Native DOM element
this.activeBox = fancyElem[0];
},
setType: function(type)
{
this.type = type;
},
show: function(fancyElem)
{
fancyElem.addClass('active');
$('body').addClass('fancy-active');
this.setActiveBox(fancyElem);
this.setType(fancyElem.attr('data-type'));
if( (theme.fancyHandler.mobileView() || fancyElem.attr('data-fancy-backdrop') === 'always') && fancyElem.attr('data-fancy-backdrop') !== 'disabled' && this.type != 'modal' )
{
$('#fancy-backdrop').addClass('active');
}
},
events: {
close: function(e)
{
e.preventDefault();
theme.fancyHandler.closeAllAndClear();
theme.fancyBoxes.closeAll();
},
trigger: function(e)
{
e.preventDefault();
theme.fancyBoxes.new( this.getAttribute('data-fancy-id') );
}
},
bind: function()
{
//bind to close buttons
$qsa('.close-fancy').forEach( function(elem)
{
elem.addEventListener('click', theme.fancyHandler.events.close);
});
//bind to triggers
//edit: not in use right now. beware some buttons may have both .trigger-fancy class and data-trigger-fancy
// $qsa('.trigger-fancy').forEach( function(elem)
// {
// elem.addEventListener('click', theme.fancyHandler.events.trigger);
// });
},
init: function()
{
// Bind to fancy module 2.0
this.bind();
//return;
// legacy
$('body').on('click', '[data-trigger-fancy]', function(e)
{
theme.log('Clicked Fancy Trigger', 'font-weight:bold');
console.debug('CurrentTargets:', e.target, e.currentTarget);
e.preventDefault();
const triggerElem = $(this);
// Refactor, is always removeing active state from trigger, which means?? edit: seems to work now?
if( triggerElem.attr('data-fancy-active') || (theme.fancyHandler.activeButton && e.target.contains(theme.fancyHandler.activeButton) ) )
{
theme.log('Clicked fancy trigger, but some fancy box is already active', 'color:#f00000;');
triggerElem.removeAttr('data-fancy-active');
return;
}
const targetId = '#'+triggerElem.attr('data-trigger-fancy');
const fancyElem = $(targetId);
theme.logAll('Triggering fancy '+targetId, fancyElem, 'With button:', triggerElem);
theme.fancyHandler.show(fancyElem);
theme.fancyHandler.setActiveButton(triggerElem);
});
}
}
theme.fancyHandler.init();
$(document).on('keyup', function(e)
{
if( e.key === "Escape" )
{
if(document.body.classList.contains('fancy-active') || document.body.classList.contains('modal-active'))
{
theme.fancyHandler.closeAllAndClear();
}
}
});
$(document).on('mousedown', function(e)
{
if( theme.fancyHandler.activeBox )
{
theme.fancyHandler.handleClick(e);
}
// if( document.body.classList.contains('modal-active') )
// {
// console.log('Clicked when modal is open');
// var activeElement = $('.' +$('.active[data-modal]').attr('data-modal'));
// console.log('Active element: '+$('.active[data-modal]').attr('data-modal'))
// console.log(activeElement);
// if (!activeElement.is(e.target) && activeElement.has(e.target).length === 0)
// {
// clearFancyBox();
// clearModals();
// }
// }
});
// $('.close-fancy, .fancy-modal .x').on('click', function()
// $('.close-fancy').on('click', function(e)
// {
// // clearModals();
// e.preventDefault();
// theme.fancyHandler.closeAllAndClear();
// theme.fancyBoxes.closeAll();
// });
//=============================================
// Fancy boxes
//=============================================
// $('[data-fancy^="fancy"]').click(function (e)
// {
// return true;
// console.log('Start fancy box');
// let toggler = $(this);
// let type = toggler.attr('data-fancy-type');
// toggler.addClass('active');
// $('html').addClass('fancy-active');
// var elem = $('#'+toggler.attr('data-fancy') );
// console.log(elem);
// if( type == 'flyout' )
// {
// $('.dimmed.flyout').fadeIn();
// elem.fadeIn(300, function()
// {
// console.log('elem faded in');
// });
// elem.addClass('active');
// e.preventDefault();
// }
// else if( type == 'hybrid' && window.innerWidth >= 768 )
// {
// // $('html').addClass('hybrid');
// // $('.dimmed.flyout').fadeIn(100);
// // elem.fadeIn(100, function()
// // {
// // console.log('elem faded in');
// // });
// // elem.addClass('active');
// }
// else
// {
// $('.dimmed.full').fadeIn();
// // elem.animate({"right": '+=550'}, 200);
// elem.css('transform', 'translateX(0px)').css('opacity', 1).css('visibility', 'visible');
// elem.addClass('active');
// e.preventDefault();
// }
// });
//=============================================
//=============================================
theme.liveModal = {
load: function(triggerElem)
{
const loadingButton = new theme.helpers.loadingButton(triggerElem);
const hookOnload = triggerElem.getAttribute('data-hook-onload');
$.get(triggerElem.getAttribute('data-json-url'), function(data)
{
const modalId = triggerElem.getAttribute('data-modal');
theme.fancyBoxes.new( modalId );
const modal = $id(modalId);
if(hookOnload)
{
const result = theme.hooks[hookOnload](data);
if( result === 0 )
{
return false;
}
}
else
{
const contentElem = modal.querySelector('.modal-content');
contentElem.innerHTML = data.textpage.content;
}
loadingButton.clear();
}).fail( function(request, status, errorMessage )
{
alert("Error\nCould not load: "+triggerElem.getAttribute('data-json-url').replace('?format=json', ''));
});
},
init: function()
{
$qsa('.trigger-live-modal').forEach( function(triggerElem)
{
triggerElem.addEventListener('click', function(e)
{
e.preventDefault();
theme.liveModal.load(triggerElem);
});
});
}
};
theme.liveModal.init();
$('[data-modal]').click(function (e)
{
return;
e.preventDefault();
console.log('Start modal');
var initiator = $(this);
var elem = $('.'+$(this).attr('data-modal'));
var jsonData = $(this).attr('data-modal-json') || false;
$(this).addClass('active');
if( jsonData != false )
{
$.get(jsonData, function(data)
{
console.log(data);
$('html').addClass('modal-active');
if( initiator.attr('data-type') === 'stock' )
{
if( data.productInventory == false )
{
alert('Product inventory locations not enabled in Retail');
return;
}
$('.stock-modal .stockdata').html('');
var locations = data.productInventory.locations;
var storeHtml = '';
for( var i in locations)
{
let store = locations[i]
console.log(store.location.title);
storeHtml += '';
storeHtml += '
';
storeHtml += '
';
storeHtml += '
'+store.location.title+' ';
storeHtml += ' '+store.location.address.formatted+' ';
storeHtml += ' ';
storeHtml += '
';
if( store.inventory > 0 )
{
if( theme.settings.show_amount_of_products_on_productpage )
storeHtml += '
'+theme.text.inStock+' ('+store.inventory+')
';
else
storeHtml += '
'+theme.text.inStock+'
';
}
else
{
storeHtml += '
'+theme.text.outOfStock+'
';
}
storeHtml += '
';
storeHtml += '
';
}
$('.stock-modal .stockdata').html(storeHtml);
//$('.stock-modal .updatedat').html(theme.text.updatedAt + ': ');
}
else
{
elem.find('.json-content').html(data.textpage.content);
}
$('.dimmed.full').fadeIn();
elem.fadeIn();
});
}
else
{
$('html').addClass('modal-active');
$('.dimmed.full').fadeIn();
elem.fadeIn();
}
});
/*********************************************************************************
// START Dynamic Countdown Blocks
*********************************************************************************/
function expiredBlock(element)
{
const id = element.attr('data-id');
const block = $('[data-countdown-id="'+id+'"]');
console.log('Expired product countdown deal with id: '+ id);
element.html(''+theme.text.dealExpired+' ');
//block.countdown('destroy');
block.find('.product-block-image').css('opacity', '0.5');
block.find('h4').css('text-decoration', 'line-through').css('opacity', '0.5');
block.find('.quickshop-button').remove();
block.find('.quick-order').css('opacity', '0.5');
block.find('input').attr('disabled', true);
block.find('.button').on('click', function()
{
return false
});
}
function expiredBlockAllow(elem)
{
elem.countdown('destroy');
elem.parent().remove();
}
var runningCountdowns = [];
window.parseCountdownProducts = function()
{
if( typeof jQuery().countdown === 'undefined' )
{
return;
}
theme.logGroup('parseCountdownProducts()', true);
$('[data-countdown]').each( function(index)
{
const element = $(this);
const type = element.attr('data-type');
const timerVal = element.attr('data-countdown');
const id = element.attr('data-id');
theme.log('found [data-countdown] for target element #'+id);
let config = {
until: new Date( timerVal ),
serverSync: theme.shop.getServerTime(),
format: 'dhms',
onExpiry: function(){ theme.settings.dealDisableExpiredSale ? expiredBlock(element) : expiredBlockAllow(element); },
alwaysExpire: true,
labels: theme.text.countdown.labels,
labels1: theme.text.countdown.labels1
};
switch(type)
{
case 'text':
config.layout = '{dn}: {hnn}: {mnn}: {snn} '
break;
default:
config.alwaysExpire = false;
break;
}
runningCountdowns.push('.countdown-'+id);
element.countdown(config);
});
console.log(runningCountdowns);
theme.logGroupEnd();
};
parseCountdownProducts()
function removeCountdownProducts()
{
for( var i = 0; i elem.clientHeight )
{
const parent = elem.parentNode;
const viewAllButton = document.createElement('div');
viewAllButton.classList.add('button', 'button-tiny', 'button-lined-soft');
viewAllButton.textContent = theme.text.viewAll;
viewAllButton.style.marginLeft = '50%';
viewAllButton.style.transform = 'translateX(-50%)';
viewAllButton.onclick = function()
{
elem.classList.add('active');
viewAllButton.remove();
// If the parent is toggle-content feature, we need to expand that as well
// Or our own content stays hidden anyway
if( parent.classList.contains('toggle-content') )
{
parent.style.height = 'auto';
}
};
parent.append(viewAllButton);
}
else
{
elem.classList.add('active');
}
});
//=============================================
// Faq
//=============================================
if( theme.shop.template == 'pages/service.rain' )
{
$('.faq-item .question').on('click', function()
{
/*$('.faq-item .question.active').next().slideUp();
$('.faq-item .question.active').removeClass('active');*/
$(this).toggleClass('active');
$(this).next().slideToggle();
});
}
theme.addToCart = {
triggerSelector: '.trigger-add-to-cart',
htmlResponse: null,
hydrateDom: function()
{
const newQty = this.htmlResponse.find('#cart-qty').html();
//const newFancyCart = this.htmlResponse.find('#fancy-cart').html();
const cartItems = this.htmlResponse.find('.cart-items-holder').html();
$('#cart-qty').html( newQty );
//$('#fancy-cart').html( newFancyCart );
$('.cart-items-holder').html( cartItems );
},
openFancyCart: function()
{
$('#cart-header-link').click();
},
showPopup: function()
{
},
clickHandler: function(e)
{
if( !theme.settings.live_add_to_cart )
{
console.log('Live add to cart disabled, submit form');
return true;
}
e.preventDefault();
const button = e.currentTarget;
const loadingButton = new theme.helpers.loadingButton(button);
try
{
console.log(button.getAttribute('data-metadata'));
window.md = button.getAttribute('data-metadata');
const metadata = JSON.parse(button.getAttribute('data-metadata'));
console.log(metadata);
const pid = button.getAttribute('data-pid');
const vid = button.getAttribute('data-vid');
const title = button.getAttribute('data-title');
const variantTitle = button.getAttribute('data-variant');
const image = button.getAttribute('data-image');
const price = button.getAttribute('data-price');
let imgElement = new Image();
imgElement.src = metadata.image || theme.images.placeholderSquare;
imgElement.classList.add('img-responsive');
const productHasRelated = button.getAttribute('data-has-related') == 'true' ? true : false;
let form = button.closest('form');
if( !form )
{
console.log('Quick add to cart: No form found. Trying #product_configure_form');
form = $id('product_configure_form');
}
const formFields = $(form).serialize();
const formAction = form.action;
$.post( formAction, formFields, function()
{
console.log('Posted quick cart button: ');
console.log(formFields);
}).done( function(data)
{
theme.log(data);
// Process to make usable
const html = $('
').append(data);
theme.addToCart.htmlResponse = html;
let msg = new theme.message();
msg.fromHtml(html);
console.log('---- message -----');
console.log(msg.messageText);
console.log(msg.messageHtml);
// If it's an error (e.g. required custom field) and not already on product page
// Simply submit for forced redirection to product page..
if( msg.type == 'error' && theme.template !== 'pages/product.rain')
{
form.submit();
return;
}
theme.addToCart.hydrateDom();
if( !metadata || !msg.wasAddedToCart() )
{
msg.append();
}
else if( window.innerWidth < 768 || theme.shop.cart_redirect_back )
{
$('.cart-items-holder').prepend(''+msg.messageText+'
');
theme.addToCart.openFancyCart();
}
else
{
// Reset single quotes;
metadata.title = metadata.title.replace('#039;', "'");
metadata.variant = metadata.variant.replace('#039;', "'");
$id('fm-cart-product-title').innerHTML = ( metadata.title + (metadata.variant ? (' - ' + metadata.variant) : '') );
// using jquery because elements may not exist depending on vat switcher..
$('#fm-cart-price').html( theme.helpers.parsePrice(metadata.price.price) );
$('#fm-cart-price-incl').html( theme.helpers.parsePrice(metadata.price.price_incl) );
$('#fm-cart-price-excl').html( theme.helpers.parsePrice(metadata.price.price_excl) );
const upsellHolderElem = theme.addToCart.htmlResponse.find('#cart-upsell-holder');
if( upsellHolderElem.length > 0 )
{
$id('fm-cart-related').innerHTML = ( theme.addToCart.htmlResponse.find('#cart-upsell-holder').prop("outerHTML") );
}
$id('fm-cart-image').innerHTML = '';
$id('fm-cart-image').appendChild(imgElement);
if( upsellHolderElem.length > 0 )
{
const dynamicUpsellProducts = new theme.dynamicProducts( $id('cart-upsells') );
dynamicUpsellProducts.onComplete = function() {
theme.fancyBoxes.new('fancy-modal-cart');
};
dynamicUpsellProducts.run();
}
else
{
theme.fancyBoxes.new('fancy-modal-cart');
}
}
loadingButton.clear();
}).fail( function()
{
console.log('AJAX error, Probably IE issues');
location.reload();
});
}
catch(e)
{
console.log(e);
}
},
init: function()
{
$('body').on('click', '.trigger-add-to-cart', theme.addToCart.clickHandler);
}
};
theme.addToCart.init();
if( theme.shop.template == 'pages/collection.rain' )
{
window.collectionCategoryScroller = new theme.horizontalScroller('#collection-category-carousel', {
enableNav: theme.settings.collection_subcats_carousel_navigation
});
// $('.filter-show-more').on('click', function(e)
$('#collection').on('click', '.filter-show-more', function(e)
{
e.preventDefault();
const groupId = $(this).attr('data-filter-group');
$('.filter-group-'+groupId+' .filter-value').removeClass('hidden-filter');
$('.filter-group-'+groupId+' .more').remove();
window.sessionStorage.setItem('data-filter-group-'+groupId, true);
$('').appendTo("head");
});
$('#collection').on('change', '.custom-filter-form-live .fancy-radio, .custom-filter-form-live .fancy-checkbox', function()
{
theme.log('Changed filter form');
const form = $(this).closest('form').submit();
});
$('#collection').on('submit', '.custom-filter-form', function(e)
{
e.preventDefault();
$('.product-grid, .custom-filters-holder').css('filter', 'blur(4px)');
$('.product-grid, .custom-filters-holder').css('pointer-events', 'none');
const form = $(this);
const formData = form.serialize();
const filerType = form.attr('data-filter-type'); // fancybox or sidebar
// Are we calling from sidebar? need this for scroll pos in the div
const collectionSidebar = $id('collection-sidebar') ?? false;
const formAction = form.attr('action');
const urlBuilder = new theme.urlBuilder(formAction);
urlBuilder.addParam('request_type', 'ajax')
.addParam('request_action', 'collection_page')
.addParam('filter_type', form.attr('data-filter-type'));
if( filerType == 'sidebar')
{
urlBuilder.addParam('sidebar_scrolltop', collectionSidebar.scrollTop);
}
else if( filerType == 'fancybox' )
{
// Close all fancyboxes if we're using the fancybox filters, cause we're done with that for now..
theme.fancyHandler.closeAllAndClear();
}
$.get( urlBuilder.url(), formData, function(data)
{
// Do some cleanup first..
removeCountdownProducts();
const fancyFiltersCurrentlyActive = $('#fancy-filters').hasClass('active');
// Hydrate/overwrite current collection content
$('#collection').html ( data );
fancyFiltersCurrentlyActive ? $('[data-trigger-fancy="fancy-filters"]').first().click() : $('#fancy-filters').removeClass('active');
// Set new sidebar as we've just updated the DOM
const collectionSidebar = $id('collection-sidebar');
if( collectionSidebar )
{
theme.log('Sidebar enabled, set scrollTop of '+collectionSidebar.id+' to: '+collectionSidebar.getAttribute('data-scrolltop'));
// Keep track of sidebar/filters scroll position
collectionSidebar.scrollTop = collectionSidebar.getAttribute('data-scrolltop');
}
// Fix pagination
window.history.pushState({type: 'collection'},'TITLE', formAction+'page1.html?'+formData);
// Tell the world that the content has been loaded/refreshed
theme.events.fire('themeCollectionChanged');
//parseCountdownProducts();
//theme.lazyLoad();
//initPriceSlider();
// Scroll into view..
if( window.pageYOffset > 150 )
{
theme.scrollTo($id('collection'), -50);
}
});
});
addEventListener("popstate", function (e)
{
if( !history.state || (history.state && history.state.type !== 'collection') )
{
return true;
}
console.log('popstate fired');
console.log(e);
const urlBuilder = new theme.urlBuilder(location.href);
const pageUrl = urlBuilder.addParam('request_type', 'ajax').addParam('request_action', 'collection_page').url();
$.get( pageUrl, function(data)
{
removeCountdownProducts();
$('#collection').html ( data );
//parseCountdownProducts();
//theme.lazyLoad();
theme.events.fire('themeCollectionChanged');
//initPriceSlider();
});
});
}
// INFINITE SCROLL
if( theme.shop.template == 'pages/collection.rain' && theme.settings.collection_pagination_mode == 'live' )
{
$('#collection').on('click', '.collection-load-more', function(e)
{
e.preventDefault();
const button = $(this);
const url = button.attr('href');
const currentPage = button.attr('data-current-page');
const direction = button.attr('data-direction');
// paginationButton.find('i').attr('class', 'fa fa-spinner fa-spin');
const urlBuilder = new theme.urlBuilder(url);
const pageUrl = urlBuilder.addParam('request_type', 'ajax').addParam('request_action', 'collection_products').url();
$.get(pageUrl, function(data)
{
removeCountdownProducts();
const html = $('
').append(data);
const productHtml = html.find('.product-grid').html();
const paginationElem = html.find('.pagination-'+direction);
if( direction === 'previous' )
{
$('.product-grid').prepend( productHtml );
}
else
{
$('.product-grid').append( productHtml );
}
if( paginationElem.length > 0 )
{
$('.pagination-'+direction).html( paginationElem.html() );
}
else
{
$('.pagination-'+direction).remove();
}
parseCountdownProducts();
theme.lazyLoad();
theme.productHandler.intersectProductBlocks();
const loadedPageNumber = parseInt( currentPage ) + (direction === 'previous' ? -1 : 1);
window.history.replaceState({}, $(data).find('title').text(), 'page'+loadedPageNumber+'.html'+document.location.search);
// Set in storage
theme.collection.page = loadedPageNumber;
});
});
}
// INFINITE SCROLL
$('.copy-link').on('click', function(e)
{
var tempInput = document.createElement("input");
tempInput.style = "position: absolute; left: -10000px; top: -10000px";
tempInput.value = $(this).attr('href');
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
$(this).attr('data-original-title', 'Copied!');
//$(this).tooltip('hide');
//$(this).tooltip('update');
// $(this).tooltip('show');
e.preventDefault();
});
$('.toggle-title').on('click', function(e)
{
theme.log('toggling sibling');
e.preventDefault();
const title = $(this);
const content = title.next();
const contentHeight = content.prop('scrollHeight');
// Only if we have content to toggle, we could also misuse the toggle title class for styling purposes
if( !content.hasClass('toggle-content') )
{
return;
}
// Handle mobile only toggles
if( title.hasClass('toggle-title-md') && window.innerWidth > 767 )
{
return;
}
if( title.hasClass('toggle-active') )
{
content.css('height', '0px');
}
else
{
content.addClass('toggle-active');
content.css('height', contentHeight+'px');
}
title.toggleClass('toggle-active');
});
// Init
theme.events.init(); // bind global listeners for specific theme events
//theme.lazyLoad(); // load up initial dom elements lazy loading
theme.productHandler.intersectProductBlocks(); // load up initial dom elements lazy loading
theme.headerScroll.check(); // initial page load checking header/scroll position
});
$('#theme-messages').on('click', '.theme-message-close', function()
{
var message = $(this).parent();
message.animate({'right':'-500px', 'opacity': 0}, 500, function()
{
message.remove();
});
});
if( theme.isDemoShop )
{
if( !localStorage.getItem('theme_viewed_presets') )
{
const presetLink = $id('demo-preset-link');
if( presetLink )
{
presetLink.addEventListener('click', function(e)
{
localStorage.setItem('theme_viewed_presets', true);
});
presetLink.parentNode.classList.add('preset-links-holder-active');
}
}
}
if( theme.settings.navigation_mode == 'menubar' && theme.settings.navbar_sub_brands )
{
theme.navbarBrands = {
limit: 9,
waitingForAmount: null,
injected: false,
data: {},
runWhenAjaxFinished: function()
{
theme.log('navbarBrands.runWhenAjaxFinished');
if( theme.navbarBrands.waitingForAmount === 0 )
{
theme.log('theme.navbarBrands.waitingForAmount==0');
theme.navbarBrands.inject( theme.navbarBrands.data );
}
},
inject: function(jsonData)
{
theme.log('navbarBrands.inject');
theme.navbarBrands.injected = true;
sessionStorage.setItem('navbar_brands', JSON.stringify(jsonData) );
$qsa('.navbar-brands-col').forEach(function(elem)
{
const mainId = elem.getAttribute('data-category-id');
const data = jsonData[mainId];
theme.log(data);
if( data && Object.keys(data.brands).length > 1 )
{
theme.log(data.brands);
const contentElem = elem.querySelector('.navbar-brands-list');
let i = 0;
contentElem.innerHTML = '';
for( var key in data.brands )
{
if( key == 0 )
continue;
if( i > theme.navbarBrands.limit )
break;
const brand = data.brands[key];
const link = document.createElement('a');
link.innerText = (i === theme.navbarBrands.limit ? theme.text.viewAll : brand.title);
link.classList.add('d-block', 'mt-1');
if( i === theme.navbarBrands.limit )
{
link.classList.add('bold');
}
link.href = data.url + (i === theme.navbarBrands.limit ? '' : '?brand='+brand.id);
contentElem.appendChild(link);
i++;
}
}
else
{
elem.remove();
}
});
},
run: function()
{
if( theme.navbarBrands.waitingForAmount !== null )
return; //already run
theme.log('theme.navbarBrands.run()');
const links = $qsa('.navbar-main-link-dropdown');
theme.navbarBrands.waitingForAmount = links.length;
links.forEach(function(elem)
{
$.get( elem.href+'?format=json', function(data)
{
if( data.collection && data.collection.brands )
{
theme.navbarBrands.data[ data.collection.category_id ] = {
url: elem.href,
brands: data.collection.brands
};
}
theme.navbarBrands.waitingForAmount--;
theme.navbarBrands.runWhenAjaxFinished();
});
});
},
init: function()
{
theme.log('theme.navbarBrands.init()');
if( sessionStorage.getItem('navbar_brands') )
{
theme.navbarBrands.inject( JSON.parse(sessionStorage.getItem('navbar_brands')) );
return;
}
setTimeout(theme.navbarBrands.run, 2000);
}
};
theme.navbarBrands.init();
}
console.log('* Lightspeed theme designed by Dyvelopment.com *');
console.log('* For custom design or other custom work contact us at www.dyvelopment.com *');