In JavaScript, events are actions that happen in an app. They’re triggered by various things like inputs being entered, forms being submitted, and changes in an element like resizing, or errors that happen when an app is running, etc. We can assign event handler to handle these events. Events that happen to DOM elements can be handled by assigning an event handler to properties of the DOM object for the corresponding events. In this article, we will look at the onfocus
, oncancel
, and oncanplay
event handlers.
onfocus
The onfocus
property of the document
object lets us set an event handler for the focus
event, which is the opposite of the blur
event. The focus
event is trigger when a user sets focus on an HTML element. If we want to the focus event to fire for non-input elements, we have to put tabindex
attribute to it. What that attribute added we can focus on it with our computer’s Tab key. For example, we can attach the onfocus
event handler to the document
object by writing:
document.onfocus = () => {
console.log('focus');
}
We can also get the Event
object that triggered the focus event by adding the event
parameter to the event handler function like in the following code:
document.onfocus = (event) => {
console.log(event);
}
Then when we click in and out of the page, we something like the following output from the code above:
bubbles: false
cancelBubble: false
cancelable: false
composed: true
currentTarget: null
defaultPrevented: false
detail: 0
eventPhase: 0
explicitOriginalTarget: <html>
isTrusted: true
layerX: 0
layerY: 0
originalTarget: HTMLDocument https://fiddle.jshell.net/_display/
rangeOffset: 0
rangeParent: null
relatedTarget: null
returnValue: true
srcElement: HTMLDocument https://fiddle.jshell.net/_display/
target: HTMLDocument https://fiddle.jshell.net/_display/
timeStamp: 1463
type: "focus"
view: Window https://fiddle.jshell.net/_display
which: 0
The output above is the properties and the corresponding values of the Event
object. To see more details about the Event
object, we can look at the previous articles.
oncancel
To get handle the situation when the dialog
element has closed, we can use the oncancel
event handler, since the cancel
event is triggered when it’s closed. Handling the event with the oncancel
event handler prevents it from bubbling, so parent handlers aren’t notified of the event. Only one oncancel
handler can be assigned to an object at once. However, if we use the addEventListener
to attach the event handler function to our element, then we can get around this limitation. For example, we can use it like in the following code:
const dialog = document.getElementById('dialog');
const openButton = document.getElementById('open-button');
openButton.onclick = () => {
dialog.showModal();
};
dialog.oncancel = (event) => {
console.log('cancel');
console.log(event);
}
Then we have to add the dialog
element to our HTML code:
<button id='open-button'>
Open Dialog
</button>
<dialog id="dialog">
<form method="dialog">
<p>
Dialog
</p>
<menu>
<button id="cancel-button" value="cancel">Cancel</button>
<button id="confirmBtn" value="default">Confirm</button>
</menu>
</form>
</dialog>
In the code above we added a dialog
element to the HTML and get the DOM element for the HTML dialog
element with the getElementById
method, which gets us has the following methods:
close()
— a dialog instance method to close thedialog
element. An optional string can be passed in as an argument, which updates thereturnValue
of thedialog
, which is useful for indicating which button the user used to closed it.show()
— a dialog instance method to display the dialog modelessly, which means we still allow interaction from the outside. It takes no arguments.showModal()
— a dialog instance method to display the dialog as a modal over the top of anything else. It displays on the top layer along with a ::backdrop pseudo-element. Interaction with elements outside the dialog is blocked and the content outside can’t be interacted with.
dialog
DOM elements also have the following value properties:
open
— a boolean property that reflects theopen
HTML attribute, which indicates whether a dialog is open for interaction.returnValue
— a string property that sets and returns the return value for the dialog. We can assign it a value directly or we can pass in an argument to theclose
method to set this property.
We didn’t need to call the close()
method to close the dialog box. Having a button is enough. Also, we don’t have to click a button to close the dialog, we can also press the Esc key on our keyboard to do so.
Note that the dialog
element isn’t enabled by default on Firefox. To use it in Firefox, we have to set dom.dialog_element.enabled
to true
in the about:config
page. Chrome has this feature enabled by default. Then if we click the ‘Open Dialog’ button that we just made, then we will see a native browser dialog box. Then if we press the Esc key to close the dialog, then the cancel
event will be triggered and the event handler function that we assigned to the dialog.oncancel
will run. The event
parameter of the event handler function will get an Event
object, which has the information about the source of the cancel
event which is our dialog
element. So we would get something like the following in our console.log
output:
bubbles: false
cancelBubble: false
cancelable: true
composed: false
currentTarget: null
defaultPrevented: false
eventPhase: 0
isTrusted: true
path: (5) [dialog#dialog, body, html, document, Window]
returnValue: true
srcElement: dialog#dialog
target: dialog#dialog
timeStamp: 1102.240000385791
type: "cancel"
To see more details about the properties of the Event
object, we can look at the previous parts of this series.
oncanplay
We can assign an event handler function to the oncanplay
property when we want to handle the canplay
event. The canplay
event is fired when the user agent can play the media, but estimates that not enough data has been loaded to play the media up to its end without having to stop for further buffering of content. For example, we can use it for videos to see if enough parts of the video are downloaded to play until the end, we can first add a video element to the HTML code:
<video width="320" height="240" controls id='video'>
<source src="https://sample-videos.com/video123/mp4/240/big_buck_bunny_240p_30mb.mp4" type="video/mp4">
</video>
Then in our JavaScript code, we can add the following code to check if the video has downloaded enough to play:
const video = document.getElementById('video');
video.oncanplay = (event) => {
console.log(event);
}
We can also attach the canplay
event listener by using the addEventListener
method on the video DOM node instead like in the following code:
const video = document.getElementById('video');
video.addEventListener('canplay', (event) => {
console.log(event);
});
Either way, we can check if enough parts of the media has been downloaded in order for it to finish by using the readyState
property of the media element, which include video and audio elements. The readyState
can have one of the following possible values:
- The constant
HAVE_NOTHING
or number0
— there’s no information about the media resource - The constant
HAVE_METADATA
or number1
— enough parts of the media resource has been downloaded that the metadata attributes are initialized. Seeking won’t raise exceptions in this state or beyond - The constant
HAVE_CURRENT_DATA
or number2
— there’s enough data available for current playback position, but not enough to actually play more than one frame - The constant
HAVE_FUTURE_DATA
or number3
— there’s enough data for the current playback position is downloaded, as well as enough data for playing at least a little bit into the future, which means at least 2 frames of video. - The constant
HAVE_ENOUGH_DATA
or number4
— there’s enough data available, and that the download rate is high enough, that the media can be played through to the end without interruption.
We can get the readyState
property of our video element by writing the following code:
const video = document.getElementById('video');
video.oncanplay = (event) => {
console.log(event.target.readyState);
}
If our video can be played all the way through, we should have 4 logged in the console.log
output.
The onfocus
property of the document
object lets us set an event handler for the focus
event. We can use it to check if our element is focus or not. To focus non-input elements, we can add a tabindex
attribute to it. To get handle the situation when the dialog
element has closed, we can use the oncancel
event handler. The corresponding event which is the cancel
event is triggered when the Esc key on the keyboard is pressed. We can assign an event handler function to the oncanplay
property when we want to handle the canplay
event, which is the event that’s triggered when the user agent can play the media, but estimates that not enough data has been loaded to play the media up to its end without having to stop for more buffering of content. We can check if the media has downloaded enough data to be played all the way through by checking the readyState
from the media element.