5 Appendix

The sections below are intended to provide a quick reference for JavaScript functions, best practices, or useful guidelines you need to keep in mind when building forms. Please consider contributing your own JavaScript functions, or other helpful additions to this appendix. It will be updated regularly as new items are submitted.

5.1 JavaScript functions

You can copy and paste any of the functions below directly into the JavaScript panel of your parent form. To access the JavaScript panel click on the curly braces icon {} in the top right corner of the Forms page when using the online Form Builder application.

5.1.1 Unique ID (UUID)

From Stackoverflow.

function generateUUID () { // Public Domain/MIT
    var d = new Date().getTime();
    if (typeof performance !== 'undefined' && typeof performance.now === 'function'){
        d += performance.now(); //use high-precision timer if available
    }
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = (d + Math.random() * 16) % 16 | 0;
        d = Math.floor(d / 16);
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
}

5.1.2 Statistical week.

For WDFW the standard statistical week starts on Monday and ends on Sunday. The first day of the year is always in week 1. This function generates the statistical week from a date value. To use in a mobile form create a new text input element below your survey_start_datetime data element. Then in the Dynamic Value box of the new input enter: survey_start_datetime.fishStatWeek().

Date.prototype.fishStatWeek = function () {
  var jan_one = new Date(this.getFullYear(), 0, 1);
  var week_day = jan_one.getDay();
  var adj_day = -1;
  if (week_day === 0) adj_day = 0;
  var n_days = ((this - jan_one) / 86400000) + 1;
  return Math.ceil((n_days + week_day - 1) / 7) + adj_day + 1;
};

5.1.3 Pad a number

Pad a number with three leading zeros. For example, change 01 to 0001, or 2 to 0002. Thanks to Jake Shapely for this function.

function pad(num) {
    var s = num + "";
    while (s.length < 3) s = "0" + s;
    return s;
};

5.1.4 Contains() method

This code uses the array property prototype to add a new contains() method for JavaScript arrays. It returns a value of true if the desired array element exists in the array. For example, if the array consists of: [“Chinook”, “Coho”, “Chum”, “Sockeye”, “Cutthroat”, “Steelhead”] and species is “Coho” then the statement:

["Chinook", "Coho", "Chum", "Sockeye", "Cutthroat", "Steelhead"].contains(species)

will return true. If the species is not listed in the array the function will return false.

Array.prototype.contains = function(element){
    return this.indexOf(element) > -1;
};

5.2 Character limits

The iFormBuilder platform imposes limits on the number of characters that are allow for naming or defining various items. The following table was compiled from disparate parts of the iFormBuilder website by Steve VanderPloeg.

IForm character limits:

  • Form Name Label: 500
  • Form Name: 50
  • Field Name Label: 1000
  • Field Name: 65
  • Conditional Values: 500
  • Dynamic Values: 500
  • Dynamic Labels: 500
  • Client Validation: 500
  • Validation Labels: 500
  • Data column name: 65
  • Text-area widget: 65,000

5.3 Maximum inputs per form

The iFormBuilder website recommends limiting the number of inputs in a form or subform to 100. If your needs exceed 100 inputs for any given form, they recommend breaking up those forms into one or more subforms. As mobile devices have become more powerful those recommended limits have increased from 35-40 inputs to the most recent recommendation of 100 inputs (as of 2016).

This is only a guideline, and given the increasing power of newer devices, these recommendations may already be out of date. The highly opinionated counter-recommendation in this manual is to try and keep your forms as simple as possible by minimizing the number of subforms whenever possible. Then test thoroughly to ensure your forms stay responsive. Instead of setting an arbitary limit on the number of inputs per form, a better policy is to carefully test for performance issues. Depending on the type of inputs, you may be able to exceed the 100 input recommendation by a considerable margin. Only break up forms into subforms if performance starts to deteriorate markedly.

To streamline data entry you should instead be vigilant in hiding inputs whenever possible. A few judiciously placed questions in tandem with condition statements can often serve to hide all but the few relevant inputs needed for any given observation. For field use, speed of data entry is often the most important consideration. Switching between subforms slows down the process. Ideally you would have just one parent form for header data and one primary subform for the majority of your repeat observations.