Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Published by Scroll Versions from space TDDM and version 1

Overview

As with our use of HTML, rendered markup needs to serve more than one purpose, and we do this using Javascript logic. The Javascript language has evolved over the years with more features and conveniences being made available at a very fast pace. In order to make use of these language enhancements while also respecting browser compatibility, we manipulate our Javascript by running it through the Babel transpiler for target legacy browsers, and adding specific language feature polyfills where they make a difference to the developer experience of creating composable components.

...

They are well commented so the best place to get the full details is in the code, but here is an overview of the major ones:

  • tui/util - array : Array helpers like groupBy(), object helpers like structuralDeepClone(), and function helpers like memoize() and debounce(). totaraUrl(), which generates a URL to a page on Totara, can also be imported from here.
  • tui/config - general : General page configuration info like the web root, session key, and current theme.
  • tui/notifications - show : Show a notification toast message for a successful action.
  • tui/theme - functions : Functions for interacting with the theme, e.g. getting CSS variable values.
  • tui/errors - error : Error display code.
  • tui/accessibility - accessibility : Accessibility helpers.
  • tui/pending - signal : Signal to behat that we are waiting for something.
  • tui/dom/focus - control : Control focus.
  • tui/dom/position - get : Get the position of elements on the page.
  • tui/dom/transitions - wait : Wait for a transition.

Asynchronous code

In general, the recommended way to write async code is using the ES6 async/await feature. You can also use Promises, which async/await use under the hood.

Use The use of callbacks for asynchronous functionality is strongly discouraged in favor favour of async/await and Promises as it makes for much more maintainable code.

...

Data loading in components is done over GraphQL. You can use the tui/components/loader/Loader component to display a loading spinner while content is loading.

It's recommended to base the rendering state off on whether the query result is populated yet rather than $apollo.loading, as $apollo.loading will will be false if an error occurs, and will be true again if the query refetches re-fetches for any reason. However, you can combine this with checking $apollo.loading in in the condition too , so that the loader doesn't stay visible if the query fails.

...

We use Babel to compile modern (ES6 and later) JavaScript syntax to ES5 in a separate bundle that is served to IE 11 only. This only covers syntax and language features, so it's important to check the browser support for any JS APIs you use to make sure they are available in IE 11 (the supported browsers or polyfilled ), and are available in Edge Legacy(for IE11).

ImplementedofoffindfindCustomjiraArray.findIndexJavaScriptReference/Global_Objects/Array/findIndexhttps://JavaScriptReference/Global_Objects/Array/includesCustomEvent/CustomEventAPI/Element/closestElement.matchesElementmatchesElement.remove/API/ChildNode/removeFetch APIAPIFetch_APIgithubcom/github/fetchNumber.isFiniteisFinitePromise/Promisegithub.com/stefanpenner/es6-promiseString.startsWithStringstartsWithString.endsWith/String/endsWithString/includesNodeList.forEach/API/NodeList/forEachString.fromCodePointfromCodePoint
PolyfillFunctional overviewPolyfillImplementationAvailable since Totara version

Array.

find

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/On overview pageNofindcore-js13
Array.copyWithinfindIndexhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithinOn overview pageNofindIndexcore-js13
Array.fillfromhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fillOn overview pageNofromcore-js14
Array.includeshttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includescore-js13
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527
CustomEventhttps://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEventOn MDN overview page12
Element.closesthttps://developer.mozilla.org/en-US/docs/Web/API/On overview page

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

Array.includesElement/closestOn MDN overview page12
Element.matcheshttps://developer.mozilla.org/en-US/docs/Web/API/Element/matchesOn MDN overview page12
Element.removehttps://developer.mozilla.org/en-US/docs/Web/API/ChildNode/removeOn MDN overview page

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

CustomEvent12
Fetch APIhttps://developer.mozilla.org/en-US/docs/Web/API/On overview page

Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-16912

Element.closestFetch_APIhttps://github.com/github/fetch12
Maphttps://developer.mozilla.org/en-US/docs/Web/On overview page

Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-16912

JavaScript/Reference/Global_Objects/Mapcore-js14
NodeList.forEachhttps://developer.mozilla.org/en-US/docs/Web/API/NodeList/On overview page

Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-16912

forEachcore-js13
Number.isFinitehttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinitecore-js13
Number.isIntegerhttps://developer.mozilla.org/en-US/docs/WebOn overview page

Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-16912

/JavaScript/Reference/Global_Objects/Number/isIntegercore-js13
Number.isNaNhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaNcore-js13
Number.parseFloathttps://developer.mozilla.

Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-16912

org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseFloatcore-js13
Number.parseInthttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/On overview page

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

Number.isIntegerhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isIntegerOn overview page

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

Number.isNaNhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaNOn overview page

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

Number.parseFloathttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseFloatOn overview page

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

Number.parseInthttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseIntOn overview page

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

Object.assignhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assignOn overview page
Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-16912
Object.ishttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isOn overview pageNo
Object.entrieshttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entriesCustom

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

Object.valueshttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valuesCustom

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

parseIntcore-js13
Object.assignhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assigncore-js12
Object.createhttps://

Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-16912

developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/createcore-js14
Object.entrieshttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/On overview page

Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-16912

entriescore-js13
Object.valueshttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valuescore-js13
Promisehttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ObjectsOn overview page

Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-16912

String.includes/Promisehttps://github.com/stefanpenner/es6-promise12
Sethttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/On overview page

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

String.repeatSetcore-js14
String.startsWithhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWithcore-js12
String.endsWithhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeatOn overview pageNoendsWithcore-js12
String.fromCodePointhttps://developer.mozilla.org/en-US/docs/WebOn overview page

Jira Legacy
serverTotara Tracker
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-22527

/JavaScript/Reference/Global_Objects/String/fromCodePointcore-js14
String.includeshttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/On overview page

Jira Legacy
serverTotara Tracker
serverId4a8dcb52-d096-357c-b554-693e13845e2e
keyTL-24120

...

includescore-js13

IE 11 limitations

There are some limitations to be aware of when writing code that needs to work with IE 11 and Edge Legacy (Edge 16 - 18)with IE 11.

Aside from JS APIs, the following JS language features do not work in either IE or Edge Legacy:

  • for...of  - can not be polyfilled in IE 11 in a way that is both performant and standards compliant.standards-compliant
  • Generators do technically work but will be flagged by the linter as they perform poorly in IE 11

If you are using Totara 13-15 (which supports Edge Legacy 16-18), the following language features cannot be used:

  • Object spread - is not supported by Edge by Edge Legacy. Array spread and parameter spread are fine.Generators - these do technically work, but will be flagged by the linter as they perform poorly in IE 11.

These JS APIs are supported but have some pitfalls:

  • Object.keys()  with with a non-object argument throws an exception in IE. Make , so make sure to only call it with an object.
  • Promise - is supported via Polyfill in IE 11, but due to the aforementioned lack of micro-task support, it may not behave exactly as in other browsers, which can expose race condition bugs with user events that don't happen in other browsers. This However, this is rare however, and the solution is usually to improve the robustness of your code as there is usually an underlying problem if you run in to into this.

IE 11 lacks support for executing JS in micro-tasks, which can result in slightly degraded performance of asynchronous code , and updates to Vue components being delayed until after native events are processed. This is a platform-level feature which that is not possible to polyfill or emulate.

...