mirror of
https://github.com/discourse/discourse.git
synced 2024-12-16 11:48:34 +08:00
126 lines
3.2 KiB
JavaScript
126 lines
3.2 KiB
JavaScript
let timeout;
|
|
const loadingQueue = [];
|
|
const localCache = {};
|
|
const failedCache = {};
|
|
|
|
function resolveSize(img) {
|
|
$(img).addClass('size-resolved');
|
|
|
|
if (img.width > 0 && img.width === img.height) {
|
|
$(img).addClass('onebox-avatar');
|
|
}
|
|
}
|
|
|
|
// Detect square images and apply smaller onebox-avatar class
|
|
function applySquareGenericOnebox($elem, normalizedUrl) {
|
|
if (!$elem.hasClass('whitelistedgeneric')) {
|
|
return;
|
|
}
|
|
|
|
let $img = $elem.find('.onebox-body img.thumbnail');
|
|
let img = $img[0];
|
|
|
|
// already resolved... skip
|
|
if ($img.length !== 1 || $img.hasClass('size-resolved')) {
|
|
return;
|
|
}
|
|
|
|
if (img.complete) {
|
|
resolveSize(img, $elem, normalizedUrl);
|
|
} else {
|
|
$img.on('load.onebox', () => {
|
|
resolveSize(img, $elem, normalizedUrl);
|
|
$img.off('load.onebox');
|
|
});
|
|
}
|
|
}
|
|
|
|
function loadNext(ajax) {
|
|
if (loadingQueue.length === 0) {
|
|
timeout = null;
|
|
return;
|
|
}
|
|
|
|
let timeoutMs = 150;
|
|
let removeLoading = true;
|
|
const { url, refresh, $elem, categoryId, topicId } = loadingQueue.shift();
|
|
|
|
// Retrieve the onebox
|
|
return ajax("/onebox", {
|
|
dataType: 'html',
|
|
data: {
|
|
url,
|
|
refresh,
|
|
category_id: categoryId,
|
|
topic_id: topicId
|
|
},
|
|
cache: true
|
|
}).then(html => {
|
|
let $html = $(html);
|
|
localCache[normalize(url)] = $html;
|
|
$elem.replaceWith($html);
|
|
applySquareGenericOnebox($html, normalize(url));
|
|
}, result => {
|
|
if (result && result.jqXHR && result.jqXHR.status === 429) {
|
|
timeoutMs = 2000;
|
|
removeLoading = false;
|
|
loadingQueue.unshift({ url, refresh, $elem, categoryId, topicId });
|
|
} else {
|
|
failedCache[normalize(url)] = true;
|
|
}
|
|
}).finally(() => {
|
|
timeout = Ember.run.later(() => loadNext(ajax), timeoutMs);
|
|
if (removeLoading) {
|
|
$elem.removeClass('loading-onebox');
|
|
$elem.data('onebox-loaded');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Perform a lookup of a onebox based an anchor $element.
|
|
// It will insert a loading indicator and remove it when the loading is complete or fails.
|
|
export function load({ elem , refresh = true, ajax, synchronous = false, categoryId, topicId }) {
|
|
const $elem = $(elem);
|
|
|
|
// If the onebox has loaded or is loading, return
|
|
if ($elem.data('onebox-loaded')) return;
|
|
if ($elem.hasClass('loading-onebox')) return;
|
|
|
|
const url = elem.href;
|
|
|
|
// Unless we're forcing a refresh...
|
|
if (!refresh) {
|
|
// If we have it in our cache, return it.
|
|
const cached = localCache[normalize(url)];
|
|
if (cached) return cached.prop('outerHTML');
|
|
|
|
// If the request failed, don't do anything
|
|
const failed = failedCache[normalize(url)];
|
|
if (failed) return;
|
|
}
|
|
|
|
// Add the loading CSS class
|
|
$elem.addClass('loading-onebox');
|
|
|
|
// Add to the loading queue
|
|
loadingQueue.push({ url, refresh, $elem, categoryId, topicId });
|
|
|
|
// Load next url in queue
|
|
if (synchronous) {
|
|
return loadNext(ajax);
|
|
} else {
|
|
timeout = timeout || Ember.run.later(() => loadNext(ajax), 150);
|
|
}
|
|
}
|
|
|
|
// Sometimes jQuery will return URLs with trailing slashes when the
|
|
// `href` didn't have them.
|
|
function normalize(url) {
|
|
return url.replace(/\/$/, '');
|
|
}
|
|
|
|
export function lookupCache(url) {
|
|
const cached = localCache[normalize(url)];
|
|
return cached && cached.prop('outerHTML');
|
|
}
|