XF 2.2 Migrating to native JavaScript in XenForo 2.3

digitalpoint

Well-known member
So rather than clog the boosting performance thread, I'm going to drop questions here as they come up...

Let's say I have this for XF 2.2:
JavaScript:
this.$target.nextAll('input[name="payload"]').val(JSON.stringify(payload));
this.$target.closest('form').find('.formSubmitRow button').removeClass('is-disabled').prop("disabled", false);
$('#webauthn_verify .status').html($('#webauthn_verify').data('verified'));

And then this for XF 2.3:
JavaScript:
this.$target[0].parentElement.querySelector('input[name="payload"]').value = JSON.stringify(payload);
let element = this.$target[0].closest('form').querySelector('.formSubmitRow button');
element.classList.remove('is-disabled');
element.disabled = false;
document.querySelector('#webauthn_verify .status').innerHTML = document.getElementById('webauthn_verify').dataset.verified;

BTW, I haven't actually tested it yet, so ignore the fact that there probably are bugs. That being said, my question is abuot this.$target. In 2.3 I assume we still have it, and I'm thinking I'll probably have to go back to remove the [0] when referencing it since in 2.2 it's just dropping it out of jQuery and getting just the element.

TL;DR:
Is there a way to reference a this.$target element that works in both 2.2 and 2.3?
 
XF 2.3 now uses this.target rather than this.$target.

One approach is:

JavaScript:
const target = this.$target ? this.$target[0] : this.target
 
XF 2.3 now uses this.target rather than this.$target.

One approach is:

JavaScript:
const target = this.$target ? this.$target[0] : this.target
What if I were to give the handler a this.target now and then set that within the init method and reference this.target now within all the other methods? Basically would be easier to later drop support for 2.2 because I only had to remove a line of code in the init if that would work. I know it would work in 2.2, but just wondering if there would be any gotchas like 2.3 throwing an exception because this.target was set somewhere unexpected.

Something like this in the init method of the handler:
JavaScript:
if(!this.target)
{
    this.target = this.$target[0];
}
 
Does the XF.ajax() method in 2.3 have the ability to run a request synchronously if needed?

In 2.2 you can do it by calling this before XF.ajax():
JavaScript:
$.ajaxSetup({
    async: false
});

This particular use case is when guest page caching is enabled and we need to fetch a CSRF token before any other AJAX runs (other AJAX requests will fail because of the missing CSRF token if they run before this request completes).

Just wondering if I should go ahead and write my own XMLHttpRequest stuff for this particular thing...
 
XF 2.3 uses the Fetch API behind the scenes and the flow is similar to $.ajax - in that it returns a Promise chain.

By design, it isn’t supposed to be synchronous, though you can kind of replicate that with async/await keywords on methods.

So if you’re going to write your own synchronous method then I’d base it on the Fetch API and use async/await.

I’ll ping @Jeremy P because theoretically some sort of synchronous method might be useful in the core - or he might have some other ideas.
 
Double posting but, for those who absolutely need it...

The PAGE_CONTAINER template in both public and admin has a data-xf attribute on the <html> tag from 2.3 onwards, which includes the major and minor version (2.3 and 3.0) so you can query this from JS or CSS, and if html[data-xf] does not exist, you’re looking at 2.2 or older.
 
XF 2.3 uses the Fetch API behind the scenes and the flow is similar to $.ajax - in that it returns a Promise chain.

By design, it isn’t supposed to be synchronous, though you can kind of replicate that with async/await keywords on methods.

So if you’re going to write your own synchronous method then I’d base it on the Fetch API and use async/await.

I’ll ping @Jeremy P because theoretically some sort of synchronous method might be useful in the core - or he might have some other ideas.
Ya, this particular case is the only use I have for a forced synchronous request (fetching a CSRF token synchronously so other AJAX requests don't fail before the CSRF token is returned).

If it wasn't for the fact that Safari didn't support Sec-Fetch-Site before 16.4 (at least they do now), I'd just say do away with CSRF tokens finally and problem solved with the synchronous AJAX need. But well, Apple is ****ing us here.
 
I don't suppose there's some secret way to use namespaced events that would work with 2.2 and 2.3? Things like xf:page-load-start and xf:reinit are the first ones I've run into that I use (there's more... just haven't gotten that far yet). Might be where I need to actually look for html[data-xf]...
 
I don't suppose there's some secret way to use namespaced events that would work with 2.2 and 2.3? Things like xf:page-load-start and xf:reinit are the first ones I've run into that I use (there's more... just haven't gotten that far yet). Might be where I need to actually look for html[data-xf]...
They aren’t namespaced events, exactly.

By namespaced events we mean, e.g. click.something. This is still a normal click event, but it’s suffixed with a namespaced. It enables you to “off” an event in that namespace without affecting other events that have no namespace or another namespace. Or you can off all events for a namespace by passing in .something.

It’s not actually used that often.

But events with a colon in them are not the same thing. These events still work the same way as in 2.2.
 
Ya, I know they work the same. I guess what I mean is if someone happens to know of a way to make something like xf:reinit work without using XF.on() or $.on() (assuming of course you don't need to reference it later for something like "off").

Like you can't just do document.addEventListener('xf:reinit', e => {}) since that doesn't work in 2.2 (and I suspect that's not going to work in 2.3 either).
 
Ya, this particular case is the only use I have for a forced synchronous request (fetching a CSRF token synchronously so other AJAX requests don't fail before the CSRF token is returned).
I do understand the specific use case here necessitates them, but given synchronous requests are considered deprecated I'm not sure we'll be introducing anything to support them directly in the core. I think manually creating an XMLHttpRequest would be the way to go.

Like you can't just do document.addEventListener('xf:reinit', e => {}) since that doesn't work in 2.2 (and I suspect that's not going to work in 2.3 either).
That does actually work in 2.3, but of course that doesn't help the situation at hand. I think this would require conditionally using $.on or XF.on to support both 2.2 and 2.3.
 
Are we getting replacements for the utility functions like $.extend() and some of the custom jQuery functions you guys added like addClassTransitioned() and removeClassTransitioned()?
 
I spent way too long trying to build my own replacement for the Transitioned functions last night and when I realized how much code it was actually requiring, I figured I should probably ask. 😂

Never realized how annoying it must have been to write that code to get it to actually work properly. hah
 
Top Bottom