PageSourceSearch

https://bazimiami.com/wp-content/themes/rosa/assets/js/main.js

js bazimiami.com collected 2026-10-06 22:18:14 UTC 64,462 bytes, 2,145 lines download raw bytes

1// /* ====== SHARED VARS ====== */
2
3var phone, touch, ltie9, dh, ar, fonts, ieMobile;
4
5var ua = navigator.userAgent;
6var winLoc = window.location.toString();
7
8var is_webkit       = ua.match(/webkit/i);
9var is_firefox      = ua.match(/gecko/i);
10var is_newer_ie     = ua.match(/msie (9|([1-9][0-9]))/i);
11var is_older_ie     = ua.match(/msie/i) && !is_newer_ie;
12var is_ancient_ie   = ua.match(/msie 6/i);
13var is_ie           = is_ancient_ie || is_older_ie || is_newer_ie;
14var is_mobile_ie    = navigator.userAgent.indexOf('IEMobile') !== -1;
15var is_mobile       = ua.match(/mobile/i);
16var is_OSX          = ua.match(/(iPad|iPhone|iPod|Macintosh)/g) ? true : false;
17var iOS 			= getIOSVersion(ua);
18
19
20var nua = navigator.userAgent;
21var is_android = ((nua.indexOf('Mozilla/5.0') !== -1 && nua.indexOf('Android ') !== -1 && nua.indexOf('AppleWebKit') !== -1) && nua.indexOf('Chrome') === -1);
22var isAndroid = ua.indexOf("android") > -1; //&& ua.indexOf("mobile");
23
24var useTransform = true;
25var use2DTransform = (ua.match(/msie 9/i) || winLoc.match(/transform\=2d/i));
26var transform;
27
28// setting up transform prefixes
29var prefixes = {
30	webkit: 'webkitTransform',
31	firefox: 'MozTransform',
32	ie: 'msTransform',
33	w3c: 'transform'
34};
35
36if (useTransform) {
37	if (is_webkit) {
38		transform = prefixes.webkit;
39	} else if (is_firefox) {
40		transform = prefixes.firefox;
41	} else if (is_newer_ie) {
42		transform = prefixes.ie;
43	}
44}
45
46var windowWidth 		= window.innerWidth,
47    windowHeight 		= window.innerHeight;
48
49/* --- To enable verbose debug add to Theme Options > Custom Code footer -> globalDebug=true; --- */
50var globalDebug = false,
51	timestamp,
52    gifImages;
53
54(function ($, window, undefined) {
55
56	/* --- DETECT VIEWPORT SIZE --- */
57
58	function browserSize() {
59		wh = $(window).height();
60		ww = $(window).width();
61		dh = $(document).height();
62		ar = ww / wh;
63	}
64
65
66	/* --- DETECT PLATFORM --- */
67
68	function platformDetect() {
69		$.support.touch = 'ontouchend' in document;
70		var navUA = navigator.userAgent.toLowerCase(),
71			navPlat = navigator.platform.toLowerCase();
72
73		var isiPhone = navPlat.indexOf("iphone"),
74			isiPod = navPlat.indexOf("ipod"),
75			isAndroidPhone = navPlat.indexOf("android"),
76			safari = (navUA.indexOf('safari') != -1 && navUA.indexOf('chrome') == -1) ? true : false,
77			svgSupport = (window.SVGAngle) ? true : false,
78			svgSupportAlt = (document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")) ? true : false,
79			ff3x = (/gecko/i.test(navUA) && /rv:1.9/i.test(navUA)) ? true : false;
80
81        ieMobile = navigator.userAgent.match(/Windows Phone/i) ? true : false;
82		phone = (isiPhone > -1 || isiPod > -1 || isAndroidPhone > -1) ? true : false;
83		touch = $.support.touch ? true : false;
84		ltie9 = $.support.leadingWhitespace ? false : true;
85
86		var $bod = $('body');
87
88		if (touch) $('html').addClass('touch');
89		if (ieMobile) $('html').addClass('is--winmob');
90		if (is_android) $('html').addClass('is--ancient-android');
91		if (safari) $bod.addClass('safari');
92		if (phone) $bod.addClass('phone');
93
94
95	}
96/* --- Magnific Popup Initialization --- */
97
98function magnificPopupInit() {
99	if (globalDebug) {
100		console.log("Magnific Popup - Init");
101	}
102
103	$('.js-post-gallery').each(function () { // the containers for all your galleries should have the class gallery
104		$(this).magnificPopup({
105			tPrev: objectl10n.tPrev,
106			tNext: objectl10n.tNext,
107			tCounter: objectl10n.tCounter,
108			delegate: 'a[href$=".jpg"], a[href$=".jpeg"], a[href$=".png"], a[href$=".gif"]', // the container for each your gallery items
109			type: 'image',
110			closeOnContentClick: false,
111			closeBtnInside: false,
112			removalDelay: 500,
113			mainClass: 'mfp-fade',
114			image: {
115				markup: '<div class="mfp-figure">' +
116				'<div class="mfp-close"></div>' +
117				'<div class="mfp-img"></div>' +
118				'<div class="mfp-bottom-bar">' +
119				'<div class="mfp-title"></div>' +
120				'<div class="mfp-counter"></div>' +
121				'</div>' +
122				'</div>',
123				titleSrc: function (item) {
124					var output = '';
125					if (typeof item.el.attr('data-alt') !== "undefined" && item.el.attr('data-alt') !== "") {
126						output += '<small>' + item.el.attr('data-alt') + '</small>';
127					}
128					return output;
129				}
130			},
131			gallery: {
132				enabled: true,
133				navigateByImgClick: true
134				//arrowMarkup: '<a href="#" class="gallery-arrow gallery-arrow--%dir% control-item arrow-button arrow-button--%dir%">%dir%</a>'
135			},
136			callbacks: {
137				elementParse: function (item) {
138
139					if (this.currItem != undefined) {
140						item = this.currItem;
141					}
142
143					var output = '';
144					if (typeof item.el.attr('data-alt') !== "undefined" && item.el.attr('data-alt') !== "") {
145						output += '<small>' + item.el.attr('data-alt') + '</small>';
146					}
147
148					$('.mfp-title').html(output);
149				},
150				change: function (item) {
151					var output = '';
152					if (typeof item.el.attr('data-alt') !== "undefined" && item.el.attr('data-alt') !== "") {
153						output += '<small>' + item.el.attr('data-alt') + '</small>';
154					}
155
156					$('.mfp-title').html(output);
157				}
158			}
159		});
160	});
161
162}
163
164/* --- Royal Slider Init --- */
165
166function royalSliderInit($container) {
167	if (globalDebug) {
168		console.log("Royal Slider - Init");
169	}
170
171	$container = typeof $container !== 'undefined' ? $container : $('body');
172
173	// Transform Wordpress Galleries to Sliders
174	$container.find('.wp-gallery').each(function () {
175		sliderMarkupGallery($(this));
176	});
177
178	// Find and initialize each slider
179	$container.find('.js-pixslider').each(function () {
180		sliderInit($(this));
181	});
182
183}
184
185/*
186 * Slider Initialization
187 */
188function sliderInit($slider) {
189
190	$slider.find('img').removeClass('invisible');
191
192	var $children = $(this).children(),
193		rs_arrows = typeof $slider.data('arrows') !== "undefined",
194		rs_bullets = typeof $slider.data('bullets') !== "undefined" ? "bullets" : "none",
195		rs_autoheight = typeof $slider.data('autoheight') !== "undefined",
196		rs_autoScaleSlider = false,
197		rs_autoScaleSliderWidth = $slider.data('autoscalesliderwidth'),
198		rs_autoScaleSliderHeight = $slider.data('autoscalesliderheight'),
199		rs_customArrows = typeof $slider.data('customarrows') !== "undefined",
200		rs_slidesSpacing = typeof $slider.data('slidesspacing') !== "undefined" ? parseInt($slider.data('slidesspacing')) : 0,
201		rs_keyboardNav = typeof $slider.data('fullscreen') !== "undefined",
202		rs_imageScale = $slider.data('imagescale'),
203		rs_visibleNearby = typeof $slider.data('visiblenearby') !== "undefined" ? true : false,
204		rs_imageAlignCenter = typeof $slider.data('imagealigncenter') !== "undefined",
205		rs_transition = typeof $slider.data('slidertransition') !== "undefined" && $slider.data('slidertransition') != '' ? $slider.data('slidertransition') : 'move',
206		rs_autoPlay = typeof $slider.data('sliderautoplay') !== "undefined" ? true : false,
207		rs_delay = typeof $slider.data('sliderdelay') !== "undefined" && $slider.data('sliderdelay') != '' ? $slider.data('sliderdelay') : '1000',
208		rs_drag = true,
209		rs_globalCaption = typeof $slider.data('showcaptions') !== "undefined" ? true : false,
210        is_headerSlider = $slider.hasClass('header--slideshow') ? true : false,
211        hoverArrows = typeof $slider.data('hoverarrows') !== "undefined";
212
213	// Single slide case
214	if ($children.length == 1) {
215		rs_arrows = false;
216		rs_bullets = 'none';
217		rs_customArrows = false;
218		rs_keyboardNav = false;
219		rs_drag = false;
220		rs_transition = 'fade';
221        rs_customArrows = false;
222	}
223
224	// make sure default arrows won't appear if customArrows is set
225	if (rs_customArrows) arrows = false;
226
227	//the main params for Royal Slider
228	var royalSliderParams = {
229		autoHeight: rs_autoheight,
230		autoScaleSlider: rs_autoScaleSlider,
231		loop: true,
232		autoScaleSliderWidth: rs_autoScaleSliderWidth,
233		autoScaleSliderHeight: rs_autoScaleSliderHeight,
234		imageScaleMode: rs_imageScale,
235		imageAlignCenter: rs_imageAlignCenter,
236		slidesSpacing: rs_slidesSpacing,
237		arrowsNav: rs_arrows,
238		controlNavigation: rs_bullets,
239		keyboardNavEnabled: rs_keyboardNav,
240		arrowsNavAutoHide: false,
241		sliderDrag: rs_drag,
242		transitionType: rs_transition,
243		autoPlay: {
244			enabled: rs_autoPlay,
245			stopAtAction: true,
246			pauseOnHover: true,
247			delay: rs_delay
248		},
249		globalCaption: rs_globalCaption,
250		numImagesToPreload: 4
251	};
252
253	if (rs_visibleNearby) {
254		royalSliderParams['visibleNearby'] = {
255			enabled: true,
256			//centerArea: 0.8,
257			center: true,
258			breakpoint: 0,
259			//breakpointCenterArea: 0.64,
260			navigateByCenterClick: false
261		}
262	}
263
264
265	//lets fire it up
266	$slider.royalSlider(royalSliderParams);
267	$slider.addClass('slider--loaded');
268
269
270	var royalSlider = $slider.data('royalSlider');
271	var slidesNumber = royalSlider.numSlides;
272
273	// create the markup for the customArrows
274    if (royalSlider && rs_customArrows) {
275
276        var classes = '';
277
278        if(is_headerSlider) classes = 'slider-arrows-header';
279        if(hoverArrows && !Modernizr.touch) classes += ' arrows--hover ';
280
281        var $gallery_control = $(
282            '<div class="' + classes + '">' +
283            '<div class="rsArrow rsArrowLeft js-arrow-left" style="display: block;"><div class="rsArrowIcn"></div></div>' +
284            '<div class="rsArrow rsArrowRight js-arrow-right" style="display: block;"><div class="rsArrowIcn"></div></div>' +
285            '</div>'
286        );
287
288        if ($slider.data('customarrows') == "left") {
289            $gallery_control.addClass('gallery-control--left');
290        }
291
292        $gallery_control.insertBefore($slider);
293
294        $gallery_control.on('click', '.js-arrow-left', function (event) {
295            event.preventDefault();
296            royalSlider.prev();
297        });
298
299        $gallery_control.on('click', '.js-arrow-right', function (event) {
300            event.preventDefault();
301            royalSlider.next();
302        });
303    }
304
305    if(hoverArrows && !Modernizr.touch){
306        hoverArrow($('.slider-arrows-header .rsArrow'));
307
308    }
309
310	if (slidesNumber == 1) $slider.addClass('single-slide');
311
312	$slider.addClass('slider--loaded');
313}
314
315/*
316 * Wordpress Galleries to Sliders
317 * Create the markup for the slider from the gallery shortcode
318 * take all the images and insert them in the .gallery <div>
319 */
320function sliderMarkupGallery($gallery) {
321	var $old_gallery = $gallery,
322		gallery_data = $gallery.data(),
323		$images = $old_gallery.find('img'),
324		$new_gallery = $('<div class="pixslider js-pixslider">');
325
326	$images.prependTo($new_gallery).addClass('rsImg');
327
328	//add the data attributes
329	$.each(gallery_data, function (key, value) {
330		$new_gallery.attr('data-' + key, value);
331	})
332
333	$old_gallery.replaceWith($new_gallery);
334}
335
336/*
337    Get slider arrows to hover, following the cursor
338 */
339
340function hoverArrow($arrow){
341    var $mouseX = 0, $mouseY = 0;
342    var $arrowH = 35, $arrowW = 35;
343
344    $arrow.mouseenter(function(e){
345        $(this).addClass('visible');
346
347        moveArrow($(this));
348    });
349
350    var $loop;
351
352    function moveArrow($arrow){
353        var $mouseX;
354        var $mouseY;
355
356        $arrow.mousemove(function(e){
357            $mouseX = e.pageX - $arrow.offset().left - 40;
358            $mouseY = e.pageY - $arrow.offset().top - 40;
359        });
360
361        var $arrowIcn = $arrow.find('.rsArrowIcn');
362
363        $loop = setInterval(function(){
364            pixGS.TweenMax.to($arrowIcn, 0, {x: $mouseX, y: $mouseY, z: 0.01});
365        }, 10);
366
367
368        $arrow.mouseleave(function(e){
369            $(this).removeClass('visible');
370            clearInterval($loop);
371        });
372    }
373}
374/* --- GMAP Init --- */
375
376// Overwrite Math.log to accept a second optional parameter as base for logarithm
377Math.log = (function () {
378	var log = Math.log;
379	return function (n, base) {
380		return log(n) / (base ? log(base) : 1);
381	};
382})();
383
384function get_url_parameter(needed_param, gmap_url) {
385	var sURLVariables = (gmap_url.split('?'))[1];
386	if (typeof sURLVariables === "undefined") {
387		return sURLVariables;
388	}
389	sURLVariables = sURLVariables.split('&');
390	for (var i = 0; i < sURLVariables.length; i++) {
391		var sParameterName = sURLVariables[i].split('=');
392		if (sParameterName[0] == needed_param) {
393			return sParameterName[1];
394		}
395	}
396}
397
398function get_newMap_oldUrl_coordinates(url) {
399	var coordinates = {},
400		split,
401		distance;
402
403	split = url.split('!3d');
404	coordinates.latitude = split[1];
405	split = split[0].split('!2d');
406	coordinates.longitude = split[1];
407	split = split[0].split('!1d');
408	distance = split[1];
409	coordinates.zoom = 21 - Math.round(Math.log(Math.round(distance / 218), 2));
410
411	return coordinates;
412}
413
414function get_newMap_newUrl_coordinates(url) {
415	var coordinates = {};
416
417	url = url.split('@')[1];
418	url = url.split('z/')[0];
419	url = url.split(',');
420
421	coordinates.latitude 	= url[0];
422	coordinates.longitude 	= url[1];
423	coordinates.zoom 		= url[2];
424
425	if (coordinates.zoom.indexOf('z') >= 0) {
426		coordinates.zoom = coordinates.zoom.substring(0, coordinates.zoom.length - 1);
427	}
428
429	return coordinates;
430}
431
432function get_oldMap_coordinates(url) {
433	var coordinates = {},
434		variables;
435
436	variables = get_url_parameter('ll', url);
437	if (typeof variables == "undefined") {
438		variables = get_url_parameter('sll', url);
439	}
440
441	if (typeof variables == "undefined") {
442		return variables;
443	}
444
445	variables = variables.split(',');
446	coordinates.latitude = variables[0];
447	coordinates.longitude = variables[1];
448
449	coordinates.zoom = get_url_parameter('z', url);
450	if (typeof coordinates.zoom === "undefined") {
451		coordinates.zoom = 10;
452	}
453
454	return coordinates;
455}
456
457function gmapInit($container) {
458	var $gmaps;
459
460	if (typeof $container !== "undefined") {
461		$gmaps = $container.find('.gmap');
462	} else {
463		$gmaps = $('.gmap');
464	}
465
466	if ( $gmaps.length && typeof google !== 'undefined' ) {
467		if (globalDebug) {console.log("GMap Init");}
468
469		$gmaps.each(function () {
470
471			var $gmap = $( this ),
472				url = $gmap.data( 'url' ),
473				style = typeof $gmap.data( 'customstyle' ) !== "undefined" ? "style1" : google.maps.MapTypeId.ROADMAP,
474				coordinates,
475				pins 		= [],
476				gmap_markercontent = $gmap.data( 'markercontent' );
477
478			if ( url ) {
479				//Parse the URL and load variables (ll = latitude/longitude; z = zoom)
480				coordinates = get_oldMap_coordinates( url );
481				if ( typeof variables == "undefined" ) {
482					coordinates = url.split( '!3d' )[0] !== url ? get_newMap_oldUrl_coordinates( url ) : get_newMap_newUrl_coordinates( url );
483				}
484
485				if ( typeof coordinates !== "undefined" && coordinates.latitude && coordinates.longitude ) {
486					pins.push({
487						latLng: [coordinates.latitude, coordinates.longitude],
488						options: {
489							content: '<div class="map__marker-wrap"><div class="map__marker">' + gmap_markercontent + '</div></div>'
490						}
491					});
492				}
493			}
494
495			// if there were no pins we could handle get out
496			if (!pins.length) {
497				return;
498			}
499
500			$gmap.gmap3( {
501				map: {
502					options: {
503						center: new google.maps.LatLng( coordinates.latitude, coordinates.longitude ),
504						zoom: parseInt( coordinates.zoom ),
505						mapTypeId: style,
506						mapTypeControlOptions: {mapTypeIds: []},
507						scrollwheel: false
508					}
509				},
510				overlay: {
511					values: pins
512				},
513				styledmaptype: {
514					id: "style1",
515					options: {
516						name: "Style 1"
517					},
518					styles: [
519						{
520							"stylers": [
521								{"saturation": -100},
522								{"gamma": 3.00},
523								{"visibility": "simplified"}
524							]
525						}, {
526							"featureType": "road",
527							"stylers": [
528								{"hue": $( "body" ).data( "color" ) ? $( "body" ).data( "color" ) : "#ffaa00"},
529								{"saturation": 48},
530								{"gamma": 0.40},
531								{"visibility": "on"}
532							]
533						}, {
534							"featureType": "administrative",
535							"stylers": [
536								{"visibility": "on"}
537							]
538						}
539					]
540				}
541			});
542
543		});
544	}
545
546}
547
548function gmapMultiplePinsInit($container) {
549
550	var $gmaps;
551
552	if (typeof $container !== "undefined") {
553		$gmaps = $container.find('.gmap--multiple-pins');
554	} else {
555		$gmaps = $('.gmap--multiple-pins');
556	}
557
558	$imageMarkup 	= $('.js-map-pin');
559
560	if ( $imageMarkup.length > 0 ) {
561		$imageMarkup = $($imageMarkup[0]).html();
562	}
563
564	if ( $gmaps.length && typeof google !== 'undefined' ) {
565		if (globalDebug) {console.log("GMap Multiple Pins Init");}
566
567		$gmaps.each(function () {
568
569			var $gmap = $( this ),
570				links,
571				style = typeof $gmap.data( 'customstyle' ) !== "undefined" ? "style1" : google.maps.MapTypeId.ROADMAP,
572				pins 		= [],
573				zoom		= 10;
574
575			links = $gmap.data('pins');
576
577			$.each(links, function(label, url) {
578				var coordinates;
579				if (url) {
580					coordinates = get_oldMap_coordinates(url);
581					if (typeof variables == "undefined") {
582						coordinates = url.split('!3d')[0] !== url ? get_newMap_oldUrl_coordinates(url) : get_newMap_newUrl_coordinates(url);
583					}
584					if (typeof coordinates !== "undefined" && coordinates.latitude && coordinates.longitude) {
585						pins.push({
586							latLng: [coordinates.latitude, coordinates.longitude],
587							options: {
588								content: '<div class="gmap__marker"><div class="gmap__marker__btn">' + label + '</div>' + $imageMarkup + '</div>'
589							}
590						});
591					}
592				}
593			});
594
595			// if there were no pins we could handle get out
596			if (!pins.length) {
597				return;
598			}
599
600			$gmap.gmap3( {
601				map: {
602					options: {
603						zoom: zoom,
604						mapTypeId: style,
605						mapTypeControl: false,
606						panControl: true,
607						panControlOptions: {
608							position: google.maps.ControlPosition.LEFT_CENTER
609						},
610						zoomControl: true,
611						zoomControlOptions: {
612							style: google.maps.ZoomControlStyle.LARGE,
613							position: google.maps.ControlPosition.LEFT_CENTER
614						},
615						scaleControl: true,
616						streetViewControl: true,
617						streetViewControlOptions: {
618							position: google.maps.ControlPosition.LEFT_CENTER
619						},
620						scrollwheel: false
621					}
622				},
623				overlay: {
624					values: pins
625				},
626				styledmaptype: {
627					id: "style1",
628					options: {
629						name: "Style 1"
630					},
631					styles: [
632						{
633							"stylers": [
634								{"saturation": -100},
635								{"gamma": 3.00},
636								{"visibility": "simplified"}
637							]
638						}, {
639							"featureType": "road",
640							"stylers": [
641								{"hue": $( "body" ).data( "color" ) ? $( "body" ).data( "color" ) : "#ffaa00"},
642								{"saturation": 48},
643								{"gamma": 0.40},
644								{"visibility": "on"}
645							]
646						}, {
647							"featureType": "administrative",
648							"stylers": [
649								{"saturation": -30},
650								{"gamma": 0.6},
651								{"visibility": "on"}
652							]
653						}, {
654							"featureType": "administrative.neighborhood",
655							"stylers": [
656								{"visibility": "off"}
657							]
658						}
659					]
660				}
661			}, "autofit");
662
663			var map = $gmap.gmap3("get");
664
665			google.maps.event.addListenerOnce(map, 'idle', function() {
666				if (typeof map == "undefined") return;
667
668				if (1 < pins.length) {
669					map.setZoom(map.getZoom() - 1);
670				} else {
671					map.setZoom(zoom);
672				}
673			});
674
675		});
676	}
677
678}
679
680var Parallax = {
681    selector: '.article__parallax',
682    covers: $([]),
683    amount: 0,
684    initialized: false,
685    start: 0,
686    stop: 0,
687
688    initialize: function () {
689        var that = this;
690
691        // if this is a touch device initialize the slider and skip the complicated part
692
693        if (detectIE() || Modernizr.touch && !this.initialized) {
694
695            $('.article__header').each(function (i, hero) {
696
697                var $hero   = $(hero),
698                    $cover  = $hero.children('.article__parallax'), 
699                    $image  = $cover.find('.article__parallax__img');
700
701                $cover.show();
702
703                // if ( ! $image.length ) {
704                //     $image = $cover.children('picture').children('img');
705                // }
706
707                if ( $image.length ) {
708
709                    var imageWidth  = $image.css('width', 'auto').outerWidth(),
710                        imageHeight = $image.outerHeight(),
711                        heroHeight  = $hero.outerHeight(),
712                        scaleX      = windowWidth / imageWidth;
713                        scaleY      = windowHeight / imageHeight;
714                        scale       = Math.max(scaleX, scaleY);
715                        newWidth    = parseInt(imageWidth * scale),
716                        newHeight   = scale * imageHeight;
717
718                    $image.css({
719                        'max-width': 'none',
720                        width: newWidth,
721                        opacity: 1
722                    });
723
724                    $cover.css({
725                        top: 0,
726                        left: (windowWidth - newWidth) / 2
727                    });
728                }
729
730                pixGS.TweenMax.to($cover, .3, {
731                    opacity: 1
732                });
733
734                $hero.css('min-height', windowHeight);
735                royalSliderInit($cover);
736                gmapInit($cover);
737                gmapMultiplePinsInit($cover);
738            });
739
740            return;
741        }
742
743        this.stop           = documentHeight - windowHeight;
744        this.amount         = $body.data('parallax-speed') || 0.5;
745        this.initialized    = true;
746
747        // clean up
748        $('.covers').empty();
749
750        $('.article__parallax').each(function (i, cover) {
751
752            // grab all the variables we need
753            var $cover      = $(cover),
754                $hero       = $cover.parent(),
755                $clone      = $cover.clone().wrap("div.article__header"),
756                $cloneImage = $clone.find('.article__parallax__img'),
757                $cloneSlider = $clone.find('.article__parallax__slider'),
758                heroHeight  = $hero.outerHeight(),
759                heroOffset  = $hero.offset(),
760                $target     = $cover.children(),
761                $cloneTarget = $clone.children(),
762                imageWidth  = $target.outerWidth(),
763                imageHeight = $target.outerHeight(),
764                adminBar    = parseInt($html.css('marginTop')),
765                amount      = that.amount,
766
767            // we may need to scale the image up or down
768            // so we need to find the max scale of both X and Y axis
769                scaleX,
770                scaleY,
771                scale,
772                newWidth,
773                distance,
774                speeds      = {
775                    static: 0,
776                    slow:   0.25,
777                    medium: 0.5,
778                    fast:   0.75,
779                    fixed:  1
780                };
781
782            $cover.removeAttr('style');
783            $clone.data('source', $cover).appendTo('.covers').show();
784            $clone.css('height', heroHeight);
785
786            // let's see if the user wants different speed for different whateva'
787            if (typeof parallax_speeds !== "undefined") {
788                $.each(speeds, function(speed, value) {
789                    if (typeof parallax_speeds[speed] !== "undefined") {
790                        if ($hero.is(parallax_speeds[speed])) {
791                            amount = value;
792                        }
793                    }
794                });
795            }
796
797            scaleX      = windowWidth / imageWidth;
798            scaleY      = (heroHeight + (windowHeight - heroHeight) * amount) / imageHeight;
799            scale       = Math.max(scaleX, scaleY);
800            newWidth    = parseInt(imageWidth * scale);
801            distance    = (windowHeight - heroHeight) * amount;
802
803            // if there's a slider we are working with we may have to set the height
804            $cloneTarget.css('height', heroHeight + distance);
805
806            // set the new width, the image should have height: auto to scale properly
807            $cloneImage.css({
808                'width': newWidth,
809                'height': 'auto'
810            });
811
812            // align the clone to its surrogate
813            // we use TweenMax cause it'll take care of the vendor prefixes
814            // pixGS.TweenMax.to($clone, 0, { top: 0 });
815
816            // prepare image / slider timeline
817            var parallax = {
818                    start:      heroOffset.top - windowHeight - distance / 2,
819                    end:        heroOffset.top + heroHeight + distance / 2,
820                    timeline:   new pixGS.TimelineMax({ paused: true })
821                },
822            // the container timeline
823                parallax2 = {
824                    start:      0,
825                    end:        documentHeight,
826                    timeline:   new pixGS.TimelineMax({ paused: true })
827                };
828
829            // move the image for a parallax effect
830            parallax.timeline.fromTo($cloneTarget, 1, {
831                y: '-=' + heroHeight * amount
832            }, {
833                y: '+=' + heroHeight * amount * 2,
834                ease: pixGS.Linear.easeNone,
835                force3D: true
836            });
837
838            // parallax.timeline.fromTo($cloneSlider.find('.hero__content, .hero__caption'), 1, {
839            //     y: '+=' + windowHeight * amount
840            // }, {
841            //     y: '-=' + windowHeight * amount * 2,
842            //     ease: pixGS.Linear.easeNone,
843            //     force3D: true
844            // }, '-=1');
845
846            // move the container to match scrolling
847            parallax2.timeline.fromTo($clone, 1, {
848                y: heroOffset.top
849            }, {
850                y: heroOffset.top - documentHeight,
851                ease: pixGS.Linear.easeNone,
852                force3D: true
853            });
854
855            // set the parallax info as data attributes on the clone to be used on update
856            $clone
857                .data('parallax', parallax)
858                .data('parallax2', parallax2);
859
860            // update progress on the timelines to match current scroll position
861            that.update();
862
863            // or the slider
864            royalSliderInit($clone);
865            gmapInit($clone);
866            gmapMultiplePinsInit($clone);
867
868            if (that.initialized) {
869                pixGS.TweenMax.to($clone, .3, {'opacity': 1});
870            }
871
872        });
873
874    },
875
876    update: function () {
877        // return;
878        if (Modernizr.touch || is_ie || latestKnownScrollY > this.stop || latestKnownScrollY < this.start) {
879            return;
880        }
881
882        $('.covers .article__parallax').each(function (i, cover) {
883            var $cover      = $(cover),
884                parallax    = $cover.data('parallax'),
885                parallax2   = $cover.data('parallax2'),
886                progress    = (latestKnownScrollY - parallax.start) / (parallax.end - parallax.start),
887                progress2   = (latestKnownScrollY - parallax2.start) / (parallax2.end - parallax2.start);
888
889            progress = 0 > progress ? 0 : progress;
890            progress = 1 < progress ? 1 : progress;
891
892            progress2 = 0 > progress2 ? 0 : progress2;
893            progress2 = 1 < progress2 ? 1 : progress2;
894
895            parallax.timeline.progress(progress);
896            parallax2.timeline.progress(progress2);
897        });
898
899    }
900};
901var DownArrow = {
902    selector:   '.down-arrow',
903    $arrow:     null,
904    timeline:   null,
905    start:      0,
906    end:        0,
907    bubble:     false,
908
909    initialize: function () {
910
911        var that = this;
912
913        this.$arrow = $(this.selector);
914
915        if (empty(this.$arrow)) {
916            return;
917        }
918
919        this.start      = 0;
920        this.end        = this.start + 300;
921        this.timeline   = new pixGS.TimelineMax({ paused: true });
922        this.$next      = this.$arrow.closest('.article__header').nextAll('.article__header, .article--page').first();
923
924        if (!empty(this.$next)) {
925            this.nextTop    = this.$next.offset().top;
926            this.nextHeight = this.$next.outerHeight();
927        }
928
929
930        if (this.$arrow.hasClass('down-arrow--bubble')) {
931            this.timeline.to(this.$arrow, .2, {y: 10, opacity: 0, ease: pixGS.Linear.easeNone, overwrite: "none"});
932            this.timeline.to('.blurp--top', .3, {scaleY: 0, ease: pixGS.Linear.easeNone, overwrite: "none"});
933            this.bubble = true;
934        } else {
935            this.timeline.to(this.$arrow, 1, {y: 100, opacity: 0, ease: pixGS.Linear.easeNone, overwrite: "none"});
936        }
937
938        this.$arrow.on('click', function (e) {
939            e.preventDefault();
940
941            if (empty(that.$next)) {
942                return;
943            }
944
945            if (that.$next.is('.article__header')) {
946                smoothScrollTo(that.nextTop - windowHeight/2 + that.nextHeight/2);
947            } else {
948                smoothScrollTo(that.nextTop - $('.site-header').outerHeight());
949            }
950
951        });
952    },
953
954    update: function () {
955
956        if (empty(this.$arrow) || this.bubble) {
957            return;
958        }
959
960        if (Modernizr.touch && is_OSX) {
961            this.timeline.progress(0);
962            return;
963        }
964
965        setProgress(this.timeline, this.start, this.end);
966    }
967}
968var ScrollToTop = {
969    start:      0,
970    end:        0,
971    timeline:   null,
972    played:     false,
973
974    initialize: function () {
975
976        var $button         = $('.btn--top'),
977            offsetTop       = $button.offset().top,
978            footerHeight    = $('.copyright-area').outerHeight(),
979            start           = offsetTop - windowHeight + footerHeight * 3 / 4;
980
981        if (empty($button)) {
982            return;
983        }
984
985        $button.data('offsetTop', offsetTop);
986
987        this.timeline   = new pixGS.TimelineMax({ paused: true });
988
989        this.timeline.fromTo('.blurp--bottom', .6, {
990            y:          40,
991            scale:      0.5
992        }, {
993            y:          0,
994            scale:      1,
995            ease:       pixGS.Power3.easeOut,
996            force3D:    true
997
998        });
999
1000        this.timeline.fromTo($('.btn__arrow--top'), .4, {
1001            y: 15,
1002            opacity: 0
1003        }, {
1004            y: 0,
1005            scale: 1,
1006            opacity: 1,
1007            ease: pixGS.Back.easeOut
1008        }, '-=0.1');
1009
1010        this.timeline.fromTo($('.btn__arrow--bottom'),.4, {
1011            y: 15,
1012            opacity: 0
1013        }, {
1014            y: 0,
1015            scale: 1,
1016            opacity: 1,
1017            ease: pixGS.Back.easeOut
1018        }, '-=0.25');
1019
1020        $button.on('click', function (e) {
1021            e.preventDefault();
1022            smoothScrollTo(0);
1023        });
1024
1025        this.update();
1026    },
1027
1028    update: function () {
1029
1030        var $button         = $('.btn--top'),
1031            offsetTop       = $button.data('offsetTop'),
1032            footerHeight    = $('.copyright-area').outerHeight(),
1033            start           = offsetTop - windowHeight + footerHeight * 3 / 4,
1034            end             = start + windowHeight;
1035
1036        if (empty($button) || this.timeline == null) {
1037            return;
1038        }
1039
1040        if (Modernizr.touch && is_OSX) {
1041            this.timeline.progress(1);
1042            return;
1043        }
1044
1045        if (start < latestKnownScrollY) {
1046            if (!this.played) {
1047                this.timeline.play();
1048                this.played = true;
1049            }
1050        } else {
1051            if (this.played) {
1052                this.timeline.reverse();
1053                this.played = false;
1054            }
1055        }
1056    }
1057}
1058
1059/* --- Cover Animations Init --- */
1060
1061var CoverAnimation = {
1062    selector:       '.article__header',
1063    initialized:    false,
1064    animated:       false,
1065
1066    initialize: function () {
1067
1068        var that = this;
1069
1070        if (this.initialized) {
1071            return;
1072        }
1073
1074        this.initialized = true;
1075
1076        $(this.selector).each(function(i, header) {
1077
1078            var $header         = $(header),
1079                $headline       = $header.find('.article__headline'),
1080                timeline        = new pixGS.TimelineMax(),
1081                $title          = $headline.find('.headline__primary'),
1082                $subtitle       = $headline.find('.headline__secondary'),
1083                $description    = $headline.find('.headline__description'),
1084                $star           = $headline.find('.star'),
1085                $lines          = $headline.find('.line'),
1086                $arrows         = $description.find('.arrow'),
1087                $hr             = $description.find('hr'),
1088                headerTop       = $header.offset().top,
1089                headerHeight    = $header.outerHeight();
1090
1091            $header.find('.pixcode--separator').width($title.width());
1092
1093            $description.css({opacity: 1});
1094            $description = $description.children().not('.pixcode--separator');
1095            $description.css({opacity: 0});
1096
1097            // ------ A
1098
1099            timeline.fromTo($title, 0.72, {'letter-spacing': '1em', 'margin-right': '-0.9em'}, {'letter-spacing': '0.2em', 'margin-right': '-0.1em', ease: pixGS.Expo.easeOut});
1100            timeline.fromTo($title, 0.89, {opacity: 0}, {opacity: 1, ease: pixGS.Expo.easeOut}, '-=0.72');
1101            timeline.fromTo($title, 1, {'y': 30}, {'y': 0, ease: pixGS.Expo.easeOut}, '-=0.89');
1102            timeline.fromTo($subtitle, 0.65, {opacity: 0}, {opacity: 1, ease: pixGS.Quint.easeOut}, '-=0.65');
1103            timeline.fromTo($subtitle, 0.9, {y: 30}, {y: 0, ease: pixGS.Quint.easeOut}, '-=0.65');
1104            timeline.fromTo($star, 0.15, {opacity: 0}, {opacity: 1, ease: pixGS.Quint.easeOut}, '-=0.6');
1105            timeline.fromTo($star, 0.55, {rotation: -270}, {rotation: 0, ease: pixGS.Back.easeOut}, '-=0.5');
1106            timeline.fromTo($lines, 0.6, {width: 0}, {width: '42%', opacity: 1, ease: pixGS.Quint.easeOut}, '-=0.55');
1107            timeline.fromTo($hr, 0.6, {width: 0}, {width: '100%', opacity: 1, ease: pixGS.Quint.easeOut}, '-=0.6');
1108            timeline.fromTo($arrows, 0.2, {opacity: 0}, {opacity: 1, ease: pixGS.Quint.easeOut}, '-=0.27');
1109            timeline.fromTo($description, 0.5, {opacity: 0}, {opacity: 1, ease: pixGS.Quint.easeOut}, '-=0.28');
1110            timeline.fromTo($description, 0.75, {y: -20}, {y: 0}, '-=0.5');
1111
1112            // ------ B
1113            timeline.addLabel("animatedIn");
1114
1115            if (i == 0) {
1116                timeline.to($headline, 1.08, {y: 150, ease: pixGS.Linear.easeNone});
1117                timeline.to($title, 1.08, {opacity: 0, y: -60, ease: pixGS.Quad.easeIn}, '-=1.08');
1118            } else {
1119                timeline.to($title, 1.08, {opacity: 0, y: -60, ease: pixGS.Quad.easeIn});
1120            }
1121
1122            timeline.to($description, 1.08, {y: 60, opacity: 0, ease: pixGS.Quad.easeIn}, '-=1.08');
1123            timeline.to($subtitle, 1.08, {opacity: 0, y: -90, ease: pixGS.Quad.easeIn}, '-=1.08');
1124            timeline.to($lines, 0.86, {width: 0, opacity: 0, ease: pixGS.Quad.easeIn}, '-=0.94');
1125            timeline.to($hr, 0.86, {width: 0, opacity: 0, ease: pixGS.Quad.easeIn}, '-=0.86');
1126            timeline.to($star, 1, {rotation: 180}, '-=1.08');
1127            timeline.to($star, 0.11, {opacity: 0}, '-=0.03');
1128            timeline.to($arrows, 0.14, {opacity: 0}, '-=1.08');
1129
1130            timeline.addLabel("animatedOut");
1131
1132            // ------ C
1133
1134            var animatedInTime      = timeline.getLabelTime("animatedIn"),
1135                animatedOutTime     = timeline.getLabelTime("animatedOut"),
1136                start               = headerTop + headerHeight / 2 - wh / 2,
1137                end                 = start + headerHeight / 2,
1138                ab, bc;
1139
1140            if (i == 0) {
1141                start = headerTop;
1142                end = start + windowHeight / 2;
1143            }
1144
1145            ab = animatedInTime / animatedOutTime;
1146            bc = 1 - ab;
1147
1148            if (Modernizr.touch && is_OSX) {
1149                timeline.tweenTo("animatedIn");
1150                return;
1151            }
1152
1153            timeline.tweenTo("animatedOut", {
1154                onComplete: function () {
1155                    $headline.data("animated", true);
1156                },
1157                onUpdate: function () {
1158                    var progress        = (1 / (end - start)) * (latestKnownScrollY - start),
1159                        partialProgress = progress < 0 ? ab : ab + bc * progress,
1160                        currentProgress = timeline.progress();
1161
1162                    if (Math.abs(partialProgress - currentProgress) < 0.01) {
1163                        $headline.data("animated", true);
1164                        this.kill();
1165                    }
1166                }
1167            });
1168
1169            $headline.data('tween', {
1170                timeline:       timeline,
1171                ab:             ab,
1172                bc:             bc,
1173                start:          start,
1174                end:            end
1175            });
1176
1177        });
1178
1179        this.update();
1180
1181    },
1182
1183    update: function () {
1184
1185        var that = this;
1186
1187        $(this.selector).each(function (i, element) {
1188
1189            var $headline   = $(element).find('.article__headline'),
1190                options     = $headline.data('tween'),
1191                progress    = 0;
1192
1193            // some sanity check
1194            // we wouldn't want to divide by 0 - the Universe might come to an end
1195            if (! empty(options) && (options.end - options.start) !== 0) {
1196
1197                // progress on the total timeline (ac)
1198                progress = (1 / (options.end - options.start)) * (latestKnownScrollY - options.start);
1199
1200                // progress on partial timeline (bc)
1201                // point B being labeled as "animated"
1202                var partialProgress = options.ab + options.bc * progress;
1203
1204                $headline.data('progress', partialProgress);
1205
1206                if (!$headline.data("animated") || (Modernizr.touch && is_OSX)) {
1207                    return;
1208                }
1209
1210                if (0 > progress) {
1211                    partialProgress = options.ab;
1212                }
1213
1214                if (1 > partialProgress) {
1215                    options.timeline.progress(partialProgress);
1216                    return;
1217                }
1218
1219                options.timeline.progress(1);
1220            }
1221        });
1222    }
1223}
1224/* --- Navigator Init --- */
1225
1226var Navigator = {
1227    // variables
1228    $el:                $('<div class="navigator"></div>'),
1229    sectionSelector:    '.article__header',
1230    scrollDuration:     300,
1231
1232    // private
1233    currentSelected:    0,
1234    lastSelected:       0,
1235    isWhite:            true,
1236    wasWhite:           true,
1237    initialized:        false,
1238    timeline:           new pixGS.TimelineMax({ paused: true }),
1239    nextTop:            0,
1240    footer:             null,
1241    footerTop:          0,
1242
1243    initialize: function () {
1244
1245        var that        = this,
1246            $navigator  = this.$el;
1247
1248        this.initialized    = true;
1249        this.$sections      = $(that.sectionSelector);
1250
1251        this.footer = $('.sidebar--footer__dark');
1252
1253        if (this.footer.length) {
1254            this.footerTop = this.footer.offset().top;
1255        }
1256
1257        if (this.$sections.length < 2) {
1258            return;
1259        }
1260
1261
1262        for (var index = 0; index < this.$sections.length; index++) {
1263
1264            var $section        = $(that.$sections[index]),
1265                sectionTop      = $section.offset().top,
1266                sectionHeight   = $section.outerHeight(),
1267                $button         = $('<a href="#" class="navigator__item"><div class="bullet"></div></a>');
1268
1269            if ($section.css('display') == 'none') {
1270
1271                if (!$section.next().is('.article--page')) {
1272                    that.$sections.splice(index, 1);
1273                    index--;
1274                    continue;
1275                } else {
1276                    sectionTop = that.nextTop;
1277                }
1278            } else {
1279                that.nextTop += sectionHeight;
1280            }
1281
1282            if ($section.next().is('.article--page')) {
1283                that.nextTop += $section.next().outerHeight();
1284            }
1285
1286            $button.appendTo($navigator);
1287            $button.data('scrollTo', sectionTop - windowHeight/2 + sectionHeight/2);
1288            $section.data('offsetTop', sectionTop);
1289
1290            // closures
1291            (function ($newButton) {
1292                $newButton.on('click', function (event) {
1293                    event.preventDefault();
1294                    event.stopPropagation();
1295
1296                    smoothScrollTo($newButton.data('scrollTo'));
1297
1298                    return false;
1299                });
1300            })($button);
1301
1302        }
1303
1304        this.$selected          = $('<div class="navigator__item  navigator__item--selected"><div class="bullet"></div></div>').appendTo($navigator);
1305        this.$selectedBullet    = this.$selected.find('.bullet');
1306
1307        this.timeline.add(pixGS.TweenMax.to(that.$selectedBullet, 0, {}));
1308
1309        this.timeline.add(pixGS.TweenMax.to(that.$selectedBullet, 0.1, {
1310            borderTopLeftRadius: 20,
1311            borderTopRightRadius: 20,
1312            borderBottomLeftRadius: 50,
1313            borderBottomRightRadius: 50,
1314            'scaleY': 2,
1315            'scaleX': 0.6
1316        }));
1317
1318        this.timeline.add(pixGS.TweenMax.to(that.$selectedBullet, 0.1, {
1319            borderTopLeftRadius: 50,
1320            borderTopRightRadius: 50,
1321            borderBottomLeftRadius: 50,
1322            borderBottomRightRadius: 50,
1323            'scaleY': 1,
1324            'scaleX': 1
1325        }));
1326
1327        this.timeline.add(pixGS.TweenMax.to(that.$selectedBullet, 0, {
1328            'scale': 1.2
1329        }));
1330
1331
1332        $navigator.css({'margin-top': -1 * $navigator.height() / 2}).prependTo("body");
1333
1334        this.update();
1335
1336        $('.navigator__item').each(function (i, obj) {
1337
1338            var items   = $('.navigator__item').length,
1339                stagger = 3000 + i * 400,
1340                $obj    = $(obj);
1341
1342            if ($obj.is('.navigator__item--selected')) {
1343                stagger = stagger + items * 100;
1344            }
1345
1346            setTimeout(function () {
1347                pixGS.TweenMax.fromTo($obj, 1, {opacity: 0, scale: 0.7}, {opacity: 1.25, scale: 1, ease: pixGS.Elastic.easeOut});
1348            }, stagger);
1349        });
1350
1351        if($navigator.hasClass('navigator--transparent'))
1352            pixGS.TweenMax.to($navigator, 2, {opacity: .2 });
1353        else
1354            pixGS.TweenMax.to($navigator, .3, {opacity: 1 });
1355    },
1356
1357    update: function () {
1358
1359        var that        = this,
1360            $navigator  = this.$el;
1361
1362        if (!this.initialized) {
1363//            this.initialize();
1364            return;
1365        }
1366
1367        // loop through each header and find current state
1368        this.$sections.each(function(i, element) {
1369
1370            var $section                = $(element),
1371                sectionTop              = $section.data('offsetTop'),
1372                sectionBottom           = sectionTop + $section.outerHeight(),
1373                navigatorMiddle         = latestKnownScrollY + (windowHeight / 2);
1374
1375            // if there's no header
1376
1377            if ($section.css('display') == 'none') {
1378                sectionBottom = sectionTop;
1379                if (!$section.next().is('.article--page')) {
1380                    return;
1381                }
1382            }
1383
1384            if (navigatorMiddle > sectionTop) {
1385                that.currentSelected = i;
1386                that.isWhite = true;
1387
1388                if (navigatorMiddle > sectionBottom) {
1389                    that.isWhite = false;
1390                }
1391            }
1392
1393        });
1394
1395        if (this.footerTop != 0 && this.footerTop < latestKnownScrollY + (windowHeight / 2)) {
1396            this.isWhite = true;
1397        }
1398
1399        // if the navigator's indicator has to be moved
1400        // then move it accordingly and update state
1401        if (this.lastSelected != this.currentSelected) {
1402            this.lastSelected = this.currentSelected;
1403            pixGS.TweenMax.to(this.$selected, 0.3, {top: 24 * that.currentSelected});
1404            that.timeline.tweenFromTo(0, 0.3);
1405//            that.timeline.play();
1406        }
1407
1408        // if the navigator's color has to be changed
1409        // then change it accordingly and update state
1410        if (this.wasWhite != this.isWhite) {
1411            this.wasWhite = this.isWhite;
1412            $navigator.toggleClass('navigator--black', !that.isWhite);
1413        }
1414    }
1415
1416}
1417/* --- Sticky Header Init --- */
1418
1419function stickyHeaderInit() {
1420
1421    var headerSelector      = '.site-header',
1422        $header             = $(headerSelector),
1423        headerHeight        = $header.outerHeight(),
1424        $headers            = $('.article__header'),
1425        offset              = $headers.length ? $headers.first().outerHeight() : 0;
1426
1427    $header.headroom({
1428        tolerance: 15,
1429        offset: offset - headerHeight - 1,
1430        // animate with GSAP
1431        onPin: function () {
1432        },
1433        onUnpin: function () {
1434            if ($('html').hasClass('navigation--is-visible')) {return}
1435        }
1436    });
1437}
1438/* ====== INTERNAL FUNCTIONS ====== */
1439
1440/* --- NICESCROLL --- */
1441
1442
1443var $body               = $('body'),
1444    $html               = $('html'),
1445    $window             = $(window),
1446    $document           = $(document),
1447    documentHeight      = $document.height(),
1448    aspectRatio         = windowWidth / windowHeight,
1449    orientation         = windowWidth > windowHeight ? 'landscape' : 'portrait';
1450
1451function niceScrollInit() {
1452    if (globalDebug) {console.log("NiceScroll Init");}
1453
1454    var smoothScroll    = $('body').data('smoothscrolling') !== undefined,
1455        root            = document.documentElement;
1456
1457    if (smoothScroll && !Modernizr.touch && !is_mobile_ie && !is_OSX) {
1458
1459        var $window = $(window);		// Window object
1460
1461        $window.on("mousewheel DOMMouseScroll", function(event) {
1462
1463            var scrollTo,
1464                scrollDistance  = 400,
1465                delta;
1466
1467            if (event.type == 'mousewheel') {
1468                delta    = event.originalEvent.wheelDelta / 120;
1469            }
1470            else if (event.type == 'DOMMouseScroll') {
1471                delta    = - event.originalEvent.detail / 3;
1472            }
1473
1474            scrollTo = latestKnownScrollY - delta * scrollDistance;
1475
1476            if (scrollTo) {
1477
1478                event.preventDefault();
1479
1480                pixGS.TweenMax.to($window, .6, {
1481                    scrollTo: {
1482                        y:          scrollTo,
1483                        autoKill:   true
1484                    },
1485                    ease:           pixGS.Power1.easeOut,	// For more easing functions see http://api.greensock.com/js/com/greensock/easing/package-detail.html
1486                    autoKill:       true,
1487                    overwrite:      5
1488                });
1489
1490            }
1491
1492        });
1493
1494    }
1495
1496}
1497
1498
1499function smoothScrollTo(y, speed) {
1500
1501    speed = typeof speed == "undefined" ? 1 : speed;
1502
1503    var distance = Math.abs(latestKnownScrollY - y),
1504        time     = speed * distance / 2000;
1505
1506    pixGS.TweenMax.to($(window), time, {scrollTo: {y: y, autoKill: true, ease: pixGS.Quint.easeInOut}});
1507}
1508
1509
1510function menuTrigger(){
1511
1512    $('.js-nav-trigger').on('click', function(e) {
1513
1514        e.preventDefault();
1515        e.stopPropagation();
1516
1517        var $html = $('html');
1518
1519        if($html.hasClass('navigation--is-visible')){
1520            $('body').css('overflow', '');
1521            $html.removeClass('navigation--is-visible');
1522        } else {
1523            $('body').css({'overflow': 'hidden'});
1524            $html.addClass('navigation--is-visible');
1525
1526            if ($html.is('.is--ancient-android, .is--winmob, .is--ie')) {
1527                $('.navigation--main').height(windowHeight);
1528            }
1529        }
1530    });
1531}
1532
1533
1534/* --- $VIDEOS --- */
1535
1536function initVideos() {
1537
1538    var videos = $('iframe, video');
1539
1540    // Figure out and save aspect ratio for each video
1541    videos.each(function() {
1542        $(this).data('aspectRatio', this.width / this.height)
1543            // and remove the hard coded width/height
1544            .removeAttr('height')
1545            .removeAttr('width');
1546    });
1547
1548    // Firefox Opacity Video Hack
1549    $('iframe').each(function(){
1550		var url = $(this).attr("src");
1551	    if ( !empty(url) )
1552			$(this).attr("src", setQueryParameter(url, "wmode", "transparenartt"));
1553	});
1554}
1555
1556
1557function resizeVideos() {
1558
1559    var videos = $('iframe, video');
1560
1561    videos.each(function() {
1562        var video = $(this),
1563            ratio = video.data('aspectRatio'),
1564            w = video.css('width', '100%').width(),
1565            h = w/ratio;
1566        video.height(h);
1567    });
1568}
1569
1570
1571/* ====== INTERNAL FUNCTIONS END ====== */
1572
1573function init() {
1574	if (globalDebug) {console.group("Init");}
1575
1576	// /* GLOBAL VARS */
1577	touch = false;
1578
1579    if (typeof (isIe) != 'undefined' || (!(window.ActiveXObject) && "ActiveXObject" in window)) {
1580        $('html').addClass('is--ie');
1581    }
1582
1583	//  GET BROWSER DIMENSIONS
1584	browserSize();
1585
1586	// /* DETECT PLATFORM */
1587	platformDetect();
1588
1589	loadAddThisScript();
1590
1591	if (is_android || window.opera) {
1592		$('html').addClass('android-browser').removeClass('no-android-browser');
1593	}
1594
1595    var is_iexplore = detectIE();
1596
1597    if (is_iexplore) {
1598        $('body').addClass('is_iexplore  no-scroll-effect');
1599    }
1600
1601	var is_retina = (window.retina || window.devicePixelRatio > 1);
1602	if (is_retina && $('.site-logo--image-2x').length) {
1603
1604	    $('.site-logo--image-2x').children('img').each(function(){
1605
1606            if (typeof $(this).data('logo2x') !== "undefined") {
1607                $(this).attr('src', $(this).data('logo2x'));
1608                $('.site-logo--image-2x').addClass('using-retina-logo');
1609            }
1610        });
1611	}
1612
1613//	stickyHeader();
1614
1615	/* ONE TIME EVENT HANDLERS */
1616	eventHandlersOnce();
1617
1618	/* INSTANTIATE EVENT HANDLERS */
1619	eventHandlers();
1620
1621	if (globalDebug) {console.groupEnd();}
1622}
1623
1624
1625/* ====== EVENT HANDLERS ====== */
1626
1627function eventHandlersOnce() {
1628	if (globalDebug) {console.group("Event Handlers Once");}
1629
1630    menuTrigger();
1631
1632	if (globalDebug) {console.groupEnd();}
1633}
1634
1635function eventHandlers() {
1636	if (globalDebug) {console.group("Event Handlers");}
1637
1638
1639	//Magnific Popup arrows
1640	$('body').off('click', '.js-arrow-popup-prev', magnificPrev).on('click', '.js-arrow-popup-prev', magnificPrev);
1641	$('body').off('click', '.js-arrow-popup-next', magnificNext).on('click', '.js-arrow-popup-next', magnificNext);
1642
1643    var filterHandler;
1644
1645    if(touch) {
1646        filterHandler = 'click';
1647    } else {
1648        filterHandler = 'hover';
1649    }
1650
1651    if(ieMobile) filterHandler = 'click';
1652
1653    $('.pix-dropdown').on(filterHandler, function(e){
1654        e.stopPropagation();
1655
1656        $(this).toggleClass('active');
1657    });
1658
1659
1660    $('.tabs__nav').find("li > a").click(function () {
1661        setTimeout(function(){
1662            Parallax.update();
1663        }, 300);
1664    });
1665
1666	if (globalDebug) {console.groupEnd();}
1667}
1668
1669
1670/* --- GLOBAL EVENT HANDLERS --- */
1671
1672function magnificPrev(e) {
1673	if (globalDebug) {console.log("Magnific Popup Prev");}
1674
1675	e.preventDefault();
1676	var magnificPopup = $.magnificPopup.instance;
1677	magnificPopup.prev();
1678	return false;
1679}
1680
1681function magnificNext(e) {
1682	if (globalDebug) {console.log("Magnific Popup Next");}
1683
1684	e.preventDefault();
1685	var magnificPopup = $.magnificPopup.instance;
1686	magnificPopup.next();
1687	return false;
1688}
1689
1690
1691// $(window).bind('beforeunload', function(event) {
1692// 	if (globalDebug) {console.log("ON BEFORE UNLOAD");}
1693
1694// 	event.stopPropagation();
1695
1696// 	animateBlog('out');
1697// });
1698
1699
1700/* ====== ON DOCUMENT READY ====== */
1701
1702$(document).ready(function(){
1703
1704	if (globalDebug) {console.group("OnDocumentReady");}
1705
1706	/* --- INITIALIZE --- */
1707	init();
1708
1709	if (globalDebug) {console.groupEnd();}
1710});
1711
1712
1713/* ====== ON WINDOW LOAD ====== */
1714
1715$(window).load(function(){
1716
1717	if (globalDebug) {console.group("OnWindowLoad");}
1718
1719    stickyHeaderInit();
1720
1721    if (is_mobile_ie) {
1722        $("html").addClass("mobile-ie");
1723    }
1724
1725    //Set textarea from contact page to autoresize
1726    if($("textarea").length) { $("textarea").autosize(); }
1727
1728    $(".pixcode--tabs").organicTabs();
1729
1730    if (!$('html').is('.ie9, .lt-ie9')) {
1731        setTimeout(function() {
1732            Parallax.initialize();
1733            CoverAnimation.initialize();
1734        }, 600);
1735    } else {
1736        setTimeout(function() {
1737            Parallax.initialize();
1738            CoverAnimation.initialize();
1739        }, 400);
1740    }
1741    niceScrollInit();
1742    //if(!$('html').is('.ie9, .lt-ie9') ){
1743        requestTick();
1744    //}
1745    // always
1746    
1747    royalSliderInit($('.article__content'));
1748
1749    // if ($('.js-pixslider').length) {
1750    //     var slider = $('.js-pixslider').data('royalSlider');
1751
1752    //     slider.ev.on('rsAfterInit rsAfterContentSet rsAfterSlideChange', function () {
1753    //         ScrollToTop.initialize();
1754    //     });
1755    // }
1756
1757    magnificPopupInit();
1758    initVideos();
1759    resizeVideos();
1760    // gmapInit();
1761    // gmapMultiplePinsInit();
1762
1763
1764    if(!empty($('#date-otreservations'))){
1765
1766        // Pikaday
1767        var picker = new Pikaday({
1768            field: document.getElementById('date-otreservations'),
1769            format: 'MM/DD/YYYY',
1770            minDate: moment().toDate()
1771        });
1772        picker.setDate(moment().format('MM/DD/YYYY'));
1773    }
1774
1775    $('.pixcode--tabs').organicTabs();
1776    DownArrow.initialize();
1777
1778    setTimeout(function () {
1779        Navigator.initialize();
1780        ScrollToTop.initialize();
1781    }, 60);
1782});
1783
1784
1785function setProgress(timeline, start, end) {
1786
1787    var progress = (latestKnownScrollY - start) / (end - start);
1788
1789    if (0 > progress) {
1790        timeline.progress(0);
1791        return;
1792    }
1793
1794    if (1 < progress) {
1795        timeline.progress(1);
1796        return;
1797    }
1798
1799    timeline.progress(progress);
1800}
1801
1802
1803/* ====== ON RESIZE ====== */
1804
1805$(window).on("debouncedresize", function(e) {
1806
1807	if (globalDebug) {console.group("OnResize");}
1808
1809    windowWidth     = $(window).width();
1810    windowHeight    = $(window).height();
1811
1812    resizeVideos();
1813
1814    royalSliderInit($('.js-pixslider').not('.article__parallax .js-pixslider'));
1815
1816    gmapInit();
1817    gmapMultiplePinsInit();
1818    ScrollToTop.initialize();
1819    Parallax.initialize();
1820    CoverAnimation.initialize();
1821});
1822
1823$(window).on("orientationchange", function(e) {
1824    setTimeout(function () {
1825        Parallax.initialize();
1826        CoverAnimation.initialize();
1827    }, 300)
1828});
1829
1830var latestKnownScrollY = $('html').scrollTop() || $('body').scrollTop(),
1831    ticking = false;
1832
1833function updateStuff() {
1834    ticking = false;
1835
1836    Parallax.update();
1837    CoverAnimation.update();
1838    Navigator.update();
1839    ScrollToTop.update();
1840    DownArrow.update();
1841}
1842
1843function requestTick() {
1844    if (!ticking) {
1845        requestAnimationFrame(updateStuff);
1846    }
1847    ticking = true;
1848}
1849
1850$(window).on("scroll", function () {
1851    latestKnownScrollY = $('html').scrollTop() || $('body').scrollTop();
1852    //if(!$('html').is('.ie9, .lt-ie9') ){
1853        requestTick();
1854    //}
1855});
1856
1857if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && window.innerHeight != document.documentElement.clientHeight) {
1858
1859    var fixViewportHeight = function() {
1860        $('html, body').outerHeight(window.innerHeight);
1861    };
1862
1863    window.addEventListener("scroll", fixViewportHeight, false);
1864    window.addEventListener("orientationchange", fixViewportHeight, false);
1865    fixViewportHeight();
1866}
1867
1868function detectIE() {
1869    var ua = window.navigator.userAgent;
1870
1871    var msie = ua.indexOf('MSIE ');
1872    if (msie > 0) {
1873        // IE 10 or older => return version number
1874        return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
1875    }
1876
1877    var trident = ua.indexOf('Trident/');
1878    if (trident > 0) {
1879        // IE 11 => return version number
1880        var rv = ua.indexOf('rv:');
1881        return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
1882    }
1883
1884    var edge = ua.indexOf('Edge/');
1885    if (edge > 0) {
1886       // IE 12 => return version number
1887       return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
1888    }
1889
1890    // other browser
1891    return false;
1892}
1893
1894
1895// smooth scrolling to anchors
1896$(function() {
1897
1898    var $header = $('.site-header'),
1899        headerHeight = parseInt($header.outerHeight(), 10),
1900        $html = $('html');
1901
1902    $('.site-header a[href*=#]:not([href=#])').click(function() {
1903
1904        var timeout = 0;
1905
1906        if ($html.hasClass('navigation--is-visible')) {
1907            $('body').css('overflow', '');
1908            $html.removeClass('navigation--is-visible');
1909            timeout = 600;
1910        }
1911
1912
1913        if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
1914            var target = $(this.hash);
1915            target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
1916            if (target.length) {
1917                setTimeout(function () {
1918                    $('html,body').animate({
1919                        scrollTop: target.offset().top - headerHeight
1920                    }, 1000);
1921                }, timeout);
1922                return false;
1923            }
1924        }
1925
1926    });
1927});
1928/* --- 404 Page --- */
1929gifImages = [
1930	"http://i.imgur.com/ShiZM6m.gif",
1931    "http://i.imgur.com/8ZYNp.gif",
1932    "http://i.imgur.com/Xb4fq.gif",
1933    "http://i.imgur.com/UYPLKwN.gif",
1934    "http://media.tumblr.com/d9e792a91d5391b8a7aa22689d4e2555/tumblr_inline_mwq1hmelce1qmoozl.gif",
1935    "http://www.teen.com/wp-content/uploads/2013/10/world-without-jennifer-lawrence-gifs-food-uproxx-2.gif"
1936]
1937
1938function getGif() {
1939	return gifImages[Math.floor(Math.random() * gifImages.length)];
1940}
1941
1942function changeBackground() {
1943	$('.error404').css('background-image', 'url(' + getGif() + ')');
1944}
1945
1946$(window).on('load', function() {
1947    if ($('.error404').length) {
1948        changeBackground();
1949    }
1950});
1951
1952$(window).keydown(function (e) {
1953	if (e.keyCode == 32) {
1954		changeBackground();
1955	}
1956})
1957/* === Functions that require jQuery but have no place on this Earth, yet === */
1958// Adapted from https://gist.github.com/paulirish/1579671 which derived from
1959// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
1960// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
1961
1962// requestAnimationFrame polyfill by Erik Möller.
1963// Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon
1964
1965// MIT license
1966
1967if (!Date.now)
1968    Date.now = function() { return new Date().getTime(); };
1969
1970(function() {
1971    'use strict';
1972
1973    var vendors = ['webkit', 'moz'];
1974    for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
1975        var vp = vendors[i];
1976        window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
1977        window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame']
1978        || window[vp+'CancelRequestAnimationFrame']);
1979    }
1980    if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
1981        || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
1982        var lastTime = 0;
1983        window.requestAnimationFrame = function(callback) {
1984            var now = Date.now();
1985            var nextTime = Math.max(lastTime + 16, now);
1986            return setTimeout(function() { callback(lastTime = nextTime); },
1987                nextTime - now);
1988        };
1989        window.cancelAnimationFrame = clearTimeout;
1990    }
1991}());
1992
1993//here we change the link of the Edit button in the Admin Bar
1994//to make sure it reflects the current page
1995function adminBarEditFix(id) {
1996	//get the admin ajax url and clean it
1997	var baseURL = ajaxurl.replace('admin-ajax.php', 'post.php');
1998
1999	$('#wp-admin-bar-edit a').attr('href', baseURL + '?post=' + id + '&action=edit');
2000}
2001
2002/* --- Load AddThis Async --- */
2003function loadAddThisScript() {
2004	if (window.addthis) {
2005		if (globalDebug) {
2006			console.log("AddThis Load Script");
2007		}
2008		// Listen for the ready event
2009		addthis.addEventListener('addthis.ready', addthisReady);
2010		addthis.init();
2011	}
2012}
2013
2014/* --- AddThis On Ready - The API is fully loaded --- */
2015//only fire this the first time we load the AddThis API - even when using ajax
2016function addthisReady() {
2017	if (globalDebug) {
2018		console.log("AddThis Ready");
2019	}
2020	addThisInit();
2021}
2022
2023/* --- AddThis Init --- */
2024function addThisInit() {
2025	if (window.addthis) {
2026		if (globalDebug) {
2027			console.log("AddThis Toolbox INIT");
2028		}
2029
2030		addthis.toolbox('.addthis_toolbox');
2031	}
2032}
2033// returns the depth of the element "e" relative to element with id=id
2034// for this calculation only parents with classname = waypoint are considered
2035function getLevelDepth(e, id, waypoint, cnt) {
2036	cnt = cnt || 0;
2037	if (e.id.indexOf(id) >= 0) return cnt;
2038	if ($(e).hasClass(waypoint)) {
2039		++cnt;
2040	}
2041	return e.parentNode && getLevelDepth(e.parentNode, id, waypoint, cnt);
2042}
2043
2044// returns the closest element to 'e' that has class "classname"
2045function closest(e, classname) {
2046	if ($(e).hasClass(classname)) {
2047		return e;
2048	}
2049	return e.parentNode && closest(e.parentNode, classname);
2050}
2051
2052})
2053(jQuery, window);
2054// /* ====== HELPER FUNCTIONS ====== */
2055
2056//similar to PHP's empty function
2057function empty(data) {
2058	if (typeof(data) == 'number' || typeof(data) == 'boolean') {
2059		return false;
2060	}
2061	if (typeof(data) == 'undefined' || data === null) {
2062		return true;
2063	}
2064	if (typeof(data.length) != 'undefined') {
2065		return data.length === 0;
2066	}
2067	var count = 0;
2068	for (var i in data) {
2069		// if(data.hasOwnProperty(i))
2070		//
2071		// This doesn't work in ie8/ie9 due the fact that hasOwnProperty works only on native objects.
2072		// http://stackoverflow.com/questions/8157700/object-has-no-hasownproperty-method-i-e-its-undefined-ie8
2073		//
2074		// for hosts objects we do this
2075		if (Object.prototype.hasOwnProperty.call(data, i)) {
2076			count++;
2077		}
2078	}
2079	return count === 0;
2080}
2081
2082function extend(a, b) {
2083	for (var key in b) {
2084		if (b.hasOwnProperty(key)) {
2085			a[key] = b[key];
2086		}
2087	}
2088	return a;
2089}
2090
2091// taken from https://github.com/inuyaksa/jquery.nicescroll/blob/master/jquery.nicescroll.js
2092function hasParent(e, id) {
2093	if (!e) return false;
2094	var el = e.target || e.srcElement || e || false;
2095	while (el && el.id != id) {
2096		el = el.parentNode || false;
2097	}
2098	return (el !== false);
2099}
2100
2101function mobilecheck() {
2102	var check = false;
2103	(function (a) {
2104		if (/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|
2104sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4)))check = true;
2105	})(navigator.userAgent || navigator.vendor || window.opera);
2106	return check;
2107}
2108
2109/* --- Set Query Parameter--- */
2110function setQueryParameter(uri, key, value) {
2111	var re = new RegExp("([?|&])" + key + "=.*?(&|$)", "i");
2112	separator = uri.indexOf('?') !== -1 ? "&" : "?";
2113	if (uri.match(re)) {
2114		return uri.replace(re, '$1' + key + "=" + value + '$2');
2115	}
2116	else {
2117		return uri + separator + key + "=" + value;
2118	}
2119}
2120
2121// http://stackoverflow.com/a/7557433
2122function isElementInViewport (el) {
2123
2124    //special bonus for those using jQuery
2125    if (el instanceof jQuery) {
2126        el = el[0];
2127    }
2128
2129    var rect = el.getBoundingClientRect();
2130
2131    return (
2132    rect.top >= 0 &&
2133    rect.left >= 0 &&
2134    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
2135    rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
2136    );
2137}
2138
2139function getIOSVersion(ua) {
2140	ua = ua || navigator.userAgent;
2141	return parseFloat(
2142			('' + (/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(ua) || [0,''])[1])
2143				.replace('undefined', '3_2').replace('_', '.').replace('_', '')
2144		) || false;
2145}

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.