You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
devdocs/assets/javascripts/views/content/entry_page.js

226 lines
6.3 KiB

/*
* decaffeinate suggestions:
* DS002: Fix invalid constructor
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS205: Consider reworking code to avoid use of IIFEs
* DS206: Consider reworking classes to avoid initClass
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
(function() {
let LINKS = undefined;
const Cls = (app.views.EntryPage = class EntryPage extends app.View {
constructor(...args) {
this.beforeRoute = this.beforeRoute.bind(this);
this.onSuccess = this.onSuccess.bind(this);
this.onError = this.onError.bind(this);
this.onClick = this.onClick.bind(this);
this.onAltC = this.onAltC.bind(this);
this.onAltO = this.onAltO.bind(this);
super(...args);
}
static initClass() {
this.className = '_page';
this.errorClass = '_page-error';
this.events =
{click: 'onClick'};
this.shortcuts = {
altC: 'onAltC',
altO: 'onAltO'
};
this.routes =
{before: 'beforeRoute'};
LINKS = {
home: 'Homepage',
code: 'Source code'
};
}
init() {
this.cacheMap = {};
this.cacheStack = [];
}
deactivate() {
if (super.deactivate(...arguments)) {
this.empty();
this.entry = null;
}
}
loading() {
this.empty();
this.trigger('loading');
}
render(content, fromCache) {
if (content == null) { content = ''; }
if (fromCache == null) { fromCache = false; }
if (!this.activated) { return; }
this.empty();
this.subview = new (this.subViewClass())(this.el, this.entry);
$.batchUpdate(this.el, () => {
this.subview.render(content, fromCache);
if (!fromCache) { this.addCopyButtons(); }
});
if (app.disabledDocs.findBy('slug', this.entry.doc.slug)) {
this.hiddenView = new app.views.HiddenPage(this.el, this.entry);
}
setFaviconForDoc(this.entry.doc);
this.delay(this.polyfillMathML);
this.trigger('loaded');
}
addCopyButtons() {
if (!this.copyButton) {
this.copyButton = document.createElement('button');
this.copyButton.innerHTML = '<svg><use xlink:href="#icon-copy"/></svg>';
this.copyButton.type = 'button';
this.copyButton.className = '_pre-clip';
this.copyButton.title = 'Copy to clipboard';
this.copyButton.setAttribute('aria-label', 'Copy to clipboard');
}
for (var el of Array.from(this.findAllByTag('pre'))) { el.appendChild(this.copyButton.cloneNode(true)); }
}
polyfillMathML() {
if ((window.supportsMathML !== false) || !!this.polyfilledMathML || !this.findByTag('math')) { return; }
this.polyfilledMathML = true;
$.append(document.head, `<link rel="stylesheet" href="${app.config.mathml_stylesheet}">`);
}
prepareContent(content) {
if (!this.entry.isIndex() || !this.entry.doc.links) { return content; }
const links = (() => {
const result = [];
for (var link in this.entry.doc.links) {
var url = this.entry.doc.links[link];
result.push(`<a href="${url}" class="_links-link">${LINKS[link]}</a>`);
}
return result;
})();
return `<p class="_links">${links.join('')}</p>${content}`;
}
empty() {
if (this.subview != null) {
this.subview.deactivate();
}
this.subview = null;
if (this.hiddenView != null) {
this.hiddenView.deactivate();
}
this.hiddenView = null;
this.resetClass();
super.empty(...arguments);
}
subViewClass() {
return app.views[`${$.classify(this.entry.doc.type)}Page`] || app.views.BasePage;
}
getTitle() {
return this.entry.doc.fullName + (this.entry.isIndex() ? ' documentation' : ` / ${this.entry.name}`);
}
beforeRoute() {
this.cache();
this.abort();
}
onRoute(context) {
const isSameFile = context.entry.filePath() === (this.entry != null ? this.entry.filePath() : undefined);
this.entry = context.entry;
if (!isSameFile) { this.restore() || this.load(); }
}
load() {
this.loading();
this.xhr = this.entry.loadFile(this.onSuccess, this.onError);
}
abort() {
if (this.xhr) {
this.xhr.abort();
this.xhr = (this.entry = null);
}
}
onSuccess(response) {
if (!this.activated) { return; }
this.xhr = null;
this.render(this.prepareContent(response));
}
onError() {
this.xhr = null;
this.render(this.tmpl('pageLoadError'));
this.resetClass();
this.addClass(this.constructor.errorClass);
if (app.serviceWorker != null) {
app.serviceWorker.update();
}
}
cache() {
let path;
if (this.xhr || !this.entry || this.cacheMap[(path = this.entry.filePath())]) { return; }
this.cacheMap[path] = this.el.innerHTML;
this.cacheStack.push(path);
while (this.cacheStack.length > app.config.history_cache_size) {
delete this.cacheMap[this.cacheStack.shift()];
}
}
restore() {
let path;
if (this.cacheMap[(path = this.entry.filePath())]) {
this.render(this.cacheMap[path], true);
return true;
}
}
onClick(event) {
const target = $.eventTarget(event);
if (target.hasAttribute('data-retry')) {
$.stopEvent(event);
this.load();
} else if (target.classList.contains('_pre-clip')) {
$.stopEvent(event);
target.classList.add($.copyToClipboard(target.parentNode.textContent) ? '_pre-clip-success' : '_pre-clip-error');
setTimeout((() => target.className = '_pre-clip'), 2000);
}
}
onAltC() {
let link;
if (!(link = this.find('._attribution:last-child ._attribution-link'))) { return; }
console.log(link.href + location.hash);
navigator.clipboard.writeText(link.href + location.hash);
}
onAltO() {
let link;
if (!(link = this.find('._attribution:last-child ._attribution-link'))) { return; }
this.delay(() => $.popup(link.href + location.hash));
}
});
Cls.initClass();
return Cls;
})();