/** * Pesquisa Inteligente * @description Execurar buscas sem recarregar a página * @author Carlos Vinicius * @contributor Edson Domingos Júnior * @version 3.9 * @date 2012-10-22 */ "function"!==typeof String.prototype.replaceSpecialChars&&(String.prototype.replaceSpecialChars=function(){var b={"\u00e7":"c","\u00e6":"ae","\u0153":"oe","\u00e1":"a","\u00e9":"e","\u00ed":"i","\u00f3":"o","\u00fa":"u","\u00e0":"a","\u00e8":"e","\u00ec":"i","\u00f2":"o","\u00f9":"u","\u00e4":"a","\u00eb":"e","\u00ef":"i","\u00f6":"o","\u00fc":"u","\u00ff":"y","\u00e2":"a","\u00ea":"e","\u00ee":"i","\u00f4":"o","\u00fb":"u","\u00e5":"a","\u00e3":"a","\u00f8":"o","\u00f5":"o",u:"u","\u00c1":"A","\u00c9":"E","\u00cd":"I","\u00d3":"O","\u00da":"U","\u00ca":"E","\u00d4":"O","\u00dc":"U","\u00c3":"A","\u00d5":"O","\u00c0":"A","\u00c7":"C"};return this.replace(/[\u00e0-\u00fa]/g,function(a){return"undefined"!=typeof b[a]?b[a]:a})}); "function"!==typeof String.prototype.trim&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}); jQuery.fn.vtexSmartResearch=function(opts) { $this=jQuery(this); var log=function(msg,type){ if(typeof console=="object") console.log("[Smart Research - "+(type||"Erro")+"] "+msg); }; var defaults= { pageLimit:null, // Número máximo de páginas que o script irá retornar. Exemplo "pageLimit=3" só será retornado resultados até a terceira página loadContent:".prateleira[id^=ResultItems]", // Elemento que esta em volta da(s) prateleira(s) de produtos. shelfClass:".prateleira", // Pratelira de produtos (filha do elemento definido de um "loadContent") filtersMenu:".search-multiple-navigator", // Menu com os filtros linksMenu:".search-single-navigator", // Menu de links menuDepartament:".navigation .menu-departamento", // seletor do menu da página de departamentos mergeMenu:true, // Define se o menu de links será mesclado com o de filtros será mesclado na página de departamento insertMenuAfter:".search-multiple-navigator h3:first", // O menu de links será inserido após este elemento emptySearchElem:jQuery('
'), // Elemento Html (em Objeto jQuery) no qual será adicionado a mensagem de busca vazia elemLoading:'
Carregando ...
', // Elemento com mensagem de carregando ao iniciar a requisição da página seguinte returnTopText:'voltar aoTOPO', // Mensagem de "retornar ao topo" emptySearchMsg:'

Esta combinação de filtros não retornou nenhum resultado!

', // Html com a mensagem para ser apresentada quando não existirem resultados para os filtros selecionados filterErrorMsg:"Houve um erro ao tentar filtrar a página!", // Mensagem de erro exibida quando existe algum erro de servidor ao aplicar os filtros searchUrl:null, // Url da página de busca (opicional) usePopup:false, // Opção p/ definir se deseja que a mensagem de não localizado seja exibida em um popup showLinks:true, // Exibe o menu de links caso o de filtro não seja encontrado popupAutoCloseSeconds:3, // Caso esteja utilizando popup, defina aqui o tempo para que ele feche automaticamente // Função que retorna o valor p/ onde a página deve rolar quando o usuário marca ou desmarca um filtro filterScrollTop:function(shelfOffset) { return (shelfOffset.top-20); }, callback:function(){}, // Cálculo do tamanho do conteúdo/vitrine para que uma nova página seja chamada antes do usuário chegar ao "final" do site getShelfHeight:function(container) { return (container.scrollTop()+container.height()); }, // Callback após inserir a prateleira na página shelfCallback:function(){}, // Callback em cada requisição Ajax (Para requisições feitas com sucesso) // Recebe como parâmetro um objeto contendo a quantidade total de requisições feitas e a quantidade de filtros selecionados ajaxCallback:function(){}, // Função que é executada quando a seleção de filtros não retorna nenhum resultado // Recebe como parâmetro um objeto contendo a quantidade total de requisições feitas e a quantidade de filtros selecionados emptySearchCallback:function(){}, // Função para permitir ou não que a rolagem infinita execute na página esta deve retornar "true" ou "false" // Recebe como parâmetro um objeto contendo a quantidade total de requisições feitas e a quantidade de filtros selecionados authorizeScroll:function(){return true;}, // Função para permitir ou não que o conteúdo de "loadContent" seja atualizado. Esta deve retornar "true" ou "false" // Recebe como parâmetro um objeto contendo a quantidade total de requisições feitas e a quantidade de filtros selecionados authorizeUpdate:function(){return true;}, // Callback de cada laço percorrendo os fildsets e os labels. Retorna um objeto com algumas informações labelCallback:function(data){} }; var options=jQuery.extend(defaults, opts), _console="object"===typeof(console), $empty=jQuery(""), elemLoading=jQuery(options.elemLoading), currentPage=2, moreResults=true, _window=jQuery(window), _document=jQuery(document), _html=jQuery("html,body"), body=jQuery("body"), currentSearchUrl="", urlFilters="", searchUrl="", animatingFilter=false, loadContentE=jQuery(options.loadContent), filtersMenuE=jQuery(options.filtersMenu), ajaxCallbackObj={requests:0,filters:0,isEmpty:false}, labelCallbackData={}; var fn= { getUrl:function(scroll) { var s=scroll||false; if(s) return currentSearchUrl.replace(/PageNumber=[0-9]*/,"PageNumber="+currentPage); else return (searchUrl+urlFilters).replace(/PageNumber=[0-9]*/,"PageNumber="+pageNumber); }, getSearchUrl:function() { var url, content, preg; jQuery("script:not([src])").each(function(){ content=jQuery(this)[0].innerHTML; preg=/\/buscapagina\?.+&PageNumber=/i; if(content.search(/\/buscapagina\?/i)>-1) { url=preg.exec(content); return false; } }); if(typeof(url)!=="undefined" && typeof(url[0])!=="undefined") return url[0]; else { log("Não foi possível localizar a url de busca da página.\n Tente adicionar o .js ao final da página. \n[Método: getSearchUrl]"); return ""; } }, scrollToTop:function() { var elem=body.find("#returnToTop"); if(elem.length<1) { elem=jQuery('
'+options.returnTopText+'
'); body.append(elem); } var windowH=_window.height(); _window.bind("resize",function(){ windowH=_window.height(); }); _window.bind("scroll",function(){ if(_window.scrollTop()>(windowH)) elem.stop(true).fadeTo(300,1,function(){elem.show();}); else elem.stop(true).fadeTo(300,0,function(){elem.hide();}); }); elem.bind("click",function(){ _html.animate({scrollTop:0},"slow"); return false; }); }, infinitScroll:function() { var elementPages,pages,currentStatus,tmp; elementPages=body.find(".pager:first").attr("id"); tmp=(elementPages||"").split("_").pop(); pages=(null!==options.pageLimit)?options.pageLimit:window["pagecount_"+tmp]; currentStatus=true; // Reportando erros // if("undefined"===typeof pages) log("Não foi possível localizar quantidade de páginas.\n Tente adicionar o .js ao final da página. \n[Método: infinitScroll]"); if("undefined"===typeof pages) pages=99999999; _window.bind('scroll',function(){ var _this=jQuery(this); if(!animatingFilter && currentPage<=pages && moreResults && options.authorizeScroll(ajaxCallbackObj)) { if((_this.scrollTop()+_this.height())>=(options.getShelfHeight(loadContentE)) && currentStatus) { var currentItems=loadContentE.find(options.shelfClass).filter(":last"); currentItems.after(elemLoading); currentStatus=false; pageJqxhr=jQuery.ajax({ url: fn.getUrl(true), success:function(data) { if(data.trim().length<1) { moreResults=false; log("Não existem mais resultados a partir da página: "+(currentPage-1),"Aviso"); } else currentItems.after(data); currentStatus=true; elemLoading.remove(); ajaxCallbackObj.requests++; options.ajaxCallback(ajaxCallbackObj); } }); currentPage++; } } else return false; }); } }; if(null!==options.searchUrl) currentSearchUrl=searchUrl=options.searchUrl; else currentSearchUrl=searchUrl=fn.getSearchUrl(); // Reporting Errors if($this.length<1) { log("Nenhuma opção de filtro encontrada","Aviso"); if(options.showLinks) jQuery(options.linksMenu).css("visibility","visible").show(); fn.infinitScroll(); fn.scrollToTop(); return $this; } // Reporting Errors if(loadContentE.length<1){log("Elemento para destino da requisição não foi encontrado \n ("+loadContentE.selector+")"); return false;} if(filtersMenuE.length<1) log("O menu de filtros não foi encontrado \n ("+filtersMenuE.selector+")"); var currentUrl=document.location.href, linksMenuE=jQuery(options.linksMenu), prodOverlay=jQuery('
'), departamentE=jQuery(options.menuDepartament), loadContentOffset=loadContentE.offset(), pageNumber=1, shelfJqxhr=null, pageJqxhr=null; options.emptySearchElem.append(options.emptySearchMsg); loadContentE.before(prodOverlay); var fns= { exec:function() { fns.setFilterMenu(); fns.fieldsetFormat(); $this.each(function(){ var _this=jQuery(this), label=_this.parent(); if(_this.is(":checked")) { urlFilters+="&"+(_this.attr("rel")||""); // Adicionando classe ao label label.addClass("sr_selected"); } fns.adjustText(_this); // Add span vazio (depois de executar de "adjustText") label.append(''); _this.bind("change",function(){ fns.inputAction(); if(_this.is(":checked")) fns.addFilter(_this); else fns.removeFilter(_this); ajaxCallbackObj.filters=$this.filter(":checked").length; }); }); if(""!==urlFilters) fns.addFilter($empty); }, mergeMenu:function() { if(!options.mergeMenu) return false; var elem=departamentE; elem.insertAfter(options.insertMenuAfter); fns.departamentMenuFormat(elem); }, mergeMenuList:function() { var i=0; filtersMenuE.find("h3,h4").each(function(){ var ul=linksMenuE.find("h3,h4").eq(i).next("ul"); ul.insertAfter(jQuery(this)); fns.departamentMenuFormat(ul); i++; }); }, departamentMenuFormat:function(elem) { elem.find("a").each(function(){ var a=jQuery(this); a.text(fns.removeCounter(a.text())); }); }, fieldsetFormat:function() { labelCallbackData.fieldsetCount=0; labelCallbackData.tmpCurrentLabel={}; filtersMenuE.find("fieldset").each(function(){ var $t=jQuery(this), label=$t.find("label"), fieldsetClass="filtro_"+($t.find("h5:first").text()||"").toLowerCase().replaceSpecialChars().replace(/\s/g,"-"); labelCallbackData[fieldsetClass]={}; // Ocultar fieldset quando não existe filtro e sair desste método if(label.length<1) { $t.hide(); return; } // Adicionar classe ao fieldset $t.addClass(fieldsetClass); // Adicionando classe e título ao label label.each(function(ndx){ var t=jQuery(this), v=(t.find("input").val()||""), labelClass="sr_"+v.toLowerCase().replaceSpecialChars().replace(/\s/g,"-"); labelCallbackData.tmpCurrentLabel= { fieldsetParent:[$t,fieldsetClass], elem:t }; labelCallbackData[fieldsetClass][ndx.toString()]= { className:labelClass, title:v }; t.addClass(labelClass).attr({"title":v,"index":ndx}); options.labelCallback(labelCallbackData); }); labelCallbackData.fieldsetCount++; }); }, inputAction:function() { if(null!==pageJqxhr) pageJqxhr.abort(); if(null!==shelfJqxhr) shelfJqxhr.abort(); currentPage=2; moreResults=true; }, addFilter:function(input) { urlFilters+="&"+(input.attr("rel")||""); prodOverlay.fadeTo(300,0.6); currentSearchUrl=fn.getUrl(); shelfJqxhr=jQuery.ajax({ url:currentSearchUrl, success:fns.filterAjaxSuccess, error:fns.filterAjaxError }); // Adicionando classe ao label input.parent().addClass("sr_selected"); }, removeFilter:function(input) { var url=(input.attr("rel")||""); prodOverlay.fadeTo(300,0.6); if(url!=="") urlFilters=urlFilters.replace("&"+url,""); currentSearchUrl=fn.getUrl(); shelfJqxhr=jQuery.ajax({ url:currentSearchUrl, success:fns.filterAjaxSuccess, error:fns.filterAjaxError }); // Removendo classe do label input.parent().removeClass("sr_selected"); }, filterAjaxSuccess:function(data) { var $data=jQuery(data); prodOverlay.fadeTo(300,0,function(){jQuery(this).hide();}); fns.updateContent($data); ajaxCallbackObj.requests++; options.ajaxCallback(ajaxCallbackObj); _html.animate({scrollTop:options.filterScrollTop((loadContentOffset||{top:0,left:0}))},600); }, filterAjaxError:function() { prodOverlay.fadeTo(300,0,function(){jQuery(this).hide();}); alert(options.filterErrorMsg); log("Houve um erro ao tentar fazer a requisição da página com filtros."); }, updateContent:function($data) { animatingFilter=true; if(!options.authorizeUpdate(ajaxCallbackObj)) return false; var shelf=$data.filter(options.shelfClass); var shelfPage=loadContentE.find(options.shelfClass); (shelfPage.length>0?shelfPage:options.emptySearchElem).slideUp(600,function(){ jQuery(this).remove(); // Removendo a mensagem de busca vazia, esta remoção "forçada" foi feita para // corrigir um bug encontrado ao clicar em vários filtros if(options.usePopup) body.find(".boxPopUp2").vtexPopUp2(); else options.emptySearchElem.remove(); if(shelf.length>0) { shelf.hide(); loadContentE.append(shelf); options.shelfCallback(); shelf.slideDown(600,function(){ animatingFilter=false; }); ajaxCallbackObj.isEmpty=false; } else { ajaxCallbackObj.isEmpty=true; if(options.usePopup) options.emptySearchElem.addClass("freeContent autoClose ac_"+options.popupAutoCloseSeconds).vtexPopUp2().stop(true).show(); else { loadContentE.append(options.emptySearchElem); options.emptySearchElem.show().css("height","auto").fadeTo(300,0.2,function(){ options.emptySearchElem.fadeTo(300,1); }); } options.emptySearchCallback(ajaxCallbackObj); } }); }, adjustText:function(input) { var label=input.parent(), text=label.text(); qtt=""; text=fns.removeCounter(text); label.text(text).prepend(input); }, removeCounter:function(text) { return text.replace(/\([0-9]+\)/ig,function(a){ qtt=a.replace(/\(|\)/,""); return ""; }); }, setFilterMenu:function() { if(filtersMenuE.length>0) { linksMenuE.hide(); filtersMenuE.show(); } } }; if(body.hasClass("departamento")) fns.mergeMenu(); else if(body.hasClass("categoria") || body.hasClass("resultado-busca")) fns.mergeMenuList(); fns.exec(); fn.infinitScroll(); fn.scrollToTop(); options.callback(); // Exibindo o menu filtersMenuE.css("visibility","visible"); };