diff --git a/src/core/annotation.js b/src/core/annotation.js index 46a59c916bae7f..d4f0cedc7ef61b 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -620,6 +620,7 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { WidgetAnnotation.call(this, params); this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q'); + this.data.maxLen = Util.getInheritableProperty(params.dict, 'MaxLen'); } Util.inherit(TextWidgetAnnotation, WidgetAnnotation, { diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index 6f8456e725e5fd..65b4e1f201a48a 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -66,6 +66,13 @@ AnnotationElementFactory.prototype = return new TextAnnotationElement(parameters); case AnnotationType.WIDGET: + switch (parameters.data.fieldType) { + case 'Tx': + return new TextWidgetAnnotationElement(parameters); + } + warn('Unimplemented Widget annotation type: ' + + parameters.data.fieldType); + // Fallback to default one, which does not render anything. return new WidgetAnnotationElement(parameters); case AnnotationType.POPUP: @@ -356,9 +363,7 @@ var TextAnnotationElement = (function TextAnnotationElementClosure() { * @alias WidgetAnnotationElement */ var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() { - function WidgetAnnotationElement(parameters) { - var isRenderable = !parameters.data.hasAppearance && - !!parameters.data.fieldValue; + function WidgetAnnotationElement(parameters, isRenderable) { AnnotationElement.call(this, parameters, isRenderable); } @@ -371,19 +376,87 @@ var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() { * @returns {HTMLSectionElement} */ render: function WidgetAnnotationElement_render() { - var content = document.createElement('div'); - content.textContent = this.data.fieldValue; + return this.container; + }, + + /** + * Check bit value for given position in fieldFlags. + * Note: position is 1 based index. + * + * @private + * @memberof WidgetAnnotationElement + * @returns {boolean} + */ + _hasFlag: function WidgetAnnotationElement_hasFlag(position) { + return !!(this.data.fieldFlags & (1 << (position - 1))); + } + }); + + return WidgetAnnotationElement; +})(); + +/** + * @class + * @alias TextWidgetAnnotationElement + */ +var TextWidgetAnnotationElement = + (function TextWidgetAnnotationElementClosure() { + + var READONLY_BIT = 1; + var MULTILINE_BIT = 13; + + function TextWidgetAnnotationElement(parameters) { + WidgetAnnotationElement.call(this, parameters, true); + } + + Util.inherit(TextWidgetAnnotationElement, WidgetAnnotationElement, { + /** + * Render the text widget annotation's HTML element. + * + * @public + * @memberof TextWidgetAnnotationElement + * @returns {HTMLSectionElement} + */ + render: function TextWidgetAnnotationElement_render() { + var container = WidgetAnnotationElement.prototype.render.call(this); + + var isReadonly = this._hasFlag(READONLY_BIT); + var isMultiline = this._hasFlag(MULTILINE_BIT); + + var content; + if (isMultiline) { + content = document.createElement('textarea'); + } else { + content = document.createElement('input'); + content.type = 'text'; + } + + content.disabled = isReadonly; + content.value = this.data.fieldValue; var textAlignment = this.data.textAlignment; content.style.textAlign = ['left', 'center', 'right'][textAlignment]; - content.style.verticalAlign = 'middle'; - content.style.display = 'table-cell'; + if (this.data.maxLen !== null) { + content.maxLength = this.data.maxLen; + } var font = (this.data.fontRefName ? this.page.commonObjs.getData(this.data.fontRefName) : null); this._setTextStyle(content, font); - this.container.appendChild(content); - return this.container; + if (!isMultiline && !('fontSize' in this.data)) { + // hack to guess font size based on content hight + // so small text fields are rendered correctly. + // TODO: remove this when we can apply the default appearance. + var height = this.data.rect[3] - this.data.rect[1]; + if (height < 15) { + content.style.fontSize = (height - 1) + 'px'; + } + } + + container.appendChild(content); + + container.className = 'widgetAnnotation'; + return container; }, /** @@ -392,10 +465,10 @@ var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() { * @private * @param {HTMLDivElement} element * @param {Object} font - * @memberof WidgetAnnotationElement + * @memberof TextWidgetAnnotationElement */ _setTextStyle: - function WidgetAnnotationElement_setTextStyle(element, font) { + function TextWidgetAnnotationElement_setTextStyle(element, font) { // TODO: This duplicates some of the logic in CanvasGraphics.setFont(). var style = element.style; if ('fontSize' in this.data) { @@ -421,7 +494,7 @@ var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() { } }); - return WidgetAnnotationElement; + return TextWidgetAnnotationElement; })(); /** diff --git a/web/annotation_layer_builder.css b/web/annotation_layer_builder.css index 3c6b4e43ddfd2e..925f2d81ee1e85 100644 --- a/web/annotation_layer_builder.css +++ b/web/annotation_layer_builder.css @@ -75,3 +75,26 @@ .annotationLayer .strikeoutAnnotation { cursor: pointer; } + +.annotationLayer input[disabled], textarea[disabled] { + cursor: not-allowed; +} + +.annotationLayer .widgetAnnotation > input[type='text'], textarea { + vertical-align: top; +} + +.annotationLayer .widgetAnnotation textarea { + resize: none; + width: 100%; + height: 100%; + background: rgba(192, 192, 192, 0.2); + border: 0px none; +} + +.annotationLayer .widgetAnnotation input[type='text'] { + width: 100%; + height: 100%; + background: rgba(192, 192, 192, 0.2); + border: 0px none; +}