PDA

View Full Version : Can anyone tell me how to create custom events??



shachi
09-16-2006, 07:03 PM
Hello all,
I hope whoever reads this post has already understood my needs. I want information(or help) about creating custom events. If anyone has enough knowledge about it please share with me and others.
Thanks.

Twey
09-16-2006, 07:06 PM
var prop = 3;

function check() {
if(prop != check.old)
prop.onchange();
}

check.old = prop;

window.setInterval(check, 100);

prop.onchange = function() {
alert("Property change event has been fired! Property is now: " + this);
};

jscheuer1
09-16-2006, 07:40 PM
Looks like the event would fire every 100ms once the prop value had changed.

Oh, and:


Error: prop.onchange is not a function
Source File: file://localhost/ . . . /test/prop_h.htm
Line: 11

Twey
09-16-2006, 08:07 PM
You are, of course, quite right.
var prop = 3;

var onchange = {
'prop': function() {
alert("Property change event has been fired! Property is now: " + this);
}
};

function check() {
if(prop != check.old) {
check.old = prop;
if(onchange['prop'])
onchange['prop'].apply(prop);
}
}

check.old = prop;

window.setInterval(check, 100);

shachi
09-17-2006, 05:45 AM
Twey,jschuer1: Can you tell me what this code does(of course, I know it demonstrates a custom event) but how to use it?? Thanks.

jscheuer1
09-17-2006, 06:21 AM
It sets up a polling function that checks for a condition (a change in the variable prop's value, in this case) every 100ms. When it detects a change it executes a function which, in this case pops up the alert. You could adapt it to check for any condition and to execute anything when that condition is met. Polls do not have to be continuous. Nor must they use such advanced object oriented coding. If you have a look at this post:

http://www.dynamicdrive.com/forums/showthread.php?t=13003

It gives a more practical example of a poll using a more mundane coding style. It is a poll that only begins when something else is initiated and that can therefore end when its sought for condition is found and acted upon.

Twey
09-17-2006, 10:09 AM
Nor must they use such advanced object oriented coding.The idea was that in a real-world setting, one could have a list of properties to monitor, and add/remove them dynamically.

jscheuer1
09-17-2006, 11:06 AM
The idea was that in a real-world setting, one could have a list of properties to monitor, and add/remove them dynamically.

I wasn't complaining. I could learn a thing or two from you as regards this type of javascript. I was just saying, for shachi's benefit, that it doesn't have to start out like that when you are first trying to understand the basic concept.

Twey
09-17-2006, 11:11 AM
I was just making a note as to why I did it :)

shachi
09-17-2006, 07:22 PM
jscheuer1, Twey: I still don't get a thing(may be because if my low experience in javascript) can you give me a little simple example?? I am all :confused:

mwinter
09-17-2006, 07:29 PM
I hope whoever reads this post has already understood my needs.

It's certainly clear that you want to dispatch custom events, but the question is where. What are these events? Are they to be dispatched into the document tree, or are they events used by user-defined objects?



I want information(or help) about creating custom events.

I'd like more information from you, first. :)


As for the whole polling idea, I wouldn't recommend it. For a start, a property might change many times within 100ms and polling wouldn't necessarily detect any of those changes. If an event should be generated when modifying a property, use methods to manage that property and have the setter dispatch the event:



function MyObject() {
var data,
listeners = [];

function dispatchEvent(event) {
for (var i = 0, n = listeners.length; i < n; ++i)
listeners[i].call(this, event);
}

this.addEventListener = function(listener) {
if (!listeners.contains(listener)) listeners.push(listener);
};
this.removeEventListener = function(listener) {
listeners.remove(listener);
};

this.getData = function() {
return data;
};
this.setData = function(value) {
var previous = data;

data = value;
dispatchEvent.call(this, {oldValue : previous, newValue : value});
};
}

That omits supporting code, but it shows one approach. It can also be tweaked to allow different types of event if necessary.

Mike

shachi
09-18-2006, 05:55 AM
but the question is where. What are these events? Are they to be dispatched into the document tree, or are they events used by user-defined objects?

I want to know just about creating custom events like ondragend and ondragstart. About where they will be dispatched, I have no idea what you mean.

jscheuer1
09-18-2006, 06:32 AM
Well then, as I think Mike said, at least in part, and what I'd recommend is - simply fire off a function when those events occur in your code. What you are asking implies that you have a function that initializes the drag and one that ends it, something like:


function initdrag(){
code to drag an element here
}

function stopdrag(){
code to stop dragging here
}

just add:


function initdrag(){
ondragstart();
code to drag an element here
}

function stopdrag(){
ondragend();
code to stop dragging here
}

Then those functions will fire whenever (one when) dragging starts and the other when dragging ends. What you put in those functions and what arguments you pass to them is entirely up to you.

shachi
09-18-2006, 08:30 AM
jscheuer1: does that mean that I make some events like onResponseRecieve = doSomething() the same way?? Thanks for clearing the point. :)

jscheuer1
09-18-2006, 08:49 AM
Well, let's not get too carried away here. :)


onResponseRecieve = doSomething()

is a little vague. However, as written, it implies:


var onResponseRecieve = doSomething();

All that means is, if doSomething() is defined as a function, then:

onResponseRecieve()

is now an equivalent function.

shachi
09-18-2006, 09:16 AM
Thanks, jschuer1. Can I also do this:

someobject.prototype.somevariable = somefunction();

??

jscheuer1
09-18-2006, 10:25 AM
Not exactly, at least not that I can see. I've seen:


someobject.prototype.somevariable = function(){alert('here');};

But, trying to assign a prototype function from an existing function doesn't seem to work.

shachi
09-18-2006, 12:22 PM
Thanks again. But then what if I want to make something like object(object2bedragged).ondragstart = something??

mwinter
09-18-2006, 02:47 PM
someobject.prototype.somevariable = somefunction();

Not exactly, at least not that I can see.

No, not exactly, but exceedingly close:



someobject.prototype.somevariable = somefunction;

though it should be noted that it wouldn't be the prototype property of an object as objects don't have prototype properties: it would be of the constructor function used to create that object (and others like it).


Calling a function, as shown in the original snippet, is viable if, and only if, that function returns a value. For example, somefunction might be a factory for event listeners, so it could return a reference to a function.

Mike

shachi
09-18-2006, 03:14 PM
mwinter, jscheuer1: So will this work then??



var object = {
dragstart: function(){
//dragging code here.
}
}
object.dragstart = foo;


mwinter: how come objects do not have prototype properties?? I have seen something like Array.prototype.indexOf in which Array is an object. I am not quite clear of what you said, could you please simplify it for me?? Thanks. :)

Twey
09-18-2006, 05:35 PM
So will this work then?Should do.
how come objects do not have prototype properties?? I have seen something like Array.prototype.indexOf in which Array is an object.No, Array is a constructor function. Consider:
function A() {}

A.prototype.b = "c";

A.b; // undefined

var d = new A();

d.b; // "c"

shachi
09-18-2006, 06:03 PM
Oh, that's the point. Thanks Twey.

Ok(sorry if I have a lot of questions and I am bothering you too much, I am just a newbie you know), So If I want to make something like somehtmlelement.ondragStart = foo; do I need to make a new constructor for the onDragStart event??

Twey
09-18-2006, 07:01 PM
You're not allowed to append custom properties to DOM nodes. Most browsers will let you get away with it, but you shouldn't.

No, all you need is a single separate object to hold the function(s) using something that can be identified with the HTML element as a key.

mwinter
09-19-2006, 11:04 AM
So will this work then??



var object = {
dragstart: function(){
//dragging code here.
}
}
object.dragstart = foo;


What do you expect it do?

A new object will be created as if "new Object()" were used. A property will be created on that object named dragstart with a function reference as its value. A reference to this newly-created object will be assigned to the variable, object.

In the statement that followed, the dragstart property of the object refered to by the variable, object, will be replaced with the value of the variable, foo.

If that's what you expected, then yes, it "works".



how come objects do not have prototype properties??

They just don't. The prototype object is an inheritance mechanism, so prototype objects are a property of functions. When a function is used as a constructor with the new operator, the prototype property of that function is used to create the internal prototype chain of the created object.



I have seen something like Array.prototype.indexOf in which Array is an object.

As Twey wrote, Array is a function. The other built-ins like Object, RegExp, Date, String, Number, Error, and Function are also functions. They are used to create objects of their respective types.




You're not allowed to append custom properties to DOM nodes. Most browsers will let you get away with it, but you shouldn't.

I think you overstate that. DOM objects are host objects, therefore their behaviour is determined by the host. That does mean, in theory, that no new properties can be created on those objects, and it's not really necessary to do so (though it can simplify things). However, to say that "you're not allowed to" is going too far, I think.



No, all you need is a single separate object to hold the function(s) using something that can be identified with the HTML element as a key.

Objects cannot, in general, act as "keys". A "key" is simply a property name, and as such, it is a string. When converting objects to strings, most return values from the toString method are identical. Whilst some objects could be given toString methods that return unique values, that won't work for host objects. It would be necessary to use a user-defined collection that can handle objects properly.

Mike

Twey
09-19-2006, 04:59 PM
Objects cannot, in general, act as "keys". A "key" is simply a property name, and as such, it is a string.Hence:
something that can be identified with the HTML element as a key.Such as an ID, for example.

mwinter
09-19-2006, 06:32 PM
something that can be identified with the HTML element as a key.

Such as an ID, for example.

Sorry, I misread you. The end of the sentence, "with the HTML element as a key" stood out.

Mike

shachi
09-20-2006, 06:24 PM
Ah, thanks mwinter and Twey. Even with all your descriptions I am still confused about this. Ok, let me try to explain what I understood(just a simple example of custom events).



function foo(){
this.onCreate = function(){}
this.onCreate();
}
var testobj = new foo();
testobj.onCreate = doSomethingFunny;
function doSomethingFunny(){
alert("Why did the chicken cross the road?? Becuase she wanted to get to the other side!!");
}


Sorry for asking the same question again and again and again but I am not very clear about this. Please accept my apologies. :(

mwinter
09-20-2006, 07:45 PM
function foo(){
this.onCreate = function(){}
this.onCreate();
}
var testobj = new foo();
testobj.onCreate = doSomethingFunny;
function doSomethingFunny(){
alert("Why did the chicken cross the road?? Becuase she wanted to get to the other side!!");
}

You couldn't use that, exactly. The constructor function (foo) would have finished executing before you could replace the onCreate property. You could either pass the listener as an argument to the constructor:



function Foo(callback) {
/* Do stuff... */

if (callback) callback.call(this);
}

var object = new Foo(function() {
alert('Object created!');
});

or, you could move initialisation into a separate function to be called by client code:



function Foo() {}
Foo.prototype.initialise = function() {
/* Do stuff ... */

if (this.oncreate) this.oncreate();
};

var object = new Foo();
object.oncreate = function() {
alert('Object created!');
};

object.initialise();

Mike

shachi
09-21-2006, 10:28 AM
mwinter: I would use the second one. So do I make other events the same way too??

mwinter
09-22-2006, 02:07 PM
So do I make other events the same way too??Maybe. You still haven't described the problem you're trying to solve, so it's hard to say.

Mike

shachi
09-22-2006, 03:17 PM
Well, I don't actually have a problem. :) I just wanted to know how to create custom events.

mwinter
09-22-2006, 03:47 PM
Well, I don't actually have a problem. :)

I didn't say you did. I wrote: "the problem".



problem n

something or someone that is difficult to deal with.
a puzzle or question set for solving.
Maths a statement requiring a solution usually by means of several operations.






I just wanted to know how to create custom events.

But you never described whether (and how) those events are supposed to interact with the host, or if they are meant for client code.

I asked two questions in my first post in this thread and you didn't answer them. If you still don't understand what I mean by dispatch, pick up a dictionary.

You might think that the question you ask actually has a definitive meaning. It doesn't, and until you elaborate (a lot), you may, or may not, get a relevant answer. What I have posted so far in this thread has been in response to other questions or suggestions raised during the discussion. I haven't once attempted to respond to the thread itself because I don't know what you're really after.

Mike

shachi
09-22-2006, 05:13 PM
Well then, let me describe fully what I want(I'll try my best). Ok, so I have seen those cool libraries(like YUI and even dojo) using customevents like onMenuCollapse or onDragAreaEnter so I wanted to learn how to create them for my own uses(like onResponseRecieved, onSent ...) and that's why I started this thread. I know what dispatch is(similar to realeasing) but I didn't understand what you meant by:



Are they to be dispatched into the document tree, or are they events used by user-defined objects?


So, now are you clear on my point?? Thanks again.

mwinter
09-22-2006, 06:54 PM
OK, the next consideration is should these events have multiple handlers? Using event properties:



myObject.onevent = function() {};

makes allowing several functions listen for the same event a little awkward.

Expanding on the first post I made, you could create an object based around the following template:



function MyObject() {
/* This object literal contains the different event types that
* you want your object to have. The value of each property is
* an array object reference: the array acts as a simple list to
* store each added listener.
*/
var events = {
create: [],
'drag-enter': [],
'drag-leave': []
};

this.dispatchEvent = (type, event) {
var listeners = events[type];

for (var i = 0, n = listeners.length; i < n; ++i)
listeners[i].call(this, event);
};

this.addEventListener = function(type, listener) {
var listeners = events[type];

if (listeners.indexOf(listener) == -1) listeners.push(listener);
};
this.removeEventListener = function(type, listener) {
var listeners = events[type],
index = listeners.indexOf(listener);

if (index != -1) listeners.splice(index, 1);
};
}

For maximum compatibility, you'd need to define some of those methods used. See the code in my remedial.js (http://mwinter.webhop.info/dd/pearldoves/remedial.js) for examples (and per-specification implementations).

Client code would do something like:



var object = new MyObject();

object.addEventListener('create', function(event) {
/* Do stuff */
});

You would do something like:



MyObject.prototype.initialise = function() {
/* Do stuff */

/* Dispatch the create event: */
this.dispatchEvent('create', {object: 'state'});
};

The second argument to the dispatchEvent can be anything you like, but whatever it is, it should represent details about the event and the state of the object. If there is no state information to send, you could either pass null or an object ("new Object()" or "{}").



I didn't understand what you meant by:



Are they to be dispatched into the document tree, or are they events used by user-defined objects?


The potential confusion comes from the fact that one can create events like the click event. You can populate that with information about the event and hand it to the browser. The browser would then call click event listeners just like it would had the user clicked on an element. What you want to do is allow client code (scripts that would use an object you wrote) to listen for actions that your code performs.

Mike

shachi
09-28-2006, 05:34 PM
mwinter: Aha, now I seem to be getting something about this but I still cannot "fully" get the MyObject part maybe because there are a lot of things I don't know about(like the call property and splice and ...)



What you want to do is allow client code (scripts that would use an object you wrote) to listen for actions that your code performs.


What if I want to create an event called document.ontripleclick instead of listening to any object I wrote??

Sorry for the late post by the way but I had a lot of school works.