BannerNotification is a JavaScript library that wraps around the built-in BannerNotification library for UCP.
Additionally, it brings back support for automatically inserting banner notifications on top of visible modals. Currently, this is compatible with ShowCustomModal. Modal.js support is limited.
Importing
To import the library in your own scripts, use:
importArticle({
type: 'script',
article: 'u:dev:MediaWiki:BannerNotification.js'
});
The BannerNotification constructor won't be immediately available, but you can listen when it's available using the dev.banners
hook:
mw.hook('dev.banners').add(function(BannerNotification) {
// BannerNotification is the banner constructor
new BannerNotification('Hello world', 'notify').show();
// You can also access it with `window.dev.banners.BannerNotification`, but it's advised to keep your own reference to it
});
Usage
Construction
Once you have access to the BannerNotification
constructor, you can create with the regular interface.
new BannerNotification(content, type, $parent, timeout)
content
- Notification content. If a string, it will be interpreted as HTML. Make sure you're properly sanitizing what you pass to it. If anything other than a string, it will be stringified. This means that jQuery object or Element instances will not be useful. Therefore, any events will have to be attached after construction and displaying with.show()
using the.$element
property as is shown later in the documentation.type
- Notification type. String. Possible values are:notify
,confirm
,warn
,error
$parent
- The container that contains the notification. Has to be a jQuery object.timeout
- Notification display timeout in milliseconds. By default, there is no timeout.
Methods
Calling methods on BannerNotification
objects is the most common way of interacting with them, besides constructing them. Most of the time, you will only have to worry about showing them.
.show()
- Displays the notification. If a modal is in the foreground, it will be appended on top of it unless a
$parent
was explicitly passed to the constructor. .hide()
- Hides the notification.
.setType(type)
- Sets the notification type. Does not update the banner's icon if
.show()
was already called on it without being hidden again. It's advised not to use this method, and instead construct a new object once the type is computed. - Possible values are:
notify
,confirm
,warn
,error
.setContent(content)
- Sets the notification content. Does not update the banner's content if
.show()
was already called on it without it being hidden again. It's advised not to use this method, and instead construct a new object once the content is computed. .onClose(handler)
- Sets a callback for when the notification is closed. There can only be one callback at a time. It is not called if the notification expires on its own after the timeout runs out.
Properties
The returned BannerNotification
object has many available properties. Having to use them is rare, but there are specific cases where you will need to use them. Note that these properties are intended for read-only use. Directly assigning a value will not impact the actual notification. Complex cases can be found in the examples section.
.$element
- jQuery object for the banner. It will be null if
.show
wasn't called yet, or.hide
was called. More specifically, it will be null when the.hidden
property istrue
. This property is useful if you wish to attach event listeners to the banner's contents, or otherwise interact with them. .$parent
- The jQuery object passed as the parent on construction. It will not be updated with the automatically computed parent if it's not provided on construction. If none was passed on construction, it will be undefined.
.content
- The content string. Will get updated if
.setContent
is called. .type
- The type string. Will get updated if
.setType
is called. .hidden
- Boolean that indicates whether the banner is hidden or not. Calling
.show
will set this tofalse
, and calling.hide
will set this totrue
. .onCloseHandler
- The current handler for when the notification is closed. If none was passed, it will be a function that does nothing. This property can be useful if you want to set a close handler, but also want to keep a reference to the previous handler so you can call it after your new one gets executed.
Examples
This is the simplest interaction you can have with BannerNotifications. It's also the most common and, often enough, all you really need to know to use this library.
mw.hook('dev.banners').add(function(BannerNotification) {
new BannerNotification('Hello', 'notify').show();
});
If you're using internationalized messages, like you probably should be doing, with i18n-js, you should use .escape()
or .parse()
to make sure you're not accidentally exposing your scripts to XSS attacks.
// Here we're assuming that you have an instance `i18n` of your script's messages
mw.hook('dev.banners').add(function(BannerNotification) {
new BannerNotification(i18n.msg('banner-content').escape(), 'notify').show();
});
If you want to have a custom parent to attach the banner notifications to, you can use the third parameter. This is one of the rarer usecases, but it can come in handy with specific UIs.
mw.hook('dev.banners').add(function(BannerNotification) {
// Attach to the article's content. It will look weird, but hey, this is just an example!
var $parent = $('#mw-content-text');
new BannerNotification('This is the article content. I bet it\'s totally wrong!', 'notify', $parent).show();
});
If you want to set a timeout for your banner to automatically fade out, you can use the fourth parameter. Note how undefined is being passed as the 3rd $parent
parameter, as we're not interested in setting a custom parent. You can also use null
, though undefined is the standard default value.
mw.hook('dev.banners').add(function(BannerNotification) {
new BannerNotification('I will fade out after 2 seconds', 'notify', undefined, 2000).show();
});
If you want to attach events to the banner notification element itself, you'll have to keep a reference to it with a variable. Then you can use the $element
property to do what you want. The following example will implement a cancelable timeout which is currently not possible with the timeout parameter the BannerNotification constructor provides, and is about as complicated as these examples get.
mw.hook('dev.banners').add(function(BannerNotification) {
var banner = new BannerNotification('This notification will automatically hide itself unless you click me before 5 seconds pass. Click me now!', 'notify').show();
var $content = banner.$element.find('.wds-banner-notification__text');
var timeoutId = setTimeout(function() {
banner.hide();
}, 5000);
$content.on('click', function() {
clearTimeout(timeoutId);
alert('Congratulations, you have successfully averted disaster!');
$content.text('We are all safe now');
// Note: This will not update the icon! Not yet, anyway, it's a bit of an oversight in the library I guess
// It's only useful when reusing an instance that you repeatedly hide and show, but this pattern is discouraged
banner.setType('confirm');
});
banner.onClose(function() {
alert('No! How dare you close it manually! Do you have ANY idea what you\'ve just done???');
});
});