Merge pull request #7649 from timvandermeij/interactive-forms-tx-comb
Text widget annotations: implement comb support
This commit is contained in:
		
						commit
						6c263c1994
					
				@ -676,14 +676,13 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() {
 | 
			
		||||
     *
 | 
			
		||||
     * @public
 | 
			
		||||
     * @memberof WidgetAnnotation
 | 
			
		||||
     * @param {number} flag - Bit position, numbered from one instead of
 | 
			
		||||
     *                        zero, to check
 | 
			
		||||
     * @param {number} flag - Hexadecimal representation for an annotation
 | 
			
		||||
     *                        field characteristic
 | 
			
		||||
     * @return {boolean}
 | 
			
		||||
     * @see {@link shared/util.js}
 | 
			
		||||
     */
 | 
			
		||||
    hasFieldFlag: function WidgetAnnotation_hasFieldFlag(flag) {
 | 
			
		||||
      var mask = 1 << (flag - 1);
 | 
			
		||||
      return !!(this.data.fieldFlags & mask);
 | 
			
		||||
      return !!(this.data.fieldFlags & flag);
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@ -711,6 +710,11 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
 | 
			
		||||
    // Process field flags for the display layer.
 | 
			
		||||
    this.data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);
 | 
			
		||||
    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, {
 | 
			
		||||
 | 
			
		||||
@ -465,6 +465,14 @@ var TextWidgetAnnotationElement = (
 | 
			
		||||
        if (this.data.maxLen !== null) {
 | 
			
		||||
          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 {
 | 
			
		||||
        element = document.createElement('div');
 | 
			
		||||
        element.textContent = this.data.fieldValue;
 | 
			
		||||
 | 
			
		||||
@ -94,25 +94,25 @@ var AnnotationFlag = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var AnnotationFieldFlag = {
 | 
			
		||||
  READONLY: 1,
 | 
			
		||||
  REQUIRED: 2,
 | 
			
		||||
  NOEXPORT: 3,
 | 
			
		||||
  MULTILINE: 13,
 | 
			
		||||
  PASSWORD: 14,
 | 
			
		||||
  NOTOGGLETOOFF: 15,
 | 
			
		||||
  RADIO: 16,
 | 
			
		||||
  PUSHBUTTON: 17,
 | 
			
		||||
  COMBO: 18,
 | 
			
		||||
  EDIT: 19,
 | 
			
		||||
  SORT: 20,
 | 
			
		||||
  FILESELECT: 21,
 | 
			
		||||
  MULTISELECT: 22,
 | 
			
		||||
  DONOTSPELLCHECK: 23,
 | 
			
		||||
  DONOTSCROLL: 24,
 | 
			
		||||
  COMB: 25,
 | 
			
		||||
  RICHTEXT: 26,
 | 
			
		||||
  RADIOSINUNISON: 26,
 | 
			
		||||
  COMMITONSELCHANGE: 27,
 | 
			
		||||
  READONLY: 0x0000001,
 | 
			
		||||
  REQUIRED: 0x0000002,
 | 
			
		||||
  NOEXPORT: 0x0000004,
 | 
			
		||||
  MULTILINE: 0x0001000,
 | 
			
		||||
  PASSWORD: 0x0002000,
 | 
			
		||||
  NOTOGGLETOOFF: 0x0004000,
 | 
			
		||||
  RADIO: 0x0008000,
 | 
			
		||||
  PUSHBUTTON: 0x0010000,
 | 
			
		||||
  COMBO: 0x0020000,
 | 
			
		||||
  EDIT: 0x0040000,
 | 
			
		||||
  SORT: 0x0080000,
 | 
			
		||||
  FILESELECT: 0x0100000,
 | 
			
		||||
  MULTISELECT: 0x0200000,
 | 
			
		||||
  DONOTSPELLCHECK: 0x0400000,
 | 
			
		||||
  DONOTSCROLL: 0x0800000,
 | 
			
		||||
  COMB: 0x1000000,
 | 
			
		||||
  RICHTEXT: 0x2000000,
 | 
			
		||||
  RADIOSINUNISON: 0x2000000,
 | 
			
		||||
  COMMITONSELCHANGE: 0x4000000,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var AnnotationBorderStyleType = {
 | 
			
		||||
 | 
			
		||||
@ -67,6 +67,12 @@
 | 
			
		||||
  border: 1px solid transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .textWidgetAnnotation input.comb {
 | 
			
		||||
  font-family: monospace;
 | 
			
		||||
  padding-left: 2px;
 | 
			
		||||
  padding-right: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .popupAnnotation {
 | 
			
		||||
  display: block !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@ -3204,14 +3204,14 @@
 | 
			
		||||
    },
 | 
			
		||||
    {  "id": "annotation-text-widget-annotations",
 | 
			
		||||
       "file": "pdfs/annotation-text-widget.pdf",
 | 
			
		||||
       "md5": "cc9672539ad5b837152a9c6961e5f106",
 | 
			
		||||
       "md5": "b7b8923a12998fca8603fae53f73f19b",
 | 
			
		||||
       "rounds": 1,
 | 
			
		||||
       "type": "eq",
 | 
			
		||||
       "annotations": true
 | 
			
		||||
    },
 | 
			
		||||
    {  "id": "annotation-text-widget-forms",
 | 
			
		||||
       "file": "pdfs/annotation-text-widget.pdf",
 | 
			
		||||
       "md5": "cc9672539ad5b837152a9c6961e5f106",
 | 
			
		||||
       "md5": "b7b8923a12998fca8603fae53f73f19b",
 | 
			
		||||
       "rounds": 1,
 | 
			
		||||
       "type": "eq",
 | 
			
		||||
       "forms": true
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
/* globals expect, it, describe, Dict, Name, Annotation, AnnotationBorderStyle,
 | 
			
		||||
           AnnotationBorderStyleType, AnnotationType, AnnotationFlag, PDFJS,
 | 
			
		||||
           beforeEach, afterEach, stringToBytes, AnnotationFactory, Ref, isRef,
 | 
			
		||||
           beforeAll, afterAll */
 | 
			
		||||
           beforeAll, afterAll, AnnotationFieldFlag */
 | 
			
		||||
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
@ -481,6 +481,7 @@ describe('Annotation layer', function() {
 | 
			
		||||
      expect(textWidgetAnnotation.data.maxLen).toEqual(null);
 | 
			
		||||
      expect(textWidgetAnnotation.data.readOnly).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',
 | 
			
		||||
@ -499,13 +500,15 @@ describe('Annotation layer', function() {
 | 
			
		||||
      expect(textWidgetAnnotation.data.maxLen).toEqual(null);
 | 
			
		||||
      expect(textWidgetAnnotation.data.readOnly).toEqual(false);
 | 
			
		||||
      expect(textWidgetAnnotation.data.multiLine).toEqual(false);
 | 
			
		||||
      expect(textWidgetAnnotation.data.comb).toEqual(false);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should set valid text alignment, maximum length and flags',
 | 
			
		||||
        function() {
 | 
			
		||||
      textWidgetDict.set('Q', 1);
 | 
			
		||||
      textWidgetDict.set('MaxLen', 20);
 | 
			
		||||
      textWidgetDict.set('Ff', 4097);
 | 
			
		||||
      textWidgetDict.set('Ff', AnnotationFieldFlag.READONLY +
 | 
			
		||||
                               AnnotationFieldFlag.MULTILINE);
 | 
			
		||||
 | 
			
		||||
      var textWidgetRef = new Ref(84, 0);
 | 
			
		||||
      var xref = new XRefMock([
 | 
			
		||||
@ -518,6 +521,64 @@ describe('Annotation layer', function() {
 | 
			
		||||
      expect(textWidgetAnnotation.data.readOnly).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() {
 | 
			
		||||
 | 
			
		||||
@ -77,6 +77,22 @@
 | 
			
		||||
  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 {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  width: 20em;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user