diff --git a/l10n/da/viewer.properties b/l10n/da/viewer.properties
index 6d208db70..f9d77da1b 100644
--- a/l10n/da/viewer.properties
+++ b/l10n/da/viewer.properties
@@ -17,7 +17,7 @@ page_scale_width=Sidebredde
page_scale_fit=Helside
page_scale_auto=Automatisk zoom
page_scale_actual=Faktisk størrelse
-toggle_slider.title=Skift Slider
+toggle_slider.title=Skift slider
thumbs.title=Vis thumbnails
outline.title=Vis dokumentoversigt
loading=Indlæser... {{percent}}%
@@ -29,3 +29,17 @@ page_of=af {{pageCount}}
no_outline=Ingen dokumentoversigt tilgængelig
open_file.title=Åbn fil
text_annotation_type=[{{type}} Kommentar]
+toggle_slider_label=Skift slider
+thumbs_label=Thumbnails
+outline_label=Dokumentoversigt
+bookmark_label=Aktuel visning
+previous_label=Forrige
+next_label=Næste
+print_label=Udskriv
+download_label=Hent
+zoom_out_label=Zoom ud
+zoom_in_label=Zoom ind
+zoom.title=Zoom
+thumb_page_title=Side {{page}}
+thumb_page_canvas=Thumbnail af side {{page}}
+request_password=PDF filen er beskyttet med et kodeord:
diff --git a/l10n/en-US/viewer.properties b/l10n/en-US/viewer.properties
index 1cc46eedf..c8b061d49 100644
--- a/l10n/en-US/viewer.properties
+++ b/l10n/en-US/viewer.properties
@@ -42,5 +42,7 @@ zoom_in_label=Zoom In
zoom.title=Zoom
thumb_page_title=Page {{page}}
thumb_page_canvas=Thumbnail of Page {{page}}
+request_password=PDF is protected by a password:
search.title=Search Document
search_label=Search
+
diff --git a/l10n/fr/metadata.inc b/l10n/fr/metadata.inc
new file mode 100644
index 000000000..874e93a18
--- /dev/null
+++ b/l10n/fr/metadata.inc
@@ -0,0 +1,7 @@
+
+
+ fr
+ PDF Viewer
+ Utilise HTML5 pour afficher les documents PDF directement dans Firefox.
+
+
diff --git a/l10n/fr/viewer.properties b/l10n/fr/viewer.properties
new file mode 100644
index 000000000..c93df3681
--- /dev/null
+++ b/l10n/fr/viewer.properties
@@ -0,0 +1,45 @@
+bookmark.title=Vue courante (copier ou ouvrir dans une nouvelle fenêtre)
+previous.title=Précédente
+next.title=Suivante
+print.title=Imprimer
+download.title=Télécharger
+zoom_out.title=Zoom arrière
+zoom_in.title=Zoom avant
+error_more_info=Plus d'informations
+error_less_info=Moins d'informations
+error_close=Fermer
+error_build=Version de PDF.JS : {{build}}
+error_message=Message : {{message}}
+error_stack=Pile : {{stack}}
+error_file=Fichier : {{file}}
+error_line=Ligne : {{line}}
+page_scale_width=Largeur de la page
+page_scale_fit=Ajuster à la page
+page_scale_auto=Zoom automatique
+page_scale_actual=Taille réelle
+toggle_slider.title=Afficher/Masquer la barre latérale
+thumbs.title=Afficher/masquer les vignettes
+outline.title=Afficher/masquer la structure
+loading=Chargement… {{percent}}%
+loading_error_indicator=Erreur
+loading_error=Une erreur est survenue lors du chargement du PDF.
+rendering_error=Une erreur est survenue lors de l'affichage de la page.
+page_label=Page :
+page_of=sur {{pageCount}}
+no_outline=Pas de structure disponible
+open_file.title=Ouvrir un fichier
+text_annotation_type=[Annotation {{type}}]
+toggle_slider_label=Afficher/Masquer la barre latérale
+thumbs_label=Vignettes
+outline_label=Structure du document
+bookmark_label=Vue courante
+previous_label=Précédente
+next_label=Suivante
+print_label=Imprimer
+download_label=Télécharger
+zoom_out_label=Zoom arrière
+zoom_in_label=Zoom avant
+zoom.title=Zoom
+thumb_page_title=Page {{page}}
+thumb_page_canvas=Aperçu de la page {{page}}
+request_password=Ce PDF est protégé par un mot de passe :
diff --git a/l10n/ja/metadata.inc b/l10n/ja/metadata.inc
new file mode 100644
index 000000000..7ca474685
--- /dev/null
+++ b/l10n/ja/metadata.inc
@@ -0,0 +1,8 @@
+
+
+ ja
+ PDF Viewer
+ HTML5を使用して、Firefoxで直接PDFファイルを表示します。
+
+
+
diff --git a/l10n/ja/viewer.properties b/l10n/ja/viewer.properties
new file mode 100644
index 000000000..4bbe8c48b
--- /dev/null
+++ b/l10n/ja/viewer.properties
@@ -0,0 +1,45 @@
+bookmark.title=現在のビュー (コピーまたは新しいウインドウで開く)
+previous.title=前のページ
+next.title=次のページ
+print.title=印刷
+download.title=ダウンロード
+zoom_out.title=縮小
+zoom_in.title=拡大
+error_more_info=詳細情報
+error_less_info=詳細情報の非表示
+error_close=閉じる
+error_build=PDF.JS Build: {{build}}
+error_message=メッセージ: {{message}}
+error_stack=スタック: {{stack}}
+error_file=ファイル: {{file}}
+error_line=ライン: {{line}}
+page_scale_width=幅に合わせる
+page_scale_fit=ページのサイズに合わせる
+page_scale_auto=自動ズーム
+page_scale_actual=実際のサイズ
+toggle_slider.title=サイドバーの切り替え
+thumbs.title=縮小版を表示
+outline.title=文書の目次を表示
+loading=読み込み中... {{percent}}%
+loading_error_indicator=エラー
+loading_error=PDFの読み込み中にエラーが発生しました
+rendering_error=ページのレンダリング中にエラーが発生しました
+page_label=ページ:
+page_of=of {{pageCount}}
+no_outline=利用可能な目次はありません
+open_file.title=ファイルを開く
+text_annotation_type=[{{type}} 注釈]
+toggle_slider_label=サイドバーの切り替え
+thumbs_label=縮小版
+outline_label=文書の目次
+bookmark_label=現在のビュー
+previous_label=前へ
+next_label=次へ
+print_label=印刷
+download_label=ダウンロード
+zoom_out_label=縮小
+zoom_in_label=拡大
+zoom.title=ズーム
+thumb_page_title=ページ {{page}}
+thumb_page_canvas=ページの縮小版 {{page}}
+request_password=PDFはパスワードによって保護されています
diff --git a/l10n/ru/viewer.properties b/l10n/ru/viewer.properties
index a946cde98..796add2af 100644
--- a/l10n/ru/viewer.properties
+++ b/l10n/ru/viewer.properties
@@ -40,3 +40,6 @@ download_label=Загрузить
zoom_out_label=Уменьшить
zoom_in_label=Увеличить
zoom.title=Масштаб
+thumb_page_title=Страница {{page}}
+thumb_page_canvas=Уменьшенное изображение страницы {{page}}
+request_password=PDF защищён паролем:
diff --git a/l10n/sv/metadata.inc b/l10n/sv/metadata.inc
new file mode 100644
index 000000000..6753d83e9
--- /dev/null
+++ b/l10n/sv/metadata.inc
@@ -0,0 +1,8 @@
+
+
+ sv
+ PDF Läsare
+ Använder HTML5 för att visa PDF filer direkt i Firefox.
+
+
+
diff --git a/l10n/sv/viewer.properties b/l10n/sv/viewer.properties
new file mode 100644
index 000000000..3aadfd44f
--- /dev/null
+++ b/l10n/sv/viewer.properties
@@ -0,0 +1,45 @@
+bookmark.title=Aktuell vy (visa eller öppna i nytt fönster)
+previous.title=Föregående sida
+next.title=Nästa sida
+print.title=Skriv ut
+download.title=Ladda ner
+zoom_out.title=Zooma ut
+zoom_in.title=Zooma in
+error_more_info=Mer information
+error_less_info=Mindre information
+error_close=Stäng
+error_build=PDF.JS bygge: {{build}}
+error_message=Meddelande: {{message}}
+error_stack=Stack: {{stack}}
+error_file=Fil: {{file}}
+error_line=Rad: {{line}}
+page_scale_width=Sidbredd
+page_scale_fit=Passa sida
+page_scale_auto=Automatisk zoom
+page_scale_actual=Faktisk storlek
+toggle_slider.title=Visa/Dölj panel
+thumbs.title=Visa miniatyrer
+outline.title=Visa dokumentdisposition
+loading=Laddar... {{percent}}%
+loading_error_indicator=Fel
+loading_error=Ett fel inträffade när PDF dokumentet laddades.
+rendering_error=Ett fel inträffade när PDF dokumentet renderades.
+page_label=Sida:
+page_of=av {{pageCount}}
+no_outline=Ingen dokumentdisposition tillgänglig
+open_file.title=Öppna fil
+text_annotation_type=[{{type}} Annotering]
+toggle_slider_label=Visa/Dölj panel
+thumbs_label=Miniatyrer
+outline_label=Disposition
+bookmark_label=Aktuell vy
+previous_label=Föregående
+next_label=Nästa
+print_label=Skriv ut
+download_label=Ladda ner
+zoom_out_label=Zooma ut
+zoom_in_label=Zooma in
+zoom.title=Zooma
+thumb_page_title=Sida {{page}}
+thumb_page_canvas=Miniatyr av sida {{page}}
+request_password=PDF dokumentet är skyddat av ett lösenord:
\ No newline at end of file
diff --git a/l10n/zh-CN/metadata.inc b/l10n/zh-CN/metadata.inc
new file mode 100644
index 000000000..04be27c78
--- /dev/null
+++ b/l10n/zh-CN/metadata.inc
@@ -0,0 +1,8 @@
+
+
+ zh-CN
+ PDF 查看器
+ 使用 HTML5 来支持在 Firefox 中直接显示 PDF 文件。
+
+
+
diff --git a/l10n/zh-CN/viewer.properties b/l10n/zh-CN/viewer.properties
new file mode 100644
index 000000000..8b670fe12
--- /dev/null
+++ b/l10n/zh-CN/viewer.properties
@@ -0,0 +1,45 @@
+bookmark.title=当前视图(复制或在新窗口中打开)
+previous.title=上一页
+next.title=下一页
+print.title=打印
+download.title=下载
+zoom_out.title=缩小
+zoom_in.title=放大
+error_more_info=更多信息
+error_less_info=更少信息
+error_close=关闭
+error_build=PDF.JS Build: {{build}}
+error_message=Message: {{message}}
+error_stack=Stack: {{stack}}
+error_file=File: {{file}}
+error_line=Line: {{line}}
+page_scale_width=适合页宽
+page_scale_fit=适合页面
+page_scale_auto=自动缩放
+page_scale_actual=实际大小
+toggle_slider.title=切换侧栏
+thumbs.title=显示缩略图
+outline.title=显示文档大纲
+loading=正在载入... {{percent}}%
+loading_error_indicator=错误
+loading_error=载入PDF时发生错误。
+rendering_error=呈现页面时发生错误。
+page_label=页:
+page_of=/ {{pageCount}}
+no_outline=无可用大纲
+open_file.title=打开文件
+text_annotation_type=[{{type}} 注解]
+toggle_slider_label=切换侧栏
+thumbs_label=缩略图
+outline_label=文档大纲
+bookmark_label=当前视图
+previous_label=向上
+next_label=向下
+print_label=打印
+download_label=下载
+zoom_out_label=缩小
+zoom_in_label=放大
+zoom.title=缩放
+thumb_page_title=页码 {{page}}
+thumb_page_canvas=页面 {{page}} 的缩略图
+request_password=PDF 被密码保护:
diff --git a/l10n/zh-TW/metadata.inc b/l10n/zh-TW/metadata.inc
new file mode 100644
index 000000000..6ef722be8
--- /dev/null
+++ b/l10n/zh-TW/metadata.inc
@@ -0,0 +1,8 @@
+
+
+ zh-TW
+ PDF 瀏覽器
+ 利用 HTML5 技術在 Firefox 中直接顯示 PDF 格式檔案。
+
+
+
diff --git a/l10n/zh-TW/viewer.properties b/l10n/zh-TW/viewer.properties
new file mode 100644
index 000000000..0f2182594
--- /dev/null
+++ b/l10n/zh-TW/viewer.properties
@@ -0,0 +1,45 @@
+bookmark.title=目前檢視(複製或在新視窗中開啟)
+previous.title=上一頁
+next.title=下一頁
+print.title=列印
+download.title=下載
+zoom_out.title=縮小
+zoom_in.title=放大
+error_more_info=更多資訊
+error_less_info=更少資訊
+error_close=關閉
+error_build=PDF.JS 版本號: {{build}}
+error_message=錯誤信息: {{message}}
+error_stack=堆疊: {{stack}}
+error_file=檔案: {{file}}
+error_line=行數: {{line}}
+page_scale_width=符合頁寬
+page_scale_fit=符合頁面
+page_scale_auto=自動縮放
+page_scale_actual=實際大小
+toggle_slider.title=切換側邊欄
+thumbs.title=顯示縮圖
+outline.title=顯示文件綱要
+loading=正在載入... {{percent}}%
+loading_error_indicator=錯誤
+loading_error=載入PDF檔案時發生錯誤。
+rendering_error=渲染頁面時發生錯誤。
+page_label=頁次:
+page_of=, 共 {{pageCount}} 頁
+no_outline=無可用的綱要
+open_file.title=開啟檔案
+text_annotation_type=[{{type}} 註解]
+toggle_slider_label=切換側邊欄
+thumbs_label=縮圖
+outline_label=文件綱要
+bookmark_label=目前檢視
+previous_label=上一頁
+next_label=下一頁
+print_label=列印
+download_label=下載
+zoom_out_label=縮小
+zoom_in_label=放大
+zoom.title=縮放
+thumb_page_title=第 {{page}} 頁
+thumb_page_canvas=第 {{page}} 頁的縮圖
+request_password=PDF 檔案受密碼保護:
diff --git a/src/api.js b/src/api.js
index 976faf898..48d017c6d 100644
--- a/src/api.js
+++ b/src/api.js
@@ -7,20 +7,46 @@
* is used, which means it must follow the same origin rules that any XHR does
* e.g. No cross domain requests without CORS.
*
- * @param {string|TypedAray} source Either a url to a PDF is located or a
- * typed array (Uint8Array) already populated with data.
- * @param {Object} headers An object containing the http headers like this:
- * { Authorization: "BASIC XXX" }.
+ * @param {string|TypedAray|object} source Can be an url to where a PDF is
+ * located, a typed array (Uint8Array) already populated with data or
+ * and parameter object with the following possible fields:
+ * - url - The URL of the PDF.
+ * - data - A typed array with PDF data.
+ * - httpHeaders - Basic authentication headers.
+ * - password - For decrypting password-protected PDFs.
+ *
* @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
*/
-PDFJS.getDocument = function getDocument(source, headers) {
+PDFJS.getDocument = function getDocument(source) {
+ var url, data, headers, password, parameters = {};
+ if (typeof source === 'string') {
+ url = source;
+ } else if (isArrayBuffer(source)) {
+ data = source;
+ } else if (typeof source === 'object') {
+ url = source.url;
+ data = source.data;
+ headers = source.httpHeaders;
+ password = source.password;
+ parameters.password = password || null;
+
+ if (!url && !data)
+ error('Invalid parameter array, need either .data or .url');
+ } else {
+ error('Invalid parameter in getDocument, need either Uint8Array, ' +
+ 'string or a parameter object');
+ }
+
var promise = new PDFJS.Promise();
var transport = new WorkerTransport(promise);
- if (typeof source === 'string') {
+ if (data) {
+ // assuming the data is array, instantiating directly from it
+ transport.sendData(data, parameters);
+ } else if (url) {
// fetch url
PDFJS.getPdf(
{
- url: source,
+ url: url,
progress: function getPDFProgress(evt) {
if (evt.lengthComputable)
promise.progress({
@@ -35,12 +61,10 @@ PDFJS.getDocument = function getDocument(source, headers) {
headers: headers
},
function getPDFLoad(data) {
- transport.sendData(data);
+ transport.sendData(data, parameters);
});
- } else {
- // assuming the source is array, instantiating directly from it
- transport.sendData(source);
}
+
return promise;
};
@@ -122,6 +146,11 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
});
return promise;
},
+ isEncrypted: function PDFDocumentProxy_isEncrypted() {
+ var promise = new PDFJS.Promise();
+ promise.resolve(this.pdfInfo.encrypted);
+ return promise;
+ },
destroy: function PDFDocumentProxy_destroy() {
this.transport.destroy();
}
@@ -473,6 +502,14 @@ var WorkerTransport = (function WorkerTransportClosure() {
this.workerReadyPromise.resolve(pdfDocument);
}, this);
+ messageHandler.on('NeedPassword', function transportPassword(data) {
+ this.workerReadyPromise.reject(data.exception.message, data.exception);
+ }, this);
+
+ messageHandler.on('IncorrectPassword', function transportBadPass(data) {
+ this.workerReadyPromise.reject(data.exception.message, data.exception);
+ }, this);
+
messageHandler.on('GetPage', function transportPage(data) {
var pageInfo = data.pageInfo;
var page = new PDFPageProxy(pageInfo, this);
@@ -575,8 +612,8 @@ var WorkerTransport = (function WorkerTransportClosure() {
});
},
- sendData: function WorkerTransport_sendData(data) {
- this.messageHandler.send('GetDocRequest', data);
+ sendData: function WorkerTransport_sendData(data, params) {
+ this.messageHandler.send('GetDocRequest', {data: data, params: params});
},
getPage: function WorkerTransport_getPage(pageNumber, promise) {
diff --git a/src/core.js b/src/core.js
index e1a9476a3..4af055bfe 100644
--- a/src/core.js
+++ b/src/core.js
@@ -362,19 +362,19 @@ var Page = (function PageClosure() {
* `PDFDocument` objects on the main thread created.
*/
var PDFDocument = (function PDFDocumentClosure() {
- function PDFDocument(arg, callback) {
+ function PDFDocument(arg, password) {
if (isStream(arg))
- init.call(this, arg);
+ init.call(this, arg, password);
else if (isArrayBuffer(arg))
- init.call(this, new Stream(arg));
+ init.call(this, new Stream(arg), password);
else
error('PDFDocument: Unknown argument type');
}
- function init(stream) {
+ function init(stream, password) {
assertWellFormed(stream.length > 0, 'stream must have data');
this.stream = stream;
- this.setup();
+ this.setup(password);
this.acroForm = this.catalog.catDict.get('AcroForm');
}
@@ -465,11 +465,12 @@ var PDFDocument = (function PDFDocumentClosure() {
}
// May not be a PDF file, continue anyway.
},
- setup: function PDFDocument_setup(ownerPassword, userPassword) {
+ setup: function PDFDocument_setup(password) {
this.checkHeader();
var xref = new XRef(this.stream,
this.startXRef,
- this.mainXRefEntriesOffset);
+ this.mainXRefEntriesOffset,
+ password);
this.xref = xref;
this.catalog = new Catalog(xref);
},
diff --git a/src/crypto.js b/src/crypto.js
index dcd820554..c86551f36 100644
--- a/src/crypto.js
+++ b/src/crypto.js
@@ -556,7 +556,9 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
var encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
ownerPassword, userPassword, flags,
revision, keyLength, encryptMetadata);
- if (!encryptionKey && password) {
+ if (!encryptionKey && !password) {
+ throw new PasswordException('No password given', 'needpassword');
+ } else if (!encryptionKey && password) {
// Attempting use the password as an owner password
var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword,
revision, keyLength);
@@ -566,7 +568,7 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
}
if (!encryptionKey)
- error('incorrect password or encryption data');
+ throw new PasswordException('Incorrect Password', 'incorrectpassword');
this.encryptionKey = encryptionKey;
diff --git a/src/obj.js b/src/obj.js
index 9b99eb8f7..3432ac68d 100644
--- a/src/obj.js
+++ b/src/obj.js
@@ -298,7 +298,7 @@ var Catalog = (function CatalogClosure() {
})();
var XRef = (function XRefClosure() {
- function XRef(stream, startXRef, mainXRefEntriesOffset) {
+ function XRef(stream, startXRef, mainXRefEntriesOffset, password) {
this.stream = stream;
this.entries = [];
this.xrefstms = {};
@@ -311,8 +311,7 @@ var XRef = (function XRefClosure() {
var encrypt = trailerDict.get('Encrypt');
if (encrypt) {
var fileId = trailerDict.get('ID');
- this.encrypt = new CipherTransformFactory(encrypt,
- fileId[0] /*, password */);
+ this.encrypt = new CipherTransformFactory(encrypt, fileId[0], password);
}
// get the root dictionary (catalog) object
diff --git a/src/util.js b/src/util.js
index 140b18cf1..90e6cee5d 100644
--- a/src/util.js
+++ b/src/util.js
@@ -58,6 +58,19 @@ function shadow(obj, prop, value) {
return value;
}
+var PasswordException = (function PasswordExceptionClosure() {
+ function PasswordException(msg, code) {
+ this.name = 'PasswordException';
+ this.message = msg;
+ this.code = code;
+ }
+
+ PasswordException.prototype = new Error();
+ PasswordException.constructor = PasswordException;
+
+ return PasswordException;
+})();
+
function bytesToString(bytes) {
var str = '';
var length = bytes.length;
@@ -456,7 +469,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
}
this.isResolved = true;
- this.data = data || null;
+ this.data = (typeof data !== 'undefined') ? data : null;
var callbacks = this.callbacks;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
@@ -471,7 +484,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
}
},
- reject: function Promise_reject(reason) {
+ reject: function Promise_reject(reason, exception) {
if (this.isRejected) {
error('A Promise can be rejected only once ' + this.name);
}
@@ -484,7 +497,7 @@ var Promise = PDFJS.Promise = (function PromiseClosure() {
var errbacks = this.errbacks;
for (var i = 0, ii = errbacks.length; i < ii; i++) {
- errbacks[i].call(null, reason);
+ errbacks[i].call(null, reason, exception);
}
},
diff --git a/src/worker.js b/src/worker.js
index b3ba7671e..253232768 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -88,14 +88,35 @@ var WorkerMessageHandler = {
handler.on('GetDocRequest', function wphSetupDoc(data) {
// Create only the model of the PDFDoc, which is enough for
// processing the content of the pdf.
- pdfModel = new PDFDocument(new Stream(data));
+ var pdfData = data.data;
+ var pdfPassword = data.params.password;
+ try {
+ pdfModel = new PDFDocument(new Stream(pdfData), pdfPassword);
+ } catch (e) {
+ if (e instanceof PasswordException) {
+ if (e.code === 'needpassword') {
+ handler.send('NeedPassword', {
+ exception: e
+ });
+ } else if (e.code === 'incorrectpassword') {
+ handler.send('IncorrectPassword', {
+ exception: e
+ });
+ }
+
+ return;
+ } else {
+ throw e;
+ }
+ }
var doc = {
numPages: pdfModel.numPages,
fingerprint: pdfModel.getFingerprint(),
destinations: pdfModel.catalog.destinations,
outline: pdfModel.catalog.documentOutline,
info: pdfModel.getDocumentInfo(),
- metadata: pdfModel.catalog.metadata
+ metadata: pdfModel.catalog.metadata,
+ encrypted: !!pdfModel.xref.encrypt
};
handler.send('GetDoc', {pdfInfo: doc});
});
diff --git a/web/compatibility.js b/web/compatibility.js
index 5c192c9a9..528841bb6 100644
--- a/web/compatibility.js
+++ b/web/compatibility.js
@@ -120,6 +120,9 @@
return new Uint8Array(new VBArray(this.responseBody).toArray());
}
});
+ Object.defineProperty(xhrPrototype, 'overrideMimeType', {
+ value: function xmlHttpRequestOverrideMimeType(mimeType) {}
+ });
return;
}
@@ -217,15 +220,84 @@
var div = document.createElement('div');
if ('dataset' in div)
return; // dataset property exists
- var oldCreateElement = document.createElement;
- document.createElement = function newCreateElement() {
- var result = oldCreateElement.apply(document, arguments);
- if (arguments[0] === 'div') {
- // creating dataset property for the div elements
- result.dataset = {};
+
+ Object.defineProperty(HTMLElement.prototype, 'dataset', {
+ get: function() {
+ if (this._dataset)
+ return this._dataset;
+
+ var dataset = {};
+ for (var j = 0, jj = this.attributes.length; j < jj; j++) {
+ var attribute = this.attributes[j];
+ if (attribute.name.substring(0, 5) != 'data-')
+ continue;
+ var key = attribute.name.substring(5).replace(/\-([a-z])/g,
+ function(all, ch) { return ch.toUpperCase(); });
+ dataset[key] = attribute.value;
+ }
+
+ Object.defineProperty(this, '_dataset', {
+ value: dataset,
+ writable: false,
+ enumerable: false
+ });
+ return dataset;
+ },
+ enumerable: true
+ });
+})();
+
+// HTMLElement classList property
+(function checkClassListProperty() {
+ var div = document.createElement('div');
+ if ('classList' in div)
+ return; // classList property exists
+
+ function changeList(element, itemName, add, remove) {
+ var s = element.className || '';
+ var list = s.split(/\s+/g);
+ if (list[0] == '') list.shift();
+ var index = list.indexOf(itemName);
+ if (index < 0 && add)
+ list.push(itemName);
+ if (index >= 0 && remove)
+ list.splice(index, 1);
+ element.className = list.join(' ');
+ }
+
+ var classListPrototype = {
+ add: function(name) {
+ changeList(this.element, name, true, false);
+ },
+ remove: function(name) {
+ changeList(this.element, name, false, true);
+ },
+ toggle: function(name) {
+ changeList(this.element, name, true, true);
}
- return result;
};
+
+ Object.defineProperty(HTMLElement.prototype, 'classList', {
+ get: function() {
+ if (this._classList)
+ return this._classList;
+
+ var classList = Object.create(classListPrototype, {
+ element: {
+ value: this,
+ writable: false,
+ enumerable: true
+ }
+ });
+ Object.defineProperty(this, '_classList', {
+ value: classList,
+ writable: false,
+ enumerable: false
+ });
+ return classList;
+ },
+ enumerable: true
+ });
})();
// Check console compatability
@@ -252,3 +324,17 @@
document.addEventListener('click', ignoreIfTargetDisabled, true);
}
})();
+
+// Checks if navigator.language is supported
+(function checkNavigatorLanguage() {
+ if ('language' in navigator)
+ return;
+ Object.defineProperty(navigator, 'language', {
+ get: function navigatorLanguage() {
+ var language = navigator.userLanguage || 'en-US';
+ return language.substring(0, 2).toLowerCase() +
+ language.substring(2).toUpperCase();
+ },
+ enumerable: true
+ });
+})();
diff --git a/web/viewer.css b/web/viewer.css
index 3446c1627..cb6a7b474 100644
--- a/web/viewer.css
+++ b/web/viewer.css
@@ -428,6 +428,10 @@ html[dir='rtl'] .dropdownToolbarButton {
background: transparent;
}
+.dropdownToolbarButton > select > option {
+ background: hsl(0,0%,24%);
+}
+
#customScaleOption {
display: none;
}
@@ -984,3 +988,47 @@ canvas {
#PDFBug table {
font-size: 10px;
}
+
+@media all and (max-width: 770px) {
+ #scaleSelectContainer, #fileInput, #pageNumberLabel {
+ display: none;
+ }
+
+ #sidebarContainer {
+ top: 33px;
+ z-index: 100;
+ }
+ #sidebarContent {
+ top: 33px;
+ background-color: hsla(0,0%,0%,.7);
+ }
+ #thumbnailView, #outlineView {
+ top: 66px;
+ }
+
+ html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer {
+ left: 0px;
+ }
+ html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer {
+ right: 0px;
+ }
+
+ #pageNumber {
+ width: 30px;
+ }
+}
+
+@media all and (max-width: 500px) {
+ #viewBookmark {
+ display: none;
+ }
+
+ html[dir='ltr'] .outerCenter {
+ float: left;
+ left: 180px;
+ }
+ html[dir='rtl'] .outerCenter {
+ float: right;
+ right: 180px;
+ }
+}
diff --git a/web/viewer.html b/web/viewer.html
index 17688ef0c..b2d1a9243 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -89,7 +89,7 @@
Next
-
+
@@ -127,7 +127,7 @@
Zoom In
-
+