Skip to content

Commit

Permalink
implement interactive text forms
Browse files Browse the repository at this point in the history
  • Loading branch information
xlc committed Feb 14, 2016
1 parent a758de8 commit 78cf950
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand Down
97 changes: 85 additions & 12 deletions src/display/annotation_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
}

Expand All @@ -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;
},

/**
Expand All @@ -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) {
Expand All @@ -421,7 +494,7 @@ var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() {
}
});

return WidgetAnnotationElement;
return TextWidgetAnnotationElement;
})();

/**
Expand Down
23 changes: 23 additions & 0 deletions web/annotation_layer_builder.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

0 comments on commit 78cf950

Please sign in to comment.