/**
* This file contains Javascript utility functions used for accordion menu operation.
* All the operation start from function doFacetLoad.
* Oraginally there are only facets category on the page. Once the user click a facet option under the category, we will replace the
* whole category div with the server returning facets data
Price:
* 0.00-50.00 (10)
* 50.00-100.00 (3)
* 100.00-150.00 (1)
Color:
* Black (3)
* Blue (6)
* Brown (3)
* Green (4)
Feature:
* Cotton (4)
* Eco-Friendly (2)
* Organic (2)
* Wool (1)
For example, the above is original content of the facet pannel when user visit category page.
two actions fired when user click 0.00-50.00 (10).
one is call facetClickAction function to generate accordion menu.the below is content of facet pannel.
two is call atg.store.facet.loadData function to generate product list.
Price:
* 0.00-50.00
Color
* Black (2)
* Blue (4)
* Brown (2)
* Green (2)
* Grey (1)
Feature
* Cotton (4)
* Eco-Friendly (1)
* Organic (2)
*/
var wipeOut;
var facetSearchUpdate = "";
var strFacetSource;
var nRedirect = 0;
var currentAnimation;
var okAnimation = 0;
var status = 0;
var hash;
var customEventListenerHandler;
var isHashBeingUpdated = false;
var catNavNotSupported = false;
function setRedirect(nInt) {
nRedirect = nInt;
}
function getRedirect() {
return nRedirect;
}
function setFacetTarget(strDivId) {
facetSearchUpdate = dojo.byId(strDivId);
}
function getFacetTarget() {
return facetSearchUpdate;
}
function setFacetSource(strPage) {
strFacetSource = strPage;
}
function getFacetSource() {
return strFacetSource;
}
function getCategoryHolder() {
return dojo.byId("facetOptions");
}
function cleanDiv(tarDiv) {
// clean out divs
var i=0;
for (i = tarDiv.childNodes.length - 1; i >= 0; i--) {
tarDiv.removeChild(tarDiv.childNodes[i]);
}
tarDiv.innerHTML = "";
}
function buildFacets(objFacetList) {
// the container div for facet pannel
var facetOptionsDiv = dojo.byId("facetOptions");
var id;
var isNew;
var j=0;
for (j = 0; j < objFacetList.length; j++) {
id = objFacetList[j].id;
var divId = "facetoptions_" + id;
// find the div container for current facet refineElement ( facet category)
var facetSingleOptionDiv = dojo.byId(divId);
if (facetSingleOptionDiv) {// if this facet category i.e price, color... is already existed in this page then clean its ontent.
cleanDiv(facetSingleOptionDiv);
isNew = false;
} else { // this is a new facet category , create a new div for it.
facetSingleOptionDiv = document.createElement("div");
facetSingleOptionDiv.id = divId;
isNew = true;
}
buildFacetOption(objFacetList[j], facetSingleOptionDiv, objFacetList.length == 1 && location.href.indexOf('subcategory.jsp') > -1);
facetSingleOptionDiv.style.display = "block";
if (isNew) {
facetOptionsDiv.appendChild(facetSingleOptionDiv);
}
}
}
/**
* Build element with link to desect some facet selection
* @param facetOpton
* @param facetSingleOptionDiv
* @param onlyOneFacetChosen need for special parameter, used for rendering page when no facets had been chosen
*/
function buildFacetOption(facetOpton, facetSingleOptionDiv, onlyOneFacetChosen) {
var facetLabel;
var facetData;
var facetName;
var facetUrl;
var pageUrl=null;
var facetCat;
var facetCatName;
var facetValue;
var addFacet;
var removeFacet;
facetName = facetOpton.name;
facetUrl = facetOpton.urlFacet;
facetCat = facetOpton.id;
facetCatName = facetOpton.catName;
trailSize = facetOpton.trailSize;
addFacet = facetOpton.addFacet;
removeFacet = facetOpton.removeFacet;
facetValue = facetOpton.value;
var facetUl = document.createElement("ul");
facetSingleOptionDiv.appendChild(facetUl);
var facetLi = document.createElement("li");
facetUl.appendChild(facetLi);
if (!getRedirect()) {
var facetHref = generateNavigationFragmentIdentifier(dojo.byId("qfh_docSort").value, 1, 'false', facetUrl, dojo.byId("catIdSaved").value, 'handleProductsLoad', true);
facetLi.className = 'remove';
facetLi.innerHTML = "" + facetName + "";
} else {
facetLi.innerHTML = "" + facetName + "";
}
facetSingleOptionDiv.appendChild(facetUl);
//show this facet category after rendering it.
if (dojo.byId("facet_" + facetCat)) {
dojo.byId("facet_" + facetCat).style.display = "block";
}
}
function updateCategory(objCategory, categoryCount, category) {
var catId = objCategory.catid;
var catName = objCategory.name;
var catDOMId = "facet_" + catId;
if (dojo.byId(catDOMId)) {
// already there
handleUpdateCategory(objCategory, category);
} else {
// not there yet
handleCreateCategory(objCategory, categoryCount);
}
dojo.byId(catDOMId).style.display = "block";
}
function handleUpdateCategory(objCategory, category) {
var catId = objCategory.catid;
var catName = objCategory.name;
var catProp = objCategory.catprop;
var catDOMId = "facet_" + catId;
var optDOMId = "facetoptions_" + catId;
//only have to update options for category
var curCategory = dojo.byId(catDOMId);
// clean category
cleanDiv(curCategory);
var containerHead = dojo.doc.createElement("h5");
containerHead.innerHTML = catName;
curCategory.appendChild(containerHead);
curCategory.appendChild(buildCategoryOptions(objCategory.options, catId, catName, 0 ,catProp));
if (objCategory.options.length > 0 && ("facet_" + category) == catDOMId) {
//curCategory.setAttribute("style", "display:block;");
curCategory.style.display = "block"; //modify in 11.22 2008 browser incompatablity
//alert(("facet_"+category));
}
}
function handleCreateCategory(objCategory, categoryCount) {
var catId = objCategory.catid;
var catName = objCategory.name;
var catProp = objCategory.catprop;
var catDOMId = "facet_" + catId;
var curCategoryHolder = getCategoryHolder();
var container = document.createElement("div");
container.id = catDOMId;
container.className = "atg_store_facetsGroup";
var containerHead = dojo.doc.createElement("h5");
containerHead.innerHTML = catName + ":";
container.appendChild(containerHead);
container.appendChild(buildCategoryOptions(objCategory.options, catId, catName, categoryCount, catProp));
curCategoryHolder.appendChild(container);
}
function buildCategoryOptions(objOptions, strCat, categoryName, categoryCount, categoryProp) {
var tarContainer = document.createElement("div");
var facetContainer;
var singleFacet;
tarContainer.id = "facetoptions_" + strCat;
facetContainer = document.createElement("ul");
var recShown = 5;
var recCount = 0;
if (objOptions.length <= recShown) {
recShown = objOptions.length;
}
if (categoryProp == "price") {
for (var i = 0; i < objOptions.length; i++) {
createOption(facetContainer, tarContainer.id, objOptions[i].name, objOptions[i].urlFacet, objOptions[i].urlPage, objOptions[i].qty, strCat, 0, false, categoryCount, objOptions[i].trailSize, categoryName);
recCount = recCount + 1;
}
}
else {
for (var i = 0; i < recShown; i++) {
createOption(facetContainer, tarContainer.id, objOptions[i].name, objOptions[i].urlFacet, objOptions[i].urlPage, objOptions[i].qty, strCat, 0, false, categoryCount, objOptions[i].trailSize, categoryName);
recCount = recCount + 1;
}
}
if (categoryProp != "price") {
if (objOptions.length > recCount) {
/* append more link to the end of the options ul */
var moreLi = createOption(facetContainer, tarContainer.id, moreLable, "", "", "", strCat, 1, false, categoryCount, "", categoryName,"");
for (var j = recShown; j < objOptions.length; j++) {
createOption(facetContainer, tarContainer.id, objOptions[j].name, objOptions[j].urlFacet, objOptions[j].urlPage, objOptions[j].qty, strCat, 0, true, categoryCount, objOptions[j].trailSize, categoryName,"none");
}
var lessLi = createOption(facetContainer, tarContainer.id, lessLable, "", "", "", strCat, 2, false, categoryCount, "", categoryName,"none");
facetContainer.appendChild(lessLi);
}
}
tarContainer.appendChild(facetContainer);
return tarContainer;
}
function createOption(optionContainer, idx, name, urlFacet, urlPage, qty, strCat, optionType, debug, categoryCount, trailSize, categoryName, displayValue) {
var optName = name;
var optUrl = urlFacet;
var optQty = qty;
var optDisplay = "";
var title = "";
var singleFacet = document.createElement("li");
if (optionType == 2) {
singleFacet.className = "atg_store_facetLess";
singleFacet.id = "lessDiv" + idx;
// singleFacet.setAttribute("style", "display:block");
singleFacet.style.display = "block"; //modify in 11.22 2008 browser incompatablity
}
if (optionType == 1) {
singleFacet.className = "atg_store_facetMore";
singleFacet.id = "moreDiv" + idx;
// singleFacet.setAttribute("style", "display:block");
singleFacet.style.display = "block"; //modify in 11.22 2008 browser incompatablity
}
var tempA_href = "";
if (optionType == 1 || optionType == 2) {
tempA_href = "javascript:atg.store.util.toggleBothDiv('" + idx + "', " + categoryCount + "," + optionType + ");";
optDisplay = optName;
} else if (optionType == 0) {
optDisplay = optName + " (" + optQty + ")";
if (!getRedirect()) {
tempA_href = "javascript:facetClickAction('" + strCat + "','" + optUrl + "',1," + trailSize + "," + qty + ",'"+ generateNavigationFragmentIdentifier(dojo.byId("qfh_docSort").value, 1, 'false', optUrl, dojo.byId("catIdSaved").value, 'handleProductsLoad', true) + "'," + false + ");";
} else {
tempA_href = pageUrl;
}
}
if (optionType == 1 || optionType == 2) {
title = optDisplay;
}
else {
title = filterByLabel + " " + categoryName;
}
var tempA = "" + optDisplay + "";
singleFacet.innerHTML = tempA;
if ( displayValue != null && displayValue != ""){
singleFacet.style.display = displayValue;
}
optionContainer.appendChild(singleFacet);
return singleFacet;
}
/**
* Function for refreshing facet panel + for reloading products
* @param category
* @param urlFacet
* @param action
* @param trailSize
* @param qty
* @param pFragmentIdentifier
* @param deselectSingleFacetChoice - special param to track situation, when user deselects last facet chosen
*/
function facetClickAction(category, urlFacet, action, trailSize, qty, pFragmentIdentifier, deselectSingleFacetChoice) {
// action: 1 = add, 0 = remove
content.trailSize = trailSize;
content.numResults = qty;
switch (action) {
case 0 :
content.addFacet = ""; // clear gloable content's addFacet to empty.
currentAnimation = dojo.fx.wipeIn({
node : "facet_" + category,
duration : 500
});
okAnimation = 1;
break;
case 1 :
content.addFacet = "";
currentAnimation = dojo.animateProperty({
node : "facet_" + category,
duration : 500,
properties : {
height : 50
}
});
okAnimation = 0;
break;
}
// reset page number on facet click
var searchSettings = {q_docSort: dojo.byId("qfh_docSort").value, q_docSortOrder: dojo.byId("qfh_docSortOrder").value, q_pageNum:1, viewAll:"false", q_pageSize: dojo.byId("qfh_pageSize").value, q_question: dojo.byId("questionSaved").value, q_facetTrail: urlFacet, categoryId: dojo.byId("catIdSaved").value};
dojo.byId("facetTrailSaved").value = urlFacet;
if (!deselectSingleFacetChoice || catNavNotSupported) {
setFragmentIdentifier(pFragmentIdentifier);
handleProductsLoad(searchSettings, category);
} else {
ajaxNavigation(dojo.byId("catIdSaved").value, 1, false, '', dojo.byId("qfh_pageSize").value, generateNavigationFragmentIdentifier('', '1', false,'', dojo.byId("catIdSaved").value, 'categoryProducts', false) + '&reloadFPcategory=' + category);
reloadFacets(searchSettings, category);
}
}
function buildCategories(objCategoryList, category, objFacets) {
var i=0;
var j=0;
objOut = dojo.byId("facetOptions");
// iterate through all facets
for (i = 0; i < objCategoryList.length; i++) {
var canBeUpdated = true;
for (j = 0; j < objFacets.length; j++) {
if (objCategoryList[i].catid == objFacets[j].id) {
canBeUpdated = false;
break;
}
}
if (canBeUpdated) {
updateCategory(objCategoryList[i], objCategoryList.length, category);
}
}
}
function handleFacetLoad(objStructure, category) {
var i=0;
content.facetTrail = objStructure.facetTrail;
//content.trailSize = objStructure.trailSize;
//console.dir(objStructure);
var facetOptionsDiv = dojo.byId("facetOptions");
for (i = 0; facetOptionsDiv && facetOptionsDiv.innerHTML != "" && i < facetOptionsDiv.childNodes.length; i++) {
var obj = facetOptionsDiv.childNodes[i];
if (obj && obj.style) {
obj.style.display = "none";
}
}
// load the facets
// facets here means the facet option that user has clicked on and exist in the facetTrail.
var objFacets = objStructure.facets;
buildFacets(objFacets);
//category here means the facet category. i.e price, color, size... and there are several options under corresponded category.
// load categories
var objCategories = objStructure.categories;
buildCategories(objCategories, category, objFacets);
i=0;
var matchingItemsList = '';
for (i = 0; i < objStructure.products.length; i++) {
matchingItemsList += objStructure.products[i].repositoryId + ' ';
}
hideUnRenderedFacets(objFacets, objCategories);
if (okAnimation == 1) {
currentAnimation.play();
okAnimation = 0;
}
}
//this function removes facets that is left from the last "facet gadget refresh" but is not included in new set
function hideUnRenderedFacets(objFacets, objCategories) {
//this check is needee
var renderedFacetElements = dojo.query("[id^=facet_]");
for (var i = 0; i < renderedFacetElements.length; i++) {
var isFacetShouldBeRendered = false;
var id = renderedFacetElements[i].id.substring(6);
for(var j = 0; j < objFacets.length; j++) {
if (id == objFacets[j].id) {
isFacetShouldBeRendered = true;
}
}
if (!isFacetShouldBeRendered) {
for(var j = 0; j < objCategories.length; j++) {
if (id == objCategories[j].catid) {
isFacetShouldBeRendered = true;
}
}
}
//do not render facet
if (!isFacetShouldBeRendered) {
renderedFacetElements[i].parentNode.removeChild(renderedFacetElements[i]);
}
}
}
/**
* This method render facet panel + loads products.
* @param searchSettings search settings
* @param category - facet category
*/
function handleProductsLoad(searchSettings, category) {
p_url = contextPath + "/browse/gadgets/categoryContents.jsp";
if (typeof(searchSettings.urlParams) != "undefined") {
p_url = p_url + '?' + searchSettings.urlParams;
searchSettings.urlParams = '';
}
var bindArgs = {
url : p_url,
content : searchSettings,
error : function(response, ioArgs) {
ajaxRequestIdentefication(false);
console.debug("Error: " + response);
},
load : function(response, ioArgs) {
var facetJson = response.substring(response.indexOf('facetJsonStart') + 14, response.indexOf('facetJsonEnd'));
var objStructure = dojo.trim(facetJson);
handleFacetLoad(objStructure, category);
atg.store.facet.handleResponse(response, null);
ajaxRequestIdentefication(false);
}
};
ajaxRequestIdentefication(true);
dojo.xhrGet(bindArgs);
}
/*
ajax request content for pagination element
pResultsPerPage - or pageSize or howMany - count of products shown per one page
pCategoryId - category id - used adv search or for category browsing
pFeatures - feature - used for adv search. one of search options
pViewAll - view all parameter - indicate request on show all products (user can see page by page or all)
pSearchInput - search criteria - text being searched
pPageNum - current page number - used for navigation. Page which products will be shown
*/
function simplePagination(pResultsPerPage, pCategoryId, pFeatures, pViewAll, pSearchInput, pPageNum) {
if (pViewAll == 'true') {
p_url = contextPath + '/search/gadgets/searchRequestHandler.jsp?viewAll=true';
pResultsPerPage = -1;
pPageNum = -1;
} else {
p_url = contextPath + '/search/gadgets/searchRequestHandler.jsp';
}
var data = {q_pageSize: pResultsPerPage, categoryId: pCategoryId, features: pFeatures, searchInput: pSearchInput, q_pageNum: pPageNum, preventFormHandlerRedirect: false};
madeAJAXRequest(data, p_url);
}
/**
* Used for ajax enabldd category navigation.
* Used by sort and pagination links on the browsing category pages.
* @param pViewAll view all
* @param pFragmentIdentifier fragment identifier
*/
function ajaxNavigation(pCategoryId, pPageNum, pViewAll, pDocSort, pPageSize, pFragmentIdentifier, pIsForward) {
if (pViewAll == 'true') {
p_url = contextPath + '/browse/gadgets/categoryProducts.jsp?viewAll=true';
} else {
p_url = contextPath + '/browse/gadgets/categoryProducts.jsp';
}
var data = {categoryId: pCategoryId, q_pageSize: pPageSize, q_pageNum: pPageNum, q_docSort:pDocSort};
// Fix for Jira USPS-987: For some reason resetting the state using HistoryState() results in infinte AJAX request loop
if (pIsForward && pIsForward == "1") {
console.debug("It's a browser forward event.");
} else {
setFragmentIdentifier(pFragmentIdentifier);
}
madeAJAXRequest(data, p_url);
}
function madeAJAXRequest(pData, pUrl) {
var bindArgs = {
content: pData,
url : pUrl,
error : function(response, ioArgs) {
ajaxRequestIdentefication(false);
console.debug("Error: " + response);
},
load : function(response, ioArgs) {
var mainObject=dojo.query("[divId='ajaxRefreshableContent']")[0];
if(mainObject){
mainObject.innerHTML=response;
}
ajaxRequestIdentefication(false);
}
};
skipPageReload = true;
ajaxRequestIdentefication(true);
dojo.xhrGet(bindArgs);
}
/**
* Function to prepare fragment identifier, which will be used to hold state of the ajax navigation
* @param docSort
* @param pageNumber
* @param isViewAll
* @param facetUrl
* @param categoryId
* @param nsraction shows what loader (jsp) should proceed this parameters.
* @param isATGSearch - needed to identify - should we use facetTrail (feature of the ATGSearch)
*/
function generateNavigationFragmentIdentifier(docSort, pageNumber, isViewAll, facetUrl, categoryId, nsraction, isATGSearch) {
var ajaxStateParams = "#q_docSort=" + docSort;
if (isATGSearch) {
ajaxStateParams = ajaxStateParams + "&q_docSortOrder=" + dojo.byId("qfh_docSortOrder").value;
}
ajaxStateParams = ajaxStateParams + "&q_pageNum=" + pageNumber + "&viewAll=" + isViewAll;
if (isATGSearch) {
ajaxStateParams = ajaxStateParams + "&q_pageSize=" + dojo.byId("qfh_pageSize").value + "&q_question=" + dojo.byId("questionSaved").value;
}
ajaxStateParams = ajaxStateParams + "&q_facetTrail=" + facetUrl + "&categoryId=" + categoryId + "&nsraction=" + nsraction;
return ajaxStateParams;
}
// ---------------------- dojo.back based history ----------------------------
function HistoryState(state) {
this.state = state;
this.restoreState = function() {
if (this.state && this.state != '') {
ajaxNavigationStateReload(this.state);
} else {
location.reload();
}
};
this.restoreStateForward = function() {
this.state = this.state + "&q_isForward=1";
this.restoreState();
};
// back, forward and changeUrl are needed by dojo
this.back = this.restoreState;
this.forward = this.restoreStateForward; // Jira USPS-987, forward gets its own function to pass qry param telling it's a forward; this is consumed by ajaxNavivigationXXX() methods
this.changeUrl = this.state;
}
/**
* This function is used to reload ajax navigation state. Mainly for back button support.
* Should be called on the pages where ajax enabled facets and navigation is used
*/
function ajaxNavigationStateReload(savedDirectives) {
if (isFragmentIdentifierSet(savedDirectives)) {
var sDirQuestion = extractParam(savedDirectives, 'q_question');
var sDirFacetTrail = extractParam(savedDirectives, 'q_facetTrail');
if (sDirQuestion != '' && typeof(dojo.byId("questionSaved")) != "undefined") {
dojo.byId("questionSaved").value = sDirQuestion;
}
if (sDirFacetTrail != '' && typeof(dojo.byId("facetTrailSaved")) != "undefined") {
dojo.byId("facetTrailSaved").value = sDirFacetTrail;
}
var action = extractParam(savedDirectives, 'nsraction');
if (action == 'handleProductsLoad') {
var searchSettings = {
urlParams: savedDirectives.substring(1, savedDirectives.length)
};
handleProductsLoad(searchSettings, '');
} else if (action == 'categoryProducts') {
var pCategoryId = extractParam(savedDirectives, 'categoryId');
var pPageNum = extractParam(savedDirectives, 'q_pageNum');
var pViewAll = extractParam(savedDirectives, 'viewAll');
var pDocSort = extractParam(savedDirectives, 'q_docSort');
var pPageSize = extractParam(savedDirectives, 'q_pageSize');
var isForward = extractParam(savedDirectives, 'q_isForward');
ajaxNavigation(pCategoryId, pPageNum, pViewAll, pDocSort, pPageSize, savedDirectives, isForward);
if (extractParam(savedDirectives, 'reloadFPcategory') != '') {
// reset page number on facet click
var searchSettings = {q_docSort: dojo.byId("qfh_docSort").value, q_docSortOrder: dojo.byId("qfh_docSortOrder").value, q_pageNum:1, viewAll:"false", q_pageSize: dojo.byId("qfh_pageSize").value, q_question: dojo.byId("questionSaved").value, q_facetTrail: '', categoryId: dojo.byId("catIdSaved").value};
reloadFacets(searchSettings, extractParam(savedDirectives, 'reloadFPcategory'));
}
}
}
}
function isFragmentIdentifierSet(savedDirectives) {
return (savedDirectives != '' && savedDirectives.indexOf('nsraction') > -1);
}
/**
* Function is used to extract param from the string
* @param str
* @param paramName
*/
function extractParam(str, paramName) {
var tempStartPos = str.indexOf(paramName);
if (tempStartPos > -1) {
tempStartPos = tempStartPos + paramName.length + 1; // 1 for = sign
var tempEndPos = str.indexOf('&', tempStartPos);
tempEndPos = (tempEndPos > -1) ? tempEndPos : str.length;
return str.substring(tempStartPos, tempEndPos);
} else {
return '';
}
}
function setFragmentIdentifier(pFragmentIdentifier) {
dojo.back.addToHistory(new HistoryState(pFragmentIdentifier));
}
function reloadFacets(searchSettings, category) {
var bindArgs = {
url : contextPath + "/atgsearch/gadgets/ajaxSearch.jsp",
content : searchSettings,
error : function(response, ioArgs) {
console.debug("Error: " + response);
},
load : function(response, ioArgs) {
if (typeof(response) != "undefined") {
var objStructure = dojo.trim(response);
handleFacetLoad(objStructure, category);
}
}
};
dojo.xhrGet(bindArgs);
}
/**
*
* @param showAjaxSpinnerImage boolean identifying should we add ajax spinner image or remove
*/
function ajaxRequestIdentefication(showAjaxSpinnerImage) {
if (showAjaxSpinnerImage) {
dojo.query("div[name='transparentLayer']").addClass("active");
dojo.query("div[name='ajaxSpinner']").addClass("active");
} else {
dojo.query("div[name='transparentLayer']").removeClass("active");
dojo.query("div[name='ajaxSpinner']").removeClass("active");
}
}
/**
* @param checkBoxElement checkbox on checkout page that tells to create or not to create an account
*/
function updateSaveCCoption(checkBoxElement) {
var sCCInfoBox = dojo.byId('saveCreditCardInfoBox');
//checkBoxElement.checked == true - is not redunency
if (checkBoxElement.checked == true || checkBoxElement.checked == 'true' || checkBoxElement.checked == 'checked' ) {
sCCInfoBox.style.display = "";
} else {
sCCInfoBox.style.display = "none";
}
}