diff --git a/webclient/gulpfile.js b/webclient/gulpfile.js index 3d8168631..471449909 100644 --- a/webclient/gulpfile.js +++ b/webclient/gulpfile.js @@ -1,3 +1,5 @@ +/* eslint func-names: ["error", "always"] */ + import gulp from "gulp"; import addsrc from "gulp-add-src"; import babel from "gulp-babel"; @@ -33,9 +35,9 @@ import { configRelease, configLocal } from "./config.js"; // eslint-disable-line // from https://github.com/gulpjs/gulp/blob/master/docs/recipes/running-task-steps-per-folder.md function getFolders(dir) { - return fs.readdirSync(dir).filter(function (file) { - return fs.statSync(path.join(dir, file)).isDirectory(); - }); + return fs + .readdirSync(dir) + .filter((file) => fs.statSync(path.join(dir, file)).isDirectory()); } // Selected at the bottom of the script @@ -83,48 +85,50 @@ function cleanBuild(cb) { // --- Main CSS Pipeline --- function compileMainScss() { return merge( - ["light", "dark"].map(function (theme) { - return gulp + ["light", "dark"].map((theme) => + gulp .src("src/main.scss") .pipe(injectStr.prepend(`$theme: "${theme}";\n`)) .pipe(sass().on("error", sass.logError)) .pipe(rename(`main-${theme}.css`)) - .pipe(gulp.dest("build/tmp")); - }) + .pipe(gulp.dest("build/tmp")) + ) ); } function compileSpectreScss() { return merge( - ["light", "dark"].map(function (theme) { - return ( - gulp - .src("src/spectre-all.scss") - .pipe(injectStr.prepend(`$theme: "${theme}";\n`)) - .pipe(sass().on("error", sass.logError)) - .pipe( - purgecss({ - content: ["src/index.html", "src/views/*/*.inc"], - }) - ) - // .pipe(csso()) - .pipe(rename(`spectre-all-purged-${theme}.css`)) - .pipe(gulp.dest("build/tmp")) - ); - }) + ["light", "dark"].map((theme) => + gulp + .src("src/spectre-all.scss") + .pipe(injectStr.prepend(`$theme: "${theme}";\n`)) + .pipe(sass().on("error", sass.logError)) + .pipe( + purgecss({ + content: ["src/index.html", "src/views/*/*.inc"], + }) + ) + // .pipe(csso()) + .pipe(rename(`spectre-all-purged-${theme}.css`)) + .pipe(gulp.dest("build/tmp")) + ) ); } /* function mergeMainCss() { - return merge(["light", "dark"].map(function(theme) { - return gulp.src(['build/tmp/main-' + theme + '.css', - 'build/tmp/spectre-all-purged-' + theme + '.css']) - .pipe(concat('app-main-merged-' + theme + '.css')) - .pipe(gulp.dest('build/css')) - .pipe(csso()) - .pipe(rename('app-main-merged-' + theme + '.min.css')) - .pipe(gulp.dest('build/css')); - })); + return merge(["light", "dark"].map((theme) => + gulp + .src([ + `build/tmp/main-${theme}.css`, + `build/tmp/spectre-all-purged-${theme}.css`, + ]) + .pipe(concat(`app-main-merged-${theme}.css`)) + .pipe(gulp.dest("build/css")) + .pipe(csso()) + .pipe(rename(`app-main-merged-${theme}.min.css`)) + .pipe(gulp.dest("build/css")) + ) + ); } */ gulp.task( "main_css", @@ -224,22 +228,22 @@ gulp.task( ); // --- Views compilation pipeline --- -gulp.task("views", function (done) { +gulp.task("views", (done) => { const viewsSrcPath = "src/views"; const folders = getFolders(viewsSrcPath); if (folders.length === 0) return done(); // nothing to do! - const tasks = folders.map(function (folder) { + const tasks = folders.map((folder) => { const cssTask = merge( - ["light", "dark"].map(function (theme) { - return gulp + ["light", "dark"].map((theme) => + gulp .src(path.join(viewsSrcPath, folder, `/view-${folder}.scss`)) .pipe(injectStr.prepend(`$theme: "${theme}";\n`)) .pipe(sass().on("error", sass.logError)) .pipe(rename(`view-${theme}.css`)) - .pipe(gulp.dest(`build/tmp/views/${folder}`)); - }) + .pipe(gulp.dest(`build/tmp/views/${folder}`)) + ) ); const jsTask = gulp @@ -281,15 +285,15 @@ gulp.task("views", function (done) { }); // --- Build pages sources --- -gulp.task("pages_src", function (done) { +gulp.task("pages_src", (done) => { const viewsBuildPath = "build/tmp/views"; const folders = getFolders(viewsBuildPath); if (folders.length === 0) return done(); // nothing to do! - const tasks = folders.map(function (folder) { + const tasks = folders.map((folder) => { const viewCSS = merge( - ["light", "dark"].map(function (theme) { + ["light", "dark"].map((theme) => { // Extract used spectre classes for this view and merge with core & view css const viewCSSCore = gulp .src(`build/tmp/spectre-all-purged-${theme}.css`) @@ -338,15 +342,15 @@ gulp.task("pages_src", function (done) { }); // --- Build pages output --- -gulp.task("pages_out", function (done) { +gulp.task("pages_out", (done) => { const viewsBuildPath = "build/tmp/views"; const folders = getFolders(viewsBuildPath); if (folders.length === 0) return done(); // nothing to do! - const tasks = folders.map(function (folder) { + const tasks = folders.map((folder) => { const themedTasks = merge( - ["light", "dark"].map(function (theme) { + ["light", "dark"].map((theme) => { const viewHtml = gulp .src("src/index.html") .pipe(rename(`index-view-${folder}-${theme}.html`)) @@ -375,9 +379,7 @@ gulp.task("pages_out", function (done) { ), { starttag: "", - transform: function (filePath, file) { - return file.contents.toString("utf8"); - }, + transform: (filePath, file) => file.contents.toString("utf8"), quiet: true, removeTags: true, } @@ -544,10 +546,9 @@ function i18nCompileLangfiles() { // --- Markdown Pipeline --- const renderer = { - code: function (code, infostring) { - return `
${code}
`; - }, - link: function (href, title, text) { + code: (code, infostring) => + `
${code}
`, + link: (href, title, text) => { if (href.startsWith("http")) return `${text}`; return `${text}`; @@ -584,7 +585,7 @@ function revisionAssets(done) { // css is deferred using preload, which revAll currently doesn't detect includeFilesInManifest: [".js", ".webp", ".svg", ".png", ".ico"], dontRenameFile: [".html"], - transformFilename: function (file, hash) { + transformFilename: (file, hash) => { const ext = path.extname(file.path); return `cache_${hash.substr(0, 8)}.${path.basename( file.path, diff --git a/webclient/package.json b/webclient/package.json index edf7247b3..6e884b285 100644 --- a/webclient/package.json +++ b/webclient/package.json @@ -12,6 +12,9 @@ "extends": [ "@paulhfischer/eslint-config-javascript" ], + "ignorePatterns": [ + "**/googlebef9161f1176c5e0.html" + ], "env": { "browser": true }, @@ -34,6 +37,10 @@ "error", "never" ], + "func-names": [ + "error", + "as-needed" + ], "no-template-curly-in-string": "off", "no-console": [ "error", diff --git a/webclient/src/core.js b/webclient/src/core.js index aa6bf1c87..38a1628a5 100644 --- a/webclient/src/core.js +++ b/webclient/src/core.js @@ -7,65 +7,63 @@ let navigatum; // This is a wrapper around fetch that avoids duplicate requests if the // same resource is requested another time before the first request has // returned. -const cachedFetch = (function () { - return { - fetch: function (url, options) { - return new Promise((resolve) => { - if (url in this.cache) { - resolve(this.cache[url]); - } else if (url in this.promise_callbacks) { - this.promise_callbacks[url].push(resolve); - } else { - this.promise_callbacks[url] = [resolve]; - if (!options.headers) options.headers = {}; - fetch(url, options) - .then((response) => { - if (!response.ok) { - if (response.status === 404) - throw new Error("${{_.core_js.error.404}}$"); - else if (response.status === 500) - throw new Error("${{_.core_js.error.500}}$"); - else if (response.status === 503) - throw new Error("${{_.core_js.error.503}}$"); - else { - const errorStatus = "${{_.core_js.error.status}}$"; - throw new Error(`${errorStatus}$${response.status}`); - } +const cachedFetch = (() => ({ + fetch: function (url, options) { + return new Promise((resolve) => { + if (url in this.cache) { + resolve(this.cache[url]); + } else if (url in this.promise_callbacks) { + this.promise_callbacks[url].push(resolve); + } else { + this.promise_callbacks[url] = [resolve]; + if (!options.headers) options.headers = {}; + fetch(url, options) + .then((response) => { + if (!response.ok) { + if (response.status === 404) + throw new Error("${{_.core_js.error.404}}$"); + else if (response.status === 500) + throw new Error("${{_.core_js.error.500}}$"); + else if (response.status === 503) + throw new Error("${{_.core_js.error.503}}$"); + else { + const errorStatus = "${{_.core_js.error.status}}$"; + throw new Error(`${errorStatus}$${response.status}`); } - navigatum.app.error.msg = null; - return options.as_text ? response.text() : response.json(); - }) - .catch((error) => { - let msg; - if (error instanceof TypeError) - msg = "${{_.core_js.error.network}}$"; - else msg = error.message; + } + navigatum.app.error.msg = null; + return options.as_text ? response.text() : response.json(); + }) + .catch((error) => { + let msg; + if (error instanceof TypeError) + msg = "${{_.core_js.error.network}}$"; + else msg = error.message; - if (!msg) msg = "${{_.core_js.error.unknown}}$"; + if (!msg) msg = "${{_.core_js.error.unknown}}$"; - console.warn("Error on fetch:", error); + console.warn("Error on fetch:", error); - if (navigatum && navigatum.app) navigatum.app.error.msg = msg; + if (navigatum && navigatum.app) navigatum.app.error.msg = msg; - return null; - }) - .then((data) => { - if (data !== null) this.cache[url] = data; + return null; + }) + .then((data) => { + if (data !== null) this.cache[url] = data; - this.promise_callbacks[url].forEach((callback) => { - callback(data); - }); - delete this.promise_callbacks[url]; + this.promise_callbacks[url].forEach((callback) => { + callback(data); }); - } - }); - }, - cache: {}, - promise_callbacks: {}, - }; -})(); + delete this.promise_callbacks[url]; + }); + } + }); + }, + cache: {}, + promise_callbacks: {}, +}))(); -navigatum = (function () { +navigatum = (() => { const apiBase = "/* @echo api_prefix */"; const cache = {}; @@ -145,7 +143,7 @@ navigatum = (function () { }, searchBlur: function () { if (this.search.keep_focus) { - window.setTimeout(function () { + window.setTimeout(() => { // This is relevant if the call is delayed and focused has // already been disabled e.g. when clicking on an entry. if (this.search.focused) @@ -157,12 +155,12 @@ navigatum = (function () { } }, searchInput: function (e) { - navigatum.getModule("autocomplete").then(function (c) { + navigatum.getModule("autocomplete").then((c) => { c.onInput(e.srcElement.value); }); }, searchKeydown: function (e) { - navigatum.getModule("autocomplete").then(function (c) { + navigatum.getModule("autocomplete").then((c) => { c.onKeyDown(e); }); }, @@ -266,12 +264,12 @@ navigatum = (function () { } }, getView: function (name) { - return function (resolve, reject) { + return (resolve, reject) => { if (name in navigatum.views) { resolve(navigatum.views[name]); } else { viewsResolveCallbacks[name] = resolve; - window.setTimeout(function () { + window.setTimeout(() => { if (name in viewsResolveCallbacks) { if (navigatum.app) navigatum.app.error.msg = @@ -360,7 +358,7 @@ navigatum = (function () { // This timeout is required because else the browser might skip to // transition if the change is too fast (if resources are in cache) - window.setTimeout(function () { + window.setTimeout(() => { document.getElementById("content").classList.add("visible"); document.getElementById("content").style.opacity = ""; document.getElementById("loading-page").classList.remove("show"); diff --git a/webclient/src/feedback.js b/webclient/src/feedback.js index 3d2b28045..2f5efb38e 100644 --- a/webclient/src/feedback.js +++ b/webclient/src/feedback.js @@ -3,18 +3,14 @@ // It is only loaded when the feedback form is being opened. // eslint-disable-next-line no-unused-vars -const feedback = (function () { +const feedback = (() => { let token = null; function _requestPage(method, url, data, onsuccess, onerror) { const req = new XMLHttpRequest(); req.open(method, window.encodeURI(url), true); - req.onload = function () { - onsuccess(this); - }; - req.onerror = function () { - onerror(this); - }; + req.onload = onsuccess(this); + req.onerror = onerror(this); if (data === null) { req.send(); } else { @@ -61,7 +57,7 @@ const feedback = (function () { "POST", "/* @echo api_prefix */feedback/get_token", null, - function (r) { + (r) => { if (r.status === 201) { token = { creation: Date.now(), @@ -79,7 +75,7 @@ const feedback = (function () { _showError(`${unexpectedTokenError}${r.status}`, true); } }, - function (r) { + (r) => { _showError("${{_.feedback.error.token_req_failed}}$", false); console.error(r); } @@ -155,7 +151,7 @@ const feedback = (function () { privacy_checked: privacy, delete_issue_requested: deleteIssue, }), - function (r) { + (r) => { _showLoading(false); if (r.status === 201) { localStorage.removeItem("coordinate-feedback"); @@ -180,7 +176,7 @@ const feedback = (function () { _showError(`${unexpectedStatusError}${r.status}`, false); } }, - function (r) { + (r) => { _showLoading(false); _showError("${{_.feedback.error.send_req_failed}}$"); console.error(r); @@ -226,13 +222,9 @@ const feedback = (function () { .getElementById("feedback-overlay-2") .addEventListener("click", closeForm, false); - document.getElementById("feedback-category").addEventListener( - "change", - function (e) { - updateFeedbackForm(e.value); - }, - false - ); + document + .getElementById("feedback-category") + .addEventListener("change", (e) => updateFeedbackForm(e.value), false); document .getElementById("feedback-send") diff --git a/webclient/src/history-states.js b/webclient/src/history-states.js index bcc0c9fbc..8053b0a85 100644 --- a/webclient/src/history-states.js +++ b/webclient/src/history-states.js @@ -8,7 +8,7 @@ // TODO: only if initialized and fallback==false -(function () { +(() => { const stateIndexSymbol = "__state__index__"; const stateDataSymbol = "viewState"; @@ -53,7 +53,7 @@ window.history.states.splice(window.history.stateIndex + 2); window.history.stateIndex += 1; } - window.history.saveCurrentViewState = function () { + window.history.saveCurrentViewState = () => { if ( navigatum.router && navigatum.router.currentRoute.matched[0] && @@ -70,11 +70,11 @@ ); } }; - window.history.pushState = function (data, title, url = null) { + window.history.pushState = (data, title, url = null) => { add(data, title, url); historyPushState.bind(window.history)(data, title, url); }; - document.addEventListener("popstate", function (e) { + document.addEventListener("popstate", (e) => { // If navigation is window.history navigation (click on back/forward), // the 'popstate' event is emitted before 'beforeResolve()'. // So in this case, we need to temporarily store the old state index, diff --git a/webclient/src/legacy.js b/webclient/src/legacy.js index da60e3009..ca7ddcff5 100644 --- a/webclient/src/legacy.js +++ b/webclient/src/legacy.js @@ -3,9 +3,7 @@ import "regenerator-runtime/runtime"; /* eslint no-extend-native: "off" */ // For some reason this polyfill is not included automatically if (typeof String.prototype.startsWith === "undefined") { - String.prototype.startsWith = function (needle) { - return this.indexOf(needle) === 0; - }; + String.prototype.startsWith = (needle) => this.indexOf(needle) === 0; } /* split */ diff --git a/webclient/src/modules/autocomplete.js b/webclient/src/modules/autocomplete.js index 329ce9cc9..a0c4523b0 100644 --- a/webclient/src/modules/autocomplete.js +++ b/webclient/src/modules/autocomplete.js @@ -1,6 +1,6 @@ navigatum.registerModule( "autocomplete", - (function () { + (() => { function getVisibleElements() { const visible = []; diff --git a/webclient/src/modules/interactive-map.js b/webclient/src/modules/interactive-map.js index 23d708b4f..8b707947d 100644 --- a/webclient/src/modules/interactive-map.js +++ b/webclient/src/modules/interactive-map.js @@ -1,6 +1,6 @@ navigatum.registerModule( "interactive-map", - (function () { + (() => { /* global mapboxgl */ let _map; @@ -12,7 +12,7 @@ navigatum.registerModule( // Add Evented functionality from mapboxgl FloorControl.prototype = Object.create(mapboxgl.Evented.prototype); - FloorControl.prototype.onAdd = function (map) { + FloorControl.prototype.onAdd = (map) => { this.map = map; this.container = document.createElement("div"); this.container.classList.add("mapboxgl-ctrl-group"); @@ -56,11 +56,11 @@ navigatum.registerModule( return this.container; }; - FloorControl.prototype.onRemove = function () { + FloorControl.prototype.onRemove = () => { this.container.parentNode.removeChild(this.container); this.map = undefined; }; - FloorControl.prototype.updateFloors = function (floors, visibleId) { + FloorControl.prototype.updateFloors = (floors, visibleId) => { // `floors` is null or a list of floors with data, // `visibleId` is the id of the visible floor. if (floors === null) { @@ -70,9 +70,9 @@ navigatum.registerModule( this.floor_list.innerHTML = ""; const _this = this; - const clickHandlerBuilder = function (allFloors, i) { + const clickHandlerBuilder = (allFloors, i) => { // Because JS - return function () { + return () => { if (allFloors) { _this._setActiveFloor(i, allFloors[i].floor); _this.fire("floor-changed", { @@ -125,7 +125,7 @@ navigatum.registerModule( } }; // Recalculate the layout for displaying n floor buttons - FloorControl.prototype._recalculateLayout = function (n) { + FloorControl.prototype._recalculateLayout = (n) => { // Calculate required and available size to choose between // vertical (default) or horizontal layout const mapHeight = @@ -161,7 +161,7 @@ navigatum.registerModule( else this.container.classList.add("horizontal"); } }; - FloorControl.prototype._setActiveFloor = function (floorListI, name) { + FloorControl.prototype._setActiveFloor = (floorListI, name) => { for (let i = 0; i < this.floor_list.children.length; i++) { if (i === floorListI) this.floor_list.children[i].classList.add("active"); @@ -174,8 +174,8 @@ navigatum.registerModule( return { map: undefined, - init: function () { - return new Promise((resolve) => { + init: () => + new Promise((resolve) => { const head = document.getElementsByTagName("head")[0]; // Add CSS first (required by Mapbox) const elCSS = document.createElement("link"); @@ -193,8 +193,7 @@ navigatum.registerModule( resolve(); }; head.appendChild(elJS); - }); - }, + }), createMarker: function (hueRotation = 0) { const markerDiv = document.createElement("div"); const markerIcon = document.createElement("span"); @@ -255,7 +254,7 @@ navigatum.registerModule( // "Backup" the mapboxgl default fullscreen handler fullscreenCtl._onClickFullscreenDefault = fullscreenCtl._onClickFullscreen; - fullscreenCtl._onClickFullscreen = function () { + fullscreenCtl._onClickFullscreen = () => { if (isMobile) { fullscreenCtl._onClickFullscreenDefault(); } else { @@ -291,13 +290,13 @@ navigatum.registerModule( // into "loading" state, so map.loaded() is not reliable // enough to know whether just the initial loading has // succeded. - map.on("load", function () { + map.on("load", () => { map.initialLoaded = true; }); const _this = this; map.floorControl = new FloorControl(); - map.floorControl.on("floor-changed", function (args) { + map.floorControl.on("floor-changed", (args) => { _this.setOverlayImage( args.file ? `/* @echo cdn_prefix */maps/overlay/${args.file}` @@ -328,9 +327,7 @@ navigatum.registerModule( // to be required to do changes here) if (!_map.initialLoaded) { const _this = this; - _map.on("load", function () { - _this.setOverlayImage(imgUrl, coords); - }); + _map.on("load", () => _this.setOverlayImage(imgUrl, coords)); return; } diff --git a/webclient/src/views/md/view-md.js b/webclient/src/views/md/view-md.js index a10ebeeba..43ab17835 100644 --- a/webclient/src/views/md/view-md.js +++ b/webclient/src/views/md/view-md.js @@ -54,7 +54,7 @@ navigatum.registerView("md", { loadPage: function (content) { this.content = content; - this.$nextTick(function () { + this.$nextTick(() => { const e = document.getElementById("view-md"); if (e === null) { console.warn( diff --git a/webclient/src/views/search/view-search.js b/webclient/src/views/search/view-search.js index 8345fa49b..92f8057c1 100644 --- a/webclient/src/views/search/view-search.js +++ b/webclient/src/views/search/view-search.js @@ -82,7 +82,7 @@ navigatum.registerView("search", { // In the future it is planned that this search results page // has a different format. const _this = this; - navigatum.getModule("autocomplete").then(function (c) { + navigatum.getModule("autocomplete").then((c) => { _this.sections = c.extractFacets(data); }); }, diff --git a/webclient/src/views/view/view-view.js b/webclient/src/views/view/view-view.js index 7e811a5d7..1504175f2 100644 --- a/webclient/src/views/view/view-view.js +++ b/webclient/src/views/view/view-view.js @@ -408,7 +408,7 @@ navigatum.registerView("view", { this.state.map.selected = "interactive"; const doMapUpdate = function () { - navigatum.getModule("interactive-map").then(function (c) { + navigatum.getModule("interactive-map").then((c) => { _this.map.interactive.component = c; let { map } = _this.map.interactive; @@ -506,7 +506,7 @@ navigatum.registerView("view", { if (fromUi) { document.getElementById("map-accordion").checked = false; - /* window.setTimeout(function() { + /* window.setTimeout(() => { document.getElementById("roomfinder-map-img").scrollIntoView(false); }, 50); */ window.scrollTo( @@ -564,7 +564,7 @@ navigatum.registerView("view", { local.display_list = []; // this.$nextTick doesn't work for some reason, the view freezes // before the loading indicator is visible. - window.setTimeout(function () { + window.setTimeout(() => { local.display_list = tmp; local.loading = false; }, 20); @@ -589,7 +589,7 @@ navigatum.registerView("view", { if (success) { const _this = this; _this.copied = true; - window.setTimeout(function () { + window.setTimeout(() => { _this.copied = false; }, 1000); } @@ -632,7 +632,7 @@ navigatum.registerView("view", { window.addEventListener("storage", updateCoordinateCounter); updateCoordinateCounter(); - this.$nextTick(function () { + this.$nextTick(() => { // Even though 'mounted' is called there is no guarantee apparently, // that it really is mounted now. For this reason we try to poll now. // (Not the best solution probably)