· 5 years ago · Jun 29, 2020, 11:20 AM
1
2
3/* FoundIt! Integration Config | Boots */
4
5window.FI_Config = {
6 version: 'Boots v1.0',
7 requestTimeout: 5000,
8 foundItApiProgramCode: '',
9 abortOnUnknownPageType: true,
10
11 categoryPageItemsInCarousel: 6,
12
13 productTabs: true,
14 productTabsMinTabs: 1,
15 productTabsMaxTabs: 5,
16 productTabsMinProducts: 3,
17 productTabsItemsInCarousel: 6,
18
19 gaClientTrackingTrackerName: null,
20 gaClientTrackingEventCategory: 'FoundIt',
21 gaClientTrackingCustomDimensionIndex: null,
22 disableTrackingUrlParameter: false, // set true to remove the ?fi= tracking URL parameter
23 disableTrackingEntirely: true, // set true to disable all tracking
24 //trackingEnabledEvents: [], // string array of selective events to track
25
26 thisPageType: null, // Put a string here ('Category', 'Search', 'Product') to force the page type
27 thisPageUrl: null, // Put a URL string here to force the page URL
28
29 /******* API Program Code and page URL override for testing *******/
30 /******* REMOVE BEFORE PRODUCTION DEPLOYMENT! *******/
31 foundItApiProgramCode: 'test-pages',
32 thisPageUrl: 'http://www.foundit.com/boots-pdp', // Put a URL string here to force the page URL
33 /******* END *******/
34
35 gaClientTrackingFunction: function() {
36 return (typeof window.ga === 'function') ? window.ga : null;
37 },
38
39 slots: [
40 {
41 id: 'plp-main',
42 key: 'Main Links',
43 title: '',
44 attach: 'after',
45 target: 'div#widget_breadcrumb',
46 template: 'main-links'
47 }
48 ,{
49 id: 'pdp-products-widget',
50 key: 'Product Widget',
51 title: 'More like this',
52 attach: 'prepend',
53 target: 'div#estore_productpage_template_container div.row.template_row_spacer',
54 template: 'product-page-links-products-widget'
55 }
56 ],
57 templates: {
58 'main-links': {
59 html: {
60 wrapStart: '<nav class="fi-plp-main__nav">',
61 //heading: '<h2 class="fi-plp-main__heading">#{title}</h2>',
62 listStart: '<div class="fi-plp-main__arrow fi-arrow fi-arrow-left" fi-arrow-direction="left"></div><div class="fi-plp-main__arrow fi-arrow fi-arrow-right" fi-arrow-direction="right"></div><ul class="fi-plp-main__list fi-list-scrollable">',
63 item: '<li class="fi-plp-main__item"><a class="fi-link fi-plp-main__link" href="#{url}" data-tracking="#{trackLinkClickString}" data-page-type="#{pageTypeString}" rel="nofollow" draggable="false"><div class="fi-plp-main__image-crop"><img class="fi-image fi-plp-main__image" src="#{imageurl}" draggable="false"/></div><div class="fi-plp-main__text"><span class="fi-plp-main-inner-text">#{text}</span></div></a></li>',
64 dummyItem: '<li class="fi-plp-main__item fi-plp-main__item-dummy"></li>',
65 listEnd: '</ul>',
66 wrapEnd: '</nav>'
67 }
68 }
69 ,'product-page-links-products-widget': {
70 html: {
71 wrapStart: '<div class="fi-pdp-pw__nav">',
72 headingStart: '<h3 class="fi-pdp-pw__heading">#{title}</h3><div class="fi-pdp-pw__tab-headers">',
73 heading: '<div class="fi-pdp-pw__tab-heading" fi-pw-tab-id="#{id}" title="#{heading}">#{heading}</div>',
74 headingEnd: '</div>',
75 listStart: '<div class="fi-pdp-pw__tab-content" fi-pw-tab-id="#{id}"><div class="fi-pdp-pw__tab-content-container"><div class="fi-arrow fi-arrow-left" fi-arrow-direction="left"></div><div class="fi-arrow fi-arrow-right" fi-arrow-direction="right"></div><div class="fi-pdp-pw__content fi-list-scrollable">',
76 item: '<div class="fi-pdp-pw__product_card-ext"> <div class="fi-pdp-pw__item"> <a class="fi-link fi-pdp-pw__link" href="#{href}" title="#{title}" data-tracking="#{trackLinkClickString}" data-page-type="#{pageTypeString}" draggable="false"> <span class="fi-pdp-pw__product_offer_notify">Offer</span> <div class="fi-pdp-pw__image-crop"> <img src="#{imageUrl}" class="fi-pdp-pw__image" alt="#{title}" draggable="false" /> </div> <div class="fi-pdp-pw__product_description">#{title}</div> <div class="fi-pdp-pw__product-rating"> <span class="fi-pdp-pw__rating"></span> <span class="fi-pdp-pw__product-review-count">(999)</span> </div> <div class="fi-pdp-pw__price-box"> <span class="fi-pdp-pw__price">#{price}</span> <div class="fi-pdp-pw__sale-save-was"><span class="fi-pdp-pw__sale-save">Save £99.99</span> <span class="fi-pdp-pw__sale-was">Was £299.99</span></div> </div> </a> </div></div>',
77 dummyItem: '<div class="fi-pdp-pw__product_card-ext fi-pdp-pw__product_card-ext-dummy"><div class="fi-pdp-pw__item"></div></div>',
78 subitem: '',
79 listEnd: '</div></div><div class="fi-pdp-pw__see-all"><a class="fi-link fi-pdp-pw__see-all-link" href="#{url}" data-tracking="#{trackLinkClickString}" data-page-type="#{pageTypeString}">Shop all #{text}</a></div></div>',
80 wrapEnd: '</div><div class="fi-pdp-pw__line"></div>'
81 }
82 }
83 },
84 styles: [
85 '.fi-slot * { margin: 0; padding: 0; }',
86
87 // Category/Search page - DESKTOP
88 '.fi-slot--plp-main { margin: 35px auto !important; padding: 0 10px 0 5px; }',
89 '.fi-plp-main__nav { position: relative; padding: 0 20px; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }',
90 '.fi-plp-main__list { display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: flex-start; overflow: hidden; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; scrollbar-width: none; }',
91 '.fi-plp-main__list::-webkit-scrollbar { display: none; background: transparent; width: 0px; }',
92 '.fi-plp-main__item { display: inline-block; text-align: center; box-sizing: border-box; min-width: calc(100% / 6); max-width: calc(100% / 6); padding: 0 20px; }',
93 '.fi-slot a.fi-plp-main__link { display: block; position: relative; -webkit-user-drag: none; }',
94 '.fi-plp-main__image-crop { display: inline-block; box-sizing: border-box; border: 1px solid #d0d0d0; border-radius: 50%; margin-top: 10px; overflow: hidden; height: 155px; width: 155px; }',
95 'a.fi-plp-main__link:hover .fi-plp-main__image-crop { transform: scale(1.1); transition: 0.2s ease-in-out; }',
96 '.fi-plp-main__image { display: block; margin: auto; width: 100%; -webkit-user-drag: none; }',
97 '.fi-plp-main__text { display: block; padding-top: 10px; max-height: 52px; overflow: hidden; width: 100%; line-height: 16px; }',
98 '.fi-plp-main-inner-text { color: #333; font-family: "F37 Ginger Bold", Tahoma, Arial, sans-serif; font-size: 14px; font-weight: bold; white-space: normal; } ',
99 'a.fi-plp-main__link:hover .fi-plp-main-inner-text { color: #262626; }',
100 'a.fi-plp-main__link:focus { outline: none; }',
101 '.fi-arrow { position: absolute; display: inline-block; height: 16px; width: 16px; top: 38%; font-size: 40; user-select: none; -moz-user-select: none; -khtml-user-select: none; -webkit-user-select: none; -o-user-select: none; }',
102 '.fi-arrow:before { display: inline-block; height: 12px; width: 12px; content: ""; border: solid #E8E8E8; transform: rotate(45deg); } ',
103 '.fi-arrow-left { left: 0; }',
104 '.fi-arrow-right { right: 0; }',
105 '.fi-arrow-left:before { margin-top: 3px; margin-left: 5px; border-width: 0px 0px 2px 2px; }',
106 '.fi-arrow-right:before { margin-top: 3px; border-width: 2px 2px 0px 0px; }',
107 '.fi-arrow-active { cursor: pointer; }',
108 '.fi-arrow-active:before { border-color: black; }',
109
110 // Category/Search page - SMALLER DESKTOP
111 '@media only screen and (max-width: 1279px) {',
112 ' .fi-plp-main__item { padding: 0 15px; }',
113 ' .fi-plp-main__image-crop { box-sizing: border-box; height: 125px; width: 125px; }',
114 '}',
115
116 // Category/Search page - TABLET
117 '@media only screen and (max-width: 1023px) {',
118 ' .fi-slot--plp-main { margin: 25px -17px !important; padding: 0px; }',
119 ' .fi-plp-main__nav { padding: 0; }',
120 ' .fi-plp-main__list { overflow-x: scroll; }',
121 ' .fi-plp-main__item { min-width: calc(100% / 5.7); max-width: calc(100% / 5.7); padding: 0 12px; }',
122 ' .fi-plp-main__item:first-child { padding-left: 8px; }',
123 ' .fi-plp-main__item:last-child { padding-right: 8px; }',
124 ' .fi-plp-main__item-dummy { display: none; }',
125 ' .fi-plp-main__image-crop { box-sizing: border-box; height: 121px; width: 121px; }',
126 ' .fi-plp-main__text { padding-top: 8px; }',
127 ' .fi-plp-main-inner-text { font-size: 12px; } ',
128 ' .fi-arrow { display: none; }',
129 '}',
130
131 // Category/Search page - MOBILE
132 '@media only screen and (max-width: 767px) {',
133 ' .fi-plp-main__item { min-width: calc(100% / 4.25); max-width: calc(100% / 4.25); padding: 0 6px; }',
134 ' .fi-plp-main__image-crop { height: 105px; width: 105px; }',
135 '}',
136
137 // Category/Search page - MOBILE
138 '@media only screen and (max-width: 599px) {',
139 ' .fi-plp-main__item { min-width: calc(100% / 3.25); max-width: calc(100% / 3.25); padding: 0 6px; }',
140 ' .fi-plp-main__image-crop { height: 91px; width: 91px; }',
141 '}',
142
143 // Product page - DESKTOP
144 '#fi-pdp-products-widget { display: block; margin: 0 auto; width: 100%; padding-top: 25px; }',
145 '.fi-pdp-pw__nav { position: relative; margin: 0 auto; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }',
146 '.fi-pdp-pw__heading { color: #333333; font-size: 20px; font-weight: 400; text-align: center; }',
147
148 '.fi-pdp-pw__tab-headers { font-size: 14px; text-align: center; overflow: hidden; align-items: center; justify-content: center; margin: 24px 0; flex-wrap: nowrap; display: flex; white-space: nowrap; }',
149 '.fi-pdp-pw__tab-heading { display: inline-block; cursor: pointer; line-height: 18px; letter-spacing: 0.22px; white-space: nowrap; color: #333333; margin-right: 60px; padding-bottom: 4px; font-family: "F37 Ginger", Tahoma, Arial, sans-serif; font-size: 14px; font-weight: 300; }',
150 '.fi-pdp-pw__tab-heading::before { display: block; content: attr(title); font-weight: bold; height: 1px; color: transparent; overflow: hidden;visibility: hidden; }',
151 '.fi-pdp-pw__tab-heading.fi-pw-tab-active, .fi-pdp-pw__tab-heading:hover { cursor: pointer; font-weight: bold; box-shadow: inset 0 -2px 0 0 #979797; transition: 0.25s; }',
152 '.fi-pdp-pw__tab-content { display: none; overflow: hidden; padding: 0 25px; }',
153 '.fi-pdp-pw__tab-content.fi-pw-tab-active { display: block; }',
154 '.fi-pdp-pw__tab-content-container { position: relative; }',
155 '.fi-pdp-pw__tab-content-container .fi-arrow { display: none; height: 44px; width: 30px; top: 25%; z-index: 10; } ',
156 '.fi-pdp-pw__tab-content-container .fi-arrow.fi-arrow-active { display: block; }',
157 '.fi-pdp-pw__tab-content-container .fi-arrow:before { border-color: #333333; margin: 0; height: 12px; width: 12px; }',
158 '.fi-pdp-pw__tab-content-container .fi-arrow-left { padding-left: 5px; margin-left: -25px; }',
159 '.fi-pdp-pw__tab-content-container .fi-arrow-right { margin-right: -32px; }',
160 '.fi-pdp-pw__tab-content-container .fi-arrow-left:before { border-width: 0px 0px 3px 3px; }',
161 '.fi-pdp-pw__tab-content-container .fi-arrow-right:before { border-width: 3px 3px 0px 0px; }',
162 '.fi-pdp-pw__product_card-ext { display: inline-block; box-sizing: border-box; min-width: calc(100% / 6); max-width: calc(100% / 6); padding: 0 10px; }',
163 '.fi-pdp-pw__content { display: flex; justify-content: flex-start; overflow: hidden; animation: fadeEffect 1s; clear: both; padding-bottom: 50px !important; margin-bottom: -50px !important; }',
164 '.fi-pdp-pw__content.fi-list-scrollable { -ms-overflow-style: none; -webkit-overflow-scrolling: touch; scrollbar-width: none; }',
165 '.fi-pdp-pw__content.fi-list-scrollable::-webkit-scrollbar { display: none; background: transparent; width: 0px; height: 0; }',
166 '.fi-pdp-pw__item { position: relative; padding: 0; }',
167 'a.fi-pdp-pw__link { width: 100%; display: inline-block; -webkit-user-drag: none; text-decoration: none; }',
168 '.fi-pdp-pw__image-crop { display: block; box-sizing: border-box; border: 1px solid #d0d0d0; border-radius: 50%; overflow: hidden; max-height: 175px; max-width: 175px; margin: 10px auto; }',
169 '.fi-pdp-pw__image { display: block; margin: auto; width: 100%; transform: scale(0.8); -webkit-user-drag: none; }',
170 '.fi-pdp-pw__product_description { display: -webkit-box; height: 40px; -webkit-line-clamp: 2; -webkit-box-orient: vertical; text-overflow: ellipsis; overflow: hidden; line-height: 20px; padding: 7px 5px 0 5px; font-family: "F37 Ginger Bold", Tahoma, Arial, sans-serif; font-size: 14px; text-align: center; }',
171
172 '.fi-pdp-pw__product-rating { text-align: center; height: 18px; padding: 5px 0 0 0; }',
173 '.fi-pdp-pw__rating { color: #FFCC00; text-align: left; position: relative; }',
174 '.fi-pdp-pw__rating::before { content: "\\e033 \\e033 \\e033 \\e034"; position: absolute; left: 0; letter-spacing: 2px; font-family: "ElegantIcons"; font-size: .87em; z-index: 9; vertical-align: top; }',
175 '.fi-pdp-pw__rating::after { color: #D0D0D0; letter-spacing: 2px; font-family: "ElegantIcons"; font-size: .87em; content: "\\e033 \\e033 \\e033 \\e033 \\e033"; vertical-align: top; }',
176 '.fi-pdp-pw__product-review-count {} ',
177
178 'div.fi-pdp-pw__price-box { padding-top: 20px; text-align: center; }',
179 'span.fi-pdp-pw__price { font-size: 20px; font-weight: bold; text-align: center; }',
180 'span.fi-pdp-pw__price:not(.fi-pdp-pw__with-sale-price) { }',
181 '.fi-pdp-pw__sale-save-was { display: block; color: #101010; font-size: 14px; }',
182 '.fi-pdp-pw__sale-save-was:empty { display: none; }',
183 '.fi-pdp-pw__product_card-ext:first-child .fi-pdp-pw__sale-save-was { display: none; }',
184 'span.fi-pdp-pw__sale-save { display: inline-block; }',
185 'span.fi-pdp-pw__sale-was { display: inline-block; }',
186
187 'span.fi-pdp-pw__product_offer_notify { left: 15px; top: 11px; font-size: 12px; display: inline-block; width: 40px; height: 40px; border-radius: 50px; position: absolute; background: #CC0033; color: #fff; line-height: 39px; font-weight: bold; z-index: 9; text-align: center; }',
188 '.fi-pdp-pw__product_card-ext:first-child span.fi-pdp-pw__product_offer_notify { display: none; }',
189
190 '.fi-pdp-pw__see-all { text-align: center; }',
191 'a.fi-pdp-pw__see-all-link { display: inline-block; background-color: #CAE0F5; border-radius: 3px; color: #004990; font-size: 21px; font-weight: bold; padding: 15px 90px; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 85%; margin: 30px 0 0 0; }',
192 'a.fi-pdp-pw__see-all-link[href=""] { display: none; }',
193 '.fi-pdp-pw__line { border: solid 1px #e7e7e7; margin: 41px auto 0 auto; width: 81%; }',
194
195
196 // Product page - SMALLER DESKTOP
197 '@media only screen and (max-width: 1279px) {',
198 ' .fi-pdp-pw__image-crop { box-sizing: border-box; height: 125px; width: 125px; }',
199 '}',
200
201 '@media only screen and (min-width: 1025px) {',
202 ' a.fi-pdp-pw__link:hover .fi-pdp-pw__image-crop { transform: scale(1.1); transition: 0.2s ease-in-out; }',
203 '}',
204
205 // Product page - DESKTOP/TABLET
206 '@media only screen and (max-width: 1024px) {',
207 ' #fi-pdp-products-widget-desktop .fi-arrow { display: none; }',
208 ' .fi-pdp-pw__nav { text-align: center; user-select: none; }',
209 ' .fi-pdp-pw__tab-headers { display: inline-flex; justify-content: flex-start; max-width: 100%; overflow-x: scroll; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; scrollbar-width: none; }',
210 ' .fi-pdp-pw__tab-headers::-webkit-scrollbar { display: none; background: transparent; width: 0px; height: 0px; }',
211 ' .fi-pdp-pw__tab-heading { margin-right: 24px; }',
212 ' .fi-pdp-pw__tab-heading:last-child { margin-right: 0; }',
213 ' .fi-pdp-pw__tab-content { display: none; margin-left: 0; overflow: hidden; padding: 0; }',
214 ' .fi-pdp-pw__tab-content-container { padding: 0; }',
215 ' .fi-pdp-pw__content { overflow-x: scroll; padding: 0; }',
216 ' .fi-pdp-pw__product_card-ext { min-width: calc(100% / 4.25); max-width: calc(100% / 4.25); padding: 0 5px; }',
217 ' .fi-pdp-pw__product_card-ext:first-child { margin-left: -5px; }',
218 ' .fi-pdp-pw__product_card-ext:last-child { margin-right: -5px; }',
219 ' .fi-pdp-pw__product_card-ext-dummy { display: none; }',
220 ' .fi-pdp-pw__image-crop { box-sizing: border-box; height: auto; width: auto; }',
221 ' .fi-pdp-pw__product_description { padding: 3px 5px 0 5px; }',
222 '}',
223
224 // Product page - MOBILE
225 '@media only screen and (max-width: 767px) {',
226 ' #fi-pdp-products-widget { padding-bottom: 15px; }',
227 ' .fi-pdp-pw__heading { font-family: inherit; font-weight: bold; }',
228 ' .fi-pdp-pw__tab-headers { margin: 18 0; }',
229 ' .fi-pdp-pw__tab-heading { font-size: 12px; }',
230 ' .fi-pdp-pw__product_card-ext { min-width: calc(100% / 2.15); max-width: calc(100% / 2.15); padding: 0 5px; }',
231 ' .fi-pdp-pw__product_description { font-size: 12px; }',
232 ' .fi-pdp-pw__product-rating { padding-top: 2px; }',
233 ' .fi-pdp-pw__product-review-count {font-size: 12px; } ',
234 ' div.fi-pdp-pw__price-box { padding-top: 15px; }',
235 ' .fi-pdp-pw__sale-save-was { font-size: 11px; line-height: 14px; padding-top: 2px; }',
236 ' span.fi-pdp-pw__product_offer_notify { left: 0px; top: 5px; font-size: 10px; width: 30px; height: 30px; line-height: 30px; }',
237 ' a.fi-pdp-pw__see-all-link { font-size: 14px; padding: 10px 30px; max-width: 95%; margin: 20px 0 0 0; }',
238 ' .fi-pdp-pw__line { display: none; }',
239 '}',
240
241 ''
242 ]
243};
244
245/* FoundIt! Integration | Boots */
246
247window.FI_Scripts = {
248 // Return TRUE for cases when we want to stop the integration from running
249 noRunFlag: function() { },
250
251 // These scripts run at init
252 initScripts: function() {
253 FI_Scripts.cleanup(); // Cleanup before every run as their deployment takes care of ajax handling.
254 },
255
256 // Extract the page type
257 extractPageType: function(url) {
258 var pathName = url.replace(/[?#]{1}.*/, '');
259 if (pathName == '/') return null;
260 else if ( pathName.indexOf('/sitesearch') == 0 ) return 'Search';
261 else if ( pathName.match(/[0-9]{6,}([\?#].*)*$/) ) return 'Product';
262 else if ( pathName.match(/(\/online|\/search|ADC|Display|OrderDetail|AjaxLogonForm|ADCAccountSummary|webapp|StoreLookupView|UserRegistrationForm|AdvantageCardApply|AddressBookForm|store|terms|wishlist|boots-shopping|DigitalOffersShopNowCmd|OrderShippingBillingView|PHExtendedRegistrationView|EStoreStoreDetailNonAjaxView|UserRegistrationUpdate|TrackOrderStatus|shop-online|opticians-advice|OrderChangeServiceItemUpdate|advantage-card|DigitalMyOffersView|Logoff|ClickInfo|ClinicStatusView|[0-9]{6,}-$|[0-9]{6,}p$)/i) ) return null;
263 else return 'Category';
264 },
265
266 // Clean up a search term
267 cleanUpSearchTerm: function(searchTerm) {
268 searchTerm = searchTerm.replace(/[-_]/g, ' '); // Replace any dash or underscore with a space
269 searchTerm = searchTerm.replace(/[^A-Z0-9&: ]/gi, ''); // Remove any unwanted character
270 searchTerm = searchTerm.replace(/[ ]{2,}/g, ' '); // Replace multiple spaces with single ones
271 searchTerm = searchTerm.trim(); // Remove leading and trailing whitespaces
272 searchTerm = searchTerm.toLowerCase();
273 return searchTerm;
274 },
275
276 // Clean up a URL
277 cleanUpUrl: function(url) {
278 var pathName = url.replace(/[?#]{1}.*/, '');
279 var queryString = (url.indexOf('?') > -1) ? url.replace(/(.*?)(\?[^#]*)(.*)/, '$2') : '';
280 var hash = (url.indexOf('#') > -1) ? url.replace(/(.*?)(\#.*)/, '$2') : '';
281 var thisPageType = FI_Scripts.extractPageType(url);
282
283 pathName = pathName.replace(/\/$/, '');
284
285 queryString = queryString.replace(/[?&]fi=[^&]+/,''); // Remove FoundIt tracking
286 queryString = queryString.replace(/[?&](utm_source|utm_medium|utm_campaign|cm_mmc|gclid|gclsrc|pp|epik|CAWELAID)=[^$]*/gi,''); // Remove tracking parameters
287 queryString = queryString.replace(/[?&](page|pageNo)=[^&]+/gi,''); // Remove pagination
288
289 // Category page
290 if (thisPageType == 'Category') {
291 pathName = pathName.replace(/\/\//,'\/');
292 queryString = '';
293 hash = hash.replace(/(#[^&]*)&.*/, '$1'); // Remove any non-facet additional stuff
294 hash = hash.replace(/#(?!facet).*/, ''); // Remove everything but facet from hash
295 hash = hash.replace(/ /, ',');
296 var facetsToRemove = [
297 '-7000000000000135620' // Size
298 ,'-1046' // Rating
299 ,'-1050494951535058' // Promotion
300 ,'11211410599101957166805840123' // Price range
301 ];
302 var regEx = new RegExp( '(' + facetsToRemove.join('|') + ')[0-9]+[,]?' , 'g' );
303 hash = hash.replace(regEx, '');
304 hash = hash.replace(/(#facet:|,)$/, ''); // Remove leftover empty facet or comma
305 }
306
307 // Search page
308 else if (thisPageType == 'Search') {
309 var searchString = '', facets = '';
310 var searchStringMatches = queryString.match(/searchTerm=(.*?)([&:][^ +]+|$)/i); // Extract search string
311 if (searchStringMatches && searchStringMatches.length > 1) {
312 searchString = searchStringMatches[1]; // Extract first group match
313 searchString = searchString.replace(/[+]/g, ' '); // Replace plus signs with spaces
314 searchString = searchString.replace(/%20/g, ' '); // Replace %20 with spaces
315 searchString = FI_Scripts.cleanUpSearchTerm(searchString);
316 searchString = searchString.replace(/[ ]/g, '+'); // Replace spaces with plus signs
317 if (queryString.indexOf('&') !== -1) {
318 facets = queryString.substring(queryString.indexOf('&'), queryString.length);
319 facets = facets.replace(/&(promotionalText|productSizes|roundedReviewScore|sortBy|orderBy)[^&]*/gi, '');
320 }
321 queryString = '?searchTerm=' + searchString.toLowerCase() + facets;
322 }
323 hash = '';
324 }
325
326 // Product page
327 else if (thisPageType == 'Product') {
328 if (pathName.indexOf('/details/') > -1) {
329 var productIdRegExMatches = pathName.match(/(.*?\/details\/[0-9]+)/);
330 if (productIdRegExMatches && productIdRegExMatches.length > 1) {
331 pathName = productIdRegExMatches[1];
332 queryString = '';
333 }
334 }
335 else if (pathName.indexOf('/products') > -1) {
336 pathName = '/products';
337 queryString = queryString.replace(/(product_id=[0-9]*)(.*)/, '$1');
338 }
339 hash = '';
340 }
341
342 // Unknown page
343 else {
344 pathName = '';
345 queryString = '';
346 hash ='';
347 }
348
349 return pathName + queryString + hash;
350 },
351
352 // Get the page type for the current page
353 getThisPageType: function() {
354 return FI_Scripts.extractPageType(window.location.pathname);
355 },
356
357 // Get a clean URL for the current page
358 getThisPageUrl: function() {
359 var baseUrl = window.location.protocol + '//' + window.location.hostname;
360 var pathName = unescape(window.location.pathname);
361 var queryString = unescape(window.location.search);
362 var hash = unescape(window.location.hash);
363 var url = baseUrl + FI_Scripts.cleanUpUrl(pathName + queryString + hash);
364 return url;
365 },
366
367 postRenderScripts: function() {
368 var i;
369 // Add links click event listener
370 var linkElems = document.getElementsByClassName('fi-link');
371 for (i = 0; i < linkElems.length; i++) {
372 var linkElem = linkElems[i];
373 linkElem.addEventListener('click', function(e) {
374 if (this.hasAttribute('data-stop')) {
375 e.stopPropagation();
376 }
377 FI_Core.gaTrackLinkClick(this.getAttribute('data-tracking'), this.getAttribute('data-page-type'));
378 });
379 }
380
381 // Add listeners to arrow elements
382 var arrowElements = document.querySelectorAll('.fi-arrow');
383 for (i = 0; i < arrowElements.length; i++) {
384 arrowElements[i].addEventListener('click', FI_Core.onArrowClick);
385 }
386
387 // Add listeners to list elements
388 var listElements = document.querySelectorAll('.fi-list-scrollable');
389 for (i = 0; i < listElements.length ; i++) {
390 listElements[i].addEventListener('scroll', function() {
391 FI_Core.renderArrows(this);
392 FI_Scripts.adjustNoScrollStyle();
393 });
394 FI_Core.renderArrows(listElements[i]);
395 }
396
397 // Category/Search - Change style for minimum number of links
398 var scrollableElements = document.querySelectorAll('ul.fi-list-scrollable li.fi-plp-main__item:not(.fi-plp-main__item-dummy)');
399 if (scrollableElements.length <= FI_Config.categoryPageItemsInCarousel) {
400 var dummyScrollableElements = document.querySelectorAll('ul.fi-list-scrollable li.fi-plp-main__item-dummy');
401 for (i = 0; i < dummyScrollableElements.length ; i++) {
402 dummyScrollableElements[i].outerHTML = '';
403 }
404 var navElements = document.querySelectorAll('.fi-plp-main__nav');
405 for (i = 0; i < navElements.length ; i++) {
406 navElements[i].classList.add('min-links-or-less');
407 }
408 }
409
410 if (FI_Config.productTabs) {
411 var tabHeader = document.querySelector('.fi-pdp-pw__tab-headers');
412 FI_Core.attachDrawScroll(tabHeader);
413
414 var tabHeadingElements = document.querySelectorAll('.fi-pdp-pw__tab-heading');
415 for (i = 0; i < tabHeadingElements.length; i++) {
416 tabHeadingElements[i].addEventListener('click', FI_Core.openTab);
417 }
418
419 // Product - Change style for minimum number of links
420 var j;
421 var tabContainerElements = document.querySelectorAll('.fi-pdp-pw__tab-content-container');
422 for (i = 0; i < tabContainerElements.length ; i++) {
423 var scrollableElements = tabContainerElements[i].querySelectorAll('.fi-pdp-pw__product_card-ext:not(.fi-pdp-pw__product_card-ext-dummy)');
424 if (scrollableElements.length <= FI_Config.productTabsItemsInCarousel) {
425 var dummyScrollableElements = tabContainerElements[i].querySelectorAll('.fi-pdp-pw__product_card-ext-dummy');
426 for (j = 0; j < dummyScrollableElements.length ; j++) {
427 dummyScrollableElements[j].outerHTML = '';
428 }
429 tabContainerElements[i].classList.add('min-links-or-less');
430 }
431 }
432
433 FI_Scripts.adjustNoScrollStyle();
434 FI_Core.activateTab(1);
435 }
436
437 var pdpCarousel = document.querySelector('.fi-plp-main__list');
438 FI_Core.attachDrawScroll(pdpCarousel);
439
440 // Custom image positioning
441 var images = document.querySelectorAll('.fi-image');
442 for (var i=0; i< images.length; i++) {
443 var src = images[i].src;
444
445 if (src.indexOf('#') > 0) {
446 var pairs = src.substring(src.indexOf('#') + 1).split('&');
447 var bgColour = pairs[0].split('=')[1];
448 var margin = pairs[1].split('=')[1];
449 var scale = (pairs.length > 2) ? pairs[2].split('=')[1] : null;
450
451 if (margin && margin.length > 0) images[i].style.cssText += 'margin-top: ' + margin + 'px;';
452 if (scale && scale.length > 0) images[i].style.cssText += 'transform: scale(' + scale + ');';
453 if (bgColour && bgColour.length > 0) images[i].parentElement.style.cssText += 'background-color: #' + bgColour + ';';
454 images[i].src = src.substring(0, src.indexOf('#'));
455 }
456 }
457
458 },
459
460 adjustNoScrollStyle: function() {
461 var tabContentElements = document.querySelectorAll('.fi-pdp-pw__tab-content');
462 for (var i = 0; i < tabContentElements.length; i++) {
463 var tabContentElem = tabContentElements[i];
464 tabContentElem.style.display = 'block';
465 var tabScrollableElem = tabContentElem.querySelector('.fi-pdp-pw__content');
466 if (tabScrollableElem.scrollWidth <= tabScrollableElem.clientWidth) {
467 tabScrollableElem.classList.remove('fi-list-scrollable');
468 }
469 tabContentElem.style.display = '';
470 }
471 },
472
473 ellipsizeDescriptions: function() {
474 var tabContentElements = document.querySelectorAll('.fi-pdp-pw__tab-content');
475 for (var i = 0; i < tabContentElements.length; i++) {
476 var tabContentElem = tabContentElements[i];
477 tabContentElem.style.display = 'block';
478 var descriptionElements = tabContentElem.querySelectorAll('.fi-pdp-pw__product_description');
479 for (var j = 0; j < descriptionElements.length; j++) {
480 FI_Scripts.ellipsizeContent(descriptionElements[j]);
481 }
482 tabContentElem.style.display = '';
483 }
484 },
485
486 ellipsizeContent: function(element) {
487 var wordArray = element.innerHTML.split(' ');
488 while (element.scrollHeight > element.offsetHeight) {
489 wordArray.pop();
490 element.innerHTML = wordArray.join(' ') + '...';
491 }
492 },
493
494 cleanup: function() {
495 var elements = document.querySelectorAll('[class^="fi-"], [data-id="fi-style"]');
496 for (var i = 0; i < elements.length; i++) {
497 elements[i].outerHTML = '';
498 }
499
500 var slots = FI_Config.slots, slot, s;
501 if (slots) {
502 for (s = 0; s < slots.length; s++) {
503 slot = slots[s];
504 if (slot.element) {
505 slot.element = null;
506 }
507 }
508 }
509 },
510
511 ajaxHandler: function(evt){
512 var currentPageUrl = FI_Scripts.getThisPageUrl();
513 if (currentPageUrl !== FI_Config.thisPageUrl) {
514 FI_Config.thisPageUrl = currentPageUrl;
515 FI_Config.thisPageType = FI_Scripts.getThisPageType();
516 FI_Scripts.cleanup();
517 FI_Core.init();
518 }
519 },
520
521 ajaxObserver: null
522
523};
524
525
526/* FoundIt! Integration Core - Boots version */
527
528window.FI_Core = {
529 version: '1.2.1',
530
531 //--- API Settings ---
532 api: {
533 url: 'https://rtapi.foundit.com',
534 page: '/page/',
535 product: '/product',
536 },
537
538 //--- Load ---
539 load: function() {
540 if (document.readyState === "interactive" || document.readyState === "complete" || document.readyState === "loaded") {
541 FI_Core.init();
542 }
543 else {
544 document.addEventListener('DOMContentLoaded', FI_Core.init, true);
545 }
546 },
547
548 //--- Initialise ---
549 init: function() {
550 if (FI_Scripts.noRunFlag()) return;
551 if (!FI_Config.thisPageType) FI_Config.thisPageType = FI_Scripts.getThisPageType();
552 if (FI_Config.abortOnUnknownPageType && !FI_Config.thisPageType) return;
553 if (!FI_Config.thisPageUrl) FI_Config.thisPageUrl = FI_Scripts.getThisPageUrl();
554 if (FI_Scripts.initScripts) FI_Scripts.initScripts();
555 var xhr = FI_Core.request('GET', FI_Core.api.url + FI_Core.api.page + FI_Config.foundItApiProgramCode + '/' + FI_Core.urlEncode(FI_Config.thisPageUrl));
556 if (!xhr) {
557 FI_Core.gaTrackEvent('api-error-noxhr', FI_Config.thisPageUrl, true);
558 return;
559 }
560 if (FI_Config.requestTimeout) xhr.timeout = FI_Config.requestTimeout;
561 xhr.onloadstart = function() {
562 FI_Core.gaTrackEvent('api-request', FI_Config.thisPageUrl, true);
563 };
564 xhr.onabort = function() {
565 FI_Core.gaTrackEvent('api-abort', FI_Config.thisPageUrl, true);
566 };
567 xhr.onerror = function() {
568 FI_Core.gaTrackEvent('api-error-xhr', FI_Config.thisPageUrl, true);
569 };
570 xhr.ontimeout = function() {
571 FI_Core.gaTrackEvent('api-timeout', FI_Config.thisPageUrl, true);
572 };
573 xhr.onload = function(e) {
574 if (e.currentTarget.status == 200) {
575 try {
576 var data = JSON.parse(xhr.responseText);
577 FI_Core.gaTrackEvent('api-success', FI_Config.thisPageUrl, true);
578 }
579 catch(ex) {
580 FI_Core.gaTrackEvent('api-error-json', FI_Config.thisPageUrl, true);
581 }
582 if (data) {
583 FI_Core.render(data);
584 }
585 }
586 else {
587 FI_Core.gaTrackEvent('api-error-http-' + e.currentTarget.status, FI_Config.thisPageUrl, true);
588 }
589 };
590 xhr.send();
591 },
592
593
594 //--- Analytics events queue ---
595 gaEventsQueue: [],
596
597
598
599 //--- Track FoundIt! links click ---
600 gaTrackLinkClick: function(trackLinkClickString, pageTypeString) {
601 trackLinkClickString = typeof trackLinkClickString !== 'undefined' ? trackLinkClickString : 'noTrackingString';
602 FI_Core.gaTrackEvent('links-click', trackLinkClickString, false, pageTypeString);
603 },
604
605
606
607 //--- Google Analytics event tracking ---
608 gaTrackEvent: function(eventAction, eventLabel, nonInteractionFlagValue, customDimensionValue) {
609 if (FI_Config.disableTrackingEntirely) return;
610 if (typeof FI_Config.trackingEnabledEvents !== 'undefined' && FI_Config.trackingEnabledEvents.indexOf(eventAction) === -1) return;
611 var fieldsObject = {};
612 fieldsObject['transport'] = 'beacon';
613 fieldsObject['nonInteraction'] = typeof nonInteractionFlagValue !== 'undefined' ? nonInteractionFlagValue : true;
614 if (FI_Config.gaClientTrackingCustomDimensionIndex && customDimensionValue !== 'undefined') {
615 fieldsObject['dimension' + FI_Config.gaClientTrackingCustomDimensionIndex] = customDimensionValue;
616 }
617 FI_Core.gaEventsQueue.push({eventAction: eventAction, eventLabel: eventLabel, fieldsObject: fieldsObject});
618 FI_Core.gaEventsQueueSend();
619 },
620
621
622
623 //--- Analytics events queue send ---
624 gaEventsQueueSend: function() {
625 var gaTrackerName = (FI_Config.gaClientTrackingTrackerName) ? FI_Config.gaClientTrackingTrackerName : FI_Core.gaGetTrackerName();
626 if (FI_Config.gaClientTrackingFunction() && gaTrackerName) {
627 for (i = 0; i < FI_Core.gaEventsQueue.length; i++) {
628 FI_Config.gaClientTrackingFunction()(
629 gaTrackerName + '.' + 'send'
630 ,'event'
631 ,FI_Config.gaClientTrackingEventCategory
632 ,FI_Core.gaEventsQueue[i]['eventAction']
633 ,FI_Core.gaEventsQueue[i]['eventLabel']
634 ,1
635 ,FI_Core.gaEventsQueue[i]['fieldsObject']
636 );
637 }
638 FI_Core.gaEventsQueue.length = 0;
639 }
640 else {
641 if (FI_Core.gaQueueSendTimeout) clearTimeout(FI_Core.gaQueueSendTimeout);
642 FI_Core.gaQueueSendTimeout = setTimeout(FI_Core.gaEventsQueueSend, 500);
643 }
644 },
645
646
647
648 //--- Get main Analytics tracker name ---
649 gaGetTrackerName: function() {
650 try {
651 if (FI_Config.gaClientTrackingFunction() && FI_Config.gaClientTrackingFunction().getAll().length > 0) {
652 return FI_Config.gaClientTrackingFunction().getAll()[0].b.data.values[':name'];
653 }
654 return null;
655 }
656 catch (ex) {
657 return null;
658 }
659 },
660
661
662
663 //--- URL: Encode ---
664 urlEncode: function(url) {
665 return encodeURIComponent(encodeURIComponent(url));
666 },
667
668
669
670 //--- Request: Cross-Origin Resource Sharing ---
671 request: function(method, url) {
672 var xhr = new XMLHttpRequest();
673 if ('withCredentials' in xhr) {
674 xhr.open(method, url, true);
675 } else if (typeof XDomainRequest != 'undefined') {
676 xhr = new XDomainRequest();
677 xhr.open(method, url);
678 } else {
679 xhr = null;
680 }
681 return xhr;
682 },
683
684
685
686 //--- Attach Element ---
687 attachElementTo: function(elem, target, attach) {
688 switch(attach) {
689 case 'before':
690 target.parentNode.insertBefore(elem, target);
691 break;
692 case 'after':
693 target.parentNode.insertBefore(elem, target.nextSibling);
694 break;
695 case 'prepend':
696 target.insertBefore(elem, target.childNodes[0]);
697 break;
698 default:
699 target.appendChild(elem);
700 }
701 return elem;
702 },
703
704
705
706 //--- Create Slot ---
707 createSlot: function(slot) {
708 var target = document.querySelector(slot.target),
709 elem;
710 if (!target) return;
711 elem = document.createElement('div');
712 elem.className = 'fi-slot fi-slot--' + slot.id;
713 elem.setAttribute('id', 'fi-' + slot.id);
714 return FI_Core.attachElementTo(elem, target, slot.attach);
715 },
716
717 //--- Checks slot type ---
718 isMobileSlot: function(slot) {
719 return slot && /-mobile$/.test(slot.id)
720 },
721
722 //--- Template: Links ---
723 templateLinks: function(slot, links) {
724 var html = '',
725 template = FI_Config.templates[slot.template].html,
726 l,
727 link,
728 separator,
729 trackingUrlParameter = '',
730 destinationUrl,
731 trackLinkClickString,
732 linksContainerName;
733
734 var numberOfItemsInCarousel = FI_Config.categoryPageItemsInCarousel;
735 var linksOrigLength = links.length
736
737 html += template.wrapStart || '';
738 if (slot.title && template.heading) {
739 html += template.heading.replace('#{title}', slot.title);
740 }
741 html += template.listStart || '';
742
743 //extends array to the nearest number divisible by numberOfItemsInCarousel
744 if (!FI_Core.isMobileSlot(slot) && (linksOrigLength % numberOfItemsInCarousel !== 0)) {
745 links = links.concat(
746 FI_Core.newFilledArray(
747 numberOfItemsInCarousel - (linksOrigLength % numberOfItemsInCarousel),
748 { isDummy: true }));
749 }
750
751 for (l = 0; l < links.length; l++) {
752 link = links[l];
753 if(link.isDummy) {
754 html += template.dummyItem
755 } else {
756 if (!FI_Config.disableTrackingUrlParameter) {
757 separator = (link.DestinationUrl.indexOf('?') === -1) ? '?' : '&';
758 trackingUrlParameter = separator + 'fi=' + FI_Config.thisPageType.substr(0, 1).toLowerCase();
759 if (link.DestinationUrl.indexOf('#') === -1) destinationUrl = link.DestinationUrl + trackingUrlParameter;
760 else destinationUrl = link.DestinationUrl.substring(0, link.DestinationUrl.indexOf('#')) + trackingUrlParameter + link.DestinationUrl.substring(link.DestinationUrl.indexOf('#'), link.DestinationUrl.length);
761 }
762
763 linksContainerName = slot.key.split(' ').join('-');
764 trackLinkClickString = FI_Config.thisPageUrl + '|' + FI_Config.thisPageType + '|' + linksContainerName + '|' + link.Order + '|' + links.length + '|' + link.AnchorText.replace(/"/g, '"') + '|' + link.DestinationUrl;
765 html += template.item
766 .replace('#{url}', destinationUrl)
767 .replace('#{text}', link.AnchorText)
768 .replace('#{imageurl}', link.ImageUrl)
769 .replace('#{trackLinkClickString}', trackLinkClickString)
770 .replace('#{pageTypeString}', FI_Config.thisPageType);
771 }
772 }
773 html += template.listEnd || '';
774 html += template.wrapEnd || '';
775 return html;
776 },
777
778 formatPrice: function(currencySymbol, price) {
779 return currencySymbol + ('' + price).replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,");
780 },
781 //--- Template: Products ---
782 templateProducts: function(slot, json) {
783 var html = '',
784 tabHeaders = '',
785 tabContents = '',
786 separator,
787 template = FI_Config.templates[slot.template].html,
788 linksContainerName = slot.key.split(' ').join('-');
789
790 html += template.wrapStart || '';
791 html += template.headingStart || '';
792
793 if (slot.title) {
794 html = html.replace('#{title}', slot.title);
795 }
796
797 var maxTabs = Math.min(FI_Config.productTabsMaxTabs, json.length);
798 var numberOfItemsInCarousel = FI_Config.productTabsItemsInCarousel;
799
800 for (var i=0, tabId=1; i<maxTabs; i++) {
801 var productsCountOrig = json[i].products.length;
802 if (productsCountOrig >= FI_Config.productTabsMinProducts) {
803 var products = json[i].products
804 if((productsCountOrig % numberOfItemsInCarousel) !== 0) {
805 products = products.concat(
806 FI_Core.newFilledArray(
807 numberOfItemsInCarousel - (productsCountOrig % numberOfItemsInCarousel),
808 { isDummy: true }));
809 }
810 tabHeaders += template.heading.replace('#{id}', tabId)
811 .split('#{heading}')
812 .join(json[i].Title);
813 tabContents += template.listStart.replace('#{id}', tabId);
814
815 for (var j=0; j<products.length; j++) {
816 if(products[j].isDummy) {
817 tabContents += template.dummyItem
818 } else {
819 var productTrackLinkClickString = FI_Config.thisPageUrl + '|' + FI_Config.thisPageType + '|' + linksContainerName + '|' + j + '|' + json.length + '|' + json[i].Title.replace(/"/g, '"') + '|' + json[i].products[j].DestinationUrl;
820
821 destinationUrl = products[j].DestinationUrl;
822
823 if (!FI_Config.disableTrackingUrlParameter) {
824 separator = (destinationUrl.indexOf('?') === -1) ? '?' : '&';
825 if (FI_Config.thisPageType == "Product")
826 destinationUrl += separator + 'fi=' + "wp";
827 }
828
829 var price = products[j].Price ? parseFloat(products[j].Price.substr(1)) : NaN;
830 var currencySymbol = products[j].Price.substr(0, 1);
831 var salePrice = products[j].SalePrice ? parseFloat(products[j].SalePrice.substr(1)) : NaN;
832
833 var isSalePriceSet = !isNaN(price) && !isNaN(salePrice) && salePrice > 0 && salePrice < price;
834
835 tabContents += template.item
836 .split('#{title}').join(products[j].Title)
837 .split('#{productId}').join(products[j].Id)
838 .split('#{href}').join(destinationUrl)
839 .replace('#{imageUrl}', products[j].ImageUrl)
840 .replace('#{price}', FI_Core.formatPrice(currencySymbol, price))
841 .replace('#{brand}', products[j].Brand)
842 .replace('#{trackLinkClickString}', productTrackLinkClickString)
843 .replace('#{pageTypeString}', FI_Config.thisPageType)
844 .replace('#{salePrice}', isSalePriceSet ? FI_Core.formatPrice(currencySymbol, Math.ceil(salePrice)) : '')
845 .replace('#{discountPercentage}', isSalePriceSet ? Math.round(100 * (price - salePrice) / price) + '% OFF' : '')
846 .replace('fi-pdp-pw__price"', isSalePriceSet ? 'fi-pdp-pw__price fi-pdp-pw__with-sale-price"' : 'fi-pdp-pw__price"');
847 }
848 }
849
850 var trackLinkClickString = FI_Config.thisPageUrl + '|' + FI_Config.thisPageType + '|' + linksContainerName + '|' + i + '|' + json.length + '|' + json[i].Title.replace(/"/g, '"') + '|' + json[i].DestinationUrl;
851
852 destinationUrl = json[i].DestinationUrl;
853
854 if (!FI_Config.disableTrackingUrlParameter && destinationUrl > "") {
855 separator = (destinationUrl.indexOf('?') === -1) ? '?' : '&';
856 if (FI_Config.thisPageType == "Product")
857 destinationUrl += separator + 'fi=' + "wc";
858 }
859
860 tabContents += template.listEnd
861 .replace('#{text}', json[i].Title)
862 .replace('#{url}', destinationUrl)
863 .replace('#{trackLinkClickString}', trackLinkClickString)
864 .replace('#{pageTypeString}', FI_Config.thisPageType);
865 tabId++;
866 }
867 }
868
869 html += tabHeaders;
870
871 html += template.headingEnd;
872
873 html += tabContents;
874
875 html += template.wrapEnd || '';
876
877 if (tabId > FI_Config.productTabsMinTabs) { return html; }
878 else { return null; }
879 },
880
881
882 //--- Render ---
883 render: function(data) {
884 var slots = FI_Config.slots, slot, s,
885 linkLists = data.Links, linkList, l,
886 rendered;
887 if (linkLists && slots) {
888 for (s = 0; s < slots.length; s++) {
889 slot = slots[s];
890 linkList = linkLists[slot.key];
891 if (linkList) {
892 if (!slot.element) {
893 slot.element = FI_Core.createSlot(slot);
894 if (!slot.element) continue;
895 }
896 if (FI_Config.thisPageType == 'Product' && FI_Config.productTabs) {
897 // If at least one tab is present render, otherwise remove container element
898 var templateProductsContent = FI_Core.templateProducts(slot, linkList);
899 if (templateProductsContent) {
900 slot.element.innerHTML = templateProductsContent;
901 }
902 else {
903 slot.element.parentNode.removeChild(slot.element);
904 }
905 }
906 else {
907 slot.element.innerHTML = FI_Core.templateLinks(slot, linkList);
908 }
909 rendered = true;
910 }
911 }
912 }
913 else {
914 FI_Core.gaTrackEvent('links-no-links', FI_Config.thisPageUrl, true);
915 }
916 if (rendered) {
917 FI_Core.gaTrackEvent('links-rendered', FI_Config.thisPageUrl, true);
918 if (document.querySelector('style[data-id="fi-style"]') == null) {
919 var elem = document.createElement('style');
920 elem.setAttribute('data-id', 'fi-style');
921 elem.innerHTML = FI_Config.styles.join(' ');
922 FI_Core.attachElementTo(elem, document.body);
923 }
924 FI_Scripts.postRenderScripts();
925 }
926 else {
927 FI_Core.gaTrackEvent('links-not-rendered', FI_Config.thisPageUrl, true);
928 }
929 },
930
931 openTab: function(evt) {
932 var tabId = evt.currentTarget.getAttribute('fi-pw-tab-id');
933 FI_Core.activateTab(tabId);
934 FI_Core.gaTrackEvent('open-tab', evt.currentTarget.innerText, false);
935 },
936
937 activateTab: function(tabId) {
938 var i, tabHeadingElements, tabContentElements, tabIdElements;
939
940 // Hide all tab heading elements
941 tabHeadingElements = document.querySelectorAll('.fi-pdp-pw__tab-heading');
942 for (i = 0; i < tabHeadingElements.length; i++) {
943 tabHeadingElements[i].classList.remove('fi-pw-tab-active');
944 }
945
946 // Hide all tab content elements
947 tabContentElements = document.querySelectorAll('.fi-pdp-pw__tab-content');
948 for (i = 0; i < tabContentElements.length; i++) {
949 tabContentElements[i].classList.remove('fi-pw-tab-active');
950 }
951
952 // Make current tab active in all containers
953 tabIdElements = document.querySelectorAll('div[fi-pw-tab-id="' + tabId + '"]');
954 for (i = 0; i < tabIdElements.length; i++) {
955 tabIdElements[i].classList.add('fi-pw-tab-active');
956 if (tabIdElements[i].classList.contains('fi-pdp-pw__tab-content')) {
957 FI_Core.renderArrows(tabIdElements[i].querySelector('.fi-pdp-pw__content'));
958 }
959 }
960
961 var scrollableElement = document.querySelector(".fi-pdp-pw__tab-content.fi-pw-tab-active .fi-list-scrollable");
962 FI_Core.attachDrawScroll(scrollableElement);
963 },
964
965 easeInOutQuad: function (t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t },
966
967 scrollInProgress: false,
968
969 sideScroll: function(element, distance, duration){
970 if (FI_Core.scrollInProgress) return;
971
972 FI_Core.scrollInProgress = true;
973
974 var stop = false;
975
976 var startx = Math.ceil(element.scrollLeft);
977 var distanceSign = distance && distance / Math.abs(distance);
978 var distanceCeil = distanceSign * Math.ceil(Math.abs(distance));
979 var destx = startx + distance;
980
981 var start = null;
982
983 function startAnim(timeStamp) {
984 start = timeStamp;
985 draw(timeStamp);
986 }
987
988 function draw(now) {
989 if (stop) {
990 FI_Core.scrollInProgress = false;
991 return;
992 }
993
994 if (now - start >= duration) stop = true;
995
996 var p = (now - start) / duration;
997 val = FI_Core.easeInOutQuad(p);
998 var shiftDistance = stop ? distanceCeil : (destx - startx) * val
999
1000 element.scrollLeft = startx + shiftDistance
1001 requestAnimationFrame(draw);
1002 }
1003
1004 requestAnimationFrame(startAnim);
1005 },
1006
1007 onArrowClick: function(e) {
1008 if (this.classList.contains('fi-arrow-active')) {
1009 var container = this.parentNode.querySelector('.fi-list-scrollable');
1010
1011 if (!container) return;
1012
1013 var direction = this.getAttribute('fi-arrow-direction');
1014
1015 var distanceToRightBorder = container.scrollWidth - container.clientWidth - container.scrollLeft;
1016 var distanceToLeftBorder = container.scrollLeft;
1017 var remaingDistance = direction === 'left' ? distanceToLeftBorder : distanceToRightBorder;
1018
1019 var directionSign = direction === 'left' ? -1 : 1;
1020 var scrollDistance = container.clientWidth;
1021
1022 var adjustedDistance = Math.abs(scrollDistance - remaingDistance);
1023
1024 if(adjustedDistance < 10) scrollDistance = Math.max(scrollDistance, remaingDistance)
1025
1026 FI_Core.sideScroll(container, directionSign * (scrollDistance), 1000);
1027 }
1028 e.stopPropagation()
1029 },
1030
1031 renderArrows: function(scrollElement) {
1032 var arrowActiveClassName = 'fi-arrow-active';
1033 var scrollElementParent = scrollElement.parentNode;
1034 var leftArrow = scrollElementParent.querySelector('.fi-arrow-left');
1035 var rightArrow = scrollElementParent.querySelector('.fi-arrow-right');
1036
1037 if (scrollElement.scrollLeft == 0) {
1038 leftArrow.classList.remove(arrowActiveClassName);
1039 }
1040 else if (scrollElement.scrollLeft > 0) {
1041 leftArrow.classList.add(arrowActiveClassName);
1042 }
1043
1044 if (Math.ceil(scrollElement.scrollLeft + scrollElement.clientWidth) >= scrollElement.scrollWidth) {
1045 rightArrow.classList.remove(arrowActiveClassName);
1046 }
1047 else {
1048 rightArrow.classList.add(arrowActiveClassName);
1049 }
1050 },
1051
1052 drawScrollDisposable: {},
1053
1054 attachDrawScroll: function(el) {
1055 var initPageX = 0, lastPosX = 0, mouseDownTimestamp = 0, drag = false;
1056
1057 if (!el || !el.className) return;
1058
1059 if (FI_Core.drawScrollDisposable[el.className]) {
1060 FI_Core.drawScrollDisposable[el.className]();
1061 FI_Core.drawScrollDisposable[el.className] = null;
1062 }
1063
1064 var dragScrollMouseDown = function(e) {
1065 initPageX = lastPosX = e.pageX;
1066 drag = true;
1067 mouseDownTimestamp = Date.now();
1068 };
1069 var dragScrollMouseUp = function(_) { drag = false };
1070 var dragScrollMouseLeave = function(e) {
1071 if (e.target.className.indexOf(el.className) !== -1) {
1072 drag = false
1073 }
1074 };
1075 var dragScrollMouseMove = function(e) {
1076 if (!drag) return;
1077 var diffX = e.pageX - lastPosX;
1078 lastPosX = e.pageX
1079 el.scrollLeft -= diffX * 2
1080 }
1081 var dragScrollClick = function(e) {
1082 if((Date.now() - mouseDownTimestamp > 350) || Math.abs(initPageX - e.pageX) > 5) {
1083 e.stopPropagation()
1084 e.preventDefault()
1085 }
1086 }
1087
1088 el.addEventListener('mousedown', dragScrollMouseDown, true);
1089 el.addEventListener('mouseup', dragScrollMouseUp, true);
1090 el.addEventListener('mouseleave', dragScrollMouseLeave, true);
1091 el.addEventListener('mousemove', dragScrollMouseMove, true);
1092 el.addEventListener('click', dragScrollClick, true);
1093
1094 FI_Core.drawScrollDisposable[el.className] = function () {
1095 el.removeEventListener('mousedown', dragScrollMouseDown, true);
1096 el.removeEventListener('mouseup', dragScrollMouseUp, true);
1097 el.removeEventListener('mouseleave', dragScrollMouseLeave, true);
1098 el.removeEventListener('mousemove', dragScrollMouseMove, true);
1099 el.removeEventListener('click', dragScrollClick, true);
1100 }
1101 },
1102
1103 newFilledArray: function(len, val) {
1104 var rv = new Array(len);
1105 while (--len >= 0) {
1106 rv[len] = val;
1107 }
1108 return rv;
1109 }
1110};
1111
1112FI_Core.load();