From f3ee85efab5d081d6576afb8e6edda5e736805ac Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Wed, 2 Nov 2011 20:46:39 -0500 Subject: [PATCH 1/6] Simple AcroForms support --- src/core.js | 90 +++++++++++++++++++++++++++++++++++------------- web/viewer.css | 21 ++++++++++++ web/viewer.js | 93 +++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 167 insertions(+), 37 deletions(-) diff --git a/src/core.js b/src/core.js index 09d665972..fa9747c72 100644 --- a/src/core.js +++ b/src/core.js @@ -265,46 +265,87 @@ var Page = (function pagePage() { } }, getLinks: function pageGetLinks() { + var links = []; + var annotations = pageGetAnnotations(); + var i, n = annotations.length; + for (i = 0; i < n; ++i) { + if (annotations[i].type != 'Link') + continue; + links.push(annotations[i]); + } + return links; + }, + getAnnotations: function pageGetAnnotations() { var xref = this.xref; var annotations = xref.fetchIfRef(this.annotations) || []; var i, n = annotations.length; - var links = []; + var items = []; for (i = 0; i < n; ++i) { var annotation = xref.fetch(annotations[i]); if (!isDict(annotation)) continue; var subtype = annotation.get('Subtype'); - if (!isName(subtype) || subtype.name != 'Link') + if (!isName(subtype)) continue; var rect = annotation.get('Rect'); var topLeftCorner = this.rotatePoint(rect[0], rect[1]); var bottomRightCorner = this.rotatePoint(rect[2], rect[3]); - var link = {}; - link.x = Math.min(topLeftCorner.x, bottomRightCorner.x); - link.y = Math.min(topLeftCorner.y, bottomRightCorner.y); - link.width = Math.abs(topLeftCorner.x - bottomRightCorner.x); - link.height = Math.abs(topLeftCorner.y - bottomRightCorner.y); - var a = this.xref.fetchIfRef(annotation.get('A')); - if (a) { - switch (a.get('S').name) { - case 'URI': - link.url = a.get('URI'); + var item = {}; + item.type = subtype.name; + item.x = Math.min(topLeftCorner.x, bottomRightCorner.x); + item.y = Math.min(topLeftCorner.y, bottomRightCorner.y); + item.width = Math.abs(topLeftCorner.x - bottomRightCorner.x); + item.height = Math.abs(topLeftCorner.y - bottomRightCorner.y); + switch (subtype.name) { + case 'Link': + var a = this.xref.fetchIfRef(annotation.get('A')); + if (a) { + switch (a.get('S').name) { + case 'URI': + link.url = a.get('URI'); + break; + case 'GoTo': + link.dest = a.get('D'); + break; + default: + TODO('other link types'); + } + } else if (annotation.has('Dest')) { + // simple destination link + var dest = annotation.get('Dest'); + link.dest = isName(dest) ? dest.name : dest; + } + break; + case 'Widget': + var fieldType = annotation.get('FT'); + if (!isName(fieldType)) break; - case 'GoTo': - link.dest = a.get('D'); - break; - default: - TODO('other link types'); - } - } else if (annotation.has('Dest')) { - // simple destination link - var dest = annotation.get('Dest'); - link.dest = isName(dest) ? dest.name : dest; + item.fieldType = fieldType.name; + var fieldName = []; + var name = stringToPDFString(annotation.get('T')); + if (name) + fieldName.push(name) + var parent = xref.fetchIfRef(annotation.get('Parent')); + while (parent) { + name = stringToPDFString(parent.get('T')); + if (name) + fieldName.unshift(name); + parent = xref.fetchIfRef(parent.get('Parent')); + } + item.fullName = fieldName.join('.'); + var alternativeText = stringToPDFString(annotation.get('TU') || ''); + item.alternativeText = alternativeText; + var da = annotation.get('DA') || ''; + var m = /([\d\.]+)\sTf/.exec(da); + if (m) + item.fontSize = parseFloat(m[1]); + item.flags = annotation.get('Ff') || 0; + break; } - links.push(link); + items.push(item); } - return links; + return items; }, startRendering: function pageStartRendering(ctx, callback) { this.ctx = ctx; @@ -342,6 +383,7 @@ var PDFDocModel = (function pdfDoc() { assertWellFormed(stream.length > 0, 'stream must have data'); this.stream = stream; this.setup(); + this.acroForm = this.xref.fetchIfRef(this.catalog.catDict.get('AcroForm')); } function find(stream, needle, limit, backwards) { diff --git a/web/viewer.css b/web/viewer.css index 27ad0638a..456d3eb94 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -231,6 +231,23 @@ canvas { -webkit-box-shadow: 0px 2px 10px #ff0; } +.page > .inputHint { + opacity: 0.2; + background: #ccc; + position: absolute; +} + +.page > .inputControl { + background: transparent; + border: 0px none; + position: absolute; + margin: auto; +} + +.page > .inputControl[type='checkbox'] { + margin: 0px; +} + #viewer { margin: 44px 0px 0px; padding: 8px 0px; @@ -281,6 +298,10 @@ canvas { display: block; page-break-after: always; } + + .inputHint { + display: none; + } } #loading { diff --git a/web/viewer.js b/web/viewer.js index 1ab2c555c..5d9e083d7 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -33,6 +33,7 @@ var PDFView = { thumbnails: [], currentScale: kDefaultScale, initialBookmark: document.location.hash.substring(1), + formFields: [], setScale: function pdfViewSetScale(val, resetAutoSettings) { var pages = this.pages; @@ -362,7 +363,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, div.removeAttribute('data-loaded'); }; - function setupLinks(content, scale) { + function setupAnnotations(content, scale) { function bindLink(link, dest) { link.href = PDFView.getDestinationHash(dest); link.onclick = function pageViewSetupLinksOnclick() { @@ -371,18 +372,82 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, return false; }; } + function bindInputItem(input, item) { + if (input.name in PDFView.formFields) { + var value = PDFView.formFields[input.name]; + if (input.type == 'checkbox') + input.checked = value; + else if (!input.type || input.type == 'text') + input.value = value; + } + input.onchange = function pageViewSetupInputOnBlur() { + if (input.type == 'checkbox') + PDFView.formFields[input.name] = input.checked; + else if (!input.type || input.type == 'text') + PDFView.formFields[input.name] = input.value; + }; + } + function createElementWithStyle(tagName, item) { + var element = document.createElement(tagName); + element.style.left = (Math.floor(item.x - view.x) * scale) + 'px'; + element.style.top = (Math.floor(item.y - view.y) * scale) + 'px'; + element.style.width = Math.ceil(item.width * scale) + 'px'; + element.style.height = Math.ceil(item.height * scale) + 'px'; + return element; + } + function assignFontStyle(element, item) { + var fontStyles = ''; + if ('fontSize' in item) + fontStyles += 'font-size: ' + Math.round(item.fontSize * scale) + 'px'; + element.setAttribute('style', element.getAttribute('style') + fontStyles); + } - var links = content.getLinks(); - for (var i = 0; i < links.length; i++) { - var link = document.createElement('a'); - link.style.left = (Math.floor(links[i].x - view.x) * scale) + 'px'; - link.style.top = (Math.floor(links[i].y - view.y) * scale) + 'px'; - link.style.width = Math.ceil(links[i].width * scale) + 'px'; - link.style.height = Math.ceil(links[i].height * scale) + 'px'; - link.href = links[i].url || ''; - if (!links[i].url) - bindLink(link, ('dest' in links[i]) ? links[i].dest : null); - div.appendChild(link); + var items = content.getAnnotations(); + for (var i = 0; i < items.length; i++) { + var item = items[i]; + switch (item.type) { + case 'Link': + var link = createElementWithStyle('a', item); + link.href = item.url || ''; + if (!item.url) + bindLink(link, ('dest' in item) ? item.dest : null); + div.appendChild(link); + break; + case 'Widget': + if (item.fieldType != 'Tx' && item.fieldType != 'Btn' && + item.fieldType != 'Ch') + break; + var inputDiv = createElementWithStyle('div', item); + inputDiv.className = 'inputHint'; + div.appendChild(inputDiv); + var input; + if (item.fieldType == 'Tx') { + input = createElementWithStyle('input', item); + } + if (item.fieldType == 'Btn') { + input = createElementWithStyle('input', item); + if (item.flags & 32768) { + input.type = 'radio'; + TODO('radio button is not supported'); + } else if (item.flags & 65536) { + input.type = 'button'; + TODO('pushbutton is not supported'); + } else { + input.type = 'checkbox'; + } + } + if (item.fieldType == 'Ch') { + input = createElementWithStyle('select', item); + TODO('select box is not supported'); + } + input.className = 'inputControl'; + input.name = item.fullName; + input.title = item.alternativeText; + assignFontStyle(input, item); + bindInputItem(input, item); + div.appendChild(input); + break; + } } } @@ -489,7 +554,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, stats.begin = Date.now(); this.content.startRendering(ctx, this.updateStats); - setupLinks(this.content, this.scale); + setupAnnotations(this.content, this.scale); div.setAttribute('data-loaded', true); return true; @@ -738,6 +803,8 @@ window.addEventListener('pagechange', function pagechange(evt) { window.addEventListener('keydown', function keydown(evt) { var curElement = document.activeElement; + if (curElement && curElement.tagName == 'INPUT') + return; var controlsElement = document.getElementById('controls'); while (curElement) { if (curElement === controlsElement) From 3d36a05d7f4fbddbccae1c416f9905ff62c72de5 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Wed, 2 Nov 2011 22:00:33 -0500 Subject: [PATCH 2/6] Text alignment inside input controls --- src/core.js | 1 + web/viewer.js | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/core.js b/src/core.js index fa9747c72..e410c9d52 100644 --- a/src/core.js +++ b/src/core.js @@ -340,6 +340,7 @@ var Page = (function pagePage() { var m = /([\d\.]+)\sTf/.exec(da); if (m) item.fontSize = parseFloat(m[1]); + item.textAlignment = annotation.get('Q'); item.flags = annotation.get('Ff') || 0; break; } diff --git a/web/viewer.js b/web/viewer.js index 5d9e083d7..0c9b6c2c9 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -398,7 +398,18 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, function assignFontStyle(element, item) { var fontStyles = ''; if ('fontSize' in item) - fontStyles += 'font-size: ' + Math.round(item.fontSize * scale) + 'px'; + fontStyles += 'font-size: ' + Math.round(item.fontSize * scale) + 'px;'; + switch (item.textAlignment) { + case 0: + fontStyles += 'text-align: left;'; + break; + case 1: + fontStyles += 'text-align: center;'; + break; + case 2: + fontStyles += 'text-align: right;'; + break; + } element.setAttribute('style', element.getAttribute('style') + fontStyles); } From b5ba29be1335c201d54c66e7bf6890324d97a8f7 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Wed, 2 Nov 2011 22:20:53 -0500 Subject: [PATCH 3/6] lint error fix --- src/core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.js b/src/core.js index e410c9d52..7e53df430 100644 --- a/src/core.js +++ b/src/core.js @@ -325,7 +325,7 @@ var Page = (function pagePage() { var fieldName = []; var name = stringToPDFString(annotation.get('T')); if (name) - fieldName.push(name) + fieldName.push(name); var parent = xref.fetchIfRef(annotation.get('Parent')); while (parent) { name = stringToPDFString(parent.get('T')); From 1d8a40b372580fc2e51e066d583602348676b21c Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Sat, 12 Nov 2011 15:39:23 -0600 Subject: [PATCH 4/6] Fixing inheritable forms input control properties --- src/core.js | 53 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/core.js b/src/core.js index 231671542..6c447dafe 100644 --- a/src/core.js +++ b/src/core.js @@ -274,11 +274,22 @@ var Page = (function pagePage() { }, getAnnotations: function pageGetAnnotations() { var xref = this.xref; + function getInheritableProperty(annotation, name) { + var item = annotation; + while (item && !item.has(name)) { + item = xref.fetchIfRef(item.get('Parent')); + } + if (!item) + return null; + return item.get(name); + } + var annotations = xref.fetchIfRef(this.annotations) || []; var i, n = annotations.length; var items = []; for (i = 0; i < n; ++i) { - var annotation = xref.fetch(annotations[i]); + var annotationRef = annotations[i]; + var annotation = xref.fetch(annotationRef); if (!isDict(annotation)) continue; var subtype = annotation.get('Subtype'); @@ -315,30 +326,46 @@ var Page = (function pagePage() { } break; case 'Widget': - var fieldType = annotation.get('FT'); + var fieldType = getInheritableProperty(annotation, 'FT'); if (!isName(fieldType)) break; item.fieldType = fieldType.name; + // Building the full field name by collecting the field and + // its ancestors 'T' properties and joining them using '.'. var fieldName = []; - var name = stringToPDFString(annotation.get('T')); - if (name) - fieldName.push(name); - var parent = xref.fetchIfRef(annotation.get('Parent')); - while (parent) { - name = stringToPDFString(parent.get('T')); + var namedItem = annotation, ref = annotationRef; + while (namedItem) { + var parentRef = namedItem.get('Parent'); + var parent = xref.fetchIfRef(parentRef); + var name = namedItem.get('T'); if (name) - fieldName.unshift(name); - parent = xref.fetchIfRef(parent.get('Parent')); + fieldName.unshift(stringToPDFString(name)); + else { + // The field name is absent, that means more than one field + // with the same name may exist. Replacing the empty name + // with the '`' plus index in the parent's 'Kids' array. + // This is not in the PDF spec but necessary to id the + // the input controls. + var kids = xref.fetchIfRef(parent.get('Kids')); + var j, jj; + for (j = 0, jj = kids.length; j < jj; j++) { + if (kids[j].num == ref.num && kids[j].gen == ref.gen) + break; + } + fieldName.unshift('`' + j); + } + namedItem = parent; + ref = parentRef; } item.fullName = fieldName.join('.'); var alternativeText = stringToPDFString(annotation.get('TU') || ''); item.alternativeText = alternativeText; - var da = annotation.get('DA') || ''; + var da = getInheritableProperty(annotation, 'DA') || ''; var m = /([\d\.]+)\sTf/.exec(da); if (m) item.fontSize = parseFloat(m[1]); - item.textAlignment = annotation.get('Q'); - item.flags = annotation.get('Ff') || 0; + item.textAlignment = getInheritableProperty(annotation, 'Q'); + item.flags = getInheritableProperty(annotation, 'Ff') || 0; break; } items.push(item); From 6011b5b4db5597fff08d72e85293c23986dbc742 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Mon, 19 Dec 2011 20:00:50 -0600 Subject: [PATCH 5/6] Moving forms UI into examples --- examples/acroforms/forms.js | 141 ++++++++++++++++++++++++++++++++++ examples/acroforms/index.html | 51 ++++++++++++ web/viewer.css | 11 --- web/viewer.js | 67 ---------------- 4 files changed, 192 insertions(+), 78 deletions(-) create mode 100644 examples/acroforms/forms.js create mode 100644 examples/acroforms/index.html diff --git a/examples/acroforms/forms.js b/examples/acroforms/forms.js new file mode 100644 index 000000000..6ec92766d --- /dev/null +++ b/examples/acroforms/forms.js @@ -0,0 +1,141 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + +// +// Basic AcroForms input controls rendering +// + +'use strict'; + +var formFields = {}; + +function setupForm(div, content, scale) { + function bindInputItem(input, item) { + if (input.name in formFields) { + var value = formFields[input.name]; + if (input.type == 'checkbox') + input.checked = value; + else if (!input.type || input.type == 'text') + input.value = value; + } + input.onchange = function pageViewSetupInputOnBlur() { + if (input.type == 'checkbox') + formFields[input.name] = input.checked; + else if (!input.type || input.type == 'text') + formFields[input.name] = input.value; + }; + } + function createElementWithStyle(tagName, item) { + var element = document.createElement(tagName); + element.style.left = (item.x * scale) + 'px'; + element.style.top = (item.y * scale) + 'px'; + element.style.width = Math.ceil(item.width * scale) + 'px'; + element.style.height = Math.ceil(item.height * scale) + 'px'; + return element; + } + function assignFontStyle(element, item) { + var fontStyles = ''; + if ('fontSize' in item) + fontStyles += 'font-size: ' + Math.round(item.fontSize * scale) + 'px;'; + switch (item.textAlignment) { + case 0: + fontStyles += 'text-align: left;'; + break; + case 1: + fontStyles += 'text-align: center;'; + break; + case 2: + fontStyles += 'text-align: right;'; + break; + } + element.setAttribute('style', element.getAttribute('style') + fontStyles); + } + + var items = content.getAnnotations(); + for (var i = 0; i < items.length; i++) { + var item = items[i]; + switch (item.type) { + case 'Widget': + if (item.fieldType != 'Tx' && item.fieldType != 'Btn' && + item.fieldType != 'Ch') + break; + var inputDiv = createElementWithStyle('div', item); + inputDiv.className = 'inputHint'; + div.appendChild(inputDiv); + var input; + if (item.fieldType == 'Tx') { + input = createElementWithStyle('input', item); + } + if (item.fieldType == 'Btn') { + input = createElementWithStyle('input', item); + if (item.flags & 32768) { + input.type = 'radio'; + // radio button is not supported + } else if (item.flags & 65536) { + input.type = 'button'; + // pushbutton is not supported + } else { + input.type = 'checkbox'; + } + } + if (item.fieldType == 'Ch') { + input = createElementWithStyle('select', item); + // select box is not supported + } + input.className = 'inputControl'; + input.name = item.fullName; + input.title = item.alternativeText; + assignFontStyle(input, item); + bindInputItem(input, item); + div.appendChild(input); + break; + } + } +} + +function renderPage(div, pdf, pageNumber, callback) { + var page = pdf.getPage(pageNumber); + var scale = 1.5; + + var pageDisplayWidth = page.width * scale; + var pageDisplayHeight = page.height * scale; + + var pageDivHolder = document.createElement('div'); + pageDivHolder.className = 'pdfpage'; + pageDivHolder.style.width = pageDisplayWidth + 'px'; + pageDivHolder.style.height = pageDisplayHeight + 'px'; + div.appendChild(pageDivHolder); + + // Prepare canvas using PDF page dimensions + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + canvas.width = pageDisplayWidth; + canvas.height = pageDisplayHeight; + pageDivHolder.appendChild(canvas); + + + // Render PDF page into canvas context + page.startRendering(context, callback); + + // Prepare and populate form elements layer + var formDiv = document.createElement('div'); + pageDivHolder.appendChild(formDiv); + + setupForm(formDiv, page, scale); +} + +PDFJS.getPdf(pdfWithFormsPath, function getPdfForm(data) { + // Instantiate PDFDoc with PDF data + var pdf = new PDFJS.PDFDoc(data); + + // Rendering all pages starting from first + var viewer = document.getElementById('viewer'); + var pageNumber = 1; + renderPage(viewer, pdf, pageNumber++, function pageRenderingComplete() { + if (pageNumber > pdf.numPages) + return; // All pages rendered + // Continue rendering of the next page + renderPage(viewer, pdf, pageNumber++, pageRenderingComplete); + }); +}); + diff --git a/examples/acroforms/index.html b/examples/acroforms/index.html new file mode 100644 index 000000000..d07121167 --- /dev/null +++ b/examples/acroforms/index.html @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/web/viewer.css b/web/viewer.css index 28418f290..8b2b0cc4d 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -238,17 +238,6 @@ canvas { position: absolute; } -.page > .inputControl { - background: transparent; - border: 0px none; - position: absolute; - margin: auto; -} - -.page > .inputControl[type='checkbox'] { - margin: 0px; -} - .textLayer { position: absolute; left: 0; diff --git a/web/viewer.js b/web/viewer.js index e52d56acd..e1ca9ee36 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -33,7 +33,6 @@ var PDFView = { thumbnails: [], currentScale: kDefaultScale, initialBookmark: document.location.hash.substring(1), - formFields: [], setScale: function pdfViewSetScale(val, resetAutoSettings) { var pages = this.pages; @@ -468,21 +467,6 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, return false; }; } - function bindInputItem(input, item) { - if (input.name in PDFView.formFields) { - var value = PDFView.formFields[input.name]; - if (input.type == 'checkbox') - input.checked = value; - else if (!input.type || input.type == 'text') - input.value = value; - } - input.onchange = function pageViewSetupInputOnBlur() { - if (input.type == 'checkbox') - PDFView.formFields[input.name] = input.checked; - else if (!input.type || input.type == 'text') - PDFView.formFields[input.name] = input.value; - }; - } function createElementWithStyle(tagName, item) { var element = document.createElement(tagName); element.style.left = (Math.floor(item.x - view.x) * scale) + 'px'; @@ -491,23 +475,6 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, element.style.height = Math.ceil(item.height * scale) + 'px'; return element; } - function assignFontStyle(element, item) { - var fontStyles = ''; - if ('fontSize' in item) - fontStyles += 'font-size: ' + Math.round(item.fontSize * scale) + 'px;'; - switch (item.textAlignment) { - case 0: - fontStyles += 'text-align: left;'; - break; - case 1: - fontStyles += 'text-align: center;'; - break; - case 2: - fontStyles += 'text-align: right;'; - break; - } - element.setAttribute('style', element.getAttribute('style') + fontStyles); - } var items = content.getAnnotations(); for (var i = 0; i < items.length; i++) { @@ -520,40 +487,6 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, bindLink(link, ('dest' in item) ? item.dest : null); div.appendChild(link); break; - case 'Widget': - if (item.fieldType != 'Tx' && item.fieldType != 'Btn' && - item.fieldType != 'Ch') - break; - var inputDiv = createElementWithStyle('div', item); - inputDiv.className = 'inputHint'; - div.appendChild(inputDiv); - var input; - if (item.fieldType == 'Tx') { - input = createElementWithStyle('input', item); - } - if (item.fieldType == 'Btn') { - input = createElementWithStyle('input', item); - if (item.flags & 32768) { - input.type = 'radio'; - TODO('radio button is not supported'); - } else if (item.flags & 65536) { - input.type = 'button'; - TODO('pushbutton is not supported'); - } else { - input.type = 'checkbox'; - } - } - if (item.fieldType == 'Ch') { - input = createElementWithStyle('select', item); - TODO('select box is not supported'); - } - input.className = 'inputControl'; - input.name = item.fullName; - input.title = item.alternativeText; - assignFontStyle(input, item); - bindInputItem(input, item); - div.appendChild(input); - break; } } } From 8288b17edcd63543caee83a3131794ab86fe906f Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Mon, 19 Dec 2011 20:04:16 -0600 Subject: [PATCH 6/6] move inputHint to examples --- examples/acroforms/index.html | 1 + web/viewer.css | 10 ---------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/examples/acroforms/index.html b/examples/acroforms/index.html index d07121167..5fad4648a 100644 --- a/examples/acroforms/index.html +++ b/examples/acroforms/index.html @@ -39,6 +39,7 @@ .pdfpage > div { position: absolute; top: 0; left: 0; } .inputControl { background: transparent; border: 0px none; position: absolute; margin: auto; } .inputControl[type='checkbox'] { margin: 0px; } + .inputHint { opacity: 0.2; background: #ccc; position: absolute; } diff --git a/web/viewer.css b/web/viewer.css index 8b2b0cc4d..a1ef92810 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -232,12 +232,6 @@ canvas { -webkit-box-shadow: 0px 2px 10px #ff0; } -.page > .inputHint { - opacity: 0.2; - background: #ccc; - position: absolute; -} - .textLayer { position: absolute; left: 0; @@ -341,10 +335,6 @@ canvas { display: block; page-break-after: always; } - - .inputHint { - display: none; - } } #loading {