Quantcast
Channel: Orbeon Forms Blog
Viewing all 231 articles
Browse latest View live

Autosave

$
0
0
Glitches happen. While you're filing a form, your browser might crash, your computer be disconnected from the power or run out of power, your Internet connection might go down, or the server might have a technical issue. When such a glitch happens, you're likely to loose whatever work you've done since you last saved. Hence was born the Save early, Save often mantra. But why would you have to do what software can automatically do for you?

In Orbeon Forms 4.3, we introduced the autosave feature. When autosave is enabled, as the name implies, your work is automatically saved in the background as you interact with the form. Since we want to keep the distinction between data you explicitly saved and data that was autosaved, we refer to the latter as drafts. You can access drafts from the summary page, on which they are clearly marked as such. Also, if you go back to a form, and you have a draft for that form, you'll also be asked whether you'd like to continue your work from that draft.

In Orbeon Forms 4.3, autosave is available for MySQL and DB2, and needs to be enabled through properties. In the upcoming Orbeon Forms 4.4, this feature will be available and enabled by default for all relational databases supported by Orbeon Forms.

CoffeeScript: Create objects referencing other properties

$
0
0

In CoffeeScript, you can easily create an object and set the value of some of its properties:

    section =
        title: 'My section'
        element: $('.my-section')
        width: $('.my-section').width()

The width property is used to cache the width of the body. But the way it is defined isn't ideal as $('body') is duplicated. This can be a concern in terms of performance and DRYness. Instead, you could write:

    body = {}
    body.label = 'Document body'
    body.element = $('body')
    body.width = body.element.width()

I find the lack of indentation makes this code less clear. Also body. needs to be repeated on every line. Using the do keyword, you can introduce an indentation, which makes the code clearer, but this doesn't solve the lack of DRYness:

    body = {}; do ->
        body.label = 'Document body'
        body.element = $('body')
        body.width = body.element.width()

Can JavaScript's new operator solve all our problem? Let's try:

    body = new ->
        @title = 'Document body'
        @element = $('body')
        @width = @element.width()

This look like the perfect solution… unless the last property returns an object, in which case body will be equal to that object. For instance, in the following case, body will point to the document (the body's parent), which, obviously, isn't what we want. This is a result of CoffeeScript functions returning the value of the last expression, and the way new works in JavaScript when new is invoked on a function that returns an object.

    # Doesn't work, as body will point to the document
    body = new ->
        @title = 'Document body'
        @element = $('body')
        @width = @element.width()
        @parent = @element.parent()

Until CoffeeScript adds some syntactic sugar not to return the value of the last expression, you can get around this by explicitly adding a return at the end of the function if the last property is an object or in all cases, if you prefer to avoid a possible mistake:

    body = new ->
        @title = 'Document body'
        @element = $('body')
        @width = @element.width()
        @parent = @element.parent()
        return

With the return, I find this code looses some of its elegance, as its looks more like a sequence of statements than the definition of a data structure. Also, this is error prone, as leaving out the return will work in some cases and not others. Alternatively, you can use an anonymous class, and define the function as its constructor:

    body = new class
        constructor: ->
            @title = 'Document body'
            @element = $('body')
            @width = @element.width()

This makes the code somewhat heavier, harder to understand, especially if you're not declaring many classes in your code. My favorite solution leverages Underscore's _.tap. That function is in general used when chaining operations, but is at its core very simple: it applies the function passed as its second argument to the object passed as first argument, and returns the first argument. Using it we can write:

    body = _.tap {}, (o) ->
        o.title = 'Document body'
        o.element = $('body')
        o.width = o.element.width()

Now, that is a solution I can use.

More dynamic control bindings in Form Builder

$
0
0
Recently, a user asked us why, in Form Builder, there is a separate Number control in the toolbox. Is this the same as an Input Field set it to a Decimal datatype?

Our answer was, unfortunately: "Not really!". When you add a Number control, you are in fact adding an fr:number XBL component, which is able to format numbers back and forth with customizable decimal and grouping separators, and to top it off supports a prefix and suffix. In short, it has more features than just a plain input field, and it is part of a set of so-called typed controls.

Form Builder Typed Controls
Obviously, that situation is not ideal, as there are two incompatible ways of inserting a number field in From Builder!

For the longest time we have wanted to have fully dynamic XBL bindings, depending on datatypes. This is a task that we haven't yet completed.

But it occurred to us that we could already go one step in the right direction, by providing this functionality at the Form Builder level. And this is possible because Form Builder knows about datatypes at design time.

So that's just we have done and now from a user's perspective the Number control in the toolbox is just a shortcut for inserting an Input Field with Decimal datatype, as you would have expected.

What's even better is that we now have a general underlying mechanism to support this type of mappings. At the low level, we simply say that the XBL fr:number component must be used when we actually have a plain fr:number element in the form, or an xf:input bound to a decimal datatype. We express this with a CSS selector:
<xbl:binding element="fr|number, xf|input:xxf-type('xs:decimal')">
(We implemented a full CSS 3 selector parser along the way!)

This change will be available in the upcoming Orbeon Forms 4.4.

Unification of the relational persistence layers

$
0
0
XForms by itself doesn't fully solve the question of how to persist data. It provides solid foundations that we can leverage to persist data, but intentionally doesn't answer questions such as "how is the data organized?" or "how is data saved, retrieved, or searched, this in an actual database, say Oracle?". From the start, we aimed at Form Builder and Form Runner to work as much as possible out-of-the-box, which meant that we had to answer those questions. We did this by:

  • Defining an API for persistence, which Form Builder and Form Runner use, so both form definitions and form data are saved through this API.
  • Providing built-in implementations of this API for some of the most popular databases.
On the implementation side, we started with the eXist XML database; it ships with Orbeon Forms, and enables you to have a solution that works out-of-the-box without any setup required. Then, we added implementations for two relational databases: Oracle and MySQL. Those two databases are almost opposites in terms of features: Oracle is very rich and provides tons of extensions, while MySQL is a much "simpler" database. This lead us to implement things quite differently on those two databases, so we went with two completely separate implementations, which didn't really share any code.

Then, with version 4.3, we added support for DB2, and continued having separate code for each database, but found this approach not to be sustainable. It was very much a maintenance problem as every fix, new feature, or performance improvement done in one version of the code had to be ported in two other versions. This meant that the 3 implementations were not fully in sync: for instance, in 4.3 some features were added and were only available in DB2 and MySQL, but not Oracle, while some performance improvements were available for Oracle but not DB2 and MySQL. Making any type of change felt like a huge task, let alone thinking of supporting more databases.

In the upcoming Orbeon Forms 4.4, we resolved this by creating a unified implementation, which works across relational databases. The difficulty was in finding ways of doing things that didn't rely on unique database features, but were efficient enough on all databases. There are still places in the code where we need to do something different depending on the database, but those are now the exception rather than the rule.

While having a unified implementation for relational databases doesn't provide any new user-facing feature, this will allow us to improve those implementation faster, and to add support for new relational databases (did I hear someone mention SQL Server and PostgreSQL?).

Supporting permissions in your persistence API implementation

$
0
0
Up to version 4.2, implementations of the persistence API didn't need to worry about permissions; permissions were entirely checked by the part of Form Runner that was calling the persistence API. This changed with version 4.3, which introduced owner-group/based permissions. Let's see what changed:
  1. Without this feature, i.e. up to version 4.2, you could determine whether a user can perform a certain operation just based on the user's roles, the operation (create, read, update, or delete), and the app/form names. For instance, we could know if Alice was authorized to read data for the License application form even before calling the persistence API.
  2. This changes with the owner/group-based permissions: it could be that Alice can read all the data for the License application form just based on her roles (maybe she's an admin, or in charge of processing applications); but if not, she might still be authorized to access some of the data for the License application form, for instance the data she created, or data created by other users in the same group, depending on how permissions were setup.
This second point means that some filtering needs to happen, based on who the user is. Say Alice accesses the License application form summary page, and the system was setup so she can only see and access her own applications. In that case, the summary page will maybe show the 5 applications she filled, amongst the maybe thousands stored in the databases. It would be unreasonable for the implementation of the persistence API to return all the applications, and count on the caller to do the filtering: as more data is entered into the system, this could become increasingly more inefficient. Hence, the job of checking permissions has been in part shifted to the implementation of the persistence API. Now:
  • The search API only returns documents the current user has access to, and for each document specifies which operations the user can perform, this through the operations attribute on the document element in the query response.
  • This same information is also returned when reading a document. In that case, since the the document is returned in the body, the list of operations is returned "out-of-band" through the Orbeon-Operations header.
To make it easier for implementations of the persistence API to deal with permissions, Orbeon Forms offers a few helper functions, provided as static methods that can be called from Java, implemented in FormRunnerPermissions.scala. All the static methods mentioned below are in the org.orbeon.oxf.fr.FormRunner class. 
  • If you're implementing search, you could use those operations as follows:
    1. First, you might want to ask: is Alice authorized to access all license applications just based on her roles? The static method javaAuthorizedOperationsBasedOnRoles() answers this question.
    2. If the answer is positive, then you can return all the data, just as you used to be done in 4.2 and earlier.
    3. However, if the answer is negative (there are no operations Alice can do on license application just based on her roles), then you'll want to filter out and return only the applications Alice directly created, or that were created by another in her group, depending on the configuration.
    4. Finally, when returning applications Alice has access to, you can find what operations she can perform on each document by calling javaAllAuthorizedOperations().
  • If you're implementing the read operation, as mentioned earlier, you're expected to return the operations the user has access to through the Orbeon-Operations header. If you wish, you can delegate this task to the setAllAuthorizedOperationsHeader() method, which will figure out the list of operations and set the header for you.

Adjusting a dropdown width on IE7 and IE8

$
0
0
At times, the width of a dropdown (aka combo box) is constrained, in the sense that it can't be made wide enough to completely show the text for the selected option. However, with all modern browsers, when you open the dropdown, the full values show, as illustrated on the following screenshot:

A dropdown with long labels on a modern browser
Unfortunately, IE up to version 8 (included) is cropping values even when the dropdown is opened, as shown below. Depending on the values you're showing in the dropdown and the width of your dropdown, this behavior may be just a minor inconvenience or could be fatal, in particular when two values in the dropdown differ only in the end of their text, which happens to be cropped.

On IE7/IE8, labels are cropped, which can be fatal to your web app 
A solution to this problem is to use JavaScript to increase the size of the dropdown when it is opened, setting its CSS width to auto; so it shows the full values:

JavaScript fix applied to IE7/IE8

Then, you set the width back to its original value when the dropdown is closed. This method works, until you hit a dropdown with a width: 100% for which labels are short, i.e. changing the width from 100% to auto makes the dropdown narrower instead of wider. If you're making the dropdown narrower and users click on a portion of the dropdown that isn't visible anymore after its width is adjusted, IE understandably "cancels" the user's click, and the dropdown doesn't open, which means the user will have to click a second time on the narrower dropdown to open it.

Your first instinct might be to fix this with a min-width: 100%. Unfortunately, bummer, min-width doesn't work on dropdowns with IE7/IE8. This means that we have to resort to another technique: use JavaScript to check if setting the width to auto would reduce the actual width of the dropdown, and in this case just leave things as they are. If this sounds somewhat convoluted, it is because it is! But I imagine that, at times, this is price we have to pay to properly support older browsers.

You can find the JavaScript for this, along with a test case, in this jsFiddle. At the moment, our thinking is that this is too much of a corner case for us to include this code by default in Orbeon Forms, but if this solves a problem for you, feel free to use it, with Orbeon Forms or elsewhere.

Orbeon Forms 4.4

$
0
0
Today we released Orbeon Forms 4.4!

This release includes the following new features and major enhancements:
  • Oracle support for autosave and owner/group-based permission. These two features were timidly introduced in 4.3 for MySQL and DB2 only, and required two properties to be set to be enabled. With 4.4, they are available on all the relational databases supported by Orbeon Forms (Oracle, MySQL, and DB2), and are enabled by default (doc for autosave, doc for owner/group-based permissions).
  • Publish to production. This feature allows you to configure access to a remote server and to publish, unpublish, and transfer forms between the local and remote server (doc).
  • Form Runner can use the current Liferay language. When enabled, the user's language set in Liferay is propagated to Form Runner and influences the Form Runner language. This is available for the Form Runner proxy portlet only (doc).
  • Form Runner can use Liferay user, group and roles. When enabled, the Form Runner proxy portlet propagates headers with user, group and roles information to Form Runner, which can then use that information for access control (doc).
  • Form Runner is more extensible. Form Runner now supports adding custom XForms model logic (doc), simple processes (doc) support sending custom events, and you can specify your own JavaScript code (doc). The combination of these features enables custom behaviors without changing Form Runner itself.
  • Memory improvements for compiled forms. We have worked on reducing the memory footprint of compiled form definitions. This is important for users with possibly hundreds of forms deployed. In a large form scenario, we have measured 20% less memory consumed (blog post).
But that's not all: there are over 80 closed issues since Orbeon Forms 4.3. For convenience, here is the list of the most relevant changes:
  • Form Builder
    • "Set Response Selection Control Items" only updates current language (#691)
    • Removing FB JAR causes FR Summary page not found (#1265)
    • Dynamic bindings by type (#1264)
    • Enter key in Control Settings must save and close (#1189)
    • Rename Grid Details to Grid Settings (#1163)
    • FB: Test mode crashes with wizard and inner buttons (#1313)
    • Tooltip for HTML checkbox is incorrectly placed (#1362)
    • XML Schema types is not set (#1372)
    • Grid in section template empty in review and at design time (#1370)
    • FB Summary page: title and description remain in English (#1376)
  • Form Runner
    • Way to run custom XForms when Form Runner button is pressed (#1040)
    • FR: Publish to production (#1055)
    • Red star isn't shown next to labels for required fields in repeat headers (#1176)
    • Image annotation image doesn't show in PDF (#1076)
    • Allow send properties to be AVTs (#1213)
    • Property to include custom content added to the fr-form-model (#1141) (doc)
    • fr-mode doesn't update form upon save (#1232)
    • Noscript doesn't honor oxf.xforms.format.input.date (#1154)
    • Conditionals in the simple process syntax (#1144)
    • Property to add custom JavaScript to Form Runner pages (#1262)
    • Paging not working on DB2 (#1263)
    • New page missing summary, PDF, and review buttons (#1269)
    • fr:section with open="false" is closed in PDF (#1287)
    • Ability to specify fr-language on PDF URL (#1290)
    • Readonly fr:grid first column is too narrow (#1296)
    • XML Schema service: NPE if section id ends with "-section" (#1297)
    • Edit page incorrectly showing 403 when users don't have update permissions and drafts exist (#1278)
    • Page allowing selection a drafts shows drafts we can't edit (#1279)
    • Autosave: prevent users editing a draft they only have read access to (#1277)
    • Oracle support for owner/group permissions and auto-save (#1237)
    • Regression: $fr-roles returns a single string (#1243)
    • Use Liferay language as requested Form Runner language (#1122)
    • Proxy portlet doesn't forward user/role information (#946)
    • Regression: Rich Text control output in PDF is incorrect (#1288)
    • Error Summary doesn't update when FR language changes (#1291)
    • Schema generator does not support attachment controls (#1336)
    • Document REST API changes if any (#1338)
    • Autosave is enabled by default but does not work with eXist when user logged in (#1333)
    • Add a property listing the active persistence API implementations (#1186)
    • fr:currency control doesn't update in repeat iteration (#1348)
    • Summary and Home page use shorter date formats (9fbe1deddb)
    • Summary page shows "23:44 pm" (#1355)
    • IE7: Created/Modified columns too narrow (#1356)
    • More links to FR Home page (#1196)
    • Schema generator to produce XForms namespace on root element (#1366)
    • Can't authorize XML Schema Generator Service (#1367)
    • eXist: Summary page lists form data for user with only "new" permission (#1381)
    • FR: Summary: Handle persistence without permissions support (#1384)
    • Home: "Select All" also selects rows w/o checkboxes (#1380)
    • FR Home: don't link if form is not available (#1389)
    • FR Home: no link if user can only create (#1388)
    • Wizard: click on error in error summary does not switch section (#1394)
    • Regression: Summary page shows "Search returned123of200documents." (#1401)
    • Regression: Import says validation import were canceled (#1398)
  • XForms engine
    • Add CSS class for LHHA appearances when present (#1203)
    • fr:tinymce not showing if in a Bootstrap tab (#1205)
    • Implement support for data: in xf:output mediatype="image/*" (#1065)
    • XForms LocationData takes a lot of memory (#1247)
    • XPath function to access basic image metadata (#1253)
    • JSESSIONID cookie not forwarded to service when xxf:username="" is specified (#1267)
    • A submission with echo: expires the session (#1268)
    • Upgrade to Bootstrap 2.3 (#1202)
    • fr:tinymce doesn't show in table if missing label/help (#1283)
    • Box select too wide on Firefox (#1293)
    • xforms-value-changed: context info for current value (#1295)
    • Incorrect repeat layout in Liferay (#984)
    • Don't proxy Set-Cookie header in response (#1188)
    • Readonly image attachment has upload file chooser (#1240)
    • Strip unneeded whitespace in XForms processing (#1252)
    • Non-relevant textarea can get the focus (#1387)
  • Other
    • Add a feature to delete documents stored by the scope serializer (#1251)
    • In logs, display whole exception message instead of truncating it (#626)
    • Upgrade to Scala 2.10.3 (#1064)
Compatibility notes:
  • If you're using Form Builder / Form Runner with Oracle or MySQL, you need to update your database tables; see the DDL for Oracle and the DDL for MySQL. These changes to the database were necessary to support autosave and owner/group-based permissions on Oracle and MySQL.
  • Form Builder is not supported on Safari 7 at this time (see #1399).
  • If you're implementing the REST API, you should now also support the following:
    • in CRUD requests, draft in path in addition to data, used by the autosave mechanism;
    • in search requests,
      • support the new drafts element in the search request;
      • for every document you return, specify the draft="true|false" attribute, used by the autosave mechanism.
    • both CRUD and search requests 
    You can download the latest version of Orbeon Forms from the downloads page.
      Don't forget to grab a trial license for the PE version.

      Please send feedback:
      We hope you enjoy this release!

      Saving memory by removing unneeded whitespace

      $
      0
      0
      Photo by Brad Montgomery

      Orbeon Forms stores form definitions and form data in XML format. When using XML, it is customary to use new lines and indentation to make it easier for humans to read and write. Notice for example the following bit of empty form data:

      <book>
          <details>
              <title/>
              <author/>
              <language/>
              <link/>
              <rating/>
              <publication-year/>
              <review/>
              <image
                  filename=""
                  mediatype=""
                  size=""/>
          </details>
          <notes>
              <note/>
          </notes>
      </book>
      

      New lines and indentation fall in the category of so-called whitespace. Whitespace consists in anything that looks “blank”, including actual space characters and line breaks.

      What we have noticed is that, especially for large forms, whitespace can take a significant amount of memory in compiled form definitions. So for Orbeon Forms 4.4, we looked into how we could improve that situation.

      The trick is to remove whitespace where it is not needed, because in some cases you do want to keep at least some of it. For example you can remove most indentation and new lines, but consider this HTML fragment:

      <p>This is a      <b>great</b>       moment.</p>
      

      Some space after “a” and before “moment” needs to be there, but in most cases that space could be collapsed or normalized to a single space (there are exceptions). But it would certainly be wrong to remove all the spaces.

      A different example is the HTML <pre> tag, within which all the whitespace should be preserved, including indentation and new lines.

      To address this, we implemented a configurable whitespace stripper [1] for form definitions, with the intent of removing as much whitespace as we can while keeping it where it is needed.

      The result is that for very large forms, it is possible to save over 20% memory for the compiled form definition compared with Orbeon Forms 4.3.1. One very large form definition had over 15 MB of waste due to whitespace!

      These savings are especially important if you have a large number of distinct form definitions.

      We still hope to improve on this in the future. For example it is probably possible to save memory within form data as well.


      1. If you are curious as to how it’s done, see Whitespace.scala, CharacterAccumulator.scala, and WhitespaceXMLReceiver.scala. The default configuration is done with CSS 3 selectors in properties-xforms.xml.  ↩


      Inserting and reordering grid rows

      $
      0
      0
      Grids are a key ingredient in Form Builder and Form Runner, as they are the main tool you use to layout controls on a page. And since Orbeon Forms 4 they are also repeatable, which means that you can repeat one or multiple row of the grid.

      We have just added some important missing features to repeated grids:
      • The ability to reorder grid rows.
      • The ability to specify exactly where to insert a new row.
      We thought quite a bit about how to best create the user interface. Drag and drop to reorder would be nice, but it is also hard to do right (we'll still consider adding this in the future). Cramming each row with 4 more icons didn't seem like a good idea. Icons showing upon hover would have been possible, but in the end we opted for a very simple solution: a menu, available on each row, which you explicitly open. Another benefit of the menu is that you also have more space to tell the user what the operations really do.

      The new grid menu
      We now have 5 operations:
      • Insert Above
      • Insert Below
      • Move Up
      • Move Down
      • Remove
      The "Remove" operation was already available in previous versions via an icon.

      Not all operations are available at all times. For example, you can't:
      • move rows beyond the top or bottom
      • insert or remove rows beyond the configured maximum or minimum if any
      • move and reorder "frozen" rows that can appear at the beginning of a grid
      • remove a row which has "remove constraint"
      We have left the "+" icon at the top of the grid, which inserts a new row below the currently selected row. We have improved on this a bit by very discretely highlighting the current row, and improved keyboard focus handling when inserting/moving rows.

      This feature will be available in Orbeon Forms 4.5.

      Preventing cross-site request forgery (CSRF)

      $
      0
      0
      Cross-site request forgery (CSRF) is a type of exploit of your web site whereby a malicious party may be able to perform operations posing as a given user of your site, without that user having authorized those operations, or even being aware they are performed.

      You can protect your web application against CSRF attacks by generating for each user connecting to the site a random token, and requiring that token to be sent along every request. Software packages, such as Spring Security or OWASP CSRFGuard, can make it easier for you to do this in your own web application.

      Orbeon Forms does everything required to prevent CSRF attacks, out-of-the-box, so this is one less thing you'll need to worry about.

      Detecting login pages in Ajax requests

      $
      0
      0
      Way back when, in Orbeon Forms 3.9, we introduced an improved retry mechanism that kicks in when an Ajax request to the server fails. A request might fail either because the browser didn't get a response before a certain timeout, or because it got an unexpected response. In the first case, it is always worth retrying: if we were not able to contact the server now, there is a chance we might be able to do so in the future. However, an unexpected response might be the sign of a fatal error, and in that case we're only wasting the user's time in attempting to send again the request to the server.

      When getting an unexpected response, since version 3.9, Orbeon Forms' client-side code is looking at the content of the response to see if it recognized it as an error produced by Orbeon Forms' server-side code. In that case, it doesn't retry, estimating that the error was likely to happen again. Otherwise, it tries again to send the request to the server. But is always retrying when we can an unexpected response which isn't Orbeon error the wisest choice? Let's see what those pages could be:

      1. A user starts filling out a form at home, then walks downstairs to a coffee shop, orders her latte, and connects to the Wi-Fi to finish filling out the form, at which point she gets a page with a checkbox asking her to accept usage guideline for the Wi-Fi, which she does. If Orbeon Forms issues an Ajax request before she accepts the conditions, it will get that same page. Obviously, in this situation we'd like Orbeon Forms to retry the request.
      2. A user starts filling out a form, closes his laptop, drives home, and opens his laptop to continue his work. Unfortunately, in the meantime his session expired, and Ajax requests are served a login page. Obviously, in this situation retrying won't help, and we would be better off notifying the user that he needs to login again.
      How can Orbeon Forms distinguish between the first and the second case? In both cases, pages look like login pages, and are foreign to Orbeon Forms, which means it can't reliably make the difference, at least not without some help.

      This is why, in Orbeon Forms 4.5 we're introducing a way for admins to tell Orbeon Forms which pages fall in the second category, and are company login pages. Admins do this by setting the oxf.xforms.login-page-detection-regexp property to a regexp that Orbeon Forms runs agains the page returned. If the page is a match, it considers it is a login page, notifies the user (as shown below), and reloads the form, which in turn will likely take the user to the login page.


      For more on this property, see the documentation on the login page detection.

      Repeated sections

      $
      0
      0
      In addition to repeated grid rows, Form Builder and Form Runner now support repeated section content.

      Repeating section content is very similar to repeating a group of grid rows, except that the entire section content can be repeated. This includes nested grids and subsections.

      You enable content repetition in the Section Settings dialog for the section. Like for repeated grid settings, you can select the minimum and maximum number of repetitions. In addition, you can opt to configure a custom iteration name, which only impact the format of the data. In general, you shouldn't need to change this setting.

      Repeated Section Content Settings

      At design time as well as design time, a section with repeated content appears with an arrow button next to each iteration, which allows you to insert, move, and delete iterations.

      Repeated Section at Runtime
      We hope you enjoy this new feature, which will be available in Orbeon Forms 4.5!

      Related posts:

      Orbeon Forms 4.4.1 PE

      $
      0
      0
      Today we released Orbeon Forms 4.4.1 PE. This is a bug-fix update for Orbeon Forms PE only. For more details about the 4.4 release in general, see Orbeon Forms 4.4.

      This release includes the following fixes:
      • Orbeon Forms 4.4 requires additional jars for Oracle (#1484)
      • IE10: section content is partially hidden after collapsing it and uncollapsing it (#1464)
      • IE11: JavaScript error after entering app/form name in Form Builder when creating form (#1461)
      • Safari 7 is supported with Apple's Safari 7.0.1 update (see #1399).
      You can download the latest version of Orbeon Forms from the downloads page.
        Don't forget to grab a trial license for the PE version.

        Please send feedback:
        We hope you enjoy this release!

        Improving how we show help messages

        $
        0
        0
        Before Orbeon Forms 4.5, we've been using modal dialogs to show help messages. This was a rather heavy handed approach which prevented users from filling out the field while seeing the help message. Now, help messages show using a Bootstrap popover shown next to the relevant field, as shown in the screenshot below. Also, in addition to allowing users to interact with the form as they read the help message, the help message gets a fresher, more modern look, thanks to Bootstrap.

        In the vast majority of the cases both the form field and the popover will be visible at the same time. This means that if the field is on the right side of the form, the popover will show on the left; this is the opposite of what is shown in the screenshot above. In cases where the field takes the whole width of the form, the popover will show over or under the field, depending on where there is more space. Finally, only in cases where the field is taking all the real estate available on the screen (imagine a large rich text editor), will the popover show over the field.

        This feature will be available in Orbeon Forms 4.5.

        The new Duplicate button

        $
        0
        0

        We have just implemented a new Duplicate button, available on the Summary page of both Form Builder and Form Runner.

        This button allows you to copy:

        • an existing form definition, when used from Form Builder
        • existing form data, when used from deployed forms

        This enables some often-requested use cases, including:

        • Creating a template form definition and copying that template to create new forms.
        • Taking a piece of data which applies to, say, a given month of the year, and making a copy of it for the following month.

        When a form definition or form data is duplicated, all the related attachments, if any, are copied as well. You can select multiple items, and all of them will be duplicated.

        The new Duplicate button shown on the Form Builder Summary page
        The new Duplicate button shown on the Form Builder Summary page

        By default, the Duplicate button is enabled in both Form Builder and Form Runner. You can control this with the oxf.fr.summary.buttons property:

        <property
          as="xs:string"
          name="oxf.fr.summary.buttons.*.*"
          value="home review pdf delete duplicate new"/>
        

        This feature will be available in Orbeon Forms 4.5.


        Hints for checkboxes and radio buttons

        $
        0
        0
        With Form Builder, form authors can provide a help message for every form field, and we recently discussed how we improved the visual appearance of help messages. For radio buttons and checkboxes, it sometimes make sense to have a message targeting a specific radio button or checkbox, as done in this fictional example:


        You can now enter such a message through the dialog Form Builder already uses to provide the label and values for each checkbox or radio button. To that effect, the dialog now includes a third column Hint, as you can see in the screenshot below. Just like for the labels, you can use HTML in the hint if you check the corresponding checkbox at the top of the dialog.


        This feature will be available in Orbeon Forms 4.5.

        Form versioning

        $
        0
        0

        What versioning does

        Form versioning is an important new feature in Orbeon Forms 4.5. In the past, Orbeon Forms was only keeping track of one form definition for every published form. This meant that if you republished a form, the previous form definition was overwritten. It also meant that when showing data, Orbeon Forms was always using the latest published version of the form definition. However, there were cases where this could lead to unexpected results, as fields might have been added or removed in the new form definition, which means that some values could either not be shown, or would be missing when using a newer version of the form definition.

        Starting with Orbeon Forms 4.5, publishing a form definition doesn't overwrite any previously published one, but creates a new version. Also, Orbeon Forms now keeps track of the version of the form definition that was used when creating data, so it can use the same version in the future when that piece of data is edited, viewed, printed, etc.

        This feature will be available in Orbeon Forms 4.5, and can be used with all the supported relational databases (Oracle, MySQL, and DB2). At this point, it isn't supported with the eXist database. For relational databases it uses columns that were already added in version 4.4, but were still unused at the time; so if you are upgrading from 4.4, the changes to the schema are relatively minor: there are none on DB2, and only minor changes for Oracle and MySQL.

        Data migration

        The idea of data migration is to automatically update data created with an older version of the form definition to match the format of a newer form definition. It's obviously not something that you always want to happen, but there are cases when migrating data makes sense. For now, Orbeon Forms 4.5 doesn't do any data migration: editing, viewing, printing, etc of saved data is always done using the same version of the form definition used when that data was initially created. However we do have ideas on how to migrate data, for the cases where this would be desirable, and it might be something future versions of Orbeon Forms might do.

        The summary page

        The summary page for a form only uses the latest version of the form definition. In particular, this means that there will be additional columns in the table only for fields you marked as show in summary in the last version of the form definition. (Similarly, the summary page will show search fields only for fields marked as show in search in the last version.) In some case, this behavior isn't optimal, as you might have fields marked as show in summary in the last version that didn't exist in earlier versions, and vice versa, fields that were marked as show in summary in earlier versions and that aren't in the last version. A row in the summary page for data created with such an older version will show an empty cell in the corresponding column in the former case, and no data, since there is no corresponding column, in the latter case. This is something that we're planning to improve.

        Fun with dropdown menu titles

        $
        0
        0

        As we were recently fixing a few issues with the Dropdown Menu control, we started thinking more seriously about the behavior of that control in Form Builder and Form Runner, and it turned out to be interesting!

        The questions revolve around the special item at the top of the list, which we call the dropdown title. It is present to encourage the user to make a selection. With Orbeon Forms 4.4 and earlier, we simply had a rather imperative “[Select…]” title.

        So what title should we show, and when? There are different possibilities. For example:

        • When the control value is optional, we could show a different title, because in that case we shouldn’t tell the user too imperatively to enter data.
        • We could leave a blank title in both required and optional cases.

        For now we have decided to show a message in both cases, as a little bit of additional hinting shouldn’t hurt. And to be polite, we say “please”:

        Encourage the user a bit
        Encourage the user a bit

        Here is how the dropdowns look when you open them:

        Required value
        Required value
        Optional value
        Optional value

        Now when a value is required and a choice is selected, you can argue that there is no point showing “Please select:” to the user anymore, as the user shouldn’t go back to a point where no value is selected. Here we could:

        • entirely remove the title
        • show a blank title

        What if you have selected a choice by mistake, and you want to go back to an empty choice to remember to make a selection at a later time? This argues in favor of leaving a blank title. But if an initial choice is provided, either by default or by loading values from a service, you probably shouldn’t be able to get to a situation where no choice is selected!

        So it’s subtle and there might not be a “one size fits all” solution. For now, we have elected to blank the title when a value is selected even in the required case:

        Blank title for required value
        Blank title for required value

        Of course, when the selection is optional, then it makes sense to have a blank title to deselect the choice.

        Allow deselection
        Allow deselection

        In addition, we have now internationalized the title, something we had apparently overlooked for a long time (of course, Form Builder has allowed you to internationalize choices since the beginning).

        Localization
        Localization

        We noticed that in review and PDF modes, we showed the good old “[Select…]” title in the absence of a selection, which was not very useful! It is better to show an empty field, which also allows users who print forms on paper to fill in a value:

        Filled optional value in review
        Filled optional value in review
        Empty optional value in review
        Empty optional value in review

        Finally, instead of being hardcoded this is now entirely implemented in a simple XBL component which is quite easy to adapt.

        These improvements will be available in Orbeon Forms 4.5.

        Choices editor improvements

        $
        0
        0

        Orbeon Forms 4.5 introduces two features related to repeated content, discussed in other posts:

        Work on these enhancements also benefits the Form Builder Choices editor [1], and you can now reorder choices and have control over where to insert new ones:

        Reordering choices
        Reordering choices

        In addition, you can now easily switch between the form’s languages directly in the Choices editor, instead of having to close it, switch languages, and come back. This makes localization easier! [2]

        These enhancements will be available in Orbeon Forms 4.5.


        1. Which allows you to edit the choices for dropdown menus, radio buttons, checkboxes, and other selection controls.  ↩

        2. This feature was available in Orbeon Forms 3.9 but had gotten lost on the way to 4.0!  ↩

        Storing configurations outside of the Orbeon Forms war file

        $
        0
        0

        Rationale

        If you're reading this, you're most likely already familiar with the properties-local.xml file used to configure Orbeon Forms. This file typically goes inside the Orbeon Forms web app, in WEB-INF/resources/config. What if you'd like to package a single war for Orbeon Forms, and deploy that war on multiple servers on which you need to have slightly different configurations? Is it possible to store this configuration outside of the war file? It is, and we'll see how you can do this in the remainder of this post.

        Resource managers

        The directory WEB-INF/resources, as its name implies, contains files called resources. Resources can be configuration files, XSLT stylesheets, or CSS/JavaScript assets served to the browser. Resources can be stored in a variety of locations, hence Orbeon Forms loading them through a resource manager. Several resource managers come out-of-the-box with Orbeon Forms, and you could even implement your own. The 3 most frequently used resource managers are:

        • The class loader resource manager loads files from the class path. Most of the built-in resources are stored in jar files that ship with Orbeon Forms, and are thus loaded with the ClassLoader resource manager.
        • The web app resource manager typically loads files from the web app's WEB-INF/resources.
        • The file system resource manager loads files from a directory on disk you specify.

        Changing the web.xml

        By default, Orbeon Forms first attempts to load resources with the class loader resource manager, and if that fails tries with the web app resource manager. But you can change this by adding context params in the Orbeon Forms web.xml. For instance, with the following two context params added, Orbeon Forms will first try to load resources from /etc/orbeon:

        <context-param>
          <param-name>oxf.resources.priority.0</param-name>
          <param-value>
            org.orbeon.oxf.resources.FilesystemResourceManagerFactory
          </param-value>
        </context-param>
        <context-param>
          <param-name>
            oxf.resources.priority.0.oxf.resources.filesystem.sandbox-directory
          </param-name>
          <param-value>/etc/orbeon</param-value>
        </context-param>
        

        With this single change to the Orbeon Forms war, and the choice of a "standard" directory in which you'll place your configuration files, say /etc/orbeon, you can deploy the same war on multiple servers, and have different configurations in the /etc/orbeon of each server.

        Changing Tomcat's configuration

        Tomcat allows you to set the value of context parameters for an app in its own configuration, so you don't even have to change the web.xml. The following two lines added inside your Tomcat's <Context> element for the Orbeon Forms web app (e.g. in your server.xml) are equivalent to the change we did earlier to the web.xml.

        <Parameter
         override="false"
         name="oxf.resources.priority.0"
         value="org.orbeon.oxf.resources.FilesystemResourceManagerFactory"/>
        <Parameter
         override="false" 
         name="oxf.resources.priority.0.oxf.resources.filesystem.sandbox-directory"
         value="/etc/orbeon"/>
        
        Viewing all 231 articles
        Browse latest View live