Reputation: 886
I just stater a bit of OOJS but I can't get my head around one thing, making an object for and HTML element and adding events to it.
For practice sake I had an idea to make inputs that can be validated, edited etc...
Here is how I call the input and assign it the HTML object
var elements = document.querySelectorAll('.input-field');
for (var n = 0; n < elements.length; n++) {
var instance = new input(elements[n]);
}
And this actually works, the event is assigned
But when I click on the input this.element
is undefined, I really don't know how because I already constructed the object with this.element
assigned.
(function(){
'use strict';
var Input = function Input(elem) {
this.element = elem;
this.construct();
};
Input.prototype.Classes = {
INPUT: 'input-field__input',
LABEL: 'input-field__label',
EDITED: 'input-field--edited',
FOCUSED: 'input-field--focused'
};
Input.prototype.onFocus_ = function(e) {
this.element.classList.add(this.Classes.FOCUSED);
};
Input.prototype.construct = function() {
if(this.element) {
this.input = this.element.querySelector('.' + this.Classes.INPUT);
this.label = this.element.querySelector('.' + this.Classes.LABEL);
if(this.input){
this.input.addEventListener('focus', this.onFocus_);
}
}
}
var elements = document.querySelectorAll('.input-field');
for (var n = 0; n < elements.length; n++) {
var instance = new Input(elements[n]);
}
})()
<div class="input-field">
<label class="input-field__label">Name</label>
<input type="text" name="name" class="input-field__input">
</div>
<div class="input-field">
<label class="input-field__label">Last</label>
<input type="text" name="last" class="input-field__input">
</div>
The problem is that the event is assigned but it doesn't know which object is it, this
is point to actual HTML input not the Input
object.
How do I fix this?
I searched the web but couldn't find anything similar. Closest I found: JS objects attached to HTML elements
Also if you can improve the code in any way please don't mind I am still learning.
Thank you in advance
Upvotes: 0
Views: 339
Reputation: 5711
Use bind
function to define scope your function will use. Currently your scope is your element, not your class instance.
this.input.addEventListener('focus', this.onFocus_.bind(this));
(function(){
'use strict';
var Input = function Input(elem) {
this.element = elem;
this.construct();
};
Input.prototype.Classes = {
INPUT: 'input-field__input',
LABEL: 'input-field__label',
EDITED: 'input-field--edited',
FOCUSED: 'input-field--focused'
};
Input.prototype.onFocus_ = function(e) {
this.element.classList.add(this.Classes.FOCUSED);
};
Input.prototype.construct = function() {
if(this.element) {
this.input = this.element.querySelector('.' + this.Classes.INPUT);
this.label = this.element.querySelector('.' + this.Classes.LABEL);
if(this.input){
this.input.addEventListener('focus', this.onFocus_.bind(this));
}
}
}
var elements = document.querySelectorAll('.input-field');
for (var n = 0; n < elements.length; n++) {
var instance = new Input(elements[n]);
}
})()
<div class="input-field">
<label class="input-field__label">Name</label>
<input type="text" name="name" class="input-field__input">
</div>
<div class="input-field">
<label class="input-field__label">Last</label>
<input type="text" name="last" class="input-field__input">
</div>
Upvotes: 1