﻿(function ($) {

    var EPUB_GLOBAL_SETTINGS_ID = "#epub_settings_id";
    var EPUB_GLOBAL_SETTINGS = "epub_settings";

    var EPUB_NAV_HEIGHT = 64;
    var EPUB_BUTTON_WIDTH = 100;
    var EPUB_MINIBUTTON_WIDTH = 70;
    var EPUB_BUTTON_GAP = 3;
    var EPUB_NAV_GUTTER = 100;

    var EPUB_STRIP_GUTTER = 40;
    var EPUB_STRIP_TILE_WIDTH = 150;
    var EPUB_STRIP_TILE_GUTTER = 15;
    var EPUB_STRIP_SLOW_STEP = 10;
    var EPUB_STRIP_FAST_STEP = 25;
    var EPUB_STRIP_INTERVAL = 15;

    var EPUB_STRIP_TOC_JUMP = EPUB_STRIP_TILE_WIDTH + EPUB_STRIP_TILE_GUTTER;

    var EPUB_EDITION_TILE_WIDTH = 600;
    var EPUB_EDITION_TILE_GUTTER = 15;
    var EPUB_STRIP_SHELF_JUMP = EPUB_EDITION_TILE_WIDTH + EPUB_EDITION_TILE_GUTTER;

    var EPUB_ICAPTION_WIDTH_ASPECT = .75;
    var EPUB_ICAPTION_RIGHT = 2100;
    var EPUB_ICAPTION_BOTTOM = 1300;

    var EPUB_IMAGE_WIDTH = 2300;
    var EPUB_IMAGE_HEIGHT = 1380;
    var EPUB_IMAGE_PATH_STEP = "2300";

    var EPUB_IMAGE_WIDTH_STEP1 = 1920;
    var EPUB_IMAGE_HEIGHT_STEP1 = 1152;
    var EPUB_IMAGE_PATH_STEP1 = "1920";

    var EPUB_IMAGE_WIDTH_STEP2 = 1280;
    var EPUB_IMAGE_HEIGHT_STEP2 = 768;
    var EPUB_IMAGE_PATH_STEP2 = "1280";

    var EPUB_IMAGE_WIDTH_STEP3 = 1024;
    var EPUB_IMAGE_HEIGHT_STEP3 = 614;
    var EPUB_IMAGE_PATH_STEP3 = "1024";

    var EPUB_IMAGE_WIDTH_STEP4 = 960;
    var EPUB_IMAGE_HEIGHT_STEP4 = 576;
    var EPUB_IMAGE_PATH_STEP4 = "960";

    var EPUB_IMAGE_WIDTH_STEP5 = 480;
    var EPUB_IMAGE_HEIGHT_STEP5 = 288;
    var EPUB_IMAGE_PATH_STEP5 = "480";

    var EPUB_IMAGE_ASPECT = EPUB_IMAGE_HEIGHT / EPUB_IMAGE_WIDTH;

    var EPUB_FADE_RATE = 2000;
    var EPUB_SHOW_INTERVAL = 4000;
    var EPUB_SPIN_WAIT = 2500;

    var EPUB_FLIP_ANIMATION_SPEED = 30;
    var EPUB_FLIP_ANIMATION_DYNAMIC = 160;
    var EPUB_FLIP_CORNER_SIZE = 50;

    var is_mobile = false;
    var epub_edition;
    var opf_file;
    var oebps_folder;
    var epub_folder;
    var epub_shelf;
    var epub_toc;
    var epub_editions;
    var epub_show;

    var _strip_tid;
    var _show_tid;
    var _spin_tid;

    var _start_section = "";
    var _start_page = "";
    var _cache_list;

    var _current_chapter;
    var _splash_shown = false;
    var _analytics = false;

    var contentX;
    var contentY;
    var ctx = new Object();

    var iScale;
    var iWidth;
    var iHeight;
    var innerMx;
    var innerMy;
    var outerMx;
    var outerMy;
    var outerRadius;

    var mouseAbsX;
    var mouseAbsY;
    var mouseRelCenterX = 0;
    var mouseRelCenterY = 0;

    var is_mouseDown = false;
    var degHelp = Math.PI / 180;

    var CX;
    var CY;
    var MCX = 0;
    var MCY = 0;

    var r2x = 0;
    var r2y = 0;

    var T1C = 0;
    var T1X = 0;
    var T1Y = 0;
    var T2X = 0;
    var T2Y = 0;

    var T1YRel = 0;
    var T2CX = 0;
    var T2CY = 0;

    var angleClip = 0;
    var angleImage = 0;

    var actPage = 0;
    var takePage;
    var dropPage;

    var interval;
    var dynamicHelp = 0;
    var isMouseInCorner = false;

    var imageCount = 0;
    var angleCXMCY = 0;
    var angleT1XT1Y = 0;

    var flipper_chillout = false;

    var flipDynamice = EPUB_FLIP_ANIMATION_DYNAMIC;
    var imgFlipFrontRight = new Image();
    var imgFlipBackRight = new Image();
    var imgFlipFrontLeft = new Image();
    var imgFlipBackLeft = new Image();

    $.epub = {
        defaultSettings: {
            bookshelf: 'bookshelf',
            edition: 'cmjan2012',
            section: '',
            page: 0
        },

        methods: {
            init: function (options) {
                var settings = $.extend({}, $.epub.defaultSettings, options);
                $("body").append("<div id='epub_settings'></div>");
                $(EPUB_GLOBAL_SETTINGS_ID).data(EPUB_GLOBAL_SETTINGS, settings);

                epub_edition = settings.edition;
                epub_shelf = settings.bookshelf;
                epub_folder = settings.bookshelf + "/" + settings.edition;
                _analytics = settings.analytics;

                _start_section = settings.section;
                _start_page = settings.page;

                setup();
                setup_events();
            },

            next_page: function () {
                flip_page_forward();
            },

            previous_page: function () {
                flip_page_back()
            },

            goto_chapter: function (chapter) {
                goto_chapter(chapter);
            },

            goto_page: function (page) {
                var $this = this;
                var settings = $(EPUB_GLOBAL_SETTINGS_ID).data(EPUB_GLOBAL_SETTINGS);
            }
        }
    };

    function debug(text) {
        var content = $("#epub_debug").html();
        $("#epub_debug").html("DBG: " + text + "<br />" + content);
    }

    function setup() {

        var html =
            "<img id='epub_spinner' style='display:none' src='scripts/plugins/epub/images/spinner.gif' alt='' width='300' height='150' />" +
            "<div id='epub_splash'>" +
            "   <img id='epub_splash_title' style='display:none' src='scripts/plugins/epub/images/cmtitle.jpg' alt='' width='1495' height='406' />" +
            "   <img id='epub_splash_catch' style='display:none' src='scripts/plugins/epub/images/cmcatch.jpg' alt='' width='958' height='130' />" +
            "</div>";

        $("body").append(html);

        html =
            "<div id='epub'>" +
            "   <div id='epub_content'>" +
            "   </div>" +
            "   <div id='epub_navigation' style='display:none'>" +
            "      <div id='epub_navbtn_prev' class='epub_button epub_nav_button_float'><img id='epub_navimg_prev' src='scripts/plugins/epub/images/prev.png' alt='Previous' /></div >" +
            "      <div id='epub_navbtn_center' class='epub_nav_button_float'>" +
            "         <img id='epub_navimg_contents' class='epub_button' src='scripts/plugins/epub/images/contents.png' alt='Contents' />" +
            "         <img id='epub_navimg_main' class='epub_button' src='scripts/plugins/epub/images/main.png' alt='Contents' />" +
            "         <img id='epub_navimg_shelf' class='epub_button' src='scripts/plugins/epub/images/editions.png' alt='Bookshelf' />" +
            "      </div >" +
            "      <div id='epub_navbtn_next' class='epub_button epub_nav_button_float'><img id='epub_navimg_next' src='scripts/plugins/epub/images/next.png' alt='Next' /></div>" +
            "      </div>" +
            "   </div>" +
            "   <div id='epub_current_chapter_content' style='display:none'></div>" +
            "   <div id='epub_main_popup' class='epub_popup' style='display:none'>" +
            "       <div id='epub_main_container' class='epub_popup_content'>" +
            "		   <div id='epub_main_subscribe' style='padding-bottom:20px;'><b>Subscribe Now</b></div>" +
            "		   <div id='epub_main_cover'>Cover</div>" +
            "          <div id='epub_main_contents'>Table of Contents</div>" +
            "          <div id='epub_main_theater'>Todd Moen Video Theater</div>" +
            "          <div id='epub_main_slide'>Brian O'Keefe Slide Show</div>" +
            "          <div id='epub_main_elite'>Elite Advertisers</div>" +
            "       </div>" +
            "       <div class='epub_popup_anchor'></div>" +
            "   </div>" +
            "   <div id='epub_contents_popup' class='epub_popup' style='display:none'>" +
            "       <div id='epub_contents_container' class='epub_popup_content'>" +
            "          <div id='epub_toc_slider' class='epub_slider'>" +
            "             <div id='epub_toc_thumbs' class='epub_tray'></div>" +
            "             <div id='epub_toc_slider_left' class='epub_slider_left'><img src='scripts/plugins/epub/images/strip-left.png' alt='' /></div>" +
            "             <div id='epub_toc_slider_right' class='epub_slider_right'><img src='scripts/plugins/epub/images/strip-right.png' alt='' /></div>" +
            "          </div>" +
            "       </div>" +
            "       <div class='epub_popup_anchor'></div>" +
            "   </div>" +
            "   <div id='epub_shelf_popup' class='epub_popup' style='display:none'>" +
            "       <div id='epub_shelf_container' class='epub_popup_content'>" +
            "          <div id='epub_shelf_slider' class='epub_slider'>" +
            "             <div id='epub_shelf_thumbs' class='epub_tray'></div>" +
            "             <div id='epub_shelf_slider_left'class='epub_slider_left'><img src='scripts/plugins/epub/images/strip-left.png' alt='' /></div>" +
            "             <div id='epub_shelf_slider_right' class='epub_slider_right'><img src='scripts/plugins/epub/images/strip-right.png' alt='' /></div>" +
            "          </div>" +
            "       </div>" +
            "       <div class='epub_popup_anchor'></div>" +
            "   </div>" +
            "   <div id='epub_fader'></div>" +
            "   <div id='epub_flipper' style='display:none'>" +
            "      <div id='epub_page_background_left' class='epub_page_flip_background5'><img /></div>" +
            "      <div id='epub_page_background_right' class='epub_page_flip_background5'><img /></div>" +
            "      <div id='epub_canvas_container'>" +
            "         <canvas id='epub_canvas_page_flip' />" +
            "      </div>" +
            "   </div>" +
            "</div>";

        html += "<div id='epub_below_the_fold'></div>";

        html += "<div id='epub_debug' style='display:none; padding:5px; border-radius:8px;clear:both;z-index:20000;position:fixed; " +
            "left:0px;top:0px;color:red;background-color:white;overflow:auto;width:450px;height:300px;font-size:.7em'></div";

        $("body").append(html);

        browser_sniff();
        load_ebook();
    }

    function setup_events() {
        $("#epub_navimg_prev").click(function () {
            $("#epub_contents_popup").fadeOut();
            $("#epub_main_popup").fadeOut();
            $("#epub_shelf_popup").fadeOut();

            flip_page_back();
        });

        $("#epub_navimg_prev").mouseup(function () {
            $("#epub_navimg_prev").attr("src", "scripts/plugins/epub/images/prev.png");
        });

        $("#epub_navimg_prev").mousedown(function () {
            $("#epub_navimg_prev").attr("src", "scripts/plugins/epub/images/prev-down.png");
        });

        var showing_contents = false;
        $("#epub_navimg_contents").click(function () {
            $("#epub_main_popup").fadeOut();
            $("#epub_shelf_popup").fadeOut
            showing_main = false;
            showing_shelf = false;

            if (showing_contents) $("#epub_contents_popup").fadeOut();
            else $("#epub_contents_popup").fadeIn();

            showing_contents = !showing_contents;
        });

        $("#epub_navimg_contents").mouseenter(function () {
            $("#epub_main_popup").fadeOut();
            $("#epub_shelf_popup").fadeOut();
            showing_main = false;
            showing_shelf = false;

            if (showing_contents) $("#epub_contents_popup").fadeOut();
            else $("#epub_contents_popup").fadeIn();

            showing_contents = !showing_contents;
        });

        $("#epub_contents_popup").mouseleave(function () {
            $("#epub_contents_popup").fadeOut();
            showing_contents = false;
        });

        $("#epub_navimg_contents").mouseup(function () {
            $("#epub_navimg_contents").attr("src", "scripts/plugins/epub/images/contents.png");
        });

        $("#epub_navimg_contents").mousedown(function () {
            $("#epub_navimg_contents").attr("src", "scripts/plugins/epub/images/contents-down.png");
        });

        var showing_main = false;
        $("#epub_navimg_main").click(function () {
            $("#epub_contents_popup").fadeOut();
            $("#epub_shelf_popup").fadeOut();
            showing_contents = false;
            showing_shelf = false;

            if (showing_main) $("#epub_main_popup").fadeOut();
            else $("#epub_main_popup").fadeIn();

            showing_main = !showing_main;
        });

        $("#epub_navimg_main").mouseenter(function () {
            $("#epub_contents_popup").fadeOut();
            $("#epub_shelf_popup").fadeOut();
            showing_contents = false;
            showing_shelf = false;

            if (showing_main) $("#epub_main_popup").fadeOut();
            else $("#epub_main_popup").fadeIn();

            showing_main = !showing_main;
        });

        $("#epub_main_popup").mouseleave(function () {
            $("#epub_main_popup").fadeOut();
            showing_main = false;
        });

        $("#epub_navimg_main").mouseup(function () {
            $("#epub_navimg_main").attr("src", "scripts/plugins/epub/images/main.png");
        });

        $("#epub_navimg_main").mousedown(function () {
            $("#epub_navimg_main").attr("src", "scripts/plugins/epub/images/main-down.png");
        });

        var showing_shelf = false;
        $("#epub_navimg_shelf").click(function () {
            $("#epub_contents_popup").fadeOut();
            $("#epub_main_popup").fadeOut();
            showing_contents = false;
            showing_main = false;

            if (showing_shelf) $("#epub_shelf_popup").fadeOut();
            else $("#epub_shelf_popup").fadeIn();

            showing_shelf = !showing_shelf;
        });

        $("#epub_navimg_shelf").mouseenter(function () {
            $("#epub_contents_popup").fadeOut();
            $("#epub_main_popup").fadeOut();
            showing_contents = false;
            showing_main = false;

            if (showing_shelf) $("#epub_shelf_popup").fadeOut();
            else $("#epub_shelf_popup").fadeIn();

            showing_shelf = !showing_shelf;
        });

        $("#epub_shelf_popup").mouseleave(function () {
            $("#epub_shelf_popup").fadeOut();
            showing_shelf = false;
        });

        $("#epub_navimg_shelf").mouseup(function () {
            $("#epub_navimg_shelf").attr("src", "scripts/plugins/epub/images/editions.png");
        });

        $("#epub_navimg_shelf").mousedown(function () {
            $("#epub_navimg_shelf").attr("src", "scripts/plugins/epub/images/editions-down.png");
        });

        $("#epub_navimg_next").click(function () {
            $("#epub_contents_popup").fadeOut();
            $("#epub_main_popup").fadeOut();
            $("#epub_shelf_popup").fadeOut();

            flip_page_forward();
        });

        $("#epub_navimg_next").mouseup(function () {
            $("#epub_navimg_next").attr("src", "scripts/plugins/epub/images/next.png");
        });

        $("#epub_navimg_next").mousedown(function () {
            $("#epub_navimg_next").attr("src", "scripts/plugins/epub/images/next-down.png");
        });

        $(window).resize(function () {
            on_resize();
        });


        if (is_mobile) {
            $("#epub_toc_slider_left").click(function () {
                var $tray = $(this).parent().find(".epub_tray");
                slide_strip($tray, EPUB_STRIP_SLOW_STEP, Math.floor(EPUB_STRIP_TOC_JUMP / EPUB_STRIP_SLOW_STEP));
            });

            $("#epub_toc_slider_right").click(function () {
                var $tray = $(this).parent().find(".epub_tray");
                slide_strip($tray, -1 * EPUB_STRIP_SLOW_STEP, Math.floor(EPUB_STRIP_TOC_JUMP / EPUB_STRIP_SLOW_STEP));
            });
        }

        $("#epub_shelf_slider_left").click(function () {
            var $tray = $(this).parent().find(".epub_tray");
            slide_strip($tray, EPUB_STRIP_FAST_STEP, Math.floor(EPUB_STRIP_SHELF_JUMP / EPUB_STRIP_FAST_STEP));
        });

        $("#epub_shelf_slider_right").click(function () {
            var $tray = $(this).parent().find(".epub_tray");
            slide_strip($tray, -1 * EPUB_STRIP_FAST_STEP, Math.floor(EPUB_STRIP_SHELF_JUMP / EPUB_STRIP_FAST_STEP));
        });

        if (!is_mobile) {
            $(".epub_slider_left").mousedown(function () {
                var $tray = $(this).parent().find(".epub_tray");
                slide_strip($tray, EPUB_STRIP_SLOW_STEP, -1);
            });

            $(".epub_slider_left").mouseup(function () {
                slide_stop();
            });

            $(".epub_slider_left").mouseleave(function () {
                slide_stop();
            });

            $(".epub_slider_right").mousedown(function () {
                var $tray = $(this).parent().find(".epub_tray");
                slide_strip($tray, -1 * EPUB_STRIP_SLOW_STEP, -1);
            });

            $(".epub_slider_right").mouseup(function () {
                slide_stop();
            });

            $(".epub_slider_right").mouseleave(function () {
                slide_stop();
            });
        }

        $("#epub_main_subscribe").click(function () {
            $("#epub_main_popup").fadeOut();
            on_hyperlink_click("http://www.catchmagazine.net/signup.html", "_blank");
        }).css("cursor", "pointer");

        $("#epub_main_cover").click(function () {
            goto_chapter('cover');
            $("#epub_main_popup").fadeOut();
        }).css("cursor", "pointer");

        $("#epub_main_contents").click(function () {
            goto_chapter('contents');
            $("#epub_main_popup").fadeOut();
        }).css("cursor", "pointer");

        $("#epub_main_theater").click(function () {
            goto_chapter('theater');
            $("#epub_main_popup").fadeOut();
        }).css("cursor", "pointer");

        $("#epub_main_slide").click(function () {
            goto_chapter('slide');
            $("#epub_main_popup").fadeOut();
        }).css("cursor", "pointer");

        $("#epub_main_elite").click(function () {
            goto_chapter('elite');
            $("#epub_main_popup").fadeOut();
        }).css("cursor", "pointer");

        var KEY_CODES = {
            37: 'left',
            39: 'right',
            68: "D"
        }

        var key_status = { keyDown: false };
        for (code in KEY_CODES) { key_status[KEY_CODES[code]] = false; }

        $(window).keydown(function (e) {
            key_status.keyDown = true;

            if (KEY_CODES[e.keyCode]) {
                e.preventDefault();
                if (e.keyCode == 39 && !flipper_chillout) flip_page_forward();
                else if (e.keyCode == 37 && !flipper_chillout) flip_page_back();
                else if (e.ctrlKey && e.altKey && e.keyCode == 68) $("#epub_debug").toggle();
            }
        }).keyup(function (e) {
            key_status.keyDown = false;
            if (KEY_CODES[e.keyCode]) {
                e.preventDefault();
                key_status[KEY_CODES[e.keyCode]] = false;
            }
        });
    }

    function browser_sniff() {
        debug("agent: " + navigator.userAgent);
        if (navigator.userAgent.match(/Android/i) ||
             navigator.userAgent.match(/webOS/i) ||
             navigator.userAgent.match(/iPhone/i) ||
             navigator.userAgent.match(/iPod/i) ||
             navigator.userAgent.match(/iPad/i) ||
             navigator.userAgent.match(/Silk/i) ||
             navigator.userAgent.match(/Mobile/i) ||
             navigator.userAgent.match(/BlackBerry/)) {
            debug("is_mobile: true");
            is_mobile = true;
        }

        var versions = jQuery.browser.version.split('.');
        var maj_version = parseInt(versions[0]);
        var min_version = parseInt(versions[1]);

        if (jQuery.browser.mozilla && maj_version < 6) {
            on_hyperlink_click("browser.html", "_self");
        }

        else if (jQuery.browser.msie && maj_version < 9) {
            on_hyperlink_click("browser.html", "_self");
        }

        else if (jQuery.browser.webkit && maj_version < 533) {
            on_hyperlink_click("w.html", "_self");
        }

        else if (jQuery.browser.opera && maj_version < 11) {
            on_hyperlink_click("browser.html", "_self");
        }
    }

    function slide_strip($tray, step, count) {
        if (_strip_tid != null) slide_stop();
        slide_strip_step($tray, step, count);
    }

    function slide_strip_step($tray, step, count) {
        if (count == 0) {
            slide_stop();
            return;
        }

        var left = $tray.css("left");
        left = left.substring(0, left.length - 2);
        var offset = parseInt(left) + step;

        var boundary = $tray.width() - $tray.parent().width();
        $tray.css("left", offset);

        if (step > 0 && offset >= 0) {
            $tray.parent().find(".epub_slider_left").hide();
            slide_stop();
            return;
        }
        else $tray.parent().find(".epub_slider_right").show();

        if (step < 0 && offset * -1 >= boundary) {
            $tray.parent().find(".epub_slider_right").hide();
            slide_stop();
            return;
        }
        else $tray.parent().find(".epub_slider_left").show();

        _strip_tid = setTimeout(function () {
            if (count != -1) count--;
            slide_strip_step($tray, step, count);
        }, EPUB_STRIP_INTERVAL);
    }

    function slide_stop() {
        if (_strip_tid != null) clearTimeout(_strip_tid);
        _strip_tid = null;
    }

    function on_resize() {
        var window_width = $(window).width();
        var window_height = $(window).height() - EPUB_NAV_HEIGHT;

        scale_locate_mag($("#mag_background"), window_width, window_height)

        var mag_width = $("#mag_background").width();
        var mag_height = $("#mag_background").height();

        adjust_object_to_window($("#epub_spinner"));
        adjust_object_to_window($("#epub_splash_title"));
        adjust_object_to_window($("#epub_splash_catch"));

        relocate_navigation(window_width, window_height, mag_width, mag_height);
        relocate_main_popup(window_width, window_height, mag_width, mag_height);
        relocate_contents_popup(window_width, window_height, mag_width, mag_height);
        relocate_shelf_popup(window_width, window_height, mag_width, mag_height);
        relocate_icaption(window_width, window_height, mag_width, mag_height);
        relocate_hyperlinks(window_width, window_height, mag_width, mag_height);
        relocate_slideshow(window_width, window_height, mag_width, mag_height);
        relocate_theater(window_width, window_height, mag_width, mag_height);

        _flip_on_resize(window_width, window_height, mag_width, mag_height);
    }

    function scale_locate_mag($object, window_width, window_height) {
        if ((window_height / window_width) > EPUB_IMAGE_ASPECT) {
            //resize width
            $object.width(window_width).height(window_width * EPUB_IMAGE_ASPECT);
        }
        else {
            //resize height
            $object.height(window_height).width(window_height / EPUB_IMAGE_ASPECT);
        }

        var width = $object.width();
        var height = $object.height();
        var left = (window_width - width) / 2;
        var top = (window_height - height) / 2;

        $object.css('left', left);
        $object.css('top', top);

        if (_current_chapter != null) {
            var pre = _current_chapter.url.substr(0, _current_chapter.url.lastIndexOf('/'));
            fixup_background($object, pre, width);
        }
    }

    function relocate_navigation(window_width, window_height, mag_width, mag_height) {
        var center_btn_width = 3 * EPUB_MINIBUTTON_WIDTH;
        var center_width = mag_width - EPUB_NAV_GUTTER - ((2 * EPUB_BUTTON_WIDTH) + 2 * EPUB_BUTTON_GAP);
        var center_padding = (center_width - center_btn_width) / 2;

        $("#epub_navbtn_center").width(center_width - center_padding);
        $("#epub_navbtn_center").css("padding-left", center_padding);

        $("#epub_navigation").css('left', (window_width - mag_width) / 2);
        $("#epub_navigation").css('top', (window_height - mag_height) / 2 + mag_height);
    }

    function relocate_main_popup(window_width, window_height, mag_width, mag_height) {
        var width = $("#epub_main_popup").outerWidth(true);
        var height = $("#epub_main_popup").outerHeight(true);

        var left = (window_width - width) / 2;
        var top = ((window_height - mag_height) / 2 + mag_height) - height;

        $("#epub_main_popup").css('left', left);
        $("#epub_main_popup").css('top', top);

        var $anchor = $("#epub_main_popup").children(".epub_popup_anchor");
        var anchor_left = (width - $anchor.width()) / 2;
        $anchor.css('left', anchor_left);
    }

    function relocate_shelf_popup(window_width, window_height, mag_width, mag_height) {
        var width = mag_width - EPUB_STRIP_GUTTER;
        var height = $("#epub_shelf_popup").outerHeight(true);

        var left = (window_width - width) / 2;
        var top = ((window_height - mag_height) / 2 + mag_height) - height;

        $("#epub_shelf_popup").width(width);
        $("#epub_shelf_popup").css('left', left);
        $("#epub_shelf_popup").css('top', top);

        var $anchor = $("#epub_shelf_popup").children(".epub_popup_anchor");
        var anchor_left = (width - $anchor.width()) / 2 + EPUB_MINIBUTTON_WIDTH + EPUB_BUTTON_GAP;
        $anchor.css('left', anchor_left);
    }

    function relocate_contents_popup(window_width, window_height, mag_width, mag_height) {
        var width = mag_width - EPUB_STRIP_GUTTER;
        var height = $("#epub_contents_popup").outerHeight(true);

        var left = (window_width - width) / 2;
        var top = ((window_height - mag_height) / 2 + mag_height) - height;

        $("#epub_contents_popup").width(width);
        $("#epub_contents_popup").css('left', left);
        $("#epub_contents_popup").css('top', top);

        var $anchor = $("#epub_contents_popup").children(".epub_popup_anchor");
        var anchor_left = (width - $anchor.width()) / 2 - EPUB_MINIBUTTON_WIDTH + EPUB_BUTTON_GAP;
        $anchor.css('left', anchor_left);
    }

    function relocate_icaption(window_width, window_height, mag_width, mag_height) {
        $("#epub_content").find(".mag_caption").find("img").show();

        //scale coordinates
        var right = (EPUB_ICAPTION_RIGHT * mag_width) / EPUB_IMAGE_WIDTH;
        var bottom = (EPUB_ICAPTION_BOTTOM * mag_height) / EPUB_IMAGE_HEIGHT;

        var height = $("#epub_content").find(".mag_caption").height();
        var width = $("#epub_content").find(".mag_caption").width(width);
        if (width > mag_width * EPUB_ICAPTION_WIDTH_ASPECT * .70) width = mag_width * EPUB_ICAPTION_WIDTH_ASPECT * .70;
        if (width < mag_width * EPUB_ICAPTION_WIDTH_ASPECT * .20) width = mag_width * EPUB_ICAPTION_WIDTH_ASPECT * .20;

        $("#epub_content").find(".mag_caption").width(width);
        $("#epub_content").find(".mag_caption_gap").width(width);
        $("#epub_content").find(".mag_caption img").css("left", (width - 20));

        //offset coordinates from margins
        var left = right - width + (window_width - mag_width) / 2;
        var top = bottom - height + (window_height - mag_height) / 2;

        $("#epub_content").find(".mag_caption").offset({
            top: top,
            left: left
        });
    }

    function relocate_hyperlinks(window_width, window_height, mag_width, mag_height) {
        $("#epub_content").find(".mag_hyperlink").each(function () {
            adjust_object($(this), window_width, window_height, mag_width, mag_height);
        });
    }

    function relocate_slideshow(window_width, window_height, mag_width, mag_height) {
        var $slider_link = $("#epub_content").find(".mag_slideshow_link");
        if ($slider_link.length == 0) return;

        adjust_object($slider_link, window_width, window_height, mag_width, mag_height);
    }

    function relocate_theater(window_width, window_height, mag_width, mag_height) {
        $("#epub_content").find(".mag_theater").each(function () {
            var $theater = $(this);
            if ($theater.length == 0) return;

            $theater_link = $theater.find(".mag_theater_link");
            if ($theater_link.length == 0) return;

            $theater_link.each(function () {
                $(".mag_theater_link").fadeIn(2000);
                adjust_object($(this), window_width, window_height, mag_width, mag_height);
            });

            var $theater_border = $theater.find(".mag_theater_border");
            if ($theater_border.length == 0) return;

            var left = (window_width - $theater_border.width()) / 2;
            var top = (window_height - $theater_border.height()) / 2;
            $theater_border.offset({ top: top, left: left });
        });
    }

    function adjust_object($obj, window_width, window_height, mag_width, mag_height) {
        //scale coordinates
        var left = ($obj.data("left") * mag_width) / EPUB_IMAGE_WIDTH;
        var top = ($obj.data("top") * mag_height) / EPUB_IMAGE_HEIGHT;
        var width = ($obj.data("width") * mag_width) / EPUB_IMAGE_WIDTH;
        var height = ($obj.data("height") * mag_height) / EPUB_IMAGE_HEIGHT;

        //offset coordinates from margins
        left = left + (window_width - mag_width) / 2;
        top = top + (window_height - mag_height) / 2;

        $obj.offset({ top: top, left: left });
        $obj.width(width);
        $obj.height(height);
    }

    function load_ebook() {
        jQuery.get(epub_folder + '/META-INF/container.xml', {}, load_container);
        jQuery.get(epub_shelf + '/editions/editions.xml', {}, load_editions);
    }

    function load_editions(data) {
        epub_editions = new Object();
        epub_editions.loaded = false;
        epub_editions.items = new Array();
        $(data).find('edition').each(function () {
            var i = epub_editions.items.length;
            epub_editions.items[i] = new Object();
            epub_editions.items[i].id = $(this).attr("id");
            epub_editions.items[i].current = $(this).attr("current");
            epub_editions.items[i].title = $(this).attr("title");
            epub_editions.items[i].href = $(this).attr("href");
            epub_editions.items[i].thumbnail = $(this).attr("thumbnail");
        });
    }

    function load_edition_thumbnails() {
        if (epub_editions == null) return;
        if (!epub_editions.loaded) {
            epub_editions.loaded = true;
            $.each(epub_editions.items, function () {
                var div = $('<div/>').addClass("epub_tray_shelf_item_title").text(this.title);
                var img = $('<img/>').attr('src', this.thumbnail).width(600).height(360);

                var idiv = $("<div/>").addClass("epub_tray_item").attr("id", "epub_editions_tray_item").attr("style", "cursor:pointer")
                                .bind("click", { edition: this }, function (e) {
                                    load_edition(e.data.edition);
                                    $("#epub_shelf_popup").fadeOut();
                                });

                idiv.appendTo('#epub_shelf_thumbs');
                img.appendTo(idiv);
                div.appendTo(idiv);
            });

            var strip_width = epub_editions.items.length * (EPUB_EDITION_TILE_WIDTH + EPUB_EDITION_TILE_GUTTER)
            $("#epub_shelf_thumbs").width(strip_width);
        }
    }

    function load_edition(shelf_entry) {
        window.open(shelf_entry.href);
    }

    function load_container(data) {
        opf_file = $(data).find('rootfile').attr('full-path');

        // Get the OEPBS folder, if there is one
        oebps_folder = "";
        if (opf_file.indexOf('/') != -1) {
            oebps_folder = opf_file.substr(0, opf_file.lastIndexOf('/')) + "/";
        }

        opf_file = epub_folder + '/' + opf_file;
        jQuery.get(opf_file, {}, load_opf);
    }

    function load_opf(data) {
        // get the document title
        // depending on the browser, namespaces may or may not be handled here
        var title = $(data).find('title').text();
        var author = $(data).find('creator').text();

        // try by namespace
        if (title == null || title == '') {
            title = $(data).find('dc\\:title').text()
            author = $(data).find('dc\\:creator').text()
        }

        document.title = title;

        _cache_list = new Object();
        _cache_list.opf_data = data;

        // get the NCX 
        var opf_item_tag = 'opf\\:item';
        if ($(data).find('opf\\:item').length == 0) {
            opf_item_tag = 'item';
        }

        $(data).find(opf_item_tag).each(function () {
            // find the first file ending in NCX
            if ($(this).attr('href').indexOf('.ncx') != -1) {
                ncx_file = epub_folder + '/' + oebps_folder + $(this).attr('href');
                jQuery.get(ncx_file, {}, load_toc);
            }
        });
    }

    function load_toc(data) {
        var start = 0;
        epub_toc = new Array();
        $(data).find('navPoint').each(function () {
            var i = epub_toc.length;
            epub_toc[i] = new Object();
            epub_toc[i].index = i;
            epub_toc[i].page = 0;

            epub_toc[i].id = $(this).attr('id');
            if (_start_section != "" && epub_toc[i].id.toLowerCase() == _start_section.toLowerCase()) {
                _start_section == "";
                start = i;
                epub_toc[i].page = _start_page;
            }

            epub_toc[i].url = epub_folder + '/' + oebps_folder + $(this).find('content').attr('src');
            epub_toc[i].text = $(this).find('text').text();
            epub_toc[i].thumbnail = epub_folder + "/" + $(this).find('thumbnail').text();

            build_toc_popup(epub_toc[i]);
        });

        var strip_width = epub_toc.length * (EPUB_STRIP_TILE_WIDTH + EPUB_STRIP_TILE_GUTTER)
        $("#epub_toc_thumbs").width(strip_width);

        _cache_list.caching = 0;
        _cache_list.base = epub_folder + '/' + oebps_folder;
        _cache_list.stepw = 0;
        _cache_list.steph = 0;

        _cache_list.items = new Array();
        $(_cache_list.opf_data).find('item').each(function () {
            var media = $(this).attr("media-type");
            if (media.indexOf("image") == -1) return;

            var i = _cache_list.items.length;
            _cache_list.items[i] = new Object();

            var src = $(this).attr("href");
            _cache_list.items[i].is_page = $(this).attr("page") == "true";
            _cache_list.items[i].src = src;
        });

        load_chapter(epub_toc[start], true);
        build_indexes();
    }

    function build_indexes() {
        var i = 0;
        for (i = 0; i < epub_toc.length; i++) {
            var toc_entry = epub_toc[i];
            var href = "index.html#section=" + toc_entry.id;
            var $anchor = $("<a/>").attr("href", href);
            $("#epub_below_the_fold").append($anchor);
        }
    }

    function load_chapter(toc_entry, fadein) {
        _current_chapter = toc_entry;
        jQuery.get(toc_entry.url, function (data) {
            var s = data.indexOf('<body>');
            var e = data.indexOf('</body>');

            var html = data.substring(s + 6, e);
            $("#epub_current_chapter_content").html(html);
            toc_entry.$pages = $("#epub_current_chapter_content").find(".epub_nav_page");

            if (toc_entry.page == -1) toc_entry.page = toc_entry.$pages.length - 1;
            if (!_splash_shown && _start_section == "") load_splash(toc_entry);
            else load_page(toc_entry, fadein);

            flip_initialize();
        });
    }

    function load_splash(toc_entry) {
        var offset = new Object();

        var str = $("#epub_spinner").css("left");
        offset.left = parseInt(str.substring(0, str.length - 2));
        var str = $("#epub_spinner").css("top");
        offset.top = parseInt(str.substring(0, str.length - 2));

        $("#epub_spinner").data("top", offset.top);
        $("#epub_spinner").data("left", offset.left);
        $("#epub_spinner").data("width", $("#epub_spinner").width());
        $("#epub_spinner").data("height", $("#epub_spinner").height());

        str = $("#epub_splash_title").css("left");
        offset.left = parseInt(str.substring(0, str.length - 2));
        str = $("#epub_splash_title").css("top");
        offset.top = parseInt(str.substring(0, str.length - 2));

        $("#epub_splash_title").data("top", offset.top);
        $("#epub_splash_title").data("left", offset.left);
        $("#epub_splash_title").data("width", $("#epub_splash_title").width());
        $("#epub_splash_title").data("height", $("#epub_splash_title").height());

        str = $("#epub_splash_catch").css("left");
        offset.left = parseInt(str.substring(0, str.length - 2));
        str = $("#epub_splash_catch").css("top");
        offset.top = parseInt(str.substring(0, str.length - 2));

        $("#epub_splash_catch").data("top", offset.top);
        $("#epub_splash_catch").data("left", offset.left);
        $("#epub_splash_catch").data("width", $("#epub_splash_catch").width());
        $("#epub_splash_catch").data("height", $("#epub_splash_catch").height());

        adjust_object_to_window($("#epub_splash_title"));
        adjust_object_to_window($("#epub_splash_catch"));

        cache_cover();
        _splash_shown = true;
        $("#epub_splash_title").fadeIn(EPUB_FADE_RATE, function () {
            $("#epub_splash_catch").fadeIn(EPUB_FADE_RATE, function () {
                load_page(toc_entry, true)
            });
        });
    }

    function cache_cover() {
        var img = new Image();
        var pre = epub_folder + '/' + oebps_folder;
        var href = get_step_path(pre, _cache_list.items[0].src, $(window).width());
        img.src = href;
        img.onload = function (event) {
            //debug("cached cover at: " + event.target.src);
        };
    }

    function load_cache() {
        var item = _cache_list.caching;
        if (item >= _cache_list.items.length) return;

        var img = new Image();
        var pre = epub_folder + '/' + oebps_folder;
        var href = get_step_path(pre, _cache_list.items[item].src, _cache_list.stepw);
        img.src = href;

        img.onload = function (event) {
            //debug("cached: " + event.target.src);
            delete event.target;
        };

        setTimeout(function () {
            _cache_list.caching++;
            load_cache();
        }, 1000);
    }

    function adjust_object_to_window($obj) {
        //scale coordinates
        var window_width = $(window).width();
        var window_height = $(window).height();

        var left = ($obj.data("left") * window_width) / EPUB_IMAGE_WIDTH;
        var top = ($obj.data("top") * window_height) / EPUB_IMAGE_HEIGHT;
        var width = ($obj.data("width") * window_width) / EPUB_IMAGE_WIDTH;
        var height = ($obj.data("height") * window_height) / EPUB_IMAGE_HEIGHT;

        $obj.css("top", top);
        $obj.css("left", left);
        $obj.width(width);
        $obj.height(height);
    }

    function load_page(toc_entry, fadein) {
        window.location.hash = "section=" + toc_entry.id + "&page=" + toc_entry.page;
        if (_analytics) {
            _gaq.push(['_trackEvent', epub_edition + ":page", toc_entry.id, toc_entry.page]);
            _gaq.push(['_trackPageview', "/" + epub_edition + "/page/" + toc_entry.id + "/" + toc_entry.page]);
        }

        if (fadein) $("#epub_flipper").hide();
        $(".mag_caption").hide();
        $(".mag_include_flash").hide();

        start_wait();

        page = toc_entry.page;
        $("#epub_content").html($(toc_entry.$pages[page]).html());

        fixup_images();
        build_icaption();
        build_hyperlinks();
        build_slideshow();
        build_theater();

        $("#mag_background").hide();
        $(window).trigger("resize");
        if (_cache_list.caching == 0) load_cache();
        sync_flipper(toc_entry);
        load_edition_thumbnails();

        stop_wait();

        if (fadein && !is_mobile) {
            $("#epub_navigation").fadeIn(2000, function () {
                $("#epub_flipper").fadeIn(3000, function () {
                    $(".mag_caption").show();
                    $(".mag_include_flash").show();
                });
            });
        }
        else {
            $("#epub_navigation").show();
            $("#epub_flipper").show();
            $(".mag_caption").show();
            $(".mag_include_flash").show();
        }
    }

    function build_toc_popup(toc_entry) {
        var div = $('<div/>').addClass("epub_tray_toc_item_title").text(toc_entry.text);
        var img = $('<img/>').attr('src', toc_entry.thumbnail).width(150).height(90);

        var idiv = $("<div/>").addClass("epub_tray_item").attr("id", "epub_toc_tray_item").attr("style", "cursor:pointer")
                    .bind("click", { chapter: toc_entry }, function (e) {
                        e.data.chapter.page = 0;
                        load_chapter(e.data.chapter, true);
                        $("#epub_contents_popup").fadeOut();
                    });

        idiv.appendTo('#epub_toc_thumbs');
        img.appendTo(idiv);
        div.appendTo(idiv);
    }

    function fixup_images() {
        $("#epub_content").find("img").each(function () {
            if ($(this).attr("id") == "mag_background") return;

            var pre = _current_chapter.url.substr(0, _current_chapter.url.lastIndexOf('/'));
            $(this).attr("src", pre + "/" + $(this).attr("src"));
        });
    }

    function fixup_background($object, pre, width) {
        var src = $object.attr("src");
        if (src == null || src == "") return;

        var href = get_step_path(pre, src, width);
        $object.attr("src", href);
    }

    function get_step_path(pre, src, width) {
        var i = src.lastIndexOf('/');
        var path = "";
        var file = src;

        if (i > 0) {
            var path = src.substr(0, i) + '/';
            if (path == "/") path = "";

            var file = "/" + src.substr(i + 1);
        }

        var step;
        if (width > EPUB_IMAGE_WIDTH_STEP1) {
            _cache_list.stepw = EPUB_IMAGE_WIDTH;
            _cache_list.steph = EPUB_IMAGE_HEIGHT;
            step = EPUB_IMAGE_PATH_STEP;
        }

        else if (width > EPUB_IMAGE_WIDTH_STEP2) {
            _cache_list.stepw = EPUB_IMAGE_WIDTH_STEP1;
            _cache_list.steph = EPUB_IMAGE_HEIGHT_STEP1;
            step = EPUB_IMAGE_PATH_STEP1;
        }

        else if (width > EPUB_IMAGE_WIDTH_STEP3) {
            _cache_list.stepw = EPUB_IMAGE_WIDTH_STEP2;
            _cache_list.steph = EPUB_IMAGE_HEIGHT_STEP2;
            step = EPUB_IMAGE_PATH_STEP2;
        }

        else if (width > EPUB_IMAGE_WIDTH_STEP4) {
            _cache_list.stepw = EPUB_IMAGE_WIDTH_STEP3;
            _cache_list.steph = EPUB_IMAGE_HEIGHT_STEP3;
            step = EPUB_IMAGE_PATH_STEP3;
        }

        else if (width > EPUB_IMAGE_WIDTH_STEP5) {
            _cache_list.stepw = EPUB_IMAGE_WIDTH_STEP4;
            _cache_list.steph = EPUB_IMAGE_HEIGHT_STEP4;
            step = EPUB_IMAGE_PATH_STEP4;
        }

        else {
            _cache_list.stepw = EPUB_IMAGE_WIDTH_STEP5;
            _cache_list.steph = EPUB_IMAGE_HEIGHT_STEP5;
            step = EPUB_IMAGE_PATH_STEP5;
        }

        return pre + path + step + file;
    }

    function build_icaption() {
        $("#epub_content").find(".mag_caption a").attr("target", "_blank");
        var caption_html = $("#epub_content").find(".mag_caption").html();
        var caption_width = $("#epub_content").find(".mag_caption").outerWidth(true);
        var caption_height = $("#epub_content").find(".mag_caption").outerHeight(true);

        $("#epub_content").find(".mag_caption").html("");
        $("#epub_content").find(".mag_caption").hide();
        var wdiv = $("<div/>").width(caption_width).height(caption_height).addClass("mag_caption_gap");
        var div = $("<div/>").html(caption_html).addClass('mag_caption_text');
        var img = $("<img/>").attr('src', 'scripts/plugins/epub/images/icaption.png').hide();
        img.css("position", "relative").css("left", (caption_width - 20));

        wdiv.appendTo($("#epub_content").find(".mag_caption"));
        div.appendTo(wdiv);
        img.appendTo($("#epub_content").find(".mag_caption"));
        $(".mag_caption_text").hide();

        $(".mag_caption").click(function () {
            $(this).find(".mag_caption_text").fadeToggle();
        });

        $(".mag_caption").find("a").click(function () {
            if (_analytics) {
                var href = $(this).attr("href");
                _gaq.push(['_trackEvent', epub_edition + ":icap", href]);
                _gaq.push(['_trackPageview', "/" + epub_edition + "/icap?url=" + href]);
            }
        });

        $(".mag_caption").mouseenter(function () {
            $(this).find(".mag_caption_text").fadeIn();
        });

        $(".mag_caption").mouseleave(function () {
            $(this).find(".mag_caption_text").fadeOut();
        });
    }

    function build_hyperlinks() {
        $("#epub_content").find(".mag_hyperlink").each(function () {
            var offset = $(this).offset();
            $(this).find("a").hide();

            $(this).data("top", offset.top);
            $(this).data("left", offset.left);
            $(this).data("width", $(this).width());
            $(this).data("height", $(this).height());

            $(this).click(function () {
                var href = $(this).find("a").attr("href");
                var target = $(this).find("a").attr("target");
                on_hyperlink_click(href, target);
            });
        });
    }

    function on_hyperlink_click(href, target) {
        if (href.indexOf("chapter:") == 0) {
            href = href.substring(8);
            goto_chapter(href);
            return;
        }

        if (_analytics) {
            _gaq.push(['_trackEvent', epub_edition + ":ad", href]);
            _gaq.push(['_trackPageview', "/" + epub_edition + "/ad?url=" + href]);
        }

        if (target == "_blank") window.open(href);
        else window.location = href;
    }

    function build_slideshow() {
        var $slider = $("#epub_content").find(".mag_slideshow");
        if ($slider.length == 0) return;

        var $slider_link = $slider.find(".mag_slideshow_link");
        if ($slider_link.length == 0) return;

        var offset = $slider_link.offset();
        $slider_link.data("top", offset.top);
        $slider_link.data("left", offset.left);
        $slider_link.data("width", $slider_link.width());
        $slider_link.data("height", $slider_link.height());

        epub_show = new Object();
        epub_show.loading = 0;
        epub_show.showing = -1;
        epub_show.slides = new Array();
        $slider.find(".mag_slideshow_item").each(function () {
            var i = epub_show.slides.length;
            epub_show.slides[i] = new Object();
            epub_show.slides[i].src = $(this).text();
            epub_show.slides[i].shown = false;
        });

        load_next_slide();

        $slider_link.click(function () {
            $("#epub_fader").fadeIn(EPUB_FADE_RATE, function () {
                $slider.find(".mag_slideshow_border").fadeIn(function () {
                    start_slideshow();
                }).click(function () {
                    stop_slideshow();
                });
            });
        });
    }

    function build_theater() {
        $("#epub_content").find(".mag_theater").each(function () {
            var $theater = $(this);
            if ($theater.length == 0) return;

            var $theater_link = $theater.find(".mag_theater_link");
            if ($theater_link.length == 0) return;

            $theater_link.each(function () {
                var left = $theater_link.css("left");
                left = left.substring(0, left.length - 2);

                var top = $theater_link.css("top");
                top = top.substring(0, top.length - 2);

                $(this).data("top", parseInt(top));
                $(this).data("left", parseInt(left));
                $(this).data("width", $(this).width());
                $(this).data("height", $(this).height());

                if ($(this).hasClass("mag_include_flash")) {
                    $(".mag_include_flash").hide();
                    var $img = $("<img/>").attr("src", "scripts/plugins/epub/images/flash.gif");
                    $img.appendTo($(this));
                }
            });

            $theater_link.click(function () {
                $("#epub_fader").fadeIn(EPUB_FADE_RATE, function () {
                    $theater.find(".mag_theater_border").fadeIn().click(function () {
                        $theater.find(".mag_theater_border").fadeOut(function () {
                            $("#epub_fader").fadeOut(EPUB_FADE_RATE);
                        });
                    });
                });
            });
        });
    }

    function start_slideshow() {
        if (_show_tid != null) stop_slideshow();

        for (var k = 0; k < epub_show.slides.length; k++)
            epub_show.slides[k].shown = false;

        show_next_slide();
        _show_tid = setInterval(function () {
            show_next_slide();
        }, EPUB_SHOW_INTERVAL);
    }

    function show_next_slide() {
        var straggler = false;
        for (var j = 0; j < epub_show.slides.length; j++) {
            if (epub_show.slides[j].$slide != null) {
                if (!epub_show.slides[j].shown) {
                    epub_show.slides[j].shown = true;
                    var i = epub_show.showing;
                    if (i != -1) epub_show.slides[i].$slide.fadeOut(EPUB_FADE_RATE);

                    epub_show.showing = j;
                    epub_show.slides[j].$slide.fadeIn(EPUB_FADE_RATE);
                    return;
                }
            }
            else straggler = true;
        }

        if (!straggler) stop_slideshow();
    }

    function stop_slideshow() {
        if (_show_tid != null) clearInterval(_show_tid);
        _show_tid = null;

        var i = epub_show.showing;
        if (i != -1) {
            epub_show.slides[i].$slide.fadeOut(function () {
                var $slider = $("#epub_content").find(".mag_slideshow");
                $slider.find(".mag_slideshow_border").fadeOut(function () {
                    $("#epub_fader").fadeOut(EPUB_FADE_RATE);
                });
            });
        }

        else {
            var $slider = $("#epub_content").find(".mag_slideshow");
            $slider.find(".mag_slideshow_border").fadeOut(function () {
                $("#epub_fader").fadeOut(EPUB_FADE_RATE);
            });
        }
    }

    function start_wait() {
        if (_spin_tid != null) return;
        _spin_tid = setTimeout(function () {
            adjust_object_to_window($("#epub_spinner"));
            $("#epub_spinner").show();
        }, EPUB_SPIN_WAIT);
    }

    function stop_wait() {
        $("#epub_spinner").hide();
        $("#epub_splash").fadeOut(EPUB_FADE_RATE);

        if (_spin_tid != null) clearTimeout(_spin_tid);
        _spin_tid = null;
    }

    function load_next_slide() {
        var i = epub_show.loading++;
        if (i >= epub_show.slides.length) return;

        var $slider = $("#epub_content").find(".mag_slideshow");
        var pre = _current_chapter.url.substr(0, _current_chapter.url.lastIndexOf('/'));
        var src = pre + "/" + epub_show.slides[i].src;
        var $img = $("<img/>").attr("src", src).addClass("mag_slideshow_slide");

        $img.appendTo($slider);

        $img.load(function () {
            epub_show.slides[i].$slide = $img;
            load_next_slide()
        });
    }

    function goto_chapter(chapter) {
        for (i = 0; i < epub_toc.length; i++) {
            if (epub_toc[i].id == chapter) {
                epub_toc[i].page = 0;
                load_chapter(epub_toc[i], true);
                break;
            }
        }
    }

    function page_forward() {
        var toc_entry = _current_chapter;
        var page = toc_entry.page + 1;
        if (toc_entry.$pages.length <= page) {
            var i = toc_entry.index + 1;
            if (epub_toc.length > i) {
                epub_toc[i].page = 0;
                load_chapter(epub_toc[i], false);
            }

            return;
        }

        toc_entry.page = page;
        load_page(toc_entry, false);
    }

    function page_back() {
        var toc_entry = _current_chapter;
        var page = toc_entry.page - 1;
        if (page < 0) {
            var i = toc_entry.index - 1;
            if (i >= 0) {
                epub_toc[i].page = -1;
                load_chapter(epub_toc[i], false);
            }

            return;
        }

        toc_entry.page = page;
        load_page(toc_entry, false);
    }

    function sync_flipper(toc_entry) {
        var page = toc_entry.page;
        var $page = $(toc_entry.$pages[page]);

        var src = $page.find("#mag_background").attr("src");
        var file = src.substring(src.lastIndexOf('/') + 1);

        for (i = 0; i < _cache_list.items.length; i++) {
            src = _cache_list.items[i].src;
            if (file == src.substring(src.lastIndexOf('/') + 1)) {
                actPage = i * 2;
                imgFlipBackLeft = flip_get_image(actPage - 1);
                imgFlipFrontLeft = flip_get_image(actPage);
                imgFlipFrontRight = flip_get_image(actPage + 1);
                imgFlipBackRight = flip_get_image(actPage + 2);

                $('#epub_page_background_left img').attr('src', imgFlipFrontLeft.src);
                $('#epub_page_background_right img').attr('src', imgFlipFrontRight.src);

                //cache a few before and a few after current image
                flip_get_image(actPage - 5);
                flip_get_image(actPage - 4);
                flip_get_image(actPage - 3);
                flip_get_image(actPage - 2);
                flip_get_image(actPage + 3);
                flip_get_image(actPage + 4);
                flip_get_image(actPage + 5);
                return;
            }
        }

        if (toc_entry.page == 0) return;

        toc_entry.page = 0;
        sync_flipper(toc_entry);
    }

    // page flipping code

    function flip_initialize() {
        var help1 = 0;
        var help2 = 0;

        imgFlipBackLeft = flip_get_image(actPage);
        imgFlipFrontLeft = flip_get_image(actPage);
        imgFlipFrontRight = flip_get_image(actPage + 1);
        imgFlipBackRight = flip_get_image(actPage + 2);

        if (flip_get_image(actPage)) $('#epub_page_background_left img').attr('src', flip_get_image(actPage).src);
        if (flip_get_image(actPage + 1)) $('#epub_page_background_right img').attr('src', flip_get_image(actPage + 1).src);

        $("#epub_flipper").bind({ mousemove: function (event) { _flip_on_mouse_move(event) } });
        $("#epub_flipper").bind({ mousedown: function (event) { _flip_on_mouse_down(event) } });
        $("#epub_flipper").bind({ mouseup: function (event) { _flip_on_mouse_up(event) } });
        $("#epub_flipper").bind({ mouseleave: function (event) { $("#epub_flipper").css('cursor', 'auto'); } });
    }

    function _flip_on_resize(window_width, window_height, mag_width, mag_height) {
        iScale = EPUB_IMAGE_WIDTH / mag_width;
        iHeight = mag_height;
        iWidth = Math.ceil(mag_width / 2 + 1);

        contentX = (window_width - mag_width) / 2;
        contentY = (window_height - mag_height) / 2;

        innerMx = iWidth + contentX;
        innerMy = iHeight;

        outerMx = innerMx;
        outerMy = innerMy - iHeight;

        outerRadius = Math.sqrt(iWidth * iWidth + iHeight * iHeight);

        flipDynamic = window_width * EPUB_FLIP_ANIMATION_DYNAMIC / mag_width;
        if (jQuery.browser.msie) flipDynamic = flipDynamic / 4;

        $("#epub_flipper").css({ 'width': 2 * iWidth, 'height': iHeight });

        var canvas = document.getElementById("epub_canvas_page_flip");
        canvas.width = iWidth * 2 + contentX;
        canvas.height = iHeight + contentY;

        ctx = canvas.getContext("2d");

        $('#epub_page_background_left img').css({ 'left': (innerMx - iWidth) + 'px', 'top': contentY + 'px', 'width': iWidth * 2, 'height': iHeight });
        $('#epub_page_background_right img').css({ 'margin-left': "-" + iWidth + 'px', 'top': contentY + 'px', 'width': iWidth * 2, 'height': iHeight });

        $('#epub_page_background_left').css({ 'left': (innerMx - iWidth) + 'px', 'top': contentY + 'px', 'width': iWidth, 'height': iHeight });
        $('#epub_page_background_right').css({ 'left': innerMx + 'px', 'top': contentY + 'px', 'width': iWidth, 'height': iHeight });
    }

    function _flip_on_mouse_move(e) {
        var left = $("#epub_flipper").offset().left;
        var top = $("#epub_flipper").offset().top;
        mouseAbsX = e.pageX - left;
        mouseAbsY = e.pageY - top;

        flip_calc_rel_mouse_pos();
        flip_is_mouse_in_corner();

        if (is_mouseDown) flip_page_flip();
    }

    function flip_calc_rel_mouse_pos() {
        mouseRelCenterX = mouseAbsX - innerMx;
        mouseRelCenterY = mouseAbsY - innerMy - contentY;
    }

    function _flip_on_mouse_down(e) {
        if (mouseRelCenterX > 0) takePage = 1;
        if (mouseRelCenterX < 0) takePage = -1;
        if (flip_check_first_and_last_page() && flip_calculate_act_images()) is_mouseDown = true;
    }

    function _flip_on_mouse_up(e) {
        $("#epub_flipper").css('cursor', 'auto');
        if (is_mouseDown) {
            is_mouseDown = false;
            if (mouseRelCenterX >= 0) {
                var angle_clx = Math.atan((mouseRelCenterY) / Math.abs(CX - contentX - 2 * iWidth));

                flip_is_mouse_in_corner();
                if (isMouseInCorner) {
                    if (takePage == 1) dropPage = -1;
                    if (takePage == -1) dropPage = 1;
                    angle_clx = -0.04;
                }
                else dropPage = 1;

                flip_animate_begin(angle_clx, null);
            }
            else {
                var angle_clx = Math.atan((mouseRelCenterY) / (CX - contentX));

                flip_is_mouse_in_corner();
                if (isMouseInCorner) {
                    if (takePage == -1) dropPage = 1;
                    if (takePage == 1) dropPage = -1;
                    angle_clx = -0.04;
                }
                else dropPage = -1;

                flip_animate_begin(angle_clx, null);
            }

            flip_page_flip();

            mouseRelCenterX = mouseAbsX - innerMx;
            mouseRelCenterY = mouseAbsY - innerMy - contentY;
        }
    }

    function flip_calculate_act_images() {
        if (isMouseInCorner) {
            flip_take_page();
            flip_page_flip();
            return true;
        }
    }

    function flip_page_forward() {
        flipper_chillout = true;
        $(".mag_caption").hide();
        $(".mag_include_flash").hide();

        flip_sim_animate_setup((2 * iWidth) - EPUB_FLIP_CORNER_SIZE / 2, iHeight - EPUB_FLIP_CORNER_SIZE / 2, 1)
        if (flip_check_first_and_last_page() && flip_calculate_act_images()) flip_animate_begin(-0.04, flip_sim_animate_end);
    }

    function flip_page_back() {
        flipper_chillout = true;
        $(".mag_caption").hide();
        $(".mag_include_flash").hide();

        flip_sim_animate_setup(EPUB_FLIP_CORNER_SIZE / 2, iHeight - EPUB_FLIP_CORNER_SIZE / 2, -1);
        if (flip_check_first_and_last_page() && flip_calculate_act_images()) flip_animate_begin(-0.04, flip_sim_animate_end);
    }

    function flip_sim_animate_setup(x, y, take) {
        mouseAbsX = contentX + x - 8;
        mouseAbsY = contentY + y - 8;

        mouseRelCenterX = mouseAbsX - innerMx;
        mouseRelCenterY = mouseAbsY - innerMy - contentY;

        isMouseInCorner = true;
        is_mouseDown = false;

        takePage = take;
        dropPage = -1 * take;
        flipper_chillout = false;
    }

    function flip_sim_animate_end() {
        mouseAbsX = 10;
        mouseAbsY = 10;

        mouseRelCenterX = mouseAbsX - innerMx;
        mouseRelCenterY = mouseAbsY - innerMy - contentY;

        isMouseInCorner = false;
        is_mouseDown = false;
    }

    function flip_page_flip() {
        MC = Math.sqrt(Math.pow(mouseRelCenterX, 2) + Math.pow(mouseRelCenterY, 2));
        SC = Math.sqrt(Math.pow(mouseRelCenterX, 2) + Math.pow(iHeight + mouseRelCenterY, 2));

        if ((MC <= iWidth)) {
            CX = innerMx + mouseRelCenterX;
            CY = iHeight + contentY + mouseRelCenterY;
        }

        if (MC > iWidth) {
            MCX = iWidth * (Math.cos(Math.atan(mouseRelCenterY / mouseRelCenterX)));
            MCY = iWidth * Math.abs((Math.sin(Math.atan(mouseRelCenterY / mouseRelCenterX))));

            if (mouseRelCenterX < 0) MCX = MCX * -1;
            if (mouseRelCenterY < 0) MCY = MCY * -1;

            CX = MCX + innerMx;
            CY = MCY + iHeight + contentY;
        }

        angleCXMCY = Math.atan((Math.abs(CX - innerMx)) / (CY - contentY)) / degHelp;
        r2x = Math.sin(angleCXMCY * degHelp) * outerRadius;

        if (mouseRelCenterX < 0) r2x = r2x * -1;
        r2y = Math.cos(angleCXMCY * degHelp) * outerRadius;

        if ((SC > outerRadius) && (mouseRelCenterY > 0)) {
            CX = innerMx + r2x;
            CY = r2y + contentY;
        }

        T1Y = (contentY + iHeight + CY) / 2;
        T1X = (innerMx + (takePage * iWidth) + CX) / 2;
        T1C = Math.sqrt(Math.pow(innerMx + (takePage * iWidth) - T1X, 2) + Math.pow(contentY + iHeight - T1Y, 2));
        angleT1XT1Y = Math.atan((contentY + iHeight - CY) / (innerMx + (takePage * iWidth) - CX));

        if (!angleT1XT1Y) angleT1XT1Y = 0;
        if (takePage == 1) T2X = innerMx + iWidth - T1C / Math.cos(angleT1XT1Y);
        else if (takePage == -1) T2X = innerMx - iWidth + T1C / Math.cos(angleT1XT1Y);
        T2Y = iHeight + contentY;

        T2CX = T2X - CX;
        T2CY = contentY + iHeight - CY;
        if ((contentY + iHeight - CY >= 0) && (T2CY != 0)) angleImage = 90 - (Math.atan(T2CX / T2CY) / degHelp);
        else if (T2CY != 0) angleImage = -90 - (Math.atan(T2CX / T2CY) / degHelp);
        else {
            if (takePage == 1) angleImage = 0;
            else angleImage = 180;
        }

        T1YRel = iHeight + contentY - T1Y;
        if (T1YRel != 0) angleClip = Math.atan((T1X - T2X) / T1YRel) / degHelp;
        else angleClip = 0;

        var epbw = _cache_list.stepw;
        var epbh = _cache_list.steph;

        var split = 0;
        if (jQuery.browser.webkit) split = -1;

        ctx.clearRect(0, 0, $(window).width(), $(window).height());

        if (takePage == 1) {
            ctx.save();
            ctx.drawImage(imgFlipFrontRight, epbw / 2, 0, epbw / 2, epbh, iWidth + contentX + split, contentY, iWidth, iHeight);

            ctx.save();
            ctx.translate(CX, CY);
            ctx.rotate(angleImage * degHelp);
            ctx.translate(0, -iHeight);
            ctx.drawImage(imgFlipBackRight, 0, 0, epbw / 2, epbh, 0, 0, iWidth, iHeight);

            ctx.restore();

            ctx.save();
            ctx.translate(CX, CY);
            ctx.rotate(angleImage * degHelp);
            ctx.restore();

            ctx.translate(T2X, T2Y);
            ctx.rotate(angleClip * degHelp);
            ctx.translate(0, -iHeight - iWidth + 100);
            ctx.clearRect(0, 0, 2 * iWidth, 2.5 * iHeight);
            ctx.restore();
        }

        else if (takePage == -1) {
            ctx.save();
            ctx.drawImage(imgFlipFrontLeft, 0, 0, epbw / 2, epbh, contentX + split, contentY, iWidth, iHeight);

            ctx.save();
            ctx.translate(CX, CY);
            ctx.rotate((angleImage + 180) * degHelp);
            ctx.translate(-iWidth, -iHeight);
            ctx.drawImage(imgFlipBackLeft, epbw / 2, 0, epbw / 2, epbh, 0, 0, iWidth, iHeight);

            ctx.restore();

            ctx.translate(T2X, T2Y);
            ctx.rotate(angleClip * degHelp);
            ctx.translate(-2 * iWidth, -iHeight - (Math.abs(iHeight - iWidth)));
            ctx.clearRect(0, 0, 2 * iWidth, 2.5 * iHeight);
            ctx.restore();
        }
        return true;
    }

    function flip_calculate_page() {
        if (takePage > dropPage) actPage = actPage + 2;
        if (takePage < dropPage) actPage = actPage - 2;
    }

    function flip_is_mouse_in_corner() {
        if ((iWidth - Math.abs(mouseRelCenterX) < EPUB_FLIP_CORNER_SIZE) &&
                (iWidth - Math.abs(mouseRelCenterX) >= 0) &&
                (Math.abs(mouseRelCenterY) < EPUB_FLIP_CORNER_SIZE) &&
                (mouseRelCenterY <= 0)) {
            isMouseInCorner = true;
            $("#epub_flipper").css('cursor', 'pointer');
            return true;
        }
        else isMouseInCorner = false;
        $("#epub_flipper").css('cursor', 'auto');
    }

    function flip_check_first_and_last_page() {
        var len = flip_get_images_length();
        if (((actPage < len - 2) && (takePage == 1)) || ((actPage > 0) && (takePage == -1))) return true;
        else return false;
    }

    function flip_animate_begin(angle_clx, complete_callback) {
        $("#epub_canvas_container").css("z-index", "20000");
        flip_animate_flipping(angle_clx, complete_callback)
    }

    var startTm = null;
    function flip_animate_flipping(angle_clx, complete_callback) {
        $("#epub_flipper").unbind();
        if (mouseRelCenterY < 0) dynamicHelp = 20;

        if (dropPage == -1) {
            mouseRelCenterX = mouseRelCenterX - flipDynamice;
            mouseRelCenterY = Math.tan(angle_clx) * (CX - contentX) - dynamicHelp;
        }

        if (dropPage == 1) {
            mouseRelCenterX = mouseRelCenterX + flipDynamice;
            mouseRelCenterY = Math.tan(angle_clx) * Math.abs(CX - contentX - 2 * iWidth) - dynamicHelp;
        }

        if ((CX - contentX > 1) && (CX - contentX < 2 * iWidth - 1)) {
            flip_page_flip();

            var speed = EPUB_FLIP_ANIMATION_SPEED;
            interval = setTimeout(function () {
                flip_animate_flipping(angle_clx, complete_callback);
            }, speed);
        }
        else {
            if (dropPage == -1) mouseRelCenterX = -iWidth;
            if (dropPage == 1) mouseRelCenterX = iWidth;

            mouseRelCenterY = 0;
            flip_calculate_page();

            flip_page_flip();
            flip_drop_page();

            $("#epub_flipper").bind({ mousemove: function (event) { _flip_on_mouse_move(event) } });
            $("#epub_flipper").bind({ mousedown: function (event) { _flip_on_mouse_down(event) } });
            $("#epub_flipper").bind({ mouseup: function (event) { _flip_on_mouse_up(event) } });

            if (takePage == 1) page_forward();
            else if (takePage == -1) page_back();

            flip_calc_rel_mouse_pos();
            $("#epub_canvas_container").css("z-index", "1000");

            if (complete_callback != null) complete_callback();
        }
    }

    function flip_take_page() {
        flip_clear_images();
        if (takePage == 1) {
            if (flip_get_image(actPage)) $('#epub_page_background_left img').attr('src', flip_get_image(actPage).src);
            if (flip_get_image(actPage + 3)) $('#epub_page_background_right img').attr('src', flip_get_image(actPage + 3).src);

            imgFlipFrontRight = flip_get_image(actPage + 1);
            imgFlipBackRight = flip_get_image(actPage + 2);

        }
        if (takePage == -1) {
            if (flip_get_image(actPage + 1)) $('#epub_page_background_right img').attr('src', flip_get_image(actPage + 1).src);
            if (flip_get_image(actPage - 2)) $('#epub_page_background_left img').attr('src', flip_get_image(actPage - 2).src);

            imgFlipBackLeft = flip_get_image(actPage - 1);
            imgFlipFrontLeft = flip_get_image(actPage);
        }
    }

    function flip_drop_page() {
        flip_clear_images();

        if (dropPage == -1) $('#epub_page_background_left img').attr('src', flip_get_image(actPage).src);
        if (dropPage == 1) $('#epub_page_background_right img').attr('src', flip_get_image(actPage + 1).src);
    }

    function flip_get_image(page) {
        if (page < 0) page = 0;
        page = Math.floor(page / 2);

        var i = 0;
        var count = 0;

        for (i = 0; i < _cache_list.items.length; i++) {
            if (_cache_list.items[i].is_page) {
                if (page == count) break;
                else count++;
            }
        }

        if (i == _cache_list.items.length) return null;
        if (_cache_list.stepw == 0) return null;

        var img = _cache_list.items[i].image;
        if (img == null) img = new Image();

        _cache_list.items[i].image = img;
        var pre = epub_folder + '/' + oebps_folder;
        var href = get_step_path(pre, _cache_list.items[i].src, _cache_list.stepw);
        img.src = href;

        img.onload = function (event) {
            delete event.target;
        }

        return img;
    }

    function flip_get_images_length() {
        if (imageCount != 0) return imageCount;

        var i = 0;
        for (i = 0; i < _cache_list.items.length; i++)
            if (_cache_list.items[i].is_page) imageCount += 2;

        return imageCount;
    }

    function flip_clear_images() {
        var i = 0;
        for (i = 0; i < _cache_list.items.length; i++)
            delete _cache_list.items[i].image;
    }

    $.fn.epub = function (method) {
        if ($.epub.methods[method]) {
            return $.epub.methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        }
        else if (typeof method === 'object' || !method) {
            return $.epub.methods.init.apply(this, arguments);
        }
        else {
            $.error('Method ' + method + ' does not exist on jQuery.epub');
        }
    };

})(jQuery);

