I've a problem with this simple prototyping:
Game = function (moduleConfig, gameConfig) {
this.moduleConfig = moduleConfig;
this.gameConfig = gameConfig;
// Game-Commands
this.keyCommands = {
moveLeft: false,
moveRight: false
};
this.catcher = null;
this.stage = null;
return this;
}
/**
* Left arrow down
*/
Game.prototype.onKeyboardLeftDown = function () {
this.keyCommands.moveLeft = true;
}
/**
* Left arrow up
*/
Game.prototype.onKeyboardLeftUp = function () {
this.keyCommands.moveLeft = false;
}
I always get the error message: Uncaught TypeError: Cannot set property 'moveRight' of undefined when calling onKeyboardLeftDown and onKeyboardLeftUp. But i have declared moveLeft in the constructor in the keyCommands object.
The two methods were called on key down and key up events:
Game.prototype.init = function () {
// ...
// =========================================================================
// Set keyboard
KeyboardJS.on('left', this.onKeyboardLeftDown, this.onKeyboardLeftUp);
KeyboardJS.on('right', this.onKeyboardRightDown, this.onKeyboardRightUp);
// =========================================================================
};
My index.html looks like this:
<!DOCTYPE html>
<html>
<head>
<title>pixi.js example 1</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #000000;
}
</style>
<script src="js/pixi.dev.js"></script>
<script src="js/keyboard.js"></script>
<script src="js/moduleConfig.js"></script>
<script src="js/moduleResult.js"></script>
<script src="js/game.js"></script>
</head>
<body style="background-color: #EEEEEE">
<script>
var game = new Game(moduleConfig, {
screenWidth: (window.innerWidth - 10),
screenHeight: (window.innerHeight - 10),
bgColor: 0xEEEEEE
});
game.init();
</script>
</body>
</html>
Does some one see the failure? I have searched a lot, but i'm very confused (normally i develop only in c#...)
You're binding is wrong.
// Set keyboard
KeyboardJS.on('left', this.onKeyboardLeftDown, this.onKeyboardLeftUp);
this.onKeyboardLeftDown and this.onKeyboardLeftUp are called without the correct context
to fix this do something like:
KeyboardJS.on('left', this.onKeyboardLeftDown.bind(Game), this.onKeyboardLeftUp.bind(Game));
I would not recommend using bind() - for browser compatibility, but you can use something like lodash's bind or an bind "emulator" like:
function bind(fn, ctx) {
return function bound() {
return fn.apply(ctx, arguments);
};
}
Another way would be
var self = this;
KeyboardJS.on('left',
function(){self.onKeyboardLeftDown()},
function(){self.onKeyboardLeftUp()}
);
Your question is not complete, I do not see the relevant code where you try to define moveRight.
Possible problems:
you might have a typo, that keyCommands is spelled exactly
you might refer to keyCommands outside its scope
you might refer to keyCommands.moveRight before keyCommands is initialized
you might assign another value to keyCommands before referring to moveRight
Related
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>
A bad title and this might not be the best way to do what I'm trying to do (still learning javascript) but I'm trying to wrap a object using a delegate. The object in this case is an XMLHttpRequest.
var wrapper = function() {
this._delegate = /* get the delegate */
this._delegate.onreadystatechange = function() {
wrapper.readyState = this.readyState;
/* stuff that synchronizes wrapper goes here */
if(wrapper.onreadystatechange) {
wrapper.onreadystatechange();
}
};
return this;
}
The above is a simplification but when problem is that when I add an onreadystatefunction to the wrapper object like:
wrapper.onreadystatechange = function() {alert("hi)};
and the wrapper._delegate.onreadystatechange function is called, wrapper.onreadystatechange is always undefined and the alert popup never comes up. I think I'm getting my scope stuff wrong but I'm not exactly sure how to fix this. Would appreciate other suggestions but I would also like to know how to fix what I'm doing wrong. Thanks!
EDIT
Yup it was an incomplete example. sorry about that. I realized after trying to rewrite it into a complete example what my cause my issue. It seems if I don't have the outer "WRAP_FUNCTION" then it will work fine. I had written something like
WRAP_FUNCTION = (function() {
var originalXMLHttpRequest = window.XMLHttpRequest;
var wrapper = function() {
if(wrapper.wrapped) {
this._delegate = new originalXMLHttpRequest;
} else {
this._delegate = new window.XMLHttpRequest
}
this._delegate.onreadystatechange = function() {
wrapper.readyState = this.readyState;
/* stuff that synchronizes wrapper goes here */
if(wrapper.onreadystatechange) {
wrapper.onreadystatechange();
}
};
return this;
};
wrapper.prototype.open = function(method, url, async) {
this._delegate.open(method, url, async);
}
wrapper.prototype.send = function() {
this._delegate.send();
}
wrapper.wrapped = true;
return wrapper;
}
window.XMLHttpRequest = WRAP_FUNCTION;
HTML code:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script src="xmlhttp.js"></script>
<script type="text/javascript">
(function() {
var test = new XMLHttpRequest();
test.open("GET", "xmlhttp.js", true);
test.onreadystatechange=function()
{
if (test.readyState==4 && test.status==200)
{
alert("yay");
}
};
test.send();
})();
</script>
</body>
</html>
Try this.
var wrapper = function() {
// in this time var wrapper not yet defined completly
// if you want use wrapper on the finction
// need to use this instead of wrapper
var self= this;
this._delegate = /* get the delegate */
this._delegate.onreadystatechange = function() {
//this means _delegate is in this time
//if you want to use this(wrapper)
//set the value out of function
//like var self= this
//wrapper.readyState = this.readyState;
self.readyState = this.readyState;
/* stuff that synchronizes wrapper goes here */
//if(wrapper.onreadystatechange) {
// wrapper.onreadystatechange();
//}
if(self.onreadystatechange) {
self.onreadystatechange();
}
};
return this;
}
i want to build a div with scroll, that when you scroll this div, it will active anothe function.
i need to build this in a Object.
there is any way to do this?
i write here an example source (that not work) of what i want.
<script type="text/javascript">
function onsc(divName, divChange) {
this.play = function() {
window.onload = function() {
document.getElementById(divName).onscroll = function() {
this.scroll(n)
}
};
}
this.scroll = function(n) {
document.getElementById(divChange).innerHTML = "you scroll!";
}
}
c[1] = new onsc("div1", "div1_i").play();
</script>
<div id="div1_i">this div will change when you scroll</div>
<div id="div1" style="background:#C6E2FF; width:300px; height:200px; overflow-y:scroll;">
<p style="height:800px;">txt</p>
</div>
Your code was nearly there. I made a few changes and put into a JSFiddle for you.
I added comments at what you missed. Most importantly the context of this changes when you entered into that function on the onscroll event.
JavaScript
function onsc(divName, divChange) {
// First of all make `this` inherit to below functions
var self = this;
this.play = function () {
document.getElementById(divName).onscroll = function() {
// Changed this to call the parent and place the correct DIV
self.scroll(divChange)
}
}
this.scroll = function (n) {
document.getElementById(divChange).innerHTML = "you scroll!";
}
}
c = new onsc("div1", "div1_i").play();
Demo
Have a look at my JSFiddle: http://jsfiddle.net/bJD8w/2/
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.