My JavaScript object create some HTML elements (two buttons for example) and after user click on these buttons I should call some method of this object. So the question is how I can refer JS object in HTML element to call its method?
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Title Goes Here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
function myObj(){
this.a = null;
this.setA = function(a){
this.a = a;
}
this.requestA = function(){
$( "body" ).append($('<input><button onclick="referenceToMyObject.setA($(this).prev().val());">Set A</button>'));
}
return this;
}
</script>
</head>
<body>
<script>
var myObjInst = myObj();
myObjInst.requestA();
</script>
</body>
Creating the event handler inline (onclick="foo()") won’t allow you to reference the object, and is discouraged in any case because you should avoid evaluating strings as code. In addition, your code bypasses JavaScript’s idea of objects somewhat. You can reformulate it as follows:
function MyObj() {
this.a = null;
}
MyObj.prototype.setA = function(a) {
const old = this.a;
this.a = a;
console.log("Updated a from", old, "to", this.a);
};
MyObj.prototype.requestA = function() {
const input = $("<input type='text'>");
const button = $("<button>Set A</button>");
button.click((e) => {
this.setA($(e.target).prev().val());
});
const body = $("body");
body.append(input);
body.append(button);
};
$(document).ready(() => {
const myObjInst = new MyObj();
myObjInst.requestA();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Here, we use button.click to define the event handler and new MyObj() to instantiate the object. Apart from that, I cleaned up the code a bit and added a bit of logging so you can see what’s going on.
You could still define setA and requestA within the constructor, as you do in your example. I chose to define them on the prototype since their behaviour is the same across instances.
Try this and please let me know if this works for you.
(working example in JSFiddle https://jsfiddle.net/galeroy/9nocztk4/1/)
<!doctype html>
<html>
<head>
<script>
var myObject = {
createButton: function(){
var p = document.getElementById('par')
var b = document.createElement('button');
b.innerHTML = 'click me';
b.setAttribute('onclick', 'myObject.myMethod()'); // this is the important part
p.appendChild(b);
},
myMethod: function(){
alert("Button created by object, when clicked, calls another method in the same object")
}
}
function init(){
myObject.createButton();
}
</script>
</head>
<body onload="init()">
<p id="par"></p>
</body>
</html>
Related
I am trying to attach a DOM element with a callback in JavaScript. Basically, the following is what I want:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="http://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
<script src="http://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script>
var ros = new ROSLIB.Ros({ url: "ws://localhost:9090" });
var listener = new ROSLIB.Topic({
ros: ros,
name: "/listener",
messageType: "std_msgs/String",
element: document.getElementById("hi") // this is added to show my need
});
listener.subscribe(function (event) {
// do crazy things here. let say replace the text
event.element.innerHTML = event.message.data; // this is added to show my need
});
</script>
</head>
<body>
<div id="hi"> hello world </div>
</body>
</html>
I want to use the DOM element inside the callback, which was declared while initializing the listener. I found a similar question here but could not make it work in this case.
function Subscriber(element, topic) {
var listener = new ROSLIB.Topic({
ros: ros,
name: topic,
messageType: "std_msgs/String"
});
listener.addEventListener("subscribe", this, false);
this.listener = listener;
this.element = element;
}
Subscriber.prototype.handleEvent = function (event) {
switch (event.type) {
case "subscribe":
this.element.dispatchEvent(new CustomEvent("subscribe", { details: { msg: message, e: element } }));
}
};
var element = document.getElementById("hi");
var topic = "/listener";
var subscriber = new Subscriber(element, topic);
subscriber.handleEvent(function (event) {
// do crazy things here. let say replace the text
event.details.e.innerHTML = event.details.msg.data;
});
As listener is a custom object, addEventListener is unavailable. Therefore, the following error is reported at the console:
listener.addEventListener("subscribe", this, false);
Uncaught TypeError: listener.addEventListener is not a function
How to modify the subscribe callback to bind a DOM element with it in JavaScript?
I made JS script:
var zzz;
zzz = {
fff: function (Id) {
alert("You did it! Id="+Id);
},
main: function (Id) {
var button, elements;
button = document.createElement("input");
button.type = "submit";
button.onclick = function () {
zzz.fff(Id);
};
elements = document.getElementById(Id);
elements.appendChild(button);
}
};
and HTML, where I tested it:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">
<title>My Web Page!</title>
<script type="text/javascript" src="test.js"></script>
</head>
<body>
<div id="div001"></div>
<div id="div002"></div>
<script type="text/javascript">
object1 = zzz;
object1.main("div001");
object2 = zzz;
object2.main("div002");
</script>
</body>
</html>
Why it works only if I write button.onclick = function () { zzz.fff(Id); }; and with this.fff(Id) it doesn't work?
When you bind an event handler (such as onclick), inside the handler this becomes the element that triggered the event (except if you used an inline onclick="" attribute, which should be avoided).
Instead of using zzz, you could also copy this to another variable that would be available inside the handler via closure:
var that = this;
button.onclick = function () {
that.fff(Id);
};
Or you could use Function.prototype.bind:
var clickHandler = button.onclick = function () {
this.fff(Id);
};
button.onclick = clickHandler.bind(this);
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script language="javascript" type="text/javascript">
(function setFont() {
var i;
for ( i = 0; i < document.all.length; i++) {
document.all[i].style.fontFamily = "Verdana";
document.all[i].style.fontSize = "16";
document.all[i].style.color="black";
}
})();
(function abc(a)
{
alert(a);
ansArray = ['a'];
for(i=1;i<=a;i++)
{
document.write('<input type = "button" value = "a">');
document.write('<input type = "button" value = "b">');
}
var myButton = document.getElementsByTagName("input");
//alert(myButton.length);
myButton[0].onclick = function() {
if(ansArray[0] == 'a')
myButton[0].style.backgroundColor = "green";
else
myButton[0].style.backgroundColor = "red";
};
myButton[1].onclick = function() {
if(ansArray[0] == 'b')
myButton[1].style.backgroundColor = "green";
else
myButton[1].style.backgroundColor = "red";
};
})();
setFont();
</script>
</head>
<body onload="abc(2)">
</body>
</html>
A javascript function abc(a) does not get the value 2 passed from <body onload = "abc(5)">. It says undefined. How to pass the parameters in a javascript function. I have posted it earlier as well but the parameter was not there, on giveing the parameter i found the problem.Please help me. Thanks in advance
Your function is a closure, it's not exposed to the public but it is executed right after it's created.
And then it's gone.
It's not there to look cool, it has its purpose. Just make normal functions to get it work
(function(a) {
// immediately called and 'garbaged'
})(a);
vs.
function publicAlwaysCallable(a) {
console.log(a); // call me when you like
}
You don't have to use immediate function in this case. Declare it like this:
function abc(a) { ... }
If for some reason you want to encapsulate your code into closure you can do it like this:
(function(export) {
export.abc = function(a) { ... };
...
})(window);
The normal function (not closure) function abc(a){ ... } with the button click handlers are to be called at the end of the script. Not on onload event of the page. Now it works in IE9 also
Thanks everybody for your valuable suggestions.
I've got another JavaScript/jQuery-Problem. A minimal example could be this: I've got a div, and want some JavaScript executed, when the mouse enters. But for some reasons (= in reality, there a many divs, and for each data needs to be kept) I want to use a object as handler for the callback. Here's a small example:
function handler($thediv)
{
this.somedata = 8;
$thediv.mouseenter(function() { this.callback(); });
}
handler.prototype.callback = function()
{
alert(somedata);
}
An object is created when the document is loaded:
$(document).ready( function() {
new handler($("div"));
});
Nothing happens - except that the constructor is executed. I've tried and searched for hours now, but I can't fix this... probably too trivial?
Edit: A complete example.
<html>
<script type="text/javascript" src="jquery-1.6.js"></script>
</head>
<body>
<div>
blah blahasdasdadsssssssssssssss
asddddddddddddddddddddddddddd
</div>
</body>
<script type="text/javascript">
$(document).ready(function() {
new handler($("div"));
});
function handler($thediv)
{
this.somedata = 8;
$thediv.mouseenter(this.callback);
}
handler.prototype.callback = function()
{
alert(somedata);
}
</script>
</html>
The biggest issue here is the use of this in various contexts. Within the mouseenter function, this refers to div, not the object.
This should work:
http://jsfiddle.net/Nx5c7/
function handler($thediv)
{
this.somedata = 8;
this.theID=$thediv.attr("id");
var obj=this;
$thediv.mouseenter(function() {
obj.callback();
});
}
handler.prototype.callback = function()
{
alert(this.theID + " : " + this.somedata);
}
I have a javascript object which has some defined variables and attaches some event handlers. I'd like the event handlers to have access to the defined variables. Is there a way to do that ? The event-handlers are within their own local scope so don't have access to the object variables. Is there a way to pass them in without using global variables ?
I have an idea that closures would solves this but I'm not sure how.
the code below will print the object name when the page loads but when you click on the map dom object it will say name is undefined.
All help much appreciated.
Colm
<!DOCTYPE html>
<html lang="en">
<head>
<title>Map Test</title>
<meta charset="utf-8" />
<script type="text/javascript">
window.onload = function() {
var e = new EvtTest();
e.printName();
e.attachEvents();
};
function EvtTest() {
this.name = "EvtTest";
}
EvtTest.prototype.name = null;
EvtTest.prototype.attachEvents = function () {
var map = document.getElementById("map");
map.addEventListener ('click', this.evtHandler, false);
};
EvtTest.prototype.printName = function () {
console.log ("This Name : " + this.name);
};
EvtTest.prototype.evtHandler = function (e) {
e.preventDefault();
console.log ("Name : " + this.name);
};
</script>
<style type="text/css">
html, body {
height:100%;
width:100%;
margin: 0;
background-color:red;
}
#map {
height: 300px;
width: 300px;
background-color:yellow;
}
</style>
</head>
<body>
<div id="map"></div>
</body>
</html>
A little bit of fiddling:
EvtTest.prototype.attachEvents = function () {
var that = this;
var map = document.getElementById("map");
map.addEventListener ('click', function () {
that.evtHandler();
}, false);
};
Now this inside evtHandler references the object you expected.