// The carousel node data loaded from the server and used to populate the site
var nodes = null;
// The carousel html element
var carousel = null;
// The currently selected carousel node
var selectedNode = null;
// timer used for automated carousel scrolling
var scrollInterval = null;
// scroller support
var activeScroller = null;
var autoScrollAmountMin = 4;
var autoScrollAmountMax = 18;
var autoScrollDelay = 8;
var autoScrollAmount = autoScrollAmountMin;
// width of the prev/next photo scroller nav arrow areas
var photoScrollerWidth = 36;
var showEnders = true;
// timer used for initiating the display of preview content
var previewTimer = null;
var clickThrottle = null;
// binding variable
var prebound = false;
function setSelectedNode(nodeId) {
var nodeThumb = $("#" + nodeId + " div.node-thumb");
if(nodeThumb != null && nodeThumb.length > 0) {
var node = getNodeObject(nodeThumb);
if(node != null) {
expandParents(node);
}
nodeThumbClicked(nodeThumb, true, true);
}
}
/**
* Defines a simple dimension
*
* @param width
* @param height
*/
function Dimension(width, height) {
this.width = width;
this.height = height;
}
/**
* Defines a simple rect
*
* @param top
* @param right
* @param bottom
* @param left
*/
function Rect(top, right, bottom, left) {
this.top = top;
this.right = right;
this.bottom = bottom;
this.left = left;
this.width = function() {
return this.left + this.right;
};
this.height = function() {
return this.top + this.bottom;
};
this.contains = function(x, y) {
return (x >= this.left && x <= this.right) && (y >= this.top && y <= this.bottom);
};
this.toString = function() {
return this.top + "," + this.right + "," + this.bottom + "," + this.left;
};
}
/**
* Creates a cookie
*
* @param name The cookie name
* @param value The value to set for the cookie
* @param days The number of days to expire the cookie in
*/
function createCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
}
document.cookie = name + "=" + value + expires + "; path=/";
}
/**
* Reads a cookie value given the cookie name
*
* @param name The name of the cookie to read
* @param defaultVal The default value to return if the cookie is not found
*
* @returns The cookie value is returned
*/
function readCookie(name, defaultVal) {
var val = null;
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1, c.length);
}
if (c.indexOf(nameEQ) == 0) {
val = c.substring(nameEQ.length, c.length);
}
}
return val != null ? val : defaultVal;
}
/**
* Deletes a cookie
*
* @param name The name of the cookie to delete
*/
function eraseCookie(name) {
createCookie(name, "", -1);
}
/**
* Logs a dbg message
*/
function logg(text) {
//$("#logg").text(text + "");
//console.log(text + "");
}
// The default dimension used for sizing and scaling thumb nails
var defaultThumbSize = new Dimension(110, 110);
var defaultTopThumbSize = new Dimension(110, 61);
var defaultBottomThumbSize = new Dimension(110, 60);
/**
* Scales the specified dimension to fit within a max size
*
* @param dimension The dimension to be scaled
* @param maxDimension The dimension to scale to
* @return A rescaled dimension is returned
*/
function scaleDimension(dimension, maxDimension) {
var scale = new Dimension(dimension.width, dimension.height);
var resizeRatio;
while(scale.width > maxDimension.width || scale.height > maxDimension.height) {
if (scale.width > maxDimension.width) {
// Resize width, then height proportionally
resizeRatio = maxDimension.width / scale.width;
scale.width = maxDimension.width;
scale.height = Math.floor(scale.height * resizeRatio);
}
if (scale.height > maxDimension.height) {
// Resize height, then width proportionally
resizeRatio = maxDimension.height / scale.height;
scale.height = maxDimension.height;
scale.width = Math.floor(scale.width * resizeRatio);
}
}
return scale;
}
/**
* Gets the value of a query parameter passed in the document URL
*
* @param name The name of a query parameter to find
* @param defaultVal A default value to return if the query parameter is not found
*
* @return The value if found, otherwise the default value or null
*/
function getQueryParamVal(name, defaultVal) {
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var findExp = "[\\?&]" + name + "=([^]*)";
var regExp = new RegExp(findExp);
var v = defaultVal;
var result = regExp.exec(window.location.href);
if(result != null) {
v = decodeURIComponent(result[1]);
v = v.replace(/\+/g, ' ');
}
return v;
}
/**
* Gets the node object associated with the specified element
*
* @param elem
* @returns The node object, null if no data is associated
*/
function getNodeObject(elem) {
var nodeObj = null;
var parentNodeElem = null;
var sibs = $(elem).prevAll(".node");
if(sibs.length > 0) {
parentNodeElem = sibs.first();
}
if(parentNodeElem == null) {
var parents = $(elem).parents(".node");
if(parents.length > 0) {
parentNodeElem = parents.first();
}
}
if(parentNodeElem != null) {
var nodeId = $(parentNodeElem).attr("id");
nodeId = nodeId.replace(/_starter/, '');
nodeId = nodeId.replace(/_ender/, '');
nodeObj = $(carousel).data(nodeId);
}
return nodeObj;
}
/**
* Dynamically layout the page. Used for dynamic sizing events like when the
* user resizes the browser or maximizes the window.
*/
function doLayout() {
// fit the content div container into the available display
var docHeight = $(window).height();
var docWidth = $(window).width();
$("#content").css("height", docHeight + "px");
var newHeight = docHeight - 48;
var newWidth = docWidth - Math.floor(docWidth * 0.12);
var orientation;
if($(".node-display.horizontal").length > 0 && $(".carousel.horizontal").length > 0) {
// Current orientation is horizontal
orientation = "horizontal";
$(".node-display.horizontal").css("height", ((newHeight - $(".carousel.horizontal").height())) + "px");
$(".node-display.horizontal").css("width", newWidth + "px");
}
else if($(".node-display.vertical").length > 0 && $(".carousel.vertical").length > 0) {
// Current orientation is vertical
orientation = "vertical";
newWidth -= $(".carousel.vertical").width();
$(".node-display.vertical").css("height", newHeight + "px");
$(".node-display.vertical").css("width", newWidth + "px");
// size carousel content around scroller hotzones
var scrollerHeights = $(".carousel-scroller.top").height() + $(".carousel-scroller.bottom").height();
$("#carouselNodes").css("height", ($(carousel).innerHeight() - scrollerHeights) + "px");
}
var customMarkup = $("div.custom-markup-area");
$(customMarkup).hide();
// scale the image to fit the display content area
if(selectedNode != null) {
scalePhotoContent(selectedNode, $("div#photoContainer"));
// snap the photo scrollers into place
var photoDiv = $("div#photoContainer").find("div.photo");
var photoImg = $("div#photoContainer").find("div.photo img");
if($(photoImg).length > 0) {
var prevScroller = $("div.photo-scroller.prev");
$(prevScroller).css("position", "absolute");
$(prevScroller).css("top", photoImg.offset().top + "px");
$(prevScroller).css("left", photoDiv.offset().left + "px");
$(prevScroller).css("width", (photoImg.offset().left - photoDiv.offset().left) + "px");
$(prevScroller).css("height", photoImg.height() + "px");
var nextScroller = $("div.photo-scroller.next");
$(nextScroller).css("position", "absolute");
$(nextScroller).css("top", photoImg.offset().top + "px");
$(nextScroller).css("left", (photoImg.offset().left + photoImg.width()) + "px");
$(nextScroller).css("width", photoDiv.width() - ((photoImg.offset().left - photoDiv.offset().left) + photoImg.width()) + "px");
$(nextScroller).css("height", photoImg.height() + "px");
}
// see if there's custom markup and snap it into place
var custom = getCustomMarkup(selectedNode);
if(custom != null && custom.length > 0) {
$(customMarkup).hide();
$(customMarkup).html(custom);
var markupWidth, markupHeight;
if(orientation == "vertical") {
markupHeight = Math.floor(newHeight * 0.82);
markupWidth = Math.floor(newWidth * 0.75);
} else {
markupHeight = newHeight - 200;
markupWidth = Math.floor(newWidth * 0.7);
}
$(customMarkup).css("height", markupHeight + "px");
$(customMarkup).css("width", markupWidth + "px");
// note: need for a wrapper pane, see link below
// http://jscrollpane.kelvinluck.com/known_issues.html
var wrapper = $("div.custom-markup-wrapper");
$(wrapper).css("height", markupHeight + "px");
$(wrapper).css("width", markupWidth + "px");
$(wrapper).show();
var jspElem = $(wrapper).jScrollPane({
showArrows: true,
verticalArrowPositions: 'split',
horizontalArrowPositions: 'split',
verticalDragMinHeight: 20,
verticalDragMaxHeight: 20,
horizontalDragMinWidth: 20,
horizontalDragMaxWidth: 20,
horizontalalGutter: 0,
verticalGutter: 0,
contentWidth: markupWidth
});
$(customMarkup).show();
$(jspElem).data('jsp').reinitialise();
}
if(selectedNode.caption != null && selectedNode.caption.length > 0) {
$(".photo-caption-area").show();
$(".photo-caption-area").jScrollPane({
showArrows: true,
verticalArrowPositions: 'split',
horizontalArrowPositions: 'split',
verticalDragMinHeight: 20,
verticalDragMaxHeight: 20,
horizontalDragMinWidth: 20,
horizontalDragMaxWidth: 20,
horizontalalGutter: 0,
verticalGutter: 0
});
} else {
$(".photo-caption-area").hide();
}
}
var footerDiv = $("#footer");
$(footerDiv).css("top", docHeight - $(footerDiv).height() - 5);
$(footerDiv).css("left", (docWidth / 2) - ($(footerDiv).width() / 2) + 64);
// show or hide carousel scrollers
showHideCarouselScrollers(orientation);
}
/**
* showHideCarouselScrollers
*/
function showHideCarouselScrollers(orientation) {
var cnlist = $("#carouselNodeList");
var cnodes = $("#carouselNodes");
if(cnlist.length == 0 || cnodes.length == 0) {
return;
}
if(orientation == "vertical") {
var topVal = parseInt($(cnlist).css("top").replace(/px/, ''));
if(isNaN(topVal)) {
topVal = 0;
}
if(topVal >= 0) {
$(".carousel .carousel-scroller.top").removeClass("visible");
} else {
$(".carousel .carousel-scroller.top").addClass("visible");
}
if(($(cnlist).height() + topVal) > $(cnodes).height()) {
$(".carousel .carousel-scroller.bottom").addClass("visible");
// bind mousewheel for the carousel
if(prebound == false) {
$("#carouselNodes").bind("mwheelIntent", function(e, d) {
scrollCarousel("vertical", 20, (d > 0) ? "up" : "down");
});
prebound = true;
}
} else {
$(".carousel .carousel-scroller.bottom").removeClass("visible");
// unbind mousewheel for the carousel
if(prebound == true && topVal >=0) {
$("#carouselNodes").unbind("mwheelIntent");
prebound = false;
}
}
} else if(orientation == "horizontal") {
var leftVal = parseInt($(cnlist).css("left").replace(/px/, ''));
if(isNaN(leftVal)) {
leftVal = 0;
}
if(leftVal >= 0) {
$(".carousel .carousel-scroller.left").removeClass("visible");
} else {
$(".carousel .carousel-scroller.left").addClass("visible");
}
var lastVisibleNode = $(cnlist).find("div.node:visible").last();
if(($(lastVisibleNode).offset().left + $(lastVisibleNode).outerWidth() + 40) > $(carousel).width()) {
$(".carousel .carousel-scroller.right").addClass("visible");
} else {
$(".carousel .carousel-scroller.right").removeClass("visible");
}
}
}
/**
* Auto scales the node content within the specified photo container.
*
* @param node The node to scale the content for
* @param container The photo container to scale the content within
*/
function scalePhotoContent(node, container) {
var availHeight = $("#content").innerHeight();
var availWidth = $("#content").innerWidth();
var maxWidth = availWidth - (photoScrollerWidth * 8);
var maxHeight = availHeight - 48;
if($(".carousel.horizontal").length > 0) {
maxHeight -= $(".carousel.horizontal").height();
}
var imgSize;
if(node.image != null && node.image.uri != null && node.image.uri.length > 0) {
maxHeight -= $(container).find("div.photo-caption-area").height() + 40;
imgSize = scaleDimension(new Dimension(node.image.width, node.image.height),
new Dimension(maxWidth, maxHeight));
} else {
imgSize = new Dimension(0, 0);
}
var photoImg = $(container).find("div.photo img");
$(photoImg).attr("height", imgSize.height);
$(photoImg).attr("width", imgSize.width);
}
/**
* Starts auto scrolling of the carousel using the current auto scroll amount
*
* @param orientation The orientation of the carousel to be scrolled
* @param direction up, down, left or right
*/
function autoScrollCarousel(orientation, direction) {
scrollCarousel(orientation, autoScrollAmount, direction);
}
/**
* Scrolling of the carousel
*
* @param orientation The orientation of the carousel to be scrolled
* @param scrollAmount The number of pixels to scroll the carousel
* @param direction up, down, left or right
*/
function scrollCarousel(orientation, scrollAmount, direction) {
var cnlist = $("#carouselNodeList");
var cnodes = $("#carouselNodes");
if(orientation == "vertical") {
var topVal = parseInt($(cnlist).css("top").replace(/px/, ''));
if(isNaN(topVal)) {
topVal = 0;
}
if(direction == "down") {
topVal = topVal - scrollAmount;
if(($(cnlist).height() + topVal) > $(cnodes).height()) {
$(cnlist).css("top", topVal + 'px');
} else {
$(cnlist).css("top", (($(cnodes).height() - $(cnlist).height()))+ 'px');
}
} else if(direction == "up" && topVal < 0) {
topVal = topVal + scrollAmount;
if(topVal > 0) {
topVal = 0;
}
$(cnlist).css("top", topVal + 'px');
}
} else if(orientation == "horizontal") {
var leftVal = parseInt($(cnlist).css("left").replace(/px/, ''));
if(isNaN(leftVal)) {
leftVal = 0;
}
if(direction == "right") {
leftVal = leftVal - scrollAmount;
var lastVisibleNode = $(cnlist).find("div.node:visible").last();
if(($(lastVisibleNode).offset().left + $(lastVisibleNode).outerWidth() + 40) > $(carousel).width()) {
$(cnlist).css("left", leftVal + 'px');
}
} else if(direction == "left" && leftVal < 0) {
leftVal = leftVal + scrollAmount;
if(leftVal > 0) {
leftVal = 0;
}
$(cnlist).css("left", leftVal + 'px');
}
}
showHideCarouselScrollers(orientation);
}
/**
* Loads the node's display content into the page data for display
*
* @param node
*/
function loadNodeContent(carousel, node, index) {
if(node.customMarkup != null && node.customMarkup.length > 0) {
$(carousel).data(node.id + "_markup", customMarkup);
} else if(node.contentUrl != null && node.contentUrl.length > 0) {
$.get(node.contentUrl, function(content) {
$(carousel).data(node.id + "_markup", content);
});
}
// if(index == 0 && node.image != null) {
// loadNodeImage(node);
// }
for(var i = 0; i < node.children.length; i++) {
var child = node.children[i];
child.parent = node;
child.prev = (i > 0) ? node.children[i-1] : null;
child.next = (i < (node.children.length - 1)) ? node.children[i+1] : null;
loadNodeContent(carousel, child, i);
}
}
/**
* The node to load an image for
*
* @param node
*/
function loadNodeImage(node) {
if(node != null && node.image != null) {
var nodeImage = new Image();
nodeImage.src = node.image.uri;
}
}
/**
* Gets the html markup used for a carousel node
*
* @param node
* @param style
* @returns {String}
*/
function getNodeHtml(carousel, node, orientation, parentNode) {
var nodeStyle = 'node ' + orientation;
var thumbStyle = 'node-thumb ' + orientation;
if(orientation == "horizontal") {
nodeStyle += ' clearfix';
}
var hasChildren = (node.children.length > 0);
if(hasChildren == true) {
nodeStyle += ' parent';
thumbStyle += ' parent expandable';
}
var rootNode = (parentNode == null || node.topThumb != null || node.leftThumb != null);
if(rootNode == true) {
nodeStyle += ' root';
thumbStyle += ' root';
}
if(node.thumb != null && node.thumb.style != null) {
thumbStyle += ' ' + node.thumb.style;
}
var nodeHtml = '
'; // start the node
nodeHtml += '
'; // start the node thumb
if(hasChildren) {
// include name for parent nodes
var nodeNameStyle = 'node-name parent ' + orientation;
if(rootNode == true) {
nodeNameStyle += ' root';
}
var openIconSrc = "assets/12-arrow-right.png";
nodeHtml += '
';
nodeHtml += '' + node.name + '';
nodeHtml += '
';
}
if(node.thumb != null && node.thumb.uri != null && node.thumb.uri.length > 0) {
var thumbSize = scaleDimension(new Dimension(node.thumb.width, node.thumb.height), defaultThumbSize);
nodeHtml += '
';
} else if(!hasChildren) {
// only include node name for child nodes with no images
nodeHtml += node.name;
}
nodeHtml += '
'; // end thumb
var kidsHtml = "";
var starterHtml = "";
var enderHtml = "";
if(hasChildren == true) {
// all my children ...
kidsHtml = '
';
for(var j = 0; j < node.children.length; j++) {
var child = node.children[j];
kidsHtml += getNodeHtml(carousel, child, orientation, node);
$(carousel).data(child.id, child);
}
kidsHtml += '
'; // end children
if(rootNode == true && showEnders == true) {
// include top half starter element for parent nodes
starterHtml = '
';
starterHtml += '
';
starterHtml += '
';
starterHtml += ''+ node.name + '
';
if(node.topThumb != null && node.topThumb.uri != null && node.topThumb.uri.length > 0) {
var thumbSize = scaleDimension(new Dimension(node.topThumb.width, node.topThumb.height), defaultTopThumbSize);
starterHtml += '
';
}
starterHtml += '
';
// include bottom half element for parent nodes
enderHtml = '
';
enderHtml += '
';
enderHtml += '
';
enderHtml += ''+ node.name + '
';
if(node.bottomThumb != null && node.bottomThumb.uri != null && node.bottomThumb.uri.length > 0) {
var thumbSize = scaleDimension(new Dimension(node.bottomThumb.width, node.bottomThumb.height), defaultBottomThumbSize);
enderHtml += '
';
}
enderHtml += '
';
}
}
nodeHtml += '
'; // end node
nodeHtml += starterHtml; // add starter
nodeHtml += kidsHtml; // add kids
nodeHtml += enderHtml; // add ender
return nodeHtml;
}
/**
* Gets the node's html for displaying its photo image
*
* @param node
* @returns {String}
*/
function getPhotoHtml(node) {
var h;
if (node != null && node.image != null && node.image.uri != null && node.image.uri.length > 0) {
h = '';
} else {
h = '';
}
return h;
}
/**
* Gets the node's custom markup content
*
* @param node
* @returns {String}
*/
function getCustomMarkup(node) {
var h = $(carousel).data(node.id + "_markup");
return h != null ? h : "";
}
/**
* Shows the content for a specified node
*
* @param node
* The node to show content for
* @param animationPlan
* An optional prev or next value can be specified to indicate how the
* current node content animation should be transitioned
*/
function showNodeContent(node, animationPlan) {
if(node == null) {
return;
}
// update inquiry link
var mailToLink = $("a#mailToLink");
if(mailToLink.length > 0) {
var href = "mailto:" + mailToAddr + "?subject=" + mailToSubject;
if(node.name != null && node.name.length > 0) {
href += " '" + node.name + "' ";
$(mailToLink).show();
} else {
// keep inquiry link hidden for non-paintings
$(mailToLink).hide();
}
$(mailToLink).attr("href", href);
}
var photo = $("div#photo");
var nodeDiv = $("div.node-display");
if(animationPlan !== "fade") {
var nodeOverflowSave = $(nodeDiv).css("overflow");
$(nodeDiv).css("overflow", "hidden");
var speed = 500;
var marginLeftAnim = $(document).width();
if(animationPlan === "prev") {
marginLeftAnim = $(document).width() * -1.25;
} else {
// default to slide next
marginLeftAnim = $(photo).outerWidth() + 20;
}
$(photo).animate({ marginLeft: marginLeftAnim }, speed, function() {
$(photo).hide();
$(photo).html(getPhotoHtml(node));
$("#photoCaptionText").html(node.caption != null ? node.caption : "");
$("#customMarkup").html(getCustomMarkup(node));
//$("#previewContainer").hide();
$("#photoContainer").show();
$(photo).css("margin-left", 0);
$(photo).show();
$(nodeDiv).css("overflow", nodeOverflowSave);
if(node.image != null && node.image.uri != null && node.image.uri.length > 0) {
$("div.photo-scroller").show();
} else {
$("div.photo-scroller").hide();
}
doLayout();
});
} else {
// do the fade thing
$("div.photo-scroller").hide();
$("#photoContainer").hide("fade", {}, 250, function() {
$(photo).hide();
$(photo).html(getPhotoHtml(node));
$("#photoCaptionText").html(node.caption != null ? node.caption : "");
$("#customMarkup").html(getCustomMarkup(node));
$(photo).css("margin-left", 0);
$(nodeDiv).css("overflow", nodeOverflowSave);
doLayout();
$(photo).show();
$("#photoContainer").show("fade", {}, 250, function() {
if(node.image != null && node.image.uri != null && node.image.uri.length > 0) {
$("div.photo-scroller").show();
}
doLayout();
});
});
}
}
/**
* Select a new node based on the selection of a node thumbnail image
*
* @param nodeThumb
* The node thumbnail that has been clicked
* @param autoExpandCollapse
* set true to auto expand and collapse expandable nodes, defaults to
* true
* @param autoScrollIntoView
* set true to auto scroll obscured nodes into view, defaults to
* true
* @param anomationPlan
* An optional param prev/next to indicate how new content is shown.
* Set to fade, prev or next. defaults to fade
*/
function nodeThumbClicked(nodeThumb, autoExpandCollapse, autoScrollIntoView, animationPlan) {
previewTimer = null;
var carouselNodes = $("div.carousel-nodes");
var hideStarterEnders = $(nodeDiv).hasClass("root") &&
($(nodeDiv).hasClass("starter") || $(nodeDiv).hasClass("ender"));
if(autoExpandCollapse == null) {
autoExpandCollapse = true;
}
if($(nodeThumb).parent(".node").hasClass("ender")) {
nodeThumb = $(nodeThumb).parent(".node.ender").prevAll(".node.starter").first().children(".node-thumb.starter").first();
}
var newNode = getNodeObject(nodeThumb);
var selectionChanging = newNode != selectedNode;
selectedNode = newNode;
if(selectedNode != null) {
if(selectedNode.next != null) {
loadNodeImage(selectedNode.next);
}
if(selectedNode.prev != null) {
loadNodeImage(selectedNode.prev);
}
}
$("div.node-thumb").removeClass("selected");
$(nodeThumb).addClass("selected");
// Look to see if the node clicked is obscured in the carousel
if(autoScrollIntoView && !hideStarterEnders) {
if($(carouselNodes).hasClass("vertical")) {
var nodeTop = $(nodeThumb).offset().top;
var nodeBottom = $(nodeThumb).offset().top + $(nodeThumb).height() + 100;
var carouselNodesTop = $(carouselNodes).offset().top;
var carouselNodesBottom = $(carouselNodes).offset().top + $(carouselNodes).height();
var cnlist = $("#carouselNodeList");
if(nodeTop < carouselNodesTop) {
// scroll up
var topVal = $(cnlist).offset().top + (carouselNodesTop - nodeTop);
if(isNaN(topVal) || topVal > 0) {
topVal = 0;
}
$(cnlist).animate({"top":topVal + "px"}, 1000);
} else if(nodeTop > ($(carouselNodes).height() / 3)) {
// scroll down
var topVal = $(cnlist).offset().top + (carouselNodesTop - nodeTop);
if(isNaN(topVal) || topVal > 0) {
topVal = 0;
}
$(cnlist).animate({"top":topVal + "px"}, 1000);
}
} else if($(carouselNodes).hasClass("horizontal")) {
var extraAmount = 60;
var nodeLeft = $(nodeThumb).offset().left - extraAmount;
var nodeRight = $(nodeThumb).offset().left + $(nodeThumb).width() + extraAmount;
var carouselNodesLeft = $(carouselNodes).offset().left;
var carouselNodesRight = $(carouselNodes).offset().left + $(carouselNodes).width();
if(nodeLeft < carouselNodesLeft) {
scrollCarousel("horizontal", Math.abs(nodeLeft) + carouselNodesLeft, "left");
} else if(nodeRight > carouselNodesRight) {
scrollCarousel("horizontal", (nodeRight - carouselNodesRight), "right");
}
}
}
// Toggle Expand/collapse children state for nodes with kids
if(autoExpandCollapse == true && $(nodeThumb).hasClass("expandable")) {
var nodeDiv = $(nodeThumb).parent(".node");
var childDiv = $(nodeDiv).nextAll(".children").first();
var opening = $(childDiv).is(":visible") === false;
var hideStarterEnders = false;
var effect = "blind";
var options = {};
if($(nodeThumb).hasClass("horizontal")) {
options.direction = "horizontal";
} else {
options.direction = "vertical";
}
if($(nodeDiv).hasClass("root")) {
if(!$(nodeDiv).hasClass("starter") && !$(nodeDiv).hasClass("ender")) {
$("#" + $(nodeDiv).attr("id") + "_ender, #" + $(nodeDiv).attr("id") + "_starter").toggle(effect, options, 10);
$(nodeDiv).toggle(effect, options, 10);
} else {
hideStarterEnders = true;
}
}
if(options.direction === "horizontal") {
var resizeAmt = $(childDiv).width();
if(opening) {
// children will be opening
$(nodeThumb).parents(".children").each(function(i, e) {
$(e).css("width", ($(e).width() + resizeAmt) + "px");
});
$(childDiv).toggle(effect, options, 700, function() {
showHideCarouselScrollers(options.direction);
});
} else {
// children are closing up
$(childDiv).toggle(effect, options, 700, function() {
resizeAmt = resizeAmt * -1;
$(nodeThumb).parents(".children").each(function(i, e) {
$(e).css("width", ($(e).width() + resizeAmt) + "px");
});
// recursive child collapse here
collapseKids(selectedNode);
// carousel size is changing so hide scrollers
showHideCarouselScrollers(options.direction);
});
if(hideStarterEnders) {
var nodeDivId = $(nodeDiv).attr("id");
nodeDivId = nodeDivId.replace("_starter", "");
nodeDivId = nodeDivId.replace("_ender", "");
$("#" + nodeDivId + "_ender").animate({"margin-left":"-40px"}, 700, function() {
$(this).hide();
$("#" + nodeDivId + "_starter").hide();
$("#" + nodeDivId).show();
$(this).css("margin-left", "0px");
});
}
}
} else {
$(childDiv).toggle(effect, options, 700, function() {
if(!opening) {
// recursive child collapse here
collapseKids(selectedNode);
}
showHideCarouselScrollers(options.direction);
});
if(hideStarterEnders) {
var nodeDivId = $(nodeDiv).attr("id");
nodeDivId = nodeDivId.replace("_starter", "");
nodeDivId = nodeDivId.replace("_ender", "");
$("#" + nodeDivId + "_ender").animate({"margin-top":"-20px"}, 700, function() {
$(this).hide();
$("#" + nodeDivId + "_starter").hide();
$("#" + nodeDivId).show();
$(this).css("margin-top", "0px");
});
}
}
}
if(selectionChanging) {
// Display the newly selected node's content
showNodeContent(selectedNode, animationPlan != null ? animationPlan : "fade");
}
}
/**
* Auto collapse all children of the specified node
*
* @param node
*/
function collapseKids(node) {
if(node != null) {
for(var j = 0; j < node.children.length; j++) {
var child = node.children[j];
collapseKids(child);
var nodeDiv = $("#" + child.id);
if($(nodeDiv).hasClass("parent")) {
var childDiv = $(nodeDiv).nextAll(".children").first();
$(childDiv).hide();
var nodeDivId = $(nodeDiv).attr("id");
$("#" + nodeDivId + "_starter").hide();
$("#" + nodeDivId + "_ender").hide();
$("#" + nodeDivId).show();
}
}
}
}
/**
* Expand parents
*
* @param node
*/
function expandParents(node) {
if(node != null) {
var parent = node.parent;
while(parent != null) {
var nodeDiv = $("#" + parent.id);
if($(nodeDiv).hasClass("parent")) {
var childDiv = $(nodeDiv).nextAll(".children").first();
$(childDiv).show();
var nodeDivId = $(nodeDiv).attr("id");
$("#" + nodeDivId + "_starter").show();
$("#" + nodeDivId + "_ender").show();
$("#" + nodeDivId).hide();
}
parent = parent.parent;
}
}
}
/**
* Gets the direction the scroller moves the carousel
*
* @returns "down", "up", "left", "right" or "" means no scroller
*/
function getScrollerDirection(scroller) {
var direction = "";
if($(scroller).hasClass("visible")) {
if($(scroller).hasClass("bottom")) {
direction = "down";
} else if($(scroller).hasClass("top")) {
direction = "up";
} else if($(scroller).hasClass("left")) {
direction = "left";
} else if($(scroller).hasClass("right")) {
direction = "right";
}
}
return direction;
}
/**
* @param node
*/
function showNodeHoverImage(node) {
if(node.thumb != null && node.thumb.uriHover != null) {
var imgElem = $("#" + node.id + "_img");
$(imgElem).attr("src", node.thumb.uriHover);
}
}
/**
* @param node
*/
function showNodeThumbImage(node) {
if(node.thumb != null && node.thumb.uri != null) {
var imgElem = $("#" + node.id + "_img");
$(imgElem).attr("src", node.thumb.uri);
}
}
/**
* Loads the site tree into the jcarousel
*/
function loadCarousel(carousel, orientation) {
// Get carousel data items via Ajax and load it into the carousel control
$.getJSON("carousel.json", function(data) {
// Build carousel html from carousel json
nodes = data.nodes;
var carouselHtml = '';
carouselHtml += '';
carouselHtml += '
';
for(i = 0; i < nodes.length; i++) {
// add this parent node ...
var node = nodes[i];
node.parent = null;
node.prev = (i > 0) ? nodes[i-1] : null;
node.next = (i < (nodes.length - 1)) ? nodes[i+1] : null;
carouselHtml += getNodeHtml(carousel, node, orientation);
// load the node display content
loadNodeContent(carousel, node, i);
// store this node as data in the carousel for later use
$(carousel).data(node.id, node);
}
carouselHtml += '
'; // end carouselNodes
carouselHtml += '
'; // end carouselNodeList
carouselHtml += '';
// set the html
$(carousel).html(carouselHtml);
// Establish handler for showing image preview
$("div.node-thumb").live("mouseenter", function(){
var node = getNodeObject(this);
if (node != null) {
var thumb = this;
showNodeHoverImage(node);
if (node != selectedNode && previewTimer == null) {
previewTimer = setTimeout(function() {
nodeThumbClicked(thumb, false, false);
clearTimeout(previewTimer);
previewTimer = null;
}, 500);
}
}
});
$("div.node-thumb").live("mouseleave", function(){
showNodeThumbImage(getNodeObject(this));
if(previewTimer != null) {
clearTimeout(previewTimer);
}
previewTimer = null;
});
// Establish handler for hiding and showing nested content
$(".node-thumb").click(function() {
if(clickThrottle == null) {
nodeThumbClicked(this, true, true);
clickThrottle = setTimeout(function() {
clearTimeout(clickThrottle);
clickThrottle = null;
}, 800);
}
});
// setup carousel scroller hotspots
$(".carousel-scroller").mouseenter(function() {
if(scrollInterval == null) {
activeScroller = this;
var direction = getScrollerDirection(this);
if(direction.length > 0) {
scrollInterval = setInterval('autoScrollCarousel("'
+ orientation + '", ' + '"' + direction + '")', autoScrollDelay);
}
}
}
).mouseleave(function() {
if(scrollInterval != null) {
window.clearInterval(scrollInterval);
scrollInterval = null;
activeScroller = null;
autoScrollAmount = autoScrollAmountMin;
}
}
);
$(".carousel-scroller").mousemove(function(e) {
if(activeScroller == this) {
var direction = getScrollerDirection(activeScroller);
var accel = 0;
if(direction == "up") {
accel = (($(this).offset().top + $(this).height()) - e.pageY);
} else if(direction == "down") {
accel = (e.pageY - $(this).offset().top);
} else if(direction == "left") {
accel = (($(this).offset().left + $(this).width()) - e.pageX);
} else if(direction == "right") {
accel = (e.pageX - $(this).offset().left);
}
//$("span#logg").text(e.pageX + ", " + e.pageY + " amt=" + amt);
accel = Math.floor(accel / 32);
autoScrollAmount = Math.min(autoScrollAmountMax, autoScrollAmountMin + Math.abs(accel));
}
});
// setup carousel scroller hotspots
$(".carousel-scroller").click(function() {
var direction = getScrollerDirection(this);
if(direction.length > 0) {
if(scrollInterval != null) {
window.clearInterval(scrollInterval);
scrollInterval = null;
activeScroller = null;
autoScrollAmount = autoScrollAmountMin;
}
scrollCarousel(orientation, 300, direction);
}
});
});
}
/**
* Initializes the document
*
* @param carousel The carousel in the document to be initialized
* @param orientation The carousel orientation of the document
*/
function initDocument(carouselElem, orientation) {
carousel = carouselElem;
// add orientation class to all elements of the carousel
$(carousel).addClass(orientation);
loadCarousel(carousel, orientation);
var pageContent = $("div#content");
$(pageContent).find("*").each(function(i, e) {
$(e).addClass(orientation);
});
// Ensure the horizontal carousel is positioned as the last element
if(orientation == "horizontal") {
carousel = $(carousel).detach();
$(carousel).appendTo(pageContent);
}
doLayout();
// Setup over photo image navigation support
$(pageContent).mousemove(function(event) {
var photoDiv = $("div.photo");
var photoImg = $("div.photo img");
if(photoDiv.length > 0 && photoImg.length > 0) {
var scrollerArea = new Rect(
$(photoDiv).offset().top,
$(photoDiv).offset().left + $(photoDiv).width() + photoScrollerWidth,
$(photoDiv).offset().top + $(photoDiv).height(),
$(photoDiv).offset().left - photoScrollerWidth);
var imgArea = new Rect(
$(photoImg).offset().top,
$(photoImg).offset().left + $(photoImg).width(),
$(photoImg).offset().top + $(photoImg).height(),
$(photoImg).offset().left);
if(scrollerArea.contains(event.pageX, event.pageY)
&& !(imgArea.contains(event.pageX, event.pageY))) {
$("div.photo-scroller").fadeIn(500);
} else {
$("div.photo-scroller").fadeOut(500);
}
}
});
$("div.photo-scroller").live("click", function(event) {
var curThumb = $(carousel).find("div.node-thumb.selected");
var curNode = $(curThumb).parent("div.node");
var newNode = null;
var direction = null;
if($(this).hasClass("next")) {
newNode = $(curNode).next("div.node").children("div.node-thumb").first();
if(newNode.length == 0) {
var sibs = $(curNode).siblings();
newNode = $(sibs).first().children("div.node-thumb").first();
}
direction = "next";
}
else if($(this).hasClass("prev")) {
newNode = $(curNode).prev("div.node").children("div.node-thumb").first();
if(newNode.length == 0) {
var sibs = $(curNode).siblings();
newNode = $(sibs).last().children("div.node-thumb").first();
}
direction = "prev";
}
if(newNode != null && newNode.length > 0) {
$("div.photo-scroller").hide();
nodeThumbClicked(newNode, false, true, "fade");
}
});
}
/**
* common document loading stuff
*/
$(document).ready(function() {
$("#mastTitle").click(function() {
document.location.href = "index.html";
});
doLayout();
$(window).resize(function(){
doLayout();
});
});