Button widget annotations: implement checkboxes and radio buttons
This commit is contained in:
		
							parent
							
								
									d0893b0c48
								
							
						
					
					
						commit
						ba012c7a68
					
				@ -106,6 +106,8 @@ AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */ {
 | 
			
		||||
        switch (fieldType) {
 | 
			
		||||
          case 'Tx':
 | 
			
		||||
            return new TextWidgetAnnotation(parameters);
 | 
			
		||||
          case 'Btn':
 | 
			
		||||
            return new ButtonWidgetAnnotation(parameters);
 | 
			
		||||
          case 'Ch':
 | 
			
		||||
            return new ChoiceWidgetAnnotation(parameters);
 | 
			
		||||
        }
 | 
			
		||||
@ -767,6 +769,59 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
 | 
			
		||||
  return TextWidgetAnnotation;
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
var ButtonWidgetAnnotation = (function ButtonWidgetAnnotationClosure() {
 | 
			
		||||
  function ButtonWidgetAnnotation(params) {
 | 
			
		||||
    WidgetAnnotation.call(this, params);
 | 
			
		||||
 | 
			
		||||
    this.data.pushbutton = this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
 | 
			
		||||
    this.data.radio = !this.data.pushbutton &&
 | 
			
		||||
                      this.hasFieldFlag(AnnotationFieldFlag.RADIO);
 | 
			
		||||
    if (isName(this.data.fieldValue)) {
 | 
			
		||||
      this.data.fieldValue = this.data.fieldValue.name;
 | 
			
		||||
    }
 | 
			
		||||
    // Get the value of the radio button
 | 
			
		||||
    if (this.data.radio) {
 | 
			
		||||
      // Generate a unique ID in case no value is found
 | 
			
		||||
      this.data.buttonValue = Math.random().toString(16).slice(2);
 | 
			
		||||
      var appearanceState = params.dict.get('AP');
 | 
			
		||||
      if (isDict(appearanceState)) {
 | 
			
		||||
        var appearances = appearanceState.get('N');
 | 
			
		||||
        if (isDict(appearances) && appearances.has('Off')) {
 | 
			
		||||
          var keys = appearances.getKeys();
 | 
			
		||||
          for (var i = 0, ii = keys.length; i < ii; i++) {
 | 
			
		||||
            if (keys[i] !== 'Off') {
 | 
			
		||||
              this.data.buttonValue = keys[i];
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Util.inherit(ButtonWidgetAnnotation, WidgetAnnotation, {
 | 
			
		||||
    getOperatorList:
 | 
			
		||||
        function ButtonWidgetAnnotation_getOperatorList(evaluator, task,
 | 
			
		||||
                                                        renderForms) {
 | 
			
		||||
      var operatorList = new OperatorList();
 | 
			
		||||
 | 
			
		||||
      // Do not render form elements on the canvas when interactive forms are
 | 
			
		||||
      // enabled. The display layer is responsible for rendering them instead.
 | 
			
		||||
      if (renderForms) {
 | 
			
		||||
        return Promise.resolve(operatorList);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (this.appearance) {
 | 
			
		||||
        return Annotation.prototype.getOperatorList.call(this, evaluator, task,
 | 
			
		||||
                                                        renderForms);
 | 
			
		||||
      }
 | 
			
		||||
      return Promise.resolve(operatorList);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return ButtonWidgetAnnotation;
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
var ChoiceWidgetAnnotation = (function ChoiceWidgetAnnotationClosure() {
 | 
			
		||||
  function ChoiceWidgetAnnotation(params) {
 | 
			
		||||
    WidgetAnnotation.call(this, params);
 | 
			
		||||
 | 
			
		||||
@ -76,6 +76,17 @@ AnnotationElementFactory.prototype =
 | 
			
		||||
        switch (fieldType) {
 | 
			
		||||
          case 'Tx':
 | 
			
		||||
            return new TextWidgetAnnotationElement(parameters);
 | 
			
		||||
          case 'Btn':
 | 
			
		||||
            if (!parameters.data.pushbutton) {
 | 
			
		||||
              if (parameters.data.radio) {
 | 
			
		||||
                return new RadioButtonWidgetAnnotationElement(parameters);
 | 
			
		||||
              } else {
 | 
			
		||||
                return new CheckboxWidgetAnnotationElement(parameters);
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              warn('Unimplemented push button');
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
          case 'Ch':
 | 
			
		||||
            return new ChoiceWidgetAnnotationElement(parameters);
 | 
			
		||||
        }
 | 
			
		||||
@ -141,6 +152,7 @@ var AnnotationElement = (function AnnotationElementClosure() {
 | 
			
		||||
      var height = data.rect[3] - data.rect[1];
 | 
			
		||||
 | 
			
		||||
      container.setAttribute('data-annotation-id', data.id);
 | 
			
		||||
      container.setAttribute('data-annotation-name', data.fieldName);
 | 
			
		||||
 | 
			
		||||
      // Do *not* modify `data.rect`, since that will corrupt the annotation
 | 
			
		||||
      // position on subsequent calls to `_createContainer` (see issue 6804).
 | 
			
		||||
@ -531,6 +543,91 @@ var TextWidgetAnnotationElement = (
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @class
 | 
			
		||||
 * @alias CheckboxWidgetAnnotationElement
 | 
			
		||||
 */
 | 
			
		||||
var CheckboxWidgetAnnotationElement =
 | 
			
		||||
    (function CheckboxWidgetAnnotationElementClosure() {
 | 
			
		||||
  function CheckboxWidgetAnnotationElement(parameters) {
 | 
			
		||||
    WidgetAnnotationElement.call(this, parameters,
 | 
			
		||||
                                 parameters.renderInteractiveForms);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Util.inherit(CheckboxWidgetAnnotationElement, WidgetAnnotationElement, {
 | 
			
		||||
    /**
 | 
			
		||||
     * Render the checkbox widget annotation's HTML element
 | 
			
		||||
     * in the empty container.
 | 
			
		||||
     *
 | 
			
		||||
     * @public
 | 
			
		||||
     * @memberof CheckboxWidgetAnnotationElement
 | 
			
		||||
     * @returns {HTMLSectionElement}
 | 
			
		||||
     */
 | 
			
		||||
    render: function CheckboxWidgetAnnotationElement_render() {
 | 
			
		||||
      this.container.className = 'checkboxWidgetAnnotation';
 | 
			
		||||
 | 
			
		||||
      var element = document.createElement('input');
 | 
			
		||||
      element.type = 'checkbox';
 | 
			
		||||
      element.id = this.data.fieldName;
 | 
			
		||||
      if (this.data.fieldValue && this.data.fieldValue !== 'Off') {
 | 
			
		||||
        element.checked = true;
 | 
			
		||||
      }
 | 
			
		||||
      this.container.appendChild(element);
 | 
			
		||||
      element = document.createElement('label');
 | 
			
		||||
      element.htmlFor = this.data.fieldName;
 | 
			
		||||
      this.container.appendChild(element);
 | 
			
		||||
 | 
			
		||||
      return this.container;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return CheckboxWidgetAnnotationElement;
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @class
 | 
			
		||||
 * @alias RadioButtonWidgetAnnotationElement
 | 
			
		||||
 */
 | 
			
		||||
var RadioButtonWidgetAnnotationElement =
 | 
			
		||||
    (function RadioButtonWidgetAnnotationElementClosure() {
 | 
			
		||||
  function RadioButtonWidgetAnnotationElement(parameters) {
 | 
			
		||||
    WidgetAnnotationElement.call(this, parameters,
 | 
			
		||||
                                 parameters.renderInteractiveForms);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Util.inherit(RadioButtonWidgetAnnotationElement, WidgetAnnotationElement, {
 | 
			
		||||
    /**
 | 
			
		||||
     * Render the radio button widget annotation's HTML element
 | 
			
		||||
     * in the empty container.
 | 
			
		||||
     *
 | 
			
		||||
     * @public
 | 
			
		||||
     * @memberof RadioButtonWidgetAnnotationElement
 | 
			
		||||
     * @returns {HTMLSectionElement}
 | 
			
		||||
     */
 | 
			
		||||
    render: function RadioButtonWidgetAnnotationElement_render() {
 | 
			
		||||
      this.container.className = 'radioButtonWidgetAnnotation';
 | 
			
		||||
 | 
			
		||||
      var element = document.createElement('input');
 | 
			
		||||
      var id = this.data.fieldName + '.' + this.data.buttonValue;
 | 
			
		||||
      element.type = 'radio';
 | 
			
		||||
      element.id = id;
 | 
			
		||||
      element.name = this.data.fieldName;
 | 
			
		||||
      element.value = this.data.buttonValue;
 | 
			
		||||
      if (this.data.fieldValue === this.data.buttonValue) {
 | 
			
		||||
        element.checked = true;
 | 
			
		||||
      }
 | 
			
		||||
      this.container.appendChild(element);
 | 
			
		||||
      element = document.createElement('label');
 | 
			
		||||
      element.htmlFor = id;
 | 
			
		||||
      this.container.appendChild(element);
 | 
			
		||||
 | 
			
		||||
      return this.container;
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return RadioButtonWidgetAnnotationElement;
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
 /**
 | 
			
		||||
 * @class
 | 
			
		||||
 * @alias ChoiceWidgetAnnotationElement
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@ -869,6 +869,97 @@ describe('Annotation layer', function() {
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('CheckboxWidgetAnnotation', function() {
 | 
			
		||||
    var checkboxWidgetDict;
 | 
			
		||||
 | 
			
		||||
    beforeEach(function (done) {
 | 
			
		||||
      checkboxWidgetDict = new Dict();
 | 
			
		||||
      checkboxWidgetDict.set('Type', Name.get('Annot'));
 | 
			
		||||
      checkboxWidgetDict.set('Subtype', Name.get('Widget'));
 | 
			
		||||
      checkboxWidgetDict.set('FT', Name.get('Btn'));
 | 
			
		||||
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    afterEach(function () {
 | 
			
		||||
      checkboxWidgetDict = null;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should have proper flags',
 | 
			
		||||
      function() {
 | 
			
		||||
        var checkboxWidgetRef = new Ref(124, 0);
 | 
			
		||||
        var xref = new XRefMock([
 | 
			
		||||
          { ref: checkboxWidgetRef, data: checkboxWidgetDict, }
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        var checkboxWidgetAnnotation =
 | 
			
		||||
          annotationFactory.create(xref, checkboxWidgetRef);
 | 
			
		||||
        expect(checkboxWidgetAnnotation.data.radio).toEqual(false);
 | 
			
		||||
        expect(checkboxWidgetAnnotation.data.pushbutton).toEqual(false);
 | 
			
		||||
        expect(checkboxWidgetAnnotation.data.fieldValue).toEqual(null);
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    it('should have a proper value',
 | 
			
		||||
      function() {
 | 
			
		||||
        checkboxWidgetDict.set('V', Name.get('1'));
 | 
			
		||||
 | 
			
		||||
        var checkboxWidgetRef = new Ref(124, 0);
 | 
			
		||||
        var xref = new XRefMock([
 | 
			
		||||
          { ref: checkboxWidgetRef, data: checkboxWidgetDict, }
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        var checkboxWidgetAnnotation =
 | 
			
		||||
          annotationFactory.create(xref, checkboxWidgetRef);
 | 
			
		||||
        expect(checkboxWidgetAnnotation.data.fieldValue).toEqual('1');
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('RadioButtonWidgetAnnotation', function() {
 | 
			
		||||
    var radioButtonWidgetDict;
 | 
			
		||||
 | 
			
		||||
    beforeEach(function (done) {
 | 
			
		||||
      radioButtonWidgetDict = new Dict();
 | 
			
		||||
      radioButtonWidgetDict.set('Type', Name.get('Annot'));
 | 
			
		||||
      radioButtonWidgetDict.set('Subtype', Name.get('Widget'));
 | 
			
		||||
      radioButtonWidgetDict.set('FT', Name.get('Btn'));
 | 
			
		||||
      radioButtonWidgetDict.set('Ff', AnnotationFieldFlag.RADIO);
 | 
			
		||||
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    afterEach(function () {
 | 
			
		||||
      radioButtonWidgetDict = null;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should have proper flags',
 | 
			
		||||
      function() {
 | 
			
		||||
        var radioButtonWidgetRef = new Ref(124, 0);
 | 
			
		||||
        var xref = new XRefMock([
 | 
			
		||||
          { ref: radioButtonWidgetRef, data: radioButtonWidgetDict, }
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        var radioButtonWidgetAnnotation =
 | 
			
		||||
          annotationFactory.create(xref, radioButtonWidgetRef);
 | 
			
		||||
        expect(radioButtonWidgetAnnotation.data.radio).toEqual(true);
 | 
			
		||||
        expect(radioButtonWidgetAnnotation.data.pushbutton).toEqual(false);
 | 
			
		||||
        expect(radioButtonWidgetAnnotation.data.fieldValue).toEqual(null);
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    it('should have a proper value',
 | 
			
		||||
      function() {
 | 
			
		||||
        radioButtonWidgetDict.set('V', Name.get('1'));
 | 
			
		||||
 | 
			
		||||
        var radioButtonWidgetRef = new Ref(124, 0);
 | 
			
		||||
        var xref = new XRefMock([
 | 
			
		||||
          { ref: radioButtonWidgetRef, data: radioButtonWidgetDict, }
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        var radioButtonWidgetAnnotation =
 | 
			
		||||
          annotationFactory.create(xref, radioButtonWidgetRef);
 | 
			
		||||
        expect(radioButtonWidgetAnnotation.data.fieldValue).toEqual('1');
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('ChoiceWidgetAnnotation', function() {
 | 
			
		||||
    var choiceWidgetDict;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -97,6 +97,68 @@
 | 
			
		||||
  width: 115%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .checkboxWidgetAnnotation label,
 | 
			
		||||
.annotationLayer .radioButtonWidgetAnnotation label {
 | 
			
		||||
  background-color: rgba(0, 54, 255, 0.13);
 | 
			
		||||
  border: 1px solid transparent;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .checkboxWidgetAnnotation input,
 | 
			
		||||
.annotationLayer .radioButtonWidgetAnnotation input {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  left: -9999px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .radioButtonWidgetAnnotation label {
 | 
			
		||||
  border-radius: 50%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .checkboxWidgetAnnotation label:hover,
 | 
			
		||||
.annotationLayer .radioButtonWidgetAnnotation label:hover,
 | 
			
		||||
.annotationLayer .checkboxWidgetAnnotation label:focus,
 | 
			
		||||
.annotationLayer .radioButtonWidgetAnnotation label:focus,
 | 
			
		||||
.annotationLayer .checkboxWidgetAnnotation input:focus + label,
 | 
			
		||||
.annotationLayer .radioButtonWidgetAnnotation input:focus + label {
 | 
			
		||||
  border: 1px solid #000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .checkboxWidgetAnnotation input:checked + label:before,
 | 
			
		||||
.annotationLayer .radioButtonWidgetAnnotation input:checked + label:before {
 | 
			
		||||
  content: '';
 | 
			
		||||
  left: 50%;
 | 
			
		||||
  top: 50%;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .checkboxWidgetAnnotation input:checked + label:before {
 | 
			
		||||
  border-bottom: 1px solid #000;
 | 
			
		||||
  border-left: 1px solid #000;
 | 
			
		||||
  height: 25%;
 | 
			
		||||
  -webkit-transform: translate(-50%, -65%) rotateZ(-45deg);
 | 
			
		||||
  -moz-transform: translate(-50%, -65%) rotateZ(-45deg);
 | 
			
		||||
  -o-transform: translate(-50%, -65%) rotateZ(-45deg);
 | 
			
		||||
  -ms-transform: translate(-50%, -65%) rotateZ(-45deg);
 | 
			
		||||
  transform: translate(-50%, -65%) rotateZ(-45deg);
 | 
			
		||||
  width: 60%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .radioButtonWidgetAnnotation input:checked + label:before {
 | 
			
		||||
  background-color: #000;
 | 
			
		||||
  border-radius: 50%;
 | 
			
		||||
  height: 50%;
 | 
			
		||||
  -webkit-transform: translate(-50%, -50%);
 | 
			
		||||
  -moz-transform: translate(-50%, -50%);
 | 
			
		||||
  -o-transform: translate(-50%, -50%);
 | 
			
		||||
  -ms-transform: translate(-50%, -50%);
 | 
			
		||||
  transform: translate(-50%, -50%);
 | 
			
		||||
  width: 50%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.annotationLayer .popupWrapper {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  width: 20em;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user