psy.js library

This Javascript library provides functions useful for developing psychometric measures, such as questionnaires and cognitive tasks. It is freely available under open-source licences (mostly the MIT licence, but see files for details).

Some documentation is provided within the library itself, and also in the changelog below. Usage for several functions is demonstrated in the samples here: https://www.forepsyte.com/studies/samples

Latest:
v.1.6
Previous versions:
v.1.59
v.1.58
v.1.57
v.1.563
v.1.562
v.1.561
v.1.56
v.1.55
v.1.54
v.1.53
v.1.52
v.1.51
v.1.5
v.1.41
Useful open-source third-party libraries (referenced in psy.js or elsewhere):
Barrett.js
BigInt.js
gibberish-aes.js
RSA.js
shortcut.js

Version history

v.1.6
- bindTechDetails() upgraded: now saves userAgent in addition to other variables, and creates the necessary hidden <input> elements in forms["submissionForm"], if missing, to store the data.
- removed Array.prototype.indexOf shim (dropping support for Internet Explorer 6-8).
- removed getElementsByClassName() shim (dropping support for Internet Explorer 6-10). Other functions updated to use document.getElementsByClassName() instead.
- removed submitEncrypted(). It only works in the context of the PSY framework backend anyway, so has been separated to its own library.
v.1.59
- cache() upgraded: it now takes a list of objects, rather than just URLs to resources, and supports caching multiple file types (images, fonts and audio files). This is a breaking change: studies using previous psy.js versions must be updated for compatibility.
v.1.58
- new function: move(). Takes references (in formats compatible with the elementList() function) to an intended parent element, and to one or more child elements, and makes the latter children of the former. Other functions updated to use move() as appropriate.
- new function: removeAllInstances(). Removes all instances of a specified item from an array.
- cache() upgraded: it now allows (optionally) a timeout to be specified, and supports SVG-based progress bars.
v.1.57
- Tidied code and removed banner-style indentation. No substantive changes.
v.1.563
- enQuestion(), enQuestionNoValidation(), disQuestion() and disQuestionNoValidNoDelete() upgraded slightly: i) changes to text colour (black/grey denoting active/disabled, respectively) is now achieved by setting a 'black' or 'grey' class name and deleting the opposite one; ii) the opposing class name is searched for and removed for all childen of the container <div>, too.
- validate() upgraded: i) it now works with 'textarea' types (the same as for 'text' types); ii) if an element with the "REQUIRED" class has no 'name' attribute (typically indicating that it's a dropdown <option> element, as these have no individual 'name' separately from their <option> parent), it now takes the 'name' attribute value from the previous item with one (typically the <option>).
- disQuestion() upgraded: it now works with 'textarea' and 'hidden' types (the same as for 'text' types).
v.1.562
- disQuestion() upgraded slightly: i) a HIGHLIGHT_AST <span> is no longer required (although it must be the firstChild of the specified textId element if present at all); ii) better behaviour added for type='select-one' or type='select-multi' elements, resetting their selected value to their first-defined <option> (which is assumed to be the default, typically with an empty value).
v.1.561
- fixed syntax error in fadeReplace() causing incompatibility with any browser other than Firefox.
v.1.56
- new function: randInt(). Returns an integer in an inclusive range. May be called with both a lower and an upper bound, or only the upper (with the lower defaulting to zero).
- new function: fadeReplace(). Uses fade() to fade one or more stimuli down to 'off' (i.e., display='none'), then another one or more stimuli up to full opacity, with (optionally) a specified duration for these operations and a specified delay between them.
v.1.55
- consent() upgraded: it now takes a single integer argument, n, indicating the number of checkboxes which must be checked. These must have IDs "consent1", "consent2", ..."consentn".
v.1.54
- new function: enableSubmitBtns(). Enables (the default) or disables all the 'submit' buttons in a specified form.
- new function: cookiesEnabled(). Checks whether the browser is currently accepting cookies from this page, returning true (yes) or false (no).
- new function: briefingReady(). A sample script to run cookiesEnabled() (thus checking the availability of cookies, and effectively also javascript). If this check fails, it sets the innerHTML of a preset element to display a preset warning message and disables the submit buttons of a preset form (with enableSubmitBtns()); otherwise it executes an optional callback function (defaulting to a dummy function if omitted).
v.1.53
- new function: fade(). One or more stimuli may be set to fade between two specified opacity settings, over a specified duration, and optionally adding them to / removing them from the page altogether (i.e., setting display='block' or display='none') at the beginning or end of the fade effect.
- new function: elementList(). The system from display() for referencing stimuli is abstracted to this new function, and used also by fade().
v.1.52
- detectRefresh() upgraded: (i) specific checks may now be made for the cookie being set, or being clear, with distinct callback functions being executed in either case. (ii) the cookie name and value may now be set at runtime, if desired, rather than relying on the hard-coded defaults.
v1.51
- cache() upgraded: after each (brief) interval, the current percentage of loading progress is written to a globally-accessible variable, thus allowing progress indicators to be created.
v1.5

This version adds several functions useful for the presentation of cognitive tasks:

- cache(). Pre-caches a list of images, in order to prevent unpredictable delays to stimulusonset when timing accuracy os required. A callback function is executed when all images in the list are loaded.
- display(). Switches display of one or more stimuli (i.e., HTML elements) to 'on' (display='block') or 'off' (display='none'). Stimuli may be listed by DOM references, IDs or CSS classes, or any combination.
- show(). Simple convenience function; calls display() for specified stimuli and sets them to 'on'.
- hide(). Simple convenience function; calls display() for specified stimuli and sets them to 'off'.
- now(). Simple convenience function; returns the current time in (Unix epoch) milliseconds.
- trap(). Sets or removes a window.onbeforeunload warning, to display a 'confirm/cancel' message to the participant (i.e., user) if they attempt to leave, close or refresh the page.
- detectRefresh(). Uses a session cookie to detect whether the current page has been refreshed, and executes a callback function if so.
- saveTrial(). Records data from a single trial (e.g., of a cognitive test) into a Javascript object.
- collateData(). Takes data from a Javascript object, as prepared with saveTrial() across multiple trials, processes it into delimited strings, and creates and populates new hidden <input> elements in a specified form to allow the data to be submitted to the server.
v1.41

This is the first version of the psy.js library to be separated from the PSY framework and released under the MIT licence (except for third-party code used under its own open-source licences, where appropriate).

The following third-party code is collected together for convenience (see each function/snippet's own documentation for details):

- For older browsers, the built-in Array prototype is extended to include the indexOf() method.
- getElementsByClassName(). Returns an array of elements matching a specified class.
- noEnter(). Prevents enter/return keypresses (useful to override automatic form submissions).
- fisherYates(). Randomises arrays.
- browserDetect(). Detects the user's browser, version, OS and language.

In addition, the following functions are provided, mostly intended for HTML form manipulation and validation for questionnaires:

- bindTechDetails(). Inserts the browser/platform details from browserDetect(), as well as screen width and height, into HTML <input> element values.
- validate(). Validates forms, checking whether all <inputs> with the "REQUIRED" class have values. If missing values are found, the colour of containing <div> elements with "HIGHLIGHT" class is changed, optionally an asterisk is inserted into a <span> element with "HIGHLIGHT_AST" class, and a warning message is inserted into an element with id "validationwarning" and the browser's location focused on this warning. Returns true (all required form elements have been completed) or false (one or more is still missing).
- submitEncrypted(). Provides a weak SSL substitute to provide some minimal data security, or at least obfuscation, to websites without true SSL/TLS. Form data are AES-encrypted with a randomly-generated key, and this key is encrypted with a public RSA key. The encrypted data and key are inserted into HTML form elements and submitted to the server, which decrypts the AES key with its private RSA key, then decrypts the data. This approach is vulnerable to man-in-the-middle attacks and others, so cannot provide strong security.
- switchTab(). Sets one element to display="none", then another to display="block" after an optional delay. Useful (for example) to control apparent multi-page forms, etc., within a single HTML page.
- moveValidWarnTo(). Moves the "validationwarning" element expected by validate() from one parent element to another. Useful with switchTab() for individually-validated multi-page forms.
- enableButton(). Clears the 'disabled' property of an HTML button. [removed in subsequent versions]
- getRadioValue(). Takes an HTML radio element nodelist and returns the value of the currently-checked element.
- enQuestion(). Enables a questionnaire question and its corresponding <input> element(s). The 'disabled' property of one or more <input> elements is cleared, the "REQUIRED" class is added to them for use with validate(), and the font colour of a corresponding text element is set to black. Useful for allowing optional/alternative/branched questions to be used within a questionnaire.
- enQuestionNoValidation(). Like enQuestion(), but without the "REQUIRED" classes, so the question remains optional.
- disQuestion(). Opposite of enQuestion(): the question text element is set to grey, and the corresponding <input> elements are disabled and have their "REQUIRED" classes removed. <input> elements with type="text" have their values deleted.
- disQuestionNoValidNoDelete(). Like disQuestion(), but without clearing values or affecting validation.
- consent(). A very simple consent-form validation script with hard-coded behaviour: three checkboxes (typically accompanying statements about understanding the purpose of data collection, etc.) are required to be checked before an HTML button (typically a form submission button) is enabled.