/*
 * (c) Copyright 2006, Klika, all rights reserved.
 *
 * This code is the property of Klika d.o.o. The code
 * may not be included in, invoked from, or otherwise
 * used in any software, service, device, or process
 * which is sold, exchanged for profit, or for which
 * a license, subscription, or royalty fee is charged.
 *
 * Permission is granted to use this code for personal,
 * educational, research, or commercial purposes, provided
 * this notice is included, and provided this code is not
 * used as described in the above paragraph.
 *
 * This code may not be modified without express
 * permission of Klika. You may not delete, disable, or in
 * any manner alter distinctive brand features rendered
 * by the code. The use of this code in derivative work is
 * permitted, provided that the code and this notice are
 * included in full, and provided that the code is used in
 * accordance with these terms.
 *
 * Email: info at triptracker.net
 * Web:   http://slideshow.triptracker.net
 */

   var MESSAGES = {'format.date': "MM/dd/yyyy",
        'format.time': "h:mm a",
        'photoviewer.toolbar.first': "Go to Start (Home)",
        'photoviewer.toolbar.prev': "Previous Photo (Left arrow)",
        'photoviewer.toolbar.slideShow': "Start/Pause Slide Show (Space)",
        'photoviewer.toolbar.next': "Next Photo (Right arrow)",
        'photoviewer.toolbar.last': "Go to End (End)",
        'photoviewer.toolbar.email': "Email Photo",
        'photoviewer.toolbar.permalink': "Link to Photo",
        'photoviewer.toolbar.close': "Close (Esc)",
        'photoviewer.email.subject.photo': "Photo",
        'gallery.nophotos': "No photos",
        'gallery.thumbs.start': "Start",
        'gallery.thumbs.end': "End",
        'gallery.toolbar.first': "First Photo",
        'gallery.toolbar.prev': "Previous Photo",
        'gallery.toolbar.view': "View Photo",
        'gallery.toolbar.next': "Next Photo",
        'gallery.toolbar.last': "Last Photo",
        'gallery.view.full': "Maximize Window",
        'gallery.view.photo': "Show Photo Only",
        'gallery.view.text': "Show Description Only",
        'gallery.view.close': "Close Window"};
        
        
        
    var agent = navigator.userAgent.toLowerCase();
    var IE = agent.indexOf("msie") != -1 && agent.indexOf("opera") == -1;
    var IE7 = agent.indexOf("msie 7") != -1;
    var IE8 = agent.indexOf("msie 8") != -1;
    var OPERA = agent.indexOf("opera") != -1;
    var SAFARI = agent.indexOf("safari") != -1;
    var FIREFOX = agent.indexOf("gecko") != -1;
    var STRICT_MODE = document.compatMode == "CSS1Compat";
    var _DOMAIN = undefined;
    var GALLERY_W = 650;
    var GALLERY_H = 530;
    if (USE_GOOGLE_MAPS == undefined) {
        var USE_GOOGLE_MAPS = true;
    }
    var USE_OLD_MAPS = !USE_GOOGLE_MAPS;
    var TESTING = false;
    var log = getLogger();
    if (document.location.href.indexOf("#jslog") != -1) {
        log.enable();
    }

    function Logger() {
        this.enable = loggerEnable;
        this.clear = loggerClear;
        this.log = loggerLog;
        this.debug = loggerDebug;
        this.info = loggerInfo;
        this.error = loggerError;
        var console = undefined;
        try {
            console = document.createElement("textarea");
            console.style.display = "none";
            console.style.position = "absolute";
            console.style.right = "2px";
            console.style.bottom = "2px";
            console.style.width = "23em";
            console.style.height = "40em";
            console.style.fontFamily = "monospace";
            console.style.fontSize = "9px";
            console.style.color = "#000000";
            setOpacity(console, 0.7);
            console.border = "1px solid #808080";
            console.ondblclick = clearLogger;
        } catch (e) {
        }
        this.console = console;
        this.enabled = false;
        this.logTimeStart = getTimeMillis();
    }


    function getLogger() {
        var log = undefined;
        var win = window;
        while (log == undefined) {
            try {
                log = win.document.log;
            } catch (e) {
                break;
            }
            if (win == win.parent) {
                break;
            }
            win = win.parent;
        }
        if (log == undefined) {
            log = new Logger;
            document.log = log;
        }
        return log;
    }


    function clearLogger() {
        getLogger().clear();
    }


    function loggerEnable() {
        if (this.enabled || this.console == undefined) {
            return;
        }
        if (window.document.body != undefined) {
            window.document.body.appendChild(this.console);
            this.console.style.display = "";
            this.enabled = true;
        }
    }


    function loggerDebug(msg) {
        this.log("DEBUG", msg);
    }


    function loggerInfo(msg) {
        this.log("INFO", msg);
    }


    function loggerError(msg, e) {
        this.log("ERROR", msg, e);
    }


    function loggerLog(level, msg, e) {
        if (!this.enabled || this.console == undefined) {
            return;
        }
        var millis = (getTimeMillis() - this.logTimeStart) + "";
        while (millis.length < 6) {
            millis += " ";
        }
        var m = millis + " ";
        if (msg != undefined) {
            m += msg + " ";
        }
        if (e != undefined) {
            m += e.name + ": " + e.message;
        }
        this.console.value += m + "\n";
    }


    function loggerClear() {
        if (!this.enabled || this.console == undefined) {
            return;
        }
        this.console.value = "";
    }


    function getTimeMillis() {
        var t = new Date;
        return Date.UTC(t.getFullYear(), t.getMonth(), t.getDay(), t.getHours(), t.getMinutes(), t.getSeconds(), t.getMilliseconds());
    }


    function getEvent(event) {
        return event != undefined ? event : window.event;
    }


    function preventDefault(event) {
        if (event.stopEvent) {
            event.stopEvent();
        }
        if (event.preventDefault) {
            event.preventDefault();
            event.stopPropagation();
        } else {
            event.returnValue = false;
            event.cancelBubble = true;
        }
    }


    function getEventTarget(event) {
        if (event == undefined) {
            return undefined;
        }
        if (event.srcElement != undefined) {
            return event.srcElement;
        } else {
            return event.target;
        }
    }


    function getMousePosition(event) {
        event = getEvent(event);
        var scrollLeft = window.pageXOffset;
        if (scrollLeft == undefined || scrollLeft === 0) {
            scrollLeft = window.document.documentElement.scrollLeft;
        }
        if (scrollLeft == undefined || scrollLeft === 0) {
            scrollLeft = window.document.body.scrollLeft;
        }
        var scrollTop = window.pageYOffset;
        if (scrollTop == undefined || scrollTop === 0) {
            scrollTop = window.document.documentElement.scrollTop;
        }
        if (scrollTop == undefined || scrollTop === 0) {
            scrollTop = window.document.body.scrollTop;
        }
        var x = event.clientX + scrollLeft;
        var y = event.clientY + scrollTop;
        return {x: x, y: y};
    }


    function getResponse(url, async, getXML, callback, data) {
        var req = undefined;
        try {
            req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e1) {
            try {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e2) {
                req = new XMLHttpRequest;
            }
        }
        if (req == undefined) {
            log.error("Failed to initialize XML/HTTP");
            return undefined;
        }
        req.open("GET", url, async);
        if (!async) {
            req.send(undefined);
            if (req.readyState != 4) {
                log.error("Request failed: " + req.readyState);
                return undefined;
            }
            if (!getXML) {
                return req.responseText;
            } else {
                return req.responseXML;
            }
        } else {
            pollResponse(req, callback, data);
            req.send(undefined);
            return undefined;
        }
    }


    function pollResponse(req, callback, data) {
        if (req.readyState != 4) {
            window.setTimeout(function () {pollResponse(req, callback, data);}, 100);
        } else {
            callback(req, data);
        }
    }


    function getDOMLocation(node) {
        var x = node.offsetLeft;
        var y = node.offsetTop;
        while (node.offsetParent) {
            x = x + node.offsetParent.offsetLeft;
            y = y + node.offsetParent.offsetTop;
            if (node == document.getElementsByTagName("body")[0]) {
                break;
            } else {
                node = node.offsetParent;
            }
        }
        return {x: x, y: y};
    }


    function getElementsByTagName(node, tag) {
        if (node == undefined) {
            return undefined;
        }
        if (IE) {
            return node.getElementsByTagName(tag);
        }
        if (tag.indexOf(":") != -1) {
            tag = tag.split(":")[1];
        }
        return node.getElementsByTagNameNS("*", tag);
    }


    function getFirstElementsValue(node, tag) {
        if (node == undefined) {
            return undefined;
        }
        var nodes = getElementsByTagName(node, tag);
        if (nodes.length === 0) {
            return undefined;
        } else {
            return getElementValue(nodes[0]);
        }
    }


    function findDOMElement(id) {
        var el = undefined;
        var win = window;
        while (el == undefined) {
            try {
                el = win.document.getElementById(id);
            } catch (e) {
                break;
            }
            if (win === win.parent) {
                break;
            }
            win = win.parent;
        }
        return el;
    }


    function getElementValue(node) {
        var i;
        var val = "";
        for (i = 0; i < node.childNodes.length; i++) {
            if (node.childNodes[i].nodeValue !== null) {
                val += node.childNodes[i].nodeValue;
            }
        }
        return val;
    }


    function trim(str) {
        if (str == undefined) {
            return undefined;
        }
        return str.replace(/^\s*([\s\S]*\S+)\s*$|^\s*$/, "$1");
    }


    function trimToLen(str, len) {
        if (str == undefined) {
            return undefined;
        }
        if (str.length > len) {
            str = str.substring(0, len) + "...";
        }
        return str;
    }


    function getRootWindow() {
        var win = window;
        while (win != undefined) {
            try {
                if (win === win.parent) {
                    break;
                } else if (win.parent != undefined &&
                    win.parent.document.location.href.indexOf("/selenium-server/") != -1) {
                    break;
                }
                win = win.parent;
            } catch (e) {
                win.permissionDenied = true;
                break;
            }
        }
        return win;
    }


    function getURLParams() {
        var i, params = [];
        var url = window.location.search;
        if (url == undefined || url.length === 0) {
            return undefined;
        }
        url = url.substring(1);
        var namevals = url.replace(/\+/g, " ").split("&");
        for (i = 0; i < namevals.length; i++) {
            var name, val;
            var pos = namevals[i].indexOf("=");
            if (pos != -1) {
                name = namevals[i].substring(0, pos);
                val = unescape(namevals[i].substring(pos + 1));
            } else {
                name = namevals[i];
                val = undefined;
            }
            params[name] = val;
        }
        return params;
    }


    function joinLists(list1, list2) {
        var i;
        var size = 0;
        var result = [];
        if (list1 != undefined && list1.length > 0) {
            for (i = 0; i < list1.length; i++) {
                result[i] = list1[i];
            }
            size = list1.length;
        }
        if (list2 != undefined && list2.length > 0) {
            for (i = 0; i < list2.length; i++) {
                result[i + size] = list2[i];
            }
        }
        return result;
    }


    function setCookie(name, value, expire) {
        var expiry = (expire == undefined) ? "" : "; expires=" + expire.toGMTString();
        document.cookie = name + "=" + value + expiry;
    }


    function getCookie(name) {
        if (document.cookie == undefined || document.cookie.length === 0) {
            return undefined;
        }
        var search = name + "=";
        var index = document.cookie.indexOf(search);
        if (index != -1) {
            index += search.length;
            var end = document.cookie.indexOf(";", index);
            if (end == -1) {
                end = document.cookie.length;
            }
            return unescape(document.cookie.substring(index, end));
        }
    }


    function removeCookie(name) {
        var today = new Date;
        var expires = new Date;
        expires.setTime(today.getTime() - 1);
        setCookie(name, "", expires);
    }


    function getMessage(id) {
        if (MESSAGES[id] == undefined) {
            return "(" + id + ")";
        } else {
            return MESSAGES[id];
        }
    }


    function localizeNodeAttribs(node) {
        var i;
        if (node == undefined) {
            return;
        }
        if (node.alt != undefined && node.alt.indexOf("#") === 0) {
            node.alt = getMessage(node.alt.substring(1));
        }
        if (node.title != undefined && node.title.indexOf("#") === 0) {
            node.title = getMessage(node.title.substring(1));
        }
        if (node.childNodes != undefined) {
            for (i = 0; i < node.childNodes.length; i++) {
                localizeNodeAttribs(node.childNodes[i]);
            }
        }
    }


    function padNumber(n, pad) {
        n = n + "";
        while (n.length < pad) {
            n = "0" + n;
        }
        return n;
    }


    function isArray(obj) {
        if (obj instanceof Array) {
            return true;
        } else {
            return false;
        }
    }


    function simpleDateFormatter(date, pattern) {
        var d = pattern;
        d = d.replace(/yyyy/g, date.getFullYear());
        d = d.replace(/yy/g, padNumber(date.getFullYear() % 100, 2));
        d = d.replace(/MM/g, padNumber(date.getMonth() + 1, 2));
        d = d.replace(/M/g, date.getMonth() + 1);
        d = d.replace(/dd/g, padNumber(date.getDate(), 2));
        d = d.replace(/d/g, date.getDate());
        d = d.replace(/HH/g, padNumber(date.getHours(), 2));
        d = d.replace(/H/g, date.getHours());
        d = d.replace(/hh/g, padNumber(date.getHours() % 12, 2));
        d = d.replace(/h/g, date.getHours() % 12);
        d = d.replace(/mm/g, padNumber(date.getMinutes(), 2));
        d = d.replace(/m/g, date.getMinutes());
        d = d.replace(/ss/g, padNumber(date.getSeconds(), 2));
        d = d.replace(/s/g, date.getSeconds());
        var am = date.getHours() < 12 ? "AM" : "PM";
        d = d.replace(/a/g, am);
        return d;
    }


    function formatDateTime(date) {
        if (date == undefined) {
            return undefined;
        }
        return formatDate(date) + " " + formatTime(date);
    }


    function formatDate(date) {
        var datePattern = getMessage("format.date");
        return simpleDateFormatter(date, datePattern);
    }


    function formatTime(date) {
        var timePattern = getMessage("format.time");
        return simpleDateFormatter(date, timePattern);
    }


    function parseISOTime(strTime) {
        if (strTime == undefined) {
            return undefined;
        }
        var isoRE = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(\.\d{3})?([Z+-])?(\d\d)?:?(\d\d)?$/;
        if (!isoRE.test(strTime)) {
            return undefined;
        } else {
            return new Date(RegExp.$1, RegExp.$2 - 1, RegExp.$3, RegExp.$4, RegExp.$5, RegExp.$6);
        }
    }


    function setOpacity(elt, opacity) {
        if (IE) {
            elt.style.filter = "alpha(opacity=" + parseInt(opacity * 100) + ")";
        }
        elt.style.KhtmlOpacity = opacity;
        elt.style.opacity = opacity;
    }


    function validCoordinates(lat, lon) {
        if (Math.abs(lat) > 90 || Math.abs(lon) > 180) {
            return false;
        }
        if (lat === 0 && lon === 0) {
            return false;
        }
        return true;
    }



    function isHosted() {
        return false; //put in return false here to avoid annoying advert
    
        var host = document.location.host;        // returns the name of the host, e.g. localhost
        if (host == undefined) {
            host = "";
        }
        
        // return ( x || x ) && x && x && x
        
        //if the script is not on triptracker.net, not on rtsvslo.si, not on localhost and checkDomain() returns false
        //the site is considered hosted
        
        return ( host.indexOf("triptracker.net") == -1 || host.indexOf("slideshow.triptracker.net") != -1 ) &&
            host.indexOf("rtvslo.si") == -1 &&
            host != "localhost" && !checkDomain();
    }

    //checkDomain is only called from isHosted() above
    function checkDomain() {
        try {
            if (_DOMAIN == undefined) {
                return false;
            }
            var protocol = document.location.protocol;
            if (protocol == undefined) {
                protocol = "http:";
            }
            var host = document.location.host;
            if (host == undefined) {
                host = "";
            }
            host = host.toLowerCase();
            if (protocol.toLowerCase().indexOf("file") === 0) {
                return true;
            }
            var pos = host.lastIndexOf(":");
            if (pos != -1) {
                host = host.substring(0, pos);
            }
            if (host.indexOf("www.") === 0) {
                host = host.substring(4);
            }
            if (host === "" || host == "localhost" || host == "127.0.0.1") {
                return true;
            }
            var domain = _DOMAIN.toLowerCase();
            pos = domain.indexOf("://");
            if (pos != -1) {
                domain = domain.substring(pos + 3);
            }
            pos = domain.indexOf("/");
            if (pos != -1) {
                domain = domain.substring(0, pos);
            }
            if (domain.indexOf("www.") === 0) {
                domain = domain.substring(4);
            }
            if (host == domain) {
                return true;
            } else if ((new RegExp(domain)).test(host)) {
                return true;
            }
            return false;
        } catch (e) {
            return true;
        }
    }


    function getWindowSize(win) {
        var availW = win.innerWidth;
        if (availW == undefined || availW === 0 || isNaN(availW)) {
            availW = win.document.documentElement.clientWidth;
        }
        if (availW == undefined || availW === 0 || isNaN(availW)) {
            availW = win.document.body.clientWidth;
        }
        var availH = win.innerHeight;
        if (availH == undefined || availH === 0 || isNaN(availH)) {
            availH = win.document.documentElement.clientHeight;
        }
        if (availH == undefined || availH === 0 || isNaN(availH)) {
            availH = win.document.body.clientHeight;
        }
        return {w: availW, h: availH};
    }


    function getDocumentSize(win) {
        var winSize = getWindowSize(win);
        var scrollPos = getScrollPos(win);
        var w = winSize.w + scrollPos.left;
        var h = winSize.h + scrollPos.top;
        w = Math.max(w, win.document.body.offsetWidth);
        h = Math.max(h, win.document.body.offsetHeight);
        w = Math.max(w, win.document.body.scrollWidth);
        h = Math.max(h, win.document.body.scrollHeight);
        return {w: w, h: h};
    }


    function getScrollPos(win) {
        var scrollTop = win.pageYOffset;
        if (scrollTop == undefined || scrollTop === 0) {
            scrollTop = win.document.documentElement.scrollTop;
        }
        if (scrollTop == undefined || scrollTop === 0) {
            scrollTop = win.document.body.scrollTop;
        }
        var scrollLeft = win.pageXOffset;
        if (scrollLeft == undefined || scrollLeft === 0) {
            scrollLeft = win.document.documentElement.scrollLeft;
        }
        if (scrollLeft == undefined || scrollLeft === 0) {
            scrollLeft = win.document.body.scrollLeft;
        }
        return {top: scrollTop, left: scrollLeft};
    }

    var CLEAR_EVENTS = ["onclick", "ondblclick", "onkeydown", "onkeypress", "onmousedown", "onmouseup", "onmousemove", "onmouseover", "onmouseout", "onmousewheeldown", "oncontextmenu"];

    function clearEvents() {
        var i, j;
        var count = 0;
        if (document.all == undefined) {
            return;
        }
        for (i = 0; i < document.all.length; i++) {
            for (j = 0; j < CLEAR_EVENTS.length; j++) {
                var event = document.all[i][CLEAR_EVENTS[j]];
                if (event != undefined) {
                    document.all[i][CLEAR_EVENTS[j]] = null;
                    count++;
                }
            }
        }
    }

    if (window.attachEvent) {
        window.attachEvent("onunload", clearEvents);
    }

    function getGallery() {
        var gallery = undefined;
        var win = window;
        while (gallery == undefined) {
            try {
                gallery = win.document.gallery;
            } catch (e) {
                break;
            }
            var tmpWin = win;
            win = win.parent;
            if (tmpWin === win) {
                break;
            }
        }
        return gallery;
    }


    function getMap() {
        if (this.map != undefined) {
            return this.map;
        }
        try {
            if (document.map != undefined) {
                return document.map;
            }
        } catch (e) {
        }
        try {
            if (window.parent.document.map != undefined) {
                return window.parent.document.map;
            }
        } catch (e) {
        }
        return undefined;
    }


    function viewerCloseCallback(photoIndex) {
        var i, j, n = 0;
        var gallery = getGallery();
        for (i = 0; i < gallery.sets.length; i++) {
            for (j = 0; j < gallery.sets[i].photos.length; j++) {
                var p = gallery.sets[i].photos[j];
                if (p == undefined ||
                    p.orig == undefined || p.orig.src == undefined) {
                    continue;
                }
                if (n == photoIndex) {
                    gallery.setIndex = i;
                    gallery.photoIndex = j;
                    gallery.renderPhotos();
                    gallery.win.focus();
                    return;
                }
                n++;
            }
        }
    }

    var VIEWER_INDEX = 0;
    var SLIDE_DURATION = 4000;
    var SLIDE_OFFSET = 50;
    var SLIDE_PHOTOS = true;
    var FADE_BORDER = false;
    var FADE_STEPS = 10;
    var MOVE_STEP = 1;
    var PRELOAD_TIMEOUT = 60000;
    var BORDER_WIDTH = 5;
    var FONT_SIZE = 10;
    var LINE_HEIGHT = "0.7em";
    var OFFSET_LEFT = 0;
    var OFFSET_TOP = 0;
    var REST_URL = "/rest/";
    
    //var P_IMG_ROOT = "http://static.triptracker.net/jsmap/images/photoviewer";
    //var P_IMG_ROOT = "./";
    var P_IMG_ROOT = "./includes/photo_album";
    
    var TOOLBAR_IMG = "toolbar.png";
    var TOOLBAR_IMG_RUNNING = "toolbar2.png";
    var TOOLBAR_IMG_BACK = "toolbar-back";
    var TOOLBAR_IMG_MASK = "toolbar-mask.png";
    var TOOLBAR_IMG_LOADING = "loading-anim.gif";
    var TOOLBAR_W = 440;
    var TOOLBAR_H = 75;
    var TOOLBAR_IMG_W = 420;
    var TOOLBAR_IMG_H = 44;
    
    //var TOOLBAR_LINK = "http://slideshow.triptracker.net";
    var TOOLBAR_LINK = "http://www.cutec.org";
    
    var TOOLBAR_OPACITY = 0.7;
    var TOOLBAR_FONT_COLOR = "#c0c0c0";
    var TOOLBAR_FONT_STYLE = "tahoma, verdana, arial, helvetica, sans-serif";
    var BYLINE_FONT_COLOR = TOOLBAR_FONT_COLOR;
    var BYLINE_FONT_STYLE = TOOLBAR_FONT_STYLE;
    var BYLINE_POSITION_RIGHT = 5;
    var BYLINE_POSITION_BOTTOM = 5;
    var VIEWER_ID_PREFIX = "PhotoViewer";
    var VIEWER_ID_BACK = VIEWER_ID_PREFIX + "Back";
    var VIEWER_ID_TOOLBAR = VIEWER_ID_PREFIX + "Toolbar";
    var VIEWER_ID_TOOLBAR_MAP = VIEWER_ID_PREFIX + "ToolbarMap";
    var VIEWER_ID_TOOLBAR_IMG = VIEWER_ID_PREFIX + "ToolbarImg";
    var VIEWER_ID_LOADING = VIEWER_ID_PREFIX + "Loading";
    var VIEWER_ID_TIME = VIEWER_ID_PREFIX + "Time";
    var VIEWER_ID_TITLE = VIEWER_ID_PREFIX + "Title";
    var VIEWER_ID_BYLINE = VIEWER_ID_PREFIX + "Byline";
    var VIEWER_ID_PHOTO = VIEWER_ID_PREFIX + "Photo";
    var VIEWER_ID_CTXMENU = VIEWER_ID_PREFIX + "CtxMenu";
    var TITLE_MAX_LENGTH = 140;
    var TOOLBAR_IMG_LOADING_LEFT = 273;
    var TOOLBAR_IMG_LOADING_TOP = 24;






    function PhotoViewer(win, handleKeys) {
        this.setImageRoot = setImageRoot;
        this.add = addPhoto;
        this.show = showPhoto;
        this.close = closePhoto;
        this.randomize = randomize;
        this.isShown = isPhotoShown;
        this.setBackground = setPhotoBackground;
        this.setShowToolbar = setShowToolbar;
        this.setToolbarImage = setToolbarImage;
        this.setShowCallback = setShowCallback;
        this.setCloseCallback = setCloseCallback;
        this.setEndCallback = setEndCallback;
        this.setLoading = setPhotoLoading;
        this.addBackShade = addBackShade;
        this.addToolbar = addToolbar;
        this.addCaptions = addCaptions;
        this.addByLine = addByLine;
        this.addBylineCaption = addBylineCaption;
        this.next = nextPhoto;
        this.prev = prevPhoto;
        this.first = firstPhoto;
        this.last = lastPhoto;
        this.slideShow = slideShow;
        this.slideShowStop = slideShowStop;
        this.startSlideShow = startSlideShow;
        this.handleKey = viewerHandleKey;
        this.checkStartFragmentIdentifier = checkStartFragmentIdentifier;
        this.checkStopFragmentIdentifier = checkStopFragmentIdentifier;
        this.setStartFragmentIdentifier = setStartFragmentIdentifier;
        this.setStopFragmentIdentifier = setStopFragmentIdentifier;
        this.email = emailPhoto;
        this.favorite = favoritePhoto;
        this.permalink = linkPhoto;
        this.setBackgroundColor = setBackgroundColor;
        this.setBorderWidth = setBorderWidth;
        this.setSlideDuration = setSlideDuration;
        this.disablePanning = disablePanning;
        this.enablePanning = enablePanning;
        this.disableFading = disableFading;
        this.enableFading = enableFading;
        this.disableShade = disableShade;
        this.enableShade = enableShade;
        this.setShadeColor = setShadeColor;
        this.setShadeOpacity = setShadeOpacity;
        this.setFontSize = setFontSize;
        this.setFont = setFont;
        this.enableAutoPlay = enableAutoPlay;
        this.disableAutoPlay = disableAutoPlay;
        this.enableEmailLink = enableEmailLink;
        this.disableEmailLink = disableEmailLink;
        this.enablePhotoLink = enablePhotoLink;
        this.disablePhotoLink = disablePhotoLink;
        this.setOnClickEvent = setOnClickEvent;
        this.setOnRightclickEvent = setOnRightclickEvent;
        this.enableLoop = enableLoop;
        this.disableLoop = disableLoop;
        this.enableToolbarAnimator = enableToolbarAnimator;
        this.disableToolbarAnimator = disableToolbarAnimator;
        this.enableToolbar = enableToolbar;
        this.disableToolbar = disableToolbar;
        this.setControlsImageMap = setControlsImageMap;
        this.setOverrideToolbarStyles = setOverrideToolbarStyles;
        this.setNoPadding = setNoPadding;
        this.hideOverlappingElements = hideOverlappingElements;
        this.showOverlappingElements = showOverlappingElements;
        this.addContextMenu = addContextMenu;
        this.setEmailAddress = setEmailAddress;
        this.id = VIEWER_ID_PREFIX + VIEWER_INDEX;
        VIEWER_INDEX++;
        this.photos = [];
        this.index = 0;
        this.win = win != undefined ? win : window;
        this.shown = false;
        this.showToolbar = true;
        this.backgroundColor = "#000000";
        this.shadeColor = "#000000";
        this.shadeOpacity = 0.7;
        this.borderColor = "#000000";
        this.shadeColor = "#000000";
        this.shadeOpacity = 0.7;
        this.borderWidth = BORDER_WIDTH;
        this.backgroundShade = true;
        this.fadePhotos = true;
        this.autoPlay = false;
        this.enableEmailLink = false;
        this.isEnablePhotoLink = false;
        this.slideDuration = SLIDE_DURATION;
        this.panPhotos = SLIDE_PHOTOS;
        this.fontSize = FONT_SIZE;
        this.font = undefined;
        if ((handleKeys == undefined || handleKeys) &&
            !VIEWER_KEY_EVENT_ADDED) {
            if (this.win.addEventListener) {
                this.win.addEventListener("keydown", viewerHandleKey, false);
            } else {
                this.win.document.attachEvent("onkeydown", viewerHandleKey);
            }
            VIEWER_KEY_EVENT_ADDED = true;
        }
        this.win.document.viewer = this;
        if (OPERA) {
            this.disableFading();
        }
    }

    var VIEWER_KEY_EVENT_ADDED = false;

    function PhotoImg(id, src, w, h, time, title, byline, link) {
        this.id = id;
        this.src = src;
        this.w = parseInt(w, 10);
        this.h = parseInt(h, 10);
        this.time = time;
        this.title = title;
        this.byline = byline;
        this.link = link;
    }


    function getViewer() {
        var viewer = undefined;
        var win = window;
        while (viewer == undefined) {
            try {
                viewer = win.document.viewer;
            } catch (e) {
                break;
            }
            if (win === win.parent) {
                break;
            }
            win = win.parent;
        }
        return viewer;
    }


    function setImageRoot(root) {
        P_IMG_ROOT = root;
    }


    function addPhoto(photo, title, time, byline, link) {
        var type = typeof photo;
        if (typeof photo == "string") {
            photo = new PhotoImg(undefined, photo, undefined, undefined, time, title, byline, link);
        }
        this.photos.push(photo);
    }


    function randomize() {
        var o = this.photos;
        for (var j, x, i = o.length; i; j = parseInt(Math.random((new Date).getSeconds()) * i, 10), x = o[--i], o[i] = o[j], o[j] = x) {
        }
    }


    function setPhotoBackground(color, border, doShade) {
        if (color != undefined) {
            this.backgroundColor = color;
        }
        if (border != undefined) {
            this.borderColor = border;
        }
        if (doShade != undefined) {
            this.backgroundShade = doShade;
        }
    }


    function setPhotoLoading(isLoading) {
        this.isLoading = isLoading;
        var elt = this.win.document.getElementById(VIEWER_ID_LOADING);
        if (elt == undefined) {
            return;
        }
        elt.style.display = isLoading ? "" : "none";
    }


    function setBackgroundColor(color) {
        this.backgroundColor = color;
        this.borderColor = color;
    }


    function setBorderWidth(width) {
        this.borderWidth = width;
    }


    function setSlideDuration(duration) {
        this.slideDuration = duration;
    }


    function disableShade() {
        this.backgroundShade = false;
    }


    function enableShade() {
        this.backgroundShade = true;
    }


    function setShadeColor(color) {
        this.shadeColor = color;
    }


    function setShadeOpacity(opacity) {
        this.shadeOpacity = opacity;
    }


    function disableFading() {
        this.fadePhotos = false;
    }


    function enableFading() {
        this.fadePhotos = true;
    }


    function disablePanning() {
        this.panPhotos = false;
    }


    function enablePanning() {
        this.panPhotos = true;
    }


    function setFontSize(size) {
        this.fontSize = size;
    }


    function setFont(font) {
        this.font = font;
    }


    function enableAutoPlay() {
        this.autoPlay = true;
    }


    function disableAutoPlay() {
        this.autoPlay = false;
    }


    function enableEmailLink() {
        this.enableEmailLink = true;
    }


    function disableEmailLink() {
        this.enableEmailLink = false;
    }


    function enablePhotoLink() {
        this.isEnablePhotoLink = true;
    }


    function disablePhotoLink() {
        this.isEnablePhotoLink = false;
    }


    function setOnClickEvent(newfunc) {
        this.customOnClickEvent = newfunc;
    }


    function setOnRightclickEvent(newfunc) {
        this.customOnRightclickEvent = newfunc;
    }


    function enableLoop() {
        this.loop = true;
    }


    function disableLoop() {
        this.loop = false;
    }


    function enableToolbar() {
        this.showToolbar = true;
    }


    function disableToolbar() {
        this.showToolbar = false;
    }


    function enableToolbarAnimator() {
        this.toolbarAnimator = new ToolbarAnimator(this);
    }


    function disableToolbarAnimator() {
        if (this.toolbarAnimator != undefined) {
            this.toolbarAnimator.reset();
            this.toolbarAnimator = undefined;
        }
    }


    function setControlsImageMap(imagemap) {
        this.customImageMap = imagemap;
    }


    function setOverrideToolbarStyles(overrideToolbarStyles) {
        this.overrideToolbarStyles = overrideToolbarStyles;
    }


    function setNoPadding(nopadding) {
        this.nopadding = nopadding;
    }


    function setEmailAddress(address) {
        this.emailAddress = address;
    }



    /*
    showPhoto - starts the player, the showPhoto function is linked to the viewer by the alias *show*.
    in PhotoViewer: this.show = showPhoto;

    in the photo_album.html:
    
    var viewer = new PhotoViewer();
    - link each photo to viewer.show(0), viewer.show(1), etc

    */

    function showPhoto(index, cropWidth, opacity) {
        if (this.photos.length === 0) {
            return true;
        }
        if (getRootWindow().permissionDenied &&
            this.badgeMode == undefined && !getRootWindow().livemode) {
            this.setStartFragmentIdentifier(index);
            return true;
        }
        if (index != undefined) {
            this.index = index;
        }
        if (this.index < 0 || this.index >= this.photos.length) {
            log.error("Invalid photo index");
            return true;
        }
        var doc = this.win.document;
        var firstShow = false;
        if (!this.shown) {
            firstShow = true;
            doc.viewer = this;
            try {
                this.hideOverlappingElements();
            } catch (e) {
            }
        }
        var zIndex = 16384;
        var winSize = getWindowSize(this.win);
        var availW = winSize.w - (this.nopadding ? this.borderWidth * 2 : 20);
        var availH = winSize.h - (this.nopadding ? this.borderWidth * 2 : 20);
        var scrollPos = getScrollPos(this.win);
        var scrollLeft = scrollPos.left;
        var scrollTop = scrollPos.top;
        this.addBackShade(zIndex);
        this.addByLine(zIndex);
        this.addBylineCaption();
        if (this.showToolbar) {
            this.addToolbar(availW, zIndex);
            this.addCaptions();
        }
        var photo = this.photos[this.index];
        if (isNaN(photo.w) || isNaN(photo.h)) {
            if (photo.preloadImage != undefined) {
                if (isNaN(photo.w) && photo.preloadImage.width > 0) {
                    photo.w = photo.preloadImage.width;
                }
                if (isNaN(photo.h) && photo.preloadImage.height > 0) {
                    photo.h = photo.preloadImage.height;
                }
            } else {
                this.index--;
                this.next();
                return false;
            }
        }
        this.shown = true;
        var offset = this.nopadding ? 0 : 20;
        var pw = -1;
        var ph = -1;
        if (parseInt(photo.w) > availW || parseInt(photo.h) > availH) {
            if (parseInt(photo.w) / availW > parseInt(photo.h) / availH) {
                pw = availW - offset;
                ph = parseInt(pw * photo.h / photo.w);
            } else {
                ph = availH - offset;
                pw = parseInt(ph * photo.w / photo.h);
            }
        } else {
            pw = parseInt(photo.w);
            ph = parseInt(photo.h);
        }
        if (pw <= 0 || ph <= 0) {
            if (!this.showToolbar) {
                throw "Missing photo dimension";
            }
        }
        if (cropWidth == undefined) {
            cropWidth = 0;
        }
        var photoDiv = doc.createElement("div");
        photoDiv.id = VIEWER_ID_PHOTO;
        photoDiv.style.visibility = "hidden";
        photoDiv.style.position = "absolute";
        photoDiv.style.zIndex = zIndex;
        photoDiv.style.overflow = "hidden";
        photoDiv.style.border = this.borderWidth + "px solid " + this.borderColor;
        photoDiv.style.textAlign = "center";
        photoDiv.style.backgroundColor = this.backgroundColor;
        var photoElt = doc.createElement("img");
        photoElt.style.visibility = "hidden";
        photoElt.style.position = "relative";
        photoElt.style.backgroundColor = this.backgroundColor;
        photoElt.style.border = "none";
        photoElt.style.cursor = "pointer";
        photoElt.style.zIndex = (parseInt(photoDiv.style.zIndex) + 1) + "";
        photoElt.onclick = onClickEvent;
        photoElt.oncontextmenu = onContextMenuEvent;
        if (opacity != undefined && this.fadePhotos) {
            var fadeElt = FADE_BORDER ? photoDiv : photoElt;
            setOpacity(fadeElt, opacity);
        }
        var left = parseInt((availW - pw) / 2) + (this.nopadding ? 0 : OFFSET_LEFT);
        photoDiv.style.left = (left + scrollLeft + cropWidth / 2) + "px";
        var top = parseInt((availH - ph) / 2) + (this.nopadding ? 0 : OFFSET_TOP);
        photoDiv.style.top = (top + scrollTop) + "px";
        photoElt.style.visibility = "hidden";
        photoDiv.style.width = (pw - cropWidth > 0 ? pw - cropWidth : pw) + "px";
        photoDiv.style.height = ph + "px";
        photoElt.style.width = pw + "px";
        photoElt.style.height = ph + "px";
        photoElt.src = photo.src;
        photoDiv.style.visibility = "visible";
        photoElt.style.visibility = "visible";
        photoDiv.appendChild(photoElt);
        doc.body.appendChild(photoDiv);
        if (this.photoDiv != undefined) {
            try {
                doc.body.removeChild(this.photoDiv);
            } catch (e) {
            }
        }
        this.photoDiv = photoDiv;
        this.photoImg = photoElt;
        this.setLoading(false);
        if (this.showCallback != undefined) {
            this.showCallback(this.index);
        }
        if (firstShow && this.autoPlay) {
            this.slideShow(true);
        }
        return false;
    }


    function isPhotoShown() {
        return this.shown;
    }


    function closeViewer() {
        getViewer().close();
    }


    function onPhotoLoad(event) {
        var viewer = getViewer();
        if (viewer != undefined) {
            if (flickrHack(viewer, viewer.index)) {
                viewer.setLoading(false);
                viewer.index--;
                viewer.next();
                return;
            }
            viewer.show();
        }
    }


    function closePhoto() {
        var win = this.win;
        if (win == undefined) {
            win = window;
        }
        var doc = win.document;
        var elt = this.photoDiv;
        if (elt != undefined) {
            doc.body.removeChild(elt);
        }
        elt = doc.getElementById(VIEWER_ID_TOOLBAR);
        if (elt != undefined) {
            doc.body.removeChild(elt);
        }
        elt = doc.getElementById(VIEWER_ID_BYLINE);
        if (elt != undefined) {
            doc.body.removeChild(elt);
        }
        elt = doc.getElementById(VIEWER_ID_BACK);
        if (elt != undefined) {
            doc.body.removeChild(elt);
        }
        this.shown = false;
        this.slideShowRunning = false;
        this.slideShowPaused = false;
        try {
            this.showOverlappingElements();
        } catch (e) {
            log.error(e);
        }
        if (this.toolbarAnimator != undefined) {
            this.toolbarAnimator.reset();
        }
        if (this.closeCallback != undefined) {
            this.closeCallback(this.index);
        }
        if (this.contextMenu != undefined) {
            this.contextMenu.hide();
        }
    }


    function nextPhoto(n) {
        if (this.contextMenu != undefined && this.contextMenu.visible) {
            this.contextMenu.hide();
        }
        if (this.isLoading) {
            return;
        }
        if (n == undefined) {
            n = 1;
        }
        var oldIndex = this.index;
        if (this.index + n >= this.photos.length) {
            if (this.loop && n != this.photos.length) {
                this.index = 0;
            } else {
                this.index = this.photos.length - 1;
            }
        } else if (this.index + n < 0) {
            if (n < -1) {
                this.index = 0;
            } else if (this.loop) {
                this.index = this.photos.length - 1;
            } else {
                return;
            }
        } else {
            this.index += n;
        }
        if (this.index == oldIndex) {
            return;
        }
        this.slideShowStop();
        var img = new Image;
        this.photos[this.index].preloadImage = img;
        this.setLoading(true);
        img.onload = onPhotoLoad;
        img.onerror = onPhotoLoad;
        if (this.photos[this.index].src != undefined) {
            img.src = this.photos[this.index].src;
        } else {
            onPhotoLoad();
        }
    }


    function prevPhoto(n) {
        if (this.contextMenu != undefined && this.contextMenu.visible) {
            this.contextMenu.hide();
        }
        if (n == undefined) {
            n = 1;
        }
        this.next(- n);
    }


    function firstPhoto() {
        if (this.contextMenu != undefined && this.contextMenu.visible) {
            this.contextMenu.hide();
        }
        this.prev(this.photos.length);
    }


    function lastPhoto() {
        if (this.contextMenu != undefined && this.contextMenu.visible) {
            this.contextMenu.hide();
        }
        this.next(this.photos.length);
    }


    function startSlideShow() {
        if (this.contextMenu != undefined && this.contextMenu.visible) {
            this.contextMenu.hide();
        }
        getViewer().slideShow(true);
    }

    var slideTimeout;
    var slidePreloadImageLoaded = false;
    var slidePreloadTime = undefined;

    function slideShow(start) {
        if (this.toolbarAnimator != undefined) {
            this.toolbarAnimator.slideshowAction();
        }
        var nextIndex = this.index + 1;
        if (nextIndex >= this.photos.length) {
            if (this.loop) {
                nextIndex = 0;
            } else if (!this.slideShowPaused && !this.slideShowRunning) {
                this.setToolbarImage(P_IMG_ROOT + "/" + TOOLBAR_IMG);
                return;
            }
        }
        var doc = this.win.document;
        var viewer = this;
        var photoElt = this.photoImg;
        if (photoElt == undefined) {
            return;
        }
        var photoDiv = this.photoDiv;
        var fadeElt = FADE_BORDER ? photoDiv : photoElt;
        if (start != undefined && start === true) {
            if (this.slideShowPaused) {
                this.slideShowPaused = false;
                this.setToolbarImage(P_IMG_ROOT + "/" + TOOLBAR_IMG_RUNNING);
                if (this.contextMenu != undefined &&
                    this.contextMenu.visible) {
                    this.contextMenu.hide();
                }
                return;
            } else if (this.slideShowRunning) {
                this.slideShowPaused = true;
                this.setToolbarImage(P_IMG_ROOT + "/" + TOOLBAR_IMG);
                return;
            } else {
                if (this.contextMenu != undefined &&
                    this.contextMenu.visible) {
                    this.contextMenu.hide();
                }
                this.slideShowRunning = true;
                this.slideShowPaused = false;
                this.slideFirstPhoto = true;
                this.setToolbarImage(P_IMG_ROOT + "/" + TOOLBAR_IMG_RUNNING);
            }
            if (this.isLoading || this.index > this.photos.length - 1) {
                return;
            }
        } else if (this.slideShowPaused) {
            window.setTimeout(function () {viewer.slideShow(false);}, 200);
            return;
        } else if (!this.slideShowRunning) {
            this.setToolbarImage(P_IMG_ROOT + "/" + TOOLBAR_IMG);
            return;
        }
        var left = 0;
        if (photoElt.leftOffset != undefined) {
            left = parseFloat(photoElt.leftOffset);
        }
        if (left === 0) {
            if (nextIndex < this.photos.length) {
                slidePreloadImageLoaded = false;
                var slidePreloadImage = new Image;
                this.photos[nextIndex].preloadImage = slidePreloadImage;
                slidePreloadTime = getTimeMillis();
                slidePreloadImage.onload = onSlideLoad;
                slidePreloadImage.onerror = onSlideLoad;
                slidePreloadImage.src = this.photos[nextIndex].src;
            }
        }
        if (left > - SLIDE_OFFSET) {
            left -= MOVE_STEP;
            if (- left <= FADE_STEPS) {
                if (fadeElt.style.opacity != undefined &&
                    parseFloat(fadeElt.style.opacity) < 1) {
                    if (this.fadePhotos &&
                        this.photos[this.index].src != undefined) {
                        setOpacity(fadeElt, - left / FADE_STEPS);
                    }
                }
            } else if (left + SLIDE_OFFSET < FADE_STEPS) {
                if (nextIndex < this.photos.length &&
                    !slidePreloadImageLoaded) {
                    if (slidePreloadTime != undefined &&
                        getTimeMillis() - slidePreloadTime > PRELOAD_TIMEOUT) {
                        slidePreloadImageLoaded = true;
                    }
                    left++;
                    this.setLoading(true);
                } else {
                    if (nextIndex < this.photos.length &&
                        this.fadePhotos &&
                        this.photos[this.index].src != undefined) {
                        setOpacity(fadeElt, (left + SLIDE_OFFSET) / FADE_STEPS);
                    }
                }
            }
            photoElt.leftOffset = left;
            if (this.panPhotos && !this.slideFirstPhoto) {
                photoElt.style.left = left + "px";
            }
        } else {
            if (nextIndex >= this.photos.length) {
                this.slideShowRunning = false;
                this.slideShowPaused = false;
                this.setToolbarImage(P_IMG_ROOT + "/" + TOOLBAR_IMG);
                if (this.toolbarAnimator != undefined) {
                    this.toolbarAnimator.reset();
                }
                if (this.endCallback != undefined) {
                    this.endCallback();
                }
                return;
            }
            this.index = nextIndex;
            this.slideFirstPhoto = false;
            this.show(undefined, (this.panPhotos ? SLIDE_OFFSET : 0), 0);
            fadeElt = FADE_BORDER ? this.photoDiv : this.photoImg;
            if (this.fadePhotos) {
                setOpacity(fadeElt, 0);
            }
            this.photoImg.leftOffset = 0;
            if (this.panPhotos) {
                this.photoImg.style.left = "0px";
            }
        }
        var pause = this.slideDuration / SLIDE_OFFSET;
        if (this.slideFirstPhoto) {
            pause /= 2;
        }
        slideTimeout = window.setTimeout(function () {viewer.slideShow(false);}, pause);
    }


    function onSlideLoad(event) {
        var viewer = getViewer();
        if (viewer != undefined) {
            if (flickrHack(viewer, viewer.index + 1)) {
                var slidePreloadImage = viewer.photos[viewer.index + 1].preloadImage;
                slidePreloadImage.src = viewer.photos[viewer.index + 1].src;
                slidePreloadTime = getTimeMillis();
                return;
            }
            slidePreloadImageLoaded = true;
            viewer.setLoading(false);
        }
    }


    function slideShowStop() {
        this.slideShowRunning = false;
        this.slideShowPaused = false;
        var doc = this.win.document;
        var photoElt = this.photoImg;
        if (photoElt != undefined) {
            if (this.fadePhotos) {
                var fadeElt = FADE_BORDER ? this.photoDiv : photoElt;
                setOpacity(fadeElt, 1);
            }
            photoElt.style.left = "0px";
        }
    }


    function addBackShade(zIndex) {
        var doc = this.win.document;
        if (doc.getElementById(VIEWER_ID_BACK) != undefined) {
            return;
        }
        var photoBack = doc.createElement("div");
        photoBack.id = VIEWER_ID_BACK;
        photoBack.style.top = "0px";
        photoBack.style.left = "0px";
        photoBack.style.bottom = "0px";
        photoBack.style.right = "0px";
        photoBack.style.margin = "0";
        photoBack.style.padding = "0";
        photoBack.style.border = "none";
        photoBack.style.cursor = "pointer";
        if (IE && !(IE7 && STRICT_MODE)) {
            photoBack.style.position = "absolute";
            var docSize = getDocumentSize(this.win);
            photoBack.style.width = (docSize.w - 21) + "px";
            photoBack.style.height = (docSize.h - 4) + "px";
        } else {
            photoBack.style.position = "fixed";
            photoBack.style.width = "100%";
            photoBack.style.height = "100%";
        }
        photoBack.style.zIndex = zIndex - 1;
        photoBack.style.backgroundColor = this.shadeColor;
        if (this.backgroundShade) {
            setOpacity(photoBack, this.shadeOpacity);
        } else {
            setOpacity(photoBack, 0);
        }
        photoBack.onclick = onClickEvent;
        doc.body.appendChild(photoBack);
    }


    /*
    addToolbar - this function adds the toolbar when the player starts

    */


    function addToolbar(availW, zIndex) {
        var doc = this.win.document;
        var i;
        if (doc.getElementById(VIEWER_ID_TOOLBAR) != undefined) {
            return;
        }
        var photoToolbar = doc.createElement("div");
        photoToolbar.id = VIEWER_ID_TOOLBAR;
        setOpacity(photoToolbar, TOOLBAR_OPACITY);
        photoToolbar.style.zIndex = zIndex + 1;
        var imgBack = TOOLBAR_IMG_BACK;
        if (!isHosted()) {
            imgBack += "-nologo";
        }
        if (IE && !IE7) {
            imgBack += "-indexed";
        }
        imgBack += ".png";
        if (!this.overrideToolbarStyles) {
            var bottom = 10;
            if (IE && !(IE7 && STRICT_MODE)) {
                photoToolbar.style.position = "absolute";
                if (IE7 || IE8) {
                    var top = getWindowSize(this.win).h + getScrollPos(this.win).top;
                    photoToolbar.style.top = (top - TOOLBAR_H - 10) + "px";
                } else {
                    photoToolbar.style.bottom = bottom + "px";
                }
            } else {
                photoToolbar.style.position = "fixed";
                photoToolbar.style.bottom = bottom + "px";
            }
            photoToolbar.style.left = (availW - TOOLBAR_W + 10) / 2 + "px";
            photoToolbar.style.width = TOOLBAR_W + "px";
            photoToolbar.style.height = TOOLBAR_H + "px";
            photoToolbar.style.textAlign = "center";
            photoToolbar.style.backgroundImage = "url('" + P_IMG_ROOT + "/" + imgBack + "')";
            photoToolbar.style.backgroundPosition = "50% 0%";
            photoToolbar.style.backgroundRepeat = "no-repeat";
            photoToolbar.style.lineHeight = LINE_HEIGHT;
        }
        var toolbarMask = undefined;
        if (!this.enableEmailLink && TOOLBAR_IMG_MASK != undefined) {
            toolbarMask = doc.createElement("img");
            toolbarMask.style.position = "absolute";
            toolbarMask.style.width = 44;
            toolbarMask.style.height = 44;
            toolbarMask.style.left = "289px";
            toolbarMask.style.top = "0px";
            toolbarMask.src = P_IMG_ROOT + "/" + TOOLBAR_IMG_MASK;
            photoToolbar.appendChild(toolbarMask);
        }
        if (!this.isEnablePhotoLink && TOOLBAR_IMG_MASK != undefined) {
            toolbarMask = doc.createElement("img");
            toolbarMask.style.position = "absolute";
            toolbarMask.style.width = 44;
            toolbarMask.style.height = 44;
            toolbarMask.style.left = "339px";
            toolbarMask.style.top = "0px";
            toolbarMask.src = P_IMG_ROOT + "/" + TOOLBAR_IMG_MASK;
            photoToolbar.appendChild(toolbarMask);
        }
        var imgMap = this.customImageMap;
        if (imgMap === undefined) {
            imgMap = doc.createElement("map");
            var areas = [];
            areas.push(["getViewer().first()", "17", getMessage("photoviewer.toolbar.first")]);
            areas.push(["getViewer().prev()", "68", getMessage("photoviewer.toolbar.prev")]);
            areas.push(["getViewer().slideShow(true)", "122", getMessage("photoviewer.toolbar.slideShow")]);
            areas.push(["getViewer().next()", "175", getMessage("photoviewer.toolbar.next")]);
            areas.push(["getViewer().last()", "227", getMessage("photoviewer.toolbar.last")]);
            if (this.enableEmailLink) {
                areas.push(["getViewer().email()", "300", getMessage("photoviewer.toolbar.email")]);
            }
            if (this.isEnablePhotoLink) {
                areas.push(["getViewer().permalink()", "350", getMessage("photoviewer.toolbar.permalink")]);
            }
            areas.push(["getViewer().close()", "402", getMessage("photoviewer.toolbar.close")]);
            for (i = 0; i < areas.length; i++) {
                var area = doc.createElement("area");
                area.href = "javascript:void(0)";
                area.alt = areas[i][2];
                area.title = area.alt;
                area.shape = "circle";
                area.coords = areas[i][1] + ", 21, 22";
                area.onclick = buildAreaMapClosure(areas[i][0]);
                imgMap.appendChild(area);
            }
        }
        imgMap.name = VIEWER_ID_TOOLBAR_MAP;
        imgMap.id = VIEWER_ID_TOOLBAR_MAP;
        var img = doc.createElement("img");
        img.id = VIEWER_ID_TOOLBAR_IMG;
        img.src = P_IMG_ROOT + "/" + TOOLBAR_IMG;
        img.width = TOOLBAR_IMG_W;
        img.height = TOOLBAR_IMG_H;
        img.style.border = "none";
        img.style.background = "none";
        if (STRICT_MODE) {
            img.style.margin = "4px 0px 0px 0px";
        } else {
            img.style.margin = "4px";
        }
        img.useMap = "#" + VIEWER_ID_TOOLBAR_MAP;
        photoToolbar.appendChild(imgMap);
        photoToolbar.appendChild(img);
        if (isHosted()) {
            var ttLink = doc.createElement("a");
            ttLink.style.position = "absolute";
            ttLink.style.bottom = "0px";
            ttLink.style.right = "0px";
            ttLink.style.width = "25px";
            ttLink.style.height = "25px";
            ttLink.style.background = "none";
            ttLink.alt = "TripTracker.net";
            ttLink.title = ttLink.alt;
            ttLink.cursor = ttLink.alt;
            ttLink.href = TOOLBAR_LINK;
            ttLink.target = "_new";
            ttLink.alt = "TripTracker Slideshow";
            ttLink.title = ttLink.alt;
            photoToolbar.appendChild(ttLink);
        }
        var loadingIcon = doc.createElement("img");
        loadingIcon.id = VIEWER_ID_LOADING;
        loadingIcon.width = 16;
        loadingIcon.height = 16;
        loadingIcon.style.display = "none";
        loadingIcon.style.position = "absolute";
        loadingIcon.style.left = (TOOLBAR_IMG_LOADING_LEFT - 8) + "px";
        loadingIcon.style.top = (TOOLBAR_IMG_LOADING_TOP - 8) + "px";
        loadingIcon.src = P_IMG_ROOT + "/" + TOOLBAR_IMG_LOADING;
        loadingIcon.style.border = "none";
        loadingIcon.style.background = "none";
        photoToolbar.appendChild(loadingIcon);
        photoToolbar.appendChild(doc.createElement("br"));
        var photoTime = doc.createElement("span");
        photoTime.id = VIEWER_ID_TIME;
        if (!this.overrideToolbarStyles) {
            photoTime.position = "relative";
            photoTime.style.color = TOOLBAR_FONT_COLOR;
            photoTime.style.fontFamily = TOOLBAR_FONT_STYLE;
            photoTime.style.fontSize = this.fontSize + "px";
            if (STRICT_MODE) {
                photoTime.style.lineHeight = this.fontSize + "px";
            }
            if (this.font != undefined) {
                photoTime.style.font = this.font;
            }
            photoTime.style.cssFloat = "none";
            photoTime.style.fontSize = "80%";
            photoTime.style.textAlign = "right";
            photoTime.style.padding = "0px 10px";
        }
        photoTime.appendChild(doc.createTextNode(" "));
        photoToolbar.appendChild(photoTime);
        var photoTitle = doc.createElement("span");
        photoTitle.id = VIEWER_ID_TITLE;
        if (!this.overrideToolbarStyles) {
            photoTitle.position = "relative";
            photoTitle.style.color = TOOLBAR_FONT_COLOR;
            photoTitle.style.fontFamily = TOOLBAR_FONT_STYLE;
            photoTitle.style.fontSize = this.fontSize + "px";
            if (STRICT_MODE) {
                photoTitle.style.lineHeight = this.fontSize + "px";
            }
            if (this.font != undefined) {
                photoTitle.style.font = this.font;
            }
            photoTitle.style.cssFloat = "none";
            photoTitle.style.textAlign = "left";
            photoTitle.style.fontSize = "80%";
            photoTitle.style.paddingRight = "20px";
        }
        photoTitle.appendChild(doc.createTextNode(" "));
        photoToolbar.appendChild(photoTitle);
        doc.body.appendChild(photoToolbar);
    }







    function addByLine(zIndex) {
        var doc = this.win.document;
        if (doc.getElementById(VIEWER_ID_BYLINE) != undefined) {
            return;
        }
        var photoByline = doc.createElement("div");
        photoByline.appendChild(doc.createTextNode(""));
        photoByline.style.color = BYLINE_FONT_COLOR;
        photoByline.style.fontFamily = BYLINE_FONT_STYLE;
        photoByline.style.fontSize = this.fontSize + "px";
        if (this.font != undefined) {
            photoByline.style.font = this.font;
        }
        photoByline.id = VIEWER_ID_BYLINE;
        photoByline.style.position = "absolute";
        photoByline.style.right = BYLINE_POSITION_RIGHT + "px";
        if (IE && !(IE7 && STRICT_MODE)) {
            photoByline.style.position = "absolute";
            if (IE7 || IE8) {
                var top = getWindowSize(this.win).h + getScrollPos(this.win).top;
                photoByline.style.top = (top - 30) + "px";
            } else {
                photoByline.style.bottom = BYLINE_POSITION_BOTTOM + "px";
            }
        } else {
            photoByline.style.position = "fixed";
            photoByline.style.bottom = BYLINE_POSITION_BOTTOM + "px";
        }
        photoByline.style.zIndex = zIndex + 1;
        photoByline.appendChild(doc.createTextNode(" "));
        doc.body.appendChild(photoByline);
    }


    function buildAreaMapClosure(func) {
        return function (event) {eval(func);blurElement(event);return false;};
    }


    function blurElement(event) {
        var target = getEventTarget(getEvent(event));
        if (target != undefined) {
            target.blur();
        }
    }


    function setToolbarImage(img) {
        var doc = this.win.document;
        var elt = doc.getElementById(VIEWER_ID_TOOLBAR_IMG);
        if (elt != undefined) {
            elt.src = img;
        }
    }


    function setShowToolbar(doShow) {
        this.showToolbar = doShow;
    }


    function addCaptions() {
        var photo = this.photos[this.index];
        var doc = this.win.document;
        var photoTime = doc.getElementById(VIEWER_ID_TIME);
        var photoTitle = doc.getElementById(VIEWER_ID_TITLE);
        var time = (this.index + 1) + "/" + this.photos.length;
        if (photo.time != undefined) {
            time += " [" + photo.time + "]";
        }
        photoTime.firstChild.nodeValue = time;
        var title = photo.title != undefined ? photo.title : "";
        photoTitle.title = "";
        photoTitle.alt = "";
        if (title.length > TITLE_MAX_LENGTH) {
            photoTitle.title = title;
            photoTitle.alt = title;
            title = title.substring(0, TITLE_MAX_LENGTH) + " ...";
        }
        if (title.indexOf("\n") !== 0) {
            title = title.replace("\n", "<br />");
            photoTitle.innerHTML = title;
        } else {
            photoTitle.nodeValue = title;
        }
    }


    function addBylineCaption() {
        var photo = this.photos[this.index];
        var doc = this.win.document;
        var photoByline = doc.getElementById(VIEWER_ID_BYLINE);
        if (photo.byline != undefined && photo.byline.length > 0) {
            photoByline.firstChild.nodeValue = photo.byline;
        } else {
            photoByline.firstChild.nodeValue = "";
        }
    }


    function setCloseCallback(callback) {
        this.closeCallback = callback;
    }


    function setShowCallback(callback) {
        this.showCallback = callback;
    }


    function setEndCallback(callback) {
        this.endCallback = callback;
    }


    function emailPhoto() {
        var photo = this.photos[this.index];
        var doc = this.win.document;
        var title = photo.title != undefined ? photo.title : getMessage("photoviewer.email.subject.photo");
        var emailAddress = this.emailAddress !== undefined ? this.emailAddress : "";
        var mailtoLink = "mailto:" + emailAddress + "?subject=" + title + "&body=" + getPhotoURL(photo.src);
        doc.location.href = mailtoLink;
    }


    function getPhotoURL(url) {
        var loc = document.location;
        if (/\w+:\/\/.+/.test(url)) {
            return url;
        } else if (url.indexOf("/") === 0) {
            return loc.protocol + "//" + loc.host + url;
        } else {
            var path = loc.pathname;
            var pos = path.lastIndexOf("/");
            if (pos != -1) {
                path = path.substring(0, pos);
            }
            return loc.protocol + "//" + loc.host + path + "/" + url;
        }
    }


    function linkPhoto() {
        var photo = this.photos[this.index];
        window.open(photo.link ? photo.link : photo.src);
    }


    function favoritePhoto() {
        var photo = this.photos[this.index];
        var doc = this.win.document;
        var restURL = REST_URL + "markfeatured?id" + photo.id;
        try {
            var res = getResponse(restURL, false, true);
        } catch (e) {
            return;
        }
    }


    function hideOverlappingElements(node) {
        if (node == undefined) {
            node = this.win.document.body;
            this.hideOverlappingElements(node);
            return;
        }
        if (node.style != undefined && node.style.visibility != "hidden") {
            var nodeName = node.nodeName.toLowerCase();
            if (node.className != undefined &&
                node.className.indexOf("SlideshowDoHide") != -1 ||
                ((IE || FIREFOX) &&
                (nodeName == "select" ||
                nodeName == "object" || nodeName == "embed"))) {
                node.style.visibility = "hidden";
                if (this.hiddenElements == undefined) {
                    this.hiddenElements = [];
                }
                this.hiddenElements.push(node);
            }
        }
        if (node.childNodes != undefined) {
            var i;
            for (i = 0; i < node.childNodes.length; i++) {
                this.hideOverlappingElements(node.childNodes[i]);
            }
        }
    }


    function showOverlappingElements() {
        var i;
        if (this.hiddenElements != undefined) {
            for (i = 0; i < this.hiddenElements.length; i++) {
                this.hiddenElements[i].style.visibility = "visible";
            }
            this.hiddenElements = [];
        }
    }


    function viewerHandleKey(event) {
        if (typeof getViewer == "undefined" || !getViewer) {
            return true;
        }
        var viewer = getViewer();
        if (viewer == undefined || !viewer.shown) {
            return true;
        }
        event = getEvent(event);
        if (event.ctrlKey || event.altKey) {
            return true;
        }
        var keyCode = event.keyCode;
        switch (keyCode) {
          case 37:
          case 38:
            viewer.prev();
            break;
          case 39:
          case 40:
            viewer.next();
            break;
          case 33:
            viewer.prev(10);
            break;
          case 34:
            viewer.next(10);
            break;
          case 36:
            viewer.first();
            break;
          case 35:
            viewer.last();
            break;
          case 32:
          case 13:
            viewer.slideShow(true);
            break;
          case 27:
            viewer.close();
            break;
          default:
            return true;
        }
        preventDefault(event);
        return false;
    }


    function flickrHack(viewer, index) {
        if (viewer.photos[index] != undefined) {
            var preloadPhoto = viewer.photos[index].preloadImage;
            if (preloadPhoto != undefined &&
                preloadPhoto.width == 500 && preloadPhoto.height == 375) {
                var flickrRE = /.+static\.flickr\.com.+_b\.jpg/;
                if (flickrRE.test(preloadPhoto.src)) {
                    viewer.photos[index].src = viewer.photos[index].src.replace(/_b\.jpg/, "_o.jpg");
                    return true;
                }
            }
        }
        return false;
    }


    function findPhotosTT(viewer, node) {
        var i;
        if (node.nodeName.toLowerCase() == "a") {
            var onclick = node.getAttribute("onclick");
            if (onclick == undefined) {
                onclick = node.onclick;
            }
            if (onclick != undefined &&
                (new String(onclick)).indexOf("popupImg") != -1) {
                var popupRE = /.*popupImg\((.+?),(.+?),(.+?)\).*/;
                if (popupRE.test(onclick)) {
                    var url, w, h;
                    if (node.photoUrl != undefined) {
                        url = node.photoUrl;
                        w = node.photoW;
                        h = node.photoH;
                    } else {
                        url = RegExp.$1;
                        if (url.charAt(0) == "'" &&
                            url.charAt(url.length - 1) == "'") {
                            url = url.substring(1, url.length - 1);
                        }
                        w = parseInt(RegExp.$2);
                        h = parseInt(RegExp.$3);
                    }
                    var photo = new PhotoImg(undefined, url, w, h);
                    var found = false;
                    for (i = 0; i < viewer.photos.length; i++) {
                        if (viewer.photos[i].src == photo.src) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        viewer.add(photo);
                    }
                }
            }
        }
        if (node.childNodes != undefined) {
            for (i = 0; i < node.childNodes.length; i++) {
                findPhotosTT(viewer, node.childNodes[i]);
            }
        }
    }

    var defaultViewer = undefined;

    function popupImg(url, w, h, backColor, showToolbar) {
        var i;
        if (defaultViewer == undefined) {
            defaultViewer = new PhotoViewer;
        } else {
            defaultViewer.photos = [];
            defaultViewer.index = 0;
        }
        if (backColor != undefined) {
            defaultViewer.setBackground(backColor, backColor, false);
        }
        if (showToolbar == undefined || showToolbar) {
            findPhotosTT(defaultViewer, window.document.body);
            for (i = 0; i < defaultViewer.photos.length; i++) {
                if (defaultViewer.photos[i].src == url) {
                    defaultViewer.show(i);
                }
            }
        }
        if (defaultViewer.photos === undefined ||
            defaultViewer.photos.length === 0) {
            defaultViewer.setShowToolbar(false);
            defaultViewer.add(new PhotoImg(undefined, url, w, h));
            defaultViewer.show();
        }
        return false;
    }


    function onClickEvent() {
        var v = getViewer();
        if (v.contextMenu != undefined && v.contextMenu.visible) {
            v.contextMenu.hide();
            return;
        }
        if (v.toolbarAnimator != undefined) {
            v.toolbarAnimator.reset();
        }
        if (v.customOnClickEvent != undefined) {
            v.customOnClickEvent();
        } else {
            closeViewer();
        }
    }


    function onContextMenuEvent(e) {
        var v = getViewer();
        var event = getEvent(e);
        if (v.contextMenu == undefined &&
            v.customOnRightclickEvent == undefined) {
            return true;
        }
        event.cancelBubble = true;
        if (v.customOnRightclickEvent != undefined) {
            v.customOnRightclickEvent(e);
        }
        if (v.contextMenu != undefined &&
            (!v.slideShowRunning || v.slideShowPaused)) {
            v.contextMenu.show(getMousePosition(e));
        }
        return false;
    }


    function setupFragmentIdentifierModePhotoViewer(iframeLocation, iframename, viewerJSONArray) {
        var viewer = new PhotoViewer;
        viewer.origRootLocation = document.location.href;
        viewer.origIFrameLocation = iframeLocation;
        viewer.iframename = iframename;
        viewer.setCloseCallback(viewer.setStopFragmentIdentifier);
        for (var i = 0; i < viewerJSONArray.length; i++) {
            viewer.add(viewerJSONArray[i].url, viewerJSONArray[i].title, viewerJSONArray[i].date, viewerJSONArray[i].byline);
        }
        window.frames[viewer.iframename].location = viewer.origIFrameLocation + "#" + viewer.origRootLocation;
        viewer.checkStartFragmentIdentifier();
    }


    function checkStartFragmentIdentifier() {
        var href = document.location.href;
        if (href.indexOf("#startphoto=") == -1) {
            window.setTimeout(checkStartFragmentIdentifier, 500);
        } else {
            var startPhoto = parseInt(href.substring(href.lastIndexOf("=") + 1));
            var viewer = getViewer();
            if (viewer.origRootLocation.indexOf("#") == -1) {
                viewer.origRootLocation += "#";
            }
            if (FIREFOX) {
                window.history.back();
            } else {
                document.location.href = viewer.origRootLocation;
            }
            viewer.show(startPhoto);
        }
    }


    function setStopFragmentIdentifier(index) {
        window.frames[getViewer().iframename].location = this.origIFrameLocation + "#stopphoto=" + index;
        checkStartFragmentIdentifier();
    }


    function setStartFragmentIdentifier(index) {
        var rootWin = getRootWindow();
        if (this.origIFrameLocation == undefined) {
            this.origIFrameLocation = rootWin.location.href.substring(0, rootWin.location.href.indexOf("#"));
        }
        if (this.origRootLocation == undefined) {
            this.origRootLocation = rootWin.location.href.substring(rootWin.location.href.indexOf("#") + 1);
        }
        this.checkStopFragmentIdentifier();
        var frIdentifier = "#startphoto=" + index;
        rootWin.parent.location = this.origRootLocation + frIdentifier;
    }


    function checkStopFragmentIdentifier() {
        var href = getRootWindow().location.href;
        if (href.indexOf("#stopphoto") == -1) {
            window.setTimeout(checkStopFragmentIdentifier, 500);
        } else {
            var viewer = getViewer();
            var index = href.substring(href.lastIndexOf("=") + 1);
            if (viewer.origIFrameLocation.indexOf("#") == -1) {
                viewer.origIFrameLocation += "#";
            }
            if (FIREFOX) {
                window.history.back();
            } else {
                getRootWindow().location.href = viewer.origIFrameLocation;
            }
            viewerCloseCallback(index);
        }
    }


    function ToolbarAnimator(viewer) {
        this.viewer = viewer;
    }

    ToolbarAnimator.prototype.initialize = function () {var _this = this;var backDiv = findDOMElement(VIEWER_ID_BACK);var frontDiv = findDOMElement(VIEWER_ID_PHOTO);var toolbar = findDOMElement(VIEWER_ID_TOOLBAR);if (backDiv != undefined && frontDiv != undefined && toolbar != undefined) {var func = function () {_this.mouseAction();};backDiv.onmousemove = func;frontDiv.onmousemove = func;toolbar.onmousemove = func;toolbar.onclick = func;this.initialized = true;}};
    ToolbarAnimator.prototype.reset = function () {this.stop();var backDiv = findDOMElement(VIEWER_ID_BACK);var frontDiv = findDOMElement(VIEWER_ID_PHOTO);var toolbar = findDOMElement(VIEWER_ID_TOOLBAR);if (backDiv != undefined && frontDiv != undefined && toolbar != undefined) {backDiv.onmousemove = null;frontDiv.onmousemove = null;toolbar.onmousemove = null;toolbar.onclick = null;}this.initialized = false;};
    ToolbarAnimator.prototype.stop = function () {var _this = this;if (this.hiderID != undefined) {window.clearTimeout(this.hiderID);this.hiderID = undefined;}if (this.hidden) {this.showToolbar();}};
    ToolbarAnimator.prototype.mouseAction = function () {this.stop();};
    ToolbarAnimator.prototype.slideshowAction = function () {var _this = this;if (this.viewer.slideShowRunning && !this.viewer.slideShowPaused && this.hiderID == undefined) {if (!this.initialized) {this.initialize();}this.hiderID = window.setTimeout(function () {_this.hideToolbar();}, 5000);} else if (this.viewer.slideShowPaused) {this.reset();}};
    ToolbarAnimator.prototype.hideToolbar = function () {var _this = this;var toolbar = findDOMElement(VIEWER_ID_TOOLBAR);if (toolbar == undefined) {return;}var opacity = toolbar.style.KhtmlOpacity;if (opacity == undefined) {opacity = toolbar.style.opacity;}if (opacity === 0) {toolbar.style.display = "none";return;}opacity = opacity - 0.05;setOpacity(toolbar, opacity > 0 ? opacity : 0);this.hidden = true;this.hiderID = window.setTimeout(function () {_this.hideToolbar();}, 100);};
    ToolbarAnimator.prototype.showToolbar = function () {var toolbar = findDOMElement(VIEWER_ID_TOOLBAR);if (toolbar != undefined) {toolbar.style.display = "block";setOpacity(toolbar, TOOLBAR_OPACITY);}this.hidden = false;};



    function addContextMenu(contextMenu) {
        if (isHosted() || getViewer().contextMenu != undefined) {
            return;
        }
        this.contextMenu = contextMenu;
        this.contextMenu.initialize();
    }


    function PhotoViewerCtxMenuItem(text, callback) {
        this.text = text;
        this.callback = callback;
    }


    function PhotoViewerCtxMenu(cssClass) {
        this.cssClass = cssClass;
        this.items = [];
        this.ctxSubMenus = [];
    }

    PhotoViewerCtxMenu.prototype.mouseover = function (e) {var viewer = getViewer();var ctxMenu = viewer.contextMenu;if (!ctxMenu.visible) {return;}for (var i = 0; i < ctxMenu.ctxSubMenus.length; i++) {ctxMenu.ctxSubMenus[i].style.visibility = "hidden";}var subMenuId = this.id + "_sub";var subMenu = document.getElementById(subMenuId);var menuDiv = this.parentNode.parentNode;var mouseLoc = getMousePosition(e);var itemLoc = getDOMLocation(this);var menuLoc = getDOMLocation(menuDiv);if (subMenu && menuDiv) {subMenu.style.left = (menuLoc.x + menuDiv.clientWidth) + "px";subMenu.style.top = itemLoc.y + "px";subMenu.style.visibility = "visible";}};
    PhotoViewerCtxMenu.prototype.mouseclick = function (e) {var viewer = getViewer();var menu = viewer.contextMenu;var menuItem = undefined;for (var i = 0; i < menu.items.length; i++) {if (menu.items[i].DOMElement == this) {menuItem = menu.items[i];break;}var itemFound = false;if (menu.items[i].subitems == undefined) {continue;}for (var j = 0; j < menu.items[i].subitems.length; j++) {if (menu.items[i].subitems[j].DOMElement.id === this.id) {menuItem = menu.items[i].subitems[j];itemFound = true;break;}}if (itemFound) {break;}}if (menuItem != undefined && menuItem.callback != undefined) {viewer.contextMenu.hide();menuItem.callback(viewer.photos[viewer.index].src, e);}};
    PhotoViewerCtxMenu.prototype.add = function (item, subitems) {item.subitems = subitems;this.items.push(item);};
    PhotoViewerCtxMenu.prototype.initialize = function () {var viewer = getViewer();var doc = viewer.win.document;this.createMenu(doc, viewer);this.initialized = true;};
    PhotoViewerCtxMenu.prototype.createMenu = function (doc, viewer) {var ctxMenuDiv = doc.createElement("div");ctxMenuDiv.id = VIEWER_ID_CTXMENU;ctxMenuDiv.style.visibility = "hidden";ctxMenuDiv.style.position = "absolute";ctxMenuDiv.style.zIndex = 999999;var ctxMenu = doc.createElement("ul");for (var i = 0; i < this.items.length; i++) {var ctxMenuItem = doc.createElement("li");ctxMenuItem.appendChild(doc.createTextNode(this.items[i].text));ctxMenuItem.onclick = this.mouseclick;ctxMenuItem.id = VIEWER_ID_CTXMENU + "_" + i;ctxMenuItem.onmouseover = this.mouseover;this.items[i].DOMElement = ctxMenuItem;ctxMenu.appendChild(ctxMenuItem);if (this.items[i].subitems != undefined) {ctxMenuItem.className = "ctxmenu_expanded";var submenuid = ctxMenuItem.id + "_sub";this.createSubMenu(doc, viewer, this.items[i].subitems, submenuid);}}ctxMenuDiv.appendChild(ctxMenu);ctxMenuDiv.className = this.cssClass;doc.body.appendChild(ctxMenuDiv);this.ctxMenuDOM = ctxMenuDiv;};
    PhotoViewerCtxMenu.prototype.createSubMenu = function (doc, viewer, subitems, id) {var ctxSubMenuDiv = doc.createElement("div");ctxSubMenuDiv.id = id;ctxSubMenuDiv.style.visibility = "hidden";ctxSubMenuDiv.style.position = "absolute";ctxSubMenuDiv.style.zIndex = 999999;var ctxSubMenu = doc.createElement("ul");for (var i = 0; i < subitems.length; i++) {var ctxSubMenuItem = doc.createElement("li");ctxSubMenuItem.id = id + "_" + i;ctxSubMenuItem.appendChild(doc.createTextNode(subitems[i].text));ctxSubMenuItem.onclick = this.mouseclick;subitems[i].DOMElement = ctxSubMenuItem;ctxSubMenu.appendChild(ctxSubMenuItem);}ctxSubMenuDiv.appendChild(ctxSubMenu);ctxSubMenuDiv.className = this.cssClass;doc.body.appendChild(ctxSubMenuDiv);this.ctxSubMenus.push(ctxSubMenuDiv);};
    PhotoViewerCtxMenu.prototype.show = function (loc) {if (!this.initialized) {this.initialize();}for (var i = 0; i < this.ctxSubMenus.length; i++) {this.ctxSubMenus[i].style.visibility = "hidden";}this.ctxMenuDOM.style.left = loc.x + "px";this.ctxMenuDOM.style.top = loc.y + "px";this.ctxMenuDOM.style.visibility = "visible";this.visible = true;};
    PhotoViewerCtxMenu.prototype.hide = function () {this.ctxMenuDOM.style.visibility = "hidden";for (var i = 0; i < this.ctxSubMenus.length; i++) {this.ctxSubMenus[i].style.visibility = "hidden";}this.visible = false;};
    
    
    
    
    


