From 6d35073a9ce2e5f399f913ba80268a80aae6b8bf Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 27 Jul 2012 15:19:43 -0700 Subject: [PATCH 01/15] Initial build for b2g. --- make.js | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ src/core.js | 6 ++-- web/viewer.html | 1 + web/viewer.js | 21 +++++++++++- 4 files changed, 113 insertions(+), 3 deletions(-) diff --git a/make.js b/make.js index 727e740ca..cc6274fac 100755 --- a/make.js +++ b/make.js @@ -1,5 +1,7 @@ #!/usr/bin/env node require('./external/shelljs/make'); +var fs = require('fs'); +var vm = require('vm'); var ROOT_DIR = __dirname + '/', // absolute path to project's root BUILD_DIR = 'build/', @@ -15,6 +17,49 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root MOZCENTRAL_STREAM_CONVERTER_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2291', FIREFOX_STREAM_CONVERTER_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb1'; +function preprocess(inFilename, outFilename, flags) { + // TODO make this really read line by line. + var lines = fs.readFileSync(inFilename).toString().split("\n"); + var totalLines = lines.length; + var out = ''; + var i = 0; + function readLine() { + if (i < totalLines) { + return lines[i++]; + } + return null; + } + function writeLine(line) { + out += line + '\n'; + } + + var s, state = 0, stack = []; + while ((s = readLine()) !== null) { + var m = new RegExp(/^\/\/\s*#(if|else|endif)\b(?:\s+(.*))?/).exec(s); + if (m) { + if (m[1] === "if") { + stack.push(state); + state = vm.runInNewContext(m[2], flags) ? 3 : 1; + } else if (m[1] === "else") { + state = state === 1 ? 3 : 2; + } else { + state = stack.pop(); + } + } else { + if (state === 0) { + writeLine(s); + } else if(state === 3) { + writeLine(s.replace(/^\/\//g, " ")); + } + } + } + fs.writeFileSync(outFilename, out); +} + +target.pre = function() { + preprocess('in.txt', 'out.txt', {B2G: true}); +} + // // make all // @@ -482,6 +527,49 @@ target.mozcentral = function() { cp('-Rf', 'test/mozcentral/*', MOZCENTRAL_TEST_DIR); }; +target.b2g = function() { + echo(); + echo('### Building B2G (Firefox OS App)'); + var B2G_BUILD_DIR = BUILD_DIR + '/b2g/', + B2G_BUILD_CONTENT_DIR = B2G_BUILD_DIR + '/content/'; + target.production(); + target.buildnumber(); + + // Clear out everything in the b2g build directory + cd(ROOT_DIR); + rm('-Rf', B2G_BUILD_DIR); + mkdir('-p', B2G_BUILD_CONTENT_DIR); + mkdir('-p', B2G_BUILD_CONTENT_DIR + BUILD_DIR); + mkdir('-p', B2G_BUILD_CONTENT_DIR + '/web'); + + // Copy a standalone version of pdf.js inside the content directory + cp(BUILD_TARGET, B2G_BUILD_CONTENT_DIR + BUILD_DIR); + cp('-R', EXTENSION_WEB_FILES, B2G_BUILD_CONTENT_DIR + '/web'); + cp('web/viewer-snippet-b2g.html', B2G_BUILD_CONTENT_DIR + '/web/'); + // Replacing the l10n.js file with regular gh-pages one + rm(B2G_BUILD_CONTENT_DIR + '/web/l10n.js'); + cp('external/webL10n/l10n.js', B2G_BUILD_CONTENT_DIR + '/web'); + cp('web/locale.properties', B2G_BUILD_CONTENT_DIR + '/web'); + + mv('-f', B2G_BUILD_CONTENT_DIR + '/web/viewer-production.html', + B2G_BUILD_CONTENT_DIR + '/web/viewer.html'); + cd(B2G_BUILD_CONTENT_DIR + '/web'); + sed('-i', /.*PDFJSSCRIPT_INCLUDE_B2G.*\n/, cat('viewer-snippet-b2g.html'), 'viewer.html'); + rm('viewer-snippet-b2g.html'); + cd(ROOT_DIR); + + var flags = { + B2G: true + }; + var prep = [ + B2G_BUILD_CONTENT_DIR + '/web/viewer.js', + B2G_BUILD_CONTENT_DIR + '/build/pdf.js' + ]; + for (var i in prep) { + preprocess(prep[i], prep[i], flags); + } +}; + // // make chrome // diff --git a/src/core.js b/src/core.js index e8d008074..6d051b152 100644 --- a/src/core.js +++ b/src/core.js @@ -29,9 +29,11 @@ function getPdf(arg, callback) { var params = arg; if (typeof arg === 'string') params = { url: arg }; - +//#if !B2G var xhr = new XMLHttpRequest(); - +//#else +//var xhr = new XMLHttpRequest({mozSystem: true}); +//#endif xhr.open('GET', params.url); var headers = params.headers; diff --git a/web/viewer.html b/web/viewer.html index 58b35464f..d7a57fee4 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -38,6 +38,7 @@ + diff --git a/web/viewer.js b/web/viewer.js index 4de66b5af..f6874f9a9 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1880,8 +1880,9 @@ window.addEventListener('load', function webViewerLoad(evt) { PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen'); PDFView.renderHighestPriority(); }); - +//#if !B2G PDFView.open(file, 0); +//#endif }, true); function updateViewarea() { @@ -2140,3 +2141,21 @@ window.addEventListener('afterprint', function afterPrint(evt) { window.addEventListener('mozfullscreenchange', fullscreenChange, false); window.addEventListener('webkitfullscreenchange', fullscreenChange, false); })(); + +//#if B2G +// window.navigator.mozSetMessageHandler('activity', function(activity) { +// var url = activity.source.data.url; +// // Temporarily get the data here since the cross domain xhr is broken in +// // the worker currently, see bug 761227. +// var params = { +// url: url, +// error: function(e) { +// PDFView.error(mozL10n.get('loading_error', null, +// 'An error occurred while loading the PDF.'), e); +// } +// }; +// PDFJS.getPdf(params, function successCallback(data) { +// PDFView.open(data, 0); +// }); +// }); +//#endif From 492fa6edb40fb905059c01b20270535e633247ad Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 11:29:13 -0700 Subject: [PATCH 02/15] Add the new preprocessor. --- make.js | 430 +++++++++++++--------- src/api.js | 25 +- src/pdf.js | 10 +- web/viewer-snippet-firefox-extension.html | 5 +- web/viewer.html | 81 ++-- web/viewer.js | 195 +++++----- 6 files changed, 431 insertions(+), 315 deletions(-) diff --git a/make.js b/make.js index cc6274fac..bb9896391 100755 --- a/make.js +++ b/make.js @@ -1,6 +1,7 @@ #!/usr/bin/env node require('./external/shelljs/make'); var fs = require('fs'); +var path = require('path'); var vm = require('vm'); var ROOT_DIR = __dirname + '/', // absolute path to project's root @@ -10,6 +11,7 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root EXTENSION_SRC_DIR = 'extensions/', LOCALE_SRC_DIR = 'l10n/', GH_PAGES_DIR = BUILD_DIR + 'gh-pages/', + GENERIC_DIR = BUILD_DIR + 'generic/', REPO = 'git@github.com:mozilla/pdf.js.git', PYTHON_BIN = 'python2.7', MOZCENTRAL_PREF_PREFIX = 'pdfjs', @@ -17,48 +19,147 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root MOZCENTRAL_STREAM_CONVERTER_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2291', FIREFOX_STREAM_CONVERTER_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb1'; -function preprocess(inFilename, outFilename, flags) { - // TODO make this really read line by line. - var lines = fs.readFileSync(inFilename).toString().split("\n"); - var totalLines = lines.length; - var out = ''; - var i = 0; - function readLine() { - if (i < totalLines) { - return lines[i++]; - } - return null; - } - function writeLine(line) { - out += line + '\n'; - } +var DEFINES = { + PRODUCTION: true, + // The main build targets: + GENERIC: false, + FIREFOX: false, + MOZCENTRAL: false, + B2G: false, + CHROME: false +}; - var s, state = 0, stack = []; - while ((s = readLine()) !== null) { - var m = new RegExp(/^\/\/\s*#(if|else|endif)\b(?:\s+(.*))?/).exec(s); - if (m) { - if (m[1] === "if") { - stack.push(state); - state = vm.runInNewContext(m[2], flags) ? 3 : 1; - } else if (m[1] === "else") { - state = state === 1 ? 3 : 2; +function extendDefines(obj) { + var ret = {}; + for (var key in DEFINES) + ret[key] = DEFINES[key]; + for (key in obj) + ret[key] = obj[key]; + return ret; +} + +var BuildHelper = { + /** + * A simple preprocessor that is based on the firefox preprocessor + * see (https://developer.mozilla.org/en/Build/Text_Preprocessor). The main + * difference is that this supports a subset of the commands and it supports + * preproccesor commands in html style comments. + * Currently Supported commands: + * - if + * - else + * - endif + * - include + * - expand + */ + preprocess: function preprocess(inFilename, outFilename, defines) { + // TODO make this really read line by line. + var lines = fs.readFileSync(inFilename).toString().split('\n'); + var totalLines = lines.length; + var out = ''; + var i = 0; + function readLine() { + if (i < totalLines) { + return lines[i++]; + } + return null; + } + var writeLine = typeof outFilename === 'function' ? outFilename : function(line) { + out += line + '\n'; + } + function include(file) { + var realPath = fs.realpathSync(inFilename); + var dir = path.dirname(realPath); + preprocess(path.join(dir, file), writeLine, defines); + } + function expand(line) { + line = line.replace(/__[\w]+__/g, function(variable) { + variable = variable.substring(2, variable.length - 2); + if (variable in defines) { + return defines[variable]; + } + return ''; + }); + writeLine(line); + } + + var s, state = 0, stack = []; + var control = /^(?:\/\/|)?$)?/; + var lineNumber = 0; + while ((s = readLine()) !== null) { + ++lineNumber; + var m = control.exec(s); + if (m) { + switch (m[1]) { + case 'if': + stack.push(state); + try { + state = vm.runInNewContext(m[2], defines) ? 3 : 1; + } catch (e) { + console.error('Could not evalute line \'' + m[2] + '\' at ' + + fs.realpathSync(inFilename) + ':' + lineNumber); + throw e; + } + break; + case 'else': + state = state === 1 ? 3 : 2; + break; + case 'endif': + state = stack.pop(); + break; + case 'expand': + if (state === 0 || state === 3) + expand(m[2]); + break; + case 'include': + if (state === 0 || state === 3) + include(m[2]); + break; + } } else { - state = stack.pop(); - } - } else { - if (state === 0) { - writeLine(s); - } else if(state === 3) { - writeLine(s.replace(/^\/\//g, " ")); + if (state === 0) { + writeLine(s); + } else if(state === 3) { + writeLine(s.replace(/^\/\/|^/g, " ")); + } } } - } - fs.writeFileSync(outFilename, out); -} + if (state !== 0 || stack.length !== 0) + throw new Error('Missing endif in preprocessor.'); + if (typeof outFilename !== 'function') + fs.writeFileSync(outFilename, out); + }, + /** + * Simplifies common build steps. + * @param setup + * .defines defines for preprocessors + * .copy array of arrays of source and destination pairs of files to copy + * .preprocess array of arrays of source and destination pairs of files + * run through preprocessor + */ + build: function build(setup) { + var defines = setup.defines; -target.pre = function() { - preprocess('in.txt', 'out.txt', {B2G: true}); -} + setup.copy.forEach(function(option) { + var source = option[0]; + var destination = option[1]; + cp('-R', source, destination); + }); + + setup.preprocess.forEach(function(option) { + var sources = option[0]; + var destination = option[1]; + + sources = ls('-R', sources); + sources.forEach(function(source) { + // ??? Warn if the source is wildcard and dest is file? + var destWithFolder = destination; + if (test('-d', destination)) + destWithFolder += '/' + path.basename(source); + BuildHelper.preprocess(source, destWithFolder, defines); + }); + }); + } +}; // // make all @@ -76,14 +177,59 @@ target.all = function() { // Production stuff // +// Files that need to be included in every build. +var COMMON_WEB_FILES = + ['web/viewer.css', + 'web/images', + 'web/debugger.js'], + COMMON_WEB_FILES_PREPROCESS = + ['web/viewer.js', + 'web/viewer.html']; + +// +// make generic +// Builds the generic production viewer that should be compatible with most +// modern HTML5 browsers. +// +target.generic = function() { + target.bundle(); + target.locale(); + + cd(ROOT_DIR); + echo(); + echo('### Creating generic viewer'); + + rm('-rf', GENERIC_DIR); + mkdir('-p', GENERIC_DIR); + mkdir('-p', GENERIC_DIR + BUILD_DIR); + mkdir('-p', GENERIC_DIR + '/web'); + + var defines = extendDefines({GENERIC: true}); + + var setup = { + defines: defines, + copy: [ + [COMMON_WEB_FILES, GENERIC_DIR + '/web'], + ['external/webL10n/l10n.js', GENERIC_DIR + '/web'], + ['web/compatibility.js', GENERIC_DIR + '/web'], + ['web/compressed.tracemonkey-pldi-09.pdf', GENERIC_DIR + '/web'], + ['web/locale.properties', GENERIC_DIR + '/web'] + ], + preprocess: [ + [BUILD_TARGET, GENERIC_DIR + BUILD_TARGET], + [COMMON_WEB_FILES_PREPROCESS, GENERIC_DIR + '/web'] + ] + }; + BuildHelper.build(setup); +}; + // // make web // Generates the website for the project, by checking out the gh-pages branch underneath // the build directory, and then moving the various viewer files into place. // target.web = function() { - target.production(); - target.locale(); + target.generic(); target.extension(); target.pagesrepo(); @@ -91,25 +237,18 @@ target.web = function() { echo(); echo('### Creating web site'); - var GH_PAGES_SRC_FILES = [ - 'web/*', - 'external/webL10n/l10n.js' - ]; - - cp(BUILD_TARGET, GH_PAGES_DIR + BUILD_TARGET); - cp('-R', GH_PAGES_SRC_FILES, GH_PAGES_DIR + '/web'); + cp('-R', GENERIC_DIR + '/*', GH_PAGES_DIR); cp(FIREFOX_BUILD_DIR + '/*.xpi', FIREFOX_BUILD_DIR + '/*.rdf', - GH_PAGES_DIR + EXTENSION_SRC_DIR + 'firefox/'); - cp(GH_PAGES_DIR + '/web/index.html.template', GH_PAGES_DIR + '/index.html'); - mv('-f', GH_PAGES_DIR + '/web/viewer-production.html', - GH_PAGES_DIR + '/web/viewer.html'); + GH_PAGES_DIR + EXTENSION_SRC_DIR + 'firefox/'); + cp('web/index.html.template', GH_PAGES_DIR + '/index.html'); + cd(GH_PAGES_DIR); exec('git add -A'); echo(); echo("Website built in " + GH_PAGES_DIR); echo("Don't forget to cd into " + GH_PAGES_DIR + - " and issue 'git commit' to push changes."); + " and issue 'git commit' to push changes."); }; // @@ -169,20 +308,10 @@ target.locale = function() { chromeManifestContent.to(CHROME_MANIFEST_OUTPUT); }; -// -// make production -// Creates production output (pdf.js, and corresponding changes to web/ files) -// -target.production = function() { - target.bundle(); - target.viewer(); -}; - // // make bundle // Bundles all source files into one wrapper 'pdf.js' file, in the given order. // - target.bundle = function() { cd(ROOT_DIR); echo(); @@ -223,29 +352,12 @@ target.bundle = function() { bundleVersion = exec('git log --format="%h" -n 1', {silent: true}).output.replace('\n', ''); - sed(/.*PDFJSSCRIPT_INCLUDE_ALL.*\n/, bundle, 'pdf.js') - .to(ROOT_DIR + BUILD_TARGET); - sed('-i', 'PDFJSSCRIPT_BUNDLE_VER', bundleVersion, ROOT_DIR + BUILD_TARGET); + // This just preprocesses the empty pdf.js file, we don't actually want to + // preprocess everything yet since other build targets use this file. + BuildHelper.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET, + {BUNDLE: bundle, BUNDLE_VERSION: bundleVersion}); }; -// -// make viewer -// Changes development - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/web/viewer.js b/web/viewer.js index f6874f9a9..e2b2e1260 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -90,6 +90,7 @@ var ProgressBar = (function ProgressBarClosure() { return ProgressBar; })(); +//#if FIREFOX || MOZCENTRAL var FirefoxCom = (function FirefoxComClosure() { return { /** @@ -150,6 +151,7 @@ var FirefoxCom = (function FirefoxComClosure() { } }; })(); +//#endif // Settings Manager - This is a utility for saving settings // First we see if localStorage is available @@ -167,17 +169,17 @@ var Settings = (function SettingsClosure() { } })(); - var isFirefoxExtension = PDFJS.isFirefoxExtension; - function Settings(fingerprint) { var database = null; var index; - if (isFirefoxExtension) - database = FirefoxCom.requestSync('getDatabase', null) || '{}'; - else if (isLocalStorageEnabled) +//#if !(FIREFOX || MOZCENTRAL) + if (isLocalStorageEnabled) database = localStorage.getItem('database') || '{}'; else return false; +//#else +// database = FirefoxCom.requestSync('getDatabase', null) || '{}'; +//#endif database = JSON.parse(database); if (!('files' in database)) @@ -205,10 +207,12 @@ var Settings = (function SettingsClosure() { var file = this.file; file[name] = val; var database = JSON.stringify(this.database); - if (isFirefoxExtension) - FirefoxCom.requestSync('setDatabase', database); - else if (isLocalStorageEnabled) +//#if !(FIREFOX || MOZCENTRAL) + if (isLocalStorageEnabled) localStorage.setItem('database', database); +//#else +// FirefoxCom.requestSync('setDatabase', database); +//#endif }, get: function settingsGet(name, defaultValue) { @@ -460,52 +464,54 @@ var PDFView = { } var url = this.url.split('#')[0]; - if (PDFJS.isFirefoxExtension) { - // Document isn't ready just try to download with the url. - if (!this.pdfDocument) { - noData(); - return; - } - this.pdfDocument.getData().then( - function getDataSuccess(data) { - var bb = new MozBlobBuilder(); - bb.append(data.buffer); - var blobUrl = window.URL.createObjectURL( - bb.getBlob('application/pdf')); - - FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url }, - function response(err) { - if (err) { - // This error won't really be helpful because it's likely the - // fallback won't work either (or is already open). - PDFView.error('PDF failed to download.'); - } - window.URL.revokeObjectURL(blobUrl); - } - ); - }, - noData // Error ocurred try downloading with just the url. - ); - } else { - url += '#pdfjs.action=download', '_parent'; - window.open(url, '_parent'); - } +//#if !(FIREFOX || MOZCENTRAL) + url += '#pdfjs.action=download', '_parent'; + window.open(url, '_parent'); +//#else +// // Document isn't ready just try to download with the url. +// if (!this.pdfDocument) { +// noData(); +// return; +// } +// this.pdfDocument.getData().then( +// function getDataSuccess(data) { +// var bb = new MozBlobBuilder(); +// bb.append(data.buffer); +// var blobUrl = window.URL.createObjectURL( +// bb.getBlob('application/pdf')); +// +// FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url }, +// function response(err) { +// if (err) { +// // This error won't really be helpful because it's likely the +// // fallback won't work either (or is already open). +// PDFView.error('PDF failed to download.'); +// } +// window.URL.revokeObjectURL(blobUrl); +// } +// ); +// }, +// noData // Error ocurred try downloading with just the url. +// ); +//#endif }, fallback: function pdfViewFallback() { - if (!PDFJS.isFirefoxExtension) +//#if !(FIREFOX || MOZCENTRAL) return; - // Only trigger the fallback once so we don't spam the user with messages - // for one PDF. - if (this.fellback) - return; - this.fellback = true; - var url = this.url.split('#')[0]; - FirefoxCom.request('fallback', url, function response(download) { - if (!download) - return; - PDFView.download(); - }); +//#else +// // Only trigger the fallback once so we don't spam the user with messages +// // for one PDF. +// if (this.fellback) +// return; +// this.fellback = true; +// var url = this.url.split('#')[0]; +// FirefoxCom.request('fallback', url, function response(download) { +// if (!download) +// return; +// PDFView.download(); +// }); +//#endif }, navigateTo: function pdfViewNavigateTo(dest) { @@ -557,9 +563,11 @@ var PDFView = { * @param {String} anchor The anchor hash include the #. */ getAnchorUrl: function getAnchorUrl(anchor) { - if (PDFJS.isFirefoxExtension) - return this.url.split('#')[0] + anchor; +//#if !(FIREFOX || MOZCENTRAL) return anchor; +//#else +// return this.url.split('#')[0] + anchor; +//#endif }, /** @@ -593,11 +601,7 @@ var PDFView = { } } } - if (PDFJS.isFirefoxExtension) { - console.error(message + '\n' + moreInfoText); - this.fallback(); - return; - } +//#if !(FIREFOX || MOZCENTRAL) var errorWrapper = document.getElementById('errorWrapper'); errorWrapper.removeAttribute('hidden'); @@ -627,6 +631,10 @@ var PDFView = { errorMoreInfo.value = moreInfoText; errorMoreInfo.rows = moreInfoText.split('\n').length - 1; +//#else +// console.error(message + '\n' + moreInfoText); +// this.fallback(); +//#endif }, progress: function pdfViewProgress(level) { @@ -1804,15 +1812,21 @@ window.addEventListener('load', function webViewerLoad(evt) { PDFView.initialize(); var params = PDFView.parseQueryString(document.location.search.substring(1)); - var file = PDFJS.isFirefoxExtension ? - window.location.toString() : params.file || kDefaultURL; +//#if !(FIREFOX || MOZCENTRAL) + var file = params.file || kDefaultURL; +//#else +//var file = window.location.toString() +//#endif - if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader || - !window.FileList || !window.Blob) { +//#if !(FIREFOX || MOZCENTRAL) + if (!window.File || !window.FileReader || !window.FileList || !window.Blob) { document.getElementById('openFile').setAttribute('hidden', 'true'); } else { document.getElementById('fileInput').value = null; } +//#else +//document.getElementById('openFile').setAttribute('hidden', 'true'); +//#endif // Special debugging flags in the hash section of the URL. var hash = document.location.hash.substring(1); @@ -1821,18 +1835,21 @@ window.addEventListener('load', function webViewerLoad(evt) { if ('disableWorker' in hashParams) PDFJS.disableWorker = (hashParams['disableWorker'] === 'true'); - if (!PDFJS.isFirefoxExtension) { - var locale = navigator.language; - if ('locale' in hashParams) - locale = hashParams['locale']; - mozL10n.language.code = locale; - } +//#if !(FIREFOX || MOZCENTRAL) + var locale = navigator.language; + if ('locale' in hashParams) + locale = hashParams['locale']; + mozL10n.language.code = locale; +//#endif if ('disableTextLayer' in hashParams) PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true'); - if ('pdfBug' in hashParams && - (!PDFJS.isFirefoxExtension || FirefoxCom.requestSync('pdfBugEnabled'))) { +//#if !(FIREFOX || MOZCENTRAL) + if ('pdfBug' in hashParams) { +//#else +//if ('pdfBug' in hashParams && FirefoxCom.requestSync('pdfBugEnabled')) { +//#endif PDFJS.pdfBug = true; var pdfBug = hashParams['pdfBug']; var enabled = pdfBug.split(','); @@ -1840,10 +1857,12 @@ window.addEventListener('load', function webViewerLoad(evt) { PDFBug.init(); } - if (!PDFJS.isFirefoxExtension || - (PDFJS.isFirefoxExtension && FirefoxCom.requestSync('searchEnabled'))) { - document.querySelector('#viewSearch').classList.remove('hidden'); - } +//#if !(FIREFOX || MOZCENTRAL) +//#else +//if (FirefoxCom.requestSync('searchEnabled')) { +// document.querySelector('#viewSearch').classList.remove('hidden'); +//} +//#endif if (!PDFView.supportsPrinting) { document.getElementById('print').classList.add('hidden'); @@ -2143,19 +2162,19 @@ window.addEventListener('afterprint', function afterPrint(evt) { })(); //#if B2G -// window.navigator.mozSetMessageHandler('activity', function(activity) { -// var url = activity.source.data.url; -// // Temporarily get the data here since the cross domain xhr is broken in -// // the worker currently, see bug 761227. -// var params = { -// url: url, -// error: function(e) { -// PDFView.error(mozL10n.get('loading_error', null, -// 'An error occurred while loading the PDF.'), e); -// } -// }; -// PDFJS.getPdf(params, function successCallback(data) { -// PDFView.open(data, 0); -// }); -// }); +//window.navigator.mozSetMessageHandler('activity', function(activity) { +// var url = activity.source.data.url; +// // Temporarily get the data here since the cross domain xhr is broken in +// // the worker currently, see bug 761227. +// var params = { +// url: url, +// error: function(e) { +// PDFView.error(mozL10n.get('loading_error', null, +// 'An error occurred while loading the PDF.'), e); +// } +// }; +// PDFJS.getPdf(params, function successCallback(data) { +// PDFView.open(data, 0); +// }); +//}); //#endif From dd22f449538a2a56c09e91e390874ac6da2e4847 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 11:52:14 -0700 Subject: [PATCH 03/15] Update the readme to reflect build changes. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3b8d86bb1..34b1a3f5e 100644 --- a/README.md +++ b/README.md @@ -61,13 +61,13 @@ You can also view all the test pdf files on the right side serving + http://localhost:8888/test/pdfs/?frame -### Building pdf.js +### Building pdf.js. -In order to bundle all `src/` files into a final `pdf.js`, issue: +In order to bundle all `src/` files into a final `pdf.js` and build the generic viewer, issue: - $ node make bundle + $ node make generic -This will generate the file `build/pdf.js` that can be included in your final project. (WARNING: That's a large file! Consider minifying it). +This will generate the file `build/generic/build/pdf.js` that can be included in your final project. The pdf.js file is large and should be minified for production. Also, if you would like to support more browsers than firefox you'll also need to include `compatibility.js` from `build/generic/web/`. # Learning From 2c1eae5819933f9ef8fe4d8776debb7af6fcb4dd Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 12:05:03 -0700 Subject: [PATCH 04/15] Remove trailing whitespace. --- make.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make.js b/make.js index bb9896391..670aa6645 100755 --- a/make.js +++ b/make.js @@ -178,7 +178,7 @@ target.all = function() { // // Files that need to be included in every build. -var COMMON_WEB_FILES = +var COMMON_WEB_FILES = ['web/viewer.css', 'web/images', 'web/debugger.js'], From 44a6afb282e298581ad61284bcce28da38197e2c Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 12:16:28 -0700 Subject: [PATCH 05/15] Fix mozcentral build. --- web/viewer.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/viewer.html b/web/viewer.html index b97ba3a4c..daec51172 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -5,7 +5,7 @@ PDF.js viewer - + @@ -14,7 +14,7 @@ - + From e0a6b233dc6880a357024b5d7955902f01b0c7cb Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 14:27:42 -0700 Subject: [PATCH 06/15] Move builder/preprocessor into its own file. --- external/builder/builder.js | 142 ++++++++++++++++++++++++++++++++ make.js | 160 +++--------------------------------- 2 files changed, 155 insertions(+), 147 deletions(-) create mode 100644 external/builder/builder.js diff --git a/external/builder/builder.js b/external/builder/builder.js new file mode 100644 index 000000000..6eb0cd6ae --- /dev/null +++ b/external/builder/builder.js @@ -0,0 +1,142 @@ +require('../shelljs/make'); +var fs = require('fs'), + path = require('path'), + vm = require('vm'); + +/** + * A simple preprocessor that is based on the firefox preprocessor + * see (https://developer.mozilla.org/en/Build/Text_Preprocessor). The main + * difference is that this supports a subset of the commands and it supports + * preproccesor commands in html style comments. + * Currently Supported commands: + * - if + * - else + * - endif + * - include + * - expand + */ +function preprocess(inFilename, outFilename, defines) { + // TODO make this really read line by line. + var lines = fs.readFileSync(inFilename).toString().split('\n'); + var totalLines = lines.length; + var out = ''; + var i = 0; + function readLine() { + if (i < totalLines) { + return lines[i++]; + } + return null; + } + var writeLine = typeof outFilename === 'function' ? outFilename : function(line) { + out += line + '\n'; + } + function include(file) { + var realPath = fs.realpathSync(inFilename); + var dir = path.dirname(realPath); + preprocess(path.join(dir, file), writeLine, defines); + } + function expand(line) { + line = line.replace(/__[\w]+__/g, function(variable) { + variable = variable.substring(2, variable.length - 2); + if (variable in defines) { + return defines[variable]; + } + return ''; + }); + writeLine(line); + } + + var s, state = 0, stack = []; + var control = /^(?:\/\/|)?$)?/; + var lineNumber = 0; + while ((s = readLine()) !== null) { + ++lineNumber; + var m = control.exec(s); + if (m) { + switch (m[1]) { + case 'if': + stack.push(state); + try { + state = vm.runInNewContext(m[2], defines) ? 3 : 1; + } catch (e) { + console.error('Could not evalute line \'' + m[2] + '\' at ' + + fs.realpathSync(inFilename) + ':' + lineNumber); + throw e; + } + break; + case 'else': + state = state === 1 ? 3 : 2; + break; + case 'endif': + state = stack.pop(); + break; + case 'expand': + if (state === 0 || state === 3) + expand(m[2]); + break; + case 'include': + if (state === 0 || state === 3) + include(m[2]); + break; + } + } else { + if (state === 0) { + writeLine(s); + } else if(state === 3) { + writeLine(s.replace(/^\/\/|^/g, " ")); + } + } + } + if (state !== 0 || stack.length !== 0) + throw new Error('Missing endif in preprocessor.'); + if (typeof outFilename !== 'function') + fs.writeFileSync(outFilename, out); +} +exports.preprocess = preprocess; + +/** + * Simplifies common build steps. + * @param setup + * .defines defines for preprocessors + * .copy array of arrays of source and destination pairs of files to copy + * .preprocess array of arrays of source and destination pairs of files + * run through preprocessor + */ +function build(setup) { + var defines = setup.defines; + + setup.copy.forEach(function(option) { + var source = option[0]; + var destination = option[1]; + cp('-R', source, destination); + }); + + setup.preprocess.forEach(function(option) { + var sources = option[0]; + var destination = option[1]; + + sources = ls('-R', sources); + sources.forEach(function(source) { + // ??? Warn if the source is wildcard and dest is file? + var destWithFolder = destination; + if (test('-d', destination)) + destWithFolder += '/' + path.basename(source); + preprocess(source, destWithFolder, defines); + }); + }); +} +exports.build = build; + +/** + * Merge two defines arrays. Values in the second param will override values in + * the first. + */ +function merge(defaults, defines) { + var ret = {}; + for (var key in defaults) + ret[key] = defaults[key]; + for (key in defines) + ret[key] = defines[key]; + return ret; +} +exports.merge = merge; diff --git a/make.js b/make.js index 670aa6645..1d2e5cfcf 100755 --- a/make.js +++ b/make.js @@ -1,8 +1,6 @@ #!/usr/bin/env node require('./external/shelljs/make'); -var fs = require('fs'); -var path = require('path'); -var vm = require('vm'); +var builder = require('./external/builder/builder.js'); var ROOT_DIR = __dirname + '/', // absolute path to project's root BUILD_DIR = 'build/', @@ -29,138 +27,6 @@ var DEFINES = { CHROME: false }; -function extendDefines(obj) { - var ret = {}; - for (var key in DEFINES) - ret[key] = DEFINES[key]; - for (key in obj) - ret[key] = obj[key]; - return ret; -} - -var BuildHelper = { - /** - * A simple preprocessor that is based on the firefox preprocessor - * see (https://developer.mozilla.org/en/Build/Text_Preprocessor). The main - * difference is that this supports a subset of the commands and it supports - * preproccesor commands in html style comments. - * Currently Supported commands: - * - if - * - else - * - endif - * - include - * - expand - */ - preprocess: function preprocess(inFilename, outFilename, defines) { - // TODO make this really read line by line. - var lines = fs.readFileSync(inFilename).toString().split('\n'); - var totalLines = lines.length; - var out = ''; - var i = 0; - function readLine() { - if (i < totalLines) { - return lines[i++]; - } - return null; - } - var writeLine = typeof outFilename === 'function' ? outFilename : function(line) { - out += line + '\n'; - } - function include(file) { - var realPath = fs.realpathSync(inFilename); - var dir = path.dirname(realPath); - preprocess(path.join(dir, file), writeLine, defines); - } - function expand(line) { - line = line.replace(/__[\w]+__/g, function(variable) { - variable = variable.substring(2, variable.length - 2); - if (variable in defines) { - return defines[variable]; - } - return ''; - }); - writeLine(line); - } - - var s, state = 0, stack = []; - var control = /^(?:\/\/|)?$)?/; - var lineNumber = 0; - while ((s = readLine()) !== null) { - ++lineNumber; - var m = control.exec(s); - if (m) { - switch (m[1]) { - case 'if': - stack.push(state); - try { - state = vm.runInNewContext(m[2], defines) ? 3 : 1; - } catch (e) { - console.error('Could not evalute line \'' + m[2] + '\' at ' + - fs.realpathSync(inFilename) + ':' + lineNumber); - throw e; - } - break; - case 'else': - state = state === 1 ? 3 : 2; - break; - case 'endif': - state = stack.pop(); - break; - case 'expand': - if (state === 0 || state === 3) - expand(m[2]); - break; - case 'include': - if (state === 0 || state === 3) - include(m[2]); - break; - } - } else { - if (state === 0) { - writeLine(s); - } else if(state === 3) { - writeLine(s.replace(/^\/\/|^/g, " ")); - } - } - } - if (state !== 0 || stack.length !== 0) - throw new Error('Missing endif in preprocessor.'); - if (typeof outFilename !== 'function') - fs.writeFileSync(outFilename, out); - }, - /** - * Simplifies common build steps. - * @param setup - * .defines defines for preprocessors - * .copy array of arrays of source and destination pairs of files to copy - * .preprocess array of arrays of source and destination pairs of files - * run through preprocessor - */ - build: function build(setup) { - var defines = setup.defines; - - setup.copy.forEach(function(option) { - var source = option[0]; - var destination = option[1]; - cp('-R', source, destination); - }); - - setup.preprocess.forEach(function(option) { - var sources = option[0]; - var destination = option[1]; - - sources = ls('-R', sources); - sources.forEach(function(source) { - // ??? Warn if the source is wildcard and dest is file? - var destWithFolder = destination; - if (test('-d', destination)) - destWithFolder += '/' + path.basename(source); - BuildHelper.preprocess(source, destWithFolder, defines); - }); - }); - } -}; - // // make all // @@ -204,7 +70,7 @@ target.generic = function() { mkdir('-p', GENERIC_DIR + BUILD_DIR); mkdir('-p', GENERIC_DIR + '/web'); - var defines = extendDefines({GENERIC: true}); + var defines = builder.merge(DEFINES, {GENERIC: true}); var setup = { defines: defines, @@ -220,7 +86,7 @@ target.generic = function() { [COMMON_WEB_FILES_PREPROCESS, GENERIC_DIR + '/web'] ] }; - BuildHelper.build(setup); + builder.build(setup); }; // @@ -354,7 +220,7 @@ target.bundle = function() { // This just preprocesses the empty pdf.js file, we don't actually want to // preprocess everything yet since other build targets use this file. - BuildHelper.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET, + builder.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET, {BUNDLE: bundle, BUNDLE_VERSION: bundleVersion}); }; @@ -435,7 +301,7 @@ target.firefox = function() { cd(ROOT_DIR); echo(); echo('### Building Firefox extension'); - var defines = extendDefines({FIREFOX: true}); + var defines = builder.merge(DEFINES, {FIREFOX: true}); var FIREFOX_BUILD_CONTENT_DIR = FIREFOX_BUILD_DIR + '/content/', FIREFOX_EXTENSION_DIR = 'extensions/firefox/', @@ -488,7 +354,7 @@ target.firefox = function() { [COMMON_WEB_FILES_PREPROCESS, FIREFOX_BUILD_CONTENT_DIR + '/web'] ] }; - BuildHelper.build(setup); + builder.build(setup); // Remove '.DS_Store' and other hidden files find(FIREFOX_BUILD_DIR).forEach(function(file) { @@ -531,7 +397,7 @@ target.mozcentral = function() { cd(ROOT_DIR); echo(); echo('### Building mozilla-central extension'); - var defines = extendDefines({MOZCENTRAL: true}); + var defines = builder.merge(DEFINES, {MOZCENTRAL: true}); var MOZCENTRAL_DIR = BUILD_DIR + 'mozcentral/', MOZCENTRAL_EXTENSION_DIR = MOZCENTRAL_DIR + 'browser/extensions/pdfjs/', @@ -586,7 +452,7 @@ target.mozcentral = function() { [COMMON_WEB_FILES_PREPROCESS, MOZCENTRAL_CONTENT_DIR + '/web'] ] }; - BuildHelper.build(setup); + builder.build(setup); // Remove '.DS_Store' and other hidden files find(MOZCENTRAL_DIR).forEach(function(file) { @@ -624,9 +490,9 @@ target.b2g = function() { echo('### Building B2G (Firefox OS App)'); var B2G_BUILD_DIR = BUILD_DIR + '/b2g/', B2G_BUILD_CONTENT_DIR = B2G_BUILD_DIR + '/content/'; - var defines = extendDefines({ B2G: true }); + var defines = builder.merge(DEFINES, { B2G: true }); target.bundle(); - + // Clear out everything in the b2g build directory cd(ROOT_DIR); rm('-Rf', B2G_BUILD_DIR); @@ -646,7 +512,7 @@ target.b2g = function() { [BUILD_TARGET, B2G_BUILD_CONTENT_DIR + BUILD_TARGET] ] }; - BuildHelper.build(setup); + builder.build(setup); }; // @@ -656,7 +522,7 @@ target.chrome = function() { cd(ROOT_DIR); echo(); echo('### Building Chrome extension'); - var defines = extendDefines({CHROME: true}); + var defines = builder.merge(DEFINES, {CHROME: true}); var CHROME_BUILD_DIR = BUILD_DIR + '/chrome/', CHROME_BUILD_CONTENT_DIR = CHROME_BUILD_DIR + '/content/'; @@ -684,7 +550,7 @@ target.chrome = function() { ['web/locale.properties', CHROME_BUILD_CONTENT_DIR + '/web'] ] }; - BuildHelper.build(setup); + builder.build(setup); }; From 11be208388a7760240ad4ebd841e639d4e488227 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 15:31:25 -0700 Subject: [PATCH 07/15] Move firefoxcom to its own file. --- web/firefoxcom.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++ web/viewer.js | 61 +---------------------------------------------- 2 files changed, 61 insertions(+), 60 deletions(-) create mode 100644 web/firefoxcom.js diff --git a/web/firefoxcom.js b/web/firefoxcom.js new file mode 100644 index 000000000..f60c26aed --- /dev/null +++ b/web/firefoxcom.js @@ -0,0 +1,60 @@ +var FirefoxCom = (function FirefoxComClosure() { + return { + /** + * Creates an event that the extension is listening for and will + * synchronously respond to. + * NOTE: It is reccomended to use request() instead since one day we may not + * be able to synchronously reply. + * @param {String} action The action to trigger. + * @param {String} data Optional data to send. + * @return {*} The response. + */ + requestSync: function(action, data) { + var request = document.createTextNode(''); + request.setUserData('action', action, null); + request.setUserData('data', data, null); + request.setUserData('sync', true, null); + document.documentElement.appendChild(request); + + var sender = document.createEvent('Events'); + sender.initEvent('pdf.js.message', true, false); + request.dispatchEvent(sender); + var response = request.getUserData('response'); + document.documentElement.removeChild(request); + return response; + }, + /** + * Creates an event that the extension is listening for and will + * asynchronously respond by calling the callback. + * @param {String} action The action to trigger. + * @param {String} data Optional data to send. + * @param {Function} callback Optional response callback that will be called + * with one data argument. + */ + request: function(action, data, callback) { + var request = document.createTextNode(''); + request.setUserData('action', action, null); + request.setUserData('data', data, null); + request.setUserData('sync', false, null); + if (callback) { + request.setUserData('callback', callback, null); + + document.addEventListener('pdf.js.response', function listener(event) { + var node = event.target, + callback = node.getUserData('callback'), + response = node.getUserData('response'); + + document.documentElement.removeChild(node); + + document.removeEventListener('pdf.js.response', listener, false); + return callback(response); + }, false); + } + document.documentElement.appendChild(request); + + var sender = document.createEvent('HTMLEvents'); + sender.initEvent('pdf.js.message', true, false); + return request.dispatchEvent(sender); + } + }; +})(); diff --git a/web/viewer.js b/web/viewer.js index e2b2e1260..92c38c31e 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -91,66 +91,7 @@ var ProgressBar = (function ProgressBarClosure() { })(); //#if FIREFOX || MOZCENTRAL -var FirefoxCom = (function FirefoxComClosure() { - return { - /** - * Creates an event that the extension is listening for and will - * synchronously respond to. - * NOTE: It is reccomended to use request() instead since one day we may not - * be able to synchronously reply. - * @param {String} action The action to trigger. - * @param {String} data Optional data to send. - * @return {*} The response. - */ - requestSync: function(action, data) { - var request = document.createTextNode(''); - request.setUserData('action', action, null); - request.setUserData('data', data, null); - request.setUserData('sync', true, null); - document.documentElement.appendChild(request); - - var sender = document.createEvent('Events'); - sender.initEvent('pdf.js.message', true, false); - request.dispatchEvent(sender); - var response = request.getUserData('response'); - document.documentElement.removeChild(request); - return response; - }, - /** - * Creates an event that the extension is listening for and will - * asynchronously respond by calling the callback. - * @param {String} action The action to trigger. - * @param {String} data Optional data to send. - * @param {Function} callback Optional response callback that will be called - * with one data argument. - */ - request: function(action, data, callback) { - var request = document.createTextNode(''); - request.setUserData('action', action, null); - request.setUserData('data', data, null); - request.setUserData('sync', false, null); - if (callback) { - request.setUserData('callback', callback, null); - - document.addEventListener('pdf.js.response', function listener(event) { - var node = event.target, - callback = node.getUserData('callback'), - response = node.getUserData('response'); - - document.documentElement.removeChild(node); - - document.removeEventListener('pdf.js.response', listener, false); - return callback(response); - }, false); - } - document.documentElement.appendChild(request); - - var sender = document.createEvent('HTMLEvents'); - sender.initEvent('pdf.js.message', true, false); - return request.dispatchEvent(sender); - } - }; -})(); +//#include firefoxcom.js //#endif // Settings Manager - This is a utility for saving settings From 0bf583412a4817d8b0c6eb62eaf558b1fc65dcf4 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 2 Aug 2012 09:09:07 -0700 Subject: [PATCH 08/15] Add missing b2g snippet. --- web/viewer-snippet-b2g.html | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 web/viewer-snippet-b2g.html diff --git a/web/viewer-snippet-b2g.html b/web/viewer-snippet-b2g.html new file mode 100644 index 000000000..86a09d255 --- /dev/null +++ b/web/viewer-snippet-b2g.html @@ -0,0 +1,9 @@ + + + + + From c515bd2c523c5ce4c3c2b77d6c18b0c25ca7f389 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 6 Aug 2012 11:47:34 -0500 Subject: [PATCH 09/15] Adds overrideMimeType for IE10 --- web/compatibility.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/web/compatibility.js b/web/compatibility.js index 4b7119c63..2b8fb8c84 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -127,21 +127,24 @@ // No XMLHttpRequest.response ? (function checkXMLHttpRequestResponseCompatibility() { var xhrPrototype = XMLHttpRequest.prototype; + if (!('overrideMimeType' in xhrPrototype)) { + // IE10 might have response, but not overrideMimeType + Object.defineProperty(xhrPrototype, 'overrideMimeType', { + value: function xmlHttpRequestOverrideMimeType(mimeType) {} + }); + } if ('response' in xhrPrototype || 'mozResponseArrayBuffer' in xhrPrototype || 'mozResponse' in xhrPrototype || 'responseArrayBuffer' in xhrPrototype) return; - // IE ? + // IE9 ? if (typeof VBArray !== 'undefined') { Object.defineProperty(xhrPrototype, 'response', { get: function xmlHttpRequestResponseGet() { return new Uint8Array(new VBArray(this.responseBody).toArray()); } }); - Object.defineProperty(xhrPrototype, 'overrideMimeType', { - value: function xmlHttpRequestOverrideMimeType(mimeType) {} - }); return; } From b272cb7d1d692db353eb52c67f91fdf7e4ba4c4a Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 6 Aug 2012 12:50:47 -0500 Subject: [PATCH 10/15] Using readAsArrayBuffer --- web/compatibility.js | 36 ++++++++++++++++++++++++++++++++++++ web/viewer.js | 11 ++--------- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/web/compatibility.js b/web/compatibility.js index 2b8fb8c84..5a16b3d7f 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -124,6 +124,42 @@ }; })(); +// No readAsArrayBuffer ? +(function checkFileReaderReadAsArrayBuffer() { + if (typeof FileReader === 'undefined') + return; // FileReader is not implemented + var frPrototype = FileReader.prototype; + // Older versions of Firefox might not have readAsArrayBuffer + if ('readAsArrayBuffer' in frPrototype) + return; // readAsArrayBuffer is implemented + Object.defineProperty(frPrototype, 'readAsArrayBuffer', { + value: function fileReaderReadAsArrayBuffer(blob) { + var fileReader = new FileReader(); + var originalReader = this; + fileReader.onload = function fileReaderOnload(evt) { + var data = evt.target.result; + var buffer = new ArrayBuffer(data.length); + var uint8Array = new Uint8Array(buffer); + + for (var i = 0; i < data.length; i++) + uint8Array[i] = data.charCodeAt(i); + + Object.defineProperty(originalReader, 'result', { + value: buffer, + enumerable: true, + writable: false, + configurable: true + }); + + var event = document.createEvent('HTMLEvents'); + event.initEvent('load', false, false); + originalReader.dispatchEvent(event); + }; + fileReader.readAsBinaryString(blob); + } + }); +})(); + // No XMLHttpRequest.response ? (function checkXMLHttpRequestResponseCompatibility() { var xhrPrototype = XMLHttpRequest.prototype; diff --git a/web/viewer.js b/web/viewer.js index 40102852b..324f229cb 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1944,20 +1944,13 @@ window.addEventListener('change', function webViewerChange(evt) { // Read the local file into a Uint8Array. var fileReader = new FileReader(); fileReader.onload = function webViewerChangeFileReaderOnload(evt) { - var data = evt.target.result; - var buffer = new ArrayBuffer(data.length); + var buffer = evt.target.result; var uint8Array = new Uint8Array(buffer); - - for (var i = 0; i < data.length; i++) - uint8Array[i] = data.charCodeAt(i); - PDFView.open(uint8Array, 0); }; - // Read as a binary string since "readAsArrayBuffer" is not yet - // implemented in Firefox. var file = files[0]; - fileReader.readAsBinaryString(file); + fileReader.readAsArrayBuffer(file); document.title = file.name; // URL does not reflect proper document location - hiding some icons. From a114d13308dea037045ac00a5491901c7c5ce0c7 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Tue, 7 Aug 2012 17:00:42 +0200 Subject: [PATCH 11/15] Fix some minor issues/nits detected by JetBrains' WebStorm inspector. --- web/viewer.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index 40102852b..237c082db 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -177,7 +177,7 @@ var Settings = (function SettingsClosure() { else if (isLocalStorageEnabled) database = localStorage.getItem('database') || '{}'; else - return false; + return; database = JSON.parse(database); if (!('files' in database)) @@ -351,8 +351,8 @@ var PDFView = { set page(val) { var pages = this.pages; var input = document.getElementById('pageNumber'); + var event = document.createEvent('UIEvents'); if (!(0 < val && val <= pages.length)) { - var event = document.createEvent('UIEvents'); event.initUIEvent('pagechange', false, false, window, 0); event.pageNumber = this.page; window.dispatchEvent(event); @@ -361,7 +361,6 @@ var PDFView = { pages[val - 1].updateStats(); currentPageNumber = val; - var event = document.createEvent('UIEvents'); event.initUIEvent('pagechange', false, false, window, 0); event.pageNumber = val; window.dispatchEvent(event); @@ -487,7 +486,7 @@ var PDFView = { noData // Error ocurred try downloading with just the url. ); } else { - url += '#pdfjs.action=download', '_parent'; + url += '#pdfjs.action=download'; window.open(url, '_parent'); } }, @@ -795,7 +794,7 @@ var PDFView = { // 2 if last scrolled up page before the visible pages var numVisible = visibleViews.length; if (numVisible === 0) { - info('No visible views.'); + //info('No visible views.'); return false; } for (var i = 0; i < numVisible; ++i) { @@ -944,7 +943,6 @@ var PDFView = { } else { this.page = pageNumber; // simple page } - return; } } else if (/^\d+$/.test(hash)) // page number this.page = hash; @@ -1015,7 +1013,7 @@ var PDFView = { extractPageText(pageIndex + 1); } ); - }; + } extractPageText(0); }, @@ -1701,13 +1699,13 @@ var CustomStyle = (function CustomStyleClosure() { //if all fails then set to undefined return (_cache[propName] = 'undefined'); - } + }; CustomStyle.setProp = function set(propName, element, str) { var prop = this.getProp(propName); if (prop != 'undefined') element.style[prop] = str; - } + }; return CustomStyle; })(); @@ -1776,7 +1774,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { // Resume rendering renderTimer = setInterval(renderTextLayer, renderInterval); }, resumeInterval); - }; // textLayerOnScroll + } // textLayerOnScroll window.addEventListener('scroll', textLayerOnScroll, false); }; // endLayout From d01071f426c0d782f46531d7436323b29cb29882 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Tue, 7 Aug 2012 17:54:05 +0200 Subject: [PATCH 12/15] Remove the commented out call to info() --- web/viewer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/viewer.js b/web/viewer.js index 237c082db..eb3a1cfbb 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -794,7 +794,6 @@ var PDFView = { // 2 if last scrolled up page before the visible pages var numVisible = visibleViews.length; if (numVisible === 0) { - //info('No visible views.'); return false; } for (var i = 0; i < numVisible; ++i) { From 2ca8c0d99975a0ef11e032eccae71dd7d79ade9c Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 8 Aug 2012 09:07:31 -0700 Subject: [PATCH 13/15] Cleanup references to dom elements. --- src/canvas.js | 5 ++++- web/viewer.js | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/canvas.js b/src/canvas.js index 058b57b7e..122dd5e59 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -1258,7 +1258,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { return CanvasGraphics; })(); -if (!isWorker) { +function checkPutBinaryImageDataCompatibility() { // Feature detection if the browser can use an Uint8Array directly as imgData. var canvas = document.createElement('canvas'); canvas.width = 1; @@ -1293,3 +1293,6 @@ if (!isWorker) { }; } } +if (!isWorker) { + checkPutBinaryImageDataCompatibility(); +} diff --git a/web/viewer.js b/web/viewer.js index a631bc004..b8118567c 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1707,6 +1707,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { if (textDivs.length === 0) { clearInterval(renderTimer); renderingDone = true; + self.textLayerDiv = textLayerDiv = canvas = ctx = null; return; } var textDiv = textDivs.shift(); From eaffcfa9206645edfc8cce2e2382071d75cccdd7 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Wed, 8 Aug 2012 20:26:24 +0200 Subject: [PATCH 14/15] Fix some typos in comments and variable names. Fix some nits in debugger.js. --- web/debugger.js | 14 +++++++------- web/viewer.js | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/web/debugger.js b/web/debugger.js index aeb3ab4ce..0cfe26355 100644 --- a/web/debugger.js +++ b/web/debugger.js @@ -44,7 +44,7 @@ var FontInspector = (function FontInspectorClosure() { } } return { - // Poperties/functions needed by PDFBug. + // Properties/functions needed by PDFBug. id: 'FontInspector', name: 'Font Inspector', panel: null, @@ -140,7 +140,7 @@ var StepperManager = (function StepperManagerClosure() { var stepperChooser = null; var breakPoints = {}; return { - // Poperties/functions needed by PDFBug. + // Properties/functions needed by PDFBug. id: 'Stepper', name: 'Stepper', panel: null, @@ -207,7 +207,7 @@ var StepperManager = (function StepperManagerClosure() { var Stepper = (function StepperClosure() { function Stepper(panel, pageIndex, initialBreakPoints) { this.panel = panel; - this.len; + this.len = 0; this.breakPoint = 0; this.nextBreakPoint = null; this.pageIndex = pageIndex; @@ -236,6 +236,7 @@ var Stepper = (function StepperClosure() { headerRow.appendChild(c('th', 'fn')); headerRow.appendChild(c('th', 'args')); + var self = this; for (var i = 0; i < IRQueue.fnArray.length; i++) { var line = c('tr'); line.className = 'line'; @@ -249,7 +250,6 @@ var Stepper = (function StepperClosure() { cbox.type = 'checkbox'; cbox.className = 'points'; cbox.checked = checked; - var self = this; cbox.onclick = (function(x) { return function() { if (this.checked) @@ -298,7 +298,7 @@ var Stepper = (function StepperClosure() { callback(); break; } - } + }; dom.addEventListener('keydown', listener, false); self.goTo(idx); }, @@ -331,7 +331,7 @@ var Stats = (function Stats() { return false; } return { - // Poperties/functions needed by PDFBug. + // Properties/functions needed by PDFBug. id: 'Stats', name: 'Stats', panel: null, @@ -429,12 +429,12 @@ var PDFBug = (function PDFBugClosure() { // Initialize all the debugging tools. var tools = this.tools; + var self = this; for (var i = 0; i < tools.length; ++i) { var tool = tools[i]; var panel = document.createElement('div'); var panelButton = document.createElement('button'); panelButton.textContent = tool.name; - var self = this; panelButton.addEventListener('click', (function(selected) { return function(event) { event.preventDefault(); diff --git a/web/viewer.js b/web/viewer.js index 9b810b76f..1e6bf8a12 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -431,7 +431,7 @@ var PDFView = { // } // ); // }, -// noData // Error ocurred try downloading with just the url. +// noData // Error occurred try downloading with just the url. // ); //#endif }, @@ -798,14 +798,14 @@ var PDFView = { search: function pdfViewStartSearch() { // Limit this function to run every ms. var SEARCH_TIMEOUT = 250; - var lastSeach = this.lastSearch; + var lastSearch = this.lastSearch; var now = Date.now(); - if (lastSeach && (now - lastSeach) < SEARCH_TIMEOUT) { + if (lastSearch && (now - lastSearch) < SEARCH_TIMEOUT) { if (!this.searchTimer) { this.searchTimer = setTimeout(function resumeSearch() { PDFView.search(); }, - SEARCH_TIMEOUT - (now - lastSeach) + SEARCH_TIMEOUT - (now - lastSearch) ); } return; From 5b583e596a83f26e56d7d8cde0c10c7d8400531d Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 8 Aug 2012 13:31:15 -0500 Subject: [PATCH 15/15] data.length optimization --- web/compatibility.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/compatibility.js b/web/compatibility.js index 5a16b3d7f..cb2941042 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -141,7 +141,7 @@ var buffer = new ArrayBuffer(data.length); var uint8Array = new Uint8Array(buffer); - for (var i = 0; i < data.length; i++) + for (var i = 0, ii = data.length; i < ii; i++) uint8Array[i] = data.charCodeAt(i); Object.defineProperty(originalReader, 'result', {