Merge pull request #7649 from timvandermeij/interactive-forms-tx-comb

Text widget annotations: implement comb support
This commit is contained in:
Jonas Jenwald 2016-09-22 11:36:30 +02:00 committed by GitHub
commit 6c263c1994
8 changed files with 122 additions and 27 deletions

View File

@ -676,14 +676,13 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() {
* *
* @public * @public
* @memberof WidgetAnnotation * @memberof WidgetAnnotation
* @param {number} flag - Bit position, numbered from one instead of * @param {number} flag - Hexadecimal representation for an annotation
* zero, to check * field characteristic
* @return {boolean} * @return {boolean}
* @see {@link shared/util.js} * @see {@link shared/util.js}
*/ */
hasFieldFlag: function WidgetAnnotation_hasFieldFlag(flag) { hasFieldFlag: function WidgetAnnotation_hasFieldFlag(flag) {
var mask = 1 << (flag - 1); return !!(this.data.fieldFlags & flag);
return !!(this.data.fieldFlags & mask);
}, },
}); });
@ -711,6 +710,11 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
// Process field flags for the display layer. // Process field flags for the display layer.
this.data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY); this.data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);
this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE); this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE);
this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) &&
!this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) &&
!this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) &&
!this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
this.data.maxLen !== null;
} }
Util.inherit(TextWidgetAnnotation, WidgetAnnotation, { Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {

View File

@ -465,6 +465,14 @@ var TextWidgetAnnotationElement = (
if (this.data.maxLen !== null) { if (this.data.maxLen !== null) {
element.maxLength = this.data.maxLen; element.maxLength = this.data.maxLen;
} }
if (this.data.comb) {
var fieldWidth = this.data.rect[2] - this.data.rect[0];
var combWidth = fieldWidth / this.data.maxLen;
element.classList.add('comb');
element.style.letterSpacing = 'calc(' + combWidth + 'px - 1ch)';
}
} else { } else {
element = document.createElement('div'); element = document.createElement('div');
element.textContent = this.data.fieldValue; element.textContent = this.data.fieldValue;

View File

@ -94,25 +94,25 @@ var AnnotationFlag = {
}; };
var AnnotationFieldFlag = { var AnnotationFieldFlag = {
READONLY: 1, READONLY: 0x0000001,
REQUIRED: 2, REQUIRED: 0x0000002,
NOEXPORT: 3, NOEXPORT: 0x0000004,
MULTILINE: 13, MULTILINE: 0x0001000,
PASSWORD: 14, PASSWORD: 0x0002000,
NOTOGGLETOOFF: 15, NOTOGGLETOOFF: 0x0004000,
RADIO: 16, RADIO: 0x0008000,
PUSHBUTTON: 17, PUSHBUTTON: 0x0010000,
COMBO: 18, COMBO: 0x0020000,
EDIT: 19, EDIT: 0x0040000,
SORT: 20, SORT: 0x0080000,
FILESELECT: 21, FILESELECT: 0x0100000,
MULTISELECT: 22, MULTISELECT: 0x0200000,
DONOTSPELLCHECK: 23, DONOTSPELLCHECK: 0x0400000,
DONOTSCROLL: 24, DONOTSCROLL: 0x0800000,
COMB: 25, COMB: 0x1000000,
RICHTEXT: 26, RICHTEXT: 0x2000000,
RADIOSINUNISON: 26, RADIOSINUNISON: 0x2000000,
COMMITONSELCHANGE: 27, COMMITONSELCHANGE: 0x4000000,
}; };
var AnnotationBorderStyleType = { var AnnotationBorderStyleType = {

View File

@ -67,6 +67,12 @@
border: 1px solid transparent; border: 1px solid transparent;
} }
.annotationLayer .textWidgetAnnotation input.comb {
font-family: monospace;
padding-left: 2px;
padding-right: 0;
}
.annotationLayer .popupAnnotation { .annotationLayer .popupAnnotation {
display: block !important; display: block !important;
} }

Binary file not shown.

View File

@ -3204,14 +3204,14 @@
}, },
{ "id": "annotation-text-widget-annotations", { "id": "annotation-text-widget-annotations",
"file": "pdfs/annotation-text-widget.pdf", "file": "pdfs/annotation-text-widget.pdf",
"md5": "cc9672539ad5b837152a9c6961e5f106", "md5": "b7b8923a12998fca8603fae53f73f19b",
"rounds": 1, "rounds": 1,
"type": "eq", "type": "eq",
"annotations": true "annotations": true
}, },
{ "id": "annotation-text-widget-forms", { "id": "annotation-text-widget-forms",
"file": "pdfs/annotation-text-widget.pdf", "file": "pdfs/annotation-text-widget.pdf",
"md5": "cc9672539ad5b837152a9c6961e5f106", "md5": "b7b8923a12998fca8603fae53f73f19b",
"rounds": 1, "rounds": 1,
"type": "eq", "type": "eq",
"forms": true "forms": true

View File

@ -1,7 +1,7 @@
/* globals expect, it, describe, Dict, Name, Annotation, AnnotationBorderStyle, /* globals expect, it, describe, Dict, Name, Annotation, AnnotationBorderStyle,
AnnotationBorderStyleType, AnnotationType, AnnotationFlag, PDFJS, AnnotationBorderStyleType, AnnotationType, AnnotationFlag, PDFJS,
beforeEach, afterEach, stringToBytes, AnnotationFactory, Ref, isRef, beforeEach, afterEach, stringToBytes, AnnotationFactory, Ref, isRef,
beforeAll, afterAll */ beforeAll, afterAll, AnnotationFieldFlag */
'use strict'; 'use strict';
@ -481,6 +481,7 @@ describe('Annotation layer', function() {
expect(textWidgetAnnotation.data.maxLen).toEqual(null); expect(textWidgetAnnotation.data.maxLen).toEqual(null);
expect(textWidgetAnnotation.data.readOnly).toEqual(false); expect(textWidgetAnnotation.data.readOnly).toEqual(false);
expect(textWidgetAnnotation.data.multiLine).toEqual(false); expect(textWidgetAnnotation.data.multiLine).toEqual(false);
expect(textWidgetAnnotation.data.comb).toEqual(false);
}); });
it('should not set invalid text alignment, maximum length and flags', it('should not set invalid text alignment, maximum length and flags',
@ -499,13 +500,15 @@ describe('Annotation layer', function() {
expect(textWidgetAnnotation.data.maxLen).toEqual(null); expect(textWidgetAnnotation.data.maxLen).toEqual(null);
expect(textWidgetAnnotation.data.readOnly).toEqual(false); expect(textWidgetAnnotation.data.readOnly).toEqual(false);
expect(textWidgetAnnotation.data.multiLine).toEqual(false); expect(textWidgetAnnotation.data.multiLine).toEqual(false);
expect(textWidgetAnnotation.data.comb).toEqual(false);
}); });
it('should set valid text alignment, maximum length and flags', it('should set valid text alignment, maximum length and flags',
function() { function() {
textWidgetDict.set('Q', 1); textWidgetDict.set('Q', 1);
textWidgetDict.set('MaxLen', 20); textWidgetDict.set('MaxLen', 20);
textWidgetDict.set('Ff', 4097); textWidgetDict.set('Ff', AnnotationFieldFlag.READONLY +
AnnotationFieldFlag.MULTILINE);
var textWidgetRef = new Ref(84, 0); var textWidgetRef = new Ref(84, 0);
var xref = new XRefMock([ var xref = new XRefMock([
@ -518,6 +521,64 @@ describe('Annotation layer', function() {
expect(textWidgetAnnotation.data.readOnly).toEqual(true); expect(textWidgetAnnotation.data.readOnly).toEqual(true);
expect(textWidgetAnnotation.data.multiLine).toEqual(true); expect(textWidgetAnnotation.data.multiLine).toEqual(true);
}); });
it('should reject comb fields without a maximum length', function() {
textWidgetDict.set('Ff', AnnotationFieldFlag.COMB);
var textWidgetRef = new Ref(46, 0);
var xref = new XRefMock([
{ ref: textWidgetRef, data: textWidgetDict, }
]);
var textWidgetAnnotation = annotationFactory.create(xref, textWidgetRef);
expect(textWidgetAnnotation.data.comb).toEqual(false);
});
it('should accept comb fields with a maximum length', function() {
textWidgetDict.set('MaxLen', 20);
textWidgetDict.set('Ff', AnnotationFieldFlag.COMB);
var textWidgetRef = new Ref(46, 0);
var xref = new XRefMock([
{ ref: textWidgetRef, data: textWidgetDict, }
]);
var textWidgetAnnotation = annotationFactory.create(xref, textWidgetRef);
expect(textWidgetAnnotation.data.comb).toEqual(true);
});
it('should only accept comb fields when the flags are valid', function() {
var invalidFieldFlags = [
AnnotationFieldFlag.MULTILINE, AnnotationFieldFlag.PASSWORD,
AnnotationFieldFlag.FILESELECT
];
// Start with all invalid flags set and remove them one by one.
// The field may only use combs when all invalid flags are unset.
var flags = AnnotationFieldFlag.COMB + AnnotationFieldFlag.MULTILINE +
AnnotationFieldFlag.PASSWORD + AnnotationFieldFlag.FILESELECT;
for (var i = 0, ii = invalidFieldFlags.length; i <= ii; i++) {
textWidgetDict.set('MaxLen', 20);
textWidgetDict.set('Ff', flags);
var textWidgetRef = new Ref(93, 0);
var xref = new XRefMock([
{ ref: textWidgetRef, data: textWidgetDict, }
]);
var textWidgetAnnotation = annotationFactory.create(xref,
textWidgetRef);
var valid = (invalidFieldFlags.length === 0);
expect(textWidgetAnnotation.data.comb).toEqual(valid);
// Remove the last invalid flag for the next iteration.
if (!valid) {
flags -= invalidFieldFlags.splice(-1, 1);
}
}
});
}); });
describe('FileAttachmentAnnotation', function() { describe('FileAttachmentAnnotation', function() {

View File

@ -77,6 +77,22 @@
border: 1px solid transparent; border: 1px solid transparent;
} }
.annotationLayer .textWidgetAnnotation input.comb {
font-family: monospace;
padding-left: 2px;
padding-right: 0;
}
.annotationLayer .textWidgetAnnotation input.comb:focus {
/*
* Letter spacing is placed on the right side of each character. Hence, the
* letter spacing of the last character may be placed outside the visible
* area, causing horizontal scrolling. We avoid this by extending the width
* when the element has focus and revert this when it loses focus.
*/
width: 115%;
}
.annotationLayer .popupWrapper { .annotationLayer .popupWrapper {
position: absolute; position: absolute;
width: 20em; width: 20em;