PageSourceSearch

https://www.daltile.com/scripts/searchresult/searchresultstemplate.js

js daltile.com collected 2026-09-24 19:04:35 UTC 44,105 bytes, 1,049 lines download raw bytes

1function zoom(e) {
2    var zoomer = e.currentTarget;
3    e.offsetX ? offsetX = e.offsetX : offsetX = e?.touches[0]?.pageX;
4    e.offsetY ? offsetY = e.offsetY : offsetX = e?.touches[0]?.pageX;
5    x = offsetX / zoomer.offsetWidth * 100
6    y = offsetY / zoomer.offsetHeight * 100
7    zoomer.style.backgroundPosition = x + '% ' + y + '%';
8}
9
10function searchResultsTemplateInit() {
11    Coveo.TemplateHelpers
12        .registerTemplateHelper("contentimage", (value, options) => {
13            return `<img class="content-view image" src="${value}">`
14        });
15
16    const searchInterfaceElement = document.querySelector(".CoveoSearchInterface");
17    Coveo.$$(searchInterfaceElement).on('changeAnalyticsCustomData', (e, args) => {
18        if (['documentOpen', 'viewSample', 'viewRoom', 'documentQuickview'].indexOf(args.actionCause) > -1) {
19            console.log(args.resultData)
20            let clickedResult = args.resultData.raw;
21            args.metaObject['clicks.c_type'] = clickedResult['sourcedisplayname'];
22        }
23    });
24    Coveo.init(searchInterfaceElement);
25
26    const FilterStateManager = {
27        currentEvent: "initialFilter",
28        currentEventObj: null,
29        currentParams: {},
30        defaultEvent: "defaultFilter",
31        listenEvents: true,
32        lastQuery: "",
33        lastEventExecuted: true,
34        filters: {},
35        values: {},
36        root: searchInterfaceElement,
37        registerFilter(key, filter) {
38            this.filters[key] = filter;
39        },
40        setLastQuery(query) {
41            this.lastQuery = query;
42        },
43        executeQuery() {
44            const root = searchInterfaceElement;
45            if (root)
46                Coveo.executeQuery(root);
47            return this;
48        },
49        setEventData(eventname, result, params) {
50            this.currentEvent = eventname;
51            this.currentParams = params;
52            this.currentEventObj = this.getEvent();
53            this.currentEventObj.setResult(result);
54            this.lastEventExecuted = false;
55            return this;
56        },
57        triggerEvent(eventname, result, params, execute) {
58            if ((this.currentEventObj && !this.currentEventObj.isOrphan() && !this.listenEvents) || !this.listenEvents) return;
59            this.setEventData(eventname, result, params)
60                .stopListening()
61                .logClickEvent();
62            if (execute) {
63                this.logSearchEvent()
64                    .executeQuery();
65            }
66            return this;
67        },
68        logSearchEvent() {
69            if (!this.currentEventObj || this.currentEventObj.getClickAction() === "" || this.currentEventObj.getClickType() === "") return;
70            const cause = {
71                name: this.currentEventObj.getClickAction(),
72                type: this.currentEventObj.getClickType()
73            };
74            try {
75                Coveo.logSearchEvent(this.root, cause, this.currentParams);
76            } catch (e) {
77                console.log(e);
78            }
79            return this
80        },
81        logClickEvent() {
82            if (!this.currentEventObj || this.currentEventObj.getClickAction() === "" || this.currentEventObj.getClickType() === "") return;
83            const cause = {
84                name: this.currentEventObj.getClickAction(),
85                type: this.currentEventObj.getClickType()
86            };
87            const metadata = {};
88            if (this.currentEventObj.getResult()) {
89                try {
90                    Coveo.logClickEvent(this.root, cause, this.currentParams, this.currentEventObj.getResult());
91                } catch (e) {
92                    console.log(e);
93                }
94            }
95            return this;
96        },
97        isListening() {
98            return this.listenEvents;
99        },
100        stopListening() {
101            this.listenEvents = false;
102            return this;
103        },
104        startListening() {
105            this.listenEvents = true;
106            this.currentEvent = "defaultFilter";
107            this.currentParams = {};
108            //this.currentEventObj = null;
109            return this;
110        },
111        getDefaultEvent() {
112            return this.filters[this.defaultEvent].setParams({});
113        },
114        getEvent() {
115            let event = this.filters[this.currentEvent];
116            if (event) {
117                event.setParams(this.currentParams);
118                return event
119            }
120            return this.getDefaultEvent();
121        },
122        isSeriesName(name) {
123            if (name && this.values && this.values[name.trim().toLowerCase().replace(" ", "-")] != undefined)
124                return true;
125            return false;
126        },
127        isNewQuery(query) {
128            if (!query) query = "";
129            if (this.lastQuery?.trim() === query?.trim())
130                return false;
131            this.lastQuery = query;
132            return true;
133        },
134        getValues() {
135            const config = Coveo.SearchEndpoint.defaultEndpoint;
136            const token = "Bearer " + config.accessToken.token;
137            const _self = this;
138            const response = fetch(`/coveo/rest/search/v2/values`, {
139                method: 'POST',
140                headers: {
141                    'Accept': 'application/json',
142                    'Content-Type': 'application/json',
143                    'Authorization': token
144                },
145                body: JSON.stringify({
146                    "field": "@seriesname",
147                    "maximumNumberOfValues": 1000,
148                    "constantQueryOverride": "@sitetargethostname==" + coveoSearchAssetsModel.ContextTargetHostName
149                })
150            });
151            response.then(function (response) {
152                console.log(response)
153                const json = response.json();
154                json.then(function (result) {
155                    console.log(result.values);
156                    for (i in result.values) {
157                        const serie = result.values[i];
158                        _self.values[serie.value.trim().toLowerCase().replace(" ", "-")] = serie["numberOfResults"]
159                    }
160                });
161            });
162        }
163    };
164    class FilterState {
165        searchAction = ""
166        searchType = ""
167        clickAction = ""
168        clickType = ""
169        result = null
170        seriesmatch = "false"
171        orphanEvent = true
172        constructor(name) {
173            this.name = name;
174            FilterStateManager.registerFilter(this.name, this);
175        }
176        capitalizeFirstLetter(keyword) {
177            const arr = keyword.split(" ");
178            //loop through each element of the array and capitalize the first letter.
179            for (var i = 0; i < arr.length; i++) {
180                arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1);
181            }
182            //Join all the elements of the array back into a string 
183            //using a blankspace as a separator 
184            const str2 = arr.join(" ");
185            return str2;
186        }
187        isOrphan() {
188            return this.orphanEvent;
189        }
190        getSearchAction() {
191            return this.searchAction;
192        }
193        getSearchType() {
194            return this.searchType;
195        }
196        getClickAction() {
197            return this.clickAction;
198        }
199        getClickType() {
200            return this.clickType;
201        }
202        hasResult() {
203            return (this.result != null) ? true : false;
204        }
205        getResult() {
206            return this.result;
207        }
208        setResult(result) {
209            this.result = result;
210        }
211        getDocumentTypeFacet() {
212            const objectTypeFacet = document.querySelector('.CoveoDynamicFacet[data-field="@sourcedisplayname"]');
213            if (objectTypeFacet) {
214                return Coveo.get(objectTypeFacet);
215            }
216            return null;
217        }
218        getLookFacet() {
219            const lookFacet = document.querySelector('.CoveoDynamicFacet[data-field="@serieslook"]');
220            if (lookFacet) {
221                return Coveo.get(lookFacet);
222            }
223            return null;
224        }
225        getSeriesFacet() {
226            const seriesFacet = document.querySelector('.CoveoDynamicFacet[data-field="@seriesname"]');
227            if (seriesFacet) {
228                return Coveo.get(seriesFacet);
229            }
230            return null;
231        }
232        resetSearchBox() {
233            const searchbox = document.querySelector(".CoveoOmnibox");
234            if (searchbox)
235                Coveo.get(searchbox).clear();
236        }
237        resetAllFacets() {
238            document.querySelectorAll('.CoveoDynamicFacet').forEach(facet => {
239                facet.CoveoDynamicFacet.reset();
240            });
241        }
242        setParams(params) {
243            this.params = params;
244        }
245        buildContext(queryBuilder) {
246            queryBuilder.addContext({
247                "seriesmatch": this.seriesmatch
248            });
249            return this;
250        }
251        applyFilter(coveoparams) { }
252    }
253
254    class InitialFilter extends FilterState {
255        constructor() {
256            super("initialFilter");
257            this.seriesmatch = "false"
258        }
259        applyFilter() {
260            this.orphanEvent = false;
261            console.log(this.name);
262        }
263    }
264    class DefaultFilter extends FilterState {
265        constructor() {
266            super("defaultFilter");
267            this.seriesmatch = "false"
268        }
269        applyFilter() {
270            this.orphanEvent = false;
271            console.log(this.name);
272        }
273    }
274    class NewQueryFilter extends FilterState {
275        constructor() {
276            super("newqueryFilter");
277            this.seriesmatch = "false"
278        }
279        applyFilter() {
280            this.orphanEvent = false;
281            console.log(this.name)
282            this.resetAllFacets();
283        }
284    }
285    class ComponentUpdateFilter extends FilterState {
286        constructor() {
287            super("componentupdateFilter");
288            this.seriesmatch = "false"
289        }
290        applyFilter() {
291            this.orphanEvent = false;
292            console.log(this.name)
293        }
294    }
295    class ViewProductsFilter extends FilterState {
296        searchAction = "FilterSeriesCard"
297        searchType = "filterData"
298        clickAction = "FilterSeriesClick"
299        clickType = "filterData"
300        constructor() {
301            super("viewproductsFilter");
302            this.seriesmatch = "true"
303        }
304        applyFilter(coveoparams) {
305            this.orphanEvent = false;
306            console.log(this.name);
307            const seriesname = this.params.seriesname;
308            const documentfacet = this.getDocumentTypeFacet();
309            const seriesfacet = this.getSeriesFacet();
310            this.resetAllFacets();
311            if (seriesfacet) {
312                seriesfacet.selectValue(this.capitalizeFirstLetter(seriesname));
313                this.resetSearchBox()
314                coveoparams.currentTarget.Coveostate.attributes["q"] = seriesname;
315                FilterStateManager.lastQuery = "";
316            } else {
317                FilterStateManager.lastQuery = seriesname;
318                coveoparams.currentTarget.Coveostate.attributes["q"] = seriesname;
319            }
320            if (documentfacet) {
321                documentfacet.selectValue("product");
322                documentfacet.selectValue("series");
323            }
324        }
325    }
326    class ViewProductsFilterSearch extends FilterState {
327        searchAction = "FilterSeriesSearch"
328        searchType = "filterData"
329        clickAction = "FilterSeriesClick"
330        clickType = "filterData"
331        constructor() {
332            super("ViewProductsFilterSearch");
333            this.seriesmatch = "true"
334        }
335        applyFilter(coveoparams) {
336            this.orphanEvent = false;
337            console.log(this.name);
338            const seriesname = this.params.seriesname;
339            const documentfacet = this.getDocumentTypeFacet();
340            const seriesfacet = this.getSeriesFacet();
341            this.resetAllFacets();
342            if (seriesfacet) {
343                seriesfacet.selectValue(this.capitalizeFirstLetter(seriesname));
344                //this.resetSearchBox()
345                FilterStateManager.lastQuery = "";
346            } else {
347                FilterStateManager.lastQuery = seriesname;
348                coveoparams.currentTarget.Coveostate.attributes["q"] = seriesname;
349            }
350            if (documentfacet) {
351                documentfacet.selectValue("product");
352                documentfacet.selectValue("series");
353            }
354        }
355    }
356    class ViewLooksFilter extends FilterState {
357        searchAction = "FilterLooksSearch"
358        searchType = "filterData"
359        clickAction = "FilterLooksClick"
360        clickType = "filterData"
361        constructor() {
362            super("viewlooksFilter");
363            this.seriesmatch = "false"
364        }
365        applyFilter(coveoparams) {
366            this.orphanEvent = false;
367            console.log(this.name)
368            const lookfacet = this.getLookFacet();
369            const documentfacet = this.getDocumentTypeFacet();
370            const serieslook = this.params.serieslook;
371            this.resetAllFacets();
372            if (lookfacet) {
373                lookfacet.selectValue(serieslook);
374                this.resetSearchBox()
375                FilterStateManager.lastQuery = "";
376            } else {
377                coveoparams.currentTarget.Coveostate.attributes["q"] = serieslook;
378                FilterStateManager.lastQuery = serieslook;
379            }
380            if (documentfacet) {
381                documentfacet.selectValue("Series");
382            }
383        }
384    }
385    const FilterFactory = {
386        buildAllFilters() {
387            FilterStateManager.getValues();
388            FilterStateManager.filters = {};
389            new DefaultFilter();
390            new InitialFilter();
391            new NewQueryFilter();
392            new ViewProductsFilter();
393            new ViewProductsFilterSearch();
394            new ViewLooksFilter();
395            new ComponentUpdateFilter();
396        }
397    }.buildAllFilters();
398
399    const SeriesSwatch = (function (_super) {
400        __extends(SeriesSwatch, Coveo.Component);
401        function SeriesSwatch(element, options, bindings, result) {
402            _super.call(this, element, SeriesSwatch.ID, bindings);
403            this.type = 'SeriesSwatch';
404            Coveo.Component.bindComponentToElement(element, this);
405            this.element = element;
406            this.options = options;
407            this.bindings = bindings;
408            this.result = result;
409            this.render = function () {
410                var swatches = this.result.raw.productswatchurl;
411                var urls = this.result.raw.pdpurl
412                let links = "";
413                for (i = 0; i < 4; i++) {
414                    if (this.result.raw.uri !== undefined && swatches[i] !== undefined)
415                        links += `<a href='${this.result.raw.seriespageurl}' ><img alt='swatch1' src='${swatches[i]}'></a>`;
416                }
417                if (swatches.length > 4) {
418                    links += `<a class="other-swatches" href='${this.result.raw.seriespageurl}' ><p>${swatches.length - 4}</p></a>`;
419                }
420                this.element.innerHTML += links;
421                var _self = this;
422                this.element.querySelectorAll("a").forEach(a => {
423                    a.onclick = _self.openSeriesPage;
424                    a.oncontextmenu = _self.openSeriesPage;
425                });
426            };
427            this.openSeriesPage = function (e, anchor) {
428                const root = searchInterfaceElement;
429                const cause = {
430                    name: "swatchClick",
431                    type: "document"
432                };
433                const metadata = {};
434                const result = this.parentNode.CoveoSeriesSwatch.result;
435                Coveo.logClickEvent(root, cause, metadata, result);
436            };
437            this.render();
438        }
439        SeriesSwatch.ID = 'SeriesSwatch';
440        Coveo.Initialization.registerAutoCreateComponent(SeriesSwatch);
441    })(Coveo.Component);
442    const SeriesImage = (function (_super) {
443        __extends(SeriesImage, Coveo.Component);
444        function SeriesImage(element, options, bindings, result) {
445            _super.call(this, element, SeriesImage.ID, bindings);
446            this.type = 'SeriesImage';
447            Coveo.Component.bindComponentToElement(element, this);
448            this.element = element;
449            this.options = options;
450            this.bindings = bindings;
451            this.result = result;
452            this.marazziimg = "/-/media/Project/DalTile-Sites/Marazzi/Site-Search/Marazzi---No-Series-Image-Available-Placeholder.jpg";
453            this.daltileimg = "/-/media/Project/DalTile-Sites/Daltile/Site-Search/No-Product-Image-Available.jpg";
454            this.americanimg = "/-/media/Project/DalTile-Sites/AmericanOlean/Site-Search/No-Product-Image-Available.jpg";
455            this.getImage = function (site) {
456                if (!site || site.length == 0)
457                    site = window.location.hostname;
458                else
459                    site = site[0];
460                if (site.toLowerCase().includes("daltile"))
461                    return this.daltileimg;
462                else if (site.toLowerCase().includes("americanolean"))
463                    return this.americanimg;
464                else if (site.toLowerCase().includes("marazziusa"))
465                    return this.marazziimg;
466                else
467                    return "";
468            }
469            this.isHosted = function () {
470                if (window.location.hostname.toLowerCase().includes("coveo"))
471                    return true;
472            }
473            this.render = function () {
474                let imgurl = this.result?.raw?.primaryroomsceneurl;
475                let imgAlt = (this.result?.raw?.alt) ?? '';
476                let site = this.result?.raw?.sitetargethostname;
477                let lvf = this.result?.raw?.producttype;
478                const planId = this.result?.raw?.planid;
479                const validPlanIds = [
480                    "PP1674198",
481                    "PP1673988",
482                    "PP1673425",
483                    "PP1675116",
484                    "PP1674618"
485                ];
486
487                if (!imgurl || imgurl.trim() === "") {
488                    imgurl = this.getImage(site);
489                } else if (this.isHosted() && !imgurl.includes("http")) {
490                    hostname = "https://www.daltile.com";
491                    imgurl = hostname + imgurl;
492                }
493                imgurl = imgurl.replaceAll("web.170.170", "web.570.570").replace("$TRIMTHUMBNAIL$", "$PRODUCTIMAGE$");
494                image = `<figure class="zoom series" onmousemove="zoom(event)" style="background-image: url(&quot;${imgurl}&quot;); background-position: 8.2% 37.0107%;">
495                     <img  class="series-view image" alt="${imgAlt}" src="${imgurl}">
496                     </figure>`;
497
498                if (validPlanIds.includes(planId[0])) {
499                    image += "<div class='lvt'>VITACORE PVC FREE FLOORING</div>";
500                } else if (lvf && (lvf.includes("Luxury Vinyl Tile") || lvf.includes("LVT Trim"))) {
501                    image += "<div class='lvt'>LUXURY VINYL FLOORING</div>";
502                }
503
504                this.element.innerHTML += image;
505            };
506            this.render();
507        }
508        SeriesImage.ID = 'SeriesImage';
509        Coveo.Initialization.registerAutoCreateComponent(SeriesImage);
510    })(Coveo.Component);
511    const ProductImage = (function (_super) {
512        __extends(ProductImage, Coveo.Component);
513        function ProductImage(element, options, bindings, result) {
514            _super.call(this, element, ProductImage.ID, bindings);
515            this.type = 'ProductImage';
516            Coveo.Component.bindComponentToElement(element, this);
517            this.element = element;
518            this.options = options;
519            this.bindings = bindings;
520            this.result = result;
521            this.marazziimg = "/-/media/Project/DalTile-Sites/Marazzi/Site-Search/Marazzi---No-Series-Image-Available-Placeholder.jpg";
522            this.daltileimg = "/-/media/Project/DalTile-Sites/Daltile/Site-Search/No-Product-Image-Available.jpg";
523            this.americanimg = "/-/media/Project/DalTile-Sites/AmericanOlean/Site-Search/No-Product-Image-Available.jpg";
524            this.getImage = function (site) {
525                if (!site || site.length == 0)
526                    site = window.location.hostname;
527                else
528                    site = site[0];
529                if (site.toLowerCase().includes("daltile"))
530                    return this.daltileimg;
531                else if (site.toLowerCase().includes("americanolean"))
532                    return this.americanimg;
533                else if (site.toLowerCase().includes("marazziusa"))
534                    return this.marazziimg;
535                else
536                    return "";
537            }
538            this.isHosted = function () {
539                if (window.location.hostname.toLowerCase().includes("coveo"))
540                    return true;
541            }
542            this.render = function () {
543                let imgurl = this.result?.raw?.productimageurl;
544                let secondaryroomsceneurl = this.result?.raw?.secondaryroomsceneurl;
545                const imgAlt = (this.result?.raw?.alt) ?? '';
546                const site = this.result?.raw?.sitetargethostname;
547                const lvf = this.result?.raw?.producttype;
548                const planId = this.result?.raw?.planid;
549                const validPlanIds = [
550                    "PP1674198",
551                    "PP1673988",
552                    "PP1673425",
553                    "PP1675116",
554                    "PP1674618"
555                ];
556
557                if (!imgurl || imgurl.length === 0) {
558                    imgurl = this.getImage(site);
559                } else {
560                    imgurl = imgurl[0];
561                }
562
563                if (this.isHosted() && !imgurl.includes("http")) {
564                    hostname = "https://www.daltile.com";
565                    imgurl = hostname + imgurl;
566                }
567
568                imgurl = imgurl.replaceAll("web.170.170", "web.570.570").replace("$TRIMTHUMBNAIL$", "$PRODUCTIMAGE$");
569                image = `<img class="product-view image sample-image" alt="${imgAlt}" src="${imgurl}"/>`;
570
571                if (secondaryroomsceneurl && secondaryroomsceneurl.length > 0) {
572                    secondaryroomsceneurl = secondaryroomsceneurl.replaceAll("web.170.170", "web.570.570").replace("$TRIMTHUMBNAIL$", "$PRODUCTIMAGE$");
573                    image += `<img class="product-view image roomscene-image" alt="${imgAlt}" src="${secondaryroomsceneurl}"/>`;
574                }
575
576                if (validPlanIds.includes(planId[0])) {
577                    image += "<div class='lvt'>VITACORE PVC FREE FLOORING</div>";
578                } else if (lvf && (lvf.includes("Luxury Vinyl Tile") || lvf.includes("LVT Trim"))) {
579                    image += "<div class='lvt'>LUXURY VINYL FLOORING</div>";
580                }          
581
582                this.element.innerHTML += image;
583            };
584            this.render();
585        }
586        ProductImage.ID = 'ProductImage';
587        Coveo.Initialization.registerAutoCreateComponent(ProductImage);
588    })(Coveo.Component);
589
590    const DocumentImage = (function (_super) {
591        __extends(DocumentImage, Coveo.Component);
592        function DocumentImage(element, options, bindings, result) {
593            _super.call(this, element, DocumentImage.ID, bindings);
594            this.type = 'DocumentImage';
595            Coveo.Component.bindComponentToElement(element, this);
596            this.element = element;
597            this.options = options;
598            this.bindings = bindings;
599            this.result = result;
600            this.isHosted = function () {
601                if (window.location.hostname.toLowerCase().includes("coveo"))
602                    return true;
603            }
604            this.render = function () {
605                let imgurl = this.result?.raw?.documentimageurl;
606                const imgAlt = (this.result?.raw?.alt) ?? '';
607
608                if (!imgurl || imgurl.length === 0) {
609                    return;
610                }
611
612                if (Array.isArray(imgurl)) {
613                    imgurl = imgurl[0];
614                }
615
616                if (this.isHosted() && !imgurl.includes("http")) {
617                    hostname = "https://www.daltile.com";
618                    imgurl = hostname + imgurl;
619                }
620
621                imgurl = imgurl.replaceAll("web.170.170", "web.570.570").replace("$TRIMTHUMBNAIL$", "$PRODUCTIMAGE$");
622                image = `<img class="document-view image" alt="${imgAlt}" src="${imgurl}"/>`;
623
624                this.element.innerHTML += image;
625            };
626            this.render();
627        }
628        DocumentImage.ID = 'DocumentImage';
629        Coveo.Initialization.registerAutoCreateComponent(DocumentImage);
630    })(Coveo.Component);
631
632    const FavoritesButton = (function (_super) {
633        __extends(FavoritesButton, Coveo.Component);
634        function FavoritesButton(element, options, bindings, result) {
635            _super.call(this, element, FavoritesButton.ID, bindings);
636            this.type = 'FavoritesButton';
637            Coveo.Component.bindComponentToElement(element, this);
638            this.element = element;
639            this.options = options;
640            this.bindings = bindings;
641            this.result = result;
642            this.render = function () {
643                const skus = this.result.raw?.sku?.split(";");
644                const defaultApplication = this.result.raw?.roomvodefaultapplication;
645
646                let productTypeValue = '';
647                if (defaultApplication && defaultApplication.length > 0 && defaultApplication[0]) {
648                    productTypeValue = defaultApplication[0].trim().toLowerCase();
649                } else {
650                    const productType = this.result.raw?.producttype?.split(" ");
651                    productTypeValue = productType[0].trim().toLowerCase();
652                }
653
654                this.element.setAttribute("data-selling-sku", skus[
6540].trim());
655                this.element.setAttribute("data-product-type", productTypeValue);
656            };
657            this.render();
658        }
659        FavoritesButton.ID = 'FavoritesButton';
660        Coveo.Initialization.registerAutoCreateComponent(FavoritesButton);
661    })(Coveo.Component);
662
663    const SeriesFilter = (function (_super) {
664        __extends(SeriesFilter, Coveo.Component);
665        function SeriesFilter(element, options, bindings, result) {
666            _super.call(this, element, SeriesFilter.ID, bindings);
667            this.type = 'SeriesFilter';
668            Coveo.Component.bindComponentToElement(element, this);
669            this.element = element;
670            this.options = options;
671            this.bindings = bindings;
672            this.result = result;
673            this.hasSeriesFilter = false;
674            this.render = function () {
675                this.element.innerHTML += "View Products";
676                this.element.setAttribute("tabindex", "0");
677                this.element.onclick = this.filterSeries;
678                this.element.onkeyup = this.catchEnter;
679            };
680            this.catchEnter = function (e, anchor) {
681                if (e.keyCode === 13) {
682                    this.CoveoSeriesFilter.element.click();
683                }
684            };
685            this.filterSeries = function (e, anchor) {
686                if (!FilterStateManager.isListening())
687                    FilterStateManager.startListening();
688                FilterStateManager.triggerEvent("viewproductsFilter", this.CoveoSeriesFilter.result, {
689                    seriesname: this.CoveoSeriesFilter.result.raw.seriesname
690                }, true);
691            };
692            this.render();
693        }
694        SeriesFilter.ID = 'SeriesFilter';
695        Coveo.Initialization.registerAutoCreateComponent(SeriesFilter);
696    })(Coveo.Component);
697    const LookFilter = (function (_super) {
698        __extends(LookFilter, Coveo.Component);
699        function LookFilter(element, options, bindings, result) {
700            _super.call(this, element, LookFilter.ID, bindings);
701            this.type = 'LookFilter';
702            Coveo.Component.bindComponentToElement(element, this);
703            this.element = element;
704            this.options = options;
705            this.bindings = bindings;
706            this.result = result;
707            this.hasLookFilter = false;
708            this.render = function () {
709                this.element.innerHTML += "Similar look";
710                this.element.setAttribute("tabindex", "0");
711                this.element.onclick = this.filterLooks;
712                this.element.onkeyup = this.catchEnter;
713            };
714            this.catchEnter = function (e, anchor) {
715                if (e.keyCode === 13) {
716                    this.CoveoLookFilter.element.click();
717                }
718            };
719            this.filterLooks = function (e, anchor) {
720                if (!FilterStateManager.isListening())
721                    FilterStateManager.startListening();
722                FilterStateManager.triggerEvent("viewlooksFilter", this.CoveoLookFilter.result, {
723                    serieslook: this.CoveoLookFilter.result.raw.serieslook
724                }, true);
725            };
726            this.render();
727        }
728        LookFilter.ID = 'LookFilter';
729        Coveo.Initialization.registerAutoCreateComponent(LookFilter);
730    })(Coveo.Component);
731
732    const ViewRoom = (function (_super) {
733        __extends(ViewRoom, Coveo.Component);
734        function ViewRoom(element, options, bindings, result) {
735            _super.call(this, element, ViewRoom.ID, bindings);
736            this.type = 'ViewRoom';
737            Coveo.Component.bindComponentToElement(element, this);
738            this.element = element;
739            this.options = options;
740            this.bindings = bindings;
741            this.result = result;
742            this.render = function () {
743                if ((!this.result.raw.sample || this.result.raw.sample.length === 0) || !this.result.raw.sampleavailable || (this.result.raw.sampleavailable && this.result.raw.sampleavailable === "N"))
744                    this.element.classList.add("custom-button");
745                else
746                    this.element.classList.add("custom-button");
747                this.element.innerHTML += "View In a Room";
748                this.element.setAttribute("tabindex", "0");
749                this.element.onclick = this.openRoom;
750                this.element.onkeyup = this.catchEnter;
751            };
752            this.catchEnter = function (e, anchor) {
753                if (e.keyCode === 13) {
754                    this.CoveoViewRoom.element.click();
755                }
756            };
757            this.openRoom = function (e, anchor) {
758                console.log(this);
759                let cause = {
760                    name: "viewRoom",
761                    type: "click"
762                };
763                Coveo.logClickEvent(this.CoveoViewRoom.root, cause, {}, this.CoveoViewRoom.result);
764                let productType = '';
765                const defaultApplication = this.CoveoViewRoom.result.raw?.roomvodefaultapplication;
766                if (defaultApplication && defaultApplication.length > 0 && defaultApplication[0]) {
767                    productType = defaultApplication[0].trim().toLowerCase();
768                }
769
770                const skus = this.CoveoViewRoom.result.raw?.sku?.split(";");
771                if (skus && skus.length > 0 && skus[0]) {
772                    roomvo.startStandaloneVisualizer(productType, skus[
7720].trim());
773                    console.log(productType);
774                    console.log(skus[0].trim());
775                }
776            };
777            this.render();
778        }
779        ViewRoom.ID = 'ViewRoom';
780        Coveo.Initialization.registerAutoCreateComponent(ViewRoom);
781    })(Coveo.Component);
782
783    const GetSample = (function (_super) {
784        __extends(GetSample, Coveo.Component);
785        function GetSample(element, options, bindings, result) {
786            _super.call(this, element, GetSample.ID, bindings);
787            this.type = 'GetSample';
788            Coveo.Component.bindComponentToElement(element, this);
789            this.element = element;
790            this.options = options;
791            this.bindings = bindings;
792            this.result = result;
793            this.render = function () {
794                let text = "Get Sample";
795                if ((!this.result.raw.sample || this.result.raw.sample.length == 0) || !this.result.raw.sampleavailable || (this.result.raw.sampleavailable && this.result.raw.sampleavailable === "N")) {
796                    //this.element.remove();
797                    //return;
798                    text = "Sample Coming Soon"
799                    this.element.setAttribute("title", "Sample Coming Soon");
800                    this.element.classList.remove("custom-button");
801                    this.element.classList.add("custom-button-disabled");
802                }
803                this.element.innerHTML += text;
804                if (this.result.raw.sample && (this.result.raw.sampleavailable && this.result.raw.sampleavailable === "Y")) {
805                    let sample = this.result.raw.sample[0];
806                    this.element.classList.add("primary-anchor-text");
807                    this.element.classList.add("order-sample-button");
808                    this.element.classList.add("js-order-sample-button");
809                    this.element.setAttribute("data-daltile-swatchbox", "");
810                    this.element.setAttribute("tabindex", "0");
811                    if (sample)
812                        this.element.setAttribute("data-daltile-swatchbox-external-sku", sample.trim());
813                    this.element.setAttribute("data-daltile-swatchbox-redirect-url", `https://${this.result.raw.sitetargethostname}`);
814                    this.element.setAttribute("data-finish", this.result.raw.finish);
815                    this.element.onkeyup = this.catchEnter;
816                }
817                this.element.onclick = this.sendClickEvent;
818            };
819            this.catchEnter = function (e, anchor) {
820                if (e.keyCode === 13) {
821                    this.CoveoGetSample.element.click();
822                }
823            };
824            this.sendClickEvent = function (e, anchor) {
825                let cause = {
826                    name: "viewSample",
827                    type: "click"
828                };
829                Coveo.logClickEvent(this.CoveoGetSample.root, cause, {}, this.CoveoGetSample.result);
830            };
831            this.render();
832        }
833        GetSample.ID = 'GetSample';
834        Coveo.Initialization.registerAutoCreateComponent(GetSample);
835    })(Coveo.Component);
836
837    const DownloadDocument = (function (_super) {
838        __extends(DownloadDocument, Coveo.Component);
839        function DownloadDocument(element, options, bindings, result) {
840            _super.call(this, element, DownloadDocument.ID, bindings);
841            this.type = 'DownloadDocument';
842            Coveo.Component.bindComponentToElement(element, this);
843            this.element = element;
844            this.options = options;
845            this.bindings = bindings;
846            this.result = result;
847            this.render = function () {
848                this.element.innerHTML += "Download PDF";
849                this.element.setAttribute("tabindex", "0");
850                this.element.onclick = this.downloadFile;
851                this.element.onkeyup = this.catchEnter;
852            };
853            this.catchEnter = function (e) {
854                if (e.keyCode === 13) {
855                    this.CoveoDownloadDocument.element.click();
856                }
857            };
858            this.downloadFile = function (e) {
859                e.preventDefault();
860                const component = this.CoveoDownloadDocument;
861                const documentUrl = component.result.raw.documenturl;
862                
863                // Log click event for analytics
864                const cause = {
865                    name: "downloadDocument",
866                    type: "click"
867                };
868                Coveo.logClickEvent(component.root, cause, {}, component.result);
869                
870                if (!documentUrl) return;
871
872                // Handle array values
873                if (Array.isArray(documentUrl)) {
874                    documentUrl = documentUrl[0];
875                }
876
877                download(documentUrl);
878            };
879            this.render();
880        }
881        DownloadDocument.ID = 'DownloadDocument';
882        Coveo.Initialization.registerAutoCreateComponent(DownloadDocument);
883    })(Coveo.Component);
884
885    const documents = {
886        fetchDocuments() {
887            const config = Coveo.SearchEndpoint.defaultEndpoint;
888            const token = "Bearer " + config.accessToken.token;
889            const _self = this;
890            let model = coveoSearchAssetsModel;
891            let series = model.AdvancedExpressionSeriesId;
892            const response = fetch(`/coveo/rest/search/v2`, {
893                method: 'POST',
894                headers: {
895                    'Accept': 'application/json',
896                    'Content-Type': 'application/json',
897                    'Authorization': token
898                },
899                body: JSON.stringify({
900                    q: "",
901                    aq: `@formattedseriesname=="${series}" AND @sourcedisplayname=="document"`,
902                    "numberOfResults": 20,
903                    fieldsToInclude: [
904                        "alt",
905                        "documenttype",
906                        "documenturl",
907                        "title",
908                        "sourcedisplayname"
909                    ]
910                })
911            });
912            response.then(function (response) {
913                const json = response.json();
914                json.then(function (data) {
915                    if (!data.results || !data.results.length) {
916                        return;
917                    }
918                    window.latestCoveoDocuments = data.results;
919                });
920            });
921        }
922    }.fetchDocuments();
923
924    Coveo.$$(searchInterfaceElement).on('state:change:q', function (e, args) {
925        console.log("query")
926        console.log(e)
927        if ((FilterStateManager.currentEventObj && !FilterStateManager.currentEventObj.isOrphan() && !FilterStateManager.listenEvents) || !FilterStateManager.listenEvents) return;
928        const query = e.currentTarget.Coveostate.attributes["q"];
929        if (FilterStateManager.isSeriesName(query) && FilterStateManager.isNewQuery(query)) {
930            FilterStateManager.triggerEvent("ViewProductsFilterSearch", null, {
931                seriesname: query
932            }, false);
933        } else if (FilterStateManager.isNewQuery(query)) {
934            FilterStateManager.triggerEvent("newqueryFilter", null, {}, false);
935        } else { }
936    });
937    Coveo.$$(searchInterfaceElement).on('state:change', function (e, args) { });
938    Coveo.$$(searchInterfaceElement).on("buildingQuery", function (e, args) {
939        FilterStateManager.stopListening()
940            .getEvent()
941            .buildContext(args.queryBuilder)
942            .applyFilter(e);
943    });
944    Coveo.$$(searchInterfaceElement).on("queryError", function (e, args) {
945        FilterStateManager.startListening()
946    });
947    Coveo.$$(searchInterfaceElement).on("querySuccess", function (e, args) {
948        FilterStateManager.startListening()
949        document.querySelector(".coveo-themed").focus()
950    });
951    Coveo.$$(searchInterfaceElement).on("noResults", function (e, args) {
952        FilterStateManager.startListening()
953    });
954    Coveo.$$(searchInterfaceElement).on("newResultsDisplayed", function () {
955        const facet = document.getElementById("document-facet");
956        if (!facet) return;
957
958        const docs = window.latestCoveoDocuments || [];
959        addDocumentDownloadIcon(facet, docs);
960
961        const observer = new MutationObserver(() => {
962            addDocumentDownloadIcon(facet, docs);
963        });
964
965        observer.observe(facet, {
966            childList: true,
967            subtree: true
968        });
969    });
970}
971
972function addDocumentDownloadIcon(facet, docs) {
973    const documentMap = {};
974
975    docs.forEach(result => {
976        const documentType = result.raw?.documenttype;
977        const documentUrl = result.raw?.documenturl;
978
979        if (documentType && documentUrl) {
980            documentMap[documentType.trim().toLowerCase()] = documentUrl;
981        }
982    });
983
984    const values = facet.querySelectorAll(
985        ".coveo-dynamic-facet-value"
986    );
987
988    values.forEach(value => {
989        if (value.querySelector(".facet-download-icon")) return;
990
991        const facetValue = value.getAttribute("data-value");
992        if (!facetValue) return;
993
994        const matchedUrl =
995            documentMap[facetValue.trim().toLowerCase()];
996
997        if (!matchedUrl) return;
998
999        const label = value.querySelector(".coveo-checkbox-label");
1000        if (!label) return;
1001
1002        const icon = document.createElement("span");
1003        icon.className = "facet-download-icon";
1004        icon.innerHTML = "";
1005        icon.title = "Download";
1006        icon.setAttribute("data-document-url", matchedUrl);
1007        icon.setAttribute("data-document-type", facetValue);
1008
1009        label.after(icon);
1010
1011        icon.addEventListener("click", e => {
1012            const documentUrl = e.currentTarget.getAttribute("data-document-url");
1013            if (!documentUrl) return;
1014            download(documentUrl);
1015        });
1016    });
1017}
1018
1019function download(documentUrl) {
1020    // Extract filename from URL
1021    const urlParts = documentUrl.split('/');
1022    const filename = urlParts[urlParts.length - 1] || 'document.pdf';
1023
1024    // Fetch as blob to force download (bypasses cross-origin restrictions)
1025    fetch(documentUrl)
1026        .then(response => {
1027            if (!response.ok) throw new Error('Network response was not ok');
1028            return response.blob();
1029        })
1030        .then(blob => {
1031            const blobUrl = window.URL.createObjectURL(blob);
1032            const link = document.createElement('a');
1033            link.href = blobUrl;
1034            link.download = filename;
1035            document.body.appendChild(link);
1036            link.click();
1037            document.body.removeChild(link);
1038            window.URL.revokeObjectURL(blobUrl);
1039        })
1040        .catch(error => {
1041            console.error('Download failed:', error);
1042            // Fallback: open in new tab if fetch fails
1043            window.open(documentUrl, '_blank');
1044        });
1045}
1046
1047document.addEventListener('CoveoSearchEndpointInitialized', function () {
1048    searchResultsTemplateInit();
1049});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.