diff --git a/bower.json b/bower.json index 2cc1726ef..66be2bdaa 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "pdfjs-dist", - "version": "1.6.214", + "version": "1.6.217", "main": [ "build/pdf.js", "build/pdf.worker.js" diff --git a/build/pdf.combined.js b/build/pdf.combined.js index 08c32c1bc..79e7cdaa8 100644 --- a/build/pdf.combined.js +++ b/build/pdf.combined.js @@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdfCombined = {})); // Use strict in our context only - users might not want it 'use strict'; -var pdfjsVersion = '1.6.214'; -var pdfjsBuild = '7b2a9ee'; +var pdfjsVersion = '1.6.217'; +var pdfjsBuild = '9b3a91f'; var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? @@ -1878,15 +1878,15 @@ var Util = (function UtilClosure() { } }; - Util.getInheritableProperty = function Util_getInheritableProperty(dict, - name) { + Util.getInheritableProperty = + function Util_getInheritableProperty(dict, name, getArray) { while (dict && !dict.has(name)) { dict = dict.get('Parent'); } if (!dict) { return null; } - return dict.get(name); + return getArray ? dict.getArray(name) : dict.get(name); }; Util.inherit = function Util_inherit(sub, base, prototype) { @@ -24229,6 +24229,8 @@ AnnotationElementFactory.prototype = switch (fieldType) { case 'Tx': return new TextWidgetAnnotationElement(parameters); + case 'Ch': + return new ChoiceWidgetAnnotationElement(parameters); } return new WidgetAnnotationElement(parameters); @@ -24553,9 +24555,7 @@ var TextAnnotationElement = (function TextAnnotationElementClosure() { * @alias WidgetAnnotationElement */ var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() { - function WidgetAnnotationElement(parameters) { - var isRenderable = parameters.renderInteractiveForms || - (!parameters.data.hasAppearance && !!parameters.data.fieldValue); + function WidgetAnnotationElement(parameters, isRenderable) { AnnotationElement.call(this, parameters, isRenderable); } @@ -24585,7 +24585,9 @@ var TextWidgetAnnotationElement = ( var TEXT_ALIGNMENT = ['left', 'center', 'right']; function TextWidgetAnnotationElement(parameters) { - WidgetAnnotationElement.call(this, parameters); + var isRenderable = parameters.renderInteractiveForms || + (!parameters.data.hasAppearance && !!parameters.data.fieldValue); + WidgetAnnotationElement.call(this, parameters, isRenderable); } Util.inherit(TextWidgetAnnotationElement, WidgetAnnotationElement, { @@ -24681,6 +24683,64 @@ var TextWidgetAnnotationElement = ( return TextWidgetAnnotationElement; })(); +/** + * @class + * @alias ChoiceWidgetAnnotationElement + */ +var ChoiceWidgetAnnotationElement = ( + function ChoiceWidgetAnnotationElementClosure() { + function ChoiceWidgetAnnotationElement(parameters) { + WidgetAnnotationElement.call(this, parameters, + parameters.renderInteractiveForms); + } + + Util.inherit(ChoiceWidgetAnnotationElement, WidgetAnnotationElement, { + /** + * Render the choice widget annotation's HTML element in the empty + * container. + * + * @public + * @memberof ChoiceWidgetAnnotationElement + * @returns {HTMLSectionElement} + */ + render: function ChoiceWidgetAnnotationElement_render() { + this.container.className = 'choiceWidgetAnnotation'; + + var selectElement = document.createElement('select'); + selectElement.disabled = this.data.readOnly; + + if (!this.data.combo) { + // List boxes have a size and (optionally) multiple selection. + selectElement.size = this.data.options.length; + + if (this.data.multiSelect) { + selectElement.multiple = true; + } + } + + // Insert the options into the choice field. + for (var i = 0, ii = this.data.options.length; i < ii; i++) { + var option = this.data.options[i]; + + var optionElement = document.createElement('option'); + optionElement.textContent = option.displayValue; + optionElement.value = option.exportValue; + + if (this.data.fieldValue.indexOf(option.displayValue) >= 0) { + optionElement.setAttribute('selected', true); + } + + selectElement.appendChild(optionElement); + } + + this.container.appendChild(selectElement); + return this.container; + } + }); + + return ChoiceWidgetAnnotationElement; +})(); + /** * @class * @alias PopupAnnotationElement @@ -49229,6 +49289,8 @@ AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */ { switch (fieldType) { case 'Tx': return new TextWidgetAnnotation(parameters); + case 'Ch': + return new ChoiceWidgetAnnotation(parameters); } warn('Unimplemented widget field type "' + fieldType + '", ' + 'falling back to base field type.'); @@ -49742,8 +49804,8 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() { var data = this.data; data.annotationType = AnnotationType.WIDGET; - data.fieldValue = stringToPDFString( - Util.getInheritableProperty(dict, 'V') || ''); + data.fieldValue = Util.getInheritableProperty(dict, 'V', + /* getArray = */ true); data.alternativeText = stringToPDFString(dict.get('TU') || ''); data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || ''; var fieldType = Util.getInheritableProperty(dict, 'FT'); @@ -49755,6 +49817,8 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() { data.fieldFlags = 0; } + data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY); + // Hide signatures because we cannot validate them. if (data.fieldType === 'Sig') { this.setFlags(AnnotationFlag.HIDDEN); @@ -49816,6 +49880,9 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { function TextWidgetAnnotation(params) { WidgetAnnotation.call(this, params); + // The field value is always a string. + this.data.fieldValue = stringToPDFString(this.data.fieldValue || ''); + // Determine the alignment of text in the field. var alignment = Util.getInheritableProperty(params.dict, 'Q'); if (!isInt(alignment) || alignment < 0 || alignment > 2) { @@ -49831,7 +49898,6 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { this.data.maxLen = maximumLength; // 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) && @@ -49875,6 +49941,62 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { return TextWidgetAnnotation; })(); +var ChoiceWidgetAnnotation = (function ChoiceWidgetAnnotationClosure() { + function ChoiceWidgetAnnotation(params) { + WidgetAnnotation.call(this, params); + + // Determine the options. The options array may consist of strings or + // arrays. If the array consists of arrays, then the first element of + // each array is the export value and the second element of each array is + // the display value. If the array consists of strings, then these + // represent both the export and display value. In this case, we convert + // it to an array of arrays as well for convenience in the display layer. + this.data.options = []; + + var options = params.dict.getArray('Opt'); + if (isArray(options)) { + for (var i = 0, ii = options.length; i < ii; i++) { + var option = options[i]; + + this.data.options[i] = { + exportValue: isArray(option) ? option[0] : option, + displayValue: isArray(option) ? option[1] : option, + }; + } + } + + // Determine the field value. In this case, it may be a string or an + // array of strings. For convenience in the display layer, convert the + // string to an array of one string as well. + if (!isArray(this.data.fieldValue)) { + this.data.fieldValue = [this.data.fieldValue]; + } + + // Process field flags for the display layer. + this.data.combo = this.hasFieldFlag(AnnotationFieldFlag.COMBO); + this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT); + } + + Util.inherit(ChoiceWidgetAnnotation, WidgetAnnotation, { + getOperatorList: + function ChoiceWidgetAnnotation_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); + } + + return Annotation.prototype.getOperatorList.call(this, evaluator, task, + renderForms); + } + }); + + return ChoiceWidgetAnnotation; +})(); + var TextAnnotation = (function TextAnnotationClosure() { var DEFAULT_ICON_SIZE = 22; // px diff --git a/build/pdf.js b/build/pdf.js index 27f7ed612..c563bd8c8 100644 --- a/build/pdf.js +++ b/build/pdf.js @@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdf = {})); // Use strict in our context only - users might not want it 'use strict'; -var pdfjsVersion = '1.6.214'; -var pdfjsBuild = '7b2a9ee'; +var pdfjsVersion = '1.6.217'; +var pdfjsBuild = '9b3a91f'; var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? @@ -892,15 +892,15 @@ var Util = (function UtilClosure() { } }; - Util.getInheritableProperty = function Util_getInheritableProperty(dict, - name) { + Util.getInheritableProperty = + function Util_getInheritableProperty(dict, name, getArray) { while (dict && !dict.has(name)) { dict = dict.get('Parent'); } if (!dict) { return null; } - return dict.get(name); + return getArray ? dict.getArray(name) : dict.get(name); }; Util.inherit = function Util_inherit(sub, base, prototype) { @@ -4395,6 +4395,8 @@ AnnotationElementFactory.prototype = switch (fieldType) { case 'Tx': return new TextWidgetAnnotationElement(parameters); + case 'Ch': + return new ChoiceWidgetAnnotationElement(parameters); } return new WidgetAnnotationElement(parameters); @@ -4719,9 +4721,7 @@ var TextAnnotationElement = (function TextAnnotationElementClosure() { * @alias WidgetAnnotationElement */ var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() { - function WidgetAnnotationElement(parameters) { - var isRenderable = parameters.renderInteractiveForms || - (!parameters.data.hasAppearance && !!parameters.data.fieldValue); + function WidgetAnnotationElement(parameters, isRenderable) { AnnotationElement.call(this, parameters, isRenderable); } @@ -4751,7 +4751,9 @@ var TextWidgetAnnotationElement = ( var TEXT_ALIGNMENT = ['left', 'center', 'right']; function TextWidgetAnnotationElement(parameters) { - WidgetAnnotationElement.call(this, parameters); + var isRenderable = parameters.renderInteractiveForms || + (!parameters.data.hasAppearance && !!parameters.data.fieldValue); + WidgetAnnotationElement.call(this, parameters, isRenderable); } Util.inherit(TextWidgetAnnotationElement, WidgetAnnotationElement, { @@ -4847,6 +4849,64 @@ var TextWidgetAnnotationElement = ( return TextWidgetAnnotationElement; })(); +/** + * @class + * @alias ChoiceWidgetAnnotationElement + */ +var ChoiceWidgetAnnotationElement = ( + function ChoiceWidgetAnnotationElementClosure() { + function ChoiceWidgetAnnotationElement(parameters) { + WidgetAnnotationElement.call(this, parameters, + parameters.renderInteractiveForms); + } + + Util.inherit(ChoiceWidgetAnnotationElement, WidgetAnnotationElement, { + /** + * Render the choice widget annotation's HTML element in the empty + * container. + * + * @public + * @memberof ChoiceWidgetAnnotationElement + * @returns {HTMLSectionElement} + */ + render: function ChoiceWidgetAnnotationElement_render() { + this.container.className = 'choiceWidgetAnnotation'; + + var selectElement = document.createElement('select'); + selectElement.disabled = this.data.readOnly; + + if (!this.data.combo) { + // List boxes have a size and (optionally) multiple selection. + selectElement.size = this.data.options.length; + + if (this.data.multiSelect) { + selectElement.multiple = true; + } + } + + // Insert the options into the choice field. + for (var i = 0, ii = this.data.options.length; i < ii; i++) { + var option = this.data.options[i]; + + var optionElement = document.createElement('option'); + optionElement.textContent = option.displayValue; + optionElement.value = option.exportValue; + + if (this.data.fieldValue.indexOf(option.displayValue) >= 0) { + optionElement.setAttribute('selected', true); + } + + selectElement.appendChild(optionElement); + } + + this.container.appendChild(selectElement); + return this.container; + } + }); + + return ChoiceWidgetAnnotationElement; +})(); + /** * @class * @alias PopupAnnotationElement diff --git a/build/pdf.worker.js b/build/pdf.worker.js index 4695aa44a..d4b2436da 100644 --- a/build/pdf.worker.js +++ b/build/pdf.worker.js @@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdfWorker = {})); // Use strict in our context only - users might not want it 'use strict'; -var pdfjsVersion = '1.6.214'; -var pdfjsBuild = '7b2a9ee'; +var pdfjsVersion = '1.6.217'; +var pdfjsBuild = '9b3a91f'; var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? @@ -1878,15 +1878,15 @@ var Util = (function UtilClosure() { } }; - Util.getInheritableProperty = function Util_getInheritableProperty(dict, - name) { + Util.getInheritableProperty = + function Util_getInheritableProperty(dict, name, getArray) { while (dict && !dict.has(name)) { dict = dict.get('Parent'); } if (!dict) { return null; } - return dict.get(name); + return getArray ? dict.getArray(name) : dict.get(name); }; Util.inherit = function Util_inherit(sub, base, prototype) { @@ -40347,6 +40347,8 @@ AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */ { switch (fieldType) { case 'Tx': return new TextWidgetAnnotation(parameters); + case 'Ch': + return new ChoiceWidgetAnnotation(parameters); } warn('Unimplemented widget field type "' + fieldType + '", ' + 'falling back to base field type.'); @@ -40860,8 +40862,8 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() { var data = this.data; data.annotationType = AnnotationType.WIDGET; - data.fieldValue = stringToPDFString( - Util.getInheritableProperty(dict, 'V') || ''); + data.fieldValue = Util.getInheritableProperty(dict, 'V', + /* getArray = */ true); data.alternativeText = stringToPDFString(dict.get('TU') || ''); data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || ''; var fieldType = Util.getInheritableProperty(dict, 'FT'); @@ -40873,6 +40875,8 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() { data.fieldFlags = 0; } + data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY); + // Hide signatures because we cannot validate them. if (data.fieldType === 'Sig') { this.setFlags(AnnotationFlag.HIDDEN); @@ -40934,6 +40938,9 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { function TextWidgetAnnotation(params) { WidgetAnnotation.call(this, params); + // The field value is always a string. + this.data.fieldValue = stringToPDFString(this.data.fieldValue || ''); + // Determine the alignment of text in the field. var alignment = Util.getInheritableProperty(params.dict, 'Q'); if (!isInt(alignment) || alignment < 0 || alignment > 2) { @@ -40949,7 +40956,6 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { this.data.maxLen = maximumLength; // 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) && @@ -40993,6 +40999,62 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { return TextWidgetAnnotation; })(); +var ChoiceWidgetAnnotation = (function ChoiceWidgetAnnotationClosure() { + function ChoiceWidgetAnnotation(params) { + WidgetAnnotation.call(this, params); + + // Determine the options. The options array may consist of strings or + // arrays. If the array consists of arrays, then the first element of + // each array is the export value and the second element of each array is + // the display value. If the array consists of strings, then these + // represent both the export and display value. In this case, we convert + // it to an array of arrays as well for convenience in the display layer. + this.data.options = []; + + var options = params.dict.getArray('Opt'); + if (isArray(options)) { + for (var i = 0, ii = options.length; i < ii; i++) { + var option = options[i]; + + this.data.options[i] = { + exportValue: isArray(option) ? option[0] : option, + displayValue: isArray(option) ? option[1] : option, + }; + } + } + + // Determine the field value. In this case, it may be a string or an + // array of strings. For convenience in the display layer, convert the + // string to an array of one string as well. + if (!isArray(this.data.fieldValue)) { + this.data.fieldValue = [this.data.fieldValue]; + } + + // Process field flags for the display layer. + this.data.combo = this.hasFieldFlag(AnnotationFieldFlag.COMBO); + this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT); + } + + Util.inherit(ChoiceWidgetAnnotation, WidgetAnnotation, { + getOperatorList: + function ChoiceWidgetAnnotation_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); + } + + return Annotation.prototype.getOperatorList.call(this, evaluator, task, + renderForms); + } + }); + + return ChoiceWidgetAnnotation; +})(); + var TextAnnotation = (function TextAnnotationClosure() { var DEFAULT_ICON_SIZE = 22; // px diff --git a/package.json b/package.json index d603cb5c1..254d46fbb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pdfjs-dist", - "version": "1.6.214", + "version": "1.6.217", "main": "build/pdf.js", "description": "Generic build of Mozilla's PDF.js library.", "keywords": [ diff --git a/web/pdf_viewer.css b/web/pdf_viewer.css index fa2d1eb32..5614df308 100644 --- a/web/pdf_viewer.css +++ b/web/pdf_viewer.css @@ -111,7 +111,8 @@ } .annotationLayer .textWidgetAnnotation input, -.annotationLayer .textWidgetAnnotation textarea { +.annotationLayer .textWidgetAnnotation textarea, +.annotationLayer .choiceWidgetAnnotation select { background-color: rgba(0, 54, 255, 0.13); border: 1px solid transparent; box-sizing: border-box; @@ -129,19 +130,22 @@ } .annotationLayer .textWidgetAnnotation input[disabled], -.annotationLayer .textWidgetAnnotation textarea[disabled] { +.annotationLayer .textWidgetAnnotation textarea[disabled], +.annotationLayer .choiceWidgetAnnotation select[disabled] { background: none; border: 1px solid transparent; cursor: not-allowed; } .annotationLayer .textWidgetAnnotation input:hover, -.annotationLayer .textWidgetAnnotation textarea:hover { +.annotationLayer .textWidgetAnnotation textarea:hover, +.annotationLayer .choiceWidgetAnnotation select:hover { border: 1px solid #000; } .annotationLayer .textWidgetAnnotation input:focus, -.annotationLayer .textWidgetAnnotation textarea:focus { +.annotationLayer .textWidgetAnnotation textarea:focus, +.annotationLayer .choiceWidgetAnnotation select:focus { background: none; border: 1px solid transparent; }