﻿var pageVerts, bookVerts
var dragTimerID
var cornervisible=0
var pagepos=0;
var mousePos
var currentMousePos
var pageLeftPath
var Images = new Array()
var gradientImages = new Array()
var autoturn = 0
var skiphistory=false
var orientation=0
var dragMode=0
var currentPagePos
var mouseClickOffset
var enumCatalogueState = {loading:0,ready:1,busy:3}
var catalogueState = enumCatalogueState['loading']
var ox = (pageWidth-1) / Math.sin(degrees * Math.PI / 180)
var oy = ox * Math.cos(degrees * Math.PI / 180)
        
function setOrientation(dir,v){
    //Flips all objects within book area
    //Polygon textures have to be swapped when this happens so no visible change occurs
    //on the screen
    
    orientation=dir 
    switch(renderMode){
    case enumRenderMode['vml']:
        document.getElementById('VMLPageImageLeft').src=Images[2+dir].src
        document.getElementById('VMLPageRightImageFill').src=Images[3-dir].src
        document.getElementById('VMLnextPageRightImageFill').src=Images[(1-dir)*4+(1-dir)].src
        document.getElementById('VMLnextPageLeftImage').src=Images[(1-dir)*4+dir].src
        document.getElementById('VMLPageLeftGradientFill').src= formatString(gradientUrlFormat,catalogueID,Number(dir))
        document.getElementById('VMLPageRightGradientFill').src= formatString(gradientUrlFormat,catalogueID,Number(!dir))

        document.getElementById('VMLPageImageLeft').style.flip= (dir==0?'':'x')
        document.getElementById('VMLnextPageLeftImage').style.flip= (dir==0?'':'x')
        document.getElementById('saucer').style.flip=(dir==0?'':'x')

        document.getElementById('VMLPageRightImageFill').position=(dir==0?'0,1':'1,1')
        document.getElementById('VMLnextPageRightImageFill').position=(dir==0?'1,1':'0,1')
        document.getElementById('VMLPageRightGradientFill').position=(dir==0?'0,1':'1,1')

        document.getElementById('VMLPageRightGradient').coordorigin=(dir==0?'1 1':'-1 1')
        document.getElementById('VMLPageLeftGradient').coordorigin=(dir==0?'1 1':'-1 1')
        
        document.getElementById('VMLPageImageRight').coordorigin=(dir==0?'1 1':'-1 1')
        document.getElementById('VMLnextPageRightImage').coordorigin=(dir==0?'1 1':'-1 1')
        document.getElementById('VMLShadow').coordorigin=(dir==0?'1 1':'-1 1')
        document.getElementById('VMLTopMask').coordorigin=(dir==0?'1 ':'-1 ') + (-topspace*2+1)
        
        if (dir==0){
            //forwards

            if (bookmode==1) {
                if (currentpage==0){
                    document.getElementById('VMLPageImageLeft').style.visibility='hidden'
                    document.getElementById('VMLPageLeftGradient').style.visibility='hidden'
                } else {
                    document.getElementById('VMLPageImageLeft').style.visibility='visible'
                    document.getElementById('VMLPageLeftGradient').style.visibility='visible'
                }
                if (currentpage==pageCount-2)
                    document.getElementById('VMLnextPageRightImageFill').type='solid'
                else
                    document.getElementById('VMLnextPageRightImageFill').type='tile'
                    
                if (currentpage==pageCount)
                    document.getElementById('VMLPageImageRight').style.visibility='hidden'
                else
                    document.getElementById('VMLPageImageRight').style.visibility='visible'
            }
            
        } else {
            //backwards

            if (bookmode==1) {
                if (currentpage==pageCount) {
                    document.getElementById('VMLPageImageLeft').style.visibility='hidden'
                    document.getElementById('VMLPageLeftGradient').style.visibility='hidden'
                } else {
                    document.getElementById('VMLPageImageLeft').style.visibility='visible'
                    document.getElementById('VMLPageLeftGradient').style.visibility='visible'
                }
                
                if (currentpage==2)
                    document.getElementById('VMLnextPageRightImageFill').type='solid'
                else
                    document.getElementById('VMLnextPageRightImageFill').type='tile'
                    
                if (currentpage==0){
                    document.getElementById('VMLPageImageRight').style.visibility='hidden'
                    document.getElementById('VMLPageRightGradient').style.visibility='hidden'
                }else{
                    document.getElementById('VMLPageImageRight').style.visibility='visible'
                    document.getElementById('VMLPageRightGradient').style.visibility='visible'
                }
            }
        }
    break;
    case enumRenderMode['svg']:
            
            document.getElementById('svgsaucer').setAttribute('transform', (dir==0?'':'translate('+2*pageWidth+',0) scale(-1,1)'))
            
            document.getElementById('SVGPageImageLeft').setAttributeNS('http://www.w3.org/1999/xlink','href', Images[2+dir].src)
            document.getElementById('SVGPageImageRight').setAttributeNS('http://www.w3.org/1999/xlink','href', Images[3-dir].src)
            document.getElementById('SVGnextPageLeftImage').setAttributeNS('http://www.w3.org/1999/xlink','href', Images[(1-dir)*4+dir].src)
            document.getElementById('SVGnextPageRightImage').setAttributeNS('http://www.w3.org/1999/xlink','href', Images[(1-dir)*4+(1-dir)].src)//
            
            document.getElementById('SVGPageRightGradient').setAttributeNS('http://www.w3.org/1999/xlink','href', gradientImages[Number(!dir)].src)
            document.getElementById('SVGPageLeftGradient').setAttributeNS('http://www.w3.org/1999/xlink','href', gradientImages[dir].src)
            
           
            document.getElementById('SVGPageImageLeft').setAttribute('transform', (dir==0?'':'translate('+pageWidth+',0) scale(-1,1)'))
            document.getElementById('SVGPageImageRight').setAttribute('transform', (dir==0?'':'translate('+pageWidth*3+',0) scale(-1,1)'))
            document.getElementById('SVGnextPageRightImage').setAttribute('transform', (dir==0?'':'translate('+pageWidth*3+',0) scale(-1,1)'))
            
            document.getElementById('SVGPageRightGradient').setAttribute('transform', (dir==0?'':'translate('+(pageWidth*2+gradientWidth)+',0) scale(-1,1)'))
            document.getElementById('SVGPageLeftGradient').setAttribute('transform', (dir==0?'':'translate('+(pageWidth*2-gradientWidth)+',0) scale(-1,1)'))
            
            document.getElementById('SVGPageImageRightPoly').setAttribute('transform', (dir==0?'':'translate('+pageWidth*3+',0) scale(-1,1)'))
            document.getElementById('SVGnextPageRightImagePoly').setAttribute('transform', (dir==0?'':'translate('+pageWidth*3+',0) scale(-1,1)'))
            document.getElementById('SVGNoNextPageRightImage').setAttribute('transform', (dir==0?'':'translate('+pageWidth*3+',0) scale(-1,1)'))
            document.getElementById('SVGTopMaskPoly').setAttribute('transform', (dir==0?'':'translate('+pageWidth*2+',0) scale(-1,1)'))
            document.getElementById('SVGPageRightGradientPoly').setAttribute('transform', (dir==0?'':'translate('+(pageWidth*2+gradientWidth)+',0) scale(-1,1)'))

        if (dir==0){
            //forwards

            if (bookmode==1) {
                if (currentpage==0){
                    document.getElementById('SVGPageImageLeft').style.visibility='hidden'
                    document.getElementById('SVGPageLeftGradient').style.visibility='hidden'
                } else {
                    document.getElementById('SVGPageImageLeft').style.visibility='visible'
                    document.getElementById('SVGPageLeftGradient').style.visibility='visible'
                }
                if (currentpage==pageCount-2) {
                    document.getElementById('SVGnextPageRightImage').style.visibility='hidden'
                    document.getElementById('SVGNoNextPageRightImage').style.visibility='visible'
                } else {
                    document.getElementById('SVGnextPageRightImage').style.visibility='visible'
                    document.getElementById('SVGNoNextPageRightImage').style.visibility='hidden'
                }
                               
                if (currentpage==pageCount)
                    document.getElementById('SVGPageImageRight').style.visibility='hidden'
                else
                    document.getElementById('SVGPageImageRight').style.visibility='visible'
            }
            
        } else {
            //backwards
            
            if (bookmode==1) {
                if (currentpage==pageCount) {
                    document.getElementById('SVGPageImageLeft').style.visibility='hidden'
                    document.getElementById('SVGPageLeftGradient').style.visibility='hidden'
                } else {
                    document.getElementById('SVGPageImageLeft').style.visibility='visible'
                    document.getElementById('SVGPageLeftGradient').style.visibility='visible'
                }
                if (currentpage==2) {
                    document.getElementById('SVGNoNextPageRightImage').style.visibility='visible'
                    document.getElementById('SVGnextPageRightImage').style.visibility='hidden'
                } else {
                    document.getElementById('SVGNoNextPageRightImage').style.visibility='hidden'
                    document.getElementById('SVGnextPageRightImage').style.visibility='visible'
                }
                
                if (currentpage==0){
                    document.getElementById('SVGPageImageRight').style.visibility='hidden'
                    document.getElementById('SVGPageRightGradient').style.visibility='hidden'
                }else{
                    document.getElementById('SVGPageImageRight').style.visibility='visible'
                    document.getElementById('SVGPageRightGradient').style.visibility='visible'
                }
            }
        }
    break;
    case enumRenderMode['basic']:
        document.getElementById('BasicPageImageLeft').src=Images[2].src
        document.getElementById('BasicPageImageRight').src=Images[3].src
        if (currentpage==0){
            document.getElementById('BasicPageImageLeft').style.visibility='hidden'
        }else{
            document.getElementById('BasicPageImageLeft').style.visibility='visible'
        }

        if (currentpage==pageCount){
            document.getElementById('BasicPageImageRight').style.visibility='hidden'
        }else{
            document.getElementById('BasicPageImageRight').style.visibility='visible'
        }
        
    break;
    }
}

function addPageHistory(n){
    //Checkpoints the book's state by changing the contents of a hidden iframe
    //This allows forwards and back buttons to work
    if (skiphistory) {skiphistory=false;return}
    
    try {
        var iframe = document.getElementById('historytracker')
        iframe.contentWindow.document.open()
            if (browser.browser=='Opera') {
            iframe.contentWindow.document.write('<script>function x(){parent.historyChanged()}</script>')
            iframe.contentWindow.document.write('<img src="javascript:location.href=\'javascript:x();\';" alt="" style="position:absolute;left:-1px;top:-1px;opacity:0;width:0px;height:0px;">')
        }
        
        iframe.contentWindow.document.write('<div id="lastpage">' + n + '</div>')
        iframe.contentWindow.document.close()
    } catch (e) {
        return
    }
}

function currentImageLoaded(){
   
    if (Images[2].reallycomplete && Images[3].reallycomplete) {

        if (autoturn!=0){
                for (var i = 0;i<Images.length;i++)
                    if (!Images[i].reallycomplete)
                        return
            catalogueState = enumCatalogueState['ready']
            if (autoturn==1) pageNext_buttonclick()
            if (autoturn==-1) pagePrev_buttonclick()

        } else {
            switch (renderMode){
            case enumRenderMode['vml']:
                document.getElementById('VMLPageImageLeft').src = Images[2].src
                document.getElementById('VMLPageRightImageFill').src = Images[3].src
            break;
            case enumRenderMode['svg']:
                document.getElementById('SVGPageImageLeft').setAttributeNS('http://www.w3.org/1999/xlink','href', Images[2].src)
                document.getElementById('SVGPageImageRight').setAttributeNS('http://www.w3.org/1999/xlink','href', Images[3].src)
            break;
            case enumRenderMode['basic']:
                document.getElementById('BasicPageImageLeft').src=Images[2].src
                document.getElementById('BasicPageImageRight').src=Images[3].src
            break;                
            }
        }
    }
}

function nextImageLoaded(){
    
    var dir = Number((this==Images[4]) || (this==Images[5]))
    
    if (Images[dir*4].reallycomplete && Images[dir*4+1].reallycomplete) {

        if (catalogueState == enumCatalogueState['busy']) catalogueState = enumCatalogueState['ready']
        
        if (autoturn==0)
            pageMouseMove(null,true)

        if (dir!=orientation){
            switch(renderMode){
            case enumRenderMode['vml']:
                document.getElementById('VMLnextPageLeftImage').src = Images[dir*4+(1-dir)].src
                document.getElementById('VMLnextPageRightImageFill').src = Images[dir*4+dir].src
                
            break;
            case enumRenderMode['svg']:
                document.getElementById('SVGnextPageLeftImage').setAttributeNS('http://www.w3.org/1999/xlink','href', Images[dir*4+(1-dir)].src)
                document.getElementById('SVGnextPageRightImage').setAttributeNS('http://www.w3.org/1999/xlink','href', Images[dir*4+dir].src)//
            break;
            }
            setPageTurnedPos(0)
        }

        if (autoturn!=0){
            for (var i = 0;i<Images.length;i++)
                if (!Images[i].reallycomplete)
                    return

            if (autoturn==1) pageNext_buttonclick()
            if (autoturn==-1) pagePrev_buttonclick()
        }
        
    }

}


function ImageLoaded(){
    //complete is set to true after the onload event fires, therefore
    //must define our own complete flag

    this.reallycomplete=true
    
    if ((this==Images[2]) || (this==Images[3]))
        currentImageLoaded.call(this)
    else if (this==Images[0] || this==Images[1] || this==Images[4] || this==Images[5])
        nextImageLoaded.call(this)
    
    for (var i = 0;i<Images.length;i++)
        if (!Images[i].reallycomplete)
            return

    if (renderMode==enumRenderMode['svg'])
        for (var i = 0;i<gradientImages.length;i++)
            if (!gradientImages[i].reallycomplete)
                return

    if (catalogueState == enumCatalogueState['loading']) {
        initComplete()
    }
}

function loadImages(imagesToLoad){
    //Given array of number (images to load) it loads
    //the images into an array. This is to preload images
    for (var i=0; i<imagesToLoad.length;i++)
        Images[imagesToLoad[i]] = new Image()
    
    for (var i=0; i<imagesToLoad.length;i++){
        var pageNo 
        
        if (bookmode==0) 
            pageNo = ((currentpage - 3 + imagesToLoad[i] + pageCount) % pageCount) + 1
        else
            pageNo = currentpage - 2 + imagesToLoad[i]
        
        if (pageNo > 0 && pageNo <= pageCount){
            Images[imagesToLoad[i]].onload = ImageLoaded
            Images[imagesToLoad[i]].src = formatString(imageUrlFormat,catalogueID,0, pageNo)
        } else 
            ImageLoaded.call(Images[imagesToLoad[i]])
    }
}

function vmlPageLoad(){

    //sets up vml offscreen buffer and sets up window resize event to keep image above book in place

    //Even though, due to the html markup, filled already has a value or 1, norton antivirus will prevent the whole site from working unless
    //this is set.

    document.getElementById('VMLTopMask').Filled = 1;

    document.getElementById('VMLTopMaskFill').src = cleanURL(getCurrentStyle(document.getElementById('topspace')).backgroundImage)

    var i = elementPos(document.getElementById('container'))[0] - elementPos(document.getElementById('topspace'))[0]

    document.getElementById('VMLTopMaskFill').origin=((1 + ((i-.5)/navWidth)) % 1) +', ' + (1 - (.5/navHeight))
    
    try {
        document.execCommand("BackgroundImageCache", false, true)
    } catch(e) {/*no problem*/}
    

}

function svgPageLoad(){

    document.getElementById('SVGTopMask').setAttributeNS('http://www.w3.org/1999/xlink','href', cleanURL(getCurrentStyle(document.getElementById('topspace')).backgroundImage))
    var i = elementPos(document.getElementById('container'))[0] - elementPos(document.getElementById('topspace'))[0]

    document.getElementById('SVGTopMask').setAttribute('x', -i)
    
    //This prevents firefox from trying to center something with an even width, in an odd number of pixels
    if (window.addEventListener && document.createEvent && window.dispatchEvent) {
        window.addEventListener('resize',  function() {document.documentElement.style.paddingRight=(document.documentElement.clientWidth & 1)?'1px':'0px'}, false)
        var evt = document.createEvent("HTMLEvents")
        evt.initEvent("resize", true, false)
        window.dispatchEvent(evt)
    }
    
    //Preload gradients - Required for firefox 3 to prevent flicker

    for (var i=0;i<2;i++)
        gradientImages[i]=new Image()
    
    for (var i=0;i<2;i++) {
        gradientImages[i].onload = ImageLoaded
        gradientImages[i].src=formatString(gradientUrlFormat,catalogueID,i) //calculate this first, otherwise firefox flickers
    }


}

function basicPageLoad(){
    //nothing to do here
}

function pageload(){

    bookVerts = new Object()
    
    bookVerts.topSpaceLeft=[0,-topspace]
    bookVerts.topSpaceRight=[bookWidth,-topspace]
    bookVerts.topLeft=[0,0]
    bookVerts.topRight=[bookWidth,0]
    bookVerts.bottomLeft=[0,bookheight]
    bookVerts.bottomRight=[bookWidth,bookheight]
    bookVerts.topMid=[pageWidth,0]
    bookVerts.bottomMid=[pageWidth,bookheight]


    if (renderMode==enumRenderMode['vml'])
        vmlPageLoad()
    else if (renderMode==enumRenderMode['svg'])
        svgPageLoad()
    else if (renderMode==enumRenderMode['basic']){
        basicPageLoad()
    }

    currentpage -= bookmode
    
    setPageTurnedPos(0)
    
    loadImages([0,1,2,3,4,5])

    initHotspots()

    if (browser.browser=='IE') addPageHistory(currentpage)  //Internet explorer cannot go back to an empty document
                                                            //but other browsers do
}

function initComplete(){
        setOrientation(orientation)
        
        if (renderMode==enumRenderMode['vml']) 
            document.getElementById('vmlbookdiv').style.display='block'
        else if (renderMode==enumRenderMode['svg']) 
            document.getElementById('svgelement').style.display='block'
        
            animate('LoadingFadeOut',100,0,300, 
                function(n){document.getElementById('loadingsplash').style.opacity=n/100;
                document.getElementById('loadingsplash').style.filter='alpha(opacity='+n+')'},function(){document.getElementById('loadingsplash').style.display='none'}, true)

        catalogueState = enumCatalogueState['ready']
        
}

function retreatPage(){
    Images[5]=Images[3]
    Images[4]=Images[2]
    Images[3]=Images[1]
    Images[2]=Images[0]
    currentpage = (currentpage - 3) % pageCount + 1  //allows book to wrap round
    setOrientation(currentpage==0?0:1)
    setPageTurnedPos(0)
    addPageHistory(currentpage)
    loadImages([0,1])
}


function advancePage(){
    document.getElementById('instructions').style.display='none'
    Images[0]=Images[2]
    Images[1]=Images[3]
    Images[2]=Images[4]
    Images[3]=Images[5]
    currentpage = (currentpage + 1) % pageCount + 1  //allows book to wrap round
    setOrientation(currentpage==pageCount?1:0)
    setPageTurnedPos(0)
    addPageHistory(currentpage)
    loadImages([4,5])
}

function pageNext_buttonclick(){
    if (catalogueState != enumCatalogueState['ready']) return
    autoturn=0
    if (orientation!=0) setOrientation(0)
    if ((bookmode==1) && (currentpage+2>pageCount)) return
    catalogueState = enumCatalogueState['busy']
    if (renderMode==enumRenderMode['basic']){
        advancePage();
    } else 
        animate ('PageAnimation',pagepos,100,pageTurnTime, function(n) {setPageTurnedPos(n)}, advancePage, false)
    return false;
}

function pagePrev_buttonclick(){

    if (catalogueState != enumCatalogueState['ready']) return
    autoturn=0
    if ((bookmode==1) && (currentpage-2<0)) return
    if (orientation!=1) setOrientation(1)
    catalogueState = enumCatalogueState['busy']
    if (renderMode==enumRenderMode['basic']){
        retreatPage();
    } else 
        animate ('PageAnimation',pagepos,100,pageTurnTime, function(n) {setPageTurnedPos(n)}, retreatPage, false)
}


function setPageTurnedPos(n){
    if (n>100) {n=100}
    pagepos=n

    x = ox * Math.sin((n / 100 - 0.5) * degrees * Math.PI / 90) + pageWidth
    y = ox * Math.cos((n / 100 - 0.5) * degrees * Math.PI / 90) - oy

    var nextimgx = 2 * pageWidth - x-1
    var nextimgy = bookheight - y -1

    if (orientation==1) nextimgx=bookWidth-nextimgx
    
    setPageTurned(nextimgx,nextimgy)
}


function setPageTurned(nextimgx,nextimgy){

    nextimgx=Math.round(nextimgx)
    nextimgy=Math.round(nextimgy)

    pageVerts = new Object()

    if (orientation==1) nextimgx=bookWidth-nextimgx

    var pageAngle=2*calcAngle(nextimgx,nextimgy,bookWidth,bookheight)-3*Math.PI // this angle ensures a line of symmetry
          
    //constrain page so that is doesn't 'tear off'
   
    if (Math.sqrt(Math.pow(nextimgx-pageWidth,2)+Math.pow(nextimgy-bookheight,2))>pageWidth) {
        var n=calcAngle(pageWidth,bookheight,nextimgx,nextimgy)-Math.PI/2
        pageAngle=2*calcAngle(pageWidth-pageWidth*Math.cos(n),bookheight-pageWidth*Math.sin(n),bookWidth,bookheight)-3*Math.PI
        nextimgx=pageWidth-pageWidth*Math.cos(n)
        nextimgy=bookheight-pageWidth*Math.sin(n)
    }

    if (nextimgx + bookheight * Math.sin(pageAngle)<bookWidth && Math.sqrt(Math.pow(nextimgx-pageWidth + bookheight * Math.sin(pageAngle),2)+Math.pow(nextimgy -  bookheight * Math.cos(pageAngle),2))>pageWidth) {
        var n=calcAngle(nextimgx + bookheight * Math.sin(pageAngle),nextimgy -  bookheight * Math.cos(pageAngle),pageWidth,0)
        pageAngle=2*calcAngle(pageWidth + pageWidth*Math.sin(n),-pageWidth*Math.cos(n),bookWidth,0)-3*Math.PI

        if (pageAngle/2+Math.PI<calcAngle(bookVerts.bottomRight[0],bookVerts.bottomRight[1],bookVerts.topMid[0],bookVerts.topMid[1])) {
            pageAngle=(calcAngle(bookVerts.bottomRight[0],bookVerts.bottomRight[1],bookVerts.topMid[0],bookVerts.topMid[1])-Math.PI)*2
            n=pageAngle+3*Math.PI/2+.0001 //Seems to be a slight error (precision?) in calculations but this is on the safe side
        }
        
        nextimgx=pageWidth + pageWidth*Math.sin(n) - bookheight * Math.sin(pageAngle)
        nextimgy= -pageWidth*Math.cos(n) +  bookheight * Math.cos(pageAngle)
    }
  
    pageVerts.bottomLeft = [nextimgx,nextimgy]
    pageVerts.bottomRight = [nextimgx + pageWidth * Math.cos(pageAngle),nextimgy + pageWidth * Math.sin(pageAngle)]
    pageVerts.topLeft = [nextimgx + bookheight * Math.sin(pageAngle), nextimgy -  bookheight * Math.cos(pageAngle)]
    pageVerts.topRight = [nextimgx + bookheight * Math.sin(pageAngle) + pageWidth * Math.cos(pageAngle),nextimgy - bookheight * Math.cos(pageAngle) + pageWidth * Math.sin(pageAngle)]

    
    var shadowPath = new pathBuilder()
    var maskPath = new pathBuilder()
    var currentPagePath = new pathBuilder()
    var nextPagePath = new pathBuilder()
    pageLeftPath = new pathBuilder()

    var intersectionLeftPageTopBook = lineIntersect(pageVerts.bottomLeft, pageVerts.topLeft, bookVerts.topLeft, bookVerts.topRight)
    var intersectionLeftPageRightBook = lineIntersect(pageVerts.topLeft, pageVerts.bottomLeft, bookVerts.topRight, bookVerts.bottomRight)
    var intersectionTopPageTopBook = lineIntersect(pageVerts.topLeft, pageVerts.topRight, bookVerts.topLeft,bookVerts.topRight)
    var intersectionLeftPageBottomBook = lineIntersect(pageVerts.bottomLeft, pageVerts.topLeft, bookVerts.bottomLeft,bookVerts.bottomRight)
    var intersectionLeftPageMidBook = lineIntersect(pageVerts.bottomLeft, pageVerts.topLeft, bookVerts.bottomMid,bookVerts.topMid)
    var intersectionBottomPageMidBook = lineIntersect(pageVerts.bottomLeft, pageVerts.bottomRight, bookVerts.bottomMid,bookVerts.topMid)
    var intersectionTopPageMidBook = lineIntersect(pageVerts.topLeft, pageVerts.topRight, bookVerts.bottomMid,bookVerts.topMid)
    var intersectionBottomPageTopBook = lineIntersect(pageVerts.bottomLeft, pageVerts.bottomRight, bookVerts.topLeft,bookVerts.topRight)
    var intersectionLeftPageLeftTopSpace = lineIntersect(pageVerts.bottomLeft, pageVerts.topLeft, bookVerts.topLeft, bookVerts.topSpaceLeft)
    //The next 2 are not strictly speaking intersections the whole of the time    
    var intersectionBottomPageBottomBook = [Math.round(bookVerts.bottomRight[0]-Math.sqrt(Math.pow(nextimgx-bookVerts.bottomRight[0],2)+Math.pow(nextimgy-bookVerts.bottomRight[1],2))/2/Math.cos(pageAngle/2)),bookVerts.bottomRight[1]]
    var intersectionTopPageTopBook = [Math.round(bookVerts.bottomRight[0]-Math.sqrt(Math.pow(pageVerts.topLeft[0]-bookVerts.topRight[0],2)+Math.pow(pageVerts.topLeft[1]-bookVerts.topRight[1],2))/2/Math.cos(pageAngle/2)),bookVerts.topRight[1]]
    
    if (pageVerts.topLeft[0]>bookVerts.topRight[0]) intersectionTopPageTopBook=null

    //next page
        
    if (intersectionBottomPageBottomBook) {
        nextPagePath.addVert(intersectionBottomPageBottomBook)
        nextPagePath.addVert(bookVerts.bottomRight)
        }
    else {
        nextPagePath.addVert(intersectionLeftPageRightBook)
    }    
    
    if (intersectionTopPageTopBook) {
        nextPagePath.addVert(bookVerts.topRight)
        nextPagePath.addVert(intersectionTopPageTopBook)
        }
    else {
        nextPagePath.addVert(intersectionLeftPageRightBook)
    }    
   
    //current page
    
    if (intersectionLeftPageRightBook){
        currentPagePath.addVert(intersectionLeftPageRightBook)
        currentPagePath.addVert(bookVerts.topRight)
    } else if (intersectionLeftPageTopBook)
        currentPagePath.addVert(intersectionLeftPageTopBook)
    else 
        currentPagePath.addVert(intersectionTopPageTopBook)

    
    currentPagePath.addVert(bookVerts.topLeft)
    currentPagePath.addVert(bookVerts.bottomLeft)

    if (intersectionLeftPageBottomBook)
        currentPagePath.addVert(intersectionLeftPageBottomBook)
    else if (intersectionBottomPageBottomBook)
        currentPagePath.addVert(intersectionBottomPageBottomBook)
    else {
        currentPagePath.addVert(intersectionLeftPageRightBook)
        currentPagePath.addVert(bookVerts.bottomRight)
        }

    if (pageAngle>0)
        currentPagePath.addVert(pageVerts.bottomLeft)
    else
        currentPagePath.addVert(pageVerts.topLeft)
        
    currentPagePath.points = clipPoly(currentPagePath.points, bookVerts.topMid, bookVerts.bottomRight)
   
    //top section
    
    maskPath.addVert(bookVerts.topLeft)
    maskPath.addVert(bookVerts.topSpaceLeft)
    maskPath.addVert(bookVerts.topSpaceRight)
    
    if (intersectionLeftPageLeftTopSpace)
        maskPath.addVert(intersectionLeftPageLeftTopSpace)
    else {
        maskPath.addVert(bookVerts.topRight)
    }

    if (intersectionTopPageTopBook && pageVerts.topLeft[1] < 0){
        maskPath.addVert(intersectionTopPageTopBook)
        maskPath.addVert(pageVerts.topLeft)
    }
    
    if (intersectionLeftPageTopBook)        
        maskPath.addVert(intersectionLeftPageTopBook)
    
    if (intersectionBottomPageTopBook && pageVerts.bottomLeft[1] < 0) {
        maskPath.addVert(pageVerts.bottomLeft)
        maskPath.addVert(intersectionBottomPageTopBook)
    }
    
    maskPath.points = clipPoly(maskPath.points, bookVerts.topSpaceLeft, bookVerts.topRight)

    //shadow path

    if (intersectionBottomPageBottomBook) {
        shadowPath.addVert(intersectionBottomPageBottomBook)
        shadowPath.addVert([intersectionBottomPageBottomBook[0]+30,intersectionBottomPageBottomBook[1]])
        }
    else {
        shadowPath.addVert(intersectionLeftPageRightBook)
        shadowPath.addVert([intersectionLeftPageRightBook[0]+30,intersectionLeftPageRightBook[1]])
    }    

    if (intersectionTopPageTopBook) {
        shadowPath.addVert([intersectionTopPageTopBook[0]+15,intersectionTopPageTopBook[1]])
        shadowPath.addVert(intersectionTopPageTopBook)
        }
    else {
        shadowPath.addVert(intersectionLeftPageRightBook)
    }    
        
    n=100*Math.sqrt(Math.pow((pageVerts.bottomLeft[0]+pageVerts.topLeft[0]-bookVerts.bottomRight[0]-bookVerts.topRight[0])/2,2)+Math.pow((pageVerts.bottomLeft[1]+pageVerts.topLeft[1]-bookVerts.bottomRight[1]-bookVerts.topRight[1])/2,2))/bookWidth
    
    if (renderMode==enumRenderMode['vml']) {
        document.getElementById('VMLnextPageLeftImage').style.left= Math.floor((nextimgx + pageVerts.topRight[0]-pageWidth)/2)  +'px' 
        document.getElementById('VMLnextPageLeftImage').style.top= Math.floor((nextimgy + pageVerts.topRight[1]-bookheight)/2) + 'px' 
        document.getElementById('VMLnextPageLeftImage').style.rotation = (orientation==0 ? 1:-1) * pageAngle * 180 / Math.PI +'deg'

        ncpx=Math.ceil(Math.sin(pageAngle / 2)*(gradientHeight/2)-Math.cos(pageAngle / 2)*(gradientWidth/2)-(gradientWidth/2) + orientation)
        ncpy=Math.ceil(-Math.cos(pageAngle / 2)*(gradientHeight/2)-Math.sin(pageAngle / 2)*(gradientWidth/2)-(gradientHeight/2))
       
        document.getElementById('VMLnextPageLeftGradient').style.left=Math.floor(intersectionBottomPageBottomBook[0] + ncpx) + 'px' 
        document.getElementById('VMLnextPageLeftGradient').style.top=Math.floor(bookheight + ncpy)  + 'px' 
        document.getElementById('VMLnextPageLeftGradient').style.rotation = pageAngle * 90 / Math.PI+'deg';
        
        if (n>90)
            document.getElementById('VMLShadowFill').opacity= (100-n)*shadowopacity /10
        else 
            document.getElementById('VMLShadowFill').opacity = shadowopacity 
        document.getElementById('VMLShadow').path=shadowPath
        document.getElementById('VMLnextPageRightImage').path=nextPagePath
        document.getElementById('VMLPageImageRight').path=currentPagePath

	document.getElementById('VMLPageRightImageFill').position.y = (pageAngle < 0?0:1)

        if (((currentpage != 2 && orientation==1) || (currentpage != pageCount-2 && orientation==0)) && currentPagePath.points.length > 0) {
            currentPagePath.points[currentPagePath.points.length]=currentPagePath.points[0]
            currentPagePath.points=currentPagePath.points.concat(nextPagePath.points)
            currentPagePath.points[currentPagePath.points.length]=nextPagePath.points[0]
        }

	currentPagePath.points = clipPoly(currentPagePath.points, bookVerts.topMid, [bookVerts.bottomMid[0]+gradientWidth, bookVerts.bottomMid[1]])

        document.getElementById('VMLPageRightGradient').path=currentPagePath
        document.getElementById('VMLTopMask').path=maskPath
        
        document.getElementById('saucer').style.flip=(orientation==0?'':'x')  //This, incredibly prevents flicker
        
    } else if (renderMode==enumRenderMode['svg']){
        document.getElementById('SVGnextPageLeftImage').setAttribute('x', Math.round(nextimgx+ bookheight * Math.sin(pageAngle)))
        document.getElementById('SVGnextPageLeftImage').setAttribute('y',Math.round(nextimgy- bookheight * Math.cos(pageAngle)))
        
        if (orientation==0)
            document.getElementById('SVGnextPageLeftImage').setAttribute('transform', 'rotate(' + pageAngle * 180 / Math.PI +' ' + Math.round(nextimgx+ bookheight * Math.sin(pageAngle)) +' ' + Math.round(nextimgy-bookheight * Math.cos(pageAngle)) + ')' )
        else
            document.getElementById('SVGnextPageLeftImage').setAttribute('transform', 'rotate(' + pageAngle * 180 / Math.PI +' ' + Math.round(nextimgx+ bookheight * Math.sin(pageAngle)) +' ' + Math.round(nextimgy-bookheight * Math.cos(pageAngle)) + ') translate('+Math.round(pageWidth+2*(nextimgx+ bookheight * Math.sin(pageAngle)))+',0) scale(-1 1)' )

        document.getElementById('SVGnextPageLeftGradient').setAttribute('x',Math.round(intersectionBottomPageBottomBook[0]-gradientWidth)) 
        document.getElementById('SVGnextPageLeftGradient').setAttribute('y',bookheight-gradientHeight)
        document.getElementById('SVGnextPageLeftGradient').setAttribute('transform', 'rotate('+ pageAngle * 90 /Math.PI + ' ' + Math.round(intersectionBottomPageBottomBook[0]) + ' ' + bookheight + ')')
    
        if (n>90)
            document.getElementById('SVGShadow').setAttribute('fill-opacity', (100-n)*shadowopacity /10)
        else
            document.getElementById('SVGShadow').setAttribute('fill-opacity', shadowopacity)
        document.getElementById('SVGShadow').setAttribute('points',shadowPath)
        document.getElementById('SVGnextPageRightImagePoly').setAttribute('points',nextPagePath)
        document.getElementById('SVGPageImageRightPoly').setAttribute('points',currentPagePath)

        
        
        if ((currentpage != 2 && orientation==1) || (currentpage != pageCount-2 && orientation==0)) {
            if (currentPagePath.points.length>0) {
                currentPagePath.points[currentPagePath.points.length]=currentPagePath.points[0]
                currentPagePath.points=currentPagePath.points.concat(nextPagePath.points)
                currentPagePath.points[currentPagePath.points.length]=nextPagePath.points[0]
            } else {
                currentPagePath = nextPagePath
            }
        }
        
        document.getElementById('SVGPageRightGradientPoly').setAttribute('points',currentPagePath)
        document.getElementById('SVGTopMaskPoly').setAttribute('points',maskPath)
    }
}

function pageMouseMove(e, reset){
    if (bookmode == 0 && pageCount < 3) return; 
    if (catalogueState != enumCatalogueState['ready'] ) {return}

    e = window.event || e
    
    if (e) currentMousePos = cursorPos(e)
    if (!currentMousePos) return
    
    var pageElementPosition = elementPos(document.getElementById('container'))
       
    var x = currentMousePos[0]-pageElementPosition[0]
    var y = currentMousePos[1]-pageElementPosition[1]
    
    if ((x >= 0) && (x < bookWidth) && (y >= 0) && (y < bookheight)) {
        if (x >= pageWidth){
            //its on the right
            if (currentpage != pageCount && Images[4].reallycomplete && Images[5].reallycomplete){
                if ((cornervisible != 1) || reset) {
                    if (cornervisible==0){
                        setOrientation(0)
                        animate ('PageAnimation',pagepos,10,200, function(n) {setPageTurnedPos(n)}, function(n){}, true)    
                    } else {
                        animate ('PageAnimation',pagepos,0,200, function(n) {setPageTurnedPos(n)}, function(n){setOrientation(0);animate ('PageAnimation',0,10,200, function(n) {setPageTurnedPos(n)}, function(n){}, true)}, true)
                    }
                    cornervisible = 1
                }
                return
             }
        } else {
            //its on the left
            if (currentpage != 0 && Images[0].reallycomplete && Images[1].reallycomplete) {
                if ((cornervisible != -1) || reset) {
                    if (cornervisible==0){
                        setOrientation(1)
                        animate ('PageAnimation',pagepos,10,200, function(n) {setPageTurnedPos(n)}, function(n){}, true)
                    } else {
                        animate ('PageAnimation',pagepos,0,200, function(n) {setPageTurnedPos(n)}, function(n){setOrientation(1);animate ('PageAnimation',pagepos,10,200, function(n) {setPageTurnedPos(n)}, function(n){}, true)}, true)
                    }
                    cornervisible = -1
                }
                return
            }
        }
    } 

    if ((cornervisible !=0) || reset) {
        cornervisible=0
        animate ('PageAnimation',pagepos,0,200, function(n) {setPageTurnedPos(n)}, function(n){}, true)
    }
}

function nextpagemousedown(e){
    if (bookmode == 0 && pageCount < 3) return; 
    if (catalogueState != enumCatalogueState['ready']) return
    
    //if (dragTimerID)
    //    return //drag already initiated, must be second click
    
    e = e || window.event
   
    if (e.preventDefault)
        e.preventDefault() //Stop things from being selected

    dragMode=0

    mousePos=cursorPos(e)

    mouseClickOffset=[mousePos[0]-orientation*bookWidth+((orientation*2)-1) * pageVerts.bottomLeft[0], mousePos[1]-pageVerts.bottomLeft[1]-topspace]
    
    currentPagePos=[currentMousePos[0]-mouseClickOffset[0],currentMousePos[1]-(mouseClickOffset[1]+topspace)]
    
    catalogueState = enumCatalogueState['busy']
    
    dragTimerID = setInterval('updatePagePos()',animinterval)
        
}

function updatePagePos(){
    if (dragMode==1) {
        
        var desiredPos = [currentMousePos[0]-mouseClickOffset[0],currentMousePos[1]-(mouseClickOffset[1]+topspace)]
	    currentPagePos=[currentPagePos[0]-(currentPagePos[0]-desiredPos[0])/2,currentPagePos[1]-(currentPagePos[1]-desiredPos[1])/2]
        setPageTurned(currentPagePos[0],currentPagePos[1])
    }
}


function bodyMouseMove(e){

    e = e || window.event
    currentMousePos = cursorPos(e)
    
    if ('PageAnimation' in animationArray) return
    if (mousePos) {
        if (Math.pow(currentMousePos[0]-mousePos[0],2)+Math.pow(currentMousePos[1]-mousePos[1],2) > 9) dragMode=1
      
        if (browser.browser=='Firefox' && dragTimerID && dragMode==1) {
            //firefox 2.0 ignores timers whilst mouse is being moved, so timer can't be used
            updatePagePos()
        }
    }
}

function bodyMouseUp(e){
    if (!dragTimerID) return

    clearInterval(dragTimerID)

    catalogueState = enumCatalogueState['ready']
    dragTimerID=null
    e = e || window.event
        
    if (dragMode==1) {
    
        var i = (pageVerts.bottomLeft[0]+pageVerts.topLeft[0])/2-pageWidth
       
        tmpx=orientation*bookWidth-((orientation*2)-1) *pageVerts.bottomLeft[0]
        tmpy=pageVerts.bottomLeft[1]

        if (orientation==0)
            if (i<0) // more than halfway
                animate ('PageAnimation',0,1,200, function(n) {setPageTurned((1-n)*tmpx+n*bookVerts.bottomLeft[0],(1-n)*tmpy+n*bookVerts.bottomLeft[1])}, advancePage, false)
            else 
                animate ('PageAnimation',0,1,200, function(n) {setPageTurned((1-n)*tmpx+n*bookVerts.bottomRight[0],(1-n)*tmpy+n*bookVerts.bottomRight[1])}, function(){pagepos=0;cornervisible=0;pageMouseMove(null,true)}, false)
        else
            if (i<0) // more than halfway
                animate ('PageAnimation',0,1,200, function(n) {setPageTurned((1-n)*tmpx+n*bookVerts.bottomRight[0],(1-n)*tmpy+n*bookVerts.bottomRight[1])}, retreatPage, false)
            else 
                animate ('PageAnimation',0,1,200, function(n) {setPageTurned((1-n)*tmpx+n*bookVerts.bottomLeft[0],(1-n)*tmpy+n*bookVerts.bottomLeft[1])}, function(){pagepos=0;cornervisible=0;pageMouseMove(null,true)}, false)
    } else {
        if (orientation==0) 
            pageNext_buttonclick() 
        else 
            pagePrev_buttonclick()
    }
    return false
}


function safariEventCancel(event){
    //To fix a bug in safari
    event.stopPropagation()
}

function bodyMouseDown(e){
    e = e || window.event
    if (e.preventDefault)
        e.preventDefault()
    
    if (browser.browser.toLowerCase().indexOf('safari') != -1) {
        //Bug in safari 3.1. Should be fixed in future versions because I submitted a bug and it
        //appears to have been fixed
        
        if (document.getElementById('ZoomPanel').style.display == 'block') return;
        
        var pageElementPosition = elementPos(document.getElementById('container'))
        currentMousePos = cursorPos(e)
    
        var x = orientation * bookWidth  -(orientation*2-1) * (currentMousePos[0]-pageElementPosition[0])
        var y = currentMousePos[1]-pageElementPosition[1]
        document.getElementById('container').removeEventListener('click', safariEventCancel,true)
        if (!ptInRegion([bookVerts.topLeft,bookVerts.topRight,bookVerts.bottomRight,bookVerts.bottomLeft],[x,y])) return;
        if (ptInRegion([bookVerts.topLeft,bookVerts.topMid,bookVerts.bottomMid,bookVerts.bottomLeft],[x,y])) return;
        if (ptInRegion(pointArrayFromString(document.getElementById('SVGPageImageRightPoly').getAttribute('points')),[x,y])) return;
        
        document.getElementById('container').addEventListener('click', safariEventCancel,true)

        if (ptInRegion(pointArrayFromString(document.getElementById('SVGnextPageRightImagePoly').getAttribute('points')),[x,y])) return;        
        
        nextpagemousedown(e);
    }
}


function gotoPage(n){
    n = Math.floor(n  / 2) * 2
    if (n != currentpage){
        if ((currentpage==pageCount || n < currentpage) && (bookmode==1)) {//we'll do a previous page click for this
            catalogueState = enumCatalogueState['busy']
            setOrientation(1)
            currentpage = ((n + 1 + pageCount) % pageCount) + 1
            
            if (renderMode==enumRenderMode['vml']){
                if (currentpage==2)
                    document.getElementById('VMLnextPageRightImageFill').type='solid'
                else
                    document.getElementById('VMLnextPageRightImageFill').type='tile'
            }else if (renderMode==enumRenderMode['svg']){
                if (currentpage==2) {
                    document.getElementById('SVGNoNextPageRightImage').style.visibility='visible'
                    document.getElementById('SVGnextPageRightImage').style.visibility='hidden'
                } else {
                    document.getElementById('SVGNoNextPageRightImage').style.visibility='hidden'
                    document.getElementById('SVGnextPageRightImage').style.visibility='visible'
                }
            }
            
            autoturn=-1
            loadImages([0,1,2,3])
        } else {
            
            setOrientation(0)
            catalogueState = enumCatalogueState['busy']
            currentpage=((n - 2 + pageCount) % pageCount) 
            
            if (renderMode==enumRenderMode['vml']){
                if (currentpage==pageCount-2)
                    document.getElementById('VMLnextPageRightImageFill').type='solid'
                else
                    document.getElementById('VMLnextPageRightImageFill').type='tile'
            } else if (renderMode==enumRenderMode['svg']){
                if (currentpage==pageCount-2) {
                    document.getElementById('SVGnextPageRightImage').style.visibility='hidden'
                    document.getElementById('SVGNoNextPageRightImage').style.visibility='visible'
                } else {
                    document.getElementById('SVGnextPageRightImage').style.visibility='visible'
                    document.getElementById('SVGNoNextPageRightImage').style.visibility='hidden'
                }
            }
            
            autoturn=1
            loadImages([2,3,4,5])
        }
    } else {
        skiphistory=false;
    }
}

function historyChanged(){
    if (catalogueState != enumCatalogueState['ready']) {return}

    var iframe = document.getElementById('historytracker')
    var pagediv = iframe.contentWindow.document.getElementById('lastpage')
    if (pagediv){
        if (parseInt(pagediv.innerHTML) != currentpage){
            skiphistory=true
            if (('PageAnimation' in animationArray)) delete animationArray['PageAnimation']
            gotoPage(parseInt(pagediv.innerHTML),true)
        }
    } else {
        if (currentpage-Math.floor(currentpage/2)*2 != currentpage) {
            skiphistory=true
            if (('PageAnimation' in animationArray)) delete animationArray['PageAnimation']
            gotoPage(currentpage-Math.floor(currentpage/2)*2)
        }
    }
}

function toggleCategories(){
    if (document.getElementById('categoriesPanel').style.display == 'block')
        closeCategories()
    else
        openCategories()
}

function openCategories() {
    var categories = document.getElementById('categoriesPanel')
    categories.style.filter='alpha(opacity=0)'
    categories.style.opacity='0'
    categories.style.display = 'block'
    animate('CategoriesFade',0,100,300,function(n) {document.getElementById('categoriesPanel').style.opacity=n/100;document.getElementById('categoriesPanel').style.filter='alpha(opacity='+n +')'}, function(){}, true)
    document.getElementById('goto').className = 'navlinks goto gotoselected'
}

function closeCategories() {
    var categories = document.getElementById('categoriesPanel')
    categories.style.display = 'none'
    document.getElementById('goto').className = 'navlinks goto'
}

function highlightShopFromHome(){
    var hlDiv = document.getElementById('shopfromhome')
    var strBackgroundColour = getCurrentStyle(hlDiv).backgroundColor
    var fromRGB = new Array()
    
    if (strBackgroundColour.substr(0,3) == 'rgb'){
        matches = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(strBackgroundColour)
        fromRGB.push(parseInt(matches[1]))
        fromRGB.push(parseInt(matches[2]))
        fromRGB.push(parseInt(matches[3]))
    } else if (strBackgroundColour.charAt(0)=='#') {
        matches = /^#(\w{2})(\w{2})(\w{2})$/.exec(strBackgroundColour)
        fromRGB.push(parseInt(matches[1],16))
        fromRGB.push(parseInt(matches[2],16))
        fromRGB.push(parseInt(matches[3],16))
    } else 
        return //unable to parse colour so do nothing
    
    toRGB = [255,255,140] //yellow
    //toRGB = [Math.random()*255,Math.random()*255,Math.random()*255] //yellow
    
    animate('ShopFromHomeHighLight',0,1,2000,function(n) {
        var pos=Math.abs((n-Math.floor(n))*2-1)
        var currRGB = new Array()
        currRGB=[Math.round(pos*fromRGB[0]+(1-pos)*toRGB[0]),
                Math.round(pos*fromRGB[1]+(1-pos)*toRGB[1]),
                Math.round(pos*fromRGB[2]+(1-pos)*toRGB[2])]

        document.getElementById('shopfromhome').style.backgroundColor = 'rgb('+currRGB+')'
    }, function(){}, false)    
    
}

