Files
calibre-web/cps/templates/read.html
T
Ross Williams 22a93a28e2 Refactor epub reader progress calculation
The code in epub-progress.js was causing the epub file to be loaded
twice over the network, because it created a second instance of the
epub.js library. I moved all the progress percentage display code into
epub.js. Only the locationchange polyfill code was left in the separate
file, renamed to locationchange-polyfill.js.

I rewrote the percentage progress code to use epub.js events,
giving more succinct and readable code. Also, I added localStorage
caching of the epub location calculations, required for displaying
percentage progress, which can take up to 60-90 seconds to calculate on
longer ebooks. This localStorage caching approach is recommended by
epub.js in the `locations.html` example in their repo.

Signed-off-by: Ross Williams <ross@ross-williams.net>
2025-02-21 04:15:37 +00:00

221 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html class="no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>{{_('epub Reader')}} | {{title}}</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
{% if g.google_site_verification|length > 0 %}
<meta name="google-site-verification" content="{{g.google_site_verification}}">
{% endif %}
<link rel="apple-touch-icon" sizes="140x140" href="{{ url_for('static', filename='favicon.ico') }}">
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/libs/normalize.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/popup.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/reader.css') }}">
</head>
<body>
<div id="sidebar">
<div id="panels">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<!--input id="searchBox" placeholder="search" type="search"-->
<!--a id="show-Search" class="show_view icon-search" data-view="Search">Search</a-->
<a id="show-Toc" class="show_view icon-list-1 active" data-view="Toc">TOC</a>
<a id="show-Bookmarks" class="show_view icon-bookmark" data-view="Bookmarks">Bookmarks</a>
<!--a id="show-Notes" class="show_view icon-edit" data-view="Notes">Notes</a-->
</div>
<div id="tocView" class="view">
</div>
<!--div id="searchView" class="view">
<ul id="searchResults"></ul>
</div-->
<div id="bookmarksView" class="view">
<ul id="bookmarks"></ul>
</div>
<!--div id="notesView" class="view">
<div id="new-note">
<textarea id="note-text"></textarea>
<button id="note-anchor">Anchor</button>
</div>
<ol id="notes"></ol>
</div-->
</div>
<div id="main">
<div id="titlebar">
<div id="opener">
<a id="slider" class="icon-menu">Menu</a>
</div>
<div id="metainfo">
<span id="book-title"></span>
<span id="title-seperator">&nbsp;&nbsp;–&nbsp;&nbsp;</span>
<span id="chapter-title"></span>
</div>
<div id="title-controls">
<a id="bookmark" class="icon-bookmark-empty">Bookmark</a>
<a id="setting" class="icon-cog">Settings</a>
<a id="fullscreen" class="icon-resize-full">Fullscreen</a>
</div>
</div>
<div id="divider"></div>
<div id="prev" class="arrow">‹</div>
<div id="viewer"></div>
<div id="next" class="arrow">›</div>
<div id="progress">0%</div>
<div id="loader"><img src="{{ url_for('static', filename='img/loader.gif') }}"></div>
</div>
<div class="modal md-effect-1" id="settings-modal">
<div class="md-content">
<h3>{{_('Settings')}}</h3>
<div class="form-group themes" id="themes">
{{_('Choose a theme below:')}}}<br />
<!-- Hardcoded a tick in the light theme button because it is the "default" theme. Need to find a way to do this dynamically on startup-->
<button type="button" id="lightTheme" class="lightTheme" onclick="selectTheme(this.id)"><span
id="lightSelected">✓</span>{{_('Light')}}</button>
<button type="button" id="darkTheme" class="darkTheme" onclick="selectTheme(this.id)"><span
id="darkSelected"> </span>{{_('Dark')}}</button>
<button type="button" id="sepiaTheme" class="sepiaTheme" onclick="selectTheme(this.id)"><span
id="sepiaSelected"> </span>{{_('Sepia')}}</button>
<button type="button" id="blackTheme" class="blackTheme" onclick="selectTheme(this.id)"><span
id="blackSelected"> </span>{{_('Black')}}</button>
</div>
<div class="form-group">
<p>
<input type="checkbox" id="sidebarReflow"
name="sidebarReflow">{{_('Reflow text when sidebars are open.')}}
</p>
</div>
<div class="form-group fontSizeWrapper">
<div class="slider">
<label for="fader">{{ _('Font Sizes') }}</label>
<input type="range" min="75" max="200" value="100" id="fontSizeFader" step="25">
</div>
</div>
<div class="font" id="font">
<label class="item">{{_('Font')}}:</label>
<button type="button" id="default" onclick="selectFont(this.id)"><span>✓</span>{{_('Default')}}</button>
<button type="button" id="Yahei" onclick="selectFont(this.id)"><span></span>{{_('Yahei')}}</button>
<button type="button" id="SimSun" onclick="selectFont(this.id)"><span></span>{{_('SimSun')}}</button>
<button type="button" id="KaiTi" onclick="selectFont(this.id)"><span></span>{{_('KaiTi')}}</button>
<button type="button" id="Arial" onclick="selectFont(this.id)"><span></span>{{_('Arial')}}</button>
</div>
<div class="layou" id="layout">
<label class="item">{{ _('Spread') }}:</label>
<button type="button" id="spread" onclick="spread(this.id)"><span>✓</span>{{_('Two columns')}}</button>
<button type="button" id="nonespread" onclick="spread(this.id)"><span></span>{{_('One column')}}</button>
</div>
<div class="closer icon-cancel-circled"></div>
</div>
</div>
<div class="overlay"></div>
<script src="{{ url_for('static', filename='js/libs/jquery.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/compress/jszip_epub.min.js') }}">
</script>
<script src="{{ url_for('static', filename='js/libs/epub.min.js') }}"></script>
<script type="text/javascript">
window.calibre = {
filePath: "{{ url_for('static', filename='js/libs/') }}",
cssPath: "{{ url_for('static', filename='css/') }}",
bookmarkUrl: "{{ url_for('web.set_bookmark', book_id=bookid, book_format=book_format) }}",
bookUrl: "{{ url_for('web.serve_book', book_id=bookid, book_format=book_format, anyname='file.epub') }}",
bookmark: "{{ bookmark.bookmark_key if bookmark != None }}",
useBookmarks: "{{ current_user.is_authenticated | tojson }}"
};
window.themes = {
"darkTheme": {
"bgColor": "#202124",
"css_path": "{{ url_for('static', filename='css/epub_themes.css') }}",
"title-color": "#fff"
},
"lightTheme": {
"bgColor": "white",
"css_path": "{{ url_for('static', filename='css/epub_themes.css') }}",
"title-color": "#4f4f4f"
},
"sepiaTheme": {
"bgColor": "#ece1ca",
"css_path": "{{ url_for('static', filename='css/epub_themes.css') }}",
"title-color": "#4f4f4f"
},
"blackTheme": {
"bgColor": "black",
"css_path": "{{ url_for('static', filename='css/epub_themes.css') }}",
"title-color": "#fff"
},
};
function selectTheme (id) {
let tickSpans = document.getElementById("themes").querySelectorAll("span");
// Remove tick mark from all theme buttons
tickSpans.forEach(function (tickSpan) {
document.getElementById(tickSpan.id).textContent = "";
});
// Add tick mark to the button corresponding to the currently selected theme
document.getElementById(id).querySelector("span").textContent = "✓";
// Saving theme to local storage
localStorage.setItem("calibre.reader.theme", id);
// Apply theme to epubjs iframe
reader.rendition.themes.select(id);
// Apply theme to rest of the page.
document.getElementById("main").style.backgroundColor = themes[id]["bgColor"];
document.getElementById("titlebar").style.color = themes[id]["title-color"] || "#fff";
}
// font size settings logic
let fontSizeFader = document.getElementById('fontSizeFader');
fontSizeFader.addEventListener("change", function () {
reader.rendition.themes.fontSize(`${this.value}%`);
});
let defaultFont;
function selectFont(id) {
if (!defaultFont) {
defaultFont = reader.rendition.getContents()[0]?.css('font-family');
}
spans = document.getElementById("font").querySelectorAll("span");
for(var i = 0; i < spans.length; i++) {
spans[i].textContent = "";
}
document.getElementById(id).querySelector("span").textContent = "✓";
if (id == 'default') {
reader.rendition.themes.font(defaultFont);
return;
}
reader.rendition.themes.font(id);
}
function spread(id) {
spans = document.getElementById("layout").querySelectorAll("span");
for(var i = 0; i < spans.length; i++) {
spans[i].textContent = "";
}
document.getElementById(id).querySelector("span").textContent = "✓";
reader.rendition.spread(id==='spread'?true:'none');
}
</script>
<script src="{{ url_for('static', filename='js/libs/screenfull.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/libs/reader.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/reading/epub.js') }}"></script>
<script src="{{ url_for('static', filename='js/reading/locationchange-polyfill.js') }}"></script>
</body>
</html>