From 0e5f74b6c294f575c85bcac914768cfc9e3f19e2 Mon Sep 17 00:00:00 2001
From: notmasteryet <async.processingjs@yahoo.com>
Date: Fri, 17 Jun 2011 07:37:14 -0500
Subject: [PATCH 1/7] readXRefStream and PNG predictor 12

---
 pdf.js | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 160 insertions(+), 16 deletions(-)

diff --git a/pdf.js b/pdf.js
index 17537d233..dc2302d2d 100644
--- a/pdf.js
+++ b/pdf.js
@@ -506,6 +506,94 @@ var FlateStream = (function() {
     return constructor;
 })();
 
+var PredictorStream = (function() {
+    function constructor(stream, params) {
+        this.stream = stream;
+        this.predictor = params.get("Predictor") || 1;
+        if (this.predictor <= 1) {
+            return stream; // no prediction
+        }
+        if (params.has("EarlyChange")) {
+            error("EarlyChange predictor parameter is not supported");
+        }
+        this.colors = params.get("Colors") || 1;
+        this.bitsPerComponent = params.get("BitsPerComponent") || 8;
+        this.columns = params.get("Columns") || 1;
+        if (this.colors !== 1 || this.bitsPerComponent !== 8) {
+            error("Multi-color and multi-byte predictors are not supported");
+        }
+        if (this.predictor < 10 || this.predictor > 15) {
+            error("Unsupported predictor");
+        }
+        this.currentRow = new Uint8Array(this.columns);
+        this.pos = 0;
+        this.bufferLength = 0;
+    }
+
+    constructor.prototype = {
+        readRow : function() {
+            var lastRow = this.currentRow;
+            var predictor = this.stream.getByte();
+            var currentRow = this.stream.getBytes(this.columns), i;
+            switch (predictor) {
+            default:
+                error("Unsupported predictor");
+                break;
+            case 0:
+                break;
+            case 2:
+                for (i = 0; i < currentRow.length; ++i) {
+                  currentRow[i] = (lastRow[i] + currentRow[i]) & 0xFF;
+                }
+                break;
+            }
+            this.pos = 0;
+            this.bufferLength = currentRow.length;
+            this.currentRow = currentRow;
+        },
+        getByte : function() {
+            if (this.pos >= this.bufferLength) {
+               this.readRow();
+            }
+            return this.currentRow[this.pos++];
+        },
+        getBytes : function(n) {
+            var i, bytes;
+            bytes = new Uint8Array(n);
+            for (i = 0; i < n; ++i) {
+              if (this.pos >= this.bufferLength) {
+                this.readRow();
+              }
+              bytes[i] = this.currentRow[this.pos++];
+            }
+            return bytes;
+        },
+        getChar : function() {
+            return String.formCharCode(this.getByte());
+        },
+        lookChar : function() {
+            if (this.pos >= this.bufferLength) {
+               this.readRow();
+            }
+            return String.formCharCode(this.currentRow[this.pos]);
+        },
+        skip : function(n) {
+            var i;
+            if (!n) {
+                n = 1;
+            }
+            while (n > this.bufferLength - this.pos) {
+                n -= this.bufferLength - this.pos;
+                this.readRow();
+                if (this.bufferLength === 0) break;
+            }
+            this.pos += n;
+        }
+    };
+
+    return constructor;
+})();
+
 var DecryptStream = (function() {
     function constructor(str, fileKey, encAlgorithm, keyLength) {
         // TODO
@@ -1079,7 +1167,9 @@ var Parser = (function() {
                                            this.encAlgorithm,
                                            this.keyLength);
             }
-            return this.filter(stream, dict);
+            stream = this.filter(stream, dict);
+            stream.parameters = dict; 
+            return stream;
         },
         filter: function(stream, dict) {
             var filter = dict.get2("Filter", "F");
@@ -1104,8 +1194,9 @@ var Parser = (function() {
         },
         makeFilter: function(stream, name, params) {
             if (name == "FlateDecode" || name == "Fl") {
-                if (params)
-                    error("params not supported yet for FlateDecode");
+                if (params) {
+                    return new PredictorStream(new FlateStream(stream), params);
+                }
                 return new FlateStream(stream);
             } else {
                 error("filter '" + name + "' not supported yet");
@@ -1198,10 +1289,10 @@ var XRef = (function() {
         this.stream = stream;
         this.entries = [];
         this.xrefstms = {};
-        this.readXRef(startXRef);
+        var trailerDict = this.readXRef(startXRef);
 
         // get the root dictionary (catalog) object
-        if (!IsRef(this.root = this.trailerDict.get("Root")))
+        if (!IsRef(this.root = trailerDict.get("Root")))
             error("Invalid root reference");
 
         // prepare the XRef cache
@@ -1256,18 +1347,18 @@ var XRef = (function() {
                 error("Invalid XRef table");
 
             // get the 'Prev' pointer
-            var more = false;
+            var prev;
             obj = dict.get("Prev");
             if (IsInt(obj)) {
-                this.prev = obj;
-                more = true;
+                prev = obj;
             } else if (IsRef(obj)) {
                 // certain buggy PDF generators generate "/Prev NNN 0 R" instead
                 // of "/Prev NNN"
-                this.prev = obj.num;
-                more = true;
+                prev = obj.num;
+            }
+            if (prev) {
+              this.readXRef(prev);
             }
-            this.trailerDict = dict;
 
             // check for 'XRefStm' key
             if (IsInt(obj = dict.get("XRefStm"))) {
@@ -1277,11 +1368,64 @@ var XRef = (function() {
                 this.xrefstms[pos] = 1; // avoid infinite recursion
                 this.readXRef(pos);
             }
-
-            return more;
+            return dict;
         },
-        readXRefStream: function(parser) {
-            error("Invalid XRef stream");
+        readXRefStream: function(stream) {
+            var streamParameters = stream.parameters;
+            var length = streamParameters.get("Length");
+            var byteWidths = streamParameters.get("W");
+            var range = streamParameters.get("Index");
+            if (!range) {
+                range = [0, streamParameters.get("Size")];
+            }
+            var i, j;
+            while (range.length > 0) {
+                var first = range[0], n = range[1];
+                if (!IsInt(first) || !IsInt(n)) {
+                    error("Invalid XRef range fields");
+                }
+                var typeFieldWidth = byteWidths[0], offsetFieldWidth = byteWidths[1], generationFieldWidth = byteWidths[2];
+                if (!IsInt(typeFieldWidth) || !IsInt(offsetFieldWidth) || !IsInt(generationFieldWidth)) {
+                    error("Invalid XRef entry fields length");
+                }
+                for (i = 0; i < n; ++i) {
+                    var type = 0, offset = 0, generation = 0;
+                    for (j = 0; j < typeFieldWidth; ++j) {
+                       type = (type << 8) | stream.getByte();
+                    }
+                    for (j = 0; j < offsetFieldWidth; ++j) {
+                       offset = (offset << 8) | stream.getByte();
+                    }
+                    for (j = 0; j < generationFieldWidth; ++j) {
+                       generation = (generation << 8) | stream.getByte();
+                    }
+                    var entry = { offset: offset, gen: generation };
+                    if (typeFieldWidth > 0) {
+                        switch (type) {
+                        case 0:
+                           entry.free = true;
+                           break;
+                        case 1:
+                           entry.uncompressed = true;
+                           break;
+                        case 2:
+                           break;
+                        default:
+                           error("Invalid XRef entry type");
+                           break;
+                        }
+                    }
+                    if (!this.entries[first + i]) {
+                        this.entries[first + i] = entry;
+                    }
+                }
+                range.splice(0, 2);
+            }
+            var prev = streamParameters.get("Prev");
+            if (IsInt(prev)) {
+                this.readXRef(prev);
+            }
+            return streamParameters;
         },
         readXRef: function(startXRef) {
             var stream = this.stream;
@@ -1565,7 +1709,7 @@ var PDFDoc = (function() {
         },
         getPage: function(n) {
             var linearization = this.linearization;
-            assert(!linearization, "linearized page access not implemented");
+            // assert(!linearization, "linearized page access not implemented");
             return this.catalog.getPage(n);
         }
     };

From c3a7bc7d796eaae9aaf8261e18a7e8801eeb71cb Mon Sep 17 00:00:00 2001
From: notmasteryet <async.processingjs@yahoo.com>
Date: Sat, 18 Jun 2011 23:49:31 -0500
Subject: [PATCH 2/7] Add Yury to the contributors list

---
 LICENSE | 1 +
 1 file changed, 1 insertion(+)

diff --git a/LICENSE b/LICENSE
index 3d42ba007..81658476c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -6,6 +6,7 @@
                   Shaon Barman <shaon.barman@gmail.com>
                   Vivien Nicolas <21@vingtetun.org>
                   Justin D'Arcangelo <justindarc@gmail.com>
+                  Yury Delendik
 
     Permission is hereby granted, free of charge, to any person obtaining a
     copy of this software and associated documentation files (the "Software"),

From 4c018956f2c00fc184c45643dea90adcc8db304d Mon Sep 17 00:00:00 2001
From: Chris Jones <jones.chris.g@gmail.com>
Date: Sat, 18 Jun 2011 22:04:36 -0700
Subject: [PATCH 3/7] mozMeasureText() is non-standard and deprecated

---
 fonts.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fonts.js b/fonts.js
index 7978cd60d..6c643ae40 100644
--- a/fonts.js
+++ b/fonts.js
@@ -203,7 +203,7 @@ Font.prototype = {
       }
     }
     ctx.font = "bold italic 20px " + fontName + ", Symbol, Arial";
-    var textWidth = ctx.mozMeasureText(testString);
+    var textWidth = ctx.measureText(testString).width;
 
     if (debug)
       ctx.fillText(testString, 20, 20);
@@ -218,7 +218,7 @@ Font.prototype = {
         window.clearInterval(interval);
         Fonts[fontName].loading = false;
         warn("Is " + fontName + " for charset: " + charset + " loaded?");
-      } else if (textWidth != ctx.mozMeasureText(testString)) {
+      } else if (textWidth != ctx.measureText(testString).width) {
         window.clearInterval(interval);
         Fonts[fontName].loading = false;
       }

From 23e19c08b10732d5736340760b2cf906dc5cd914 Mon Sep 17 00:00:00 2001
From: Chris Jones <jones.chris.g@gmail.com>
Date: Sat, 18 Jun 2011 23:18:46 -0700
Subject: [PATCH 4/7] use strict mode and fix violators

---
 fonts.js             |  5 ++++-
 glyphlist.js         |  5 +++++
 multi-page-viewer.js |  2 ++
 pdf.js               | 18 +++++++++++-------
 viewer.js            |  8 +++++---
 5 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/fonts.js b/fonts.js
index 6c643ae40..0c8725fb4 100644
--- a/fonts.js
+++ b/fonts.js
@@ -1,6 +1,8 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
+"use strict";
+
 /**
  * Maximum file size of the font.
  */
@@ -1042,7 +1044,8 @@ var Type1Parser = function() {
   this.extractFontProgram = function t1_extractFontProgram(aStream) {
     var eexecString = decrypt(aStream, kEexecEncryptionKey, 4);
     var subrs = [],  glyphs = [];
-    var inSubrs = inGlyphs = false;
+    var inGlyphs = false;
+    var inSubrs = false;
     var glyph = "";
 
     var token = "";
diff --git a/glyphlist.js b/glyphlist.js
index 1a0190133..72a90431f 100644
--- a/glyphlist.js
+++ b/glyphlist.js
@@ -1,3 +1,8 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+"use strict";
+
 var GlyphsUnicode = {
   A: 0x0041,
   AE: 0x00C6,
diff --git a/multi-page-viewer.js b/multi-page-viewer.js
index cc4a286ff..2410eb7bf 100644
--- a/multi-page-viewer.js
+++ b/multi-page-viewer.js
@@ -1,6 +1,8 @@
 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
 
+"use strict";
+
 var PDFViewer = {
     queryParams: {},
 
diff --git a/pdf.js b/pdf.js
index 993b5063d..a051e57f3 100644
--- a/pdf.js
+++ b/pdf.js
@@ -1,6 +1,8 @@
 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
 
+"use strict";
+
 var ERRORS = 0, WARNINGS = 1, TODOS = 5;
 var verbosity = WARNINGS;
 
@@ -389,6 +391,12 @@ var FlateStream = (function() {
             return [codes, maxLen];
         },
         readBlock: function() {
+            function repeat(stream, array, len, offset, what) {
+                var repeat = stream.getBits(len) + offset;
+                while (repeat-- > 0)
+                    array[i++] = what;
+            }
+
             var stream = this.stream;
 
             // read block header
@@ -449,11 +457,6 @@ var FlateStream = (function() {
                 var codes = numLitCodes + numDistCodes;
                 var codeLengths = new Array(codes);
                 while (i < codes) {
-                    function repeat(stream, array, len, offset, what) {
-                        var repeat = stream.getBits(len) + offset;
-                        while (repeat-- > 0)
-                            array[i++] = what;
-                    }
                     var code = this.getCode(codeLenCodeTab);
                     if (code == 16) {
                         repeat(this, codeLengths, 2, 3, len);
@@ -813,6 +816,7 @@ var Lexer = (function() {
             var done = false;
             var str = "";
             var stream = this.stream;
+            var ch;
             do {
                 switch (ch = stream.getChar()) {
                 case undefined:
@@ -1573,7 +1577,7 @@ var Catalog = (function() {
             return shadow(this, "toplevelPagesDict", obj);
         },
         get numPages() {
-            obj = this.toplevelPagesDict.get("Count");
+            var obj = this.toplevelPagesDict.get("Count");
             assertWellFormed(IsInt(obj),
                              "page count in top level pages object is not an integer");
             // shadow the prototype getter
@@ -2527,7 +2531,7 @@ var CanvasGraphics = (function() {
                 error("No support for array of functions");
             else if (!IsPDFFunction(fnObj))
                 error("Invalid function");
-            fn = new PDFFunction(this.xref, fnObj);
+            var fn = new PDFFunction(this.xref, fnObj);
 
             var gradient = this.ctx.createLinearGradient(x0, y0, x1, y1);
             var step = (t1 - t0) / 10;
diff --git a/viewer.js b/viewer.js
index 59d8167a2..675f2fb87 100644
--- a/viewer.js
+++ b/viewer.js
@@ -1,12 +1,14 @@
 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
 
-var pdfDocument, canvas, pageDisplay, pageNum, pageInterval;
+"use strict";
+
+var pdfDocument, canvas, numPages, pageDisplay, pageNum, pageInterval;
 function load(userInput) {
     canvas = document.getElementById("canvas");
     canvas.mozOpaque = true;
     pageNum = parseInt(queryParams().page) || 1;
-    fileName = userInput;
+    var fileName = userInput;
     if (!userInput) {
       fileName = queryParams().file || "compressed.tracemonkey-pldi-09.pdf";
     }
@@ -26,7 +28,7 @@ function queryParams() {
 
 function open(url) {
     document.title = url;
-    req = new XMLHttpRequest();
+    var req = new XMLHttpRequest();
     req.open("GET", url);
     req.mozResponseType = req.responseType = "arraybuffer";
     req.expected = (document.URL.indexOf("file:") == 0) ? 0 : 200;

From 9477df21ce3a6c8278ab9d376d3f1a848299fcc0 Mon Sep 17 00:00:00 2001
From: Chris Jones <jones.chris.g@gmail.com>
Date: Sat, 18 Jun 2011 23:21:30 -0700
Subject: [PATCH 5/7] use strict in the utils/ too

---
 utils/cffStandardStrings.js | 11 ++++++++---
 utils/fonts_utils.js        |  5 +++++
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/utils/cffStandardStrings.js b/utils/cffStandardStrings.js
index 8977cd8f2..1b328a2da 100644
--- a/utils/cffStandardStrings.js
+++ b/utils/cffStandardStrings.js
@@ -1,5 +1,10 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+"use strict";
+
 var CFFStrings = [
-  ".notdef", 
+  ".notdef",
   "space",
   "exclam",
   "quotedbl",
@@ -490,7 +495,7 @@ var CFFDictDataMap = {
   },
   "10": {
     name: "StdHW"
-  }, 
+  },
   "11": {
     name: "StdVW"
   },
@@ -597,7 +602,7 @@ var CFFDictDataMap = {
   },
   "18": {
     name: "Private",
-    operand: "number number" 
+    operand: "number number"
   },
   "19": {
     name: "Subrs"
diff --git a/utils/fonts_utils.js b/utils/fonts_utils.js
index 086648fe2..79ecf257f 100644
--- a/utils/fonts_utils.js
+++ b/utils/fonts_utils.js
@@ -1,3 +1,8 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+"use strict";
+
 /**
  * The Type2 reader code below is only used for debugging purpose since Type2
  * is only a CharString format and is never used directly as a Font file.

From cf0e22ffafe30c21fd2df04c76eb2f38cc061fbb Mon Sep 17 00:00:00 2001
From: Justin D'Arcangelo <justindarc@gmail.com>
Date: Sun, 19 Jun 2011 14:54:13 -0400
Subject: [PATCH 6/7] Changed the zoom input to utilize a pre-populated combo
 box.

---
 images/combobox.png            | Bin 0 -> 1964 bytes
 images/source/ComboBox.psd.zip | Bin 0 -> 17724 bytes
 multi-page-viewer.css          |  60 +++++++++++++++++++++++++++++++++
 multi-page-viewer.html         |  13 +++++--
 multi-page-viewer.js           |  40 +++++++++++++++++++---
 5 files changed, 106 insertions(+), 7 deletions(-)
 create mode 100644 images/combobox.png
 create mode 100644 images/source/ComboBox.psd.zip

diff --git a/images/combobox.png b/images/combobox.png
new file mode 100644
index 0000000000000000000000000000000000000000..f1527d6a2e4cdcf3f72df511bdbde4e9f843a0f9
GIT binary patch
literal 1964
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
b81(T623#fQfN0SX@BdRSOO}2Tm%0Bx3gr>A

literal 0
HcmV?d00001

diff --git a/images/source/ComboBox.psd.zip b/images/source/ComboBox.psd.zip
new file mode 100644
index 0000000000000000000000000000000000000000..232604c7514e825ae93b017a0fe186447399f32f
GIT binary patch
literal 17724
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
F@c^Z#N{Ijf

literal 0
HcmV?d00001

diff --git a/multi-page-viewer.css b/multi-page-viewer.css
index 53a28f129..293b32241 100644
--- a/multi-page-viewer.css
+++ b/multi-page-viewer.css
@@ -113,6 +113,66 @@ span {
     background: url('images/buttons.png') no-repeat -28px 0px;
 }
 
+#scaleComboBoxInput {
+    background: url('images/combobox.png') no-repeat 0px -23px;
+    display: inline-block;
+    float: left;
+    margin: 0px;
+    width: 35px;
+    height: 23px;
+}
+
+#scaleComboBoxInput input {
+    background: none;
+    border: 0px;
+    margin: 3px 2px 0px;
+    width: 31px;
+}
+
+#scaleComboBoxButton {
+    background: url('images/combobox.png') no-repeat -41px -23px;
+    cursor: pointer;
+    display: inline-block;
+    float: left;
+    margin: 0px;
+    width: 21px;
+    height: 23px;
+}
+
+#scaleComboBoxButton.down {
+    background: url('images/combobox.png') no-repeat -41px -46px;
+}
+
+#scaleComboBoxButton.disabled {
+    background: url('images/combobox.png') no-repeat -41px 0px;
+}
+
+#scaleComboBoxList {
+    background-color: #fff;
+    border: 1px solid #666;
+    clear: both;
+    position: relative;
+    display: none;
+    top: -20px;
+    width: 48px;
+}
+
+#scaleComboBoxList > ul {
+    list-style: none;
+    padding: 0px;
+    margin: 0px;
+}
+
+#scaleComboBoxList > ul > li {
+    display: inline-block;
+    cursor: pointer;
+    width: 100%;
+}
+
+#scaleComboBoxList > ul > li:hover {
+    background-color: #09f;
+}
+
 #pageNumber, #scale {
     text-align: right;
 }
diff --git a/multi-page-viewer.html b/multi-page-viewer.html
index aec84a42f..692cfb1c4 100644
--- a/multi-page-viewer.html
+++ b/multi-page-viewer.html
@@ -21,9 +21,18 @@
             <span class="label">Page Number</span>
         </span>
         <span class="control">
-            <input type="text" id="scale" value="100" size="2"/>
-            <span>%</span>
+            <span id="scaleComboBoxInput"><input type="text" id="scale" value="100%" size="2"/></span><span id="scaleComboBoxButton"></span>
             <span class="label">Zoom</span>
+            <div id="scaleComboBoxList">
+                <ul>
+                    <li>50%</li>
+                    <li>75%</li>
+                    <li>100%</li>
+                    <li>125%</li>
+                    <li>150%</li>
+                    <li>200%</li>
+                </ul>
+            </div>
         </span>
     </div>
     <div id="viewer"></div>
diff --git a/multi-page-viewer.js b/multi-page-viewer.js
index 2410eb7bf..6cb46a08a 100644
--- a/multi-page-viewer.js
+++ b/multi-page-viewer.js
@@ -8,9 +8,10 @@ var PDFViewer = {
 
     element: null,
 
-    pageNumberInput: null,
     previousPageButton: null,
     nextPageButton: null,
+    pageNumberInput: null,
+    scaleInput: null,
     
     willJumpToPage: false,
 
@@ -158,6 +159,8 @@ var PDFViewer = {
                 PDFViewer.drawPage(1);
             }
         }
+
+        PDFViewer.scaleInput.value = Math.floor(PDFViewer.scale * 100) + '%';
     },
 
     goToPage: function(num) {
@@ -317,13 +320,40 @@ window.onload = function() {
         this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
     };
 
-    var scaleInput = document.getElementById('scale');
-    scaleInput.onchange = function(evt) {
-        PDFViewer.changeScale(this.value);
+    PDFViewer.scaleInput = document.getElementById('scale');
+    PDFViewer.scaleInput.buttonElement = document.getElementById('scaleComboBoxButton');
+    PDFViewer.scaleInput.buttonElement.listElement = document.getElementById('scaleComboBoxList');
+    PDFViewer.scaleInput.onchange = function(evt) {
+        PDFViewer.changeScale(parseInt(this.value));
     };
 
+    PDFViewer.scaleInput.buttonElement.onclick = function(evt) {
+        this.listElement.style.display = (this.listElement.style.display === 'block') ? 'none' : 'block';
+    };
+    PDFViewer.scaleInput.buttonElement.onmousedown = function(evt) {
+        if (this.className.indexOf('disabled') === -1) {
+            this.className = 'down';
+        }
+    };
+    PDFViewer.scaleInput.buttonElement.onmouseup = function(evt) {
+        this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+    };
+    PDFViewer.scaleInput.buttonElement.onmouseout = function(evt) {
+        this.className = (this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
+    };
+    
+    var listItems = PDFViewer.scaleInput.buttonElement.listElement.getElementsByTagName('LI');
+
+    for (var i = 0; i < listItems.length; i++) {
+        var listItem = listItems[i];
+        listItem.onclick = function(evt) {
+            PDFViewer.changeScale(parseInt(this.innerHTML));
+            PDFViewer.scaleInput.buttonElement.listElement.style.display = 'none';
+        };
+    }
+
     PDFViewer.pageNumber = parseInt(PDFViewer.queryParams.page) || PDFViewer.pageNumber;
-    PDFViewer.scale = parseInt(scaleInput.value) / 100 || 1.0;
+    PDFViewer.scale = parseInt(PDFViewer.scaleInput.value) / 100 || 1.0;
     PDFViewer.open(PDFViewer.queryParams.file || PDFViewer.url);
 
     window.onscroll = function(evt) {        

From a3781157cf7f2f70b06742c02d0e534d3039365c Mon Sep 17 00:00:00 2001
From: Justin D'Arcangelo <justindarc@gmail.com>
Date: Sun, 19 Jun 2011 14:57:45 -0400
Subject: [PATCH 7/7] Minor CSS fix for zoom drop down.

---
 multi-page-viewer.css | 1 +
 1 file changed, 1 insertion(+)

diff --git a/multi-page-viewer.css b/multi-page-viewer.css
index 293b32241..c96567465 100644
--- a/multi-page-viewer.css
+++ b/multi-page-viewer.css
@@ -171,6 +171,7 @@ span {
 
 #scaleComboBoxList > ul > li:hover {
     background-color: #09f;
+    color: #fff;
 }
 
 #pageNumber, #scale {