openmedialibrary_reader/cbr.js/cbr.js

380 lines
12 KiB
JavaScript

this.cbrjs = {};
cbrjs.open = function(url) {
var settings = getSettings();
Ox.load('UI', function() {
var $body = Ox.$('body')
.css({
backgroundColor: 'rgb(255, 255, 255)',
overflowX: 'hidden'
});
window.app = cbrjs.CBRViewer(Ox.extend({
url: url,
}, settings)
).bindEvent({
page: updateSettings
}).appendTo($body);
Ox.$window.on({
resize: app.resize
});
});
function getSettings() {
var settings = {};
try {
settings = JSON.parse(localStorage['cbrjs.' + url]);
} catch(e) {
settings.page = 1;
}
return settings;
}
function updateSettings(data) {
Ox.forEach(data, function(value, key) {
settings[key] = value;
});
localStorage['cbrjs.' + url] = JSON.stringify(settings);
}
};
cbrjs.CBRViewer = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
url: '',
page: 1
})
.options(options || {})
.update({
page: setPage,
url: loadBook
}),
canvas;
self.pages = [];
self.rotateTimes = 0;
self.hflip = false;
self.vflip = false;
self.fitMode = 'B';
self.mimeTypes = {
'png': 'image/png',
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'gif': 'image/gif',
};
self.$frame = Ox.Element()
.on({
mousedown: function() {
self.$frame.gainFocus();
},
})
.bindEvent({
key_down: function() {
that.options({
page: self.pages.length
})
},
key_left: function() {
that.options({
page: Math.max(self.options.page - 1, 1)
})
},
key_right: function() {
that.options({
page: Math.min(self.options.page + 1, self.pages.length)
})
},
key_up: function() {
that.options({
page: 1
})
},
key_n: function() {
self.fitMode = 'N';
resize();
},
key_h: function() {
self.fitMode = 'H';
resize();
},
key_b: function() {
self.fitMode = 'B';
resize();
},
key_w: function() {
self.fitMode = 'W';
resize();
},
key_l: function() {
self.rotateTimes--;
if (self.rotateTimes < 0) {
self.rotateTimes = 3;
}
setPage();
},
key_f: function() {
if (!self.hflip && !self.vflip) {
self.hflip = true;
} else if(self.hflip == true) {
self.vflip = true;
self.hflip = false;
} else if(self.vflip == true) {
self.vflip = false;
}
setPage();
},
singleclick: function(data) {
if (data.clientX < (that.width() / 2)) {
that.options({
page: Math.max(self.options.page - 1, 1)
});
} else {
that.options({
page: Math.min(self.options.page + 1, self.pages.length)
});
}
}
})
.css({
margin: 0,
overflow: 'auto',
padding: 0,
textAlign: 'center'
});
self.$canvas = Ox.Element('<canvas>')
.appendTo(self.$frame);
canvas = self.$canvas[0];
self.$scrollbar = Ox.Range({
arrows: true,
max: self.options.page,
min: 1,
orientation: 'horizontal',
step: 1,
value: self.options.page,
thumbValue: true,
thumbSize: 64
}).bindEvent({
change: function(data) {
Ox.print('change', data);
that.options({
page: data.value
})
}
});
self.$panel = Ox.SplitPanel({})
.appendTo(that);
that.setElement(
self.$mainPanel = Ox.SplitPanel({
elements: [
{
element: self.$frame,
},
{
element: self.$scrollbar,
size: 16
}
],
orientation: 'vertical'
})
);
self.$loading = Ox.LoadingScreen({
size: 16,
})
.css({
margin: 'auto',
position: 'absolute'
})
.start()
.appendTo(that);
loadBook();
function createURLFromArray(array, mimeType) {
var blob = new Blob([array], {type: mimeType});
blob = blob.slice(array.byteOffset, array.byteOffset + array.byteLength, mimeType);
return URL.createObjectURL(blob);
}
function isImage(filename) {
var extension = filename.split('.').pop().toLowerCase();
return !Ox.isUndefined(self.mimeTypes[extension]);
}
function loadBook() {
var xhr = new XMLHttpRequest();
xhr.open('GET', self.options.url, true);
xhr.responseType = "arraybuffer";
xhr.onload = function() {
loadFromArrayBuffer(this.response, function(pages, progress, total) {
self.pages = pages;
self.$scrollbar.options({
max: Math.max(pages.length, self.options.page),
size: that.width()
})
if (pages.length == self.options.page) {
setPage();
if (self.$loading) {
self.$loading.remove();
delete self.$loading;
}
}
});
};
xhr.send(null);
}
function loadFromArrayBuffer(buffer, progress) {
var extract,
start = (new Date).getTime(),
h = new Uint8Array(buffer, 0, 10),
pathToBitJS = $('script').map(function(i, script) {
return script.src;
}).filter(function(i, url) {
return url.indexOf('bitjs') > -1;
})[0].replace('archive.js', '');
var pages = [], filenames = [], total;
if (h[0] == 0x52 && h[1] == 0x61 && h[2] == 0x72 && h[3] == 0x21) { // RAR
extract = new bitjs.archive.Unrarrer(buffer, pathToBitJS);
} else if (h[0] == 80 && h[1] == 75) { // ZIP
extract = new bitjs.archive.Unzipper(buffer, pathToBitJS);
} else { // try tar otherwise
extract = new bitjs.archive.Untarrer(buffer, pathToBitJS);
}
if (extract) {
extract.addEventListener(
bitjs.archive.UnarchiveEvent.Type.PROGRESS,
function(e) {
var percentage = e.currentBytesUnarchived / e.totalUncompressedBytesInArchive;
total = e.totalFilesInArchive
progress([], percentage, total);
}
);
extract.addEventListener(
bitjs.archive.UnarchiveEvent.Type.INFO,
function(e) {
Ox.Log('', e.msg);
}
);
extract.addEventListener(
bitjs.archive.UnarchiveEvent.Type.EXTRACT,
function(e) {
// convert DecompressedFile into a bunch of ImageFiles
if (e.unarchivedFile) {
var f = e.unarchivedFile;
// add any new pages based on the filename
if (!Ox.contains(filenames, f.filename) && isImage(f.filename)) {
filenames.push(f.filename);
pages.push(f);
} else {
total--;
}
progress(pages, pages.length/total, total);
}
}
);
extract.addEventListener(
bitjs.archive.UnarchiveEvent.Type.FINISH,
function(e) {
total = pages.length;
progress(pages, 1, pages.length);
var diff = ((new Date).getTime() - start)/1000;
Ox.Log('', 'Unarchiving done in ' + diff + 's');
}
);
extract.start();
} else {
Ox.Log('', 'bitjs.archive failed to open file');
}
}
function resize(clear) {
canvas.style.width = '';
canvas.style.height = '';
canvas.style.maxWidth = '';
canvas.style.maxHeight = '';
var maxheight = self.$frame.height() - 4;
if (clear || self.fitMode == 'N') {
} else if (self.fitMode == 'B') {
canvas.style.maxWidth = '100%';
canvas.style.maxHeight = maxheight + 'px';
} else if (self.fitMode == 'H') {
canvas.style.height = maxheight + 'px';
} else if (self.fitMode == 'W') {
canvas.style.width = '100%';
}
self.$scrollbar.options({
size: that.width()
});
}
function setImage(url) {
var ctx = canvas.getContext('2d'),
img = new Image();
img.onerror = function(e) {
canvas.width = innerWidth - 100;
canvas.height = 300;
resize(true);
ctx.fillStyle = 'orange';
ctx.font = '50px sans-serif';
ctx.strokeStyle = 'black';
ctx.fillText('Page #' + (currentImage+1) + ' (' +
imageFiles[currentImage].filename + ')', 100, 100)
ctx.fillStyle = 'red';
ctx.fillText('Is corrupt or not an image', 100, 200);
};
img.onload = function() {
var h = img.height,
w = img.width,
sw = w,
sh = h;
self.rotateTimes = (4 + self.rotateTimes) % 4;
ctx.save();
if (self.rotateTimes % 2 == 1) { sh = w; sw = h;}
canvas.height = sh;
canvas.width = sw;
ctx.translate(sw/2, sh/2);
ctx.rotate(Math.PI/2 * self.rotateTimes);
ctx.translate(-w/2, -h/2);
if (self.vflip) {
ctx.scale(1, -1)
ctx.translate(0, -h);
}
if (self.hflip) {
ctx.scale(-1, 1)
ctx.translate(-w, 0);
}
canvas.style.display = 'none';
scrollTo(0,0);
ctx.drawImage(img, 0, 0);
resize();
canvas.style.display = '';
document.body.style.overflowY = '';
ctx.restore();
};
img.src = url;
}
function setPage() {
var file = self.pages[self.options.page - 1],
filename = file.filename,
extension = file.filename.split('.').pop().toLowerCase(),
mimeType = self.mimeTypes[extension];
setImage(createURLFromArray(file.fileData, mimeType));
self.$scrollbar.options({value: self.options.page});
that.triggerEvent('page', {page: self.options.page});
}
that.resize = function() {
resize();
};
return that;
};