View Single Post
Old 03-12-2012, 03:28 PM   #8
SBT
Fanatic
SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.SBT ought to be getting tired of karma fortunes by now.
 
SBT's Avatar
 
Posts: 580
Karma: 810184
Join Date: Sep 2010
Location: Norway
Device: prs-t1, tablet, Nook Simple, assorted kindles, iPad
Thought I'd have a stab at making a dynamic web page capable of reading the content.xml/.opf/.ncx files, and then creating a toc and displaying the chapters. I've sort of succeeded; this page works in firefox, just save it at the same level as META-INF in a blown-up epub.
The akward issue is loading files dynamically into an iframe; security-conscious browsers are typically not fond of doing this for local files. Chrome should be able to do it if you use the --allow-file-access-from-files, but I can't get it to work. Firefox also behaves rather strangely; it reports an error for line 233, because the basis variable is undeclared, but if I declare it, it no longer reads loaded files properly.
I ran a bit amuck with css3, I'm afraid. Couldn't resist playing with all the nice new shiny bells and whistles.
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF8" />
<style type="text/css"> 
div#innh p:hover {
opacity:1;
background:yellow;
background: -moz-linear-gradient( left ,#ffff55, #995522);
}
div#spine {
    position:relative;
    left:2px;
    top:-4px;
    width:60px;
}
div#innh {
    opacity:0.95;
    border-style:solid double solid  none;
    border-color:#300808;
    border-width:4px 8px 4px;
    position:absolute;
    z-index:1;
    width:400px;
    height:823px;
    background:lightgreen;
    background: -moz-linear-gradient( left ,#9f6a46, #490d0d);
    color: -moz-linear-gradient( right ,#11aa55, #dfaa66);
	-moz-transform: scaleX(0.05);
	-moz-transition:-moz-transform 0.5s;
	-moz-transform-origin:left center;
    top:-384px;
    left:80px;
    overflow:hidden;
    border-radius:0 20px 20px 0;
}
div#innh p {
    margin:0 0 0 20px; 
    font-family:sans-serif;
    white-space:nowrap;
    overflow:hidden;
}
div#innh:hover{
	-moz-transform: scaleX(1);
    min-height:823px;
    height:auto;
}
div#chaps p{
    margin:0 0 0 0px; 
    font-family:sans-serif;
    white-space:nowrap;
    overflow:hidden;
}
div#chaps {
    opacity:0;
	-moz-transition:opacity 1s;
}
body {
    background:#dfaa66;
    min-height:600px;
    background: -moz-radial-gradient(300px 400px 65deg, ellipse cover, green 50%,blue 100%);
}
div#help{
    background:cyan;
    background: -moz-linear-gradient( top,#088 , cyan, cyan, cyan,white);
    border-color:darkblue ;
    border-style:none solid ridge solid;
    border-width: 8px 1px 8px 1px;
    position:absolute;
    height:0px;
    width:595px;
    top:18px;
    left:118px;
    overflow-y:auto;
    z-index:3;
	-moz-transition:height 0.6s;
	-moz-transform-origin:center top;
    border-radius:0 0 29px 29px ;
    font-family:sans-serif; 
    visibility:hidden;
}
div#help hr{ margin:0 15% ;}
div#help h2 {
    text-align:center; 
    margin:1em 0 0.5em 0 ;
    text-shadow:2px 2px 2px #044;
}
div#help p{margin:1em;}

.knapp{
    display:block;
    text-align:center;
    text-shadow:2px 2px 4px blue;
    line-height:24px;
    font-size:24px;
    color:darkblue;
    width:24px;
    height:24px;
    background:red;
    border-style:outset;
    border-width:3px;
    border-color:darkblue;
    background: -moz-radial-gradient(10px 12px 65deg, circle cover, #99f 5%,blue 80%);
    border-radius:6px;
}
div.knapp:hover {
    color:green;
}
div.knapp:active {
    border-style:inset;
    background: -moz-radial-gradient(10px 12px 65deg, circle cover, #448 5%,#00a 60%);
}

div.hjelp {
    width:70px;
    border-color:;
    color:#442;
    font-size:19px;
    margin:20px;
    text-shadow:1px 1px 3px maroon;
    background: -moz-radial-gradient(10px 12px 65deg, circle cover, #ff8 5%,#aa0 80%);
}
div.hjelp:active {
    background: -moz-radial-gradient(10px 12px 65deg, circle cover, #884 5%,#550 80%);
}   
iframe#ramme { 
    background:white;
    position:absolute;
    top:10px;
    left:108px;
    height:800px;
    width:615px;
    z-index:0;
    border-style:ridge double outset none;
    border-width:11px;
    border-color:brown;
    border-radius:0 9px 9px 0;
}

p#tittel {
    font-size:36px;
    font-style:italic;
    font-weight:bold;
    text-shadow:2px 2px 5px maroon;
    text-align:center;
    padding-bottom:14px;
    color:#a68120;
    border-color:#300808;
    margin-left:-358px;
    margin-top:393px;
    background:cyan;
    border-style:double solid none solid;
    border-width:5px 4px 2px 3px;
	-moz-transform: rotate(-90deg);
	-webkit-transform: rotate(-90deg);
	-o-transform: rotate(-90deg);
	-ms-transform: rotate(-90deg);
    background: -moz-linear-gradient( bottom,#9f6a46, #490d0d);
    width:824px;
    border-radius:20px 20px 0 0;
}

p.nav {
    letter-spacing:0.36em;
    text-shadow:1px 1px 3px #842;
    margin-top:2px;
    float:left;
    width:308px;
    text-align:center;
    font-family:sans-serif;
    font-weight:bold;
    font-style:italic;
    border-style:solid;
    color:maroon;
    background:yellow;
    position:absolute;
    top:828px;
}
p#next:active { background: -moz-linear-gradient( left ,#ff9f55, #300502); }
p#next:hover { color:#311; }
p#next {
    background: -moz-linear-gradient( left ,#ff9f55, #793522);
    border-bottom-right-radius:20px;
    border-top-right-radius:20px;
    left:420px;
}
p#prev:active { background: -moz-linear-gradient( right ,#ff9f55, #300502); }
p#prev:hover { color:#311; }
p#prev {
    background: -moz-linear-gradient( right ,#ff9f55, #793522);
    border-top-left-radius:20px;
    border-bottom-left-radius:20px;
    left:110px;
}
div#controls {
    position:absolute;
    top:30px;
    left:750px;
    width:110px;
    height:180px;
    border:ridge;
    border-color:green;
    border-radius:25px;
    margin-left:auto;
    margin-right:auto;
    background: -moz-radial-gradient(55px 90px 65deg, ellipse cover, #084 80%,lightgreen 100%);

}
</style>
<script type="text/javascript">
var fs=25
var opfFile=""
var ncxFile=""
var author=""
var title=""
var titlepage=""
var indx=0
var toggle=new Boolean()
var urlArr=new Array()
var titleArr=new Array()
var spineArr=new Array()
var tocTxtArr=new Array()
var tocUrlArr=new Array()
var toggleHelp=new Boolean()

function readFile(func, file) {
    document.getElementById("ramme").src=file
    var t=setTimeout(func+'();', 100)
}

function readContentXml() {
    opfFile=document.getElementById("ramme").contentDocument.getElementsByTagName("container")[0].getElementsByTagName("rootfiles")[0].getElementsByTagName("rootfile")[0].getAttribute("full-path")
    basis=opfFile.replace(/\/[^/]*$/,"/")
    readFile("readOpf", opfFile)
}

function readOpf() {
    var d=document.getElementById("ramme").contentDocument.getElementsByTagName("package")[0]
    var spineNodes=d.getElementsByTagName("spine")[0].getElementsByTagName("itemref")
    var manifestNodes=d.getElementsByTagName("manifest")[0].getElementsByTagName("item")
    var i=0
    var j=0
    for (j=0;j<spineNodes.length;j++) {
	for (i=0;i<manifestNodes.length;i++) {
	    if (manifestNodes[i].getAttribute("id")==spineNodes[j].getAttribute("idref")) {
		spineArr[j]=manifestNodes[i].getAttribute("href")
	    }
	}
    }
    for (i=0;i<manifestNodes.length;i++) {
	if (manifestNodes[i].getAttribute("id")==d.getElementsByTagName("spine")[0].getAttribute("toc")) { 
	    ncxFile=manifestNodes[i].getAttribute("href")
	}
    }
    titlepage=d.getElementsByTagName("guide")[0].getElementsByTagName("reference")[0].getAttribute("href")
    author=d.getElementsByTagName("metadata")[0].getElementsByTagName("dc:creator")[0].childNodes[0].nodeValue
    title=d.getElementsByTagName("metadata")[0].getElementsByTagName("dc:title")[0].childNodes[0].nodeValue
    readFile("readNcx", basis+ncxFile)
}

function readNcx() {
    var d=document.getElementById("ramme").contentDocument.getElementsByTagName("ncx")[0]
    var navPoints=d.getElementsByTagName("navMap")[0].getElementsByTagName("navPoint")
    for (i=0;i<navPoints.length;i++) {
	tocUrlArr[i]=navPoints[i].getElementsByTagName("content")[0].getAttribute("src")
	tocTxtArr[i]= navPoints[i].getElementsByTagName("text")[0].childNodes[0].nodeValue;
    }
    toggleToc()
    document.getElementById("ramme").src=basis+titlepage
    document.getElementById("ramme").style.visibility="visible"
    document.getElementById("tittel").innerHTML=author+": "+title
}

function fillToc() {
    var i=0
    var d=document.getElementById("chaps");
    d.innerHTML=""
    for (i=0; i<titleArr.length;i++) {
	d.innerHTML+="<p onClick=\"showChap("+i+")\" id=\""+i+"\">"+titleArr[i]+"</p>"
    }
}

function toggleToc() {
    var tmp=""
    toggle=document.getElementById("toggler").checked
    if (urlArr.length>0) tmp=urlArr[indx]
    if (toggle) {
	titleArr=spineArr
	urlArr=spineArr
    } 
    else {
	titleArr=tocTxtArr
	urlArr=tocUrlArr
    } 
    fillToc()
    if (tmp.length>0) {
	var i=0
	for (i=0;i<urlArr.length;i++) {
	    if (tmp==urlArr[i]) indx=i
	}
    }
    document.getElementById(indx).style.fontWeight="bold"
}
function hideToc() { 
    document.getElementById('innh').style.MozTransform='scaleX(0.05)' 
    document.getElementById('chaps').style.opacity=0
    document.getElementById('innh').style.height='823px'
}
function showToc() {
    if (toggleHelp) {
	document.getElementById('innh').style.MozTransform='scaleX(1)' 
	document.getElementById('innh').style.height='auto'
        document.getElementById('innh').style.minHeight='823px'
	document.getElementById('chaps').style.opacity=1
    }
}
function nextPrev(t) {
    indx+=t
    if (indx<0) {indx=0}
    if (indx>=urlArr.length) {indx=(urlArr.length-1)}
    showChap(indx)
}
function showHelp() {
if (toggleHelp) {
document.getElementById('help').style.visibility="visible"
document.getElementById('help').style.height='600px'
var t=setTimeout("document.getElementById('help').style.overflowY='auto'",1000)
}
else {
document.getElementById('help').style.overflowY='hidden'
document.getElementById('help').style.height='0px'
var t=setTimeout("document.getElementById('help').style.visibility='hidden'",1000)
}
toggleHelp=!toggleHelp
}

function scaleFont(t) {
    fs+=t
    document.getElementById("ramme").contentDocument.getElementsByTagName("body")[0].style.fontSize=fs+"px"
}

function showChap(n) {
    document.getElementById("ramme").src=basis+urlArr[n]
    var t=setTimeout('document.getElementById("ramme").contentDocument.getElementsByTagName("body")[0].style.fontSize=fs+"px"',50)
    var i=0
    for (i=0;i<urlArr.length;i++) {
	document.getElementById(i).style.fontWeight="normal"
    }
    document.getElementById(n).style.fontWeight="bold"
    indx=n
}

function init() {
    var msg="Only works with Firefox, I'm afraid..."
    document.getElementById("ramme").src="META-INF/container.xml"
    if (navigator.appVersion.indexOf("Chrome")>-1) {alert(msg+"\nYou could try starting chrome with --allow-file-access-from-local-files")}
    if (navigator.appName.indexOf("Opera")>-1) {alert(msg)}
    document.getElementById("ramme").style.visibility="hidden"
    readFile("readContentXml", "META-INF/container.xml")
    document.getElementById("ramme").src=basis+titlepage
}
</script>
</head>
<body onLoad="init()">
  <p onClick="nextPrev(-1)" class="nav" id="prev">Previous Chapter</p>
  <p onClick="nextPrev(1)" class="nav" id="next">Next Chapter</p>
  <iframe name="ramme" id="ramme" src="META-INF/container.xml" ></iframe>

  <div id="help" onClick="showHelp()">
    <h2>SBT's Attempt at a Viewer for Epub</h2>
   <hr>
    <ul>
      <li> Only works with Firefox when reading from files. If it is accessed through a web server, it should in theory work in all major browsers. Chrome shoul also work if started wit <tt>--allow-file-access-from-files</tt>, but I've not been successful.
      <li> Unzip your epub-file, and save this web page on the top level of the unzipped directory structure, i.e. on the same level as META-INF (not <em>in</em> META-INF)
      <li>Move the pointer over the book spine to see and select from list of contents.
      <li> Use buttons to increase/decrease font size.
      <li> If 'Spine' box is checked, the table of contents lists the xhtml files listed in the <tt>&lt;spine&gt;</tt> section of the OPF-manifest file.
      <li>Viewing window is 600x800, so this viewer can be handy when crafting an epub book to see how it looks on a standard e-reader screen.
      <li> Click inside the help window or on the help button to make this info go away.
    </ul>

<p> No copyright claimed, but an acknowledgement is always appreciated if you use this web page to create a derived work.</p>
    <div style="margin:2em 2em 1em 60%">
      <p>
	<em> SBT 
	  9. March 2012</em></p>
    </div>
  </div>
  <div id="spine" onMouseOut="hideToc()" onMouseOver="showToc()"><div> <p id="tittel">(Author:Title)</p> </div>

    <div  id="innh">     
      <div id="chaps">
      </div>
    </div>
  </div>
  <div id="controls">
    <div class="knapp hjelp" onClick="showHelp()" id="helpbt">Help</div>
    <div style="height:30px;margin-bottom:20px;">
      <div class="knapp" onClick="scaleFont(-1)" style="margin-left:22px;;float:left"><span style="font-size:10px;">A</span></div>

      <div class="knapp" onClick="scaleFont(1)"style="margin-right:22px;float:right"><span style="font-size:20px;">A</span> </div>
    </div>
    <form>
      <input type="checkbox" id="toggler" onClick="toggleToc()" value="true" ><span style="font-size:21px;color:lightgreen;text-shadow:2px 2px 2px #f44;}">Spine</span></input>
    </form>
</body>
</html>
SBT is offline   Reply With Quote