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('') .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; };