Advertisement
Guest User

Untitled

a guest
Dec 12th, 2019
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.52 KB | None | 0 0
  1. class T092M {
  2. constructor() {
  3. this.newFilterAndOrderButton();
  4. }
  5.  
  6. newFilterAndOrderButton() {
  7. const refElem = document.querySelector(".department__top");
  8.  
  9. const html = `
  10. <div class="juni-new-btns">
  11. <button type="button" class="btn-juni-1" id="open-filter-menu">
  12. Filtrar
  13. <span id="filterAmount"></span>
  14. </button>
  15. <div id="move-old-order"></div>
  16. </div>
  17. <div id="filter-control-cat-page"></div>
  18. `;
  19.  
  20. refElem.insertAdjacentHTML("afterend", html);
  21.  
  22. // Move o atual botão de ordenar para a nova posição
  23. const [, originalOrderBtn] = document.querySelectorAll(".refinar-busca");
  24. $("#move-old-order").append(originalOrderBtn);
  25. }
  26. }
  27.  
  28. new T092M();
  29.  
  30. class SliderMenu {
  31. constructor(triggerElement) {
  32. this.trigger = triggerElement;
  33. this.opts = this.defineFilterOptions();
  34. this.open = false;
  35.  
  36. // { category: "Tamanho", param: "fq=specificationFilter_27:35", labelName: "35" }
  37. this.params = [];
  38.  
  39. this.init();
  40. }
  41.  
  42. init() {
  43. const { trigger } = this;
  44. trigger.addEventListener("click", () => {
  45. const { openMenu } = this;
  46. openMenu.bind(this)();
  47. });
  48.  
  49. this.buildMenu();
  50. this.buildMenuItens();
  51. }
  52.  
  53. buildMenu() {
  54. const html = `
  55. <div class="slider-menu">
  56. <div class="slider-menu-overlay"></div>
  57. <main class="slider-menu-content">
  58. <div id="content"></div>
  59. <footer>
  60. <button id="bt-limpar" type="button" class="clean-filter-btn">Limpar filtros</button>
  61. <button id="bt-filtrar" type="button">OK</button>
  62. </footer>
  63. </main>
  64. </div>
  65. `;
  66.  
  67. document.body.insertAdjacentHTML("afterbegin", html);
  68.  
  69. const overlay = document.querySelector(".slider-menu-overlay");
  70. overlay.addEventListener("click", this.closeMenu);
  71.  
  72. // Filtrar
  73. document.getElementById("bt-filtrar").addEventListener("click", () => {
  74. // Faz a requisição
  75. this.fetchItens();
  76.  
  77. // Fecha o menu
  78. this.closeMenu();
  79. });
  80.  
  81. // Limpar filtros
  82. document.getElementById("bt-limpar").addEventListener("click", e => {
  83. this.limparFiltros();
  84. });
  85. }
  86.  
  87. buildMenuItens() {
  88. // Pega as opções que vão estar no menu
  89. const { opts } = this;
  90. const sliderContent = document.querySelector(
  91. ".slider-menu-content #content"
  92. );
  93.  
  94. // Header escrito "Filtros"
  95. const filterHeader = document.createElement("header");
  96. filterHeader.classList.add("slider-header");
  97. filterHeader.innerHTML = "<span>Filtros</span>";
  98.  
  99. // Botão de fechar o filtro
  100. const closeFilterMenuBtn = document.createElement("button");
  101. closeFilterMenuBtn.innerText = "<";
  102. closeFilterMenuBtn.addEventListener("click", this.closeMenu);
  103.  
  104. // Appenda o Titulo e o botão de fechar na tag <header>
  105. filterHeader.insertAdjacentElement("beforeend", closeFilterMenuBtn);
  106. sliderContent.insertAdjacentElement("beforebegin", filterHeader);
  107.  
  108. // Define as categorias de filtro COR, TAMANHO e FAIXA DE PREÇO
  109. opts.forEach(opt => {
  110. const { title, opts: filtersOpts, _class } = opt;
  111.  
  112. const div = document.createElement("div");
  113.  
  114. // Define um id pra div que vai conter os filtros aplicados da respectiva categoria
  115. // COR, TAMANHO E PREÇO
  116. const idFiltersAplied = title
  117. .split(" ")
  118. .join("_")
  119. .toLocaleLowerCase();
  120.  
  121. div.role = "button";
  122. div.classList.add("slider-item");
  123. div.innerHTML = `
  124. <div class="title">
  125. <h2>${title}</h2>
  126. <span id="${idFiltersAplied}-cat-aplied" class="filters-cat-aplied"></span>
  127. <span class="arrow"></span>
  128. </div>
  129. `;
  130.  
  131. // Cria a div que vai conter todas as opções de filtro da respectiva categoria
  132. const sliderSubs = document.createElement("div");
  133. sliderSubs.classList.add("slider-item-subs");
  134. if (_class) {
  135. sliderSubs.classList.add("price-filter-style");
  136. }
  137.  
  138. // Cria as opções de filtro de cada categoria ex: (Tamanho: [41,40,42], cor: [verde, amarelo])
  139. filtersOpts.forEach(filter => {
  140. const { name, rel, background } = filter;
  141. sliderSubs.insertAdjacentElement(
  142. "beforeend",
  143. this.buildCustomCheckBox(name, rel, background, title)
  144. );
  145. });
  146.  
  147. div.insertAdjacentElement("beforeend", sliderSubs);
  148.  
  149. sliderContent.insertAdjacentElement("beforeend", div);
  150. });
  151.  
  152. // add a div que vai conter os botões para remover os filtros
  153. sliderContent.insertAdjacentHTML(
  154. "beforeend",
  155. `<div id="filters-btns-bottom"></div>`
  156. );
  157.  
  158. // Adiciona o dropdown nas categorias de filtros
  159. document.querySelectorAll(".slider-item").forEach(slider => {
  160. const subs = slider.querySelector(".slider-item-subs");
  161. let clicked = false;
  162. slider.querySelector(".title").addEventListener("click", () => {
  163. if (!clicked) {
  164. $(subs).addClass("visible");
  165. $(subs).slideDown();
  166. clicked = true;
  167. } else {
  168. $(subs).removeClass("visible");
  169. $(subs).slideUp();
  170. clicked = false;
  171. }
  172. });
  173. });
  174. }
  175.  
  176. // label: Nome que vai aparecer
  177. // parametro: valor a ser mandado para requisição
  178. // categoria: cor, preço, valor
  179. buildCustomCheckBox(labelName, parametro, background, category) {
  180. const checkBoxGroup = document.createElement("div");
  181. checkBoxGroup.classList.add("checkbox-group");
  182.  
  183. // insere o input, input fake e o nome que deve aparecer pro usuário
  184. const input = document.createElement("input");
  185. input.type = "checkbox";
  186. input.name = parametro;
  187.  
  188. // Input fake
  189. const inputFake = document.createElement("span");
  190. inputFake.classList.add("fake-checkbox");
  191. inputFake.setAttribute("rel", parametro);
  192. inputFake.addEventListener("click", e => {
  193. const { target } = e;
  194. const param = target.getAttribute("rel");
  195.  
  196. const checked = target.classList.contains("checked");
  197. if (checked) {
  198. target.classList.remove("checked");
  199. this.removeParam(param);
  200. } else {
  201. target.classList.add("checked");
  202. this.addParam(param, category, labelName);
  203. console.log(this.params);
  204. }
  205. });
  206.  
  207. // label com o nome
  208. const label = document.createElement("label");
  209. label.innerText = labelName;
  210.  
  211. // Adiciona todos os elementos acima ao container checkBoxGroup
  212. checkBoxGroup.insertAdjacentElement("beforeend", inputFake);
  213. if (background) {
  214. const spanColor = document.createElement("span");
  215. spanColor.classList.add("span-color");
  216. spanColor.style.background = background;
  217. checkBoxGroup.insertAdjacentElement("beforeend", spanColor);
  218. }
  219. checkBoxGroup.insertAdjacentElement("beforeend", label);
  220. checkBoxGroup.insertAdjacentElement("beforeend", input);
  221.  
  222. return checkBoxGroup;
  223. }
  224.  
  225. addParam(param, category, labelName) {
  226. const { params, renderOnParamChange } = this;
  227. const exsist = params.find(p => p.param === param);
  228.  
  229. if (!exsist) {
  230. this.params.push({ category, param, labelName });
  231. }
  232. renderOnParamChange.bind(this)();
  233. }
  234.  
  235. removeParam(param) {
  236. const { params, renderOnParamChange, removeCheckMark } = this;
  237. const newParams = params.filter(p => p.param !== param);
  238.  
  239. this.params = newParams;
  240. renderOnParamChange.bind(this)();
  241. removeCheckMark(param);
  242. }
  243.  
  244. removeCheckMark(param) {
  245. document.querySelectorAll(".fake-checkbox.checked").forEach(cb => {
  246. const is = cb.getAttribute("rel") === param;
  247.  
  248. if (is) cb.classList.remove("checked");
  249. });
  250. }
  251.  
  252. updateFilterAmount() {
  253. document.getElementById("filterAmount").innerText = this.params.length
  254. ? `(${this.params.length})`
  255. : "";
  256. }
  257.  
  258. limparFiltros() {
  259. const { params } = this;
  260. this.params = [];
  261.  
  262. this.renderOnParamChange();
  263. params.forEach(p => this.removeCheckMark(p.param));
  264. this.fetchItens();
  265.  
  266. this.closeMenu();
  267. }
  268.  
  269. // Vou pegar todas as opções de filtro da páginas e setar numa propriedade da classe
  270. // a propriedade vai ser um objeto no seguinte formato:
  271. // { title: string, opts: [{ rel, name }] }
  272. defineFilterOptions() {
  273. const fieldsets = document.querySelectorAll(
  274. ".search-multiple-navigator fieldset"
  275. );
  276.  
  277. const itens = [...fieldsets].map(fieldset => {
  278. // Pega o tab com o titulo da categoria do filtro original
  279. const h5 = fieldset.querySelector("h5").innerText;
  280.  
  281. // Se for o item de cores
  282. const isColorItem = h5 === "Cores Filtráveis";
  283.  
  284. // Define o titulo
  285. const title = isColorItem ? "Cores" : h5;
  286. let opts = [];
  287.  
  288. const inputs = fieldset.querySelectorAll("div > label > input");
  289. inputs.forEach(input => {
  290. const rel = input.getAttribute("rel");
  291. const name = input.getAttribute("name");
  292. const { background } = window.getComputedStyle(
  293. input.nextElementSibling,
  294. ":before"
  295. );
  296.  
  297. // insere os inputs
  298. opts.push({
  299. rel,
  300. name,
  301. background: isColorItem ? background : null
  302. });
  303. });
  304.  
  305. return { title, opts };
  306. });
  307.  
  308. const filteredFilterOptions = itens.filter(item => {
  309. const { title } = item;
  310.  
  311. return title === "Cores" || title === "Tamanho";
  312. });
  313.  
  314. return [
  315. ...filteredFilterOptions,
  316. {
  317. title: "Preço",
  318. _class: "price-filter-style",
  319. opts: [
  320. { rel: "fq=P:0.00+TO+200.00", name: "até R$200" },
  321. { rel: "fq=P:200.00+TO+800.00", name: "R$200 - R$800" },
  322. { rel: "fq=P:800.00+TO+1500.00", name: "R$800 - R$1.500" }
  323. ]
  324. }
  325. ];
  326. }
  327.  
  328. // Define o primeiro parametro que vai na requisição com base no dataLayer da página
  329. defineCategoryParameter() {
  330. const [, category] = dataLayer[0].pageFacets[1].split("/");
  331. const parsedCategory = parseInt(category);
  332.  
  333. const subCategory = dataLayer[0].categoryId;
  334.  
  335. // Se forem iguais, quer dizer que não tem subcategoria na pagina
  336. // Ex: joias/brinco.
  337. if (parsedCategory === subCategory) {
  338. return `C:/${category}/`;
  339. }
  340. return `C:/${category}/${subCategory}/`;
  341. }
  342.  
  343. /**
  344. * @param {{ sizes: Array, colors: Array, prices: Array }} filtersSelected
  345. */
  346. async fetchItens() {
  347. const { params } = this;
  348. const categoryParameter = this.defineCategoryParameter();
  349.  
  350. let defaultBody = {
  351.  
  352. }
  353.  
  354. const defaultBody = {
  355. O: "OrderByReleaseDateDESC",
  356. PS: 24,
  357. sl: "c534df6b-b28d-1d0e-d68f-3efaf8c2db36",
  358. cc: 24,
  359. sm: 0,
  360. PageNumber: 1,
  361. fq: categoryParameter
  362. };
  363.  
  364. const urlParams = params.map(p => p.param);
  365.  
  366. const url = `https://www.abrand.com.br/buscapagina?${$.param(
  367. defaultBody
  368. )}&${urlParams.join("&")}`;
  369. fetch(url)
  370. .then(res => res.text())
  371. .then(data => {
  372. const [, ref] = document
  373. .querySelector(".pager.top")
  374. .getAttribute("id")
  375. .split("_");
  376. const container = document.querySelector(`#ResultItems_${ref}`);
  377. container.innerHTML = data;
  378. });
  379.  
  380. this.exibeFiltrosNoHeaderDaCategoria();
  381. this.buildApliedFiltersBtnsOnBottom();
  382. // Bota os filtros aplicados na página de categoria
  383. this.buildFiltersApliedOnCatPage();
  384. this.updateFilterAmount();
  385. }
  386.  
  387. exibeFiltrosNoHeaderDaCategoria() {
  388. const { params } = this;
  389.  
  390. const priceItens = params.filter(item => item.category === "Preço");
  391. const sizeItens = params.filter(item => item.category === "Tamanho");
  392. const colorItens = params.filter(item => item.category === "Cores");
  393.  
  394. // PRICE
  395. const pricesContainer = document.getElementById("preço-cat-aplied");
  396. let pricesHTML = "";
  397. if (priceItens.length) {
  398. pricesHTML = `(${priceItens
  399. .map((price, index, arr) => {
  400. if (index === 0) {
  401. return price.labelName;
  402. }
  403.  
  404. if (index < 2) {
  405. return `, ${price.labelName}`;
  406. }
  407.  
  408. if (index === 2) {
  409. return `, +${arr.length - 2}`;
  410. }
  411. })
  412. .join("")})`;
  413. }
  414.  
  415. pricesContainer.innerHTML = pricesHTML;
  416.  
  417. // TAMANHO
  418. const sizesContainer = document.getElementById("tamanho-cat-aplied");
  419. let sizesHTML = "";
  420. if (sizeItens.length) {
  421. sizesHTML = `(${sizeItens
  422. .map((size, index, arr) => {
  423. if (index === 0) {
  424. return size.labelName;
  425. }
  426.  
  427. if (index < 2) {
  428. return `, ${size.labelName}`;
  429. }
  430.  
  431. if (index === 2) {
  432. return `, +${arr.length - 2}`;
  433. }
  434. })
  435. .join("")})`;
  436. }
  437.  
  438. sizesContainer.innerHTML = sizesHTML;
  439.  
  440. // CORES
  441. const colorContainer = document.getElementById("cores-cat-aplied");
  442. let colorHtml = "";
  443. if (colorItens.length) {
  444. colorHtml = `(${colorItens
  445. .map((color, index, arr) => {
  446. if (index === 0) {
  447. return color.labelName;
  448. }
  449.  
  450. if (index < 2) {
  451. return `, ${color.labelName}`;
  452. }
  453.  
  454. if (index === 2) {
  455. return `, +${arr.length - 2}`;
  456. }
  457. })
  458. .join("")})`;
  459. }
  460.  
  461. colorContainer.innerHTML = colorHtml;
  462. }
  463.  
  464. /**
  465. * Exibe os filtros aplicados como botões no final do menu lateral
  466. */
  467. buildApliedFiltersBtnsOnBottom() {
  468. // {category: "Tamanho", param: "fq=specificationFilter_27:35", labelName: "35"}
  469. const { params } = this;
  470. const container = document.getElementById("filters-btns-bottom");
  471. container.innerHTML = "";
  472.  
  473. params.forEach(param => {
  474. const { category, param: rel, labelName } = param;
  475.  
  476. const button = document.createElement("button");
  477. button.type = "button";
  478. button.innerHTML = `<span class="close-icon"></span><span class="btn-filter-bottom-ttl">${labelName}</span>`;
  479. button.title = labelName;
  480. button.classList.add("btn-filter-selected");
  481.  
  482. button.addEventListener("click", e => {
  483. this.removeParam(rel);
  484. });
  485.  
  486. container.insertAdjacentElement("beforeend", button);
  487. });
  488. }
  489.  
  490. /**
  491. * Monta os filtros aplicados na página de categoria
  492. */
  493. buildFiltersApliedOnCatPage() {
  494. const { params } = this;
  495.  
  496. const container = document.getElementById("filter-control-cat-page");
  497. container.innerHTML = `
  498. <button class="clean-filter-btn cat" type="button">Limpar filtros</button>
  499. <div class="aplied-filters-cat"></div>
  500. `;
  501. if (!!params.length) {
  502. params.forEach(p => {
  503. const { param: rel, labelName } = p;
  504. const button = document.createElement("button");
  505. button.type = "button";
  506. button.innerHTML = `<span class="close-icon"></span><span class="btn-filter-bottom-ttl">${labelName}</span>`;
  507. button.title = labelName;
  508. button.classList.add("btn-filter-selected");
  509.  
  510. button.addEventListener("click", e => {
  511. this.removeParam(rel);
  512. this.buildFiltersApliedOnCatPage();
  513. this.fetchItens();
  514. });
  515.  
  516. container
  517. .querySelector(".aplied-filters-cat")
  518. .insertAdjacentElement("beforeend", button);
  519.  
  520. // Clique no botão de limpar filtros na categoria
  521. document
  522. .querySelector(".clean-filter-btn.cat")
  523. .addEventListener("click", e => {
  524. this.limparFiltros();
  525. });
  526. });
  527. } else {
  528. container.querySelector(".clean-filter-btn.cat").style.display = "none";
  529. container.querySelector(".aplied-filters-cat").style.display = "none";
  530. }
  531. }
  532.  
  533. // Toda vez que um parametro for adicionado ou removido executa esse método
  534. // Para atualizar tudo.
  535. renderOnParamChange() {
  536. this.buildApliedFiltersBtnsOnBottom();
  537. this.exibeFiltrosNoHeaderDaCategoria();
  538. }
  539.  
  540. openMenu() {
  541. this.open = true;
  542. const menu = document.querySelector(".slider-menu");
  543.  
  544. menu.classList.add("visible");
  545. document.body.classList.add("overflow-hidden");
  546. }
  547.  
  548. closeMenu() {
  549. this.open = false;
  550. const menu = document.querySelector(".slider-menu");
  551.  
  552. menu.classList.remove("visible");
  553. document.body.classList.remove("overflow-hidden");
  554. }
  555. }
  556.  
  557. const cara = new SliderMenu(document.getElementById("open-filter-menu"));
  558.  
  559. // new MenuFilter(document.querySelector(".helper-chat__help"));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement