Jake Vanderwerf
2026-05-31 d7e7d248cbe41cd7a9ef9c2fb022b6c4831f99a3
build/feed/view.js
@@ -1 +1,689 @@
(()=>{class e{constructor(){this.container=document.querySelector("section.feed-block"),this.container&&(this.a11y=window.jvbA11y,this.cache=new window.jvbCache("feed"),this.error=window.jvbError,this.config={source:"",context:"",highlight:null,gallery:!1,view:this.cache.get("feedView")||"grid",...this.container.dataset},this.initElements(),this.initFilters(),this.loadWhenAble())}loadWhenAble(){"requestIdleCallback"in window?requestIdleCallback((()=>{this.initTaxonomies(),this.initStore(),this.initListeners(),this.initGallery()}),{timeout:2e3}):setTimeout((()=>{this.initTaxonomies(),this.initStore(),this.initListeners(),this.initGallery()}),100)}initElements(){var e;this.currentTaxonomies=new Set,this.taxonomyFilters={},this.elements={filterTrigger:"[data-filter]",filters:{content:'[data-filter="content"]',orderby:'[data-filter="orderby"]',order:'[data-filter="order"]',match:'[data-filter="match"]',favourites:'[data-filter="favourites"]',taxonomy:'[data-filter^="taxonomy"]'},selectedTax:".selected-items",clearFilter:"button.clear-filters",loadMore:"button.load-more",filterContainer:".filters",grid:".item-grid"},this.ui=window.uiFromSelectors(this.elements),this.ui.content=null!==(e=this.ui.filterContainer.querySelectorAll('[name="content"]'))&&void 0!==e&&e,this.ui.taxonomies=this.ui.filterContainer.querySelectorAll("[data-taxonomy]"),this.ui.content&&this.ui.content.length>0?this.contentTypes=Array.from(this.ui.content).map((e=>e.value)):this.contentTypes=[this.container.dataset.content],this.ui.taxonomies.length>0?this.taxonomies=Array.from(this.ui.taxonomies).map((e=>e.dataset.taxonomy)):this.taxonomies=[]}async initTaxonomies(){this.selector=window.jvbSelector;const e=document.querySelectorAll('[data-filter="taxonomy"]');this.selector.isInitializing=!0,e.forEach((e=>{const t=e.dataset.taxonomy;this.currentTaxonomies.add(t),this.selector.registerFilterButton(e,{button:e,buttonSelector:'[data-filter="taxonomy"]',selected:this.ui.selectedTax}),this.addTaxonomyPreloadListeners(e,t)})),this.selector.isInitializing=!1,this.selector.subscribe(((e,t)=>{"selected-terms"===e&&this.handleTaxonomyChange(t)}))}addTaxonomyPreloadListeners(e,t){const i=()=>{this.selector.preloadTaxonomy(t)};e.addEventListener("mouseenter",i,{once:!0}),e.addEventListener("pointerdown",i,{once:!0}),e.addEventListener("focus",i,{once:!0})}handleTaxonomyChange(e){const{terms:t,taxonomy:i}=e;t.size>0?this.taxonomyFilters[i]=Array.from(t.keys()):delete this.taxonomyFilters[i];let s={page:1};Object.keys(this.taxonomyFilters).length>0&&(s.taxonomy=this.taxonomyFilters),this.updateFilter(s)}clearAllTaxonomies(){this.taxonomyFilters={},window.removeChildren(this.ui.selectedTax),this.updateFilter({taxonomy:null,page:1})}initFilters(){this.filters={content:this.contentTypes[0],orderby:"date",order:"desc",page:1},this.config.context&&(this.filters.context=this.config.context),this.config.source&&(this.filters.source=this.config.source),this.processCachedFilters(),this.processURLFilters(),this.syncUIToFilters()}syncUIToFilters(){this.ui.filterContainer&&Object.entries(this.filters).forEach((([e,t])=>{const i=this.ui.filterContainer.querySelector(`[data-filter="${e}"][value="${t}"]`);i&&(i.checked=!0)})),this.updateContentFor(this.filters.content)}nextPage(){this.store.setFilter("page",this.store.filters.page++)}initStore(){const e=window.jvbStore.register("feed",{storeName:"feed",endpoint:"feed",keyPath:"id",indexes:[{name:"content",keyPath:"content"},{name:"taxonomy",keyPath:"taxonomy"},{name:"user",keyPath:"user"},{name:"date",keyPath:"modified"},{name:"title",keyPath:"title"}],filters:this.filters,TTL:216e5,showLoading:!0,required:"content",delayFetch:!0});this.store=e.feed,this.store.subscribe(((e,t)=>{"data-loaded"===e&&(this.renderItems(),this.ui.loadMore.hidden=!0,this.store.lastResponse&&this.store.lastResponse.has_more&&(this.ui.loadMore.hidden=!this.store.lastResponse.has_more))}))}initGallery(){this.gallery=!!this.config.gallery&&window.jvbGallery,this.gallery&&this.gallery.subscribe(((e,t)=>{"load-more"===e&&this.store.lastResponse&&this.store.lastResponse.has_more&&this.nextPage()}))}processCachedFilters(){Object.keys(this.filters).forEach((e=>{let t=this.cache.get(`${this.config.source}_${this.config.context}_${e}`);t&&t!==this.filters[e]&&(this.filters[e]=t)}))}processURLFilters(){if(this.filters.page>1)return!1;const e=new URLSearchParams(window.location.search);if(!e.toString())return!1;["content","order","orderby","favourites","match"].forEach((t=>{let i=e.get(`f_${t}`);if(i){this.filters[t]=i;let e=this.ui.filters[t];e&&(e.checked=!0)}}));let t=!1;if(e.forEach(((e,i)=>{if(i.startsWith("f_tax_")){t=!0;const s=i.replace("f_tax_","");this.taxonomyFilters[s]||(this.taxonomyFilters[s]=[]),this.taxonomyFilters[s]=e.split(",").map(Number)}})),this.ui.filterContainer&&t)for(let[e,t]in Object.entries(this.taxonomyFilters)){let i=this.ui.filterContainer.querySelector(`[data-taxonomy="${e}"]`);i&&(i.dataset.fieldId?(this.selector.get(i.dataset.fieldId).selectedTerms=new Set(t),this.selector.initFieldDisplay(i.dataset.fieldId)):this.selector.registerField(i,{button:i,buttonSelector:'[data-filter="taxonomy"]',selected:this.ui.selectedTax,selectedItems:t}))}return!0}updateURL(){const e=new URLSearchParams;["content","order","orderby","match"].forEach((t=>{this.filters[t]&&e.set(`f_${t}`,this.filters[t])})),Object.entries(this.taxonomyFilters).forEach((([t,i])=>{i.length>0&&e.set(`f_tax_${t}`,i.join(","))}));const t=`${window.location.pathname}${e.toString()?"?"+e.toString():""}`;window.history.pushState({filters:this.filters},"",t)}renderItems(){let e=this.store.getFiltered();if(1===this.store.filters.page&&window.removeChildren(this.ui.grid),0===e.length)return void this.a11y.announceItems(0,this.store.filters.page>0);const t=document.createDocumentFragment(),i=s=>{const r=Math.min(s+10,e.length);for(let i=s;i<r;i++){const s=e[i],r=this.createItemElement(s);t.appendChild(r)}r<e.length?requestAnimationFrame((()=>i(r))):(this.removePlaceholders(),this.ui.grid.append(t),this.config.gallery&&this.gallery.updateGalleryItems(this.gallery.getGalleryItems()),this.a11y.makeNavigable(this.ui.grid.querySelectorAll(".item:not([data-keyboard-nav])")),this.a11y.announceItems(e.length,this.store.filters.page>1,this.store.hasMore))};e.length>0?i(0):this.a11y.announceItems(0,this.store.filters.page>1,!1),this.ui.filters.match&&(this.ui.filters.match.hidden=0===Object.keys(this.taxonomyFilters).length),this.ui.clearFilter&&(this.ui.clearFilter.hidden=0===Object.keys(this.taxonomyFilters).length)}createItemElement(e){let t=window.getTemplate(`feedItem${window.uppercaseFirst(e.content)}`);if(Object.hasOwn(t.dataset,"timeline"))return this.createTimelineElement(e,t);for(let[i,s]of Object.entries(e.fields)){let r=t.querySelector(`[data-field="${i}"]`);r&&(Object.keys(e.images).map((e=>parseInt(e))).includes(s)?[r.src,r.srcset,r.alt]=[e.images[s].tiny,`${e.images[s].tiny} 50w, ${e.images[s].small} 300w, ${e.images[s].medium} 1024w`,e.images[s]["image-alt-text"]]:"TIME"===r.tagName?(r.setAttribute("datetime",s),r.textContent=window.formatTimeAgo(s)):r.textContent=s,""===s&&r.remove())}let i=t.querySelector("a");var s;return i&&""!==e.url&&([i.href,i.title]=[e.url,`View ${null!==(s=e.fields.post_title)&&void 0!==s?s:"Item"}`]),t}splitIDs(e){return String(e).split(",").map((e=>parseInt(e.trim()))).filter((e=>e))}isImageField(e,t){return Object.hasOwn(e,"images")&&0!==Object.keys(e.images).length?(this.splitIDs(t).forEach((t=>{if(console.log("Checking id: ",t),Object.keys(e.images).includes(parseInt(t)))return console.log("Item.images does not have id"),!0})),!1):(console.log("Item has no images, or the images object is empty"),!1)}formatImageFields(e,t,i){if(console.log("Formatting image Field: ",e),console.log("value: ",t),console.log("item: ",i),0!==t.length)if(t.length>1){let s=e.querySelector("img");if(!s)return;t.forEach((t=>{let r=s.cloneNode(!0);this.formatImageField(r,t,i),e.append(r)})),s.remove()}else{if(console.log(e.tagName),"IMG"!==e.tagName&&!(e=e.querySelector("img")))return;this.formatImageField(e,t[0],i)}}formatImageField(e,t,i){[e.src,e.srset,e.alt]=[i.images[t].tiny,`${i.images[t].tiny} 50w, ${i.images[t].small} 300w, ${i.images[t].medium} 1024w`,i.images[t]["image-alt-text"]]}isTaxonomyField(e,t){return!(!Object.hasOwn(e,"taxonomies")||0===Object.keys(e.taxonomies).length||(Object.keys(e.taxonomies).forEach((e=>{if(e===t)return!0})),1))}formatTaxonomyField(e,t,i,s){if("UL"!==e.tagName||!e.querySelector("li"))return;let r=this.splitIDs(s),o=e.querySelector("li");for(let s of r){var n;let r=null!==(n=t.taxonomies[i][s])&&void 0!==n&&n;if(!r)continue;let a=o.cloneNode(!0),l=a.querySelector("a");l&&([l.href,l.title,l.textContent]=[r.url,`See more ${r.title}`,r.title],e.append(a))}o.remove()}isTimeField(e){return"TIME"===e.tagName||null!==e.querySelector("time")}formatTimeField(e,t){("TIME"===e.tagName||(e=e.querySelector("time")))&&(e.setAttribute("datetime",t),e.textContent=window.formatTimeAgo(t))}formatField(e,t){e.textContent=t}createTimelineElement(e,t){console.log(e),console.log(t);for(let[i,s]of Object.entries(e.fields))if(!["timeline","number"].includes(i)){let r=t.querySelector(`[data-field="${i}"]`);if(r||console.log(`Element Not found for ${i}`),!r||""===s)continue;this.isImageField(e,s)?this.formatImageFields(r,s,e):this.isTaxonomyField(e,i)?this.formatTaxonomyField(r,e,i,s):this.isTimeField(r)?this.formatTimeField(r,s):this.formatField(r,s)}let[i,s,r,o]=[t.querySelector("span.after-text"),t.querySelector('[data-field="number"] b'),t.querySelector('[data-field="started"] time'),t.querySelector('[data-field="updated"] time')];return i&&(i.textContent=`After ${e.fields.number} Tx`),s&&(s.textContent=e.fields.number),r&&this.formatTimeField(r,e.fields.timeline[0].post_date),o&&this.formatTimeField(o,e.fields.timeline[e.fields.timeline.length-1].post_date),t}removePlaceholders(){const e=this.ui.grid.querySelectorAll(".placeholder");e.length>0&&e.forEach((e=>e.remove()))}addPlaceholders(){let e=this.contentTypes.length;const t=document.createDocumentFragment();for(let i=0;i<12;i++){let i,s=window.getTemplate("placeholderTemplate"),r=Math.floor(Math.random()*e);i=this.ui.content&&this.ui.content.length>0?this.ui.content.filter((e=>e.value===this.contentTypes[r])).querySelector(".icon").cloneNode(!0):window.getIcon(this.container.dataset.icon),s.append(i),t.append(s)}this.ui.grid.append(t)}updateFilter(e){let t=["taxonomy","favourites","match",...Object.keys(this.filters)];e=Object.keys(e).filter((e=>t.includes(e))).reduce(((t,i)=>(t[i]=e[i],t)),{}),window.getDifferences.map(this.filters,e)&&(this.filters={...this.filters,...e},this.updateURL(),this.store.setFilters(e))}updateContentFor(e){this.ui.filterContainer.querySelectorAll('[data-filter="taxonomy"]').forEach((t=>{const i=t.dataset.for?.split(",")||[];t.hidden=i.length>0&&!i.includes(e)})),this.ui.filterContainer.querySelectorAll("[data-for]").forEach((t=>{const i=t.dataset.for?.split(",")||[];i.length>0&&(t.hidden=!i.includes(e),t.hidden&&t.checked&&(t.checked=!1))}));const t=this.ui.filterContainer.querySelector('[name="orderby"]:checked');this.updateOrderDirectionVisibility(t?.value)}updateOrderDirectionVisibility(e){const t=this.ui.filterContainer.querySelector(".order-direction");if(t){const i=t.dataset.forOrder?.split(",")||[];t.hidden=i.length>0&&!i.includes(e)}}initListeners(){this.popStateHandler=this.handlePopState.bind(this),this.clickHandler=this.handleClick.bind(this),this.changeHandler=this.handleChange.bind(this),this.imageObserver=null,this.resizeObserver=null,"IntersectionObserver"in window&&(this.imageObserver=new IntersectionObserver((e=>{e.forEach((e=>{this.loadImage(e.target),this.imageObserver.unobserve(e.target)}))}),{rootMargin:"100px",threshold:.1})),"ResizeObserver"in window?this.resizeObserver=new ResizeObserver((()=>{window.debouncer.schedule("feed-update-images",(()=>this.updateImageSizes()),250)})):window.addEventListener("resize",(()=>{window.debouncer.schedule("feed-update-images",(()=>this.updateImageSizes()),250)})),window.addEventListener("popstate",this.popStateHandler),document.addEventListener("click",this.clickHandler),document.addEventListener("change",this.changeHandler)}handlePopState(e){e.state?.filters&&this.processURLFilters()&&(this.store.setFilters(this.filters),this.a11y.announce("Feed filters updated from browser history"))}handleClick(e){window.targetCheck(e,this.elements.loadMore)?this.nextPage():window.targetCheck(e,this.elements.clearFilter)?this.clearAllTaxonomies():window.targetCheck(e,".remove-item")&&this.handleRemoveSelectedTerm(e)}handleRemoveSelectedTerm(e){const t=e.target.closest(".selected-item");if(!t)return;const i=parseInt(t.dataset.id),s=t.dataset.taxonomy;this.taxonomyFilters[s]&&(this.taxonomyFilters[s]=this.taxonomyFilters[s].filter((e=>e!==i)),0===this.taxonomyFilters[s].length&&delete this.taxonomyFilters[s]),t.remove(),this.updateFilter({taxonomy:Object.keys(this.taxonomyFilters).length>0?this.taxonomyFilters:null,page:1})}handleChange(e){let t=e.target;Object.hasOwn(t.dataset,"filter")&&("content"===t.dataset.filter?(this.updateContentFor(t.value),this.updateFilter({content:t.value,page:1})):"orderby"===t.dataset.filter?(this.updateOrderDirectionVisibility(t.value),this.updateFilter({orderby:t.value,page:1})):"order"===t.dataset.filter?this.updateFilter({order:t.value,page:1}):"match"===t.dataset.filter?this.updateFilter({match:t.checked?"all":"any",page:1}):"favourites"===t.dataset.filter&&this.updateFilter({favourites:t.checked,page:1}))}}document.addEventListener("DOMContentLoaded",(async function(){window.auth.subscribe((t=>{"auth-loaded"===t&&(window.feedBlock=new e)}))}))})();
/******/ (() => { // webpackBootstrap
/*!**************************!*\
  !*** ./src/feed/view.js ***!
  \**************************/
class FeedBlock {
  constructor() {
    this.container = document.querySelector('section.feed-block');
    if (!this.container) return;
    this.a11y = window.jvbA11y;
    this.error = window.jvbError;
    this.cache = new window.jvbCache('feed');
    this.templates = window.jvbTemplates;
    this.config = {
      contextId: '',
      context: '',
      highlight: null,
      gallery: false,
      view: this.cache.get('feedView') || 'grid',
      ...this.container.dataset
    };
    console.log(this.config);
    this.init();
  }
  init() {
    this.initElements();
    this.defineTemplates();
    this.initListeners();
    this.initFilters();
    if ('requestIdleCallback' in window) {
      requestIdleCallback(() => {
        this.initStore();
        this.initTaxonomies();
        this.processCachedFilters();
        this.processURLFilters();
        this.updateFilterUI();
        this.initGallery();
      }, {
        timeout: 2000
      });
    } else {
      setTimeout(() => {
        this.initStore();
        this.initTaxonomies();
        this.processCachedFilters();
        this.processURLFilters();
        this.updateFilterUI();
        this.initGallery();
      }, 100);
    }
  }
  initElements() {
    this.selectors = {
      filterTrigger: '[data-filter]',
      filters: {
        actions: '.filter-actions .toggle-text',
        container: '.all-filters',
        showing: '.all-filters summary .current',
        content: '[data-filter="content"]',
        ordering: '.ordering',
        orderby: '[data-filter="orderby"]',
        order: '[data-filter="order"]',
        orderWrap: '.order-direction',
        match: '[data-filter="match"]',
        favourites: '[data-filter="favourites"]',
        taxonomy: '[data-filter^="taxonomy"]'
      },
      grid: '.item-grid',
      selected: '.selected-items',
      buttons: {
        loadMore: 'button.load-more',
        remove: '.remove-term',
        clearFilters: 'button.clear-filters',
        refresh: 'button[data-action="refresh"]'
      }
    };
    this.ui = window.uiFromSelectors(this.selectors, this.container);
    this.ui.buttons.refresh = document.querySelector(this.selectors.buttons.refresh);
    //Add content and taxonomies
    let getAll = ['content', 'orderby', 'order', 'taxonomy'];
    getAll.forEach(item => {
      let items = this.ui.filters.container.querySelectorAll(this.selectors.filters[item]);
      this.ui[item] = Array.from(items);
    });
    this.contentTypes = this.ui.content.length > 0 ? this.ui.content.map(c => c.value) : [this.container.dataset.content];
    this.taxonomies = this.ui.taxonomies?.length > 0 ? Array.from(this.ui.taxonomies).map(t => t.dataset.taxonomy) : [];
  }
  /**
   *
   * @param {string} item
   */
  getChecked(item) {
    if (!['content', 'orderby', 'order'].includes(item)) {
      console.log('Invalid item to check: ', item);
    }
    let items = this.ui[item];
    if (!items) {
      return;
    }
    let checked = items.filter(i => i.checked);
    if (item === 'content' && checked.length > 0) {
      this.updateContentFor(checked[0].value);
    }
    return checked.length === 0 ? items[0].value : checked[0].value;
  }
  initListeners() {
    this.popStateHandler = this.handlePopState.bind(this);
    this.clickHandler = this.handleClick.bind(this);
    this.changeHandler = this.handleChange.bind(this);
    window.addEventListener('popstate', this.popStateHandler);
    document.addEventListener('click', this.clickHandler);
    document.addEventListener('change', this.changeHandler);
  }
  initFilters() {
    this.allowedFilters = ['content', 'order', 'orderby', 'favourites', 'match'];
    let defaults = {
      content: this.getChecked('content'),
      orderby: this.getChecked('orderby'),
      order: this.getChecked('order'),
      page: 1
    };
    if (this.config.context) defaults.context = this.config.context;
    if (this.config.contextId) defaults.contextId = this.config.contextId;
    this.filters = defaults;
    console.log(this.filters);
    this.defaults = {
      ...defaults
    };
  }
  updateFilterUI() {
    if (this.ui.filters.container) {
      //Get cached inputs
      let groups = [this.ui.content, this.ui.orderby, this.ui.order];
      groups.forEach(group => {
        if (group) {
          for (let input of group) {
            let [filter, value] = [input.dataset.filter, input.value];
            if (!Object.hasOwn(this.store.filters, filter)) break;
            let doit = this.store.filters[filter] === value;
            if (doit) {
              input.checked = doit;
              break;
            }
          }
        }
      });
      if (Object.hasOwn(this.store.filters, 'taxonomy')) {
        for (let [taxonomy, terms] of Object.entries(this.store.filters.taxonomy)) {
          terms.forEach(termId => {
            termId = parseInt(termId);
            const term = this.selector.store.get(termId);
            if (term) {
              this.createTermElement(termId);
            }
          });
        }
      }
    }
  }
  handlePopState(e) {
    if (e.state?.filters) {
      if (this.processURLFilters()) {
        this.store.setFilters(this.filters);
        this.a11y.announce('Feed filters updated from browser history');
      }
    }
  }
  handleClick(e) {
    if (window.targetCheck(e, this.selectors.buttons.loadMore)) {
      this.nextPage();
    } else if (window.targetCheck(e, this.selectors.buttons.clearFilters)) {
      this.clearFilters();
    }
    let remove = window.targetCheck(e, this.selectors.buttons.remove);
    if (remove) {
      this.removeSelectedTerm(remove);
    }
    let refresh = window.targetCheck(e, this.selectors.buttons.refresh);
    if (refresh) {
      this.store.clearCache();
      this.store.fetch();
    }
    let orderbyButton = window.targetCheck(e, '[data-filter="orderby"]');
    if (orderbyButton && orderbyButton.value === 'random' && orderbyButton.checked) {
      // Already selected random, just re-render to trigger new shuffle
      this.renderItems();
    }
  }
  nextPage() {
    const nextPage = (this.store.filters.page || 1) + 1;
    const maxPage = this.store.lastResponse?.pages || nextPage;
    this.store.setFilters({
      page: Math.min(nextPage, maxPage)
    });
  }
  handleChange(e) {
    const target = e.target;
    if (Object.hasOwn(target.dataset, 'filter')) {
      if (this.allowedFilters.includes(target.dataset.filter)) {
        let filters = {};
        filters[target.dataset.filter] = target.value;
        this.resetFilters(filters);
      }
      switch (target.dataset.filter) {
        case 'content':
          this.updateContentFor(target.value);
          break;
        case 'orderby':
          this.updateOrderOptions(target.value);
          break;
      }
    }
  }
  clearFilters() {
    this.taxFilters = {};
    window.removeChildren(this.ui.selected);
    this.taxonomies.forEach(tax => {
      let fieldId = this.getFieldId(tax);
      this.selector.selectedTerms.get(fieldId)?.clear();
    });
    this.store.setFilters({
      ...this.defaults,
      taxonomy: null
    });
    this.updateURL();
    this.saveToCacheFilters();
  }
  resetFilters(filters) {
    filters = {
      ...this.store.filters,
      page: 1,
      ...filters
    };
    this.store.setFilters(filters);
    this.updateURL();
    this.saveToCacheFilters();
  }
  getFieldId(taxonomy) {
    return this.selector.getFieldId(this.ui.taxonomies.filter(tax => tax.dataset.taxonomy === taxonomy)[0] ?? null);
  }
  removeSelectedTerm(button) {
    const termId = parseInt(button.dataset.id);
    const taxonomy = button.dataset.taxonomy;
    if (Object.hasOwn(this.taxFilters, taxonomy)) {
      this.taxFilters[taxonomy] = this.taxFilters[taxonomy].filter(id => id !== termId);
      if (this.taxFilters[taxonomy].length === 0) {
        delete this.taxFilters[taxonomy];
      }
    }
    button.remove();
    // Find the fieldId for this taxonomy
    const field = this.getFieldId(taxonomy);
    if (field) {
      this.selector.activeField = field;
      // Notify selector to remove from its selectedTerms
      this.selector.removeSelected(termId, field);
    }
    this.resetFilters({
      taxonomy: Object.keys(this.taxFilters).length > 0 ? this.taxFilters : null
    });
  }
  updateContentFor(content) {
    let checkIt = [this.ui.taxonomies, this.ui.orderby];
    this.ui.filters.showing.textContent = this.ui.content.filter(c => c.value === content)[0].dataset.label;
    checkIt.forEach(check => {
      if (!check) return;
      check.forEach(button => {
        const forTypes = button.dataset.for?.split(',') ?? [];
        button.hidden = forTypes.length > 0 && !forTypes.includes(content);
        if (button.hidden && button.checked) {
          button.checked = false;
        }
      });
    });
  }
  updateOrderOptions(order) {
    if (this.ui.filters.orderWrap) {
      let options = this.ui.filters.orderWrap.dataset.forOrder.split(',') ?? [];
      this.ui.filters.orderWrap.hidden = !options.includes(order);
    }
  }
  updateFilterControls() {
    const keys = Object.keys(this.taxFilters);
    if (this.ui.buttons.clearFilters) {
      this.ui.buttons.clearFilters.hidden = keys.length === 0;
    }
    if (this.ui.filters.actions) {
      this.ui.filters.actions.hidden = keys.length <= 1;
    }
  }
  async initTaxonomies() {
    this.taxFilters = {};
    this.selector = window.jvbSelector;
    // this.selector.scanExistingFields(this.ui.filters.container);
    // this.taxonomies.map(tax => this.selector.batchFetch.add(tax));
    // this.selector.batchFetchTaxonomies();
    this.selector.subscribe((event, data) => {
      switch (event) {
        case 'selected-terms':
          this.handleTaxonomyChange(data);
          break;
      }
    });
  }
  handleTaxonomyChange(data) {
    const {
      terms,
      taxonomy
    } = data;
    if (terms.size === 0) return;
    this.taxFilters[taxonomy] = Array.from(terms);
    this.resetFilters({
      taxonomy: this.taxFilters
    });
    terms.forEach(t => {
      this.createTermElement(t);
    });
    this.updateFilterControls();
  }
  getTaxonomyIcon(taxonomy) {
    let iconButton = this.ui.taxonomies.find(t => t.dataset.taxonomy === taxonomy);
    return iconButton?.dataset.icon.trim() || 'tag';
  }
  createTermElement(termId) {
    const term = this.selector.store.get(termId);
    if (!term) return;
    if (this.ui.selected.querySelector(`[data-id="${termId}"]`)) return;
    term.icon = this.getTaxonomyIcon(term.taxonomy);
    this.ui.selected.append(this.templates.create('feedTerm', term));
  }
  processCachedFilters() {
    Object.keys(this.filters).forEach(filter => {
      let cached = this.cache.get(`${this.config.contextId}_${this.config.context}_${filter}`);
      if (cached && cached !== this.filters[filter]) {
        this.filters[filter] = cached;
      }
    });
  }
  processURLFilters() {
    if (!this.isFirstPage()) return false;
    const params = new URLSearchParams(window.location.search);
    if (!params.toString()) return false;
    let shouldUpdate = false;
    this.allowedFilters.forEach(filter => {
      let value = params.get(`f_${filter}`);
      if (value) {
        shouldUpdate = true;
        this.filters[filter] = value;
      }
    });
    let hasTax = false;
    params.forEach((value, key) => {
      if (key.startsWith('f_tax_')) {
        hasTax = true;
        shouldUpdate = true;
        const taxonomy = key.replace('f_tax_', '');
        this.taxFilters[taxonomy] = value.split(',').map(Number);
      }
    });
    if (shouldUpdate) {
      if (hasTax) {
        this.filters.taxonomy = this.taxFilters;
      }
      this.resetFilters(this.filters);
    }
    return true;
  }
  updateURL() {
    const params = new URLSearchParams();
    this.allowedFilters.forEach(key => {
      if (Object.hasOwn(this.store.filters, key) && this.store.filters[key] !== this.defaults[key]) {
        params.set(`f_${key}`, this.store.filters[key]);
      }
    });
    for (let [tax, terms] of Object.entries(this.taxFilters)) {
      if (terms.length > 0) {
        params.set(`f_tax_${tax}`, terms.join(','));
      }
    }
    const newURL = `${window.location.pathname}${params.toString() ? '?' + params.toString() : ''}`;
    const currentURL = window.location.pathname + window.location.search; // Change this line
    if (newURL !== currentURL) {
      window.history.pushState({
        filters: this.store.filters
      }, '', newURL);
    }
  }
  saveToCacheFilters() {
    Object.keys(this.store.filters).forEach(filter => {
      const cacheKey = `${this.config.contextId}_${this.config.context}_${filter}`;
      if (this.store.filters[filter] !== this.defaults[filter]) {
        this.cache.set(cacheKey, this.store.filters[filter]);
      } else {
        this.cache.remove(cacheKey);
      }
    });
    const taxCacheKey = `${this.config.contextId}_${this.config.context}_taxonomy`;
    if (Object.keys(this.taxFilters).length > 0) {
      this.cache.set(taxCacheKey, this.taxFilters);
    } else {
      this.cache.remove(taxCacheKey);
    }
  }
  initGallery() {
    this.gallery = this.config.gallery ? window.jvbGallery : false;
    if (this.gallery) {
      this.gallery.subscribe((event, data) => {
        if (event === 'load-more' && this.store.lastResponse?.has_more) {
          this.nextPage();
        }
      });
    }
  }
  initStore() {
    let extraOrderby = this.ui.orderby.filter(v => !['date', 'date_modified', 'title', 'random'].includes(v.value));
    let extraIndexes = [];
    extraOrderby.forEach(orderby => {
      extraIndexes.push({
        name: orderby.value,
        keyPath: orderby.value
      });
    });
    const store = window.jvbStore.register('feed', {
      storeName: 'feed',
      endpoint: 'feed',
      keyPath: 'id',
      indexes: [{
        name: 'content',
        keyPath: 'content'
      }, {
        name: 'taxonomy',
        keyPath: 'taxonomy'
      }, {
        name: 'user',
        keyPath: 'user'
      }, {
        name: 'date',
        keyPath: 'date'
      }, {
        name: 'modified',
        keyPath: 'modified'
      }, {
        name: 'title',
        keyPath: 'title'
      }, ...extraIndexes],
      filters: this.filters,
      TTL: 6 * 60 * 60 * 1000,
      //6 hours
      showLoading: true,
      required: 'content'
    });
    this.store = store.feed;
    this.store.subscribe((event, data) => {
      switch (event) {
        case 'data-loaded':
          this.renderItems(data.items);
          this.ui.buttons.loadMore.hidden = true;
          if (this.store.lastResponse && this.store.lastResponse?.has_more) {
            this.ui.buttons.loadMore.hidden = !this.store.lastResponse?.has_more ?? true;
          }
          break;
      }
    });
  }
  isFirstPage() {
    return this.store.filters.page === 1;
  }
  renderItems(items = null) {
    items = items ?? this.store.getFiltered();
    if (this.isFirstPage()) {
      window.removeChildren(this.ui.grid);
    }
    if (items.length === 0) {
      this.showEmptyState();
      this.a11y.announceItems(0, this.isFirstPage());
    } else {
      window.chunkIt(items, item => this.createItemElement(item), fragment => {
        this.removePlaceholders();
        this.ui.grid.append(fragment);
        if (this.config.gallery) this.gallery.buildGalleryItems('.item img');
        this.a11y.makeNavigable(this.ui.grid.querySelectorAll('.item:not([data-keyboard-nav])'));
        this.a11y.announceItems(items.length, !this.isFirstPage(), this.store.lastResponse?.has_more ?? false);
      }, 5).then(() => {});
    }
    this.updateFilterControls();
  }
  showEmptyState() {
    window.removeChildren(this.ui.grid);
    this.ui.grid.append(this.templates.create('emptyState'));
  }
  createItemElement(item) {
    if (typeof item !== 'object') {
      item = this.store.get(item);
      if (!item) return;
    }
    return this.templates.create(`feedItem${window.uppercaseFirst(item.content)}`, item);
  }
  splitIDs(value) {
    return String(value).split(',').map(value => parseInt(value.trim())).filter(value => value);
  }
  isImageField(item, value) {
    if (!Object.hasOwn(item, 'images') || Object.keys(item.images).length === 0) {
      return false;
    }
    let values = this.splitIDs(value);
    return values.some(v => Object.keys(item.images).map(k => parseInt(k)).includes(parseInt(v)));
  }
  formatImageFields(element, value, item) {
    let values = this.splitIDs(value); // Convert string to array first
    if (values.length === 0) return;
    if (values.length > 1) {
      let image = element.querySelector('img');
      if (!image) return;
      values.forEach(imgID => {
        let img = image.cloneNode(true);
        this.formatImageField(img, imgID, item);
        element.append(img);
      });
      image.remove();
    } else {
      if (element.tagName !== 'IMG') {
        element = element.querySelector('img');
        if (!element) return;
      }
      this.formatImageField(element, values[0], item);
    }
  }
  formatImageField(element, value, item) {
    let imgData = item.images[value] ?? false;
    if (!imgData) return;
    [element.src, element.srcset, element.alt] = [imgData.tiny, `${imgData.tiny} 50w, ${imgData.small} 300w, ${imgData.medium} 1024w`, imgData['image-alt-text']];
  }
  isTaxonomyField(item, field) {
    if (!Object.hasOwn(item, 'taxonomies') || Object.keys(item.taxonomies).length === 0) {
      return false;
    }
    return Object.keys(item.taxonomies).includes(field);
  }
  formatTaxonomyField(element, item, field, value) {
    if (element.tagName !== 'UL' || !element.querySelector('li')) return;
    let values = this.splitIDs(value);
    if (values.length === 0) {
      element.remove();
    }
    let listItem = element.querySelector('li');
    for (let termID of values) {
      let term = item.taxonomies[field][termID] ?? false;
      if (!term) continue;
      let termItem = listItem.cloneNode(true);
      let link = termItem.querySelector('a');
      if (!link) continue;
      let title = window.decodeHTMLEntities(term.title);
      [link.href, link.title, link.textContent] = [term.url, `See more ${title}`, title];
      element.append(termItem);
    }
    listItem.remove();
  }
  isTimeField(el) {
    return el.tagName === 'TIME' || el.querySelector('time') !== null;
  }
  formatTimeField(element, value) {
    if (element.tagName !== 'TIME') {
      element = element.querySelector('time');
      if (!element) return;
    }
    element.setAttribute('datetime', value);
    element.textContent = window.formatTimeAgo(value, 'F Y');
  }
  formatField(element, value) {
    element.textContent = window.decodeHTMLEntities(value);
  }
  addTimelineElements(item, template) {
    let [afterEl, number, started, last] = [template.querySelector('span.after-text'), template.querySelector('[data-field="number"] b'), template.querySelector('[data-field="started"] time'), template.querySelector('[data-field="updated"] time')];
    if (afterEl) {
      afterEl.textContent = `After ${item.number - 1} Tx`;
    }
    if (number) {
      number.textContent = item.number - 1;
    }
    if (started) {
      this.formatTimeField(started, item.fields.timeline[0]['post_date']);
    }
    if (last) {
      this.formatTimeField(last, item.fields.timeline[item.fields.timeline.length - 1]['post_date']);
    }
  }
  removePlaceholders() {
    const placeholders = this.ui.grid.querySelectorAll('.placeholder');
    if (placeholders.length > 0) {
      placeholders.forEach(p => p.remove());
    }
  }
  defineTemplates() {
    const T = this.templates;
    const f = this;
    T.define('feedTerm', {
      refs: {
        icon: '.icon',
        span: 'span'
      },
      setup({
        el,
        refs,
        manyRefs,
        data
      }) {
        el.dataset.id = data.id;
        el.dataset.taxonomy = data.taxonomy;
        if (refs.icon) refs.icon.className = `icon icon-${data.icon}`;
        if (refs.span) refs.span.textContent = window.decodeHTMLEntities(data.name);
      }
    });
    T.define('emptyState');
    this.contentTypes.forEach(content => {
      T.define(`feedItem${window.uppercaseFirst(content)}`, {
        refs: {
          link: 'a'
        },
        manyRefs: {
          fields: '[data-field]'
        },
        setup({
          el,
          refs,
          manyRefs,
          data
        }) {
          const isTimeline = Object.hasOwn(el.dataset, 'timeline');
          if (manyRefs.fields) {
            for (let field of manyRefs.fields) {
              if (isTimeline && ['timeline', 'number'].includes(field.dataset.field)) continue;
              const value = Object.hasOwn(data.fields, field.dataset.field) ? data.fields[field.dataset.field] : false;
              if (!value) {
                field.remove();
                continue;
              }
              if (f.isImageField(data, value)) {
                f.formatImageField(field, value, data);
              } else if (f.isTaxonomyField(data, field.dataset.field)) {
                f.formatTaxonomyField(field, data, field.dataset.field, value);
              } else if (f.isTimeField(field)) {
                f.formatTimeField(field, value);
              } else {
                f.formatField(field, value);
              }
            }
            if (refs.link && data.url !== '') {
              refs.link.href = data.url;
              refs.link.title = `View ${data.fields['post_title'] ?? 'Item'}`;
            }
            if (isTimeline) f.addTimelineElements(data, el);
          }
        }
      });
    });
  }
  // addPlaceholders() {
  //  let total = this.contentTypes.length;
  //  const fragment = document.createDocumentFragment();
  //  for (let i = 0; i < 12; i++) {
  //     let template = window.getTemplate('placeholderTemplate');
  //
  //     let rand = Math.floor(Math.random() * total);
  //     let icon;
  //     if (this.ui.content && this.ui.content.length > 0) {
  //        icon = this.ui.content.filter((content) => { return content.value === this.contentTypes[rand]}).querySelector('.icon').cloneNode(true);
  //     } else {
  //        icon = window.getIcon(this.container.dataset.icon);
  //     }
  //     template.append(icon);
  //     fragment.append(template);
  //  }
  //  this.ui.grid.append(fragment);
  // }
}
document.addEventListener('DOMContentLoaded', async function () {
  window.auth.subscribe(event => {
    if (event === 'auth-loaded') {
      window.feedBlock = new FeedBlock();
    }
  });
});
/******/ })()
;
//# sourceMappingURL=view.js.map