diff --git a/cps/static/css/kthoom.css b/cps/static/css/kthoom.css
index 7e175de9..770b94a2 100644
--- a/cps/static/css/kthoom.css
+++ b/cps/static/css/kthoom.css
@@ -1,17 +1,21 @@
body {
- background: #444;
+ background: #444;
overflow-x: hidden;
overflow-y: auto;
- color: white;
- font-family: sans-serif;
- margin: 0px;
+ color: white;
+ font-family: sans-serif;
+ margin: 0px;
}
#main {
- text-align: center;
+ text-align: center;
z-index: 2;
}
+.view {
+ padding-top:0px;
+}
+
#sidebar a,
#sidebar ul,
#sidebar li,
@@ -20,10 +24,28 @@ body {
text-align: center;
}
+#sidebar ul {
+ position: relative;
+}
+
#sidebar a {
display: inline-block;
position: relative;
cursor: pointer;
+ padding: 4px;
+
+ transition: all .2s ease;
+}
+
+#sidebar a:hover,
+#sidebar a:focus {
+ outline: none;
+ box-shadow: 0px 2px 8px 1px black;
+}
+
+#sidebar a.active,
+#sidebar a.active img + span {
+ background-color: #45B29D;
}
#sidebar li img {
@@ -47,21 +69,65 @@ body {
}
#progress {
- position: absolute;
- display: inline;
- left: 20%;
- right: 20%;
- height: 20px;
- margin-top: 4px;
- text-align: right;
+ position: absolute;
+ display: inline;
+ top: 0;
+ left: 0;
+ right: 0;
+ min-height: 4px;
+ font-family: sans-serif;
+ font-size: 10px;
+ line-height: 10px;
+ text-align: right;
+
+ transition: min-height 150ms ease-in-out;
+}
+
+#progress .bar-load,
+#progress .bar-read {
+ display: flex;
+ align-items: flex-end;
+ justify-content: flex-end;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+
+ transition: width 150ms ease-in-out;
+}
+
+#progress .bar-load {
+ color: #000;
+ background-color: #CCC;
+}
+
+#progress .bar-read {
+ color: #FFF;
+ background-color: #45B29D;
+}
+
+#progress .text {
+ display: none;
+ padding: 0 5px;
+}
+
+#progress.loading,
+#titlebar:hover #progress {
+ min-height: 10px;
+}
+
+#progress.loading .text,
+#titlebar:hover #progress .text {
+ display: inline-block;
}
.hide {
- display: none !important;
+ display: none !important;
}
#mainContent {
overflow: auto;
+ outline: none;
}
#mainText {
@@ -82,6 +148,10 @@ body {
height: auto;
}
+#metainfo {
+ max-width: 70%;
+}
+
#prev {
left: 40px;
}
@@ -176,43 +246,11 @@ th {
color: #FFF;
}
+.dark-theme #progress .bar-read {
+ background-color: red;
+}
+
+
.dark-theme .overlay {
background-color: rgba(0,0,0,0.8);
}
-
-.view {
- padding-top:0px;
-}
-
-#Progress {
- margin: auto;
- width: 80%;
- background-color: #ddd;
- display: inline-block;
- margin-top: 5px;
-}
-
-#meter {
- width: 0%;
- height: 5px;
- background-color: #1C5484;
-}
-
-#meter2 {
- width: 0%;
- height: 15px;
- background-color: #028138;
-}
-
-#page {
- text-align:left;
- margin-top:-20px;
- font-size:80%;
- width: 0%;
-}
-
-#progress_title {
- text-align:right;
- margin-top:-15px;
- font-size:80%;
-}
diff --git a/cps/static/js/kthoom.js b/cps/static/js/kthoom.js
index 1754c460..70958c27 100644
--- a/cps/static/js/kthoom.js
+++ b/cps/static/js/kthoom.js
@@ -17,8 +17,6 @@
*/
/* global screenfull */
-// var start = 0;
-
if (window.opera) {
window.console.log = function(str) {
opera.postError(str);
@@ -44,11 +42,12 @@ if (typeof window.kthoom === "undefined" ) {
// key codes
kthoom.Key = {
ESCAPE: 27,
+ SPACE: 32,
LEFT: 37,
UP: 38,
RIGHT: 39,
- DOWN: 40,
- A: 65, B: 66, C: 67, D: 68, E: 69, F: 70, G: 71, H: 72, I: 73, J: 74, K: 75, L: 76, M: 77,
+ DOWN: 40,
+ A: 65, B: 66, C: 67, D: 68, E: 69, F: 70, G: 71, H: 72, I: 73, J: 74, K: 75, L: 76, M: 77,
N: 78, O: 79, P: 80, Q: 81, R: 82, S: 83, T: 84, U: 85, V: 86, W: 87, X: 88, Y: 89, Z: 90,
QUESTION_MARK: 191,
LEFT_SQUARE_BRACKET: 219,
@@ -62,8 +61,8 @@ var imageFilenames = [];
var totalImages = 0;
var settings = {
- hflip: false,
- vflip: false,
+ hflip: false,
+ vflip: false,
rotateTimes: 0,
fitMode: kthoom.Key.B,
theme: "light"
@@ -106,48 +105,16 @@ kthoom.ImageFile = function(file) {
this.data = file;
};
-
-kthoom.initProgressMeter = function() {
- $("#Progress").removeClass("hide");
- $("#Progress").click(function(e) {
- var page = Math.max(1, Math.ceil((e.offsetX / $(this).width()) * totalImages)) - 1;
- currentImage = page;
- updatePage();
- });
-};
-
-kthoom.setProgressMeter = function(optLabel) {
- var pct = imageFiles.length / totalImages * 100;
- if (pct === 100) {
- //smartpct = 100;
- getElem("progress_title").innerHTML = "Complete";
- } else {
- var labelText = pct.toFixed(2) + "% " + imageFiles.length + "/" + totalImages + "";
- if (optLabel) {
- labelText = optLabel + " " + labelText;
- }
- getElem("progress_title").innerHTML=labelText;
- }
- if (!isNaN(pct)) {
- getElem("meter").style.width = pct + "%";
- }
-
- getElem("meter2").style.width= 100 * (totalImages === 0 ? 0 : ((currentImage + 1) / totalImages)) + "%";
- getElem("page").innerHTML=(currentImage + 1) + "/" + totalImages ;
-};
-
function loadFromArrayBuffer(ab) {
var f = [];
- if (typeof ab !== "object") {
- ab = JSON.parse(ab);
- }
+
f.fileData = ab.content;
f.filename = ab.name;
// add any new pages based on the filename
if (imageFilenames.indexOf(f.filename) === -1) {
imageFilenames.push(f.filename);
imageFiles.push(new kthoom.ImageFile(f));
-
+
// add thumbnails to the TOC list
$("#thumbnails").append(
"
" +
@@ -158,10 +125,10 @@ function loadFromArrayBuffer(ab) {
""
);
}
- // var percentage = (ab.page + 1) / (ab.last + 1);
+ var percentage = ((ab.page + 1) / (ab.last + 1)) * 100;
+ updateProgress(percentage);
+
totalImages = ab.last + 1;
- kthoom.setProgressMeter("Unzipping");
- // lastCompletion = percentage * 100;
// display first page if we haven't yet
if (imageFiles.length === currentImage + 1) {
@@ -169,10 +136,28 @@ function loadFromArrayBuffer(ab) {
}
}
+function scrollTocToActive() {
+ // Scroll to the thumbnail in the TOC on page change
+ $('#tocView').stop().animate({
+ scrollTop: $('#tocView a.active').position().top
+ }, 200);
+}
function updatePage() {
- getElem("page").innerHTML=(currentImage + 1) + "/" + totalImages ;
- getElem("meter2").style.width= 100 * (totalImages === 0 ? 0 : ((currentImage + 1) / totalImages)) + "%";
+ $('.page').text((currentImage + 1 ) + "/" + totalImages);
+
+ // Mark the current page in the TOC
+ $('#tocView a[data-page]')
+ // Remove the currently active thumbnail
+ .removeClass('active')
+ // Find the new one
+ .filter('[data-page='+ (currentImage + 1) +']')
+ // Set it to active
+ .addClass('active');
+
+ scrollTocToActive();
+ updateProgress();
+
if (imageFiles[currentImage]) {
setImage(imageFiles[currentImage].dataURI);
} else {
@@ -185,6 +170,22 @@ function updatePage() {
kthoom.saveSettings();
}
+function updateProgress(loadPercentage) {
+ // Set the load/unzip progress if it's passed in
+ if (loadPercentage) {
+ $("#progress .bar-load").css({ width: loadPercentage + "%" });
+
+ if (loadPercentage === 100) {
+ $("#progress")
+ .removeClass('loading')
+ .find(".load").text('');
+ }
+ }
+
+ // Set page progress bar
+ $("#progress .bar-read").css({ width: totalImages === 0 ? 0 : Math.round((currentImage + 1) / totalImages * 100) + "%"});
+}
+
function setImage(url) {
var canvas = $("#mainImage")[0];
var x = $("#mainImage")[0].getContext("2d");
@@ -332,23 +333,18 @@ function updateScale(clear) {
}
function keyHandler(evt) {
- var code = evt.keyCode;
-
- if ($("#progress").css("display") === "none") {
- return;
- }
- // canKeyNext = (($("body").css("offsetWidth") + $("body").css("scrollLeft")) / $("body").css("scrollWidth")) >= 1;
- // canKeyPrev = (scrollX <= 0);
-
- if (evt.ctrlKey || evt.shiftKey || evt.metaKey) return;
- switch (code) {
+ var hasModifier = evt.ctrlKey || evt.shiftKey || evt.metaKey;
+ switch (evt.keyCode) {
case kthoom.Key.LEFT:
+ if (hasModifier) break;
showPrevPage();
break;
case kthoom.Key.RIGHT:
+ if (hasModifier) break;
showNextPage();
break;
case kthoom.Key.L:
+ if (hasModifier) break;
settings.rotateTimes--;
if (settings.rotateTimes < 0) {
settings.rotateTimes = 3;
@@ -356,6 +352,7 @@ function keyHandler(evt) {
updatePage();
break;
case kthoom.Key.R:
+ if (hasModifier) break;
settings.rotateTimes++;
if (settings.rotateTimes > 3) {
settings.rotateTimes = 0;
@@ -363,6 +360,7 @@ function keyHandler(evt) {
updatePage();
break;
case kthoom.Key.F:
+ if (hasModifier) break;
if (!settings.hflip && !settings.vflip) {
settings.hflip = true;
} else if (settings.hflip === true && settings.vflip === true) {
@@ -377,23 +375,43 @@ function keyHandler(evt) {
updatePage();
break;
case kthoom.Key.W:
+ if (hasModifier) break;
settings.fitMode = kthoom.Key.W;
updateScale(false);
break;
case kthoom.Key.H:
+ if (hasModifier) break;
settings.fitMode = kthoom.Key.H;
updateScale(false);
break;
case kthoom.Key.B:
+ if (hasModifier) break;
settings.fitMode = kthoom.Key.B;
updateScale(false);
break;
case kthoom.Key.N:
+ if (hasModifier) break;
settings.fitMode = kthoom.Key.N;
updateScale(false);
break;
+ case kthoom.Key.SPACE:
+ var container = $('#mainContent');
+ var atTop = container.scrollTop() === 0;
+ var atBottom = container.scrollTop() >= container[0].scrollHeight - container.height();
+
+ if (evt.shiftKey && atTop) {
+ evt.preventDefault();
+ // If it's Shift + Space and the container is at the top of the page
+ showPrevPage();
+ } else if (!evt.shiftKey && atBottom) {
+ evt.preventDefault();
+ // If you're at the bottom of the page and you only pressed space
+ showNextPage();
+ container.scrollTop(0);
+ }
+ break;
default:
- //console.log('KeyCode = ' + code);
+ //console.log('KeyCode', evt.keyCode);
break;
}
}
@@ -404,31 +422,31 @@ function ImageLoadCallback() {
if (jso === null) {
setImage("error");
} else {
+ // IE 11 sometimes sees the response as a string
+ if (typeof jso !== "object") {
+ jso = JSON.parse(jso);
+ }
+
if (jso.page !== jso.last) {
this.open("GET", this.fileid + "/" + (jso.page + 1));
this.addEventListener("load", ImageLoadCallback);
this.send();
}
- /*else
- {
- var diff = ((new Date).getTime() - start) / 1000;
- console.log("Transfer done in " + diff + "s");
- }*/
+
loadFromArrayBuffer(jso);
}
}
function init(fileid) {
- // start = (new Date).getTime();
var request = new XMLHttpRequest();
request.open("GET", fileid);
request.responseType = "json";
request.fileid = fileid.substring(0, fileid.length - 2);
request.addEventListener("load", ImageLoadCallback);
request.send();
- kthoom.initProgressMeter();
document.body.className += /AppleWebKit/.test(navigator.userAgent) ? " webkit" : "";
kthoom.loadSettings();
updateScale(true);
+
$(document).keydown(keyHandler);
$(window).resize(function() {
@@ -440,6 +458,13 @@ function init(fileid) {
$("#sidebar").toggleClass("open");
$("#main").toggleClass("closed");
$(this).toggleClass("icon-menu icon-right");
+
+ // We need this in a timeout because if we call it during the CSS transition, IE11 shakes the page ¯\_(ツ)_/¯
+ setTimeout(function(){
+ // Focus on the TOC or the main content area, depending on which is open
+ $('#main:not(.closed) #mainContent, #sidebar.open #tocView').focus();
+ scrollTocToActive();
+ }, 500);
});
// Open Settings modal
@@ -487,6 +512,9 @@ function init(fileid) {
}
}
+ // Focus the scrollable area so that keyboard scrolling work as expected
+ $('#mainContent').focus();
+
$("#mainImage").click(function(evt) {
// Firefox does not support offsetX/Y so we have to manually calculate
// where the user clicked in the image.
diff --git a/cps/templates/readcbr.html b/cps/templates/readcbr.html
index 5eefa5df..de661d0e 100644
--- a/cps/templates/readcbr.html
+++ b/cps/templates/readcbr.html
@@ -1,148 +1,156 @@
-
-
-
- Comic Reader
-
-
-
-
-
-
-
+
+
+
+ Comic Reader
+
+
+
-
-
-
-
-
-
-