Skip to content
Snippets Groups Projects
Commit e1483b4e authored by ale's avatar ale
Browse files

add online ePub reader using epub.js

parent 2a742483
No related branches found
No related tags found
No related merge requests found
body {
overflow: hidden;
}
#main {
position: absolute;
width: 100%;
height: 100%;
}
#area {
width: 80%;
height: 80%;
margin: 5% auto;
max-width: 1250px;
}
#area iframe {
border: none;
}
#prev {
left: 40px;
}
#next {
right: 40px;
}
.arrow {
position: absolute;
top: 50%;
margin-top: -32px;
font-size: 64px;
color: #e2e2e2;
font-family: arial, sans-serif;
font-weight: bold;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.arrow:hover {
color: #777;
}
.arrow:active {
color: #000;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -2,11 +2,10 @@
<html lang="en">
<head>
<title>LIBER</title>
<meta charset="utf-8">
<link rel="shortcut icon" href="/static/favicon.ico">
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/liber.css">
</head>
<body>
......
......@@ -41,6 +41,15 @@
</p>
{{end}}
{{if .HasEpub}}
<p>
<a class="btn btn-large btn-primary"
href="/read/{{.Book.Id}}/{{.EpubIndex}}">
Read Online
</a>
</p>
{{end}}
</div>
</div>
......
<!DOCTYPE html>
<html lang="en">
<head>
<title>
LIBER - "{{.Book.Metadata.Title}}"
</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="shortcut icon" href="/static/favicon.ico">
<link rel="stylesheet" href="/static/css/reader.css">
</head>
<body>
<div id="main">
<div id="prev" class="arrow"></div>
<div id="area"></div>
<div id="next" class="arrow"></div>
</div>
<script src="/static/js/jquery-2.1.1.min.js"></script>
<script src="/static/js/epub.min.js"></script>
<script src="/static/js/zip.min.js"></script>
<script>
EPUBJS.filePath = "/static/js/";
$(function() {
var Book = ePub("/dl/{{.Book.Id}}/{{.FileIndex}}",
{restore: true, contained: true});
$("#prev").click(function() { Book.prevPage(); });
$("#next").click(function() { Book.nextPage(); });
$(window).keydown(function(event) {
//console.log('keydown(): ' + event.which);
if (event.which == 33 || event.which == 37 || event.which == 38) {
Book.prevPage();
} else if (event.which == 32 || event.which == 34 || event.which == 39 || event.which == 40) {
Book.nextPage();
}
});
Book.renderTo("area");
});
</script>
</body>
</html>
......@@ -141,6 +141,38 @@ func (s *uiServer) withBook(f func(*Book, http.ResponseWriter, *http.Request)) h
})
}
func (s *uiServer) withFile(f func(*Book, *File, int, http.ResponseWriter, *http.Request)) http.HandlerFunc {
return s.withBook(func(book *Book, w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
fileIndex, err := strconv.Atoi(vars["fid"])
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
files, err := s.db.GetBookFiles(book.Id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if fileIndex < 0 || fileIndex >= len(files) {
http.NotFound(w, req)
return
}
f(book, files[fileIndex], fileIndex, w, req)
})
}
func findEpub(files []*File) int {
for i, f := range files {
if f.FileType == ".epub" {
return i
}
}
return -1
}
func (s *uiServer) handleShowBook(book *Book, w http.ResponseWriter, req *http.Request) {
files, err := s.db.GetBookFiles(book.Id)
if err != nil {
......@@ -149,6 +181,9 @@ func (s *uiServer) handleShowBook(book *Book, w http.ResponseWriter, req *http.R
return
}
// Only offer the online reader if we have an EPUB file.
epubIndex := findEpub(files)
// The book's Description, if present, should be rendered
// directly as HTML. So we deal with it separately.
ctx := struct {
......@@ -156,34 +191,43 @@ func (s *uiServer) handleShowBook(book *Book, w http.ResponseWriter, req *http.R
Book *Book
Files []*File
Description template.HTML
HasEpub bool
EpubIndex int
}{
Book: book,
Files: files,
Description: template.HTML(book.Metadata.Description),
HasEpub: (epubIndex >= 0),
EpubIndex: epubIndex,
}
render("book.html", w, &ctx)
}
func (s *uiServer) handleReadBook(book *Book, file *File, fileIndex int, w http.ResponseWriter, req *http.Request) {
if file.FileType != ".epub" {
http.NotFound(w, req)
return
}
ctx := struct {
Book *Book
File *File
FileIndex int
}{
Book: book,
File: file,
FileIndex: fileIndex,
}
render("reader.html", w, &ctx)
}
var contentTypeMap = map[string]string{
".epub": "application/epub+zip",
".mobi": "application/octet-stream",
".pdf": "application/pdf",
}
func (s *uiServer) handleDownloadBook(book *Book, w http.ResponseWriter, req *http.Request) {
idx, _ := strconv.Atoi(mux.Vars(req)["n"])
files, err := s.db.GetBookFiles(book.Id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if idx < 0 || idx >= len(files) {
http.NotFound(w, req)
return
}
file := files[idx]
func (s *uiServer) handleDownloadBook(book *Book, file *File, fileIndex int, w http.ResponseWriter, req *http.Request) {
f, err := s.storage.Open(file.Path)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
......@@ -289,7 +333,8 @@ func NewHttpServer(db *Database, storage, cache *FileStorage, addr string) *http
r.Handle("/book/cover/{id:[0-9]+}", uisrv.withBook(uisrv.handleShowCover))
r.Handle("/book/thumb/{id:[0-9]+}", uisrv.withBook(uisrv.handleShowThumbnail))
r.Handle("/book/{id:[0-9]+}", uisrv.withBook(uisrv.handleShowBook))
r.Handle("/dl/{id:[0-9]+}/{n:[0-9]+}", uisrv.withBook(uisrv.handleDownloadBook))
r.Handle("/read/{id:[0-9]+}/{fid:[0-9]+}", uisrv.withFile(uisrv.handleReadBook))
r.Handle("/dl/{id:[0-9]+}/{fid:[0-9]+}", uisrv.withFile(uisrv.handleDownloadBook))
r.HandleFunc("/suggest", uisrv.handleAutocomplete)
r.HandleFunc("/search", uisrv.handleSearch)
r.HandleFunc("/", uisrv.handleHome)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment