class CollectionProduct extends HTMLElement{ constructor(){ super(); this.totalPage = 0; this.containerHeight = 0; this.perRow = this.dataset.row; this.limit = this.dataset.limit; this.viewmore = this.dataset.viewmore; this.layout = (this.dataset.layout) ? '-' + this.dataset.layout : ''; this.tagsFilter = []; this.currentPage = 1; this.initData(); this.length = this.data.length; this.progress = 0; this.parser = new DOMParser(); this.productsContainer = this.getElementsByClassName('products-container')[0]; this.collectionGrid = document.getElementsByClassName('collection-grid__wrapper')[0]; this.filterContainer = document.getElementsByClassName('grid__item--sidebar')[0]; this.submitFilter = document.getElementsByClassName('submitTagsFilter'); this.btnOpenFilterMobile = document.getElementsByClassName('js-drawer-open-collection-filters')[0]; if(this.btnOpenFilterMobile != undefined) { this.btnOpenFilterText = this.btnOpenFilterMobile.querySelector(".btn-filter-text"); } Array.from(this.submitFilter).forEach(function(btn){ btn.addEventListener("click", this.actionSubmitFilter.bind(this)); }, this); this.tagListActive = document.querySelectorAll('#CollectionSidebar-v2 .tag-list--active-tags'); if(this.filterContainer != undefined) { this.filterItems = this.filterContainer.querySelectorAll('.tag span'); Array.from(this.filterItems).forEach(function(element){ element.addEventListener("click", this.getTagsFilter.bind(this)); }, this); } if(this.viewmore == '' || !this.viewmore) { this.createPagination(); }else { this.createViewMore(); } } initData(){ this.data = []; let p = ''; try{ p = JSON.parse('{"handle":"kids-water-resistant-gps-smart-watch-pink","title":"Kids Water Resistant GPS Smart Watch - Pink","status":"ACTIVE","tags":["Additional Control_Historical Mileage","Additional Control_Historical Route","Colour_Pink","Connectivity_4G Sim Enabled","Device Type_Personal Alarm","OS Compatibility_Android","OS Compatibility_IOS","OS Compatibility_Windows","Power Source_Battery","Tracker Features_Geo-Fence Alarm","Tracker Features_Kids","Tracker Features_Listening","Tracker Features_Sim Card Slot","Tracker Features_SOS Button","Tracker Features_Water Proof","Tracker Features_Wrist Watch","Tracker Type_Kids GPS","Tracker Type_Personal GPS","Viewing_Built in screen"]}'); this.data.push(p); p = JSON.parse('{"handle":"kids-water-resistant-gps-smart-watch-blue","title":"Kids Water Resistant GPS Smart Watch - Blue","status":"ACTIVE","tags":["Additional Control_Historical Route","Collection_GPS Trackers","Colour_Blue","Connectivity_4G Sim Enabled","OS Compatibility_Android","OS Compatibility_IOS","OS Compatibility_Windows","Personal Security","Power Source_Battery","Tracker Features_Geo-Fence Alarm","Tracker Features_Kids","Tracker Features_Listening","Tracker Features_Sim Card Slot","Tracker Features_SOS Button","Tracker Features_Water Proof","Tracker Features_Wrist Watch","Tracker Type_Kids GPS","Viewing_Built in screen"]}'); this.data.push(p); p = JSON.parse('{"handle":"kids-water-resistant-gps-smart-watch-black","title":"Kids Water Resistant GPS Smart Watch - Black","status":"ACTIVE","tags":["Additional Control_Historical Route","Colour_Black","Connectivity_4G Sim Enabled","OS Compatibility_Android","OS Compatibility_IOS","OS Compatibility_Windows","Personal Security","Power Source_Battery","Tracker Features_Geo-Fence Alarm","Tracker Features_Kids","Tracker Features_Listening","Tracker Features_Sim Card Slot","Tracker Features_SOS Button","Tracker Features_Water Proof","Tracker Features_Wrist Watch","Tracker Type_Kids GPS","Tracker Type_Personal GPS","Viewing_Built in screen"]}'); this.data.push(p); p = JSON.parse('{"handle":"portable-hidden-camera-and-movement-detector","title":"Portable Hidden Camera Detector","status":"ACTIVE","tags":["Collection_Bug Detectors","Detector Type_Camera Detector","Detector Type_Wireless Frequency Detector","Device Type_Personal Alarm","New Arrivals","Power Source_Battery"]}'); this.data.push(p); p = JSON.parse('{"handle":"portable-door-stopper-alarm","title":"Portable Door Stopper Alarm","status":"ACTIVE","tags":["Device Type_Personal Alarm","Personal Security","Power Source_Battery"]}'); this.data.push(p); p = JSON.parse('{"handle":"portable-personal-alarm-white","title":"Portable Personal Alarm (White)","status":"ACTIVE","tags":["Device Type_Personal Alarm","Power Source_Battery"]}'); this.data.push(p); p = JSON.parse('{"handle":"portable-personal-alarm-blue","title":"Portable Personal Alarm (Blue)","status":"ACTIVE","tags":["Device Type_Personal Alarm","Personal Security","Power Source_Battery"]}'); this.data.push(p); p = JSON.parse('{"handle":"4g-personal-alarm-gps-tracker-with-sos","title":"4G Personal Alarm & GPS Tracker with SOS","status":"ACTIVE","tags":["Badge: New","Connectivity_4G Sim Enabled","Features_Smartphone App","GPS Accuracy_0-15 meters","Microphone_Built-In","New Arrivals","Other","Personal Security","Tracker Features_Geo-Fence Alarm","Tracker Features_Portable","Tracker Features_Water Proof","Tracker Type_Personal GPS"]}'); this.data.push(p); p = JSON.parse('{"handle":"personal-tracker-qbitm","title":"4G Compact Portable Personal Tracker with Geo-fence & SOS Alarm","status":"ACTIVE","tags":["Application_Tracksolid Pro","Battery Capacity_650 mAh","Cheating Spouse","Collection_GPS Trackers","Device Type_Personal Alarm","OS Compatibility_Android","OS Compatibility_IOS","OS Compatibility_Windows","Personal Alarms","Personal GPS Trackers","Personal Security","Power Source_Battery","Tracker Features_Compact","Tracker Features_Geo-Fence Alarm","Tracker Features_Kids","Tracker Features_Portable","Tracker Features_Sim Card Slot","Tracker Features_SOS Button","Tracker Type_Asset GPS","Tracker Type_Car GPS","Tracker Type_Kids GPS","Tracker Type_Personal GPS"]}'); this.data.push(p); p = JSON.parse('{"handle":"7-in-1-multi-functional-personal-alarm","title":"7-IN-1 Ultimate Multi-functional Personal Alarm (Grey)","status":"ACTIVE","tags":["Device Type_Personal Alarm","Features_Motion Activated","Personal Alarms","Personal Security","Power Source_Battery","SOS Alert"]}'); this.data.push(p); p = JSON.parse('{"handle":"watch-dog-alarm-with-remote-control","title":"Watch Dog\/Alarm With Remote Control","status":"ACTIVE","tags":["Application_No App","Device Type_Personal Alarm","Mount_Free standing","Personal Alarms","Personal Security","Power Source_Plug In"]}'); this.data.push(p); p = JSON.parse('{"handle":"smart-locator-with-apple-find-my","title":"MFI Certified Smart Bluetooth Tracker Works with Apple Find My (White, iOS only)","status":"ACTIVE","tags":["Device Type_Personal Alarm","Key Finder","Location_Body Worn","OS Compatibility_IOS","Personal Alarms","Personal GPS Trackers","Personal Locator","Personal Security","Smart Locator","Tracker Features_Anti-Theft","Tracker Features_Kids","Tracker Type_Kids GPS","Tracker Type_Personal GPS"]}'); this.data.push(p); p = JSON.parse('{"handle":"binocular-night-vision-full-color-4k","title":"4K Night Vision Binoculars with Long Viewing Distance & Rechargeable Lithium Battery (Full Color NV)","status":"ACTIVE","tags":["Application_No App","Battery Capacity_5000 mAh","Camera Features_No Internet Required","Camera Type_Surveillance","Collection_Spy Camera","Colour_Black","Law Enforcement","Location_Outdoor","night vision","night vision binocular","Night Vision Range_100m","Night Vision_Night Vision Enabled","Outdoor Camera Type_Trail","Personal Security","Power Source_Battery","Recording Source_Audio + Video","Storage Type_Memory Card","Storage_Memory Card","Video Playback Viewing_Memory Stored","Video Resolution_UHD 2160p (4k)","Viewing_Built in screen","Zoom_Digital"]}'); this.data.push(p); p = JSON.parse('{"handle":"2-pack-mfi-certified-smart-bluetooth-tracker-works-with-apple-find-my-white-ios-only","title":"[2 Pack] MFI Certified Smart Bluetooth Tracker Works with Apple Find My (White, iOS only)","status":"ACTIVE","tags":["Collection_GPS Trackers","GPS Accuracy_0-5 meters","Key Finder","OS Compatibility_IOS","Personal Alarms","Personal GPS Trackers","Personal Locator","Personal Security","Power Source_Battery","Smart Locator"]}'); this.data.push(p); p = JSON.parse('{"handle":"btu20-handheld-ultrasonic-dog-training-anti-bark-device","title":"GuardianPulse-Barktec Ultrasonic Dog Deterrent Device","status":"ACTIVE","tags":["__label:New from eDog","all products","Device Type_Personal Alarm","Features_Ultrasonic","Features_Water Resistant","Issue_Safety","Issue_Stop Barking","Large Dogs","Medium Dogs","Other Training Products","Personal Alarms","Personal Security","Type_Anti Dog Barking Device","Type_New","Type_Ultrasonic"]}'); this.data.push(p); } catch(e){ console.error(e); } } loadProductsGrid(start, stop, data){ let number_product = stop - start; for(let i = start; i < stop; i++) { let url = window.location.origin + '/products/' + data[i].handle + "?view=grid-item" + this.layout; fetch(url) .then((res) => { if(res.status == 404){ return false; } return res.text(); }) .then(res => this.addProduct(res, i, number_product)) .catch(err => console.log(err)); } } addProduct(res, i, number_product){ this.progress++; let doc = this.parser.parseFromString(res, 'text/html'); let product = doc.querySelector(".grid-product"); let layout = ''; let items_layout = document.getElementsByClassName('item-layout'); for(let i = 0; i < items_layout.length; i++) { if(items_layout[i].classList.contains('active')) { layout = items_layout[i].dataset.layout; } } if(product != null) { product.style.display = 'flex'; product.style.order = i + 1; product.classList.add(layout + '-active'); this.productsContainer.append(product); let compare = product.querySelector('.SPCMP_Add_span'); if(compare != null) { compare.innerText = 'COMPARE'; } let add_to_cart = product.querySelector('.grid-product__add-to-cart'); if(add_to_cart != null) { add_to_cart.addEventListener('click', function(e){ e.preventDefault(); let a_element = e.target.closest('a'); if(!a_element.classList.contains('added')) { a_element.classList.add('added'); let variant_id = a_element.dataset.variant; let formData = { 'items': [{ 'id': variant_id, 'quantity': 1 }] }; theme.cart.addItemFromForm(formData); } }); } } if(this.progress == number_product) { this.productsContainer.setAttribute('style', ''); if(this.viewmore == '' || !this.viewmore) { this.scrollToTop(); } } } render(resetCurrentPage = false){ if(resetCurrentPage) { this.currentPage = 1; } let productPerPage = this.limit; let end_index = this.currentPage * productPerPage; let start_index = end_index - productPerPage; if(this.tagsFilter.length < 1) { while (this.productsContainer.firstChild) this.productsContainer.removeChild(this.productsContainer.firstChild); let data = this.data; let stop_index = 0; if(data.length > (this.currentPage*productPerPage)) { stop_index = end_index }else{ stop_index = data.length; } if(this.currentPage > 1) { this.productsContainer.style.height = this.containerHeight + 'px'; } this.progress = 0; this.loadProductsGrid(start_index, stop_index, data); let pagination = this.productsContainer.parentElement.getElementsByClassName('pagination')[0]; if(pagination != undefined) { this.productsContainer.parentElement.removeChild(pagination); this.createPagination(data); } }else { let data = []; for (let i = 0; i < this.data.length; i++) { let productTags = this.data[i]['tags']; let is_passed = false; for(let j = 0; j < this.tagsFilter.length; j++) { if(productTags.includes(this.tagsFilter[j])) { is_passed = true; } } if(is_passed) { data.push(this.data[i]); } } while (this.productsContainer.firstChild) this.productsContainer.removeChild(this.productsContainer.firstChild); if(data.length > 0) { let stop_index = 0; if(data.length > (this.currentPage*productPerPage)) { stop_index = end_index }else{ stop_index = data.length; } if(this.currentPage > 1) { this.productsContainer.style.height = this.containerHeight + 'px'; } this.progress = 0; this.loadProductsGrid(start_index, stop_index, data); let pagination = this.productsContainer.parentElement.getElementsByClassName('pagination')[0]; this.productsContainer.parentElement.removeChild(pagination); this.createPagination(data); }else{ let notfound = '

Sorry, there are no products in this tags.

'; this.productsContainer.innerHTML = notfound; } } } reInitProductCompare(){ if(typeof window.reinitializeCompare == 'function'){ window.reinitializeCompare(); console.log("Product Compare reinited"); } } createPagination(data = []) { if(data.length > 0) { this.totalPage = data.length / this.limit; }else{ this.totalPage = this.data.length / this.limit; } if(!Number.isInteger(this.totalPage )) { this.totalPage += 1; } let pagination = document.createElement('div'); pagination.classList.add('pagination'); let html = ''; if(this.currentPage > 1) { html += ''; html += ''; html += ''; html += ''; html += ''; } for(let i = 1; i <= this.totalPage; i++) { if(this.currentPage == i) { html += ''+ i +''; }else{ html += ''+ i +''; } } if(this.currentPage < parseInt(this.totalPage)) { html += ''; html += ''; html += ''; html += ''; html += ''; } pagination.innerHTML = html; this.productsContainer.parentElement.appendChild(pagination); let pagination_item = pagination.querySelectorAll('.page a'); Array.from(pagination_item).forEach(function(element){ element.addEventListener("click", this.actionPagination.bind(this)); }, this); } actionPagination(e) { e.preventDefault(); this.currentPage = e.target.closest('a').dataset.page; // if(e.path[0].nodeName == 'A') { // this.currentPage = e.target.dataset.page; // }else{ // } let current_height = this.productsContainer.offsetHeight; this.containerHeight = current_height; this.render(); } createViewMore() { let btnViewMore = document.createElement('div'); btnViewMore.classList.add('btn-viewmore'); let viewMoreHtml = 'View more'; btnViewMore.dataset.times = 1; btnViewMore.innerHTML = viewMoreHtml; let viewMoreLink = btnViewMore.getElementsByTagName('a')[0]; viewMoreLink.addEventListener('click', this.actionViewMore.bind(this)); this.productsContainer.parentElement.appendChild(btnViewMore); } actionViewMore(e) { e.preventDefault(); this.currentTimes = e.target.closest('.btn-viewmore').dataset.times; let productPerPage = this.limit; let end_index = (parseFloat(this.currentTimes) + 1) * productPerPage; let start_index = end_index - productPerPage; let data = this.data; let number_product = end_index - start_index; let stop_index = 0; if(data.length > (this.currentTimes*productPerPage)) { stop_index = end_index }else{ stop_index = data.length; } for(let i = start_index; i < stop_index; i++) { if(data[i] != undefined) { let url = window.location.origin + '/products/' + data[i].handle + "?view=grid-item" + this.layout; fetch(url) .then(res => res.text()) .then(res => this.addProduct(res, i, number_product)); } if(i >= data.length) { let btnViewMore = this.getElementsByClassName('btn-viewmore')[0]; btnViewMore.style.display = 'none'; } } e.target.closest('.btn-viewmore').dataset.times = parseFloat(this.currentTimes) + 1; } getTagsFilter(e) { let tag = e.target.dataset.tag; Array.from(this.filterItems).forEach(function(element){ let tag_e = element.dataset.tag; let parent_e = element.parentElement; if(parent_e.classList.contains('tag--active') && tag_e == tag) { parent_e.classList.remove('tag--active'); this.removeRedTag(tag); let index = this.tagsFilter.indexOf(tag); if (index !== -1) { this.tagsFilter.splice(index, 1); } }else if (!parent_e.classList.contains('tag--active') && tag_e == tag) { parent_e.classList.add('tag--active'); let is_added = false; let tagListActiveItems = document.querySelectorAll('.tag--remove'); if(tagListActiveItems.length > 0) { Array.from(tagListActiveItems).forEach(function(item){ if(item.dataset.tag == tag) { is_added = true; } }, this); } if(!is_added) { this.addRedTag(tag); } if(!this.tagsFilter.includes(tag)) { this.tagsFilter.push(tag); } } this.btnOpenFilterText.innerText = 'Filter (' + this.tagsFilter.length + ')'; }, this); if (this.tagsFilter.length > 0 && !this.btnOpenFilterMobile.classList.contains('btn--tertiary-active')) { this.btnOpenFilterMobile.classList.add('btn--tertiary-active'); } else if (this.tagsFilter.length < 1){ this.btnOpenFilterMobile.classList.remove('btn--tertiary-active'); this.btnOpenFilterText.innerText = 'Filter'; } this.render(true); if (theme.FilterDrawer) { theme.FilterDrawer.close(); } } actionSubmitFilter(e) { e.preventDefault(); this.collectionGrid.classList.add('unload'); this.filterHandle(); let html = document.getElementsByTagName('html')[0]; let body = document.getElementsByTagName('body')[0]; let drawer = document.getElementById('FilterDrawer'); if(drawer.classList.contains('drawer--is-open')) { drawer.classList.remove('drawer--is-open'); } if(html.classList.contains('js-drawer-open') && body.classList.contains('js-drawer-open')) { html.classList.remove('js-drawer-open'); body.classList.remove('js-drawer-open'); let openFilterMobile = document.getElementsByClassName('js-drawer-open-collection-filters')[0]; openFilterMobile.click(); } } filterHandle() { this.render(true); this.collectionGrid.classList.remove('unload'); } addRedTag(tag) { let tag_arr = tag.split('_'); let html = ''+ tag_arr[1] +''; html += ''; let li_element = document.createElement('li'); li_element.classList.add('tag','tag--remove'); li_element.dataset.tag = tag; li_element.innerHTML = html; Array.from(this.tagListActive).forEach(function(ul){ let duplicatedE = li_element.cloneNode(true); ul.appendChild(duplicatedE); this.actionRemoveRedTag(duplicatedE); }.bind(this)); } removeRedTag(tag) { Array.from(this.tagListActive).forEach(function(ul){ let tags_remove = ul.getElementsByTagName('li'); for(let i = 0; i < tags_remove.length; i++) { if(tags_remove[i].dataset.tag == tag) { ul.removeChild(tags_remove[i]); } } }.bind(this)); } actionRemoveRedTag(element) { let redTag = element.querySelector('span'); redTag.addEventListener("click", function(e){ let tag_remove = redTag.parentElement.dataset.tag; let index = this.tagsFilter.indexOf(tag_remove); if (index !== -1) { this.tagsFilter.splice(index, 1); } this.removeRedTag(tag_remove); Array.from(this.filterItems).forEach(function(item){ let tag = item.dataset.tag; if(tag == tag_remove && item.parentElement.classList.contains('tag--active')) { item.parentElement.classList.remove('tag--active'); } }); if (this.tagsFilter.length < 1){ this.btnOpenFilterMobile.classList.remove('btn--tertiary-active'); this.btnOpenFilterText.innerText = 'Filter'; } else { this.btnOpenFilterText.innerText = 'Filter (' + this.tagsFilter.length + ')'; } this.render(); }.bind(this)); } switchSubmitFilterBtn() { if (this.tagsFilter.length > 0) { Array.from(this.submitFilter).forEach(function(btn){ btn.classList.remove('hide'); btn.text = 'submit filter (' + this.tagsFilter.length + ')'; }, this); }else{ Array.from(this.submitFilter).forEach(function(btn){ btn.classList.add('hide'); }, this); } } scrollToTop() { let scrollHeight = this.productsContainer.offsetTop; // if(window.innerWidth <= 768) { // scrollDiv = scrollDiv - 100; // } window.scrollTo({ top: scrollHeight - 200, behavior: 'smooth'}); } } customElements.define('collection-products', CollectionProduct);