Page MenuHomePhabricator

mediawiki.util: Deprecate mw.util.$content in favor of mw.hook( 'wikipage.content' )
Open, MediumPublic

Description

mw.util.$content from module mediawiki.util seems to be needless.

	$( function () {
		mw.util.$content...
	} );

can be replaced by

	mw.hook( 'wikipage.content' ).add( function ( $content ) {
		$content...
	} );

mw.hook() is necessary to support Live Preview.

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 22 2014, 3:09 AM
bzimport set Reference to bz63466.

Change 123559 had a related patch set uploaded by Gerrit Patch Uploader:
Deprecate mw.util.$content

https://gerrit.wikimedia.org/r/123559

Closing as won't fix per discussion between Daniel Friesen and myself at https://gerrit.wikimedia.org/r/123559.

Although the naming is unfortunate, these are different things for different use cases.

mw.hook( 'wikipage.content' ) is to get a reference to #mw-content-text (the true wiki page content, no skinning around it). It is different from $( '#mw-content-text' ) in that:

  • It can be asynchronous (you can register the hook without needing to explicitly wait for document-ready).
  • It is more semantically correct if your intent is "change content" because it will re-fire when the content changes dynamically (e.g. after saving an edit with VisualEditor, or when ajax live previewing wikitext, or in some hypothetical "ajax navigation" feature).

mw.util.$content is to get a reference to the body content wrapper (the element containing #mw-content-text, usually indicated by .mw-body). Because mw.util.$content has been around since before mw.hook, it is likely that there are existing uses out there that would benefit from using mw.hook instead. However there remain uses for mw.util.$content where mw.hook is not a suitable alternative.

Having said that, I still think we should deprecate mw.util.$content because it sucks (retrieving its value is tricky because it is asynchronously initialised without a clear callback for when that happens). However until we have an alternative for it, let's keep it.

Ideally we'd just mandate that all skins follow the convention to use mw-body class and then just document that as an API (similar to how addPortletLink's html structure has become more or less skin independent, though not quite there yet) that people use by waiting for domready and querying mw-body or mw-body-primary.

Thanks for explanation.

What about a new hook 'wikipage.body'?

In mediawiki.page.startup.js fire
mw.hook( 'wikipage.body' ).fire( mw.util.$content ) );

In mediawiki.notification.js replace
$( function () {

		mw.util.$content...

} );
by
mw.hook( 'wikipage.body' ).add( function ( $body ) {

		$body...

} );

Change 123559 abandoned by Krinkle:
Deprecate mw.util.$content

Reason:
Superseded by I30bdd893e0a0a340076.

https://gerrit.wikimedia.org/r/123559

Thanks for explanation.

What about a new hook 'wikipage.body'?

If there's a need for something subscription/offering based in that way, I think that would be useful yes.

However, I think the existing use-cases for mw.util.$content need/want something direct and synchronous.

But, based on how we solved the Notifications use case, with a dedicated interface contract to the skin, we can probably do the same for other use cases. I think that's better than the generic mw.util.$content which is quite difficult to use right now (because you have to wait for $() before it exists), and also inverts the responsibility. The module placing stuff in the body should not be the one deciding where it goes, unless it is the skin code doing it.

Re-opening this (also in light of restricted T203549). Let's identify what uses/needs it, and then migrate them to either use mw.hook('wikipage.content') for cases where they need to find things in the content, or to other mechanisms like we did for Notifications (if they need to add something).

I don't mind keeping it long-term or providing wikipage.body - if we find a need for that.

Aklapper subscribed.

@Fomafix: Hi, I'm resetting the task assignee due to inactivity. Please feel free to reclaim this task if you plan to work on this - it would be welcome! Also see https://www.mediawiki.org/wiki/Bug_management/Assignee_cleanup for more information - thanks!

Change 766859 had a related patch set uploaded (by Krinkle; author: Krinkle):

[mediawiki/extensions/InlineCategorizer@master] Remove needless use of mw.util.$content

https://gerrit.wikimedia.org/r/766859

Change 766867 had a related patch set uploaded (by Krinkle; author: Krinkle):

[mediawiki/extensions/CirrusSearch@master] ext.cirrus.serp: Use \"wikipage.content\" instead of mw.util.$content

https://gerrit.wikimedia.org/r/766867

Change 766867 merged by jenkins-bot:

[mediawiki/extensions/CirrusSearch@master] ext.cirrus.serp: Use \"wikipage.content\" instead of mw.util.$content

https://gerrit.wikimedia.org/r/766867

Change 766859 merged by jenkins-bot:

[mediawiki/extensions/InlineCategorizer@master] Remove needless use of mw.util.$content

https://gerrit.wikimedia.org/r/766859

@Krinkle It seems this has been done for all extensions now ? Which means that only gadgets and userscripts are still users. Do we investigate the userscripts or do we simply mark as deprecated and then investigate what needs it ?

@TheDJ Yeah, we could mark it as deprecated, do a Tech-News round, track the usage in Grafana/mw-js-deprecate and maybe do a few Global Search queries ourselves to help mitigate a few.

Tacsipacsi subscribed.

hu:MediaWiki:Gadget-warning.js uses this in an event handler to put a DOM element on the top of the page. The wikipage.content hook is not a good replacement, for two reasons:

  • (mildly bad) it’s asynchronous, and can be fired multiple times. Since the event handler can also run multiple times, it would require a global state to ensure that not more than one hook listener is active at a time.
  • (quite bad) it may be fired with several elements, not only mw.util.$content (e.g. DiscussionTools previews fire it too). Adding the DOM element to all sorts of parser output blocks is definitely not what the user wants to see.

What should be the path forward?