PageSourceSearch

https://thelangleyhouston.com/wp-content/plugins/rentfetch/js/rent…h-blaze-floorplan-images-init.js?ver=0.39.6

js thelangleyhouston.com collected 2026-10-08 19:15:30 UTC 12,399 bytes, 380 lines download raw bytes

1(function () {
2	'use strict';
3
4	var cornerInset = 5;
5	var cornerColorTolerance = 8;
6	var classificationCache = new Map();
7
8	function rentfetchColorsMatch(first, second) {
9		return first.slice(0, 4).every(function (channel, index) {
10			return Math.abs(channel - second[index]) <= cornerColorTolerance;
11		});
12	}
13
14	function rentfetchFindMatchingCornerColor(colors) {
15		for (var index = 0; index < colors.length; index++) {
16			var matches = colors.filter(function (color) {
17				return rentfetchColorsMatch(colors[index], color);
18			});
19
20			if (matches.length >= 3) {
21				return colors[index];
22			}
23		}
24
25		return null;
26	}
27
28	function rentfetchSampleImageCorners(image) {
29		var canvas = document.createElement('canvas');
30		var context = canvas.getContext('2d', { willReadFrequently: true });
31		var width = image.naturalWidth;
32		var height = image.naturalHeight;
33
34		if (!context || width <= cornerInset * 2 || height <= cornerInset * 2) {
35			return null;
36		}
37
38		canvas.width = 4;
39		canvas.height = 1;
40		context.fillStyle = '#fff';
41		context.fillRect(0, 0, 4, 1);
42
43		var points = [
44			[cornerInset, cornerInset],
45			[width - cornerInset - 1, cornerInset],
46			[cornerInset, height - cornerInset - 1],
47			[width - cornerInset - 1, height - cornerInset - 1],
48		];
49		var colors = points.map(function (point, index) {
50			context.drawImage(image, point[0], point[1], 1, 1, index, 0, 1, 1);
51			return Array.from(context.getImageData(index, 0, 1, 1).data);
52		});
53		var matchingColor = rentfetchFindMatchingCornerColor(colors);
54
55		return matchingColor
56			? { contained: true, color: 'rgb(' + matchingColor.slice(0, 3).join(', ') + ')' }
57			: { contained: false, color: null };
58	}
59
60	function rentfetchClassifyFloorplanImage(source) {
61		return new Promise(function (resolve) {
62			var image = new Image();
63
64			try {
65				if (new URL(source, window.location.href).origin !== window.location.origin) {
66					image.crossOrigin = 'anonymous';
67				}
68			} catch (error) {
69				resolve(null);
70				return;
71			}
72
73			image.onload = function () {
74				try {
75					resolve(rentfetchSampleImageCorners(image));
76				} catch (error) {
77					resolve(null);
78				}
79			};
80			image.onerror = function () {
81				resolve(null);
82			};
83			image.src = source;
84		});
85	}
86
87	function rentfetchGetFloorplanImageClass(classification) {
88		if (!classification) {
89			return '';
90		}
91
92		return classification.contained ? 'is-contained-image' : 'is-photo-image';
93	}
94
95	function rentfetchApplyFloorplanImageClassification(sliderElement, index, classification) {
96		var elements = sliderElement.querySelectorAll('[data-floorplan-image-index="' + index + '"]');
97		var className = rentfetchGetFloorplanImageClass(classification);
98
99		if (!className) {
100			return;
101		}
102
103		elements.forEach(function (element) {
104			element.classList.remove('is-contained-image', 'is-photo-image');
105			element.classList.add(className);
106			if (classification.color) {
107				element.style.setProperty('--rentfetch-floorplan-image-background', classification.color);
108			} else {
109				element.style.removeProperty('--rentfetch-floorplan-image-background');
110			}
111		});
112	}
113
114	function rentfetchGetFloorplanImageClassification(source) {
115		if (!classificationCache.has(source)) {
116			classificationCache.set(source, rentfetchClassifyFloorplanImage(source));
117		}
118
119		return classificationCache.get(source);
120	}
121
122	function rentfetchInitializeFloorplanSingleImage(container) {
123		var image = container.querySelector('img');
124		if (!image) {
125			return;
126		}
127
128		rentfetchGetFloorplanImageClassification(image.currentSrc || image.src).then(function (classification) {
129			var className = rentfetchGetFloorplanImageClass(classification);
130			if (!className) {
131				return;
132			}
133
134			container.classList.remove('is-contained-image', 'is-photo-image');
135			container.classList.add(className);
136			if (classification.color) {
137				container.style.setProperty('--rentfetch-floorplan-image-background', classification.color);
138			} else {
139				container.style.removeProperty('--rentfetch-floorplan-image-background');
140			}
141		});
142	}
143
144	function rentfetchClassifyFloorplanSingleImages(root) {
145		(root || document).querySelectorAll('.floorplan-single-image-wrap').forEach(rentfetchInitializeFloorplanSingleImage);
146	}
147
148	function rentfetchImageLoads(source) {
149		return new Promise(function (resolve) {
150			var image = new Image();
151			image.onload = function () {
152				resolve(true);
153			};
154			image.onerror = function () {
155				resolve(false);
156			};
157			image.src = source;
158		});
159	}
160
161	function rentfetchReindexFloorplanSlider(element) {
162		element.querySelectorAll('.floorplan-image-slide').forEach(function (slide, index) {
163			slide.dataset.floorplanImageIndex = index;
164		});
165		element.querySelectorAll('.floorplan-image-thumbnail').forEach(function (thumbnail, index) {
166			thumbnail.dataset.floorplanImageIndex = index;
167			thumbnail.setAttribute('aria-label', 'View photo ' + (index + 1));
168			thumbnail.classList.toggle('is-active', index === 0);
169			if (index === 0) {
170				thumbnail.setAttribute('aria-current', 'true');
171			} else {
172				thumbnail.removeAttribute('aria-current');
173			}
174		});
175
176		var buttons = element.querySelector('.blaze-buttons');
177		if (buttons) {
178			buttons.hidden = element.querySelectorAll('.floorplan-image-slide').length < 2;
179		}
180	}
181
182	function rentfetchRemoveFloorplanSliderImage(element, index) {
183		element.querySelectorAll('[data-floorplan-image-index="' + index + '"]').forEach(function (item) {
184			item.remove();
185		});
186		rentfetchReindexFloorplanSlider(element);
187	}
188
189	function rentfetchPrepareFloorplanSlider(element) {
190		var thumbnails = Array.from(element.querySelectorAll('.floorplan-image-thumbnail'));
191		var candidates = thumbnails.length ? thumbnails : Array.from(element.querySelectorAll('.floorplan-image-slide'));
192
193		return Promise.all(candidates.map(function (candidate) {
194			var image = candidate.querySelector('img');
195			var source = candidate.dataset.floorplanSampleSrc || (image ? image.currentSrc || image.src : '');
196			var index = Number(candidate.dataset.floorplanImageIndex);
197
198			return source ? rentfetchImageLoads(source).then(function (loaded) {
199				return { index: index, loaded: loaded };
200			}) : Promise.resolve({ index: index, loaded: false });
201		})).then(function (results) {
202			results.filter(function (result) {
203				return !result.loaded;
204			}).sort(function (first, second) {
205				return second.index - first.index;
206			}
206).forEach(function (result) {
207				rentfetchRemoveFloorplanSliderImage(element, result.index);
208			});
209
210			rentfetchReindexFloorplanSlider(element);
211			if (element.querySelector('.floorplan-image-slide')) {
212				rentfetchInitializeFloorplanSlider(element);
213			}
214		});
215	}
216
217	function rentfetchSetActiveFloorplanThumbnail(sliderElement, index) {
218		var thumbnails = sliderElement.querySelectorAll('.floorplan-image-thumbnail');
219
220		thumbnails.forEach(function (thumbnail) {
221			var active = Number(thumbnail.dataset.floorplanImageIndex) === index;
222			thumbnail.classList.toggle('is-active', active);
223			if (active) {
224				thumbnail.setAttribute('aria-current', 'true');
225				var rail = thumbnail.parentElement;
226				rail.scrollTo({
227					left: thumbnail.offsetLeft - (rail.clientWidth - thumbnail.offsetWidth) / 2,
228					behavior: 'smooth',
229				});
230			} else {
231				thumbnail.removeAttribute('aria-current');
232			}
233		});
234	}
235
236	function rentfetchInitializeFloorplanSlider(element) {
237		var slider = new BlazeSlider(element, {
238			all: {
239				enableAutoplay: false,
240				slidesToShow: 1,
241			},
242		});
243
244		if (!element.classList.contains('has-floorplan-image-thumbnails')) {
245			return;
246		}
247
248		var thumbnails = Array.from(element.querySelectorAll('.floorplan-image-thumbnail'));
249		var currentIndex = 0;
250		if (!thumbnails.length) {
251			element.querySelectorAll('.floorplan-image-slide').forEach(function (slide) {
252				var image = slide.querySelector('img');
253				var index = Number(slide.dataset.floorplanImageIndex);
254				if (image) {
255					rentfetchGetFloorplanImageClassification(image.currentSrc || image.src).then(function (classification) {
256						rentfetchApplyFloorplanImageClassification(element, index, classification);
257					});
258				}
259			});
260			return;
261		}
262
263		thumbnails.forEach(function (thumbnail) {
264			var index = Number(thumbnail.dataset.floorplanImageIndex);
265			var source = thumbnail.dataset.floorplanSampleSrc;
266
267			rentfetchGetFloorplanImageClassification(source).then(function (classification) {
268				rentfetchApplyFloorplanImageClassification(element, index, classification);
269			});
270
271			thumbnail.addEventListener('click', function () {
272				var currentThumbnails = Array.from(element.querySelectorAll('.floorplan-image-thumbnail'));
273				var total = currentThumbnails.length;
274				index = currentThumbnails.indexOf(thumbnail);
275				var forward = (index - currentIndex + total) % total;
276				var backward = (currentIndex - index + total) % total;
277
278				currentIndex = index;
279				rentfetchSetActiveFloorplanThumbnail(element, currentIndex);
280				if (forward <= backward) {
281					slider.next(forward);
282				} else {
283					slider.prev(backward);
284				}
285			});
286		});
287
288		slider.onSlide(function (stateIndex, firstVisibleSlide) {
289			currentIndex = firstVisibleSlide;
290			rentfetchSetActiveFloorplanThumbnail(element, currentIndex);
291		});
292
293		var previous = element.querySelector('.blaze-prev');
294		var next = element.querySelector('.blaze-next');
295		if (previous) {
296			previous.addEventListener('click', function () {
297				var total = element.querySelectorAll('.floorplan-image-slide').length;
298				currentIndex = (currentIndex - 1 + total) % total;
299				rentfetchSetActiveFloorplanThumbnail(element, currentIndex);
300			});
301		}
302		if (next) {
303			next.addEventListener('click', function () {
304				var total = element.querySelectorAll('.floorplan-image-slide').length;
305				currentIndex = (currentIndex + 1) % total;
306				rentfetchSetActiveFloorplanThumbnail(element, currentIndex);
307			});
308		}
309	}
310
311	function rentfetchInitializeFloorplanGallery(gallery) {
312		gallery.querySelectorAll('.floorplan-gallery-image').forEach(function (container) {
313			var source = container.dataset.floorplanSampleSrc;
314			rentfetchGetFloorplanImageClassification(source).then(function (classification) {
315				var className = rentfetchGetFloorplanImageClass(classification);
316				if (!className) {
317					return;
318				}
319
320				container.classList.add(className);
321				if (classification.color) {
322					container.style.setProperty('--rentfetch-floorplan-image-background', classification.color);
323				}
324			});
325		});
326	}
327
328	function rentfetchPrepareFloorplanGallery(gallery) {
329		var containers = Array.from(gallery.querySelectorAll('.floorplan-gallery-image'));
330
331		return Promise.all(containers.map(function (container) {
332			return rentfetchImageLoads(container.dataset.floorplanSampleSrc).then(function (loaded) {
333				if (!loaded) {
334					container.remove();
335				}
336			});
337		})).then(function () {
338			var remaining = Array.from(gallery.querySelectorAll('.floorplan-gallery-image'));
339			if (remaining.length < 3) {
340				gallery.closest('.container-floorplan-gallery').remove();
341				return;
342			}
343
344			remaining.forEach(function (container, index) {
345				container.classList.toggle('is-lightbox-only', index > 2);
346			});
347			gallery.querySelectorAll('.floorplan-gallery-view-all').forEach(function (label) {
348				label.remove();
349			});
350			var label = document.createElement('span');
351			label.className = 'floorplan-gallery-view-all';
352			label.textContent = 'View all ' + remaining.length + ' photos';
353			remaining[2].querySelector('.floorplan-gallery-link').appendChild(label);
354			rentfetchInitializeFloorplanGallery(gallery);
355		});
356	}
357
358	if (typeof module !== 'undefined' && module.exports) {
359		module.exports = {
360			rentfetchColorsMatch: rentfetchColorsMatch,
361			rentfetchFindMatchingCornerColor: rentfetchFindMatchingCornerColor,
362			rentfetchGetFloorplanImageClass: rentfetchGetFloorplanImageClass,
363		};
364	}
365
366	if (typeof document !== 'undefined') {
367		var preparationTasks = [];
368		window.rentfetchClassifyFloorplanSingleImages = rentfetchClassifyFloorplanSingleImages;
369		rentfetchClassifyFloorplanSingleImages();
370		if (typeof BlazeSlider !== 'undefined') {
371			document.querySelectorAll('.floorplan-images-slider').forEach(function (slider) {
372				preparationTasks.push(rentfetchPrepareFloorplanSlider(slider));
373			});
374		}
375		document.querySelectorAll('.floorplan-gallery-grid').forEach(function (gallery) {
376			preparationTasks.push(rentfetchPrepareFloorplanGallery(gallery));
377		});
378		window.rentfetchFloorplanImagesReady = Promise.all(preparationTasks);
379	}
380})();

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.