So I have an object lets call it A with a sub object which I'll call B which has a method/function called "CallMe" which I wish to be called when and object loads but I can't seem to get it to work. Is it even possible?
Example:
var A = {
B: {
CallMe: function() {
alert('I\'ve been Called!');
}
}
}
var objImage = new Image();
objImage.onLoad = A.B.CallMe;
objImage.src = '/img/some_image.png';
you should bind it to .onload property not .onLoad - this should fix it, silly typo - such are the worst
It works fine... you just need to need to call it (objImage.onLoad();):
var A = {
B: {
CallMe: function() {
alert('I\'ve been Called!');
}
}
}
var Image = function(){
}
Image.prototype.onLoad = null;
$(document).ready(function() {
var objImage = new Image();
objImage.onLoad = A.B.CallMe;
objImage.onLoad();
});
Test code here:
http://www.jsfiddle.net/yAJfd/1/
Related
var Lines = function(startXCon, endXCon,startYCon, endYCon)
{
this.drawCurve = function()
{
}
this.changeCurve = function(e)
{
//how can I call drawCurve from this method
}
}
The comment in my code explains the problem. Is this possible or are all methods private?
Like this:
var Lines = function(startXCon, endXCon,startYCon, endYCon){
var self = this; // store this as a variable to use in nested function
this.drawCurve = function(){}
this.changeCurve = function(e){
self.drawCurve(); //now call this.drawCurve()
}
}
I want to make a class in javascript to reuse from my main code in the connection with an indexeddb object. What I have now is:
function DATABASE() {
this.DB_NAME = 'MYdatabase';
this.DB_VERSION = 1;
this.db = null;
this.results = null;
}
DATABASE.prototype.open = function(callback) {
var req = indexedDB.open(this.DB_NAME, this.DB_VERSION);
req.onsuccess = function (evt) {
this.db = this.result;
callback();
};
req.onerror = function (evt) {
console.error("openDb:", evt.target.errorCode);
};
req.onupgradeneeded = function (evt) {
console.log("openDb.onupgradeneeded");
};
}
My problem here is that when the onsuccess executes I loose the scope of my main class and this is not what I expected. How can I do what I am looking for?
I want to make some connections at the same time with this, something like:
var DB = new DATABASE();
DB.open(function(res){});
var DB2 = new DATABASE();
DB2.open(function(res){});
var DB3 = new DATABASE();
DB3.open(function(res){});
thanks so much.
Under var req add var self = this; and use like this whenever the scope changes:
self.db = self.result;
My problem here is that when the onsuccess executes I loose the scope of my main class and this is not what I expected.
It's not scope, but the value of this during a function call depends on how the function is called. So what's happening is that the functions you're assigning to req are getting called with this being a different value than it is in the call to open.
How can I do what I am looking for?
Since your functions already close over the scope of the call to open, the easiest way is to do what Andy suggested:
DATABASE.prototype.open = function(callback) {
var req = indexedDB.open(this.DB_NAME, this.DB_VERSION);
var self = this; // <=== New
req.onsuccess = function (evt) {
self.db = this.result; // <=== Changed
callback();
};
// ...
}
Note: In the changed line, I don't know what this.result is, so I don't know whether to change this to self there as well. It's entirely possible that you actually want this.result, if result is a property of the object that this points to on the callback.
More:
You must remember this
Closures are not complicated
Does this work for you? Putting the open function inside the DATABASE instead of on the prototype.
function DATABASE() {
var _this=this;
_this.DB_NAME = 'MYdatabase';
_this.DB_VERSION = 1;
_this.db = null;
_this.results = null;
_this.open = unction(callback) {
var req = indexedDB.open(_this.DB_NAME, _this.DB_VERSION);
req.onsuccess = function (evt) {
_this.db = _this.result;
callback();
};
req.onerror = function (evt) {
console.error("openDb:", evt.target.errorCode);
};
req.onupgradeneeded = function (evt) {
console.log("openDb.onupgradeneeded");
};
}
}
var that = this
req.onsuccess = function (evt) {
that.db = that.result;
callback();
};
Also I recommend to read this article: Scope and this in JavaScript
I have written some javascript that I would to encapsulate in a closure so I can use it elsewhere. I would like do do this similar to the way jQuery has done it. I would like to be able to pass in an id to my closure and invoke some functions on it, while setting some options. Similar to this:
<script type="text/javascript">
_snr("#canvas").draw({
imageSrc : someImage.png
});
</script>
I have read a lot of different posts on how to use a closure to do this but am still struggling with the concept. Here is where I left off:
_snr = {};
(function (_snr) {
function merge(root){
for ( var i = 1; i < arguments.length; i++ )
for ( var key in arguments[i] )
root[key] = arguments[i][key];
return root;
}
_snr.draw = function (options) {
var defaults = {
canvasId : 'canvas',
imageSrc : 'images/someimage.png'
}
var options = merge(defaults, options)
return this.each(function() {
//More functions here
});
};
_snr.erase = function () {};
})(_snr);
When ever I try to call the draw function like the first code section above, I get the following error, '_snr is not a function'. Where am I going wrong here?
EDIT
Here is what I ended up doing:
function _snr(id) {
// About object is returned if there is no 'id' parameter
var about = {
Version: 0.2,
Author: "ferics2",
Created: "Summer 2011",
Updated: "3 September 2012"
};
if (id) {
if (window === this) {
return new _snr(id);
}
this.e = document.getElementById(id);
return this;
} else {
// No 'id' parameter was given, return the 'about' object
return about;
}
};
_snr.prototype = (function(){
var merge = function(root) {
for ( var i = 1; i < arguments.length; i++) {
for ( var key in arguments[i] ) {
root[key] = arguments[i][key];
}
}
return root;
};
return {
draw: function(options) {
var defaults = {
canvasId : 'canvas',
imageSrc : 'images/someimage.png'
};
options = merge(defaults, options);
return this;
},
erase: function() {
return this;
}
};
})();
I can now call:
<script type="text/javascript">
_snr("#canvas").draw({
imageSrc : someImage.png
});
</script>
Because you declared _snr as an object and not a function. Functions can have properties and methods, so there's various ways to achieve what you want, for example one of them would be say...
_snr = function(tag) {
this.tag = tag;
}
_snr.foo = function() {
//Code goes here
}
You can also pass the outer context into a closure to hide your variables from accidentally polluting the global namespace, so like...
(function(global) {
var _snr = function(tag) {
this.tag = tag;
}
_snr.foo = function() {
//Code goes here
}
//export the function to the window context:
global._snr = _snr;
})(window);
window._snr('#tag').foo('wat');
Happy coding.
Because your _snr is an object, not a function. You have to call it like this:
_snr.draw({
canvasId: '#canvas',
imageSrc: 'someImage.png'
});
When you do _snr('#canvas') that is a function call which is why you're getting that error. _snr is an object with some methods attached to it such as draw() and erase(). The reason jQuery is able to pass arguments into the $ is because they return the $ as a function object which is why we're able to pass it various selectors as arguments.
You are going wrong at the first line _snr = {}
It needs to be
_snr = function(){
selector = arguments[0]||false;
//snr init on dom object code
return _snrChild;
}
Im on a mobile phone but when im on a pc I will maybe fix the whole code c:
Here you have a snr object and that has erase and draw methods. What you intend to do is to write a _snr function which will get an id and return a wrapper object. That returned object should have erase and draw methods. so you can do
var returnedObject = _snr("my_id");
returnedObject.draw("image.png");
I started trying to create a timer function that would let me wrap a callback function so that I could later alter the behavior dynamically.
This led to a general realization that I really don't understand functions yet, and definitely don't understand what is happening with 'this'
I have a test environment setup on jsfiddle
myns = {};
myns.somefunc = function(txt) {
this.data = txt;
this.play = function() {
alert(this.data + ' : '+dafunc.data);
};
};
var dafunc = new myns.somefunc('hello world');
myns.Timer = function(msec, callback) {
this.callback = null;
this.timerID = null;
this.ding = function() {
this.callback();
};
this.set1 = function( msec, callback ) {
this.stop();
this.callback = callback;
this.timerID = setTimeout(this.ding, msec );
};
this.set2 = function( msec, callback ) {
this.callback = callback;
var wrappedDing = (function(who) {
return function() {
who.ding();
};
})(this);
this.timerID = setTimeout(wrappedDing, msec );
};
//this.set1(msec, callback);
this.set2(msec, callback);
};
var ttimer = new myns.Timer(1000, dafunc.play);
If I use the set1 method, then the callback doesn't work.
So I am trying the set2 method. This gets me to the play method but "this" is not referring to the instance of somefunc.
I thought I was on the right track, but the mix up on 'this' has me confused.
Any clues would be welcome.
The problem is that, unlike in a language like python, when you take a dafunc.play and pass it somewhere else (callback = dafunc.play) it forgets it was associated with dafunc, son you you would need to use yet another wrapper function, like you did in the set2 function.
var ttimer = new myns.Timer(1000, function(){ return dafunc.play(); });
Making all there extra functions by yourself is annoying. You could instead use the bind method that is available in newer browsers:
var wrappedDing = this.ding.bind(this);
new myns.Timer(1000, dafunc.play.bind(dafunc) );
Or you could use a similar shim if you need to support older versions of IE too.
Finally, if you are not going to take advantage of some form of inheritance or dynamic binding, you could instead rewrite your code to use closures. Since everything is lexicaly scoped, you don't have to worry about the this anymore:
(btw, I ended up simplifying the code in the proccess...)
myns = {};
myns.somefunc = function(txt) {
var obj = { data : txt };
obj.play = function() {
alert(obj.data);
};
return obj;
};
var dafunc = myns.somefunc('hello world');
myns.timer = function(msec, callback) {
var timerID = null;
var set = function(){
stop();
timerID = setTimeout(callback, msec);
};
set();
return {
set: set
};
};
var ttimer = myns.timer(1000, dafunc.play);
And one last thing: If you don't hate yourself use console.log and your browser's debugger and development console instead of using alerts for output.
How do I refactor this to use OOP , with MVC pattern:
function () {
var dataToImage = { 'a': 'a.gif', 'b': 'something.gif' };
var currentimage = dataToImage['a'];
function setCurrentImage(e){ currentImage = e.src; }
function getMousePosition(){ }
function drawToolbar {
for(i in dataToImage){
document.write('<img src="'+dataToImage[i]+'" onclick="setCurrentImage(this);">');
}
document.write('<div onclick="drawImage(this,getMousePosition())"></div>');
return;
}
function drawImage(div,xy) {
var img = document.createElement('div');
div.style["left"] = xy[0];
div.style["top"] = xy[1];
img.innerHTML='<img src="'+currentImage+'">');
div.appendChild(img);
return;
}
drawToolbar();
}());
There's a really good article on this here. I won't repeat what it says here. But to get you started you might extract a Model like this:
var Images {
get: function(id) {
return this.data[id];
},
del: function(id) {
delete this.data[id];
// might make an ajax call here to update the data serverside...
},
'data': {
'a': 'a.gif',
'b': 'something.gif'
}
};
And your controllers might be something like:
Controllers.DrawToolbar = function () {
// get the data for the images and pass it to the toolbar view
};
Controllers.DrawImage = function() {
// get the data for the image and pass it to the image view
};
Your views would be pretty much as your drawImage and drawToolbar functions are now, except the data they render would be passed as parameters. For example:
Views.Image = function (target, data, x, y) {
var imgContainer = document.createElement('div'),
img = document.createElement('img');
imgContainer.appendChild(img);
target.style["left"] = x;
target.style["top"] = y;
img.src = data;
target.appendChild(imgContainer);
};
Then you can wire things up with events as appropriate. (Use addEvent and don't set events with onclick attributes on html elements.)