Create javascript object with event handler - javascript

I have created a JavaScript Object and named it 'Button'. this object has a function that draw a button and append it to specific div element.
var Button = function (id, value) {
this.id = id;
this.value = value;
this.draw = function () {
var element = document.createElement("input");
element.type = "button";
element.id = id;
element.value = value;
document.getElementById("topDiv").appendChild(element);
}
};
I instantiate Button object and call draw() function like this:
var myButton = new Button('btn1', "Test Button");
myButton.draw();
My problem is I cant handle events. I want to connect onclick event to a function. for example:
myButton.onClick = function(){ alert(1); };
but I don't know how to define this.

Try
var Button = function (id, value) {
this.id = id;
this.value = value;
this.draw = function () {
this.element = document.createElement("input");
this.element.type = "button";
this.element.id = id;
this.element.value = value;
document.getElementById("topDiv").appendChild(this.element);
}
};
Button.prototype.addEventListener = function(event, handler){
var el = this.element;
if(!el){
throw 'Not yet rendered';
}
if (el.addEventListener){
el.addEventListener(event, handler, false);
} else if (el.attachEvent){
el.attachEvent('on' + event, handler);
}
}
Demo: Fiddle

I know it's an old question but it's worth mentioning that you could have done it after appending to div:
document.getElementById("topDiv").appendChild(element);
this.element.onclick = function(){ alert(1);};
this is more consistent and much less coding.
jsfiddle

You would have to create your own click() method (which takes a function as a parameter) that binds to the DOM element's click handler. Your draw() method can store a reference to the element in the object instance so that your click() method can access it.

As it was already mentioned, you should attach events to DOM objects.
The simple way is just to expose your DOM element from your custom class:
var Button = function (id, value) {
this.id = id;
this.value = value;
var element = document.createElement("input");
this.element = element;
this.draw = function () {
element.type = "button";
element.id = id;
element.value = value;
document.getElementById("topDiv").appendChild(element);
}
};
Now you can:
var myButton = new Button('btn1', "Test Button");
myButton.draw();
myButton.element.onclick = function(){ alert(1); };

If Native Javascript....
document.getElementById("btn1").onclick
If jQuery
$('#btn1').click(//function(){})....
If jQuery but Button is Created dynamically....
You might try..
$('#btn1').live('click',//function(){ })....
EDIT: As Suggested in the Comment:
Please read what the Documentation says:
As of jQuery 1.7, the .live() method is deprecated. Use .on() to
attach event handlers. Users of older versions of jQuery should use
.delegate() in preference to .live().
This method provides a means to attach delegated event handlers to the
document element of a page, which simplifies the use of event handlers
when content is dynamically added to a page. See the discussion of
direct versus delegated events in the .on() method for more
information.
Rewriting the .live() method in terms of its successors is straightforward; these are templates for equivalent calls for all three event attachment methods:
$(selector).live(events, data, handler); // jQuery 1.3+
$(document).delegate(selector, events, data, handler); // jQuery 1.4.3+
$(document).on(events, selector, data, handler); // jQuery 1.7+
ADDITIONAL
If You can't live without -live-...
As of jQuery 1.4 the .live() method supports custom events as well as
all JavaScript events that bubble. It also supports certain events
that don't bubble, including change, submit, focus and blur.

Related

Delegated Event Handler Selector

I'm trying to use a delegated event handler on dynamically-loaded content, like so:
AjaxProt.prototype = {
// bind handler - ensure to use $(document) to delay call to .on() method
init: function () {
var thisObj = this;
$(document).on(thisObj.event, thisObj.targetEl, function (e) {
e.preventDefault();
var url = $(thisObj.targetEl).attr('href');
thisObj.ajaxRequest(url);
});
},
ajaxRequest: function (url) {
var thisObj = this,
method = this.method,
ajaxCallType = this.ajaxCallType,
callback;
// $.ajax here
targetEl is assigned to [id^=startOfClassName]. I tried to pass the href value from init() to ajaxRequest(), but it's still only selecting the first element matching the selector on the page. How might I be able to ensure that the href value is bound to the element that's actually clicked? Thanks!
Sorry for wasting time, I figured this out myself.
All I had to do was change var url = $(thisObj.targetEl).attr('href') to var url = $(this).attr('href') since this is now in the scope of thisObj.targetEl, and therefore points to the specific element clicked.

Passing this to a method?

p.num = 100;
$('body').on('click', '.del', this.delete.bind(this));
p.delete = function(e) {
console.log(this.num); //100
//how can I get the .del element?
}
I'm trying to get the element that produced the click, but I also need access to the num property.
How can I access both types of 'this' inside my delete method?
The callback for an event receives an Event object that you can use to retrieve the element on which the event was called.
function(e) {
var element = $(e.target); //This is the element that the event was called on.
}
Disclaimer : This is the my exact answer (adapted with the current code) taken from here : Pass additional arguments to event handler?
Yet, the question doesn't seem to be an exact duplicate (but i may be wrong).
As said in the documentation of .on, you can pass datas to your event.
.on( events [, selector ] [, data ], handler )
data
Type: Anything
Data to be passed to the handler in event.data when an event is triggered.
So your event could look like that :
p.num = 100;
$('body').on('click', '.del', {object : this}, this.delete);
p.delete = function(e) {
var myObj = e.data.object;
// [myObj] will be your plugin
// [this] will be the clicked element
// [e] will be you event
}
if you're using jquery, you can combine those functions all into one like below:
note: num is an attribute so you have to use .attr().
$(document).ready(function() {
$('body').on('click', '.del', function() {
var num = $(this).attr('num');
alert('click function and num = ' + num);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Delete
or if you really want to keep them separate functions....:
$(document).ready(function() {
$('.del').on('click', function() {
deleteThis($(this));
});
});
function deleteThis(element){
var num = element.attr('num');
alert('click function and num = ' + num);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Delete
also, if youre using separate functions for the click and the delete, pass the element from click to delete: pass element - callDeleteFunction($(this)), and retrieve element - myDeleteFunction(element aka $(this))
I'm not sure what you're asking about but maybe this is what you want:
var p = {};
p.num = 100;
$('body').on('click', '.del', p.delete); // don't bind to this
p.delete = function(e) {
console.log(p.num); // here you still can call p
// this is del DOM element
}

Javascript classes & event handlers

I have a problem with this javascript code:
function MyClass() {
var id_nr = Math.ceil(Math.random() * 999999);
this.button_id = 'button_' + id_nr;
}
MyClass.prototype = {
createButton: function() {
var msg = 'Button \'' + this.button_id + '\' was clicked';
var my_button = (
'<input type="button" id="'
+ this.button_id
+ '" value="Click Me" /\>'
);
document.body.innerHTML += '<div>' + my_button + '</div>';
document.getElementById(this.button_id).onclick = function() { alert(msg); }
}
};
window.onload = function() {
var s = new MyClass();
s.createButton();
};
Yes, this current code works fine. But the problem appears when I add more than one MyClass objects:
window.onload = function() {
var s = new MyClass();
s.createButton();
var w = new MyClass();
w.createButton();
/* ...and many other buttons */
};
For some reason the onclick event will be triggered only if I click the button that was created last. And I don't know why.
One workaround could be something like this:
<input type="button" onclick="javascript:doSomeThing();" />
But unfortunately this is not the proper solution right row, because my goal is that the onclik event should be able to call another class methods as well. (Those methods are not created yet).
How can I make this code work properly? Any kind of a help is appreciated.
When you use innerHTML the contents get stripped from the DOM and then readded and parsed again, breaking any past event listener that you might have added.
If you want to do it in vanilla JS, consider using appendChild() and, also, I would suggest addEventListener(). Your code would then look like so:
var my_button = document.createElement('input');
my_button.type = 'button';
my_button.id = this.button_id;
my_button.value = 'Click me';
document.body.appendChild(my_button);
my_button.addEventListener('click', function () { alert (msg) });
Working example with vanilla Javascript
If you are up to using some jQuery, this would be so much easier to implement. Your method would look something like:
var my_button = $('<input>')
.prop('type', 'button')
.prop('id', this.button_id)
.val('Click Me')
.on('click', function () { alert(msg) } );
$('body').append(my_button)
Working example with jQuery
Or you could perhaps use the jQuery.on() method to delegate an event handler to all subsequent instances of your buttons.
Working example with delegated event handler
The use of innerHTML here seems to break the event listener "onclick".
You can avoid this by using the document.createElement method to create your html element :
var but = document.createElement("input");
but.type = "button";
but.id = this.button_id;
but.value = "Click me";
document.body.appendChild(but);
Personaly, I prefer use jQuery for manipulating the DOM tree element, as it offer really powerfull tools for this.

Clear Every Event Handler

I would like to cancel every event handler defined in a page with JavaScript. In other words, if the page previously set up many event listeners on many different DOM levels, this method would simply delete every one of them. Is there a way to do this in JavaScript?
For clearing all the events dynamically attached to elements within the body of the page, you can do:
document.body.innerHTML = document.body.innerHTML;
For clearing events attached to the window object, you can do:
window.onscroll = function() {};
and so on..
Nope there's no native event list to see what is bound to what. JQuery has its own, if you want better event management.
Here's how it's done in JQuery:
(function($) {
$.eventReport = function(selector, root) {
var s = [];
$(selector || '*', root).andSelf().each(function() {
var e = $.data(this, 'events');
if(!e) return;
s.push(this.tagName);
if(this.id) s.push('#', this.id);
if(this.className) s.push('.', this.className);
for(var p in e) s.push('\n', p);
s.push('\n\n');
});
return s.join('');
}
$.fn.eventReport = function(selector) {
return $.eventReport(selector, this);
}
})(jQuery);
You can call it various ways to suit your needs:
// all events
alert($.eventReport());
// just events on inputs
alert($.eventReport('input'));
// just events assigned to this element
alert($.eventReport('#myelement'));
// events assigned to inputs in this element
alert($.eventReport('input', '#myelement'));
alert($('#myelement').eventReport('input')); // same result
// just events assigned to this element's children
alert($('#myelement').eventReport());
alert($.eventReport('*', '#myelement'); // same result
From there, unbinding is simple.

jQuery - using $(this) in custom function

I'm trying to create a custom function that unbinds and then binds an event. It looks like this:
App.bindEvent = function(selector, eventType, eventHandler) {
$(selector).unbind(eventType);
$(selector).bind(eventType, function(event) {
eventHandler(event);
});
};
However, the problem I am facing is that I cannot use the this keyword to reference the DOM element that was clicked. For example, I cannot do this:
App.bindEvent("#my-element", "click", function() {
var myId = $(this).attr("data-my-id");
});
How would I go about getting the this keyword to point to the clicked DOM element like it does in jQuery.bind()?
Thanks for any help.
Change:
eventHandler(event);
To:
eventHandler.call(this, event);
That'll change the "scope" of your function to be the same as the scope of the original "bind" call.
How about this instead:
App.bindEvent = function(selector, eventType, eventHandler) {
var element = this;
$(selector).unbind(eventType);
$(selector).bind(eventType, function(event) {
eventHandler.call(element, event);
});
};
You need to call the handler in the context of the object:
eventHandler.call(this, event);
I think you're trying to refer to
event.target
For example:
App.bindEvent("#my-element", "click", function(event) {
var myId = $(event.target).attr("data-my-id");
});
check out jquery's event documentation

Categories