1

(new to JS, jQuery, & jqTree)

I am trying to override a method (JqTreeWidget.prototype.openNode) from one .js file (tree.jquery.js) in another (my own custom.js).

I've read that to override a js method in general, I just need to redefine it. So I am trying to do that on the method, and I think I am stuck on accessing the variable that has the original method (JqTreeWidget). I think the challenge is that the original method is in tree.jquery.js (source) that is separate from my own other custom.js file where I want to do the override.

The goal of this Question would be to allow me to write something like this in my custom.js (<reference to JqTreeWidget.prototype.openNode> would be the Answer to this Question):

var originalMethod = <reference to JqTreeWidget.prototype.openNode>;

// Override of originalMethod
<reference to JqTreeWidget.prototype.openNode> = function( node, slide ){
    // my code I want to happen 1st here
    changeAncestorHeightRecursively( node, true);

    // my code is done, and now I'm ready to call the original method
    originalMethod.call( this, node, slide );
}

I think that would be the most non-intrusive way to do the override, without actually hacking in to the tree.jquery.js source.

See my custom.js at http://codepen.io/cellepo/pen/LGoaQx The separate source tree.jquery.js is added externally in the JS settings of that codepen.

How can I get access (from within my custom.js file) to JqTreeWidget variable that is in the source file (tree.jquery.js)? Is it even possible? Is JqTreeWidget not in scope outside of tree.jquery.js, or is it not a global variable? I was hoping treeContainer.tree.prototype would have it, but I haven't had luck so far...

Thanks!

Community
  • 1
  • 1
cellepo
  • 4,001
  • 2
  • 38
  • 57
  • CodePen from above, [forked & updated with Accepted Answer here](http://codepen.io/cellepo/pen/zrQXKZ). – cellepo Feb 20 '16 at 02:50

2 Answers2

1

The prototype object can be obtained via:

jQuery.fn.tree("get_widget_class").prototype

Note that this is not a generalized solution for any jQuery plugin. This is something explicitly implemented by the tree plugin.

Dark Falcon
  • 43,592
  • 5
  • 83
  • 98
  • Looks like this indeed gets the prototype object, thanks! – cellepo Feb 20 '16 at 01:46
  • Note that the parameter "get_widget_class" is not intended to be replaced: Literally leave that in, and use the code in this Answer verbatim as-is. (I was confused at first thinking I needed to replace it with a CSS selector for my tree, which is not the case) – cellepo Feb 20 '16 at 01:47
  • Just curious: Mind explaining how ".fn.tree("get_widget_class")" works? Or do you have any API references for those methods? thanks – cellepo Feb 20 '16 at 01:48
  • 1
    `jQuery.fn` is where all jQuery plugins register their functions. It is basically the prototype of all jQuery objects. The rest was seen by reading the `tree.jquery.js` file. I am not aware of it being documented anywhere. – Dark Falcon Feb 20 '16 at 01:50
  • Cool thanks. I'm guessing after learning all this that you might have have narrowed in on the relevant part of tree.jquery.js by text searching it for "fn" or "$.fn". Nice – cellepo Feb 20 '16 at 02:01
  • Same CodePen from question, [forked & updated with this solution](http://codepen.io/cellepo/pen/zrQXKZ) – cellepo Feb 20 '16 at 02:49
0

I found this hacky workaround. But since it's a hack, I'd still prefer to find the Answer as posed in this Question (so please, continue to Answer with respect to the <reference to JqTreeWidget.prototype.openNode> I mentioned in the Question, thanks)...

As stated in this Question, the goal involves making it possible to override JqTreeWidget.prototype.openNode (from tree.jquery.js) externally in custom.js. As such, calls to changeAncestorHeightRecursively (my code) & JqTreeWidget.prototype.openNode would both be made from the override in custom.js, and tree.jquery.js source is not modified at all.

Workaround:

  1. Declare global var in html:

    <script type='text/javascript' language="javascript"> changeAncestorHeightRecursively = 1; </script>

  2. In custom.js, set the globar var to the function (the one I want to be called before JqTreeWidget.prototype.openNode):

    window.changeAncestorHeightRecursively = changeAncestorHeightRecursively;

  3. Call the global-var-referenced function at the beginning of JqTreeWidget.prototype.openNode (hack into tree.jquery.js):

    JqTreeWidget.prototype.openNode = function(node, slide) { // Only way I could figure out to get this to execute before the rest of this method // (global-var-referenced function in custom.js) changeAncestorHeightRecursively( node, true ); // Rest of original openNode code... }

This calls my code function from within tree.jquery.js, as opposed to calling the overridden method from within custom.js. So this is hacky because of the global var, and modifying tree.jquery.js source.

This will work for now, but hoping for a less hacky Solution as stated in this original Question... Thanks!

Community
  • 1
  • 1
cellepo
  • 4,001
  • 2
  • 38
  • 57
  • FWIW: This theoreticially has risks changeAncestorHeightRecursively being called before it is defined (as my custom.js is loaded last). But in reality, JqTreeWidget.prototype.openNode is only called upon user inupt. So the by the time that input happens, all js would be loaded since the user has to see the loaded page before inputting on it :) – cellepo Feb 20 '16 at 00:08