$(document).ready(function () {
// Get the values from the pagestate cookie
if (cookie.read(location.pathname) !== null) {
window.pageStateCookie = JSON.parse(cookie.read(location.pathname));
} else {
window.pageStateCookie = {};
// console.log('pagestate cookie is null')
}
// And set default values is one is missing so we know we can count on data being there
if (!window.pageStateCookie.lazyPage) {
window.pageStateCookie.lazyPage = 1;
}
if (!window.pageStateCookie.scrollPosition) {
window.pageStateCookie.scrollPosition = 0;
}
if (!window.pageStateCookie.sortOrder) {
window.pageStateCookie.sortOrder = 7;
}
// console.log('pagestatecookie: ', window.pageStateCookie);
// Store the scroll position somewhere safe
window.autoScrollValue = window.pageStateCookie.scrollPosition;
// Have we used the the previous scroll position yet for this page load ?
window.hasAutoScrolled = false;
window.loadedOnce = false;
$(window).on('scroll', function () {
cookieSaveStatus();
});
if (settings.page === 'list') {
JsonProductList.init();
} else if (settings.page === 'search-list') {
JsonProductList.init();
}
});
var settings; //settings held in this variable, it will be accessible in all sub-functions of list
var JsonProductList = {
//settings
defaultSettings: {
domElements: {
listContainer: document.getElementById('productListContainer'),
sortingContainer: document.getElementsByClassName('sortingContainer')[0],
filtersContainer: document.getElementsByClassName('product-list-sidebar')[0], //TODO Should be one filtering container
minPriceInput: document.getElementById('ctl00_plhContent_ctl08_ctl00_tbxMinPrice'),
maxPriceInput: document.getElementById('ctl00_plhContent_ctl08_ctl00_tbxMaxPrice'),
},
controllerUrl: '/Services/ProductService.asmx/ProductList',
relatedUrl: '/Services/ProductService.asmx/RelatedProducts',
defaultImageUrl: '/SL/SI/596/7e8d0f1e-58b2-4bcb-a41d-d124a29c18fc.jpg',
sortingOptions: [
{ label: 'Select Sorting...', value: 0 },
{ label: 'Name ascending', value: 3 },
{ label: 'Name descending', value: 4 },
{ label: 'Price ascending', value: 5 },
{ label: 'Price descending', value: 6 },
],
pageSizes: [3, 6, 9, 12, 24, 48, 96],
lazyLoading: {
enabled: true,
},
urlParams: {
v: '1.0', //API Version
lId: 0, //????
contId: 11, //???
countryId: 11, //country ID
customerId: 0, //customer ID
langId: 1, //language ID
cId: 54, //currencyId
p: 2, //pageNumber
rp: 2, //results per page
so: 0, //TODO so, mId, serial are globally defined. better to put them to the settings object
mId: 0, //menu Id
serial: 0,
imgSizeId: 4976, //image size ID
},
productTemplate:
'
' +
'
' +
'
<%= p.manufacturer %>
' +
'
<%= p.name %>
' +
'
' +
'<%= p.salesPrices[0].tagPriceFormatted %>' +
'<% if (p.salesPrices[0].hasPreviousPrice == true) { %><%=p.salesPrices[0].tagPriceFormatted%> <% } %>' +
'
' +
'
',
},
init: function () {
// settings = this.defaultSettings; //TODO setting should be picked up from external object
JsonProductList.prepareProductListContainer(document.getElementById(settings.domElements.listContainer));
JsonProductList.drawProductList(); //get and render products just after page loading
JsonProductList.sortingSelect(JsonProductList.defaultSettings.domElements.sortingContainer);
},
//API layer
createRequestUrl: function (urlParams) {
// Building the filters if any is checked
if (!window.loadedOnce) {
// Calculate a new RP
if(productlistSearch.getQueryVariable('searchtext') != pageStateCookie.searchTerm){
window.pageStateCookie.lazyPage = 1;
window.pageStateCookie.scrollPosition = 0;
}
var rp = settings.urlParams.rp;
var newRp = window.pageStateCookie.lazyPage * rp;
// And store the old one
window.oldRp = rp;
// Change page to 1 and save the old page
window.oldP = window.pageStateCookie.lazyPage;
settings.urlParams.p = 1;
// Next page load needs to use the multiple of the orignal RP and lazypage
settings.urlParams.rp = newRp;
// Restore the old sort order
settings.urlParams.so = window.pageStateCookie.sortOrder;
// console.log('primary load', settings.urlParams);
} else {
// console.log('secondary load', settings.urlParams);
}
// console.log('oldrp, oldp', window.oldRp, window.oldP);
var requestUrl = settings.controllerUrl;
var firstParam = true;
for (var param in urlParams) {
if (urlParams.hasOwnProperty(param)) {
if (firstParam) {
requestUrl += '?' + param;
firstParam = false;
} else {
requestUrl += '&' + param;
}
if (settings.page === 'search-list') {
requestUrl =
'/Services/ProductService.asmx/ProductList?v=1.0&cId=' +
cId +
'&langId=' +
langId +
'&so=0&countryId=' +
contId +
'&locId=' +
locId +
'&customerId=' +
customId +
'&p=' +
settings.urlParams.p +
'&rp='+
settings.urlParams.rp +
'&imgSizeId=9316&maxSearchResults=200&include=shortDesc&search=';
requestUrl += productlistSearch.getQueryVariable('searchtext');
searchPageHeader = searchPageHeader.replace('{0}', productlistSearch.getQueryVariable('searchtext'));
} else {
requestUrl += '=' + settings.urlParams[param];
}
}
}
requestUrl += JsonProductList.findFilters();
console.debug('request URL is prepared:');
console.debug(requestUrl);
return requestUrl;
},
// Update some list productListSettings from a cookie object, namely:
// Sort order, Scroll position, the page we were on if this is a lazy loading list
updateproductListSettings: function (obj) {
productListSettings.so = obj.sortOrder;
productListSettings.mp = obj.scrollPosition;
productListSettings.p = obj.lazyPage;
},
fetchProductsData: function (url, callback) {
var request;
// Show the loading div while fetching data
$('.product-list-loading').show();
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else {
request = new ActiveXObject('Microsoft.XMLHTTP');
}
if (request) {
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200) {
// When data has been fetched hide the div
$('.product-list-loading').hide();
}
};
}
request.open('GET', url, true);
// request.onreadystatechange = function () {
// //if response from server is ready and it is not exist in cache
// if (request.readyState == 4 && !localCache.exist(url)) {
// //cache it
// localCache.set(url, request.responseText);
// //pass to callback
// callback(JSON.parse(request.responseText));
// }
// //if server received request and we have response already cached
// //we are not waiting for response
// else if (request.readyState == 2 && localCache.exist(url)) {
// //take response from cache and pass to callback
// callback(JSON.parse(localCache.get(url)));
//
// }
// };
request.addEventListener('load', function () {
callback(JSON.parse(request.responseText));
});
request.send(null);
},
//products rendering
drawProductList: function () {
var urlToFetchData = JsonProductList.createRequestUrl(settings.urlParams); //create url using current settings
JsonProductList.fetchProductsData(urlToFetchData, function (result) {
// console.log(result);
var productsArray = result.data.items; // get array with products
var res = result.data;
if (settings.page === 'search-list') {
searchPageHeader = searchPageHeader.replace('{1}', result.data.totalProducts);
$('.search__page--header span').empty().append(searchPageHeader);
}
//render load more button
JsonProductList.renderLoadMoreBtn(res);
if (!window.loadedOnce) {
// console.log('restoring rp');
settings.urlParams.rp = window.oldRp;
settings.urlParams.p = window.oldP;
}
if (!productsArray || productsArray.length == 0) {
JsonProductList.renderAndAppendNoItemsPlaceholder(document.getElementById(settings.domElements.listContainer));
} else {
JsonProductList.renderAndAppendProductList(
productsArray,
document.getElementById(settings.domElements.listContainer)
);
}
// render and put products list into specified container
productListModule.productCount(res);
if (!window.loadedOnce) {
// console.log('restoring scroll position');
window.loadedOnce = true;
setPreviousScrollPosition();
}
});
},
renderLoadMoreBtn: function (res) {
if (res.totalProducts > 0) {
if (!cookies.readCookie('reloaded')) {
cookies.createCookie('itemsNumToLoad', res.productPerPage);
cookies.createCookie('reloaded', true);
}
var currentItemOnScreen = res.pageNumber * res.productPerPage;
currentItemOnScreen = currentItemOnScreen > res.totalProducts ? res.totalProducts : currentItemOnScreen;
var numberOfItemsToLoad =
res.productPerPage > res.totalProducts - currentItemOnScreen
? res.totalProducts - currentItemOnScreen
: res.productPerPage >= cookies.readCookie('itemsNumToLoad')
? cookies.readCookie('itemsNumToLoad')
: res.productPerPage;
var buttonText = btnText.replace('{itemsCountToLoadNext}', numberOfItemsToLoad);
var newText = btnFootText
.replace('{currentItemCount}', currentItemOnScreen)
.replace('{totalProduct}', res.totalProducts);
currentItemOnScreen == res.totalProducts ? $('.product-list__loadmore').addClass('hidden') : '';
$('.product-list__loadmore').removeClass('invisible').show().empty().append(buttonText);
$('.total-prod-info').removeClass('invisible').empty().append(newText);
if (numberOfItemsToLoad <= 0) {
$('.product-list__loadmore').hide();
}
}
},
renderProductDiv: function (productData) {
return productListModule.renderProductComponent(productData);
},
renderAndAppendNoItemsPlaceholder: function (container) {
var wrapper = $(container).parent();
var insert = createElement('span', 'product-list-no-items');
$(insert).text(noProductsLabel);
wrapper.find('.load-more-container').hide();
wrapper.append(insert);
},
renderAndAppendProductList: function (products, container) {
for (var i = 0; i < products.length; i++) {
var productDiv = JsonProductList.renderProductDiv(products[i]);
if (settings.lazyLoading.enabled && i == products.length - 1) {
productDiv.setAttribute('id', 'last-product-on-page-' + settings.urlParams.p);
productDiv.className = productDiv.className + ' end';
}
container.appendChild(productDiv);
}
},
//helpers
createElement: function (elementType, elementClassName, elementAttribute, elementTextString) {
function notEmpty(value) {
return value != undefined && value != '';
}
var createdElement = document.createElement(elementType);
if (notEmpty(elementClassName)) {
createdElement.setAttribute('class', elementClassName);
}
if (elementType == 'IMG' && notEmpty(elementAttribute)) {
createdElement.setAttribute('src', elementAttribute);
}
if (elementType == 'A' && notEmpty(elementAttribute)) {
createdElement.setAttribute('href', elementAttribute);
}
if (notEmpty(elementTextString)) {
var createdElementText = document.createTextNode(elementTextString);
createdElement.appendChild(createdElementText);
}
return createdElement;
},
clearElementContent: function (element) {
if (element) {
while (element.firstChild) {
element.removeChild(element.firstChild);
}
}
},
prepareProductListContainer: function (container) {
JsonProductList.clearElementContent(container);
},
isScrolledIntoView: function (element) {
if (element) {
var elemTop = element.getBoundingClientRect().top;
var elemBottom = element.getBoundingClientRect().bottom;
return (elemTop >= 0 && elemBottom <= window.innerHeight) || elemTop < 0;
} else {
return null;
}
},
//sorting features
// createSortingSelect: function (sortingOptions) {
//
// var sortingSelect = JsonProductList.createElement("SELECT", 'sortOptions');
//
// for (var i = 0; i < settings.sortingOptions.length; i++) {
//
// var sortingOption = JsonProductList.createElement("OPTION", 'sorting-selector-option');
// sortingOption.setAttribute('value', sortingOptions[i].value);
// sortingOption.appendChild(document.createTextNode(sortingOptions[i].label));
//
// sortingSelect.appendChild(sortingOption);
//
// }
//
// sortingSelect.addEventListener("change", function (e) {
//
// JsonProductList.setSorting(e.target.value);
//
// });
//
// return sortingSelect;
//
// },
//
// renderSortingSelect: function (container) {
//
// JsonProductList.clearElementContent(container);
//
// container.appendChild(JsonProductList.createSortingSelect(settings.sortingOptions));
//
// },
// TODO: Not needed for now - still need some work
sortingSelect: function () {
$('.sortOptions').on('change', function (e) {
JsonProductList.setSorting(e.target.value);
cookies.createCookie('optionSelect', e.target.value, 1);
});
},
setSorting: function (optionValue) {
settings.urlParams.so = parseInt(optionValue);
settings.urlParams.p = 1;
JsonProductList.clearElementContent(document.getElementById(settings.domElements.listContainer));
JsonProductList.drawProductList();
},
//filtering features
getMinMaxPrices: function () {
return [
parseInt(JsonProductList.defaultSettings.domElements.minPriceInput.value),
parseInt(JsonProductList.defaultSettings.domElements.maxPriceInput.value),
];
},
renderPriceSlider: function (container) {
var sliderDiv = JsonProductList.createElement('DIV', 'price-slider-container');
var sliderMinPrice = JsonProductList.createElement('INPUT', 'price-slider-min');
var sliderMaxPrice = JsonProductList.createElement('INPUT', 'price-slider-max');
sliderDiv.setAttribute('id', 'price-filter');
sliderMinPrice.setAttribute('type', 'text');
sliderMaxPrice.setAttribute('type', 'text');
container.appendChild(sliderDiv);
container.appendChild(sliderMinPrice);
container.appendChild(sliderMaxPrice);
$j('#price-filter').slider({
range: true,
min: JsonProductList.getMinMaxPrices()[0],
max: JsonProductList.getMinMaxPrices()[1],
values: JsonProductList.getMinMaxPrices(),
change: function (event, ui) {
JsonProductList.setPriceFilter(ui.values);
},
});
},
setPriceFilter: function (valuesArray) {
settings.urlParams.fn1 = 'ProductPrice';
settings.urlParams.fv1 = valuesArray[0] + '^' + valuesArray[1];
JsonProductList.renderPriceSlider.sliderMinPrice.setAttribute('value', 10);
JsonProductList.clearElementContent(document.getElementById(settings.domElements.listContainer));
JsonProductList.drawProductList();
},
//pager features
setPageSize: function (pageSize) {
settings.urlParams.rp = pageSize; //setting up current page size
for (var i = 0; i < settings.domElements.pageSizeSelectorContainers.length; i++) {
var pageSizeSelector = settings.domElements.pageSizeSelectorContainers[i].firstChild; //TODO be more specific here
pageSizeSelector.value = settings.urlParams.rp;
}
JsonProductList.drawProductList(); //redrawing product list
},
renderPageSizeSelectors: function (containers, pageSizes) {
if (containers.length) {
for (var i = 0; i < containers.length; i++) {
var selectorElement = JsonProductList.createElement('SELECT', 'page-size-selector');
for (var j = 0; j < pageSizes.length; j++) {
var pageSizeOption = JsonProductList.createElement('OPTION', 'page-size-option', '', pageSizes[j]);
pageSizeOption.setAttribute('value', pageSizes[j]);
selectorElement.appendChild(pageSizeOption);
}
selectorElement.addEventListener('change', function (e) {
JsonProductList.setPageSize(parseInt(e.target.value));
});
containers[i].appendChild(selectorElement);
}
}
},
renderCurrentPageSelector: function (productsData, container) {
var paginationList = JsonProductList.createElement('UL', 'pagination current-page-selector');
for (var i = 1; i < productsData.totalPages; i++) {
var pageSelectorListItem = JsonProductList.createElement('LI', 'current-page-selector-list-item');
pageSelectorListItem.setAttribute('data-page', i);
var pageSelectorLink = JsonProductList.createElement('A', 'current-page-selector-link');
pageSelectorLink.appendChild(document.createTextNode(i));
pageSelectorListItem.appendChild(pageSelectorLink);
paginationList.appendChild(pageSelectorListItem);
}
container.appendChild(paginationList);
},
findFilters: function () {
var filters = $('.ec90FilterBodyec90FilterBody');
var filterStr = '';
var filterInt = 1;
// Go through all the filters
filters.each(function (i) {
// Filter Ext ID
var filterId = $(this).attr('data-filtername');
// Filters that's checked
var checked = $(this).find('input:checked');
// If filter is Checked build
if (checked.length > 0) {
var filterState = true;
// Filter String to build
filterStr += '&fn' + filterInt + '=CustomFields&fk' + filterInt + '=' + filterId + '&fv' + filterInt + '=';
// Build upon each checked
checked.each(function (field) {
var value = $(this).val();
if (filterState) {
filterStr += value;
filterState = false;
} else {
filterStr += '^' + value;
}
});
// Add to FilterInt
filterInt++;
}
});
return filterStr;
},
};
// // Save page status to Cookie
var cookieSaveStatus = function () {
var values = {
sortOrder: settings.urlParams.so,
scrollPosition: window.pageYOffset, // Use this rather thann scrollY for browser compatibility
lazyPage: settings.urlParams.p,
searchTerm: productlistSearch.getQueryVariable('searchtext')
};
cookie.create(location.pathname, JSON.stringify(values), 0.02);
};
// Reset Cookie Status
// For testing purpose
function cookieEraseStatus() {
cookie.erase(location.pathname);
}
// Sets the scroll position to a previously known value.
var setPreviousScrollPosition = function () {
// console.log("New JPL Scroll restore");
if (!window.hasAutoScrolled) {
// If we haven't scrolled to a stored scroll position before
window.hasAutoScrolled = true;
if (window.pageStateCookie.scrollPosition) {
if (window.autoScrollValue != window.pageStateCookie.scrollPosition) {
// Firefox enjoys firing a scroll event on page load which overwrites our cookie
window.scroll(0, window.autoScrollValue);
} else {
window.scroll(0, window.pageStateCookie.scrollPosition);
}
}
}
};
// ajax response caching utility
var localCache = {
settings: {
timeout: 30, //timeout for cached data validness
},
//method checks if such response already cached and not timed out
exist: function (url) {
if (localStorage.getItem(url) && localStorage.getItem(url) !== '') {
var cachedData = JSON.parse(localStorage.getItem(url));
if (new Date().getTime() - cachedData.timestamp < localCache.settings.timeout) {
console.debug('Data for url exists in local cache');
return true;
}
}
},
//returns parsed data from cache
get: function (url) {
console.debug('Getting data from local cache');
return JSON.parse(localStorage.getItem(url)).data;
},
//removes old data and sets new. gives a timestamp to validate timeout
set: function (url, data) {
console.debug('Saving data to localCache...');
localStorage.removeItem(url);
var cachedData = {
timestamp: new Date().getTime(),
data: data,
};
localStorage.setItem(url, JSON.stringify(cachedData));
},
};
var cookies = {
createCookie: function (name, value, days) {
if (days) {
var date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
var expires = '; expires=' + date.toGMTString();
} else var expires = '';
document.cookie = name + '=' + value + expires + '; path=/';
},
readCookie: function (name) {
var nameEQ = name + '=';
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
},
optionCookie: function () {
if (!cookies.readCookie('optionSelect') == '') {
return parseInt(cookies.readCookie('optionSelect'));
} else {
return 7;
}
},
};
// Cookie Handler
var cookie = {
create: function (name, value, days) {
var expires = '';
if (days) {
var date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
expires = '; expires=' + date.toGMTString();
}
document.cookie = name + '=' + value + expires + '; path=/';
},
read: function (name) {
var nameEQ = name + '=';
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
},
erase: function (name) {
this.create(name, '', -1);
},
};