2

I need to override onClick method in the Tree.js. Is there any common way to override dojo/dijit classes methods?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
BigWonder
  • 225
  • 1
  • 4
  • 18

2 Answers2

10

I'm a bit confused, since you were already doing this in the last question you posted.

You've got a few choices, depending on what you want to do.

Clobbering method stubs

In the case of true stubs like onClick, it's potentially as easy as clobbering that method on your widget instance.

Programmatically:

var myWidget = new dijit.Tree({
    ...,
    onClick: function(item, node, evt) {
        /* handler code here */
    }
};

Or declaratively (this is exactly the same as what you were doing in your last question):

<div dojoType="dijit.Tree" ...>
    <script type="dojo/method" event="onClick" args="item,node,evt">
        /* handler code here */
    </script>
</div>

Connecting to method invocations

In other cases, perhaps you need to do something whenever a given method gets called, in which case you could use the widget's connect method (which is a nicer version of dojo.connect that will automatically clear itself when the widget is destroyed). In that case you could do something like this:

Programmatically:

//execute the given function whenever myWidget's onClick method is called
myWidget.connect(myWidget, 'onClick', function(item, node, evt) {
    /* handler code here */
});

Declaratively, this can be done very similarly to the above, except instead of type="dojo/method", make sure you use type="dojo/connect"

<div dojoType="dijit.Tree" ...>
    <script type="dojo/connect" event="onClick" args="item,node,evt">
        /* handler code here */
    </script>
</div>

Note that when you connect like this, your code will execute after the method whose invocation you are connecting to. If you need to do something before, your best option is probably to dojo.declare your own extension to the widget. If you need to go that far, I'll elaborate, but I think you'll likely be set with one of the above options.

Edit #1: Connecting the dots (no pun intended...oh heck, yes it was)

Since it seems that my comment appended to my answer to the original question was somehow not clear enough, here's a code block modifying the original code in that question based on the simple two steps exactly as I explained in that comment. The only tiny wrinkle is that the arguments passed to _onClick are slightly different.

<div dojoType="dijit.Tree" ...>
    <script type="dojo/connect" event="_onClick" args="node,evt">
        /* handler code here. In this case, item is accessible via node.item */
    </script>
</div>

This solution may feel a bit sub-optimal since it involves connecting to a method that's suggested to be private. However, it's a way that should work regardless of whether openOnClick is true or not. If you are certain you're going to have openOnClick set to true, you could potentially write a single function, then connect it to both onClick and onOpen instead (both get passed the item, then the node).

Edit #2: Common functions, connecting programmatically

To answer your follow-up questions, I'd like to actually address them in reverse order - since if you are interested in connecting programmatically, it will actually make the other question easier to answer.

So first, to answer your connect question: you definitely don't want to be using dojo.byId, as that's not giving you the Tree widget, that's giving you some DOM node (probably the topmost) associated with the widget. As a general rule, dojo methods don't know anything about dijit stuff.

What you do want to be doing, is what I suggested above. Here it is applied as per the code you attempted. Also note that onClick has a capital C - another general rule: widget events use camel case notation, as a way to distinguish them from plain DOM events which don't.

var mytree = dijit.byId("mytree");
mytree.connect(mytree, "onClick", function(item) {
    /* ... */
});

Now, to take that a step further and resolve your other inquiry, if you want to bind some common functionality to onClick and onOpen and onClose, you could define a function first, then connect it to both. This is one of the many things that makes JavaScript awesome - the availability of functions as first-class objects that can be easily passed around.

function handleClick(item) {
    /* do stuff here.
    Inside this function you can assume 'this' is the tree,
    since connect will ensure it runs in-context.
    */
}
var mytree = dijit.byId("mytree");
mytree.connect(mytree, "onClick", handleClick);
mytree.connect(mytree, "onOpen", handleClick);
mytree.connect(mytree, "onClose", handleClick);

Now there's one important remaining question: where should we do this? The best place is likely inside a function passed to dojo.ready (or dojo.addOnLoad, same thing, ready was added as a synonym in 1.4) so that it will run only after:

  • The DOM is parsed by the browser
  • All dojo.required modules have loaded
  • If you set parseOnLoad: true in djConfig, all widgets defined in the document's HTML will already be instantiated

So, sometime after your dojo.requires, in script, you'd do this:

dojo.ready(function() {
    /* code from previous example goes here */
});

Give it a shot.

Also, if you're interested in a bit of reading, I've actually written about a couple of topics I touched on in this edit:

Community
  • 1
  • 1
Ken Franqueiro
  • 10,559
  • 2
  • 23
  • 40
  • The problem that i have that onClick even is not fired at all. I cannot catch it. If you look in the Tree code it says something like that: If node expandable expand it, else do something. I need to have if not expandable expand and do something. When openOnClick="true" and node is expandable I cannot catch onClick event. So far nothing that you suggested worked for me. – BigWonder Jan 28 '11 at 00:31
  • In that case, (1) you didn't really ask the question you're actually asking, and (2) I answered the question you *are* asking in my answer to your *other* question (which I linked at the top of this answer). To repeat both answers, you should be able to use the connect approach given here to connect to the Tree's `_onClick` method to do what you want. – Ken Franqueiro Jan 28 '11 at 00:44
  • Since we already know what question I'm asking. Would you please just put some line of code in response. Considering that my code is:
    What exactly should I write? Sorry for making it not clear.
    – BigWonder Jan 28 '11 at 00:55
  • I've added a sample doing exactly what I said in the comment on the other answer - I'm really not sure what was so hard to follow... But I'm still confused, since on that thread you said you changed `openOnClick` to `false` and that would also solve your problem. – Ken Franqueiro Jan 28 '11 at 01:20
  • First if you don't want to answer don't answer. Second I thought that it solve my problem because I could catch event by clicking on node and expand node by clicking on the "+" sign. But enevtually I need to have both functionalities. The reason I'm asking again and again because I cannot connect your answers in something I can use. I have 0 web experience and just two words answer "use _click" doesn't help. Again you don't have to answer. – BigWonder Jan 28 '11 at 01:34
  • I already did answer, see the "Edit" portion of the answer above. ;) Sorry for giving you a hard time, but please do realize that people answering questions can get equally frustrated when it feels like a decent explanation plus a simple connect-the-dots has been turned down in favor of just asking for the code to be handed out. I see it happen more and more often, so I apologize for letting the frustration out here. – Ken Franqueiro Jan 28 '11 at 01:45
  • Now I saw the Edit portion it really helped. I create three separate callbacks: It is perform functionality I need. MY questiont can it all this logic combined in one call? Aslo when I'm trying to use dojo.connect(dojo.byId("mytree"), "onclick",... it doesnt work. Any idea why? Thank you. – BigWonder Jan 28 '11 at 03:01
  • I've added "Edit #2" in response to those questions; take a look. – Ken Franqueiro Jan 28 '11 at 04:26
  • Thank you. This is fantastic explanation. I have some further questions if you don't mind. In one case I see I can pass only one parameter to the function, other case two or three. How many there are ,and how I access there values. For example I want to know what even had happens or what are the values of my node. How do I access it? May be I should post it as another question? – BigWonder Jan 28 '11 at 18:59
  • That question is probably easy to answer, if I've interpreted the question correctly. Have a look at the Event Summary section of the API doc page for Tree: http://dojotoolkit.org/api/dijit/Tree - it tells you what parameters get passed to each exposed event. It's up to you whether you actually want/need to use all of them though. If you do have additional broader questions, yes I'd suggest perhaps asking as a new question, as this "answer" has gotten kind of long-winded by now :P – Ken Franqueiro Jan 29 '11 at 00:10
1

You could use:

dojo.connect(tree, 'onClick', function(item) {
    /** Your Action **/
});
Caleb
  • 5,084
  • 1
  • 46
  • 65
taranhb
  • 26
  • 1