Objective
Redefine the className
property of the Element
interface, manually in JavaScript.
Description
The className
property, as we learnt about it in the chapter HTML DOM — Attributes, is defined on the Element
interface. It is an accessor property meant to mirror the class
attribute on the underlying element node.
That is, when the className
property is retrieved, the underlying element's class
attribute's value is retrieved. Similarly, when a value is set on the className
property, it's set on the class
attribute of the element node.
In this exercise, you have to redefine className
manually in JavaScript.
In your implementation, className
must continue to be an accessor property that could be get and set, performing the desired actions as mentioned above.
New file
Inside the directory you created for this course on JavaScript, create a new folder called Exercise-46-Redefining-className and put the .html solution files for this exercise within it.
Solution
This is a fairly easy exercise to solve.
We just ought to define an accessor property called className
, on the Element
interface, with a getter and a setter function.
The getter function simply gets the value of the class
attribute on the calling element node, whereas the setter function simply sets the value of the attribute on the node.
That's just it.
In the code below, we accomplish this idea:
Object.defineProperty(Element.prototype, 'className', {
get: function() {
return this.getAttribute('class');
},
set: function(value) {
this.setAttribute('class', value);
}
});
Let's now test this implementation.
Recall the following code from the chapter HTML DOM — Attributes while we were learning about the className
property:
<h1 id="h1">A heading</h1>
.text-blue {
color: blue
}
var h1Element = document.getElementById('h1');
// Add the class 'text-blue'.
h1Element.className = 'text-blue';
A heading
It just sets a text-blue
class on the <h1>
element to get it colored blue.
Now, let's run this same code with our manual className
implementation, including some console.log()
statements in the implementation to be sure that it really gets put into action:
Object.defineProperty(Element.prototype, 'className', {
get: function() {
console.log('Getter invoked');
return this.getAttribute('class');
},
set: function(value) {
console.log('Setter invoked');
this.setAttribute('class', value);
}
});
var h1Element = document.getElementById('h1');
// Add the class 'text-blue'.
h1Element.className = 'text-blue';
A heading
In the link below, open up the console and see whether there is the log Setter invoked
present. If there is one, this confirms that it's our implementation that's being invoked in line 15 above.
And voila! When we open up the link, there is indeed the desired log present.
The same methodology could be used to check the execution of the getter function associated with className
— access it in a get context and then witness the log Getter invoked
.