refactoring, use Handlebars instead of jQuery objects, updated toolbar styles
This commit is contained in:
parent
fa5e67d9cf
commit
ad2ad4f379
23 changed files with 1151 additions and 267 deletions
320
lib/ComicBook.js
320
lib/ComicBook.js
|
@ -11,6 +11,9 @@
|
|||
- full browser test - IE9 / FF3.6+ / Chrome / Safari / Opera
|
||||
- don't inlcude the closure compiler, expect it (or similar) to be installed instead
|
||||
|
||||
- fix Makefile (handlebars is not compiling properly..)
|
||||
- fonts for left / right navigation, remove all sprites / images completely
|
||||
|
||||
Nice 2 have:
|
||||
- lint
|
||||
- jump to page?
|
||||
|
@ -23,6 +26,8 @@
|
|||
- really need to speed up enhancements, try to use webworkers
|
||||
- refactor so we are not using all these loose shared variables and other nastyness
|
||||
- use custom event emitters instead of hacky code
|
||||
- properly bind "this" so we don't have to keep using "self"
|
||||
- allow toolbar to be sticky
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -56,6 +61,7 @@ function merge(a, b) {
|
|||
* @returns {ComicBookException}
|
||||
*/
|
||||
var ComicBookException = {
|
||||
INVALID_ACTION: "invalid action",
|
||||
INVALID_PAGE: "invalid page",
|
||||
INVALID_PAGE_TYPE: "invalid page type",
|
||||
UNDEFINED_CONTROL: "undefined control",
|
||||
|
@ -159,6 +165,7 @@ function ComicBook(id, srcs, opts) {
|
|||
* @see #ComicBook.prototype.enhance
|
||||
*/
|
||||
function init() {
|
||||
|
||||
// setup canvas
|
||||
canvas = document.getElementById(canvas_id);
|
||||
context = canvas.getContext("2d");
|
||||
|
@ -170,199 +177,47 @@ function ComicBook(id, srcs, opts) {
|
|||
}
|
||||
|
||||
// add page controls
|
||||
// TODO: add IE event listeners too.
|
||||
canvas.addEventListener("click", self.navigation, false);
|
||||
window.addEventListener("keydown", self.navigation, false);
|
||||
window.addEventListener("hashchange", checkHash, false);
|
||||
//setInterval(function() { checkHash(); }, 300); // TODO: enable this when there is no onhashchange event
|
||||
}
|
||||
|
||||
/**
|
||||
* User controls
|
||||
*
|
||||
* TODO: save current values
|
||||
*/
|
||||
ComicBook.prototype.control = {
|
||||
|
||||
status: $(document.createElement("div"))
|
||||
.attr("id", "cb-status")
|
||||
.addClass("cb-control cb-always-on")
|
||||
.append(
|
||||
$(document.createElement("div"))
|
||||
.attr("id", "cb-progress-bar")
|
||||
.progressbar()
|
||||
),
|
||||
|
||||
toolbar: $(document.createElement("div"))
|
||||
.attr("id", "cb-toolbar")
|
||||
.addClass("cb-control")
|
||||
.append(
|
||||
$(document.createElement("button"))
|
||||
.attr("title", "close the toolbar")
|
||||
.addClass("cb-close")
|
||||
.click(function(){
|
||||
self.toggleToolbar();
|
||||
})
|
||||
)
|
||||
.append(
|
||||
$(document.createElement("button"))
|
||||
.attr("title", "switch between dual and single page modes")
|
||||
.addClass("cb-layout " + options.displayMode)
|
||||
.click(function(){
|
||||
self.toggleLayout();
|
||||
})
|
||||
)
|
||||
.append(
|
||||
$(document.createElement("button"))
|
||||
.attr("title", "tweak the page colors")
|
||||
.addClass("cb-color cb-menu-button")
|
||||
.click(function(){
|
||||
self.toggleControl("color");
|
||||
})
|
||||
)
|
||||
.append(
|
||||
$(document.createElement("button"))
|
||||
.attr("title", "zoom out")
|
||||
.addClass("cb-zoom-out")
|
||||
.click(function(){
|
||||
self.zoom(scale - 0.1);
|
||||
})
|
||||
)
|
||||
.append(
|
||||
$(document.createElement("button"))
|
||||
.attr("title", "zoom in")
|
||||
.addClass("cb-zoom-in")
|
||||
.click(function(){
|
||||
self.zoom(scale + 0.1);
|
||||
})
|
||||
)
|
||||
.append(
|
||||
$(document.createElement("button"))
|
||||
.attr("title", "fit to page width")
|
||||
.addClass("cb-fit-width")
|
||||
.click(function(){
|
||||
options.zoomMode = "fitWidth"
|
||||
self.drawPage();
|
||||
})
|
||||
)
|
||||
.append(
|
||||
$(document.createElement("p"))
|
||||
.attr("id", "cb-comic-info")
|
||||
.append("<span id='cb-current-page'></span> / " + srcs.length)
|
||||
),
|
||||
|
||||
/**
|
||||
* Image enhancements
|
||||
*/
|
||||
color: $(document.createElement("div"))
|
||||
.attr("id", "cb-color")
|
||||
.addClass("cb-control")
|
||||
.append("<label for='cb-sharpen'>Brightness</label>")
|
||||
.append(
|
||||
$("<div id='cb-brightness' class='cb-option'></div>").slider({
|
||||
value: 0,
|
||||
step: 10,
|
||||
min: -1000,
|
||||
max: 1000,
|
||||
change: function(event, ui) {
|
||||
self.enhance.brightness({ brightness: ui.value });
|
||||
}
|
||||
})
|
||||
)
|
||||
.append("<label for='cb-sharpen'>Contrast</label>")
|
||||
.append(
|
||||
$("<div id='cb-contrast' class='cb-option'></div>").slider({
|
||||
value: 0,
|
||||
step: 0.001,
|
||||
min: 0,
|
||||
max: 1,
|
||||
change: function(event, ui) {
|
||||
self.enhance.brightness({ contrast: ui.value });
|
||||
}
|
||||
})
|
||||
)
|
||||
.append("<label for='cb-sharpen'>Sharpen</label>")
|
||||
.append(
|
||||
$("<div id='cb-sharpen' class='cb-option'></div>").slider({
|
||||
value: 0,
|
||||
step: 0.001,
|
||||
min: 0,
|
||||
max: 1,
|
||||
change: function(event, ui) {
|
||||
self.enhance.sharpen({ amount: ui.value });
|
||||
}
|
||||
})
|
||||
)
|
||||
.append(
|
||||
$(document.createElement("div")).addClass("cb-option")
|
||||
.append("<input type='checkbox' id='cb-desaturate' /> <label for='cb-desaturate'>Desaturate</label>")
|
||||
.append("<button id='cb-reset'>reset</button>")
|
||||
),
|
||||
|
||||
/**
|
||||
* Page navigation
|
||||
*/
|
||||
navigation: {
|
||||
|
||||
left: $(document.createElement("div"))
|
||||
.addClass("cb-control cb-navigate cb-always-on left")
|
||||
.click(function(e){
|
||||
self.drawPrevPage();
|
||||
}),
|
||||
|
||||
right: $(document.createElement("div"))
|
||||
.addClass("cb-control cb-navigate cb-always-on right")
|
||||
.click(function(e) {
|
||||
self.drawNextPage();
|
||||
})
|
||||
},
|
||||
|
||||
loadingOverlay: $(document.createElement("div"))
|
||||
.attr("id", "cb-loading-overlay")
|
||||
.addClass("cb-control")
|
||||
};
|
||||
|
||||
ComicBook.prototype.renderControls = function() {
|
||||
|
||||
$(canvas)
|
||||
.before(this.getControl("loadingOverlay"))
|
||||
.before(this.getControl("status"))
|
||||
.after(this.getControl("toolbar"))
|
||||
.after(this.getControl("navigation").left)
|
||||
.after(this.getControl("navigation").right)
|
||||
.after(this.getControl("color").hide());
|
||||
var controls = {};
|
||||
|
||||
$(".cb-menu-button").click(function(e) {
|
||||
$(this).toggleClass("active");
|
||||
$.each(Handlebars.templates, function (name, template) {
|
||||
|
||||
var $template = $(template().trim());
|
||||
controls[name] = $template;
|
||||
|
||||
$template.find('*').andSelf().filter("[data-action][data-trigger]").each(function () {
|
||||
|
||||
var $this = $(this);
|
||||
var trigger = $this.data('trigger');
|
||||
var action = $this.data('action');
|
||||
|
||||
// trigger a direct method if exists
|
||||
if (typeof self[$this.data('action')] === "function") {
|
||||
$this.on(trigger, self[action]);
|
||||
}
|
||||
|
||||
// throw an event to be caught outside if the app code
|
||||
$this.on(trigger, function (e) {
|
||||
$(self).trigger(trigger, e);
|
||||
});
|
||||
});
|
||||
|
||||
$(canvas).before($template);
|
||||
});
|
||||
|
||||
$("#cb-desaturate").click(function(){
|
||||
if ($(this).is(":checked")) {
|
||||
self.enhance.desaturate();
|
||||
} else {
|
||||
self.enhance.resaturate();
|
||||
}
|
||||
});
|
||||
|
||||
$("#cb-reset").click(function() {
|
||||
// TODO: improve performance here.
|
||||
$("#cb-brightness").slider("value", 0);
|
||||
$("#cb-contrast").slider("value", 0);
|
||||
$("#cb-saturation").slider("value", 0);
|
||||
$("#cb-sharpen").slider("value", 0);
|
||||
var desaturate = $("#cb-desaturate");
|
||||
desaturate.attr("checked", false);
|
||||
self.enhance.reset();
|
||||
});
|
||||
this.controls = controls;
|
||||
};
|
||||
|
||||
ComicBook.prototype.getControl = function(control) {
|
||||
|
||||
if (typeof this.control[control] === "undefined") {
|
||||
throw ComicBookException.UNDEFINED_CONTROL+' '+control;
|
||||
if (typeof this.controls[control] !== "object") {
|
||||
throw ComicBookException.UNDEFINED_CONTROL + ' ' + control;
|
||||
}
|
||||
|
||||
return this.control[control];
|
||||
return this.controls[control];
|
||||
};
|
||||
|
||||
ComicBook.prototype.showControl = function(control) {
|
||||
|
@ -377,23 +232,16 @@ function ComicBook(id, srcs, opts) {
|
|||
this.getControl(control).toggle().toggleClass("open");
|
||||
};
|
||||
|
||||
ComicBook.prototype.toggleToolbar = function() {
|
||||
if ($("#cb-toolbar").is(":visible")) {
|
||||
$(".cb-control").not(".cb-always-on").hide();
|
||||
} else {
|
||||
$("#cb-toolbar, .cb-control.open").show();
|
||||
}
|
||||
};
|
||||
|
||||
ComicBook.prototype.toggleLayout = function() {
|
||||
if (options.displayMode === "double") {
|
||||
$("#cb-toolbar .cb-layout").removeClass("double");
|
||||
options.displayMode = "single";
|
||||
} else {
|
||||
$("#cb-toolbar .cb-layout").removeClass("single");
|
||||
options.displayMode = "double";
|
||||
}
|
||||
$("#cb-toolbar .cb-layout").addClass(options.displayMode);
|
||||
|
||||
var $control = self.getControl("toolbar").find("[data-action=toggleLayout]");
|
||||
var displayMode = (options.displayMode === "single") ? "double" : "single";
|
||||
|
||||
$control.removeClass(options.displayMode);
|
||||
$control.addClass(displayMode);
|
||||
|
||||
options.displayMode = displayMode;
|
||||
|
||||
self.drawPage();
|
||||
};
|
||||
|
||||
|
@ -424,8 +272,7 @@ function ComicBook(id, srcs, opts) {
|
|||
init();
|
||||
|
||||
// resize navigation controls
|
||||
$(".cb-control.cb-navigate").outerHeight(window.innerHeight);
|
||||
$("#cb-toolbar").outerWidth(windowWidth());
|
||||
$(".navigate").outerHeight(window.innerHeight);
|
||||
$("#cb-loading-overlay").outerWidth(windowWidth()).height(window.innerHeight);
|
||||
|
||||
// preload images if needed
|
||||
|
@ -447,6 +294,19 @@ function ComicBook(id, srcs, opts) {
|
|||
if (typeof this.getPage(pointer) === "object") { this.drawPage(); }
|
||||
};
|
||||
|
||||
ComicBook.prototype.zoomIn = function () {
|
||||
self.zoom(scale + 0.1);
|
||||
};
|
||||
|
||||
ComicBook.prototype.zoomOut = function () {
|
||||
self.zoom(scale - 0.1);
|
||||
};
|
||||
|
||||
ComicBook.prototype.fitWidth = function () {
|
||||
options.zoomMode = "fitWidth"
|
||||
ComicBook.prototype.drawPage();
|
||||
};
|
||||
|
||||
/**
|
||||
* Preload all images, draw the page only after a given number have been loaded.
|
||||
*
|
||||
|
@ -470,7 +330,7 @@ function ComicBook(id, srcs, opts) {
|
|||
pages[i] = this;
|
||||
loaded.push(i);
|
||||
|
||||
$("#cb-progress-bar").progressbar("value", Math.floor((loaded.length / no_pages) * 100));
|
||||
$("#cb-progress-bar .progressbar-value").css("width", Math.floor((loaded.length / no_pages) * 100) + "%");
|
||||
|
||||
// double page mode needs an extra page added
|
||||
var buffer = (options.displayMode === "double" && pointer < srcs.length-1) ? 1 : 0;
|
||||
|
@ -662,7 +522,11 @@ function ComicBook(id, srcs, opts) {
|
|||
|
||||
var current_page = (options.displayMode === "double" && pointer+2 <= srcs.length)
|
||||
? (pointer+1) + "-" + (pointer+2) : pointer+1
|
||||
$("#cb-current-page").text(current_page);
|
||||
|
||||
this.getControl('toolbar')
|
||||
.find("#current-page").text(current_page)
|
||||
.end()
|
||||
.find("#page-count").text(srcs.length);
|
||||
|
||||
// revert page mode back to double if it was auto switched for a double page spread
|
||||
if (is_double_page_spread) { options.displayMode = "double"; }
|
||||
|
@ -671,21 +535,18 @@ function ComicBook(id, srcs, opts) {
|
|||
$("button.cb-fit-width").attr("disabled", (options.zoomMode === "fitWidth"));
|
||||
|
||||
// disable prev/next buttons if not needed
|
||||
$(".cb-navigate").show();
|
||||
$(".navigate").show();
|
||||
if (pointer === 0) {
|
||||
$(".cb-navigate.left").hide();
|
||||
$(".cb-navigate.right").show();
|
||||
$(".navigate-left").hide();
|
||||
$(".navigate-right").show();
|
||||
}
|
||||
|
||||
if (pointer === srcs.length-1 || (typeof page2 === "object" && pointer === srcs.length-2)) {
|
||||
$(".cb-navigate.left").show();
|
||||
$(".cb-navigate.right").hide();
|
||||
$(".navigate-left").show();
|
||||
$(".navigate-right").hide();
|
||||
}
|
||||
|
||||
// user callback
|
||||
if (typeof options.afterDrawPage === "function") {
|
||||
options.afterDrawPage(pointer + 1);
|
||||
}
|
||||
$(this).trigger("navigate");
|
||||
|
||||
// update hash location
|
||||
if (getHash() !== pointer) {
|
||||
|
@ -706,7 +567,7 @@ function ComicBook(id, srcs, opts) {
|
|||
var page;
|
||||
|
||||
try {
|
||||
page = this.getPage(pointer+1);
|
||||
page = self.getPage(pointer+1);
|
||||
} catch (e) {}
|
||||
|
||||
if (!page) { return false; }
|
||||
|
@ -714,7 +575,7 @@ function ComicBook(id, srcs, opts) {
|
|||
if (pointer + 1 < pages.length) {
|
||||
pointer += (options.displayMode === "single" || is_double_page_spread) ? 1 : 2;
|
||||
try {
|
||||
this.drawPage();
|
||||
self.drawPage();
|
||||
} catch (e) {}
|
||||
}
|
||||
};
|
||||
|
@ -729,7 +590,7 @@ function ComicBook(id, srcs, opts) {
|
|||
var page;
|
||||
|
||||
try {
|
||||
page = this.getPage(pointer-1);
|
||||
page = self.getPage(pointer-1);
|
||||
} catch (e) {}
|
||||
|
||||
if (!page) { return false; }
|
||||
|
@ -738,10 +599,35 @@ function ComicBook(id, srcs, opts) {
|
|||
|
||||
if (pointer > 0) {
|
||||
pointer -= (options.displayMode === "single" || is_double_page_spread) ? 1 : 2;
|
||||
this.drawPage();
|
||||
self.drawPage();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ComicBook.prototype.brightness = function () {
|
||||
self.enhance.brightness({ brightness: $(this).val() });
|
||||
}
|
||||
|
||||
ComicBook.prototype.contrast = function () {
|
||||
self.enhance.brightness({ contrast: $(this).val() });
|
||||
}
|
||||
|
||||
ComicBook.prototype.sharpen = function () {
|
||||
self.enhance.sharpen({ amount: $(this).val() });
|
||||
}
|
||||
|
||||
ComicBook.prototype.desaturate = function () {
|
||||
if ($(this).is(":checked")) {
|
||||
self.enhance.desaturate();
|
||||
} else {
|
||||
self.enhance.resaturate();
|
||||
}
|
||||
};
|
||||
|
||||
ComicBook.prototype.resetEnhancements = function () {
|
||||
self.enhance.reset();
|
||||
};
|
||||
|
||||
/**
|
||||
* Apply image enhancements to the canvas.
|
||||
*
|
||||
|
@ -802,11 +688,8 @@ function ComicBook(id, srcs, opts) {
|
|||
* Force black and white
|
||||
*/
|
||||
desaturate: function () {
|
||||
|
||||
options.enhance.desaturate = {};
|
||||
|
||||
Pixastic.process(canvas, "desaturate", { average : false });
|
||||
|
||||
init();
|
||||
},
|
||||
|
||||
|
@ -855,9 +738,7 @@ function ComicBook(id, srcs, opts) {
|
|||
var side = false;
|
||||
|
||||
switch (e.type) {
|
||||
case "click":
|
||||
self.toggleToolbar();
|
||||
break;
|
||||
|
||||
case "keydown":
|
||||
|
||||
// navigation
|
||||
|
@ -872,6 +753,7 @@ function ComicBook(id, srcs, opts) {
|
|||
self.toggleLayout();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ComicBookException.INVALID_NAVIGATION_EVENT+' '+e.type;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue