diff --git a/src/core/annotation.js b/src/core/annotation.js index 432f5c3dc..75d030535 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -773,17 +773,18 @@ 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.checkBox = !this.hasFieldFlag(AnnotationFieldFlag.RADIO) && + !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON); + if (this.data.checkBox) { + if (!isName(this.data.fieldValue)) { + return; + } this.data.fieldValue = this.data.fieldValue.name; - } else { - warn('Button widget annotation: field value is not a `Name` object.'); } - if (this.data.radio) { + this.data.radioButton = this.hasFieldFlag(AnnotationFieldFlag.RADIO) && + !this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON); + if (this.data.radioButton) { this.data.fieldValue = this.data.buttonValue = null; // The parent field's `V` entry holds a `Name` object with the appearance @@ -831,7 +832,7 @@ var ButtonWidgetAnnotation = (function ButtonWidgetAnnotationClosure() { if (this.appearance) { return Annotation.prototype.getOperatorList.call(this, evaluator, task, - renderForms); + renderForms); } return Promise.resolve(operatorList); } diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index e5382cdd4..b70992adf 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -77,14 +77,12 @@ AnnotationElementFactory.prototype = 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); - } + if (parameters.data.radioButton) { + return new RadioButtonWidgetAnnotationElement(parameters); + } else if (parameters.data.checkBox) { + return new CheckboxWidgetAnnotationElement(parameters); } else { - warn('Unimplemented push button'); + warn('Unimplemented button widget annotation: pushbutton'); } break; case 'Ch': @@ -152,7 +150,6 @@ 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). @@ -568,15 +565,11 @@ var CheckboxWidgetAnnotationElement = var element = document.createElement('input'); element.disabled = this.data.readOnly; element.type = 'checkbox'; - element.id = this.data.fieldName; if (this.data.fieldValue && this.data.fieldValue !== 'Off') { - element.checked = true; + element.setAttribute('checked', true); } - this.container.appendChild(element); - element = document.createElement('label'); - element.htmlFor = this.data.fieldName; - this.container.appendChild(element); + this.container.appendChild(element); return this.container; } }); @@ -608,22 +601,16 @@ var RadioButtonWidgetAnnotationElement = this.container.className = 'buttonWidgetAnnotation radioButton'; var element = document.createElement('input'); - var id = this.data.fieldName + '.' + this.data.buttonValue; element.disabled = this.data.readOnly; 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; + element.setAttribute('checked', true); } - this.container.appendChild(element); - element = document.createElement('label'); - element.htmlFor = id; - this.container.appendChild(element); + this.container.appendChild(element); return this.container; - }, + } }); return RadioButtonWidgetAnnotationElement; diff --git a/test/annotation_layer_test.css b/test/annotation_layer_test.css index be7935b64..a18dd77ec 100644 --- a/test/annotation_layer_test.css +++ b/test/annotation_layer_test.css @@ -15,6 +15,11 @@ /* Used for annotation layer tests */ +* { + padding: 0; + margin: 0; +} + .annotationLayer { position: absolute; left: 0; @@ -46,8 +51,8 @@ .annotationLayer .textWidgetAnnotation input, .annotationLayer .textWidgetAnnotation textarea, .annotationLayer .choiceWidgetAnnotation select, -.annotationLayer .buttonWidgetAnnotation.checkBox label, -.annotationLayer .buttonWidgetAnnotation.radioButton label { +.annotationLayer .buttonWidgetAnnotation.checkBox input, +.annotationLayer .buttonWidgetAnnotation.radioButton input { background-color: rgba(0, 54, 255, 0.13); border: 1px solid transparent; box-sizing: border-box; @@ -67,8 +72,8 @@ .annotationLayer .textWidgetAnnotation input[disabled], .annotationLayer .textWidgetAnnotation textarea[disabled], .annotationLayer .choiceWidgetAnnotation select[disabled], -.annotationLayer .buttonWidgetAnnotation.checkBox input[disabled] + label, -.annotationLayer .buttonWidgetAnnotation.radioButton input[disabled] + label { +.annotationLayer .buttonWidgetAnnotation.checkBox input[disabled], +.annotationLayer .buttonWidgetAnnotation.radioButton input[disabled] { background: none; border: 1px solid transparent; } @@ -79,19 +84,12 @@ padding-right: 0; } -.annotationLayer .buttonWidgetAnnotation.checkBox label, -.annotationLayer .buttonWidgetAnnotation.radioButton label { - position: absolute; -} - .annotationLayer .buttonWidgetAnnotation.checkBox input, .annotationLayer .buttonWidgetAnnotation.radioButton input { - position: absolute; - left: -9999px; -} - -.annotationLayer .buttonWidgetAnnotation.radioButton label { - border-radius: 50%; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; } .annotationLayer .popupAnnotation { diff --git a/test/unit/annotation_layer_spec.js b/test/unit/annotation_layer_spec.js index 5bdec7f9f..ba10db204 100644 --- a/test/unit/annotation_layer_spec.js +++ b/test/unit/annotation_layer_spec.js @@ -869,95 +869,63 @@ describe('Annotation layer', function() { }); }); - describe('CheckboxWidgetAnnotation', function() { - var checkboxWidgetDict; + describe('ButtonWidgetAnnotation', function() { + var buttonWidgetDict; beforeEach(function (done) { - checkboxWidgetDict = new Dict(); - checkboxWidgetDict.set('Type', Name.get('Annot')); - checkboxWidgetDict.set('Subtype', Name.get('Widget')); - checkboxWidgetDict.set('FT', Name.get('Btn')); + buttonWidgetDict = new Dict(); + buttonWidgetDict.set('Type', Name.get('Annot')); + buttonWidgetDict.set('Subtype', Name.get('Widget')); + buttonWidgetDict.set('FT', Name.get('Btn')); done(); }); afterEach(function () { - checkboxWidgetDict = null; + buttonWidgetDict = 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'); - }); - }); + it('should handle checkboxes', function() { + buttonWidgetDict.set('V', Name.get('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); + var buttonWidgetRef = new Ref(124, 0); + var xref = new XRefMock([ + { ref: buttonWidgetRef, data: buttonWidgetDict, } + ]); - done(); + var buttonWidgetAnnotation = + annotationFactory.create(xref, buttonWidgetRef); + expect(buttonWidgetAnnotation.data.checkBox).toEqual(true); + expect(buttonWidgetAnnotation.data.fieldValue).toEqual('1'); + expect(buttonWidgetAnnotation.data.radioButton).toEqual(false); }); - afterEach(function () { - radioButtonWidgetDict = null; - }); + it('should handle radio buttons', function() { + var parentDict = new Dict(); + parentDict.set('V', Name.get('1')); - it('should have proper flags', - function() { - var radioButtonWidgetRef = new Ref(124, 0); - var xref = new XRefMock([ - { ref: radioButtonWidgetRef, data: radioButtonWidgetDict, } - ]); + var normalAppearanceStateDict = new Dict(); + normalAppearanceStateDict.set('2', null); - var radioButtonWidgetAnnotation = - annotationFactory.create(xref, radioButtonWidgetRef); - expect(radioButtonWidgetAnnotation.data.radio).toEqual(true); - expect(radioButtonWidgetAnnotation.data.pushbutton).toEqual(false); - expect(radioButtonWidgetAnnotation.data.fieldValue).toEqual(null); - }); + var appearanceStatesDict = new Dict(); + appearanceStatesDict.set('N', normalAppearanceStateDict); - it('should have a proper value', - function() { - radioButtonWidgetDict.set('V', Name.get('1')); + buttonWidgetDict.set('Ff', AnnotationFieldFlag.RADIO); + buttonWidgetDict.set('Parent', parentDict); + buttonWidgetDict.set('AP', appearanceStatesDict); - var radioButtonWidgetRef = new Ref(124, 0); - var xref = new XRefMock([ - { ref: radioButtonWidgetRef, data: radioButtonWidgetDict, } - ]); + var buttonWidgetRef = new Ref(124, 0); + var xref = new XRefMock([ + { ref: buttonWidgetRef, data: buttonWidgetDict, } + ]); - var radioButtonWidgetAnnotation = - annotationFactory.create(xref, radioButtonWidgetRef); - expect(radioButtonWidgetAnnotation.data.fieldValue).toEqual('1'); - }); + var buttonWidgetAnnotation = + annotationFactory.create(xref, buttonWidgetRef); + expect(buttonWidgetAnnotation.data.checkBox).toEqual(false); + expect(buttonWidgetAnnotation.data.radioButton).toEqual(true); + expect(buttonWidgetAnnotation.data.fieldValue).toEqual('1'); + expect(buttonWidgetAnnotation.data.buttonValue).toEqual('2'); + }); }); describe('ChoiceWidgetAnnotation', function() { diff --git a/web/annotation_layer_builder.css b/web/annotation_layer_builder.css index 15e2bedc7..982f66134 100644 --- a/web/annotation_layer_builder.css +++ b/web/annotation_layer_builder.css @@ -43,7 +43,9 @@ .annotationLayer .textWidgetAnnotation input, .annotationLayer .textWidgetAnnotation textarea, -.annotationLayer .choiceWidgetAnnotation select { +.annotationLayer .choiceWidgetAnnotation select, +.annotationLayer .buttonWidgetAnnotation.checkBox input, +.annotationLayer .buttonWidgetAnnotation.radioButton input { background-color: rgba(0, 54, 255, 0.13); border: 1px solid transparent; box-sizing: border-box; @@ -63,8 +65,8 @@ .annotationLayer .textWidgetAnnotation input[disabled], .annotationLayer .textWidgetAnnotation textarea[disabled], .annotationLayer .choiceWidgetAnnotation select[disabled], -.annotationLayer .buttonWidgetAnnotation.checkBox input[disabled] + label, -.annotationLayer .buttonWidgetAnnotation.radioButton input[disabled] + label { +.annotationLayer .buttonWidgetAnnotation.checkBox input[disabled], +.annotationLayer .buttonWidgetAnnotation.radioButton input[disabled] { background: none; border: 1px solid transparent; cursor: not-allowed; @@ -72,7 +74,9 @@ .annotationLayer .textWidgetAnnotation input:hover, .annotationLayer .textWidgetAnnotation textarea:hover, -.annotationLayer .choiceWidgetAnnotation select:hover { +.annotationLayer .choiceWidgetAnnotation select:hover, +.annotationLayer .buttonWidgetAnnotation.checkBox input:hover, +.annotationLayer .buttonWidgetAnnotation.radioButton input:hover { border: 1px solid #000; } @@ -99,66 +103,12 @@ width: 115%; } -.annotationLayer .buttonWidgetAnnotation.checkBox label, -.annotationLayer .buttonWidgetAnnotation.radioButton 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 .buttonWidgetAnnotation.checkBox input, .annotationLayer .buttonWidgetAnnotation.radioButton input { - position: absolute; - left: -9999px; -} - -.annotationLayer .buttonWidgetAnnotation.radioButton label { - border-radius: 50%; -} - -.annotationLayer .buttonWidgetAnnotation.checkBox label:hover, -.annotationLayer .buttonWidgetAnnotation.checkBox label:focus, -.annotationLayer .buttonWidgetAnnotation.checkBox input:focus + label, -.annotationLayer .buttonWidgetAnnotation.radioButton label:hover, -.annotationLayer .buttonWidgetAnnotation.radioButton label:focus, -.annotationLayer .buttonWidgetAnnotation.radioButton input:focus + label { - border: 1px solid #000; -} - -.annotationLayer .buttonWidgetAnnotation.checkBox input:checked + label:before, -.annotationLayer .buttonWidgetAnnotation.radioButton input:checked + label:before { - content: ''; - left: 50%; - top: 50%; - position: absolute; -} - -.annotationLayer .buttonWidgetAnnotation.checkBox 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 .buttonWidgetAnnotation.radioButton 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%; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; } .annotationLayer .popupWrapper {