// Javascript tends to be pretty messy anyway, so I've kept all methods together
// in one page to make it easier to find what you're looking for. Unless otherwise
// noted, methods are usable from any page.

// The following global variables are used by the Search Results page
var imageAspect = 1;
var originalZoomSize = 0;
var detailZoomSize = 150;
var originalZoomUrl = "";
var selectedStoryId;
var selectedImageId;
// rootUrl is used by javascript functions that navigate to other pages.
// Its value is set to the root url of the web application in MasterPage.master.
var rootUrl;
// resizeThresholdFactor is used by resizeImage to determine when to request a
// larger version of the loaded image from the server.
var resizeThresholdFactor = 1.1;
// scrollTarget and scrollContainer are used by scrollBy and doScrollBy
// to animate scrolling of the map and story list.
var scrollTarget;
var scrollContainer;

// Utility method to return the largest of two numbers.
function max(arg1, arg2) {
    return (arg1 > arg2) ? arg1 : arg2;
}

// Utility method to return the smallest of two numbers.
function min(arg1, arg2) {
    return (arg1 < arg2) ? arg1 : arg2;
}

// Utility method to scroll a control's parent so that the control is in the middle (vertically).
function scrollIntoView(controlRef) {
    var controlContainer = controlRef.parentNode;
    var overflowHeight = controlContainer.scrollHeight - controlContainer.clientHeight;
    
    if (overflowHeight > 0) {
        var idealControlHeight = (controlContainer.clientHeight - controlRef.offsetHeight) / 2;
        var actualControlHeight = controlRef.offsetTop - controlContainer.scrollTop;
        
        if (actualControlHeight > idealControlHeight) {
            var availableScroll = overflowHeight - controlContainer.scrollTop;
            var requiredScroll = min(availableScroll, actualControlHeight - idealControlHeight);
            scrollBy(controlContainer, requiredScroll);
        } else if (actualControlHeight < idealControlHeight) {
            var availableScroll = controlContainer.scrollTop;
            var requiredScroll = min(availableScroll, idealControlHeight - actualControlHeight);
            scrollBy(controlContainer, -requiredScroll);
        }
    }
}

function scrollBy(containerRef, increment) {
    scrollTarget = containerRef.scrollTop + increment;
    scrollContainer = containerRef;
    doScrollBy();
}

function doScrollBy() {
    var distToScroll = scrollTarget - scrollContainer.scrollTop;
    var step = 0;
    
    if (distToScroll > 1) {
        step = max(distToScroll * 0.3, 1);
    } else if (distToScroll < -1) {
        step = min(distToScroll * 0.3, -1);
    }
    
    if (0 != step) {
        setTimeout("doScrollBy()", 30);
        scrollContainer.scrollTop += step;
    }
}

// Utility method to render a currency value (without currency symbol).
function renderCurrency(value)
{
    var pounds = Math.floor(value);
    var pence = (value * 100) % 100;
    
    if (pence < 10) {
        return pounds + ".0" + pence;
    } else {
        return pounds + "." + pence;
    }
}

// Utility function for setting a session cookie's value.
function setCookie(cookieName, cookieValue) {
    document.cookie = cookieName + "=" + cookieValue;
}

// Utility function for retrieving a (session) cookie's value.
function getCookie(cookieName) {
    if (null != document.cookie) {
        var cookies = document.cookie.split(";");
        for (var i = 0; i < cookies.length; i++) {
            if (null != cookies[i]) {
                var cookieParts = cookies[i].split("=");
                if (null != cookieParts
                        && cookieParts.length >= 2
                        && null != cookieParts[0]
                        && cookieParts[0].replace(" ", "") == cookieName) {
                    return cookieParts[1]
                }
            }
        }
    }
    
    return "";
}

// Adds the specified image to the cart, by adding its id to the "cart"
// session cookie. Will automatically warn the user if session cookies
// are not enabled by their browser.
// Usable from the Search Page only.
function addToCart(imageId) {
    var newCookie = getCookie("cart");
    var oldCookie = newCookie;
    
    if (null == newCookie || newCookie.length == 0) {
        newCookie = imageId;
    } else {
        newCookie += ("," + imageId);
    }
    
    setCookie("cart", newCookie);
    var checkCookie = getCookie("cart");
    
    if (checkCookie != newCookie) {
        if (checkCookie != null && checkCookie.length > 0)
        {
            setCookie("cart", oldCookie);
            alert("Your cart is full.\n\n"
                + "If you would like to order more items, you can\n"
                + "either visit the checkout now and then begin a new\n"
                + "order, or email us the reference numbers of the\n"
                + "items you would like, and we will handle your\n"
                + "order manually.");
        }
        else
        {
            alert("Session cookies are required for the cart to\n"
                + "work, but your browser does not support this.\n\n"
                + "Please adjust your browser's privacy settings.\n\n"
                + "Alternatively, you can place an order by emailing\n"
                + "us the reference numbers of the items you would\n"
                + "like, and we will handle your order manually.");
        }
    } else {
        updateCartLinkVisibility(true);
    }
}

// Removes the specified image from the cart, by removing its id
// from the "cart" session cookie.
// Usable from the Search Page only.
function removeFromCart(imageId, isCartView) {
    var cartImages = getCookie("cart").split(",");
    
    if (null != cartImages && cartImages.length > 0) {
        var newCookie = "";
        
        for (var i = 0; i < cartImages.length; i++) {
            if (cartImages[i] != imageId) {
                if (newCookie.length > 0) {
                    newCookie += ",";
                }
                
                newCookie += cartImages[i];
            }
        }
        
        setCookie("cart", newCookie);
    }

    if (isCartView) {
        document.location.href = rootUrl + "Gallery/Search.aspx?viewCart=true";
    } else {
        updateCartLinkVisibility(false);
    }
}

// Removes all images from the cart.
function clearCart() {
    setCookie("cart", "");
}

// Checks if the specified image is currently in the user's cart.
function isInCart(imageId) {
    var cartImages = getCookie("cart").split(",");

    if (null != cartImages && cartImages.length > 0) {
        for (var i = 0; i < cartImages.length; i++) {
            if (cartImages[i] == imageId) {
                return true;
            }
        }
    }
    
    return false;
}

// Checks whether there is anything in the user's cart.
function isCartEmpty() {
    var cartImages = getCookie("cart").split(",");

    if (null != cartImages && cartImages.length > 0) {
        for (var i = 0; i < cartImages.length; i++) {
            if (cartImages[i] != "") {
                return false;
            }
        }
    }
    
    return true;
}

// Updates the visibility of the "Add to Cart" and "Remove from Cart" links.
// Usable from the Search Page only.
function updateCartLinkVisibility(isInCart) {
    var addToCartLink = document.getElementById("addToCartLink");
    var removeFromCartLink = document.getElementById("removeFromCartLink");

    if (addToCartLink != null && removeFromCartLink != null)
    {
        if (isInCart) {
            addToCartLink.style.display = "none";
            removeFromCartLink.style.display = "block";
        } else {
            addToCartLink.style.display = "block";
            removeFromCartLink.style.display = "none";
        }
    }
}

// If present, this function displays the repaintOverlay pane, which sits
// on top of everything and thus forces a complete repaint when it is hidden again.
// Required when working with Opera, which tries to optimize page refreshes and
// succeeds in messing up the page when our dynamic resizing code kicks in...
function startResize() {
    try {
        var repaintOverlay = document.getElementById("repaintOverlay");
        if (null != repaintOverlay) {
            repaintOverlay.style.display = "block";
        }
    } catch (e) {
        // Ignore
    }
}

// If present, this function hids the repaintOverlay pane. See startResize().
function endResize() {
    try {
        var repaintOverlay = document.getElementById("repaintOverlay");
        if (null != repaintOverlay) {
            repaintOverlay.style.display = "none";
        }
    } catch (e) {
        // Ignore
    }
}

// Submits a new keyword search.
function submitSearch() {
    document.getElementById("SearchForm").submit();
}

// Searches for images from a specified story.
function findByStoryId(storyId) {
    window.location.href = rootUrl + "Gallery/Search.aspx?storyId=" + storyId;
}

// Searches for images in a specified gallery.
function findByGalleryId(galleryId) {
    window.location.href = rootUrl+ "Gallery/Search.aspx?galleryId=" + galleryId;
}

// Searches for images that are similar to the specified image.
function findByExample(imageId) {
    window.location.href = rootUrl + "Gallery/Search.aspx?exampleImageId=" + imageId;
}

// Loads a new image into the main viewer, resizing and
// moving the detail information if required.
// Only usable from the search page (of course).
function loadSearchResultsImage(imageId, aspect, isZoomAvailable) {
    var detailImage = document.getElementById("detailImage");
    var detailZoomImage = document.getElementById('detailZoomImage');
    detailZoomImage.src = detailImage.src = "../Images/wait.gif";
    setTimeout("_loadSearchResultsImage(" + imageId + ", " + aspect + ", " + isZoomAvailable + ")", 1000);
}

function _loadSearchResultsImage(imageId, aspect, isZoomAvailable) {
    startResize();
    try {
        var imageIdControl = document.getElementById("imageId");
        var storyIdControl = document.getElementById("storyId");
        var imageTitlePane = document.getElementById("imageTitlePane");
        var storyTitlePane = document.getElementById("storyTitlePane");
        var storyBodyPane = document.getElementById("storyBodyPane");
        var findByStoryLink = document.getElementById("findByStoryLink");
        var findByExampleLink = document.getElementById("findByExampleLink");
        var detailImage = document.getElementById("detailImage");
        var detailZoomImage = document.getElementById('detailZoomImage');

        var imageTitleDiv = document.getElementById("imageTitle-" + imageId);
        var imageRefDiv = document.getElementById("imageRef-" + imageId);
        var storyIdDiv = document.getElementById("storyId-" + imageId);
        var storyTitleDiv = document.getElementById("storyTitle-" + imageId);
        var imageDateDiv = document.getElementById("imageDate-" + imageId);
        var storyBodyDiv = document.getElementById("storyBody-" + imageId);

        var imageTitle = imageTitleDiv.innerHTML;
        var imageRef = imageRefDiv.innerHTML;
        var storyId = storyIdDiv.innerHTML;
        var storyTitle = storyTitleDiv.innerHTML;
        var imageDate = imageDateDiv.innerHTML;
        var storyBody = storyBodyDiv.innerHTML;
        var storyTitleSeparator = (null == storyTitle || "" == storyTitle || null == imageDate || "" == imageDate) ? "" : ", ";

        if (null == storyBody || "" == storyBody) {
            storyBody = "No further information is available for this image.";
        }

        // Bug with IE 5.2 on Mac - set innerHTML to "" before
        // setting it to a new value.
        imageTitlePane.innerHTML = "";
        storyTitlePane.innerHTML = "";
        storyBodyPane.innerHTML = "";

        imageTitlePane.innerHTML = imageTitle + " <strong class=\"imageRef\">[item&nbsp;reference:&nbsp;</strong>" + imageRef + "<strong class=\"imageRef\">]</strong>";
        storyTitlePane.innerHTML = storyTitle + storyTitleSeparator + imageDate;
        storyBodyPane.innerHTML = storyBody;

        imageAspect = aspect;
        originalZoomUrl = rootUrl + "ImageServer.ashx?id=" + imageId;
        originalZoomSize = 0;
        resizeSearchPage(false);
        
        if (isZoomAvailable) {
            detailZoomImage.src = originalZoomUrl + "&size=" + detailZoomSize + "&zoom=true";
            detailZoomImage.style.display = "block";
            detailZoomImage.style.height = detailZoomSize + "px";
            detailZoomImage.style.width = detailZoomSize + "px";
			detailZoomImage.style.border = "";
        } else {
            detailZoomImage.style.display = "none";
			detailZoomImage.style.border = "none";
        }

        selectedStoryId = storyId;
        selectedImageId = imageId;
        
        if (null != findByStoryLink) {
            if (storyId != null && storyId != "") {
                findByStoryLink.style.display = "block";
            } else {
                findByStoryLink.style.display = "none";
            }
        }
        
        findByExampleLink.style.display = "block";
        updateCartLinkVisibility(isInCart(selectedImageId));        
    } catch (e) {
    // Ignore errors. Tends to happen in WebbIE, presumably since it doesn't render anything.
    } finally {
        endResize();
    }
}

// Resizes the various parts of the search page after a new image is loaded or
// when the browser window is resized. If suppressReload is false, the main
// image is re-loaded if the resize causes it to be significantly larger than
// its "real" size - see resizeThresholdFactor.
// Only usable from the search page (of course).
function resizeSearchPage(suppressReload) {
    startResize();
    try {
        var contentArea = document.getElementById("contentArea");
        var resultsContainer = document.getElementById("resultsContainer");
        var sidebarContainer = document.getElementById("sidebarContainer");
        var imageContainer = document.getElementById("imageContainer");
        var descriptionContainer = document.getElementById("descriptionContainer");
        var storyBodyContainer = document.getElementById("storyBodyContainer");
        var storyBodyPane = document.getElementById("storyBodyPane");
        var imageTitlePane = document.getElementById("imageTitlePane");
        var storyTitlePane = document.getElementById("storyTitlePane");
        var storyBodyPane = document.getElementById("storyBodyPane");
        var pageControlContainer = document.getElementById("pageControlContainer");
        var detailImage = document.getElementById("detailImage");

        if (null != pageControlContainer) {
          resultsContainer.style.height = (pageControlContainer.offsetTop - resultsContainer.offsetTop) + "px";
        } else {
          resultsContainer.style.height = (contentArea.clientHeight - resultsContainer.offsetTop - 1) + "px";
        }
        
        var maxImageWidth;
        var maxImageHeight;
        
        if (imageAspect > 1) {
            sidebarContainer.style.width = "100px";
            sidebarContainer.style.height = "200px";
            descriptionContainer.style.height = "120px";
            descriptionContainer.style.width = max(resultsContainer.offsetLeft - 6, 0) + "px";
            maxImageHeight = max(descriptionContainer.offsetTop - 3, 0);
        } else {
            sidebarContainer.style.height = "100px";
            descriptionContainer.style.width = sidebarContainer.style.width = "180px";
            descriptionContainer.style.height = max(contentArea.clientHeight - sidebarContainer.offsetHeight - 5, 0) + "px";
            maxImageHeight = max(contentArea.clientHeight - 3, 100);
        }

        imageContainer.style.height = maxImageHeight + "px";
        imageContainer.style.width = (maxImageWidth = max(sidebarContainer.offsetLeft - 6, 100)) + "px";
        storyTitlePane.style.top = (imageTitlePane.offsetTop + imageTitlePane.offsetHeight) + "px";
        storyBodyPane.style.top = (storyTitlePane.offsetTop + storyTitlePane.offsetHeight) + "px";
        storyBodyPane.style.height = (descriptionContainer.clientHeight - storyBodyPane.offsetTop - 1) + "px";
        storyBodyPane.style.width = (descriptionContainer.clientWidth) + "px";

        var imageSize = resizeImage(imageAspect, detailImage, maxImageWidth, maxImageHeight, originalZoomUrl, originalZoomSize, suppressReload, false, imageContainer);
        
        if (null != imageSize) {
            originalZoomSize = imageSize;
        }
        
        centerResultsContainer();
    } catch (e) {
    // Ignore errors - tends to happen in WebbIE, presumably since it doesn't render graphics at all.
    } finally {
        endResize();
    }
}

function centerResultsContainer() {
    var containerRef = document.getElementById("resultsContainer");
    var overflow = containerRef.scrollWidth - containerRef.clientWidth;
    containerRef.scrollLeft = max(overflow/2, 0);
}

// Resizes the various parts of the home page after a browser resize event.
// Only usable from the home page (of course).
function resizeHomePage(suppressReload) {
    startResize();
    try {
        var contentArea = document.getElementById("contentArea");
        var landscapeImageWidth = Math.round(contentArea.offsetWidth * 0.19);
        var landscapeImageHeight = Math.round(contentArea.offsetHeight * 0.24);
        var portraitImageWidth = Math.round(contentArea.offsetWidth * 0.16);
        var portraitImageHeight = Math.round(contentArea.offsetHeight * 0.40);
        resizeImage(1.5, document.getElementById("gallery-0"), landscapeImageWidth, landscapeImageHeight, null, null, true, true, document.getElementById("gallery-0-container"));
        resizeImage(1.5, document.getElementById("gallery-1"), landscapeImageWidth, landscapeImageHeight, null, null, true, true, document.getElementById("gallery-1-container"));
        resizeImage(1.5, document.getElementById("gallery-2"), landscapeImageWidth, landscapeImageHeight, null, null, true, true, document.getElementById("gallery-2-container"));
        resizeImage(1.5, document.getElementById("gallery-3"), landscapeImageWidth, landscapeImageHeight, null, null, true, true, document.getElementById("gallery-3-container"));
        resizeImage(1.5, document.getElementById("pick1"), landscapeImageWidth, landscapeImageHeight, null, null, true, true, document.getElementById("pick1Container"));
        resizeImage(1.5, document.getElementById("pick2"), landscapeImageWidth, landscapeImageHeight, null, null, true, true, document.getElementById("pick2Container"));
        resizeImage(1.5, document.getElementById("pick3"), landscapeImageWidth, landscapeImageHeight, null, null, true, true, document.getElementById("pick3Container"));
        resizeImage(2/3, document.getElementById("pick4"), portraitImageWidth, portraitImageHeight, null, null, true, true, document.getElementById("pick4Container"));
        resizeImage(2/3, document.getElementById("map"), portraitImageWidth, portraitImageHeight, null, null, true, false, document.getElementById("mapContainer"));
        resizeImage(2140/872, document.getElementById("logo"), Math.round(contentArea.offsetWidth * 0.6), Math.round(contentArea.offsetHeight * 0.4), null, null, true, false);
    } catch (e) {
    // Ignore errors. Tends to happen in WebbIE, presumably since it doesn't render anything.
    } finally {
        endResize();
    }
}

// Resizes the various parts of the story (map) page after a browser resize event.
// Only usable from the story page (of course).
function resizeStoryPage() {
    startResize();
    
    try {
        var contentArea = document.getElementById("contentArea");
        var mapContainer = document.getElementById("mapContainer");
        var storyListContainer = document.getElementById("storyListContainer");
        mapContainer.style.height = (contentArea.clientHeight - 5) + "px";
        storyListContainer.style.height = (contentArea.clientHeight - 5) + "px";
        storyListContainer.style.width = max(contentArea.clientWidth - mapContainer.offsetWidth - 6, 0) + "px";
        var mapOverflowHeight = mapContainer.scrollHeight - mapContainer.clientHeight;
        if (mapOverflowHeight > 0) {
            mapContainer.scrollTop = mapOverflowHeight / 2;
        }
    } catch (e) {
    // Ignore errors. Tends to happen in WebbIE, presumably since it doesn't render anything.
    } finally {
        endResize();
    }
}

// Resizes the various parts of the checkout page after a browser resize event.
// Only usable from the checkout page (of course).
function resizeCheckoutPage() {
    startResize();
    
    try {
        var contentArea = document.getElementById("contentArea");
        var thumbnailContainer = document.getElementById("thumbnailContainer");
        var orderFormContainer = document.getElementById("orderFormContainer");
        thumbnailContainer.style.height = (contentArea.clientHeight - 5) + "px";
        orderFormContainer.style.height = (contentArea.clientHeight - 5) + "px";
        orderFormContainer.style.width = max(contentArea.clientWidth - thumbnailContainer.offsetWidth - 6, 0) + "px";
    } catch (e) {
    // Ignore errors. Tends to happen in WebbIE, presumably since it doesn't render anything.
    } finally {
        endResize();
    }
}

// Updates the price of an image on the checkout page, following a change
// to the quantity or size field of that image.
// Only usable from the checkout page (of course).
function updateImagePrice(imageId)
{
    var priceDiv = document.getElementById("image-" + imageId + "-price");
    var sizeSelectors = document.getElementsByName("image-" + imageId + "-size");
    var quantitySelectors = document.getElementsByName("image-" + imageId + "-quantity");
    var imagePrice = 0;
    
    for (var i = 0; i < sizeSelectors.length; i++) {
        imagePrice += calculateImagePrice(imageId, sizeSelectors[i], quantitySelectors[i], true);
    }
   
    var imagePriceText = renderCurrency(imagePrice);
    
    // Bug with IE 5.2 on Mac - set innerHTML to "" before
    // setting it to a new value.
    priceDiv.innerHTML = "";
    priceDiv.innerHTML = imagePriceText;
    return imagePrice;
}

// Updates the total price on the checkout page, following a change
// to the quantity or size field of an image.
// Only usable from the checkout page (of course).
function updateTotalPrice(imageIdsAsString)
{
    var priceDiv = document.getElementById("totalPriceDiv");
    var imageIds = imageIdsAsString.split(",");
    var totalPrice = 0;
    
    for (var i = 0; i < imageIds.length; i++) {
        if (imageIds[i].length > 0) {
            totalPrice += updateImagePrice(imageIds[i]);
        }
    }

    var totalPriceText = renderCurrency(totalPrice);
    priceDiv.innerHTML = "";
    priceDiv.innerHTML = totalPriceText;
}

// Utility method used by updateImagePrice and updateTotalPrice to calculate
// the price of a specified order item.
// Only usable (naturally) from the checkout page.
function calculateImagePrice(imageId, sizeSelector, quantitySelector, alertErrors) {
//    try {
        var perItemPrice = document.getElementById("image-" + imageId + "-price-each");
        var qty = parseInt(quantitySelector.value);
        
        if (perItemPrice != null) {
            // EARLY RETURN - this image is a standard product with a per-item price
            return perItemPrice.value * qty;
        }
        
        var selectedSize = sizeSelector.options[sizeSelector.selectedIndex];
        
        if (null == selectedSize || selectedSize.value == "" || null == quantitySelector.value || quantitySelector.value == "") {
            return 0;
        } else {
            var unitPrice = document.getElementById("size-" + selectedSize.value + "-price").value;
      
            if (quantitySelector.value != qty) {
                if (alertErrors) {
                    alert(quantitySelector.value + " is not a valid quantity.");
                    quantitySelector.focus();
                }

                quantitySelector.value = "1";
                qty = 1;
            }

            return unitPrice * qty;
        }
//    } catch (e) {
//        if (alertErrors) {
//            alert(e.message);
//        }
//    }
}

// Validates and submits an order from the checkout.
// Only usable (funnily enough) from the checkout.
function placeOrder(imageIdsAsString) {
    var OrderForm = document.getElementById("OrderForm");
    var numUnselectedImages = 0;
    var imageIds = imageIdsAsString.split(",");
    var totalPrice = 0;
    var skipPersonalConfirmation = false;
    
    for (var i = 0; i < imageIds.length; i++) {
        if (imageIds[i].length > 0) {
            var sizeSelectors = document.getElementsByName("image-" + imageIds[i] + "-size");
            var quantitySelectors = document.getElementsByName("image-" + imageIds[i] + "-quantity");
            
            for (var j = 0; j < sizeSelectors.length; j++)
            {
                var imagePrice = calculateImagePrice(imageIds[i], sizeSelectors[j], quantitySelectors[j], true);
                totalPrice += imagePrice;
                
                if (imagePrice == 0) {
                    numUnselectedImages++;
                }
            }
        }
    }

    if (totalPrice == 0) {
        alert("You have not specified anything to order. Please review print sizes and quantities on the left of the screen.");
        // EARLY RETURN - No images selected for ordering.
        return;
    } else if (numUnselectedImages) {
        var pluralBit = (numUnselectedImages == 1) ? "1 item has" : numUnselectedImages + " items have"
        if (!confirm(pluralBit + " no size or quantity specified, and will not be included in your order.\n\nDo you want to order the other items anyway?")) {
            // EARLY RETURN - One or more images not selected, and user decides to review.
            return;
        } else {
            skipPersonalConfirmation = true;
        }
    }
    
    if (document.getElementById("customerName").value == null
        || document.getElementById("customerAddress1").value == null
        || document.getElementById("customerCity").value == null
        || document.getElementById("customerPostcode").value == null
        || document.getElementById("customerName").value == ""
        || document.getElementById("customerAddress1").value == ""
        || document.getElementById("customerCity").value == ""
        || document.getElementById("customerPostcode").value == "") {
        alert("You have not entered all required fields on the order form.");
        // EARLY RETURN - Required fields on order form not filled in.
        return;
    }
    
    var agreedToTermsRef = document.getElementById("agreeToTerms");
    
    if (!agreedToTermsRef.checked) {
        alert("Please read and agree to the terms and conditions before submitting your order.");
        // EARLY RETURN - no agreement to terms and conditions
        return;
    }
    
    var confirmationMessage = (skipPersonalConfirmation ? "" : "Submit this order now?");

    if ((confirmationMessage == "") || confirm(confirmationMessage)) {
        OrderForm.submit();
    }
}

// Resizes the specified image (in imageRef, with natural aspect of imageAspect) to fit in
// its container (whose dimensions are imageCellWidth and imageCellHeight). If suppressReload
// is false, the image is re-requested from originalUrl at the new size if originalSize
// (which should be the natural size of the current copy of the image) is significantly
// smaller than the new size.
function resizeImage(imageAspect, imageRef, imageCellWidth, imageCellHeight, originalUrl, originalSize, suppressReload, cropToFit, containerRef) {
    try {
        var imageCellAspect = imageCellWidth / imageCellHeight;
        var imageWidth;
        var imageHeight;
        imageRef.parentNode.style.display = "";

        if (cropToFit) {
            if (imageAspect < imageCellAspect) {
              imageWidth = imageCellWidth;
              imageHeight = Math.round(imageWidth / imageAspect);
            } else {
              imageHeight = imageCellHeight;
              imageWidth = Math.round(imageHeight * imageAspect);
            }
        } else {
            if (imageAspect > imageCellAspect) {
              imageWidth = imageCellWidth;
              imageHeight = Math.round(imageWidth / imageAspect);
            } else {
              imageHeight = imageCellHeight;
              imageWidth = Math.round(imageHeight * imageAspect);
            }
        }
        
        imageRef.style.height = imageHeight + "px";
        imageRef.style.width = imageWidth + "px";

        if (null != containerRef) {
            imageRef.style.position = "relative";
            imageRef.style.top = Math.round((imageCellHeight - imageHeight) / 2.0) + "px";
            imageRef.style.left = Math.round((imageCellWidth - imageWidth) / 2.0) + "px";
        }
        
        if (null != containerRef) {
            containerRef.style.width = imageCellWidth + "px";
            containerRef.style.height = imageCellHeight + "px";
        }
        
        if ((originalUrl != null) && (originalUrl != "") && !suppressReload) {
            var imageSize = (imageAspect > 1) ? imageWidth : imageHeight;
            
            if ((imageSize > (resizeThresholdFactor * originalSize))) {
                originalSize = imageSize;
                imageRef.src = originalUrl + "&size=" + originalSize;
                return imageSize;
            }
        }
        
        return null;
    } catch (e) {
    // Ignore errors. Tends to happen in WebbIE, presumably since it doesn't render anything.
    }
}

// Moves to the next (if increment = 1) or previous page (if increment = -1) of the search results.
// Usable only from the search page.
function moveSearchResultsPage(increment) {
    try {
        var PageForm = document.getElementById("PageForm");
        PageForm.page.value = parseInt(PageForm.page.value) + increment;
        PageForm.submit();
    } catch (e) {
    // Ignore errors. Tends to happen in WebbIE, presumably since it doesn't render anything.
    }
}

// Highlights the appropriate story and marker, and ensures that both are
// scrolled into view.
// Usable only from the stories (map) page.
function mouseOverStory(storyId, scrollToMarker, scrollToLink) {
    var marker = document.getElementById("story-" + storyId + "-marker");
    var storyLink = document.getElementById("story-" + storyId + "-link");
    
    storyLink.className = "highlight";
    
    if (scrollToLink) {
        scrollIntoView(storyLink);
    }
    
    if (null != marker) {
        marker.firstChild.firstChild.className = "markerHighlight";
        marker.style.zIndex = 1;
        
        if (scrollToMarker) {
            scrollIntoView(marker);
        }
    }
}

// Removes the highlight from the appropriate story and marker.
// Usable only from the stories (map) page.
function mouseOutStory(storyId) {
    var marker = document.getElementById("story-" + storyId + "-marker");
    var storyLink = document.getElementById("story-" + storyId + "-link");
    
    storyLink.className = "";

    if (null != marker) {
        marker.firstChild.firstChild.className = "marker";
        marker.style.zIndex = "";
    }
}

// Resizes a static page following a browser resize event.
// Used from InfoPage.master for rendering all static pages.
function resizeTextPage() {
    startResize();
    try {
        var contentArea = document.getElementById("contentArea");
        var textPane = document.getElementById("textPane");
        
        textPane.style.width = (contentArea.clientWidth - 6) + "px";
        textPane.style.height = (contentArea.clientHeight - 4) + "px";
    } catch (e) {
    // Ignore errors. Tends to happen in WebbIE, presumably since it doesn't render anything.
    } finally {
        endResize();
    }
}
