Looking for some fresh ideas: passing objects issue.

Started by Chief of Nothing, July 05, 2022, 10:07:40 AM

Previous topic - Next topic

Chief of Nothing

In my effort to refactor a "bit" of JavaScript to get SMF more up to date with modern practices so things like CSP's can be used I'm stalled by analysis paralysis and I can't think of the most effective way forward as I'm not a guru programmer like many here.

So what I'm seeking is some fresh input to hopefully help me see the way forward. The part I'm up to now is refactoring all the inline events (onclick etc) to event listeners (I know I've said that before but I had to start the whole project over). To help save having to write several hundred functions to add listeners to every element that requires one I figured I'd just write a generic function to add them by querying the page for a specific data-* tag that contained the function name and parameters etc (as a JSON object so more than one listener can be added per element) which was parsed by the generic function. This actually worked very well until, of course, it comes to passing objects themselves as a parameter (this, this.xxxx, document.xxxx etc).

Here's an SMF example of passing objects
<input type="checkbox" onclick="invertAll(this, this.form, \'' . $config_var['name'] . '[\');">

To get this information in a data-* tag this and this.form will be strings. With my skill level I've worked out that without using eval (which I won't do) I can only have a partial generic function and the only way to deal with adding event listeners for functions that require objects as parameters like the above is to single them out when parsing and run them through there own specific addEventListener so the required objects can be passed successfully. Am I correct in that thought?


Well, realistically, you'll be attaching something like data-selectable="all" to the tag to indicate that it is selectable and the scope is all of it.

Since you're then going to be looking for elements that match data-selectable (whether with jQuery or querySelector/All as necessary), you must by definition have the element in question - because you must have some form of "this" from the pass through you mention. If you have "this", you must be able to, by definition, navigate to whatever DOMElement contains the form.

The reality is that you're going to end up rewriting invertAll and friends anyway, you might as well not try to do the replumbing and just write the new version you're going to end up with as a complete replacement.

Do note that there is no published roadmap for including any of this in any future version so any such changes run the risk of not being included in a future version.

Chief of Nothing

Thanks Arantor,

That does make sense and I'll give it some testing.

I know there is no "roadmap" as such for this, but as I've mentioned before the devs, well at least one of them, has said they are interested and quite frankly SMF can not continue into the future with inline events like this anymore; it's 2022 now, not 1996. I'm also not worried if what I'm doing doesn't get included, I can at least have a more secured SMF.


this is possible while retaining current infrastructure

use querySelectorAll to select all relevant data attributes and add a click event listner which will be bound to invertAll

document.querySelectorAll('[data-selectable]').forEach(el =>
el.addEventListener('click', invertAll.bind(null, el, el.form, el.dataset.selectable));

The data attribute can then be the string of form element names.

This is untested.