JS OOP: uncaught exception null

C

c.prerovsky

Hi there,

I started messing around with JavaScript OOP a few days ago and still
can't get this one to work. There are many things wich keep confusing
me, eg. the various ways to define a class or especially methods.

Ok, here's the code I'm trying to get to work. I'm trying to create a
selection mask with drag handles, which will enable the user to select
an area of an image. currently I'm stuck with
"el.addEventListener('mousedown', this.startDrag, false);" which leads
to "uncaught exception null" since this.startDrag seems not to be
recognized as a method for "this". Before this attempt I defined
functions like: "function startDrag()" which did not work fine, sind
"this" lead to the HTML element which has been clicked.

So, any ideas why this one does not work and leads to "uncaught
exception null"?

function Handle(id, maskRef) {
var el, drag;
this.id = id;
this.mask = maskRef;

el = document.createElement("div");
el.style.border = "1px solid #333333";
el.style.position = "absolute";
el.style.zIndex = "110";
el.style.width = "5px";
el.style.height = "5px";
el.style.left = "300px";

document.body.appendChild(el);

el.addEventListener('mousedown', this.startDrag, false);
el.addEventListener('mouseup', this.stopDrag, false);
document.addEventListener('mousemove', this.doDrag, false);

this.startDrag = function(event) {
drag = true;
alert(m.getInitX());
}

this.doDrag = function(event) {
if (!drag) return;
var posX = event.clientX + window.scrollX;
var posY = event.clientY + window.scrollY;

el.style.left = posX - 3 + "px";
el.style.top = posY - 3 + "px";

// update mask
var mask = document.getElementById("mask");

if (posX > this.mask.initX) {
mask.style.width = this.mask.initX - posX;
} else {
mask.style.width = mask.offsetLeft + mask.offsetWidth - posX;
mask.style.left = posX;

}
mask.style.height = (event.clientY + window.scrollY) -
mask.offsetTop - 1;
}

this.stopDrag = function(event) {
drag = false;
}
}

function Mask() {
el = document.createElement("div");
el.style.border = "1px dotted #333333";
el.style.position = "absolute";
el.style.zIndex = "100";
el.style.width = "300px";
el.style.height = "300px";
el.style.left = "400px";
el.style.top = "400px";
el.id = "mask";

document.body.appendChild(el);

var initX = el.offsetLeft;
var initY = el.offsetTop;

// create handles
var hSE = new Handle("se", this);
}

var m = new Mask();

Thanks in advance for any hints or suggestions!
Best regards,
Clemens
 
E

Elegie

(e-mail address removed) wrote:

Hi,
currently I'm stuck with
"el.addEventListener('mousedown', this.startDrag, false);" which leads
to "uncaught exception null" since this.startDrag seems not to be
recognized as a method for "this".

You've defined your method using a "function expression" pattern, and
not a "function declaration" one, which means your function object is
created as a normal variable, while the source text parsing. In other
words, you've just used a variable before defining it :)
el = document.createElement("div");
el.style.border = "1px solid #333333";
el.style.position = "absolute";
el.style.zIndex = "110";
el.style.width = "5px";
el.style.height = "5px";
el.style.left = "300px";

Lots of hard-coded values there, why not group them in a CSS class and
pass them as parameters?
alert(m.getInitX());

"m" refers to your global Mask instance, why use an instantiable "class"
if you only want a singleton?
var hSE = new Handle("se", this);

Does Handle really need to be a constructor? It seems to me you would
just like to augment an object, not create a new one.
Thanks in advance for any hints or suggestions!

Of course I'm aware you've just posted a test case, so please don't take
my comments literally, rather as a hint for your future conception.

Searching c.l.j archives at groups.google.com for "prototype" and
"closure" will give you some insight/examples about javascript OOP.

Regards.
 
C

c.prerovsky

First of all: many thanks for your help!
You've defined your method using a "function expression" pattern, and
not a "function declaration" one, which means your function object is
created as a normal variable, while the source text parsing. In other
words, you've just used a variable before defining it :)

Ahhhhh, ok, this one seems comprehensible to me. After turning all of
Handle's function declarations to Handle.prototype.funcName =
function() the null stuff is gone. As you would excpect solving one
problem uncovered a whole lot of other ones ;)

Currently the doDrag method gives me bad headace as this refers to the
Document object itself, instead of the Handle object which is what I
was expecting. Ok, the Document object triggers the mousemove event,
but I just dont understand why this does not refer to Handle's current
instance.

I know that there is a lot of css inside the constructor right now
which is because of the early development stage of the code. I'll
export it to css definitions later.
"m" refers to your global Mask instance, why use an instantiable "class"
if you only want a singleton?

This one is just leftover debugging code - sorry for not cleaning up
before posting :)

Does Handle really need to be a constructor? It seems to me you would
just like to augment an object, not create a new one.

Yes, in fact Handle and Mask have to be constructors since I want to
have eight Handles for each Mask (as you have in programs like
Photoshop). A Mask will look as follows:

o---o---o
| |
o o
| |
o---o---o

I hope you get the Idea :). Each "o" is a drag handle, while the box is
the selection area or what is called mask in my case.
Searching c.l.j archives at groups.google.com for "prototype" and
"closure" will give you some insight/examples about javascript OOP.

Still browsing through those threads - thanks!

Best regards,
Clemens
 
E

Elegie

Currently the doDrag method gives me bad headace as this refers to the
Document object itself, instead of the Handle object which is what I
was expecting. Ok, the Document object triggers the mousemove event,
but I just dont understand why this does not refer to Handle's current
instance.

The "this" value is determined when entering the execution context, when
the handler is called the parser looks to the owner, which is "document"
in your example.

See ECMA262, 3rd Ed., chapter 10 "Execution Contexts" if you desire to
know more about this :)

Therefore you need to think about how you want to make your instance
visible from the handler, so that you can use it directly (you can make
it globally accessible, or encapsulate the reference into a closure, or
make some kind of sacrifice to please computer gods).

---
document.addEventListener(
"mousemove",
(function(foo){return function(evt){return foo.doDrag(evt);}})(this),
false
);
---

Also have a look at :
<URL:http://www.jibbering.com/faq/faq_notes/closures.html#clObjI>


[Handle/Mask]

Thanks for your explanation, it's a bit clearer now.

Still browsing through those threads - thanks!

You're welcome, however there'll probably be lots of new information for
you, so be without fear; take your time while processing it, and enjoy!

Last, check:
<URL:http://groups.google.fr/group/comp....f0081d05ff/b5aab2f5e454bb92?#b5aab2f5e454bb92>


HTH and good night ;)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top