[TW5] require a core widget, modify its code and then use — OR — hijacking core functions

136 views
Skip to first unread message

Tobias Beer

unread,
Dec 17, 2015, 2:58:53 PM12/17/15
to tiddly...@googlegroups.com
I was wondering if it was possible for my own (widget) code to...
  1. require some core widget
  2. overwrite one of the functions of the required module
  3. use that to create instances for my own widget
Possible?

Or do I have to create a custom widget / overwritten one?

~

Alternatively, is there any chance to hijack any core (widget's) prototype functions?
If so, how would one do it?

Specifically, I'd like to hijack triggerPopup from the ButtonWidget.

Best wishes,

Tobias.

Jeremy Ruston

unread,
Dec 23, 2015, 11:27:20 AM12/23/15
to tiddly...@googlegroups.com
Hi Tobias

It is possible to override widget methods. The following retrieves the constructor for the button widget.

require("$:/core/modules/widgets/button.js”).button

From that, you can access the prototype and override any methods you want.

Obviously, this is a technique of last resort…

Best wishes

Jeremy.

On 17 Dec 2015, at 19:58, Tobias Beer <beert...@gmail.com> wrote:

I was wondering if it was possible for my own (widget) code to...
  1. require some core widget
  2. overwrite one of the functions of the required module
  3. use that to create instances for my own widget
Possible?

Or do I have to create a custom widget / overwritten one?

Alternatively, is there any chance to hijack any core (widget's) prototype functions?
If so, how would one do it?

Specifically, I'd like to hijack triggerPopup from the ButtonWidget.

Best wishes,

Tobias.

--
You received this message because you are subscribed to the Google Groups "TiddlyWikiDev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywikide...@googlegroups.com.
To post to this group, send email to tiddly...@googlegroups.com.
Visit this group at https://groups.google.com/group/tiddlywikidev.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywikidev/00d7769d-4541-46b3-a90c-adbfb051b1fd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tobias Beer

unread,
Dec 28, 2015, 3:09:06 PM12/28/15
to TiddlyWikiDev
Hi Jeremy,
 
Obviously, this is a technique of last resort…

I agree and I would not ask for how to do it would I see another way.


Popup.prototype.show = function(options) {...}

...so as to allow absolutely positioned popups.

Best wishes,

Tobias. 

Devin Weaver

unread,
Jan 12, 2016, 1:08:06 PM1/12/16
to TiddlyWikiDev
My take: Avoid modifying (hyjacking) core code. Instead write a new class that extends the one you wanted to modify and use that. If you are attempting to change the core functionality I would recommend cloning the repo and make the change in the core code on you own branch. If it is something worth while it could be submitted as pull request maybe behind a config option.

Tobias Beer

unread,
Jan 12, 2016, 2:00:05 PM1/12/16
to TiddlyWikiDev
Hi Devin,

Thing is, I don't see a point to reinventing the wheel or duplicating entire modules for a mild change / update, e.g. to the ButtonWidget, the ListWidget ...or a PopupMechanism.

So, if a given pull request is not being accepted then I am not at all inclined to provide a standalone solution, a fork duplicating most all code. Instead, I will hijack the very bit of the core component I have to in order to handle my case — insofar as that is possible — and otherwise pass the call down to the core handler.

This is not about me finding a solution that works for me, but about shipping plugins that at times need enhanced capabilities. Since waiting for the core to move into a desired direction is not always fruitful, whatever the reasons may be... I have yet to see why hijacking would not be one way to go about it.

Best wishes,

Tobias.

Devin Weaver

unread,
Jan 12, 2016, 3:09:34 PM1/12/16
to tiddly...@googlegroups.com
I think in my head when I read your description I was thinking object inheritance and polymorphism to manage the custom code. For example a normal widget plugin would inherit from Widget. But in the case of enhance functionality a child of Widget could be created and then your plugin would use that instead.

For example if your writing a new widget called MyWidget but needs functionality from Widget that doesn't exist in core then maybe something like this:

function SuperWidget() {
 
Widget.apply(this, arguments);
}
SuperWidget.prototype = new Widget();
// Enhance Widget as needed here

function MyWidget() {
 
SuperWidget.apply(this, arguments);
}
MyWidget.prototype = new SuperWidget();

But maybe my understanding is out of sync.

Tobias Beer

unread,
Jan 12, 2016, 3:25:14 PM1/12/16
to tiddly...@googlegroups.com
Hi Devin,

I think in my head when I read your description I was thinking object inheritance and polymorphism to manage the custom code.

In a way, yes, it is polymorphism... only just that through hijacking I put my code ahead of the core and decide when to let the core take over. Have a look at what I'm doing to Popup in tobibeer/appear.

And here's the issue of wishing for that behavior to be part of the core:

#2128 allow absolutely positioned popups to actually be anchored at the button

Best wishes,

Tobias.

Devin Weaver

unread,
Jan 13, 2016, 10:01:53 AM1/13/16
to TiddlyWikiDev
Looking at your code I would push the hackery as far away as possible. Here is a stab at how I would approach the same problem https://gist.github.com/71a1e6b22104ede5f6e7 (Google Groups just had a tantrum attempting to copy/paste the code here. Use the link above. (╯°□°)╯︵ ┻━┻ ).

Tobias Beer

unread,
Jan 13, 2016, 11:48:14 AM1/13/16
to TiddlyWikiDev
Hi Devin,
 
Looking at your code I would push the hackery as far away as possible. Here is a stab at how I would approach the same problem https://gist.github.com/71a1e6b22104ede5f6e7 (Google Groups just had a tantrum attempting to copy/paste the code here. Use the link above. (╯°□°)╯︵ ┻━┻ ).

Thanks a lot for taking the time and provide this alternative code.
I'm always keen to learn good coding practice.

I very much agree that it looks much cleaner to
factor all the popup stuff out into its own utils module.
And, I believe I can do the very same with my codebase, as well.

Other than that, though, your code basically does the same thing:
overwrite the core popup handler.

However, besides being encapsulated in its own module,
it appears to be less efficient though, since you're not only
calculating all things twice but also writing to the store twice,
once the core handler and then the custom code of EnhancedPopup.

Best wishes,

Tobias.

Devin Weaver

unread,
Jan 13, 2016, 12:41:13 PM1/13/16
to tiddly...@googlegroups.com
Yeah the core Popup object failed at good abstractions. That is unfortunate. There isn't any way to avoid the double storage save because DOMElement.offsetLeft properties are read only so you cannot change those. The only option would be to copy the logic which IMHO is worse then storing twice. Keeping the two in sync would be a nightmare.

Also I had thought that the core rendering engine would delay reactions to storage changes till next tick allowing changes to finish and the call stack to exhaust. That way multiple changes to a tiddler only trigger a final DOM render. Does the system not do this? Seems that would be a huge performance issue if it attempted to update the DOM at every step of the call stack.

Tobias Beer

unread,
Jan 13, 2016, 12:53:22 PM1/13/16
to tiddly...@googlegroups.com
Hi Devin,
 
Also I had thought that the core rendering engine would delay reactions to storage changes till next tick allowing changes to finish and the call stack to exhaust. That way multiple changes to a tiddler only trigger a final DOM render. Does the system not do this? Seems that would be a huge performance issue if it attempted to update the DOM at every step of the call stack.

That's correct. I imagine the impact here being rather negligent, performance-wise.

The only option would be to copy the logic which IMHO is worse then storing twice. Keeping the two in sync would be a nightmare.

Keeping track of and keeping up with core changes would indeed probably be a challenge / source of plenty issues.

I presume you did some testing so as to verify that your code actually works.
I think I'm inclined to update tobibeer/appear to incorporate the refactoring.
Well, will have to do tests anyway.

Ok that I leave a mention for @sukima in the version history?

Best wishes,

Tobias.

Tobias Beer

unread,
Jan 13, 2016, 12:59:10 PM1/13/16
to tiddly...@googlegroups.com
Hi again,
 
Keeping track of and keeping up with core changes would indeed probably be a challenge / source of plenty issues.

I'm actually not sure which way is better:
  1. overwrite the core function entirely
    • my current code approach
    • this means, so long as the changes are traceable I can almost compare the core code to mine, line-by-line
  2. only put the codebits that are needed for the "enhanced" functionality
    • your code approach
    • means that I will need to test and verify if and what changes to the core possibly have an impact to my code
      • the cross referencing here may actually not be easier than for 1.
        • since I need to validate two code sources, rather than one
Best wishes,

Tobias.

Devin Weaver

unread,
Jan 13, 2016, 5:17:46 PM1/13/16
to TiddlyWikiDev
((Gods Google Groups is a PITA. What's wrong with markdown?!))

Back to regularly scheduled program…

In the case of option one, the coder in me says that it would be better to use some kinds of module system like [git clone/branch/manage with npm] or [git submodules/symlinks].

I think Sandi Metz would argue that meta-programing is best handled through object abstractions (option two) but I am ill-equipped to put words in her mouth.

There is a third option… Fix the core popup code to have actual useful abstractions so extending the code would not be such a hack in the first place.

I like option three the best.

Tobias Beer

unread,
Jan 13, 2016, 8:27:42 PM1/13/16
to TiddlyWikiDev
Hi Devin,
 
There is a third option… Fix the core popup code to have actual useful abstractions so extending the code would not be such a hack in the first place.

I like option three the best.

I have no practical clue what that looks like,
but it does indeed sound best.

Best wishes,

Tobias.
Reply all
Reply to author
Forward
0 new messages