PageSourceSearch

https://safewaternetwork.org/wp-content/themes/safe-water/js/lib.js?ver=v1642108054

js safewaternetwork.org collected 2026-10-02 07:20:17 UTC 38,295 bytes, 1,408 lines download raw bytes

1var slider = {
2	instances: [],
3
4	init: function(opts) {
5		if (typeof opts == 'undefined')
6			opts = {};
7		if (typeof opts.selector == 'undefined')
8			opts.selector = '.slider';
9		if (typeof opts.drag == 'undefined')
10			opts.drag = 2;
11		if (typeof opts.min_speed == 'undefined')
12			opts.min_speed = 1;
13		if (typeof opts.slide_spacing == 'undefined')
14			opts.slide_spacing = 0;
15		if (typeof opts.move_to_nearest_mode == 'undefined')
16			opts.move_to_nearest_mode = 'center';
17		if (typeof opts.infinite_scroll == 'undefined')
18			opts.infinite_scroll = true;
19		if (typeof opts.after_create == 'undefined')
20			opts.after_create = function(slider_instance) {};
21		if (typeof opts.index_update == 'undefined')
22			opts.index_update = function(slider_instance, index) {};
23		if (typeof opts.show_prev_next == 'undefined')
24			opts.show_prev_next = true;
25		if (typeof opts.show_buttons == 'undefined')
26			opts.show_buttons = true;
27		if (typeof opts.zoom_button == 'undefined')
28			opts.zoom_button = false;
29		if (typeof opts.fullscreen_button == 'undefined')
30			opts.fullscreen_button = false;
31		if (typeof opts.auto_rotate == 'undefined')
32			opts.auto_rotate = false;
33		if (typeof opts.auto_rotate_delay == 'undefined')
34			opts.auto_rotate_delay = 6000;
35			
36		jQuery(opts.selector).each(function() {		
37			slider.instances.push(new slider.slider_instance(jQuery(this), opts));
38		});	
39	},
40
41	slider_instance: function(jq, opts) {
42		if (jq.hasClass('slider-init'))
43			return;
44		
45		var me = this;
46
47		var slides = [];
48		var jq_width = 0;
49		var container = jq.find('ul');
50		var jq_win = jQuery(window);
51		var jq_btns = false;
52		var left_position = 0;
53		var tmr_impulse = 0;
54		var tmr_nearest = 0;
55		var max_position = 0;
56		var max_item_position = 0;
57		var extra_before = [];
58		var extra_before_width = 0;
59		var extra_after = [];
60		var extra_after_width = 0;
61		var tmr_auto_rotate = 0;
62
63		me.get_jq = function() {
64			return jq;
65		};
66
67		var busy = false;
68		me.prev = function() {
69			if (busy)
70				return;
71			var cur = this.get_current_index();
72			var prev_index = cur - 1;
73			if (prev_index < 0)
74				prev_index = slides.length - 1;
75
76			if (opts.infinite_scroll)
77				me.move_to_index(prev_index, -1);
78			else
79				me.move_to_index(prev_index, prev_index < cur ? -1 : 1)
80		};
81
82		me.next = function() {
83			if (busy)
84				return;
85			var cur = this.get_current_index();
86			var next_index = cur + 1;
87			if (next_index >= slides.length)
88				next_index = 0;
89			if (opts.infinite_scroll)
90				me.move_to_index(next_index, 1);
91			else
92				me.move_to_index(next_index, next_index < cur ? -1 : 1)
93		};
94
95		/*
96			direction - 1 - closest position to right
97						-1 - closest position to left
98		*/
99		me.move_to_index = function(new_index, direction, instant) {
100			if (busy)
101				return;
102			busy = true;
103			setTimeout(function() {
104				busy = false;
105			}, 1000);
106
107			if (slides.length < 2)
108				return;
109			if (typeof instant == 'undefined')
110				instant = false;
111
112			var cur_index = this.get_current_index();	
113			if (cur_index == new_index && !instant) {
114				return;
115			}	
116
117			var distance_from_left = new_index < cur_index ? (cur_index - new_index) : (slides.length + cur_index - new_index);
118			var distance_from_right = new_index > cur_index ? (new_index - cur_index) : (slides.length + new_index - cur_index);
119			
120			var total_length = 0;
121			if (direction == 1) {
122				var i = cur_index;
123				for(var n=0; n<distance_from_right; n++) {
124					total_length += slides[i].width() + opts.slide_spacing;
125					i++;
126					if (i >= slides.length) {
127						i = 0;
128					}
129				}
130			} else {
131				var i = cur_index;
132				for(var n=0; n<distance_from_left; n++) {
133					total_length -= slides[i].width() + opts.slide_spacing;
134					i--;
135					if (i < 0) {
136						i = slides.length - 1;
137					}
138				}
139			}
140
141			move_to_nearest_animation(left_position - total_length, instant);
142
143			me.update_index(new_index);
144		}
145
146		me.get_slides = function() {
147			return slides;
148		};
149
150		me.update_index = function(new_index) {
151			if (typeof new_index == 'undefined') {
152				new_index = me.get_current_index();
153			}
154			if (opts.show_buttons && jq_btns) {
155				jq_btns.find('.active').removeClass('active');
156				jq_btns.find('a:nth-child(' + (new_index+1) + ')').addClass('active');
157			}
158
159			opts.index_update(me, new_index);
160		}
161		me.impulse = function(amt) {
162			impulse(amt);
163		}
164
165		me.get_current_index = function() {
166			var min_index = 0;
167
168			if (opts.move_to_nearest_mode == 'center') {
169				var center_pos = jq_width/2 - left_position;
170				var min_distance = -1;
171				for(var i in slides) {
172					var slide_pos = slides[i].position().left + slides[i].width()/2;
173					var dist = Math.abs(center_pos - slide_pos);
174					if (min_distance == -1 || dist < min_distance) {
175						min_distance = dist;
176						min_index = i;
177					}
178				}
179				if (extra_before.length) {
180					for(var i in extra_before) {
181						var slide_pos = extra_before[i].position().left + extra_before[i].width()/2;
182						var dist = Math.abs(center_pos - slide_pos);
183						if (dist < min_distance) {
184							min_index = (slides.length - (i % slides.length));
185							min_distance = dist;
186						}
187					}
188				}
189				if (extra_after.length) {
190					for(var i in extra_after) {
191						var slide_pos = extra_after[i].position().left + extra_after[i].width()/2;
192						var dist = Math.abs(center_pos - slide_pos);
193						if (dist < min_distance) {
194							min_index = i % slides.length;
195							min_distance = dist;
196						}
197					}
198				}
199			} else if (opts.move_to_nearest_mode == 'left') {
200				var left_pos = -left_position;
201				var min_distance = -1;
202				for(var i in slides) {
203					var slide_pos = slides[i].position().left;
204					var dist = Math.abs(left_pos - slide_pos);
205					if (min_distance == -1 || dist < min_distance) {
206						min_distance = dist;
207						min_index = i;
208					}
209				}
210				if (extra_before.length) {
211					for(var i in extra_before) {
212						var slide_pos = extra_before[i].position().left;
213						var dist = Math.abs(left_pos - slide_pos);
214						if (dist < min_distance) {
215							min_index = (slides.length - (i % slides.length));
216							min_distance = dist;
217						}
218					}
219				}
220				if (extra_after.length) {
221					for(var i in extra_after) {
222						var slide_pos = extra_after[i].position().left;
223						var dist = Math.abs(left_pos - slide_pos);
224						if (dist < min_distance) {
225							min_index = i % slides.length;
226							min_distance = dist;
227						}
228					}
229				}
230			}
231
232			return ~~min_index;
233		};
234		function create_zoom_button(slide) {
235			var btn_zoom = jQuery('<a href="#" class="btn-zoom"></a>');
236			btn_zoom.click(function(ev) {
237				var src = slide.css('background-image');
238				src = src.replace('url(','').replace(')','').replace(/\"/g, "").replace(/\'/g, "");
239
240				new image_zoom(jq, src);
241
242				ev.stopPropagation();
243				ev.preventDefault();
244				return false;
245			});					
246
247			return btn_zoom;
248		}
249
250		function create_fullscreen_button() {
251			var is_fullscreen = false;
252			var btn = jQuery('<a href="#" class="btn-fullscreen"></a>');
253			btn.click(function() {
254				is_fullscreen = !is_fullscreen;
255
256				if (is_fullscreen) {
257					jq.addClass('fullscreen');
258					var index = me.get_current_index();
259					jq.css({
260						position: 'fixed',
261						top: 0,
262						left: 0,
263						right: 0,
264						bottom: 0,
265						height: 'auto',
266						width: 'auto'
267					});
268					jq.find('.container').css('height', '100%');
269					jq.find('ul').css('height', '100%');
270					jq.find('li').each(function() {
271						jQuery(this).css({width: '100%'});
272					});
273					jq_width = 0;
274					jq_win.resize();
275					me.move_to_index(index, 1, true);
276					impulse(0.5);
277				} else {
278					jq.removeClass('fullscreen');
279					var index = me.get_current_index();
280					jq.css({
281						position: '',
282						top: '',
283						left: '',
284						right: '',
285						bottom: '',
286						height: '',
287						width: ''
288					});
289					jq.find('.container').css('height', '');
290					jq.find('ul').css('height', '100%');
291					jq.find('li').each(function() {
292						jQuery(this).css({width: ''});
293					});
294					jq_width = 0;
295					jq_win.resize();
296					me.move_to_index(index, 1, true);
297					impulse(0.5);
298				}
299				return false;
300			});
301
302			jq.append(btn);
303		}
304		function init() {
305			jq.addClass('slider-init').css('position', 'relative');
306			container.css({
307				position: 'absolute',
308				top: 0,
309				left: 0,
310				transform: 'translateX(0px)',
311				width: '100%',
312				height: '100%',
313				display: 'block',
314				'list-style': 'none'
315			});
316			container.wrap('<div class="container" style="position:relative;overflow:hidden;width:100%;" />');
317
318			container.find('li').each(function() {
319				var slide = jQuery(this);
320				slide.css({
321					position: 'absolute',
322					'list-style':'none',
323					display: 'block',
324					height: '100%',
325					'background-size':'cover',
326					'background-repeat':'no-repeat',
327					'background-position':'center'
328				});
329				slides.push(slide);
330
331				if (opts.zoom_button) {
332					slide.append(create_zoom_button(slide));
333				}
334			});
335
336			if (opts.fullscreen_button) {
337				create_fullscreen_button();
338			}
339			
340			calculate();
341
342			position();
343
344			width_listener();
345
346			touch_listener();
347
348			adjust_left_position();
349
350			move_to_nearest(true, true);
351
352			check_infinite_slides();
353
354			create_navigation_buttons();
355
356			opts.after_create(me);
357
358			if (opts.auto_rotate) {
359				tmr_auto_rotate = setInterval(function() {
360					me.next();
361				}, opts.auto_rotate_delay);
362			}
363		}
364		function cancel_auto_rotate() {
365			if (tmr_auto_rotate) {
366				clearInterval(tmr_auto_rotate);
367				tmr_auto_rotate = 0;
368			}
369		}
370		function create_navigation_buttons() {
371			if (opts.show_prev_next && slides.length > 1) {
372				var btn_prev = jQuery('<a href="#" class="btn-prev"></a>');
373				btn_prev.click(function() {
374					cancel_auto_rotate();
375					me.prev();
376					return false;
377				});
378
379				var btn_next = jQuery('<a href="#" class="btn-next"></a>');
380				btn_next.click(function() {
381					cancel_auto_rotate();
382					me.next();
383					return false;
384				});
385				jq.append(btn_prev, btn_next);
386			}
387			if (opts.show_buttons && slides.length > 1) {
388				function create_button(index) {
389					var btn = jQuery('<a href="#"></a>');
390					btn.click(function() {
391						cancel_auto_rotate();
392						me.move_to_index(index, index > me.get_current_index() ? 1 : -1);
393						return false;
394					});
395					if (index == 0)
396						btn.addClass('active');
397					return btn;
398				}
399
400				jq_btns = jQuery('<div class="buttons" />');
401				for(var i=0; i<slides.length; i++) {
402					jq_btns.append(create_button(i));
403				}
404				jq.append(jq_btns);
405			}
406		}
407		function check_infinite_slides() {
408			if (opts.infinite_scroll && slides.length) {
409				extra_before_width = 0;
410				for(var i in extra_before) {
411					var w =  extra_before[i].width() + opts.slide_spacing;
412					extra_before[i].css({left: -extra_before_width - w});
413					extra_before_width += w;
414				}
415				while(extra_before_width < jq_width*2) {
416					var next_index = slides.length - 1 - extra_before.length;
417					while(next_index < 0)
418						next_index += slides.length;
419					
420					var new_slide = slides[next_index].clone(true,true);
421					new_slide.addClass('extra' + extra_before.length);
422					container.prepend(new_slide);
423					var w = new_slide.width() + opts.slide_spacing;
424					if (w <= opts.slide_spacing)
425						return;
426					new_slide.css({left: -extra_before_width -w});
427					extra_before_width += w;
428					extra_before.push(new_slide);
429				}
430
431				extra_after_width = 0;
432				for(var i in extra_after) {
433					extra_after[i].css({left:max_position + extra_after_width});
434					var w =  extra_after[i].width() + opts.slide_spacing
435					extra_after_width += w;
436				}
437				while(extra_after_width < jq_width*2) {
438					var next_index = extra_after.length;
439					while(next_index >= slides.length)
440						next_index -= slides.length;
441					
442					var new_slide = slides[next_index].clone(true,true);
443					new_slide.addClass('extra' + extra_after.length);
444					container.append(new_slide);
445					new_slide.css({left:max_position + extra_after_width});
446					var w = new_slide.width() + opts.slide_spacing;
447					if (w <= opts.slide_spacing)
448						return;
449					extra_after_width += w;
450					extra_after.push(new_slide);
451				}
452			}
453		}
454
455		function move_container(left) {
456			
457			if (!opts.infinite_scroll) {
458				if (left > 0)
459					left = 0;	
460				if (left < -max_item_position)
461					left = -max_item_position;
462			}
463			container.css({
464				transform: 'translateX(' + ~~left + 'px)'
465			});
466			if (typeof opts.x_update != 'undefined')
467				opts.x_update(~~left, max_position);
468		}
469		function move_to_nearest_animation(new_position, instant) {
470			if (instant) {
471				left_position = new_position;
472				move_container(left_position);
473				me.update_index();
474			} else {
475				var iterations = 20;
476				var move_delta = (new_position - left_position) / iterations;
477				if (move_delta < 1 && move_delta > 0) {
478					move_delta = 1;
479				} else if (move_delta > -1 && move_delta < 0) {
480					move_delta = -1;
481				}
482				var i = 0;
483				clearInterval(tmr_nearest);
484				tmr_nearest = setInterval(function() {
485					if (i < iterations) {
486						left_position += move_delta;
487						adjust_left_position();
488						i++;
489						move_container(left_position);
490					} else {
491						me.update_index();
492						clearInterval(tmr_nearest);
493					}
494				}, 16);
495			}
496		}
497		function move_to_nearest(instant, first_index) {
498			if (typeof instant == 'undefined')
499				instant = false;
500			if (typeof first_index == 'undefined')
501				first_index = false;
502
503			if (opts.move_to_nearest_mode == 'center') {
504				var center_pos = jq_width/2 - left_position;
505				var min_distance = -1;
506				var min_slide_pos = 0;
507				for(var i in slides) {
508					var slide_pos = slides[i].position().left + slides[i].width()/2;
509					var dist = Math.abs(center_pos - slide_pos);
510					if (first_index) {
511						min_slide_pos = slide_pos;
512						break;
513					} else if (min_distance == -1 || dist < min_distance) {
514						min_distance = dist;
515						min_slide_pos = slide_pos;
516					}
517				}
518				if (!first_index) {
519					if (extra_before.length) {
520						for(var i in extra_before) {
521							var slide_pos = extra_before[i].position().left + extra_before[i].width()/2;
522							var dist = Math.abs(center_pos - slide_pos);
523							if (dist < min_distance) {
524								min_slide_pos = slide_pos;
525								min_distance = dist;
526							}
527						}
528					}
529					if (extra_after.length) {
530						for(var i in extra_after) {
531							var slide_pos = extra_after[i].position().left + extra_after[i].width()/2;
532							var dist = Math.abs(center_pos - slide_pos);
533							if (dist < min_distance) {
534								min_slide_pos = slide_pos;
535								min_distance = dist;
536							}
537						}
538					}
539				}
540
541				move_to_nearest_animation(-min_slide_pos + jq_width/2, instant);
542			} else if (opts.move_to_nearest_mode == 'left') {
543				var left_pos = -left_position;
544				var min_distance = -1;
545				var min_slide_pos = 0;
546				for(var i in slides) {
547					var slide_pos = slides[i].position().left;
548					var dist = Math.abs(left_pos - slide_pos);
549					if (first_index) {
550						min_slide_pos = slide_pos
551						break;
552					} else if (min_distance == -1 || dist < min_distance) {
553						min_distance = dist;
554						min_slide_pos = slide_pos;
555					}
556				}
557				if (!first_index) {
558					if (extra_before.length) {
559						for(var i in extra_before) {
560							var slide_pos = extra_before[i].position().left;
561							var dist = Math.abs(left_pos - slide_pos);
562							if (dist < min_distance) {
563								min_slide_pos = slide_pos;
564								min_distance = dist;
565							}
566						}
567					}
568					if (extra_after.length) {
569						for(var i in extra_after) {
570							var slide_pos = extra_after[i].position().left;
571							var dist = Math.abs(left_pos - slide_pos);
572							if (dist < min_distance) {
573								min_slide_pos = slide_pos;
574								min_distance = dist;
575							}
576						}
577					}
578				}
579
580				move_to_nearest_animation(-min_slide_pos, instant);
581			}
582		}
583		function calculate() {
584			jq_width = jq_win.width();
585		}
586		function position() {
587			var left = 0;
588			for(var i in slides) {
589				slides[i].css({left: left});
590
591				max_item_position = left;
592				left += slides[i].width() + opts.slide_spacing;
593			}
594
595			max_position = left;
596		}
597		function width_listener() {
598			jq_win.resize(function() {
599				var last_width = jq_width;
600				calculate();
601
602				if (last_width != jq_width) {
603					position();
604					move_to_nearest(true);
605					check_infinite_slides();
606				}
607			});
608		}
609		function adjust_left_position() {
610			if (opts.infinite_scroll && slides.length) {
611				if (left_position > 0) {
612					left_position -= max_position;
613				} else if (left_position < -max_position) {
614					left_position += max_position;
615				}
616			}
617		}
618		function impulse(speed) {
619			if (speed > 4)
620				speed = 4;
621			else if (speed < -4)
622				speed = -4;
623
624			speed *= (1000 / 32);
625
626			var drag = speed > 0 ? opts.drag : -opts.drag;
627			stop_impulse();
628			tmr_impulse = setInterval(function() {
629				if ((drag > 0 && speed < opts.min_speed) || (drag < 0 && speed > -opts.min_speed)) {
630					stop_impulse();
631					move_to_nearest();
632					me.update_index();
633				} else {
634					if (isNaN(speed) || isNaN(drag)) {
635						speed = 0.1;
636						drag = 0.1;
637					}
638					speed -= drag;
639					left_position += speed;
640					adjust_left_position();
641					move_container(left_position);
642				}
643
644			}, 16);
645		}
646		function stop_impulse() {
647			clearInterval(tmr_impulse);
648		}
649		function touch_listener() {
650			var start_x = 0;
651			var start_time = 0;
652			var last_delta = 0;
653			var tmr_stop = 0;
654
655			track_movement(jq.children('.container'),
656				function(x, y) {
657					start_x = x;
658					last_delta = 0;
659					start_time = Date.now();
660					stop_impulse();
661					clearInterval(tmr_nearest);
662				},
663				function (x_delta, y_delta, x, y) {
664					last_delta = x - start_x;
665					move_container(left_position + last_delta);
666					jq.addClass('dragging');
667					clearTimeout(tmr_stop);
668					cancel_auto_rotate();
669				},
670				function() {
671					if (last_delta == 0)
672						return;
673					left_position += last_delta;
674					var elapsed = Date.now() - start_time;
675					if (elapsed < 500) {
676						var speed = last_delta / elapsed;
677						impulse(speed);
678					} else {
679						adjust_left_position();
680						move_to_nearest();
681					}
682
683					tmr_stop = setTimeout(function() {
684						jq.removeClass('dragging');
685					}, 35);
686				},
687				true, true
688			);
689		}
690
691		init();
692
693		me.update_index(0);
694
695		return me;
696	}
697}
698function wait_for_dimensions(jq, callback, iterations) {
699	if (typeof iterations == 'undefined')
700		iterations = 0;
701
702	var item = jq.get(0);
703	if (typeof item.naturalWidth != 'undefined' && item.naturalWidth > 0) {
704		callback(item.naturalWidth, item.naturalHeight, iterations);
705	} else {
706		var me = this;
707		//slowly increase the time between each call
708		setTimeout(function () {
709			wait_for_dimensions(jq, callback, ++iterations);
710		}, iterations + 1);
711	}
712}
713function image_zoom(container, src) {
714	var min_zoom = 1.5;
715	var max_zoom = 2.5;
716	var zoom = jQuery('<div class="image-zoom" style="position: absolute;z-index: 10000;top: 0;left: 0;right: 0;bottom: 0;overflow: hidden;background:black;"/>');
717	var img = jQuery('<img src="' + src + '" style="position:absolute;top:0;left:0;">');
718	var btn_close = jQuery('<div class="image-zoom-close" style="position:absolute;z-index:10001;top:0;right:0;cursor:pointer;"><span>X</span></div>');
719	var running = true;
720
721	zoom.append(img, btn_close);
722	container.append(zoom);
723
724	btn_close.click(function () {
725		if (running) {
726			running = false;
727			zoom.remove();
728		}
729	});
730
731	wait_for_dimensions(img, function (width, height) {
732		var container_width = zoom.width();
733		var container_height = zoom.height();
734
735		var max_width = container_width * max_zoom;
736		var max_height = container_height * max_zoom;
737		var min_width = container_width * min_zoom;
738		var min_height = container_height * min_zoom;
739
740		if (width > max_width) {
741			height = (max_width / width) * height;
742			width = max_width;
743		} else if (width < min_width) {
744			height = (min_width / width) * height;
745			width = min_width;
746		}
747		if (height > max_height) {
748			width = (max_height / height) * width;
749			height = max_height;
750		} else if (height < min_height) {
751			width = (min_height / height) * width;
752			height = min_height;
753		}
754
755		var top = (container_height - height) / 2;
756		var left = (container_width - width) / 2;
757		var min_left = -width + container_width;
758		var min_top = -height + container_height;
759		var updated_left = 0;
760		var updated_top = 0;
761
762		img.css({
763			width: width,
764			height: height,
765			top: top,
766			left: left
767		});
768
769		track_movement(zoom, function () {
770
771		}, function (x_delta, y_delta) {
772			updated_top = top + y_delta;
773			updated_left = left + x_delta;
774
775			if (updated_top > 0)
776				updated_top = 0;
777			else if (updated_top < min_top)
778				updated_top = min_top;
779			if (updated_left > 0)
780				updated_left = 0;
781			else if (updated_left < min_left)
782				updated_left = min_left;
783
784			img.css({
785				top: updated_top,
786				left: updated_left
787			});
788		}, function () {
789			top = updated_top;
790			left = updated_left;
791		}, true);
792	});
793}
794
795function track_movement(jq, start_callback, move_callback, release_callback, track_mouse, ignore_y) {
796	var is_down = false;
797	var start_x = 0;
798	var start_y = 0;
799	if (typeof ignore_y == 'undefined')
800		ignore_y = false;
801	if (typeof track_mouse == 'undefined')
802		track_mouse = false;
803	if (track_mouse)
804		jq.mouseleave(function () {
805			if (is_down) {
806				is_down = false;
807				setTimeout(function () {
808					jq.removeClass('noclick');
809				}, 125);
810				release_callback();
811			}
812		});
813	if (track_mouse)
814		jq.on('mousedown', function (ev) {
815			is_down = true;
816			start_x = ev.clientX;
817			start_y = ev.clientY;
818			start_callback(start_x, start_y);
819			return false;
820		});
821	if (track_mouse)
822		jq.on('mouseup', function (ev) {
823			if (is_down) {
824				is_down = false;
825				setTimeout(function () {
826					jq.removeClass('noclick');
827				}, 125);
828				release_callback();
829			}
830		});
831	if (track_mouse)
832		jq.on('mousemove', function (ev) {
833			if (is_down) {
834				var x_delta = ev.clientX - start_x;
835				var y_delta = ev.clientY - start_y;
836				move_callback(x_delta, y_delta, ev.clientX, ev.clientY);
837				jq.addClass('noclick');
838				return false;
839			}
840		});
841	jq.on('touchstart', function (ev) {
842		var touches = ev.originalEvent.touches;
843		if (touches.length >= 1) {
844			start_x = touches[0].clientX;
845			start_y = touches[0].clientY;
846			is_down = true;
847			start_callback(start_x, start_y);
848		}
849	});
850	jq.on('touchend', function (ev) {
851		if (is_down) {
852			is_down = false;
853			release_callback();
854		}
855	});
856	jq.on('touchmove', function (ev) {
857		var touches = ev.originalEvent.touches;
858		if (touches.length >= 1) {
859			var x_delta = touches[0].clientX - start_x;
860			var y_delta = touches[0].clientY - start_y;
861			if (ignore_y && (Math.abs(y_delta) > Math.abs(x_delta))) {
862				return true;
863			}
864			move_callback(x_delta, y_delta, touches[0].clientX, touches[0].clientY);
865			ev.stopImmediatePropagation();
866			ev.preventDefault();
867			return false;
868		}
869	});
870}
871
872
873var FormRules = {
874	//form has fld-form-rules
875	//fields have .fld-validate-me and data-validate-type
876	ruleSets: [],
877
878	init: function () {
879		var me = this;
880		jQuery('form.fld-form-rules').each(function (index, value) {
881			jQuery(this).attr('data-validation-id', index);
882			me.ruleSets[index] = {
883				form: jQuery(this),
884				fields: [],
885			};
886			me.ruleSets[index].form.find('.fld-validate-me:not(.customselect)').each(function (fieldIndex, fieldValue) {
887				var field = jQuery(this);
888				field.attr('data-validation-id', fieldIndex);
889
890				var type = field.data('validate-type');
891
892				if (typeof type == "undefined" || type == "") {
893					var field_type = field.attr('type');
894					if (field.is('select')) {
895						type = 'dropdown';
896					} else if (field_type == 'email') {
897						type = 'email';
898					} else if (field_type == 'checkbox') {
899						type = 'checkbox';
900					} else {
901						type = 'text';
902					}
903				}
904
905
906				var msg = '';
907
908				if (type == 'email') {
909					msg = '*Oops! That&rsquo;s not a valid email address.';
910				} else if (type == 'text') {
911					msg = '*Please fill out this field.';
912				} else if (type == 'checkbox' || type == 'checklist') {
913					msg = '*This is a required field.';
914				} else if (type == 'dropdown') {
915					msg = '*Please select an item in the list.';
916				} else if (type == 'credit_card') {
917					msg = '*Oops! That&rsquo;s not a valid credit card number. Please enter the number only, no spaces or dashes.';
918				}
919
920				var error_text = false;
921				if (msg.length > 0) {
922					error_text = jQuery('<span class="error-text" style="display:none">' + msg + '</span>');
923					if (type == 'checklist' && !jQuery(this).hasClass('selection-boxes')) {
924						jQuery(this).append(error_text);
925					} else if (type == 'checkbox' || type == 'dropdown') {
926						//jQuery(this).parent().after(error_text);
927						jQuery(this).after(error_text);
928					} else {
929						jQuery(this).after(error_text);
930					}
931				}
932
933				me.ruleSets[index].fields[fieldIndex] = {
934					field: field,
935					type: type, //text, dropdown, email, credit_card, checkbox, checklist
936					error_text: error_text
937				};
938				field.blur(function () {
939					me.validateField(me.ruleSets[index].fields[fieldIndex], false);
940				});
941				field.change(function () {
942					me.validateField(me.ruleSets[index].fields[fieldIndex], false);
943				});
944				field.keyup(function () {
945					me.validateField(me.ruleSets[index].fields[fieldIndex], false);
946				});
947			});
948		});
949	},
950
951	validate: function (formJq) {
952		var me = this;
953		var ruleSet = formJq.data('validation-id');
954		var valid = true;
955		for (var i = 0; i < me.ruleSets[ruleSet].fields.length; i++) {
956			var data = me.ruleSets[ruleSet].fields[i];
957			var result = me.validateField(data, valid);
958			if (!result) {
959				valid = false;
960			}
961		}
962
963		return valid;
964	},
965
966	validateField: function (data, bFocus) {
967		var field = data.field;
968		var field_val = "";
969
970		if (typeof data.type == 'undefined') {
971			data.type = 'text';
972		}
973
974		if (field.data('validate-if-visible')) {
975			if (!field.is(':visible')) {
976				if (data.error_text) {
977					data.error_text.hide();
978				}
979				return true;
980			}
981		}
982
983
984		if (data.type == 'text' || data.type == 'dropdown' || data.type == 'email' || data.type == 'credit_card') {
985			field_val = field.val();
986
987			if (field.data('default_text') == field_val) {
988				field_val = "";
989			}
990
991		} else if (data.type == 'checkbox') {
992			if (field.prop('checked'))
993				field_val = field.val();
994			else
995				field_val = "";
996		} else if (data.type == 'checklist') {
997			var list = field.find('input');
998			var values = [];
999			for (var i = 0; i < list.length; i++) {
1000				var chk = jQuery(list[i]);
1001				if (chk.prop('checked'))
1002					values.push(chk.attr('value'));
1003			}
1004		}
1005
1006		var valid = false;
1007		if (data.error_text) {
1008			data.error_text.hide();
1009		}
1010
1011		if (data.type == 'dropdown') {
1012			if (field_val == "") {
1013				field.addClass('error');
1014				if (field.parent().children('.customselect').length > 0)
1015					field.parent().children('.customselect').addClass('error');
1016				valid = false;
1017				if (bFocus)
1018					field.focus();
1019			} else {
1020				field.removeClass('error');
1021				if (field.parent().children('.customselect').length > 0)
1022					field.parent().children('.customselect').removeClass('error');
1023				valid = true;
1024			}
1025		} else if (data.type == 'text') {
1026			if ((field_val == "") ||
1027				(typeof data.minlength != 'undefined' && field_val.length < data.minlength)) {
1028				field.addClass('error');
1029				valid = false;
1030				if (bFocus)
1031					field.focus();
1032			} else {
1033				field.removeClass('error');
1034				valid = true;
1035			}
1036		} else if (data.type == 'credit_card') {
1037			if (field_val == "" || !this.is_credit_card(field_val)) {
1038				field.addClass('error');
1039				valid = false;
1040				if (bFocus)
1041					field.focus();
1042			} else {
1043				field.removeClass('error');
1044				valid = true;
1045			}
1046		} else if (data.type == 'email') {
1047			valid = true;
1048			if (field_val == "") {
1049				valid = false;
1050			} else {
1051				var exp = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,16})?$/;
1052				var re = new RegExp(exp);
1053				var match = re.exec(field_val);
1054				if (match == null)
1055					valid = false;
1056			}
1057
1058			if (valid) {
1059				field.removeClass('error');
1060			} else {
1061				field.addClass('error');
1062				if (bFocus)
1063					field.focus();
1064			}
1065		} else if (data.type == 'checkbox') {
1066			var fld = field.parent('label');
1067			if (field_val == "") {
1068				fld.addClass('error');
1069				valid = false;
1070				if (bFocus)
1071					field.focus();
1072			} else {
1073				fld.removeClass('error');
1074				valid = true;
1075			}
1076		} else if (data.type == 'checklist') {
1077			if (values.length == 0) {
1078				field.addClass('error');
1079				valid = false;
1080				if (bFocus) {
1081					var pos = field.find('input').parent();
1082					jQuery('body,html').scrollTop(pos.offset().top - 140);
1083				}
1084			} else {
1085				field.removeClass('error');
1086				valid = true;
1087			}
1088		}
1089
1090		if (!valid && data.error_text) {
1091			data.error_text.css('display', 'block');
1092		}
1093
1094		field.trigger('fld-error-response');
1095		return valid;
1096	},
1097
1098	is_credit_card: function (number) {
1099		var sum = 0;
1100		var mul = 1;
1101
1102		for (var i = 0; i < number.length; i++) {
1103			var digit = number.substring(number.length - i - 1, number.length - i);
1104			var tproduct = parseInt(digit, 10) * mul;
1105			if (tproduct >= 10)
1106				sum += (tproduct % 10) + 1;
1107			else
1108				sum += tproduct;
1109
1110			mul = 3 - mul;
1111		}
1112
1113		if ((sum % 10) == 0)
1114			return true;
1115		else
1116			return false;
1117	}
1118};
1119
1120var FormValidationErrorResponse = {
1121	//for error response after input field, just add .error:after css with the message
1122	errorBoxes: [],
1123
1124	init: function () {
1125		var me = this;
1126		jQuery('form.fld-error-response').each(function (index, value) {
1127			var form = jQuery(this);
1128			me.errorBoxes[index] = jQuery('#' + form.data('error-response-box')).length == 0 ? null : jQuery('#' + form.data('error-response-box'));
1129
1130			form.find('.fld-validate-me').each(function (fieldIndex, fieldValue) {
1131				var field = jQuery(this);
1132				field.on('fld-error-response', function () {
1133					if (field.hasClass('error')) {
1134						if (me.errorBoxes[index] != null) {
1135							if (me.errorBoxes[index].find('.' + field.attr('name')).length == 0) {
1136								me.errorBoxes[index].append('<div class="' + field.attr('name') + ' error-response">' + field.data('error-response-text') + '</div>');
1137							}
1138						}
1139
1140					} else {
1141						if (me.errorBoxes[index] != null) {
1142							me.errorBoxes[index].find('.' + field.attr('name')).remove();
1143						}
1144					}
1145				});
1146			});
1147		});
1148	},
1149}
1150
1151function getPageScroll() {
1152	return document.body.scrollTop || jQuery(window).scrollTop();
1153}
1154
1155function wait_for_visible(jq, callback, delay_callback) {
1156	if (jq.length == 0)
1157		return;
1158
1159	if (typeof delay_callback == 'undefined')
1160		delay_callback = 10;
1161
1162	var jq_win = jQuery(window);
1163
1164	var chk_timer = setInterval(function () {
1165		if (jq.is(':visible')) {
1166			var t = getPageScroll();
1167			var h = jq_win.height();
1168			var item_pos = jq.offset().top;
1169			if (item_pos > t && item_pos < t + h) {
1170				clearInterval(chk_timer);
1171				setTimeout(function () {
1172					callback(jq);
1173				}, delay_callback);
1174			}
1175		}
1176	}, 250);
1177
1178	return chk_timer;
1179}
1180
1181(function () {
1182	var lastTime = 0;
1183	var vendors = ['ms', 'moz', 'webkit', 'o'];
1184	for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
1185		window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
1186		window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame']
1187			|| window[vendors[x] + 'CancelRequestAnimationFrame'];
1188	}
1189
1190	if (!window.requestAnimationFrame)
1191		window.requestAnimationFrame = function (callback, element) {
1192			var currTime = new Date().getTime();
1193			var timeToCall = Math.max(0, 16 - (currTime - lastTime));
1194			var id = window.setTimeout(function () { callback(currTime + timeToCall); },
1195				timeToCall);
1196			lastTime = currTime + timeToCall;
1197			return id;
1198		};
1199
1200	if (!window.cancelAnimationFrame)
1201		window.cancelAnimationFrame = function (id) {
1202			clearTimeout(id);
1203		};
1204}());
1205
1206(function () {
1207	// Reasonable defaults
1208	var PIXEL_STEP = 10;
1209	var LINE_HEIGHT = 40;
1210	var PAGE_HEIGHT = 800;
1211
1212	window.normalizeWheel = function (/*object*/ event) /*object*/ {
1213
1214		var sX = 0, sY = 0,       // spinX, spinY
1215			pX = 0, pY = 0;       // pixelX, pixelY
1216
1217		// Legacy
1218		if ('detail' in event) { sY = event.detail; }
1219		if ('wheelDelta' in event) { sY = -event.wheelDelta / 120; }
1220		if ('wheelDeltaY' in event) { sY = -event.wheelDeltaY / 120; }
1221		if ('wheelDeltaX' in event) { sX = -event.wheelDeltaX / 120; }
1222
1223		// side scrolling on FF with DOMMouseScroll
1224		if ('axis' in event && event.axis === event.HORIZONTAL_AXIS) {
1225			sX = sY;
1226			sY = 0;
1227		}
1228
1229		pX = sX * PIXEL_STEP;
1230		pY = sY * PIXEL_STEP;
1231
1232		if ('deltaY' in event) { pY = event.deltaY; }
1233		if ('deltaX' in event) { pX = event.deltaX; }
1234
1235		if ((pX || pY) && event.deltaMode) {
1236			if (event.deltaMode == 1) {          // delta in LINE units
1237				pX *= LINE_HEIGHT;
1238				pY *= LINE_HEIGHT;
1239			} else {                             // delta in PAGE units
1240				pX *= PAGE_HEIGHT;
1241				pY *= PAGE_HEIGHT;
1242			}
1243		}
1244
1245		// Fall-back if spin cannot be determined
1246		if (pX && !sX) { sX = (pX < 1) ? -1 : 1; }
1247		if (pY && !sY) { sY = (pY < 1) ? -1 : 1; }
1248
1249		return {
1250			spinX: sX,
1251			spinY: sY,
1252			pixelX: pX,
1253			pixelY: pY
1254		};
1255	};
1256})();
1257
1258var video = {
1259	// Instances are indexed by the video id rather than 1,2,3,etc so that videos are able to be
1260	// accessed if they get shuffled around in the UI 
1261	instances: new Object(),
1262
1263	// Initialize the videos
1264	// opts - an object of options for the videos. With no options set, the videos will default 
1265	//      - to a looping, muted background video
1266	init: function (opts) {
1267		if (typeof opts.selector == 'undefined')
1268			opts.selector = '.fld-video';
1269		if (typeof opts.autoplay == 'undefined')
1270			opts.autoplay = true;
1271		if (typeof opts.controls == 'undefined')
1272			opts.controls = 'none';
1273		if (typeof opts.loop == 'undefined')
1274			opts.loop = true;
1275		if (typeof opts.muted == 'undefined')
1276			opts.muted = true;
1277		if (typeof opts.playBtn == 'undefined') {
1278			opts.playBtn = 'images/play-btn.svg';
1279		}
1280		if (typeof opts.pauseBtn == 'undefined') {
1281			opts.pauseBtn = 'images/pause-btn.svg';
1282		}
1283
1284		jQuery(opts.selector).each(function () {
1285			video.buildVideoHTML(jQuery(this), opts);
1286		});
1287
1288		// Hover In:
1289		// -    Requests a gif of the video, and displays it once it is ready.
1290		// -    If the gif already exists, show the gif
1291		// Hover Out:
1292		// -    Hide the gif
1293		jQuery(opts.selector).hover(function () {
1294			var previews = jQuery(this).find('.video-previews');
1295			var gif = jQuery(this).find('.gif');
1296			if (jQuery(window).width() > 760 && gif.length == 0) {
1297				var id = jQuery(this).data('id');
1298				var gif = jQuery('<img class="gif" src="https://videodelivery.net/' + id + '/thumbnails/thumbnail.gif?time=0s&duration=1s">');
1299				gif.on('load', function () {
1300					previews.append(gif);
1301				});
1302			} else {
1303				previews.find('.gif').show();
1304			}
1305		}, function () {
1306			var previews = jQuery(this).find('.video-previews');
1307			previews.find('.gif').hide();
1308		});
1309
1310		// Hides the video previews (thumbnail and gif) and filter and plays the video
1311		jQuery(opts.selector).click(function () {
1312			var id = jQuery(this).data('id');
1313			jQuery(this).addClass('playing');
1314			// video.instances[id].player.play().catch(function() {
1315			//     video.instances[id].player.muted = true;
1316			//     video.instances[id].player.play();
1317			// });
1318		});
1319
1320	},
1321
1322	// Create the HTML of the video previews and video. Video properties have defaults,
1323	// but can be changed by setting the data-{property} attriutes
1324	// jq   - a jQuery object of an instance of the selector specified in the init function
1325	// opts - an object of options for the videos.
1326	buildVideoHTML: function (jq, opts) {
1327		if (jq.data('id') !== undefined) {
1328			var id = jq.data('id');
1329			var html = jQuery('<div class="filter"><div class="button" style="background-image: url(' + opts.playBtn + ')"></div></div><div class="video-previews"><img class="still" src="https://videodelivery.net/' + id + '/thumbnails/thumbnail.jpg?time=0s&fit=fill"></div><iframe class="video" src="https://iframe.videodelivery.net/' + id + '" allow="autoplay; accelerometer; gyroscope; encrypted-media; picture-in-picture;"  allowfullscreen="true"></iframe>');
1330			jq.append(html);
1331			video.instances[id] = {
1332				jq: jq,
1333				player: Stream(jq.find('.video')[0]),
1334				playBtn: opts.playBtn,
1335				pauseBtn: opts.pauseBtn
1336			}
1337			var controls = (typeof jq.data('controls') !== 'undefined' ? jq.data('controls') : opts.c
1337ontrols);
1338			if (controls == 'full') {
1339				video.instances[id].player.controls = true;
1340			} else {
1341				video.instances[id].player.controls = false;
1342			}
1343			// video.instances[id].player.controls = (typeof jq.data('controls') !== 'undefined' ? jq.data('controls') : opts.controls);
1344			video.instances[id].player.autoplay = (typeof jq.data('autoplay') !== 'undefined' ? jq.data('autoplay') : opts.autoplay);
1345			video.instances[id].player.muted = (typeof jq.data('muted') !== 'undefined' ? jq.data('muted') : opts.muted);
1346			video.instances[id].player.loop = (typeof jq.data('loop') !== 'undefined' ? jq.data('loop') : opts.loop);
1347			
1348			if (video.instances[id].player.autoplay) {
1349				video.instances[id].player.play();
1350			}
1351
1352			if (controls == 'none') {
1353				jq.find('.filter').remove();
1354
1355				video.instances[id].player.addEventListener('canplay', function () {
1356					jq.find('.video-previews').remove();
1357				});
1358			} else if (controls == 'limited') {
1359				jq.find('.filter').css('pointer-events', 'all');
1360
1361				jq.find('.filter').click(function () {
1362					if (video.instances[id].player.paused) {
1363						video.instances[id].player.play();
1364					} else {
1365						video.instances[id].player.pause();
1366					}
1367				});
1368			} else if (controls == 'full') {
1369				jq.find('.filter').click(function () {
1370					jQuery(this).remove();
1371					video.instances[id].player.play();
1372				});
1373			}
1374
1375			video.instances[id].player.addEventListener('play', function () {
1376				video.onPlay(video.instances[id]);
1377			});
1378			video.instances[id].player.addEventListener('pause', function () {
1379				video.onPause(video.instances[id]);
1380			});
1381		}
1382	},
1383
1384	onPlay: function (instance) {
1385		instance.jq.removeClass('paused');
1386		instance.jq.find('.button').css('background-image', 'url("' + instance.pauseBtn + '")');
1387	},
1388	onPause: function (instance) {
1389		instance.jq.addClass('paused');
1390		instance.jq.find('.button').css('background-image', 'url("' + instance.playBtn + '")');
1391	}
1392}
1393
1394
1395
1396const isInViewport = (elem, direction) => {
1397    var bounding = elem.getBoundingClientRect();
1398
1399    if (direction === 'left') {
1400        return (
1401            bounding.right >= 0
1402        );
1403    } else {
1404        return (
1405            bounding.left <= window.innerWidth
1406        );
1407    }
1408};

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.