From 70c652d5657dffbb971c3c13cfe301eeab7303a8 Mon Sep 17 00:00:00 2001 From: Fabien Basmaison Date: Tue, 6 Apr 2021 10:42:52 +0200 Subject: [PATCH] [assets] Add rules to ESLint: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix long line. - Enforce a few stylistic habits: - Avoid some potential dangerous constructs. - `arrow-spacing`: Use at least one space around arrows. - `keyword-spacing`: Use at least one space around keywords (if, else, for…). - `no-multiple-empty-lines`: Only use one empty line between code. - `no-var`: Use `let` or `const` instead of `var`: - `padded-blocks`: Do not pad blocks. - `padding-line-between-statements`: Use empty lines between some statements. - `space-before-blocks`: Use at least one space before the opening brace of a block. --- .eslintrc.js | 60 +++++++++++++++++++++++++++++- bookwyrm/static/js/bookwyrm.js | 58 ++++++++++++++++++++--------- bookwyrm/static/js/localstorage.js | 10 +++-- 3 files changed, 105 insertions(+), 23 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index b5f3c311f..5a247a43f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,6 +9,64 @@ module.exports = { "extends": "eslint:recommended", "rules": { - "strict": "error" + // Possible Errors + "no-async-promise-executor": "error", + "no-await-in-loop": "error", + "no-class-assign": "error", + "no-confusing-arrow": "error", + "no-const-assign": "error", + "no-dupe-class-members": "error", + "no-duplicate-imports": "error", + "no-template-curly-in-string": "error", + "no-useless-computed-key": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "require-atomic-updates": "error", + + // Best practices + "strict": "error", + "no-var": "error", + + // Stylistic Issues + "arrow-spacing": "error", + "keyword-spacing": "error", + "no-multiple-empty-lines": [ + "error", + { + "max": 1, + }, + ], + "padded-blocks": [ + "error", + "never", + ], + "padding-line-between-statements": [ + "error", + { + // always before return + "blankLine": "always", + "prev": "*", + "next": "return", + }, + { + // always before block-like expressions + "blankLine": "always", + "prev": "*", + "next": "block-like", + }, + { + // always after variable declaration + "blankLine": "always", + "prev": [ "const", "let", "var" ], + "next": "*", + }, + { + // not necessary between variable declaration + "blankLine": "any", + "prev": [ "const", "let", "var" ], + "next": [ "const", "let", "var" ], + }, + ], + "space-before-blocks": "error", } }; diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index ceab51767..3df49ae5e 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -56,8 +56,10 @@ let BookWyrm = new class { polling(el, delay) { let poller = this; + delay = delay || 10000; delay += (Math.random() * 1000); + setTimeout(function() { fetch('/api/updates/' + el.getAttribute('data-poll')) .then(response => response.json()) @@ -69,6 +71,7 @@ let BookWyrm = new class { updateCountElement(el, data) { const currentCount = el.innerText; const count = data.count; + if (count != currentCount) { this.addRemoveClass(el.closest('[data-poll-wrapper]'), 'hidden', count < 1); el.innerText = count; @@ -76,52 +79,62 @@ let BookWyrm = new class { } revealForm(e) { - var hidden = e.currentTarget.closest('.hidden-form').getElementsByClassName('hidden')[0]; + let hidden = e.currentTarget.closest('.hidden-form').getElementsByClassName('hidden')[0]; + if (hidden) { this.removeClass(hidden, 'hidden'); } } toggleAction(e) { - var el = e.currentTarget; - var pressed = el.getAttribute('aria-pressed') == 'false'; + let el = e.currentTarget; + let pressed = el.getAttribute('aria-pressed') == 'false'; + let targetId = el.getAttribute('data-controls'); - var targetId = el.getAttribute('data-controls'); document.querySelectorAll('[data-controls="' + targetId + '"]') - .forEach(t => t.setAttribute('aria-pressed', (t.getAttribute('aria-pressed') == 'false'))); + .forEach(t => { + t.setAttribute('aria-pressed', (t.getAttribute('aria-pressed') == 'false')) + }); if (targetId) { - var target = document.getElementById(targetId); + let target = document.getElementById(targetId); + this.addRemoveClass(target, 'hidden', !pressed); this.addRemoveClass(target, 'is-active', pressed); } // show/hide container - var container = document.getElementById('hide-' + targetId); + let container = document.getElementById('hide-' + targetId); + if (container) { this.addRemoveClass(container, 'hidden', pressed); } // set checkbox, if appropriate - var checkbox = el.getAttribute('data-controls-checkbox'); + let checkbox = el.getAttribute('data-controls-checkbox'); + if (checkbox) { document.getElementById(checkbox).checked = !!pressed; } // set focus, if appropriate - var focus = el.getAttribute('data-focus-target'); + let focus = el.getAttribute('data-focus-target'); + if (focus) { - var focusEl = document.getElementById(focus); + let focusEl = document.getElementById(focus); + focusEl.focus(); - setTimeout(function(){ focusEl.selectionStart = focusEl.selectionEnd = 10000; }, 0); + setTimeout(function() { focusEl.selectionStart = focusEl.selectionEnd = 10000; }, 0); } } // @todo Only update status if the promise is successful. interact(e) { e.preventDefault(); + + let identifier = e.target.getAttribute('data-id'); + this.ajaxPost(e.target); - var identifier = e.target.getAttribute('data-id'); // @todo This probably should be done with IDs. document.querySelectorAll(`.${identifier}`) @@ -129,12 +142,15 @@ let BookWyrm = new class { } toggleMenu(e) { - var el = e.currentTarget; - var expanded = el.getAttribute('aria-expanded') == 'false'; + let el = e.currentTarget; + let expanded = el.getAttribute('aria-expanded') == 'false'; + let targetId = el.getAttribute('data-controls'); + el.setAttribute('aria-expanded', expanded); - var targetId = el.getAttribute('data-controls'); + if (targetId) { - var target = document.getElementById(targetId); + let target = document.getElementById(targetId); + this.addRemoveClass(target, 'is-active', expanded); } } @@ -155,22 +171,28 @@ let BookWyrm = new class { } addClass(el, classname) { - var classes = el.className.split(' '); + let classes = el.className.split(' '); + if (classes.indexOf(classname) > -1) { return; } + el.className = classes.concat(classname).join(' '); } removeClass(el, className) { - var classes = []; + let classes = []; + if (el.className) { classes = el.className.split(' '); } + const idx = classes.indexOf(className); + if (idx > -1) { classes.splice(idx, 1); } + el.className = classes.join(' '); } } diff --git a/bookwyrm/static/js/localstorage.js b/bookwyrm/static/js/localstorage.js index b8ef02cd8..08b831624 100644 --- a/bookwyrm/static/js/localstorage.js +++ b/bookwyrm/static/js/localstorage.js @@ -15,8 +15,9 @@ let LocalStorageTools = new class { // set javascript listeners updateDisplay(e) { // used in set reading goal - var key = e.target.getAttribute('data-id'); - var value = e.target.getAttribute('data-value'); + let key = e.target.getAttribute('data-id'); + let value = e.target.getAttribute('data-value'); + window.localStorage.setItem(key, value); document.querySelectorAll('[data-hide="' + key + '"]') @@ -25,8 +26,9 @@ let LocalStorageTools = new class { setDisplay(el) { // used in set reading goal - var key = el.getAttribute('data-hide'); - var value = window.localStorage.getItem(key); + let key = el.getAttribute('data-hide'); + let value = window.localStorage.getItem(key); + BookWyrm.addRemoveClass(el, 'hidden', value); } }