I have class like this
class Game {
constructor(player1, player2, gameId) {
this.Clockk = {
totalSeconds: timeForAnswer,
nowSeconds: timeForAnswer,
start: function () {
var self = this;
this.interval = setInterval(function () {
self.nowSeconds -= 1;
if (self.nowSeconds == 0) {
here I want to call "answered" function
}
},
reset: function(){
this.nowSeconds = this.totalSeconds;
},
};
answered(player) {
console.log(player);
}
};
I want to call function of Game class from this.Clockk variable.
this keyword inside a variable is this.Clockkitself, how can I get parrent class itself?
If you are in a method of the Clockk object, then this will refer to the Clockk object and, in Javascript, there is no natural way to refer to a "parent" or "containing" object. So, you have to store a reference to the parent somewhere. I can think of two straightforward ways to store it that come to mind. One is to store it in the parent scope, the other is to store it in the instance data of the Clockk object itself.
FYI, I am also assuming that the answered() method is supposed to be a method on Game object (your code in your question doesn't quite show that - but that appears to be the intent).
Here are two ways to do be able to call the parent's answered() method from with the this.Clockk.start() method:
Save parent reference in parent scope
class Game {
constructor(player1, player2, gameId) {
// save parent reference here so child scopes can refer to it
let parentObj = this;
this.Clockk = {
totalSeconds: timeForAnswer,
nowSeconds: timeForAnswer,
start: function () {
var self = this;
this.interval = setInterval(function () {
self.nowSeconds -= 1;
if (self.nowSeconds == 0) {
// here I want to call "answered" function
parentObj.answered();
}
},
reset: function(){
this.nowSeconds = this.totalSeconds;
},
};
}
answered(player) {
console.log(player);
}
}
Save parent reference in Clockk instance data
class Game {
constructor(player1, player2, gameId) {
this.Clockk = {
// save parent reference in our own instance data
parent: this,
totalSeconds: timeForAnswer,
nowSeconds: timeForAnswer,
start: function () {
var self = this;
this.interval = setInterval(function () {
self.nowSeconds -= 1;
if (self.nowSeconds == 0) {
// here I want to call "answered" function
self.parent.answered();
}
},
reset: function(){
this.nowSeconds = this.totalSeconds;
},
};
}
answered(player) {
console.log(player);
}
}
Or, you could break the Clockk implementation out into it's own class definition and then you'd pass the parent to it in its constructor and then its constructor would store the parent reference in its own instance data.
Related
I want to use the variable inside itself and I see other people do it but why does it not work for me?
This is my ES6 file
// Setup module
// ------------------------------
var FullCalendarAdmin = function () {
//
// Setup module components
//
var _componentRender = function () {
// Basic calendar
var _componentFullCalendarAdmin = function (events) {
// Define element
var calendarAgendaViewElement = document.querySelector('.fullcalendar-agenda-admin');
// Initialize
if (calendarAgendaViewElement) {
var calendarAgendaViewInit = new FullCalendar.Calendar(calendarAgendaViewElement, {
plugins: ['dayGrid', 'timeGrid', 'interaction'],
select: function (start, end) {
var title = prompt("Add event:");
var data;
if (title != '') {
data = {
title: title,
start: start,
end: end
};
calendarAgendaViewInit.addEvent(data);
}
}).render();
}
};
//
// Return objects assigned to module
//
return {
init: function () {
_componentRender();
}
}
}();
// Initialize module
// ------------------------------
document.addEventListener('DOMContentLoaded', function () {
FullCalendarAdmin.init();
});
How can I use the calendarAgendaViewInit to call the addEvent function without getting function as an undefined error?
Thanks in advance!
The problem is that you invoke .render immediately.
So your calendarAgendaViewInit is not an instance of FullCalendar.Calendar but the result of the render method.
What you can do is first define the calendarAgendaViewInit variable
var calendarAgendaViewInit = new FullCalendar.Calendar(calendarAgendaViewElement, {
plugins: ['dayGrid', 'timeGrid', 'interaction'],
select: function (start, end) {
var title = prompt("Add event:");
var data;
if (title != '') {
data = {
title: title,
start: start,
end: end
};
calendarAgendaViewInit.addEvent(data);
}
});
and then call calendarAgendaViewInit.render().
This is sort of an expanded explanation to the comment above. It looks like calendarAgendaViewElement is simply a DOM element that you've found and assigned to a variable. The problem here is that you can only call methods on class instantiations that are now objects with methods inside. If you had seen others call addEvent like that, then they were likely calling it on an instantiation of a class meaning that addEvent had been previously declared as part of that class and they are simply calling that method.
See the example below,
If I declare a class as follows:
class Sample {
sayHello(){
console.log('hello')
}
}
Then instantiate a new object of the 'Sample' class:
var sampleClass = new Sample()
Then I can call 'sayHello' by referring to the method inside the object
sampleClass.sayHello() // hello
Hope that helps
Yes, I have thoroughly searched google and did not find anything that suits my requirement.
The code i have so far is at the link below:
http://jsfiddle.net/ZKwTY/4/
There are multiple onchange events which call almost the same code, i would like to combine them maybe in a comma separated fashion to call it only once.
something like this
(on1Change, on2Change, on3Change): function () {
this.loadData();
}
is this possible??
Note: these functions are bound to the controls via a framework over which i do not have control, i need to create these functions and the framework would bind these to the respective controls
or you can create your object like this
var ol = {
on1Change: this.loadData,
on2Change: this.loadData,
on3Change: this.loadData,
on4Change: this.loadData,
loadData: function () {
this.loadData1();
this.loadData2();
},
loadData1: function () {
alert('hi from loadData1');
},
loadData2: function () {
alert('hi from loadData2');
}
};
Then if you want to do it once, then declare a object
var ol = {
loadData: function () {
this.loadData1();
this.loadData2();
},
loadData1: function () {
alert('hi from loadData1');
},
loadData2: function () {
alert('hi from loadData2');
}
};// end of object
ol.on1Change = ol.on2Change = ol.on3Change = ol.on4Change = ol.loadData;
add all propteries dynamically after object declaration
use bind()
$("selector").bind(on1Change, on2Change, on3Change): function () {
this.loadData();
}.....
you can try somethig like this http://jsfiddle.net/s4VVY/
i.e. add methods after object create
[1,2,3,4,5].forEach(function(it){ol["on"+it+"Change"] = function(){this.loadData()}})
UPDATE
may be this help
var ol = (function(){
var o = {
loadData: function () {
this.loadData1();
this.loadData2();
},
loadData1: function () {
alert('hi from loadData1');
},
loadData2: function () {
alert('hi from loadData2');
}
}
o.on1Change=o.on2Change=o.on3Change=o.on4Change=function(){ this.loadData();};
return o;
})()
also you can make function bindFunc
function bindFunc(){
var obj = arguments[0],
handler = arguments[1],
properties = Array.prototype.slice.call(arguments,2);
for(var i in properties){
obj[properties[i]] = handler;
}
}
and call as
bindFunc(o,function(){this.loadData();},"on1Change","on2Change","on3Change","on4Change")
I'm trying to pass a class instance about so that I can persist its member variables. I have the following code
var mainNamespace = WinJS.Namespace.define("MainNamespace", {
setupClass: WinJS.Class.define(
function () { },
{
createSetup: function CreateSetup() {
var interactionInst = new mainNamespace.interaction();
drawScreen.DrawScreen(interactionInst);
var backgroundProc = new
mainNamespace.createProc(interactionInst);
}
),
interaction: WinJS.Class.define(
function() {},
{
clickedPos: 0,
handleTouch: function handleTouch(event) {
this.clickedPos = event.x;
console.log("New pos: " + this.clickedPos);
}
),
createProc: WinJS.Class.define(
function (interaction) {
setInterval(this.runProc, 1000, interaction);
},
{
runProc: function runNewProc(interaction) {
console.log(interaction.clickedPos);
}
...
The drawScreen namepsace is as follows:
WinJS.Namespace.define("drawScreen", {
DrawScreen: WinJS.Class.define(
function DrawScreen(interaction) {
/// Do some screen set-up here
canvas.addEventListener("MSPointerUp", interaction.handleTouch, false);
}
)
});
The problem I have is that the interaction.clickedPos never changes. Why does it not change, and am I going about this the right way for a javascript app?
EDIT:
I've now worked out WHY this is happening, but not how to fix it. When interaction.handleTouch fires, this refers to the canvas object, and NOT the interaction object - so I have no access to it's members.
The problem is on the following line:
canvas.addEventListener("MSPointerUp", interaction.handleTouch, false);
here you are passing a reference to the function handleTouch() without any connection to the current instance (interaction). You can change the context of the event handler by using the .bind() method:
canvas.addEventListener("MSPointerUp", interaction.handleTouch.bind(interaction), false);
This question is a follow-up to my last question: JavaScript Serialization and Methods. While related, I believe this is different which is why I started this thread. Regardless...
I have a complex tree of objects that I need to pass around between pages. Because of this, I'm attempting to serialize and deserialize my objects. One of my objects in particular has several collections of child objects. Each of those child object types has a function on it, that I'm trying to call. Unfortunately, I am not having any luck. I setup a test project in an attempt to isolate the problem and get to the bottom of it. Currently, I have my JavaScript Objects defined in a seperate file called objects.js. That file looks like this:
objects.js
function MyChild() { this.init(); }
MyChild.prototype = {
data: {
id: 0,
fullName: "",
},
init: function () {
},
save: function (key) {
},
load: function (key) {
},
test: function () {
alert("Testing Child functions");
}
}
function MyParent() { this.init(); }
MyParent.prototype = {
data: {
id: "",
children: null
},
init: function () {
this.data.children = [];
},
save: function (key) {
window.localStorage.setItem(key, JSON.stringify(this.data));
},
load: function (key) {
var temp = window.localStorage.getItem(key);
if (temp != null) {
this.data = JSON.parse(temp);
$.each(this.data.children, function (i, r) {
});
}
},
test: function () {
alert("Testing Parent functions");
}
}
I am creating, serializing, deserializing, and attempting to interact with these objects in an .html file. That .html file is shown here:
test.html
<div>
<input id="button1" type="button" value="Create Object Tree" onclick="button1Click();" /><br />
<input id="button2" type="button" value="Retrieve and Execute" onclick="button2Click();" /><br />
</div>
<script type="text/javascript">
function button1Click() {
var child = new MyChild();
child.data.id = 1;
var p = new MyParent();
p.data.id = "A";
p.data.children.push(child);
p.save("A");
}
function button2Click() {
var storedParent = new MyParent();
storedParent.load("A");
storedParent.test(); // This works
alert(storedParent.data.children.length); // This displays "1" like I would expect
alert(storedParent.data.children[0].data.id); // This does NOT work.
storedParent.data.children[0].test(); // This does NOT work.
}
</script>
I'm not sure what I'm doing wrong. Can someone please help me understand this? Can somone please help me fix my example. I have a hunch that I'm not serializing MyChild objects properly. But I don't understand how I should be serializing / deserializing them in relation to MyParent.
Thank you!
You need to store your data within each object, not within its prototype.
Data stored in in the prototype of an object is shared between all instances and won't be serialised by JSON.stringify, so your object data never ends up in the local storage.
To fix, add data to this within the this.init() function:
MyChild.prototype = {
init: function() {
this.data = {
id: 0,
fullName: ""
};
},
...
}
MyParent.prototype = {
init: function() {
this.data = {
id: "",
children: []
}
},
...
}
Working sample at http://jsfiddle.net/alnitak/fdwVB/
Note that attaching the functions in MyChild to the retrieved data is tricky. The code below appears to work:
load: function(key) {
var temp = window.localStorage.getItem(key);
if (temp != null) {
this.data = JSON.parse(temp);
var children = this.data.children;
for (var i = 0; i < children.length; ++i) {
children[i] = $.extend(new MyChild(), children[i]);
}
}
},
But note that it works by constructing a new "default" child for each retrieved entry, and then overwriting that child's data with the serialised values.
This could be problematic if the constructor has "side effects".
A better approach might be to allow the MyChild() constructor to take an optional complete object of initial values to use instead of the default values.
//namespace
if (!window.SlidePanel) {
window.SlidePanel = (function () {
var SlidePanel = {};
return SlidePanel;
})();
}
SlidePanel.panel = function (el) {
this.$ = el;
}
SlidePanel.panel.prototype = {
insert: function () {
},
show: function () {
},
hide: function () {
}
}
SlidePanel.up = new SlidePanel.panel($('div#up-panel'));
SlidePanel.bottom = new SlidePanel.panel($('div#bottom-panel'));
SlidePanel.left = new SlidePanel.panel($('div#left-panel'));
SlidePanel.right = new SlidePanel.panel($('div#right-panel'));
I want to be able to set show and hide functions in some place of code. I thought to add setShowFn and setHideFn function to SlidePanel.panel.prototype like this
SlidePanel.panel.prototype = {
...
setShowFn: function (fn) {
this.show = fn;
},
setHideFn: function (fn) {
this.hide = fn;
}
}
Is this a good approach or there is more elegant way to do this?
If you want to override the show or hide function on just one instance of a SlidePanel.panel, you're free to just update that instance:
SlidePanel.up.show = function() { /* ... */ };
That breaks the inheritance of show for that specific instance, without changing any other instances that still use the show property from the prototype.
If you want to update show for all instances that are using the inherited version, you can do this at any time:
SlidePanel.panel.prototype.show = function() { /* ... */ };
...since the instances have a reference back to the prototype, and so changes to the prototype happen "live." Note that any instance on which you've done the first example above will be unaffected, because it's not using the version of show from the prototype anymore.
And yes, you're free to encapsulate this in your setShowFn and setHideFn functions if you want to; just be aware that there's nothing other than convention/documentation preventing code from assigning to the properties directly even if you do.