PageSourceSearch

https://patrickcullina.com/javascript?26.11.18.1&1531511199

js patrickcullina.com collected 2026-10-04 15:59:18 UTC 38,347 bytes, 1,471 lines download raw bytes

1/**
2 * Rosetta
3 */
4
5var Site = Site || { };
6
7// Cache
8Site.$el = {
9
10	setup : function() {
11		this.window = $(window);
12		this.index  = $('#index');
13	}
14
15};
16
17// Run the setup & events methods on all Site namespaces
18$(function() {
19
20	var key, namespace;
21
22	for (key in Site) {
23		namespace = Site[key];
24		if ( namespace.hasOwnProperty('setup') && typeof namespace.setup === "function" ) {
25			namespace.setup();
26		}
27		if ( namespace.hasOwnProperty('events') && typeof namespace.events === "function" ) {
28			namespace.events();
29		}
30	}
31
32});
33
34
35var Design = {
36
37	data : {
38		stageHeight: 0,
39		stageWidth: 0,
40		textBodyStartHeight :0,
41		allThumbWidth: 0,
42		allMediaWidth: 0,
43		titleHeight: 0,
44		intextImageHeight: 0,
45		entryWidth: 0,
46		bottomMarginAdjust: 0
47	},
48
49	bindKeys : function() {
50		Cargo.Core.KeyboardShortcut.Add("Left", 37, function() {
51			Action.Project.Prev();
52			return false;
53		});
54
55		Cargo.Core.KeyboardShortcut.Add("Right", 39, function() {
56			Action.Project.Next();
57			return false;
58		});
59	},
60
61	hoverProject: function() {
62
63		// add hover class for project thumbs, if no titles or tags—add a separate class for separate styling
64
65		if (!Cargo.Model.DisplayOptions.get('title_in_thumb') && !Cargo.Model.DisplayOptions.get('tags_in_thumb')) {
66
67			hoverClass = 'hovering-no-info';
68
69			$('.thumb_info').remove();
70
71		} else {
72
73			hoverClass = 'hovering';
74
75		}
76
77		// Thumbnail hover
78		if (!Cargo.Helper.isMobile()) {
79
80			$(".thumbnails")
81				.on("mouseenter", ".project_thumb", function(e) {
82					$(this).addClass(hoverClass);
83				})
84				.on("mouseleave", ".project_thumb", function(e) {
85					$(this).removeClass(hoverClass);
86				});
87
88		}
89
90	},
91
92	setFormatting: function() {
93
94		// group sets in navigation
95
96		var navGroups = [];
97
98		$(".navigation div[data-type]").each(function() {
99
100			var type = this.getAttribute("data-type");
101
102			if ($.inArray(type, navGroups) == -1) {
103
104				// first unwrap if already wrapped
105				if ($(this).parent().hasClass("group")) {
106					$(this).unwrap();
107				}
108
109				if (type == "link" || type == "page") {
110					var items = $(".navigation div[data-type='link'], .navigation div[data-type='page']");
111					navGroups.push("link", "page");
112				} else {
113					var items = $(".navigation div[data-type='" + type + "']");
114					navGroups.push(type);
115				}
116
117				items.wrapAll("<div class='group' />");
118
119			}
120
121		});
122
123	},
124
125	captionFormatting: function() {
126
127		// formatting for captions on media images, and slideshows
128
129		// if slideshow nav is on top—(not slideshow images') captions go on bototm, else they are on top
130		if ( Cargo.Model.DisplayOptions.get("slide_nav_position") == "top" ){
131			captionClass = 'on_bottom';
132		} else {
133			captionClass = 'on_top';
134		}
135
136
137		// slideshow captions
138        $('.slideshow_caption').each(function(i){
139
140	        $(this).addClass(captionClass);
141
142        });
143
144		// take caption from the img caption attribute, and put content in an absolute position div
145		if (Cargo.Model.DisplayOptions.get('captions_view') == true) {
146
147		   	$('.project_media .img_holder img').each(function(i){
148
149			   	var caption = $(this).attr('caption');
150
151		        if ( typeof caption !== typeof undefined && caption !== false ) {
152
153		            $(this).after('<div class="caption on_bottom">' + caption + '</div>');
154
155	            }
156
157	        });
158
159		}
160
161	},
162
163	columnizeText: function() {
164
165		// columnize text on projects
166
167		var stage			= $('.entry'),
168			titleHeight		= $('.project_title').height() + parseInt($('.project_title').css('padding-bottom')),
169			footerHeight	= $('.project_footer').outerHeight(true),
170			hasText			= $('.project_content > .textcolumns').length > 0,
171			minWidth		= parseInt($('.project_content').css('min-width')),
172			projectPadding	= parseInt($('.project').css('padding-bottom')) + parseInt($('.project').css('padding-top')),
173			adjustedHeight	= Design.data.stageHeight + -Design.data.titleHeight + -projectPadding + -Design.data.bottomMarginAdjust,
174			calcColumns		= Design.data.textBodyStartHeight / adjustedHeight,
175			columnsNeeded	= Math.ceil(calcColumns);
176
177		// add a marker to see if there is overflow
178		if ($('.column-marker').length < 1) {
179			$('.textcolumns').append('<div class="column-marker" />');
180		}
181
182		// Set height of columns subtracting height of title from stage
183		$('.project_content .textcolumns').height(adjustedHeight);
184
185		// if there is no text, set a hard width on project_content instead of min-width
186		if (hasText == false) {
187			$('.project_content').width(minWidth);
188		}
189
190		//if text is taller than window stage, columnize
191		if (Design.data.textBodyStartHeight > adjustedHeight) {
192
193			$('.project_content .textcolumns').addClass('columnized');
194			$('.project_content .textcolumns').attr('columns', columnsNeeded);
195
196			columnWidth = parseInt($('.columnized').css('column-width')),
197			columnGutter = parseInt($('.columnized').css('column-gap')),
198			columnTotalWidth = columnGutter + columnWidth,
199			oneMoreColumn = 0;
200
201			// if we have a column parker past the width of columns, add another column
202			if ($('.column-marker').position().left > (columnTotalWidth * columnsNeeded) - columnGutter) {
203				oneMoreColumn = 1;
204			}
205
206			// set the column container width, and column count
207			$('.columnized').css({
208				'width' : (columnTotalWidth * (columnsNeeded + oneMoreColumn)) - columnGutter,
209				'-webkit-column-count' : columnsNeeded + oneMoreColumn,
210				   '-moz-column-count' : columnsNeeded + oneMoreColumn,
211				         'column-count': columnsNeeded + oneMoreColumn
212			});
213
214		} else {
215
216			// get rid of any column attributes that were added
217			$('.project_content').removeAttr('columns');
218			$('.project_content .textcolumns').removeAttr('style');
219			$('.project_content .textcolumns').removeClass('columnized');
220
221		}
222
223		Cargo.Event.trigger("column_complete", "Cargo");
224
225	},
226
227	noBreaksOnTop: function() {
228
229		// visually remove breaks at the top of columns, add them to the end of the content
230
231		var brAtTop = $('.break_span'),
232			spanHeight = parseInt($('.project_content').css('line-height'));
233			footer = $('.project_footer');
234
235		// determine where to add breaks that have been visually removed
236		if (footer.length > 0  && footer.is(':visible')){
237			endPlace = '.project_footer';
238		} else {
239			endPlace = 'p';
240		}
241
242		// clear top and last breaks before they are set
243		brAtTop.removeClass('top-br');
244		$('.last_span').remove();
245
246
247		$(brAtTop).each( function(el){
248
249			// set a height to each span
250			$(this).css('height', spanHeight);
251
252			// if a break is at the top of the container, remove its height, add that height to the end place
253			if (($(this).position().top - $('.project_title').outerHeight(true)) <= 1) {
254
255				$(this).addClass('top-br').css('height', '0');
256				$('.project_content ' + endPlace).append('<span class="last_span" style=" height: ' + spanHeight + 'px' + '"></span>');
257
258			}
259
260		});
261
262	},
263
264	setProjectMediaSize: function() {
265
266		// set a hard width on project media based on the combined width of its children
267
268		slideshowGutter	= ($('.slideshow').length > 0) ? $('.slideshow').length * parseInt($('.slideshow').css('margin-right')): 0;
269		projContPad	= parseInt($('.project_media').css('padding-right')),
270		mediaCount	= parseInt($('.project_media > *').length);
271
272		if ($('.project_media > *:not(.slideshow)').length > 0) {
273			Design.data.allMediaWidth = 0;
274			$('.project_media > *').each(function() {
275				Design.data.allMediaWidth += $(this).outerWidth(true);
276			});
277		}
278
279		$('.project_media').width(Design.data.allMediaWidth + projContPad + slideshowGutter);
280
281	},
282
283	setStageProperties: function() {
284
285		// set the height and width of the stage
286
287		var stagePadding = parseInt($('.thumbnails').css('padding-top')) + parseInt($('.thumbnails').css('padding-bottom'));
288
289	    Design.data.stageHeight = $('#index > div:visible').last().height();
290
291	    Design.data.stageWidth = $(window).width();
292
293	},
294
295	titleHeight: function() {
296
297		// find the height of the project title
298
299		if (Cargo.Model.DisplayOptions.get('title_in_project') && Cargo.Model.Project.GetShowTitle()) {
300
301			Design.data.titleHeight = $('.project_title').height() + parseInt($('.project_title').css('padding-bottom'));
302
303		} else {
304
305			Design.data.titleHeight = 0;
306
307		}
308
309	},
310
311	intextImageHeight: function() {
312
313		// FOR FUTURE USE (if browsers advance CSS3 columns)
314		// find the height of images inside of columns
315
316		if ($('.textcolumns p').has('span img')) {
317
318				Design.data.intextImageHeight = 0;
319
320				$('.textcolumns p span img').each(function(){
321
322					Design.data.intextImageHeight += $(this).outerHeight(true);
323
324				});
325
326		} else { Design.data.intextImageHeight = 0; }
327
328	},
329
330	setThumbSize: function() {
331
332		// set the size of thumbnails
333
334		var thumbMargin	= parseInt($('.project_thumb').css('margin-bottom')),
335			marginPerc	= (Design.data.stageHeight / thumbMargin) / 100,
336			thumbSize	= parseInt(Cargo.Model.DisplayOptions.get('thumb_size').h) + thumbMargin,
337			rowCount	= (Design.data.stageHeight + thumbMargin) / thumbSize,
338			rowsNeeded	= Math.ceil(rowCount),
339			rowHeightpx	= Design.data.stageHeight / rowsNeeded,
340			rowHeight	= Math.floor(rowHeightpx),
341			leftover	= Design.data.stageHeight - (rowHeight * rowsNeeded);
342
343		if (rowsNeeded > rowCount) {
344
345			// Set percentage height for each row depending on user's thumb height
346			$('.project_thumb').css('height', rowHeight - thumbMargin + 'px');
347
348			// Set width of each thumb based on amount of rows
349			$('.project_thumb').each(function() {
350				$(this).width(parseInt($(this).find('.thumb_image img').css('width')));
351			});
352
353			// pixels leftover if rows are an odd number
354			Design.data.bottomMarginAdjust = leftover;
355
356		}
357
358		Cargo.Event.trigger("thumbsize_complete", "Cargo");
359
360	},
361
362	setThumbSizeAfterFirstLoad: function() {
363
364		// Run setThumbSize and horizontalIsotope functions for the first time
365
366		// tell Cargo that pagination is occuring so it will not fire twice
367		if (typeof Cargo.View.Autopaginate == 'object') {
368			Cargo.View.Autopaginate.Data.is_updating = true;
369		}
370
371		var elems = $(".project_thumb[data-rowed!='true']");
372
373		// hide thumbs before until they have loaded
374		elems.css('visibility', 'hidden');
375
376		// once images have loaded
377		elems.imagesLoaded( function() {
378
379			elems.css('visibility', 'hidden');
380			Design.setThumbSize();
381			Design.horizontalIsotope();
382
383		});
384
385	},
386
387	thumbInfoClick: function() {
388
389		// make sure clicking thumb_info works in the inspector, and when in the active project thumb
390
391		var clickEvent = 'click';
392
393		// if inspector is open, clickEvent occurs on double click
394		if (location.href.match(/[\?|\&]inspecting/) !== null || parent.editor !== undefined) {
395
396			clickEvent = 'dblclick';
397
398		}
399
400		// Make thumb_info clickable
401		$(".project_thumb .thumb_info").on(clickEvent, function(){
402
403		    if ($(this).find("a").length){
404
405			    Cargo.Event.trigger("add_history", $(this).find("a:first").attr("href"));
406
407		    }
408
409		});
410
411		// if is the active project thumb, go back to start of project
412		$(".project_thumb.active .thumb_info").on(clickEvent, function(){
413
414		    setTimeout(function() {
415				Cargo.Helper.ScrollToLeft( $('#slide_container') );
416			}, 10)
417
418		});
419
420	},
421
422	horizontalIsotope: function() {
423
424		imagesLoaded( '#thumbnails', function() {
425
426			$('#thumbnails').isotope({
427
428				layoutMode: 'masonryHorizontal',
429				itemSelector: '.project_thumb',
430				sortBy: 'number',
431				transitionDuration: 0,
432				masonryHorizontal: {},
433
434			});
435
436			// for testing purposes, add class first-isotope, so we only run it once depending on whether or not 'doc ready' or 'show index' fires first
437			$('#thumbnails').addClass('first-isotope');
438
439			setTimeout( function() {
440
441				// if we are on the first page, force check for pagination
442				if (Cargo.API.Config.current_page == 1) {
443
444					if (typeof Cargo.View.Autopaginate == 'object') {
445						Cargo.View.Autopaginate.CheckForPagination();
446					}
447
448				}
449
450			}, 50);
451
452		});
453
454		// once isotope has run, add the 'data-rowed' attribute
455		$("#thumbnails .project_thumb").attr('data-rowed', 'true');
456
457		Design.firstImageIsLoaded();
458
459	},
460
461	firstImageIsLoaded: function() {
462
463		// if the first image has been loaded, show the project thumbnials, and tell pagination it is not firing
464
465		var imgLoad = imagesLoaded('#thumbnails');
466
467		imgLoad.on( 'always', function() {
468
469			var is_loaded = false;
470
471			// find out if one image has been loaded (if one image is loaded we can assume we have the height / width info for the rest of the images)
472			for ( var i = 0, len = imgLoad.images.length; i < len; i++ ) {
473
474				image = imgLoad.images[i];
475
476				if (typeof image == "object" && image.isLoaded) {
477
478					is_loaded = true;
479
480				}
481
482			}
483
484			// if one image is loaded:
485			if (is_loaded == true) {
486
487				// fade in the new projects
488				$(".project_thumb[data-rowed='true']").css({opacity: 0, visibility: 'visible'}).animate({opacity: 1}, 400);
489
490				// move the autopagination loader to the middle of the screen, and right of the projects already loaded
491				$('#autopaginate_loader').css('display', 'none').addClass('after-load');
492
493				// tell Cargo pagination it is no longer firing
494				if (typeof Cargo.View.Autopaginate == 'object') {
495					Cargo.View.Autopaginate.Data.is_updating = false;
496				}
497
498			}
499
500		});
501
502	},
503
504	isotopeOnPagination: function() {
505
506		// append new thumbnails to isotope
507		if (typeof Cargo.View.Autopaginate == 'object') {
508			Cargo.View.Autopaginate.Data.is_updating = true;
509		}
510
511		// hide thumbnails that have not been data-rowed
512		var elems = $(".project_thumb[data-rowed!='true']");
513		elems.css('visibility', 'hidden');
514
515		var imgLoad = imagesLoaded(elems);
516
517		imgLoad.on( 'always', function() {
518
519			var is_loaded = false;
520
521			// find out if one image has been loaded (if one image is loaded we can assume we have the height / width info for the rest of the images)
522			for ( var i = 0, len = imgLoad.images.length; i < len; i++ ) {
523
524				image = imgLoad.images[i];
525
526				if (typeof image == "object" && image.isLoaded) {
527
528					is_loaded = true;
529
530				}
531
532			}
533
534			// if one image has been loaded:
535			if (is_loaded == true) {
536
537				// set new thumbnails size
538				Design.setThumbSize();
539
540				// append the new thumbnails
541				$('#thumbnails').isotope( 'appended', elems);
542
543				// Add 'data-rowed' attribute and display loaded thumbs
544				elems.attr('data-rowed', 'true');
545				elems.css({opacity: 0, visibility: 'visible'}).animate({opacity: 1}, 400);
546
547				// if we've already paginated and thumbnails is not wide enough to trigger pagination again
548				if ($('#thumbnails').width() < $(window).width() + 300) {
549
550					setTimeout(function() {
551
552						if (typeof Cargo.View.Autopaginate == 'object') {
553							Cargo.View.Autopaginate.CheckForPagination();
554						}
555
556					}, 100)
557
558				}
559
560				// tell Cargo pagination it is no longer firing
561				if (typeof Cargo.View.Autopaginate == 'object') {
562					Cargo.View.Autopaginate.Data.is_updating = false;
563				}
564
565			}
566
567		});
568
569	},
570
571	dataRows: function() {
572
573		// Add attribute of data-rowed, once thumbnails have been isotoped
574
575		thumbs = $(".project_thumb[data-rowed!='true']");
576
577		thumbs.attr('data-rowed', 'true');
578
579	},
580
581	adjustStage: function() {
582
583		// Adjust the stage height of projects after thumbnail rows have been calculated so project_media aligns with thumbnails
584
585		var currentPad = parseInt($('.project').css('padding-bottom'));
586
587		Cargo.Plugins.elementResizer.setOptions({
588
589			forceVerticalMargin: $(window).height() - Design.data.stageHeight + Design.data.bottomMarginAdjust + currentPad
590
591		});
592
593		$('.project').addClass('adjust_stage');
594
595		Cargo.Plugins.elementResizer.refresh();
596
597		$('.project_media').css('visibility', 'visible');
598
599		Design.setResizerOptions();
600
601	},
602
603	setResizerOptions: function() {
604
605		// set vertical & horizontal margins on element resizer
606
607		if (Cargo.Helper.isPhone()) {
608
609			var container = screen.width;
610			var extra = 40;
611			var parent = $('.entry').width();
612
613			if (Cargo.Model.DisplayOptions.get('captions_view') == true) {
614
615				var containerBottom = parseInt($('.container').css('bottom'));
616
617			} else {
618
619				var containerBottom = 0;
620
621			}
622
623		} else {
624
625			var container = 0;
626			var parent = 0;
627			var extra = 0;
628			containerBottom = 0;
629
630		}
631
632		Cargo.Plugins.elementResizer.setOptions({
633			forceVerticalMargin: $(window).height() - $('.entry').height() + containerBottom,
634			forceHorizontalMargin: parent - container + extra
635		});
636
637	},
638
639	imageScroll: function() {
640
641		// scroll project_media image based on location in the window
642
643		var media 					= $('.project_media .img_holder img'),
644			moreThanOne				= $(media).length > 1,
645			scrollContainer			= $('#slide_container'),
646			projectContent			= $('.project_content').width() + $('.project_content').css('margin-right'),
647			projectLeftMargin		= parseInt($('.project').css('margin-left')),
648			entryWidth				= $('.entry').width(),
649			stageWidthHalf			= Design.data.stageWidth / 2,
650			thumbnailLocation		= $('#thumbnails').position().left,
651			thumbnailPadding		= parseInt($('#thumbnails').css('margin-left')),
652			noThumbsProj			= Cargo.Model.DisplayOptions.get('thumbs_below_projects') && Cargo.Helper.GetCurrentPageType() == "project",
653			noThumbsPage			= Cargo.Model.DisplayOptions.get('thumbs_below_pages') && Cargo.Helper.GetCurrentPageType() == "page",
654			imgPadding				= parseInt($('.project_media img').css('margin-right'));
655
656
657		if (moreThanOne) {
658			// if more than 1 image, identify first image
659
660			$(media).first().addClass('first');
661
662		} else if (!moreThanOne && (!noThumbsProj && !noThumbsPage)) {
663			// else, if only one image and no thumbs to the right, identify as loner
664
665			$(media).first().addClass('loner');
666
667		}
668
669		// identify last image
670		$(media).last().addClass('last');
671
672
673		// for each image
674		media.each(function() {
675
676			var	lonerImg 		= $(this).hasClass('loner'),
677				distanceRightH	= this.getBoundingClientRect().right;
678
679			// hover conditions
680			$(this).on('mouseenter', function(e) {
681
682				e.preventDefault();
683
684				// if the image is a loner and is completely in view, don't use pointer
685				if (lonerImg && (distanceRightH < $(window).width())) {
686					$(this).css('cursor', 'default');
687				} else {
688					$(this).css('cursor', 'pointer');
689				}
690
691			}).on('mouseleave', function(e) {
692
693				$(this).css('cursor', 'default');
694
695			});
696
697
698			// click conditions
699			$(this).on('click', function(e) {
700
701				e.preventDefault();
702
703				// image properties
704				var	imgWidth		= $(this).width(),
705					imgLeft			= $(this).closest('.img_holder').position().left + projectLeftMargin,
706					inView			= $(this).is(':in-viewport'),
707					lastImg			= $(this).hasClass('last'),
708					firstImg		= $(this).hasClass('first'),
709					imgRight		= imgLeft + imgWidth,
710					distanceLeft	= this.getBoundingClientRect().left,
711					distanceRight	= this.getBoundingClientRect().right,
712					distFromRight	= Design.data.stageWidth - distanceRight,
713					transitionFlag	= false;
714
715				// image position conditions
716					windowLeft		= $(scrollContainer).scrollLeft(),
717					windowRight		= windowLeft + Design.data.stageWidth,
718					isOffRight		= inView && (Design.data.stageWidth < distanceRight),
719					isOffLeft		= inView && (0 > distanceLeft),
720					isOff			= isOffLeft || isOffRight,
721					inFullView		= inView && !isOffRight && !isOffLeft,
722					isCenter		= inView && (distanceLeft < stageWidthHalf) && (distanceRight > stageWidthHalf);
723
724				// next image properties
725				if (!lastImg) {
726
727					nextImg			= $(this).closest('.img_holder').next(),
728					prevImg			= $(this).closest('.img_holder').prev(),
729					nextImgPos		= $(nextImg).position().left + projectLeftMargin,
730					nextImgPosMid	= ((Design.data.stageWidth - $(nextImg).width() + imgPadding) / 2);
731
732				}
733
734				// go to this image
735				if ((transitionFlag == false) &&
736					(	(!inFullView && !isCenter && !firstImg && !lastImg && (!nextImg.is(':in-viewport')) && (!prevImg.is(':in-viewport')))
737					||	(isOffRight && !lastImg && !firstImg && !isCenter)
738					||	(isOffLeft && !lastImg && !firstImg && !isCenter)
739					||	((firstImg && isOffRight && !isOffLeft) || (firstImg && isOffLeft && !isOffRight))
740					||	(!inFullView && !firstImg && ((nextImg.is(':in-viewport')) || (prevImg.is(':in-viewport'))))
741					||	(firstImg && (distanceRight < stageWidthHalf) && inFullView)
742					||	(lastImg && isOff)
743					||	(inFullView && (distanceRight < stageWidthHalf) && !lastImg && !isCenter && !firstImg)
744					||	(inFullView && (distanceLeft > stageWidthHalf) && !lastImg && !isCenter)
745					||	(inFullView && !isOff && !lastImg && !firstImg && isCenter && (nextImg == lastImg))
746						)) {
747
748								transitionFlag = true;
749								$(scrollContainer).animate({
750									scrollLeft: imgLeft - ((Design.data.stageWidth - imgWidth) / 2)
751								}, 300, 'easeInOutCubic', function() {
752									transitionFlag = false;
753								});
754
755
756				// go to the next image
757				} else if ((transitionFlag == false) &&
758					(	(inFullView && firstImg && !lastImg)
759					||	(inFullView && !isOff && !lastImg && !firstImg && isCenter && (nextImg !== lastImg))
760					||	(inFullView && firstImg && !lastImg && !isCenter && (distanceRight < stageWidthHalf))
761					||	(isOff && !lastImg && !firstImg && isCenter && (!nextImg.is(':in-viewport')) && (!prevImg.is(':in-viewport')))
762					||	(!isOff && !lastImg /* && !firstImg */ && isCenter && (nextImg.is(':in-viewport')) && (prevImg.is(':in-viewport')))
763					||	(firstImg && isOffRight && isOffLeft)
764						)) {
765
766								transitionFlag = true;
767								$(scrollContainer).animate({
768									scrollLeft: nextImgPos - nextImgPosMid
769								}, 300, 'easeInOutCubic', function() {
770									transitionFlag = false;
771								});
772
773				// if is the last image
774				} else if ((transitionFlag == false) &&
775						(inFullView && lastImg && isCenter && !lonerImg)
776					||	(!isOff && lastImg && isCenter && lonerImg && (windowLeft > 0))
777					||	(inFullView && lastImg && !lonerImg && !isCenter && (distanceLeft > stageWidthHalf) && (!noThumbsPage || !noThumbsProj))
778						) {
779
780								// if thumbnails are visible next to project / pages, animate to them
781								if (!noThumbsPage || !noThumbsProj) {
782
783									transitionFlag = true;
784									$(scrollContainer).animate({
785										scrollLeft: (thumbnailLocation + thumbnailPadding) - stageWidthHalf
786									}, 400, 'easeOutExpo', function() {
787										transitionFlag = false;
788									});
789
790								// or animate to beginning of the project / page
791								} else {
792
793									transitionFlag = true;
794									$(scrollContainer).animate({
795										scrollLeft: 0
796									}, 250, 'easeInOutCubic', function() {
797										transitionFlag = false;
798									});
799								}
800
801				// if is a loner (completely in viewport and there is no content to the right)
802				} else if ((transitionFlag == false) &&
803						(lonerImg && inFullView && (windowLeft <= 0) && (!noThumbsPage || !noThumbsProj))
804						) {
805
806							// do nothing
807
808				}
809
810			});
811
812		});
813
814	},
815
816	Mobile : {
817		init: function() {
818
819			if ( Cargo.Helper.isPhone() ){
820
821				$('body').addClass('phone');
822
823				$('head').append('<meta name="viewport" content="width=device-width">');
824
825				// add max-width to slide
826				$('#slide_container').css("max-width", screen.width + "px");
827
828				$('.header_text a, .navigation_toggle').bind( "touchstart", function(){
829					return true;
830				});
831
832				$('.navigation_toggle').bind("click", function(){
833
834					Design.Mobile.toggleNav();
835
836				});
837
838				$('.navigation').bind( "touchstart", function(e){
839
840					var touchtarget = $(e.target);
841
842					if ( !touchtarget.is('a') ) {
843
844						Design.Mobile.toggleNav();
845
846					}
847
848				});
849
850				Cargo.Event.on("project_load_complete", function(pid) {
851
852					Design.Mobile.toggleNav(true);
853
854				});
855
856			} else if ( Cargo.Helper.isTablet() ) {
857
858				ratio = window.devicePixelRatio;
859
860				$('body').addClass('tablet');
861				$('.container').css("max-width", (screen.width * ratio) + "px");
862
863			} else {
864
865				$('body').addClass('desktop');
866
867			}
868
869			// Add attribute once this is done
870			$('body').attr('data-mobileload', 'true');
871		},
872
873		toggleNav: function(closeNav){
874
875			if ( $('.navigation_toggle').is(".active") || closeNav ){
876
877				$(".navigation, .navigation_toggle").removeClass("active");
878
879			} else {
880
881				$(".navigation, .navigation_toggle").addClass("active");
882
883			}
884
885		}
886	}
887};
888
889
890/*********************************************
891 *
892 * Helpers
893 *
894 *********************************************/
895
896 Site.Helper = {
897
898	formatText : function(node, includeWhitespaceNodes) {
899
900		var validTags			= ['img', 'object', 'video', 'audio', 'iframe', 'div'],
901			keepClass 			= ['in-text'],
902			nodeContents		= node.contents(),
903			newPageFromCache	= true,
904			textPages			= {},
905			pageCache			= [],
906			pageCount			= 0;
907
908		// inline helper functions
909		var _isValidText = function(txt, strict) {
910
911			if (txt !== undefined) {
912				txt = txt.replace(/<!--([\s\S]*?)-->/mig, "");
913				txt = txt.replace(/(\r\n|\n|\r|\t| )/gm, "");
914				txt = txt.replace(/[^A-Za-z0-9\s!?\.,-\/#!$%\^&\*;:{}=\-_`~()[[\]]/g, "");
915
916				if (txt.length > 0) {
917					return true;
918				}
919			} else {
920				if (strict) {
921					return false;
922				} else {
923					return true;
924				}
925			}
926
927			return false;
928
929		}
930
931		var _getTag = function(el) {
932
933			if (typeof el !== "undefined") {
934				var tag = el.tagName;
935
936				if (typeof tag === "undefined") {
937					tag = 'text';
938				}
939
940				return tag.toLowerCase();
941			}
942
943		}
944
945		nodeContents.each(function(key, val) {
946
947			if ($.inArray(_getTag(val), validTags) >= 0) {
948				// Don't do anything here
949				if($.inArray($(val).attr('class'), keepClass) >= 0) {
950					pageCache.push(val);
951				}
952
953			} else {
954				if (_isValidText(val.data) && val.nodeType != 8) {
955					pageCache.push(val);
956				}
957			}
958
959		});
960
961		// Still some stuff left in cache
962		if (pageCache.length > 0) {
963
964			// Check if it needs a new page
965			for (var i = 0; i < pageCache.length; i++) {
966				if (pageCache[i].nodeType == 8 || pageCache[i].nodeName == "SCRIPT" || pageCache[i].nodeName == "STYLE") {
967					// Contains text, create new page
968					newPageFromCache = false;
969				}
970			}
971
972			if (newPageFromCache) {
973				// Create new page
974				textPages[pageCount] = pageCache;
975				pageCache = [];
976				pageCount++;
977			} else {
978				for (var i = 0; i < pageCache.length; i++) {
979					// Dump and hide remaining elements
980					$(pageCache[i]).hide().appendTo($('.project_footer'));
981				}
982			}
983
984		}
985
986		$.each(textPages, function(key, arr) {
987
988			var breaks = 0;
989			$.each(arr, function(key, el) {
990				if (el.nodeName == "BR") {
991					 breaks++;
992				}
993
994			});
995
996			if (breaks < arr.length) {
997				var first = arr[0],
998					parent = $('<p />');
999
1000				$(first).before(parent);
1001
1002				$.each(arr, function(key, el) {
1003					$(el).appendTo(parent);
1004				});
1005
1006
1007
1008			} else {
1009
1010				$.each(arr, function(key, el) {
1011					$(el).remove();
1012				});
1013			}
1014
1015		});
1016
1017		$('.project_content p').each(function(key) {
1018
1019			// Strip leading <br>
1020			var found_text = false;
1021			$(this)
1022				.contents()
1023				.filter(function() {
1024					if(this.nodeName != "br") {
1025						found_text = true;
1026					}
1027					return (!found_text);
1028				})
1029				.remove();
1030
1031		});
1032
1033	}
1034
1035 };
1036
1037 Site.Project = {
1038
1039	 Data : {
1040
1041		'file_name'			: 'thumb_size.json',
1042		'size_var'			: 'thumb_size_list',
1043		'thumb_size_list'	: false,
1044		'open'				: false
1045
1046	},
1047
1048	loadComplete : function() {
1049
1050		setTimeout(function(){
1051			Site.Project.Data.open = true;
1052		}, 100);
1053
1054		// Cache
1055		var self			= Site.Project,
1056			data			= { },
1057			ignoreList		= '.project_title, .project_footer, span img, .in-text, .in-text *',
1058			mediaElements	= 'img, video, iframe, object, audio, embed, div';
1059
1060		// Cache
1061		Site.$el.entry          = $('.entry');
1062		Site.$el.projectContent = $('.project_content');
1063		Site.$el.projectMedia   = $('.project_media');
1064
1065		// Only split on projects
1066		if ( Cargo.Helper.GetCurrentPageType() =="project" || Cargo.Helper.GetCurrentPageType() =="page" ){
1067			// Split the content into blocks
1068			Site.Helper.formatText(Site.$el.projectContent);
1069
1070			// Move elements into containers
1071			Site.$el.projectContent
1072				.children(mediaElements)
1073				.not(ignoreList)
1074				.appendTo(Site.$el.projectMedia);
1075		};
1076
1077		Site.$el.projectMedia.append('<img src="/_gfx/spacer.gif" class="spacer" width="1" height="2000" style="pointer-events:none; margin: 0; padding: 0; position: absolute; z-index: -99">');
1078
1079		if ($('.project_content p').length > 0) {
1080			// Make double <br> into single
1081			$(".project_content p").html($(".project_content p").html().replace(/(<br\s*\/?>){2,2}/gi,'<br>'));
1082			// Strip the first <br> if it is first
1083			$(".project_content p").html($(".project_content p").html().replace(/^(<br\s*\/?>)/,''));
1084			// Wrap everything
1085			$('.project_content p').wrap('<div class="textcolumns"></div>');
1086		}
1087
1088		// Wrap all breaks in spans to measure their position
1089		$('.project_content p br').wrap('<span class="break_span" />');
1090
1091		// If embedded objects have 100%, give them a max width of the user's max image width
1092		var embeddedMedia = $('.project_media > iframe, .project_media > object, .project_media > video, .project_media > audio, .project_media > embed');
1093
1094		$(embeddedMedia).each(function() {
1095			if ($(this).attr('width') == '100%') {
1096				$(this).attr('width', parseInt(Cargo.Model.DisplayOptions.GetImageWidth()));
1097			}
1098		});
1099
1100		// Prepend the title to the project content container, set width to text column width
1101		columnWidth = parseInt($('.project_content .textcolumns').css('width'));
1102		$('.project_title').prependTo('.project_content').css('maxWidth', columnWidth + 'px');
1103
1104		// If there is no title and no content, remove the content div
1105
1106		var title_exists = Cargo.Model.DisplayOptions.get('title_in_project') && Cargo.Model.Project.get("show_title") && $('.project_title').css("display") != "none";
1107		var content_exists = $.trim( $('.project_content').html()).length > 0 && $('.project_content').css("display") != "none";
1108		var footer_exists = $('.project_footer').css("display") != "none" && $.trim( $('.project_footer > *').not('.editlink').html()).length > 0;
1109
1110		if ( !title_exists && !content_exists && !footer_exists){
1111			$('.project_content, .project_footer').hide();
1112		}
1113
1114		// Remove project media if no content
1115		if ((!$.trim( $('.project_media').html() ).length )) {
1116			$('.project_media').remove();
1117		}
1118
1119		// Remove footer if no content
1120		if ((!$.trim( $('.project_footer').html() ).length )) {
1121			$('.project_footer').remove();
1122		}
1123
1124		//Remove classes before adding them conditionally
1125		$('body #thumbnails').removeClass('inline-block');
1126
1127		// If thumbs are set next to projects make them inline block
1128		if ((Cargo.Model.DisplayOptions.get('thumbs_below_pages') && Cargo.Helper.GetCurrentPageType() == "page") || (Cargo.Model.DisplayOptions.get('thumbs_below_projects') && Cargo.Helper.GetCurrentPageType() == "project")) {
1129			$('body #thumbnails').addClass('inline-block');
1130		} else {
1131			$('.project_media > *:last-child').css('margin-right', '0');
1132		}
1133
1134		// if no project media, no margin right
1135		if ($('.project_media').length <= 0) {
1136			$('.project_content').css('margin-right', '0');
1137		}
1138
1139		// Append the footer if there is text to the text container, or append it to project_content
1140		if ($('.textcolumns').length > 0) {
1141			$('.project_footer').appendTo('.project_content .textcolumns');
1142		} else {
1143			$('.project_footer').appendTo('.project_content');
1144		}
1145
1146		// add img_holder around each project media img
1147		$('.project_media > img').not('.spacer').wrap('<div class="img_holder" data-elementresizer-no-centering />');
1148
1149
1150		// Set variables for calculating ColumnizeText
1151	    Design.setStageProperties();
1152	    Design.titleHeight();
1153		Design.intextImageHeight();
1154
1155		// Find the height of the content before it is columnized
1156		Design.data.textBodyStartHeight = $('.project_content .textcolumns').height() + Design.data.intextImageHeight;
1157
1158		// Add event to fire things when it is complete
1159		Cargo.Event.trigger("formatting_complete", "Cargo");
1160
1161	},
1162
1163	mediaLinks: function () {
1164
1165		// if user wants an image to have an external link (they must wrap with a blank div)
1166		// Make sure this div works in element resizer and has a set heigh & width
1167
1168		$('.project_media > div').each(function() {
1169
1170			if (this.attributes.length === 0 ){
1171
1172				imgPadding = parseInt($('.project_media img').css('margin-right'));
1173				this_Width = $(this).find('img').width();
1174
1175				$(this).attr('data-elementresizer-no-centering', '');
1176				$(this).find('a').attr('data-elementresizer-no-centering', '');
1177
1178				$(this).width(this_Width + imgPadding);
1179				$(this).find('a').width(this_Width + imgPadding);
1180				$(this).find('img').css('margin-left', '0');
1181
1182			}
1183
1184		});
1185
1186	}
1187
1188};
1189
1190/**
1191 * Events
1192 */
1193
1194$(function() {
1195
1196	// run mobile init if it has not already
1197	if (!$('body').hasClass('phone')) {
1198		Design.Mobile.init();
1199	}
1200
1201	// display the pagination loader
1202	$('#autopaginate_loader').css('display', 'block');
1203
1204	// set first thumbsize and run first isotope
1205	Design.setThumbSizeAfterFirstLoad();
1206	Design.dataRows();
1207
1208	// if not on the phone, format sets
1209	if (!Cargo.Helper.isPhone()) {
1210		Design.setFormatting();
1211	}
1212
1213	Cargo.Core.ReplaceLoadingAnims.init();
1214	Design.bindKeys();
1215	Design.hoverProject();
1216
1217	// hide the project until ready to show
1218	$('.project').css('visibility', 'hidden');
1219
1220});
1221
1222
1223// Window Resize
1224$(window).on('resize', function() {
1225
1226    Design.setStageProperties();
1227	Design.setThumbSize();
1228	Design.horizontalIsotope();
1229
1230	Design.columnizeText();
1231
1232	Site.Project.mediaLinks();
1233
1234	if (Cargo.Helper.isMobile()) {
1235		setTimeout(function(){
1236			Design.setResizerOptions();
1237		}, 250)
1238	}
1239});
1240
1241// Project Load Complete
1242Cargo.Event.on("project_load_complete", function(pid) {
1243
1244	// load complete sometimes fires before doc.ready
1245	// For direct links, this is a problem, so delay this event
1246	if($("body[data-mobileload!='true']").length == 1) {
1247		setTimeout(function() {
1248			Cargo.Event.trigger("project_load_complete", pid);
1249		}, 100);
1250		return false;
1251	}
1252
1253	// Remove active state on Set link if thumbnails are hidden
1254	if ( (Cargo.Helper.GetCurrentPageType() =="page" && !Cargo.Model.DisplayOptions.get("thumbs_below_pages") && Cargo.Helper.IsOnSet()) ) {
1255
1256		$('.set_link.active').removeClass("active");
1257
1258	}
1259
1260	Design.setStageProperties();
1261
1262	// if we haven't already isotoped, run the first isotope
1263	if ($('#thumbnails').hasClass('first-isotope')) {
1264		Design.setThumbSizeAfterFirstLoad();
1265	}
1266
1267	Site.Project.loadComplete();
1268
1269	Site.Project.mediaLinks();
1270
1271	$('.project_media').width(Design.data.allMediaWidth);
1272
1273	Design.setProjectMediaSize();
1274
1275	Design.setResizerOptions();
1276
1277	Design.thumbInfoClick();
1278
1279	// scroll to the left on load
1280	Cargo.Helper.ScrollToLeft( $('#slide_container') );
1281
1282	// scroll to left of project if you click on the active project thumb
1283	$('.project_thumb .active .thumb_image').click( function() {
1284		setTimeout(function() {
1285			Cargo.Helper.ScrollToLeft( $('#slide_container') );
1286		}, 10)
1287	});
1288
1289
1290});
1291
1292
1293
1294Cargo.Event.on("project_load_start", function() {
1295
1296	$('.project_media').css('visibility', 'hidden');
1297
1298});
1299
1300Cargo.Event.on("formatting_complete", function() {
1301
1302	Design.setThumbSize();
1303
1304	$('.project').css('visibility', 'visible');
1305
1306	Design.captionFormatting();
1307
1308	Design.columnizeText();
1309
1310	if (!Cargo.Helper.isMobile() && Cargo.Model.DisplayOptions.get('image_scroll') == true && Cargo.Model.DisplayOptions.get('lightbox_view') == false) {
1311
1312		Design.imageScroll();
1313
1314	}
1315
1316	// Re-check for audio components that have moved
1317	Cargo.Core.Audio.CheckForAudio();
1318
1319
1320});
1321
1322Cargo.Event.on("thumbsize_complete", function() {
1323
1324		Design.adjustStage();
1325
1326});
1327
1328
1329Cargo.Event.on("elementresizer_update_complete", function() {
1330// 	Set width for project media
1331	$('.project_media').width(Design.data.allMediaWidth);
1332	Design.setProjectMediaSize();
1333
1334});
1335
1336Cargo.Event.on("pagination_start", function() {
1337
1338	// add some extra width to thumbnails container, so we don't run pagination if thumbnails end in the center of the window
1339	$("#thumbnails").width($("#thumbnails").width()+ 500);
1340
1341});
1342
1343Cargo.Event.on("pagination_complete", function() {
1344
1345	Design.isotopeOnPagination();
1346
1347	Design.hoverProject();
1348
1349});
1350
1351Cargo.Event.on("column_complete", function() {
1352
1353	Design.setProjectMediaSize();
1354	Design.noBreaksOnTop();
1355
1356
1357});
1358
1359Cargo.Event.on("project_change", function() {
1360
1361	$('body #thumbnails').removeClass('inline-block');
1362
1363	if (!$('.project').hasClass('adjust_stage')) {
1364		setTimeout(function() {
1365			Design.adjustStage();
1366		}, 100)
1367	}
1368
1369});
1370
1371Cargo.Event.on("show_index_start", function() {
1372
1373	// run mobile init if it has not already
1374	if (!$('body').hasClass('phone')) {
1375		Design.Mobile.init();
1376	}
1377
1378	// make sure the project thumbs are hidden
1379	$(".project_thumb").css('visibility', 'hidden');
1380
1381	// scroll everything to left
1382	setTimeout(function() {
1383		Cargo.Helper.ScrollToLeft( $('#slide_container') );
1384	}, 10)
1385
1386	Design.setStageProperties();
1387	Design.setProjectMediaSize();
1388
1389});
1390
1391Cargo.Event.on("admin_edit_load_complete", function() {});
1392
1393Cargo.Event.on("show_index_complete", function(pid) {
1394
1395	Design.setStageProperties();
1396
1397	// make sure un-isotoped images are hidden
1398	$(".project_thumb[data-rowed!='true']").css('visibility', 'hidden');
1399
1400	// if thumbnails have been isotoped, set the first thumb size
1401	if ($('#thumbnails').hasClass('first-isotope')) {
1402		Design.setThumbSizeAfterFirstLoad();
1403	}
1404
1405	// remove inline-block class from thumbnails for index
1406	$('body #thumbnails').removeClass('inline-block');
1407
1408});
1409
1410
1411Cargo.Event.on("slideshow_on", function(el, obj) {
1412
1413	slide_length = $('.slideshow').length;
1414	slide_pad = parseInt($('.slideshow').css('margin-right'));
1415	default_img_w = parseInt(Cargo.Model.DisplayOptions.get('image_width'));
1416
1417	Design.data.allMediaWidth = slide_length * (slide_pad+default_img_w);
1418
1419	$('.project_media').width(Design.data.allMediaWidth);
1420
1421	Design.setProjectMediaSize();
1422
1423});
1424
1425Cargo.Event.on("reseed_navigation_complete", function() {
1426
1427	// hide the index before the page reloads
1428	$('#index').css('visibility', 'hidden');
1429
1430	// if not on the phone, format sets
1431	if (!Cargo.Helper.isPhone()) {
1432		Design.setFormatting();
1433	}
1434
1435	// hard reload the page
1436	document.location.href = document.location.href;
1437
1438});
1439
1440Cargo.Event.on("navigation_set_toggle", function() {});
1441
1442Cargo.Event.on("first_project_collection_reset", function() {
1443
1444	// if has isotope, destroy isotope
1445	if ($(".thumbnails").hasClass('isotope')) {
1446		$(".thumbnails").isotope('destroy');
1447	}
1448
1449	Design.setStageProperties();
1450
1451	Design.setResizerOptions();
1452
1453});
1454
1455Cargo.Event.on("fullscreen_destroy_hotkeys", function() {
1456
1457    Design.bindKeys();
1458
1459});
1460
1461Cargo.Event.on('fullscreen-initialized', function(fullscreen_view){
1462    fullscreen_view.prevent_smart_image_picking = true;
1463});
1464
1465// easeOutExpo easing effect (used in imageScroll)
1466jQuery.extend( jQuery.easing,
1467	{
1468		easeOutExpo: function (x, t, b, c, d) {
1469		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
1470	},
1471});

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.