Maverick
Maverick

Reputation: 886

HTML element attached to JS object

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

Asigned event

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

Answers (1)

VadimB
VadimB

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

Related Questions