mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
refactor: split out logic to determine ajaxification into exported method
There was some internal logic in ajaxify that handled special links that should explicitly not be ajaxified (either it is a null href or should be loaded as a direct page load, etc.) - this was moved out to an exported method so it can be consumed by the service worker onmessage listener. Also since this logic evolved over many years, there were some duplications and so those have been amended (though I will not guarantee that it was done bug/regression free!!)
This commit is contained in:
@@ -23,6 +23,60 @@ ajaxify.widgets = { render: render };
|
|||||||
if ('scrollRestoration' in history) {
|
if ('scrollRestoration' in history) {
|
||||||
history.scrollRestoration = 'manual';
|
history.scrollRestoration = 'manual';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ajaxify.check = (item) => {
|
||||||
|
/**
|
||||||
|
* returns:
|
||||||
|
* true (ajaxify OK)
|
||||||
|
* false (browser default)
|
||||||
|
* null (no action)
|
||||||
|
*/
|
||||||
|
let urlObj;
|
||||||
|
let pathname;
|
||||||
|
try {
|
||||||
|
urlObj = new URL(item, `${document.location.origin}${config.relative_path}`);
|
||||||
|
({ pathname } = urlObj);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const internalLink = utils.isInternalURI(urlObj, window.location, config.relative_path);
|
||||||
|
// eslint-disable-next-line no-script-url
|
||||||
|
const hrefEmpty = href => href === undefined || href === '' || href === 'javascript:;';
|
||||||
|
|
||||||
|
if (item instanceof Element && item.getAttribute('data-ajaxify') === 'false') {
|
||||||
|
if (!internalLink) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default behaviour for rss feeds
|
||||||
|
if (internalLink && pathname.endsWith('.rss')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default behaviour for sitemap
|
||||||
|
if (internalLink && String(pathname).startsWith(config.relative_path + '/sitemap') && pathname.endsWith('.xml')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default behaviour for uploads and direct links to API urls
|
||||||
|
if (internalLink && ['/uploads', '/assets/', '/api/'].some(function (prefix) {
|
||||||
|
return String(pathname).startsWith(config.relative_path + prefix);
|
||||||
|
})) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-script-url
|
||||||
|
if (hrefEmpty(urlObj.href) || urlObj.protocol === 'javascript:' || pathname === '#' || pathname === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
ajaxify.go = function (url, callback, quiet) {
|
ajaxify.go = function (url, callback, quiet) {
|
||||||
// Automatically reconnect to socket and re-ajaxify on success
|
// Automatically reconnect to socket and re-ajaxify on success
|
||||||
if (!socket.connected && parseInt(app.user.uid, 10) >= 0) {
|
if (!socket.connected && parseInt(app.user.uid, 10) >= 0) {
|
||||||
@@ -512,10 +566,6 @@ $(document).ready(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function ajaxifyAnchors() {
|
function ajaxifyAnchors() {
|
||||||
function hrefEmpty(href) {
|
|
||||||
// eslint-disable-next-line no-script-url
|
|
||||||
return href === undefined || href === '' || href === 'javascript:;';
|
|
||||||
}
|
|
||||||
const location = document.location || window.location;
|
const location = document.location || window.location;
|
||||||
const rootUrl = location.protocol + '//' + (location.hostname || location.host) + (location.port ? ':' + location.port : '');
|
const rootUrl = location.protocol + '//' + (location.hostname || location.host) + (location.port ? ':' + location.port : '');
|
||||||
const contentEl = document.getElementById('content');
|
const contentEl = document.getElementById('content');
|
||||||
@@ -527,9 +577,7 @@ $(document).ready(function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const href = this.pathname;
|
|
||||||
const internalLink = utils.isInternalURI(this, window.location, config.relative_path);
|
const internalLink = utils.isInternalURI(this, window.location, config.relative_path);
|
||||||
|
|
||||||
const rootAndPath = new RegExp(`^${rootUrl}${config.relative_path}/?`);
|
const rootAndPath = new RegExp(`^${rootUrl}${config.relative_path}/?`);
|
||||||
const process = function () {
|
const process = function () {
|
||||||
if (!e.ctrlKey && !e.shiftKey && !e.metaKey && e.which === 1) {
|
if (!e.ctrlKey && !e.shiftKey && !e.metaKey && e.which === 1) {
|
||||||
@@ -560,52 +608,36 @@ $(document).ready(function () {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.getAttribute('data-ajaxify') === 'false') {
|
const check = ajaxify.check(this);
|
||||||
if (!internalLink) {
|
switch (check) {
|
||||||
return;
|
case true: {
|
||||||
}
|
if (app.flags && app.flags.hasOwnProperty('_unsaved') && app.flags._unsaved === true) {
|
||||||
return e.preventDefault();
|
if (e.ctrlKey) {
|
||||||
}
|
return;
|
||||||
|
|
||||||
// Default behaviour for rss feeds
|
|
||||||
if (internalLink && href && href.endsWith('.rss')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default behaviour for sitemap
|
|
||||||
if (internalLink && href && String(_self.pathname).startsWith(config.relative_path + '/sitemap') && href.endsWith('.xml')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default behaviour for uploads and direct links to API urls
|
|
||||||
if (internalLink && ['/uploads', '/assets/', '/api/'].some(function (prefix) {
|
|
||||||
return String(_self.pathname).startsWith(config.relative_path + prefix);
|
|
||||||
})) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-script-url
|
|
||||||
if (hrefEmpty(this.href) || this.protocol === 'javascript:' || href === '#' || href === '') {
|
|
||||||
return e.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (app.flags && app.flags.hasOwnProperty('_unsaved') && app.flags._unsaved === true) {
|
|
||||||
if (e.ctrlKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
require(['bootbox'], function (bootbox) {
|
|
||||||
bootbox.confirm('[[global:unsaved-changes]]', function (navigate) {
|
|
||||||
if (navigate) {
|
|
||||||
app.flags._unsaved = false;
|
|
||||||
process.call(_self);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
return e.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
process.call(_self);
|
require(['bootbox'], function (bootbox) {
|
||||||
|
bootbox.confirm('[[global:unsaved-changes]]', function (navigate) {
|
||||||
|
if (navigate) {
|
||||||
|
app.flags._unsaved = false;
|
||||||
|
process.call(_self);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
process.call(_self);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case null: {
|
||||||
|
e.preventDefault();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// default is default browser behaviour
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user