JavaScript (v4 and below)
The Framework uses RequireJS to load in only the JavaScript needed for the page in question. When building new elements or modules which are to be enhanced using JavaScript, the functionality should therefore be included using RequireJS.
-
Set the
data-app
attribute on theinit.js
script tag within the page to the URL that the JavaScript files are located (do not include any trailing slashes). This URL should be the full path to the folder location, but should remain protocol agnostic:<script id="js-init" src="[ CDN Folder Path ]/js/init.js" data-app="="//:[ Site domain ]/..."></script>
-
Load the JavaScript for the module by setting the
data-module
attribute on the element to which the JavaScript will be applied toapp/[module]
, where[module]
is the name given to the JavaScript file for your module without the.js
file extension:<div class="..." data-module="app/[JavaScript block name]">...</div>
As an example, if you are using v4.9.0 of the Framework, with your JavaScript files stored at www.aviva.co.uk/project/library/js
, and your module file is called project-module.js
, your js-init
setup would be:
<script id="js-init" src="./v.2023.01/documentation//cdn.abeille-assurances.fr/static/core/v.4.9.0/js/init.js" data-app="//www.aviva.co.uk/project/library/js" crossorigin="anonymous"></script>
With the call to the module being:
<div class="..." data-module="app/project-module">...</div>
Considerations when writing blocks
Multi-language support
If content being added via the JavaScript which contains text, consider making that configurable so that it can be changed if required to better suit the usage or language.
A very example of this could be a button added to a page by JS, whose text content may need to be presented in a number of different languages if the component is used globally.
Accessibility
Always consider best practices with regard to accessibility, and, wherever possible, make use of ARIA attributes to help users with assistive technologies to better navigate the page/application. See the Accessibility Manual for more information.
Writing JavaScript blocks
Use RequireJS to define the block, loading in any JavaScript files that the block is dependent on. Check the list of core JavaScript files at the bottom of this page so that files are not loaded multiple times from different locations. For example:
define( [ 'jquery', 'utility' ], function run( $, util ) { // Set up define call for RequireJS
'use strict'; // Always use strict mode var block = { // Define the js module block
init : function( el ) { // Create the init function to run on load
// Your module code goes in here, for example:
this.create( $( el ) );
}, create : function( element ) { // Additional functions can be also created
// Creation code
}
}; return { // Finally, return your block, initialising the instance of its use
initInstance: function( el ) {
block.init( el );
}
};
});
Important note: The init function for the block will be called for every instance of the element/module that occurs within the page on load, so precautions should be taken to ensure that this does not get applied multiple times to the same element/module. This could be achieved by simply checking for a particular class being present on the element/module, for example .js-module
, which is only added by the JavaScript.
Running RequireJS again
If additional content is generated or loaded in to your page by JavaScript and contains element or modules which themselves get enhanced via JavaScript (for example, a modal window that loads in some show/hide sections from another page), RequireJS will need to be run again to pick up the newly added elements.
This is achieved by triggering the moduleScan
event on the document's body element:
$( 'body' ).trigger( 'moduleScan' );
As of Framework v4.6.0, it is possible to run moduleScan without the jQuery dependency. To do this, set up the following JavaScript function:
var trigger = function( targetEl, eventName ) {
var event = document.createEvent( 'Event' );
event.initEvent( eventName, true, true );
targetEl.dispatchEvent( event );
};
moduleScan
can then be run using the following command where needed:
trigger( document.body, 'moduleScan' );
Extending the RequireJS config
v4.X.X
If you need to extend the RequireJS config setup by v4 of the Framework, use the following code:
<script>
window.requireExtend = {
paths : {
//... custom paths
},
moduleAttributes : {
'app/yourModule' : {
crossorigin : 'anonymous',
//... Any other attribute e.g. integrity
}
}
};
</script>
<script async id="js-init" src="[ CDN Folder Path ]/js/init.js" crossorigin="anonymous"></script>
Place this config extension in a separate file and load it in before the Framework's init.js
script.
Important note: There are several caveats to using this process:
- Do not overwrite the
baseUrl
orskipDataMain
config properties; these are required by Framework to work correctly. - If you are adding a config property that uses an object type, (eg.
paths
), then when the Framework config and the extension config are merged, the Framework's values will take priority. This means that if you tried to add a custom path forjquery
, it would be overwritten by the Framework's value. - If you are adding a config property that uses an array type (eg.
deps
), then the Framework's config value will be concatenated with the extension config. - If you are adding a
callback
property, this will be wrapped within the Framework's own callback function; the Framework function will run first, and then call any additional callbacks. - To add your own attributes to the script tag; include a
moduleAttributes
property that is an object type and within that object include an object for each module, where the module name is the key and within, set the attribute name as the key and the attibute value as the value.
v3.X.X and earlier
If you need to extend the RequireJS config setup by v3 or earlier of the Framework, use the following code:
<script>
document.addEventListener( 'requireready', function onRequireReady() {
// Your custom Require config which will be merged with the Frameworks config
require.config({
// ...
}); // Then you can use Require as normal for more flexibility
require( [ 'jquery' ], function run( $ ) {
// ...
});
});
</script>
Important note: Be careful not the overwrite any existing config settings, as this can and will break components.
CORS on RequireJS modules
The crossorigin
attribute on img, video or script tags enables you to configure the CORS request for an element's fetched data.
From v4.12.0 it is possbile to include custom attributes to modules by extending the RequireJs config. This can be used to include a crossorigin
attribute to handle the CORS request.
<script>
window.requireExtend = {
moduleAttributes : {
'app/yourModule' : {
crossorigin : 'anonymous',
...
//... Any other attribute e.g. integrity
},
'app/' : { // This would set the attributes to all modules where the module name starts with 'app/'
crossorigin : 'anonymous',
...
},
...
}
};
</script>
SRI on RequireJS modules
Subresource integrity is a feature of the browser that ensures the resources that are fetched are delivered without unexpected change to them, to prevent, for example files changed by a hacker on the CDN being able to execute a harmful script. This works by the browser generating a hash digest from the fetched resource against one provided in the element's integrity attribute. Framework files included using RequireJS have this feature included.
Since v4.12 it is possbile to include custom attributes to modules by extending the RequireJs config. This can be used to include a integrity attribute to handle the CORS request. The element also requires the crossorigin attribute to be present.
To generate a digest you can use a shell command below or paste the file link into .
openssl dgst -sha384 -binary FILENAME.js | openssl base64 -A
Example of how to extend the Require config to include a integrity attribute to a module:
<script>
window.requireExtend = {
moduleAttributes : {
'app/yourModule' : {
integrity : 'sha384-digestGoesHere'
crossorigin : 'anonymous',
...
//... Any other attribute e.g. integrity
},
'app/' : { // This would set the attributes to all modules where the module name starts with 'app/'
crossorigin : 'anonymous',
...
}
}
};
</script>
For more information go to the Mozilla Developer Docs.
Working programmatically with RequireJS
Sometimes you may want more flexibility than using Framework blocks; in this situation, working directly with RequireJS is the recommended approach.
To do this, wait for the RequireJS config to be load asynchronously and to fire its callback, which will emit the requireready
event on document
. This is set up as follows:
<script>
document.addEventListener( 'requireready', function onRequireReady() {
require( [ 'jquery', 'app/custom-module' ], function run( $, customModule ) {
// When Require JS has loaded and run, do something...
});
});
</script>
Loading JavaScript that not compatible with RequireJS
If, when migrating to the Framework, there are a number of blocks of JavaScript which are required for page functionality, but which it is not viable to rewrite into the Framework module format, we suggest trying this solution.
- Set the
data-app
attribute on theinit.js
script tag within the page as detailed above. -
Add in each required script under the
init.js
script tag in the following format:<script id="js-init" src="[ CDN Folder Path ]/js/init.js" data-app="./website/scripts" crossorigin="anonymous"></script> <span data-module="app/jquery.validate.min" ></span>
-
If one of the files has a dependency on another, the file is modified so that the original code is wrapped by an AMD loader function. For example, to ensure that jQuery is loaded before the JavaScript is run:
( function( factory ) { if ( typeof define === 'function' && define.amd ) { // AMD. Register as an anonymous module depending on jQuery. define( 'app/faq-manager', [ 'jquery' ], factory ); } else { // No AMD. Register plugin with global jQuery object. factory( jQuery ); } }( function( $ ) { // The original JavaScript goes here }));
Triggering a refresh
Sometimes you may want to force content to refresh, for example if elements need to be redrawn after being hidden and then shown again. Using jQuery, you can run this by calling:
$( window ).trigger( 'refresh' );
As of Framework v4.6.0, it is possible to trigger a refresh without the jQuery dependency. To do this, set up the following:
var trigger = function( targetEl, eventName ) {
var event = document.createEvent( 'Event' );
event.initEvent( eventName, true, true );
targetEl.dispatchEvent( event );
};
This can then be run using the following command where needed:
trigger( window, 'refresh' );
Important note: At this time, both the native and jQuery versions of the trigger should be used so that both Framework components which do not have a jQuery dependency and those which still do will be correctly refreshed. This will mean ensuring that jQuery has been included in your define call for RequireJS at the start of your module block (as described in the Writing JavaScript blocks section above), with the refresh call as follows:
trigger( window, 'refresh' );
$( window ).trigger('refresh' );
Interacting with Framework components
In v5.0.0, we have made interacting with Framework components easier and more reliable. All components now return an object which may contain functions which can be called to, for example, update or get settings.
The following is an example of how the settings would be updated on a date component.
require( [ 'a-date' ], function run( aDateModule ) {
'use strict'; var myDateEl = document.querySelector( '#dateInput' ), // Get my component
newSettings = {
minDate : '2016-01-01',
maxDate : '2018-01-01',
}; // Some data to use /*
* This will run the initInstance function and return the aDate object which is appended
* to the myDateEl, if the component has already been initialised, it will not run as the
* init function, but will still return the appropriate aDate object
*/
var aDateInstance = aDateModule.initInstance( myDateEl ); // Run setSetting as required
aDateInstance.setSettings( newSettings );
});
Using jQuery validate and unobtrusive
From Framework v3.0.0, jQuery validate and unobtrusive are available for use with your blocks of JavaScript. Load them by adding them to your define
block as follows:
define( [ 'jquery', 'jquery.validate' ], function run( $ ) {
...
});
define( [ 'jquery', 'jquery.validate.unobtrusive' ], function run( $ ) {
...
});
From Framework v4.0.0, jQuery validate and unobtrusive are configured to display errors correctly with the default markup for form components.
For validate and unobtrusive to work, there are certain elements which MUST be in the markup, and the markup MUST be correct as per the Framework documentation.
Updating unobtrusive settings
If you need to update the unobtrusive defaults, then do so as follows:
require( [ 'jquery', 'jquery.validate.unobtrusive' ], function run( $, unobtrusive ) {
var $form = $('form'); unobtrusive.options.errorClass = 'my-custom-error'; unobtrusive
// Remove validation
.destroy( $form )
// Reparse the document to apply new unobtrusive defaults
.parse( document );
});
Important note: this is typically a blunt approach, so a better method whenever possible would be to update the validator settings instead:
require( [ 'jquery', 'jquery.validate.unobtrusive' ], function run( $, unobtrusive ) {
var $form = $( 'form' ),
validator = $form.data( 'validator' ); if ( validator ) {
validator.settings.errorClass = 'my-custom-error';
}
});
Validator error placement
There may be occasions where error placement does not work as expected for a certain form field; to work around this, you may need to modify jquery.validate's settings, for example:
require( [ 'jquery', 'jquery.unobtrusive' ], function run( $, unobtrusive ) {
var $form = $( 'form' ),
validator = $form.data( 'validator' ); if ( validator ) {
validator.settings.errorPlacement = function errorPlacement( error, $element ) {
// Position the error message in a custom location for 'my-element'
if ( $element.attr( 'id' ) === 'my-element' ) {
$( '#my-element-error-container' ).append( error );
// Otherwise use the default errorPlacement handler
} else {
$.validator.defaults.errorPlacement.apply( this, arguments );
}
};
}
});
Core JavaScript files
Modernizr
The Framework uses Modernizr v3.11.4 (v3.6.0 prior to v4.16.7 and v3.3.1 prior to v4.0.0 of framwork) to aid in detecting browser capabilities. The build currently tests for:
- borderimage
- cssanimations
- csscalc
- cssgradients
- csstransforms
- csstransforms3d
- csstransitions
- flexbox
- formvalidation
- inputtypes
- objectfit
- smil
- svg
- touchevents
Files available to use with RequireJS
v4.X.X
block | Description | Functions / Variables |
---|---|---|
jquery | jQuery v.3.5.1 (v3.4.0 prior to release v4.16.5 and v.3.3.1 prior to release v4.9.0) | |
utility | Core utility functions |
smallTag mediumTag largeTag urlRegExp getBreakpoint() makeId( prefix ) processInPageLinks( selector, callback ) debounce( func, wait, immediate ) |
vendor/jquery/mousewheel | jQuery Mousewheel - v3.1.13 | |
vendor/jquery/jquery-ui | jQuery UI - v1.12.1 |
|
vendor/jquery/mCustomScrollbar | jQuery custom scrollbar - v3.1.5 | |
moment | Moment - v2.22.1 | Includes all locales |
vendor/pikaday | Pikaday - 1.7.0 - https://github.com/Pikaday/Pikaday (Updated to 1.8.0 in v4.9.0) |
|
vendor/numeral | Numeral.js - v2.0.6 - https://numeraljs.com | |
vendor/highcharts/highcharts | Highcharts - v6.1.0 - https://www.highcharts.com | |
vendor/highcharts/highcharts/modules/... | Highcharts modules - for v6.1.0 - https://www.highcharts.com |
|
vendor/highcharts/highstock | Highstock - v6.1.0 - https://www.highcharts.com | |
vendor/highcharts7/highcharts | Highcharts - v7.0.2 - https://www.highcharts.com | CSS available from [cdn path]/css/vendor/highcharts7/... |
vendor/highcharts7/modules/... | Highcharts modules - for v7.0.2 - https://www.highcharts.com |
|
vendor/highcharts7/indicators/... | Highcharts indicators - for v7.0.2 - https://www.highcharts.com |
|
vendor/highcharts7/lib/... | Highcharts lib - for v7.0.2 - https://www.highcharts.com |
|
vendor/highcharts7/themes/... | Highcharts themes - for v7.0.2 - https://www.highcharts.com |
|
vendor/highcharts7/highstock | Highstock - v7.0.2 - https://www.highcharts.com | |
vendor/highcharts7/highcharts-3d | Highcharts 3D - v7.0.2 - https://www.highcharts.com | CSS available from [cdn path]/css/vendor/highcharts7/... |
vendor/highcharts7/highcharts-more | Highcharts More - v7.0.2 - https://www.highcharts.com | CSS available from [cdn path]/css/vendor/highcharts7/... |
jquery.validate | jQuery validate v1.17.0 - https://jqueryvalidation.org | |
jquery.validate.unobtrusive | jQuery validate v3.2.7 |
Includes default error placement to match the Frameworks markup. When loading unobtrusive do not load jQuery validate as well. |
jquery.validate.unobtrusive-ajax | jQuery validate v3.2.4 |
Includes default error placement to match the Frameworks markup. When loading unobtrusive-ajax do not load jQuery validate as well. |
v3.X.X and earlier
block | Description | Functions / Variables |
---|---|---|
jquery | jQuery v2.2.2 | |
utility | Core utility functions |
smallTag mediumTag largeTag urlRegExp getBreakpoint() makeId( prefix ) processInPageLinks( selector, callback ) debounce( func, wait, immediate ) |
(Removed in beta v1.0.5) | ||
vendor/jquery/mousewheel | jQuery Mousewheel - v3.1.13 | |
vendor/jquery/jquery-ui | jQuery UI - v1.12.0 |
|
vendor/jquery/mCustomScrollbar | jQuery custom scrollbar - v3.1.3 | |
moment | Moment - v2.14.1 | Includes all locales |
vendor/pikaday | Pikaday - https://github.com/Pikaday/Pikaday | |
jquery.validate | jQuery validate v1.17.0 - https://jqueryvalidation.org | Available from v3.0.0 |
jquery.validate.unobtrusive | jQuery validate v3.2.7 |
Available from v3.0.0 When loading unobtrusive do not load jQuery validate as well. |
jquery.validate.unobtrusive-ajax | jQuery validate v3.2.4 |
Available from v3.0.0 When loading unobtrusive-ajax do not load jQuery validate as well. |