Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic AcroForms input controls rendering #6172

Closed
wants to merge 3 commits into from
Closed

Conversation

xlc
Copy link
Contributor

@xlc xlc commented Jul 3, 2015

There is already an example implementation of AcroForms in the examples folder. This PR aim to do it properly.

This PR only provide basic implementation of text input fields. Other types of fields (buttons, choice) will be implemented in later PRs.

Issues & Questions:

  • Printing: Currently only buttons are rendered in canvas and other form elements are not printed.
    • We need to either:
      • Render the DOMs before printing?
      • Or render all of them in canvas?
  • Appearance: Need a way to process appearances and apply them to the DOMs.
  • How to handle user input values?
    • One way is not expose any JS API. If you need to listen for value change, just do $('.annotationLayer .widgetControl').on('change', changeHandler);
    • Or add some method on PDFPageView to read/write/listen values.

@xlc
Copy link
Contributor Author

xlc commented Jul 6, 2015

Can anyone point me out how to parse/evaluate "a sequence of valid page-content graphics or text state operators that define such properties as the field’s text size and color" ?
e.g. /TimesNewRomanPSMT 12 Tf 0 0 1 rg
It is the default appearance string of annotations. I can't find any way to use existing code to process it.

@timvandermeij
Copy link
Contributor

Let's keep things simple and avoid parsing appearance streams for now. The reason I say this is that this PR has a greater chance of being merged if it is smaller and therefore easier to review and test. We need to split the work here into several PRs and iterate on the issue. For instance, let this PR just be the basic AcroForms framework with basic fields, then a next PR for the other fields, and a next PR for annotation appearance streams. The latter is also affecting my work on the annotation layer, so we need to find out the best way to implement that according to the specification.

@xlc xlc force-pushed the forms branch 4 times, most recently from e588320 to 92bee91 Compare July 7, 2015 04:04
@xlc
Copy link
Contributor Author

xlc commented Jul 7, 2015

@timvandermeij Thanks for your suggestion. Can you review the changes?

@fbender
Copy link

fbender commented Nov 16, 2015

@xlc would you mind splitting up this PR into smaller ones?
@timvandermeij How far along have you come with the annotation layer? What changes have already been merged that obsolete (part of) this PR?

Also see kind-off tracking bug #1459

@xlc
Copy link
Contributor Author

xlc commented Nov 16, 2015

@fbender How should I splitting this? This PR only implements text fields. I have more controls implemented in my other branch which depends on this. I will PR it when this is merged in.

@timvandermeij
Copy link
Contributor

Fortunately most of my PR is already merged using smaller PRs (see #5218 (comment) for a complete explanation) and I hope to do the rest soon such that that PR is done. It should not block this PR too much, but we need to have more structure first before adding new annotation features (AcroForms from here, but also the video annotation PR). Part of my PR is the handling of flags in the base class such that subclasses do not need to implement that too (as I see some flag handling in this PR). I also feel that the elements processed here should be in a class that extends the Annotation base class as AcroForm elements are Widgets if I'm not mistaken. We should unify the handling of those somewhat better here.

@fbender
Copy link

fbender commented Nov 17, 2015

How should I splitting this?

See e.g. @timvandermeij's answer:

For instance, let this PR just be the basic AcroForms framework with basic fields, then a next PR for the other fields, and a next PR for annotation appearance streams.

This needs to be adapted to the new stuff implemented in #5218 first, of course. See e.g.

but we need to have more structure first before adding new annotation features […]. Part of my PR is the handling of flags in the base class such that subclasses do not need to implement that too […]. I also feel that the elements processed here should be in a class that extends the Annotation base class as AcroForm elements are Widgets if I'm not mistaken. We should unify the handling of those somewhat better here.

This somehow seems to contradict this statement:

It should not block this PR too much

@timvandermeij can you please clarify which changes you expect to be blocking this work? Would be nice if there are (merged or still unmerged) PRs (or implementation concepts/drafts) you can link to that will help @xlc in refactoring his code.

@timvandermeij
Copy link
Contributor

I meant to say that there are no real dependencies on #5218 for this PR, but that this PR does need a bit more structure and clean-up. Examples:

  • It needs to be rebased.
  • It needs unit tests.
  • The preference name should have "disable" in it instead of "enable" to be in line with all other preferences.
  • The function getInteractiveHtmlElement seems unnecessary as it is kind of duplicating logic in getHtmlElement.
  • We should split up the Widget annotation handling into text widgets and form widgets. They are all Widget annotations, but serve a very different purpose. We already have getHtmlElementForTextWidgetAnnotation for regular text widgets, but createTextWidgetAnnotation works on form widgets although the name does not imply that, which is very confusing to me.

I think the bottom line is that I'm not completely sure on what the best structure is. In the PDF specification, Adobe tends to label everything that does not belong to the other annotation types a Widget, but there are many kinds of Widgets (static text widgets, form widgets like buttons and fields, et cetera). I don't think intertwining them all in the code is a good idea: there has to be a clear distinction between form widgets and text widgets, for instance. Ideally every type of annotation, but also every subtype like FormWidgets or TextWidgets, are separate classes. Other ideas for a good structure are of course welcome.

@xlc
Copy link
Contributor Author

xlc commented Nov 20, 2015

AFAIK, Widget annotations are form widgets. There is no static text widget (there is text annotation and free text annotation). Text Field widget is the interactive form widget you can enter text. So I don't think we need distinction between form widgets and text widgets. (Are there any non-form widgets? I can't find form PDF32000 spec)

getHtmlElementForTextWidgetAnnotation is used to display non-interactive text widgets and
createTextWidgetAnnotation is used for interactive text widgets. Both functions works with same widget annotation type but just for different modes.

I can do rebase, refactor code, unit tests, rename preference without too much problem, but I agree we need a good structure first.
Currently in order to implement a new form widget (I have already implemented a few in different branch), I have to modify annotation.js to add a new class subclass from WidgetAnnotation, read whatever fields and parse them and store fields into data object and then modify annotation_helpers.js to implement the logic to render the widget with HTML. Ideally the data object should provide a way to expose all required fields so the logic about a particular widget is in a single place. More importantly, I don't want to modify core pdfjs code in order to implement a feature in viewer. So that other viewer implementations can implement new form widgets or new annotation types without modifying the core pdfs code. (I am basically asking for #5283)

@timvandermeij
Copy link
Contributor

@xlc I agree with you that we need to think more about how to structure this properly. Fixing up this PR should not be too hard, but it's the structure that is really important in order to extend this also to all other annotation types.

@@ -634,7 +635,7 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
if (!isValidUrl(url, false)) {
url = '';
}
// According to ISO 32000-1:2008, section 12.6.4.7,
// According to ISO 32000-1:2008, section 12.6.4.7,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is no longer necessary when you rebase the patch as it has been fixed already in another commit.

@timvandermeij
Copy link
Contributor

This PR needs a rebase now that your other PR landed.

if (!isMultiline && !('fontSize' in this.data)) {
// hack to guess font size base on content hight
// so it display fine on small text field
// this need to be removed when we can apply defaultAppearance
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this to // TODO: remove this when we can apply the default appearance.

@xlc xlc force-pushed the forms branch 2 times, most recently from dc20ff9 to 78cf950 Compare February 14, 2016 22:04
@xlc
Copy link
Contributor Author

xlc commented Feb 14, 2016

@timvandermeij Updated.

this.container.appendChild(content);
return this.container;
if (!isMultiline && !('fontSize' in this.data)) {
// hack to guess font size based on content hight
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: start with a capital H and change "hight" to "height"

@timvandermeij
Copy link
Contributor

This is looking much better than before. Could you address the other nit above and then squash the commits into one?

@Snuffleupagus
Copy link
Collaborator

Also, unless I'm overlooking something, isn't #6172 (comment) still unaddressed?

@timvandermeij
Copy link
Contributor

Good point, that one has to be addressed too.

@xlc xlc force-pushed the forms branch 2 times, most recently from 54e9f5d to b6c9c04 Compare February 15, 2016 22:07
@xlc
Copy link
Contributor Author

xlc commented Feb 15, 2016

What will be the best way to save the values? Should I create a FormFieldStorage class to store the values? Or add a field to other existing class?

include = false;
}
}
if (include) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xlc
Copy link
Contributor Author

xlc commented Feb 16, 2016

@Snuffleupagus @timvandermeij I have implemented a storage solution, what do you think?

@xlc
Copy link
Contributor Author

xlc commented Mar 10, 2016

@timvandermeij Can you have a look?

@fbender
Copy link

fbender commented May 20, 2016

@xlc The branch needs to be rebased. Care to do that and ping @Snuffleupagus again afterwards?

@timvandermeij
Copy link
Contributor

timvandermeij commented Sep 17, 2016

Closing as superseded by a series of merged PRs that implemented this functionality. The remaining tasks (printing, storage and appearances) are tracked in #7613.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants