From 1b62daed9a04ed3af8e5b92d2ea2e514f4bdf1c1 Mon Sep 17 00:00:00 2001 From: rr- Date: Fri, 5 Aug 2016 20:09:11 +0200 Subject: [PATCH] client/general: clean up, refactor --- client/html/login.tpl | 19 ++++- client/html/password_reset.tpl | 6 +- client/html/settings.tpl | 82 ++++++++++++------ client/html/tag_delete.tpl | 6 +- client/html/user_delete.tpl | 6 +- client/html/user_edit.tpl | 44 ++++++++-- client/html/user_registration.tpl | 27 +++++- client/js/controllers/settings_controller.js | 2 +- client/js/tags.js | 22 ++--- client/js/util/misc.js | 50 +++++++---- client/js/util/views.js | 90 ++++++++++---------- client/js/views/login_view.js | 22 ++--- client/js/views/password_reset_view.js | 2 +- client/js/views/registration_view.js | 6 +- client/js/views/settings_view.js | 24 +++--- client/js/views/user_edit_view.js | 44 +++++----- 16 files changed, 283 insertions(+), 169 deletions(-) diff --git a/client/html/login.tpl b/client/html/login.tpl index d9e0735b..ec63e6cb 100644 --- a/client/html/login.tpl +++ b/client/html/login.tpl @@ -4,13 +4,26 @@
diff --git a/client/html/password_reset.tpl b/client/html/password_reset.tpl index 8169a2bf..a4ccc7ea 100644 --- a/client/html/password_reset.tpl +++ b/client/html/password_reset.tpl @@ -4,7 +4,11 @@
diff --git a/client/html/settings.tpl b/client/html/settings.tpl index 743d6cdc..1f524896 100644 --- a/client/html/settings.tpl +++ b/client/html/settings.tpl @@ -2,32 +2,62 @@
Browsing settings

These settings are saved to the browser's local storage and are not coupled to the user account, so they don't apply to other devices or browsers alike.

-
-
    -
  • - <%= ctx.makeCheckbox({text: 'Enable keyboard shortcuts', id: 'keyboard-shortcuts', name: 'keyboard-shortcuts', checked: ctx.browsingSettings.keyboardShortcuts}) %> - -
  • -
  • - <%= ctx.makeNumericInput({text: 'Number of posts per page', id: 'posts-per-page', name: 'posts-per-page', checked: ctx.browsingSettings.postCount, min: 10, max: 100, value: ctx.browsingSettings.postsPerPage}) %> -
  • -
  • - <%= ctx.makeCheckbox({text: 'Upscale small posts', id: 'upscale-small-posts', name: 'upscale-small-posts', checked: ctx.browsingSettings.upscaleSmallPosts}) %> -
  • -
  • - <%= ctx.makeCheckbox({text: 'Endless scroll', id: 'endless-scroll', name: 'endless-scroll', checked: ctx.browsingSettings.endlessScroll}) %> -

    Rather than using a paged navigation, smoothly scrolls through the content.

    -
  • -
  • - <%= ctx.makeCheckbox({text: 'Enable transparency grid', id: 'transparency-grid', name: 'transparency-grid', checked: ctx.browsingSettings.transparencyGrid}) %> -

    Renders a checkered pattern behind posts with transparent background.

    -
  • -
  • - <%= ctx.makeCheckbox({text: 'Show tag suggestions', id: 'tag-suggestions', name: 'tag-suggestions', checked: ctx.browsingSettings.tagSuggestions}) %> -

    Shows a popup with suggested tags in edit forms.

    -
  • -
-
+ +
diff --git a/client/html/tag_delete.tpl b/client/html/tag_delete.tpl index 5b63aa01..82736fc5 100644 --- a/client/html/tag_delete.tpl +++ b/client/html/tag_delete.tpl @@ -4,7 +4,11 @@
  • - <%= ctx.makeCheckbox({id: 'confirm-deletion', name: 'confirm-deletion', required: true, text: 'I confirm that I want to delete this tag.'}) %> + <%= ctx.makeCheckbox({ + name: 'confirm-deletion', + text: 'I confirm that I want to delete this tag.', + required: true, + }) %>
diff --git a/client/html/user_delete.tpl b/client/html/user_delete.tpl index c7c84330..9704492a 100644 --- a/client/html/user_delete.tpl +++ b/client/html/user_delete.tpl @@ -3,7 +3,11 @@
  • - <%= ctx.makeCheckbox({id: 'confirm-deletion', name: 'confirm-deletion', required: true, text: 'I confirm that I want to delete this account.'}) %> + <%= ctx.makeCheckbox({ + name: 'confirm-deletion', + text: 'I confirm that I want to delete this account.', + required: true, + }) %>
diff --git a/client/html/user_edit.tpl b/client/html/user_edit.tpl index 3805c145..88d60370 100644 --- a/client/html/user_edit.tpl +++ b/client/html/user_edit.tpl @@ -1,27 +1,46 @@
-
    +
      <% if (ctx.canEditName) { %>
    • - <%= ctx.makeTextInput({text: 'User name', id: 'user-name', name: 'name', value: ctx.user.name, pattern: ctx.userNamePattern}) %> + <%= ctx.makeTextInput({ + text: 'User name', + name: 'name', + value: ctx.user.name, + pattern: ctx.userNamePattern, + }) %>
    • <% } %> <% if (ctx.canEditPassword) { %>
    • - <%= ctx.makePasswordInput({text: 'Password', id: 'user-password', name: 'password', placeholder: 'leave blank if not changing', pattern: ctx.passwordPattern}) %> + <%= ctx.makePasswordInput({ + text: 'Password', + name: 'password', + placeholder: 'leave blank if not changing', + pattern: ctx.passwordPattern, + }) %>
    • <% } %> <% if (ctx.canEditEmail) { %>
    • - <%= ctx.makeEmailInput({text: 'Email', id: 'user-email', name: 'email', value: ctx.user.email}) %> + <%= ctx.makeEmailInput({ + text: 'Email', + name: 'email', + value: ctx.user.email, + }) %>
    • <% } %> <% if (ctx.canEditRank) { %>
    • - <%= ctx.makeSelect({text: 'Rank', id: 'user-rank', name: 'rank', keyValues: ctx.ranks, selectedKey: ctx.user.rank}) %> + <%= ctx.makeSelect({ + text: 'Rank', + name: 'rank', + keyValues: ctx.ranks, + selectedKey: ctx.user.rank, + }) %>
    • <% } %> @@ -30,8 +49,19 @@
      - <%= ctx.makeRadio({text: 'Gravatar', id: 'gravatar-radio', name: 'avatar-style', value: 'gravatar', selectedValue: ctx.user.avatarStyle}) %> - <%= ctx.makeRadio({text: 'Manual avatar', id: 'avatar-radio', name: 'avatar-style', value: 'manual', selectedValue: ctx.user.avatarStyle}) %> + <%= ctx.makeRadio({ + text: 'Gravatar', + name: 'avatar-style', + value: 'gravatar', + selectedValue: ctx.user.avatarStyle, + }) %> + + <%= ctx.makeRadio({ + text: 'Manual avatar', + name: 'avatar-style', + value: 'manual', + selectedValue: ctx.user.avatarStyle, + }) %>
      <% } %> diff --git a/client/html/user_registration.tpl b/client/html/user_registration.tpl index 8a6d3e4f..9db35ceb 100644 --- a/client/html/user_registration.tpl +++ b/client/html/user_registration.tpl @@ -4,14 +4,33 @@
      • - <%= ctx.makeTextInput({text: 'User name', id: 'user-name', name: 'user-name', placeholder: 'letters, digits, _, -', required: true, pattern: ctx.userNamePattern}) %> + <%= ctx.makeTextInput({ + text: 'User name', + name: 'name', + placeholder: 'letters, digits, _, -', + required: true, + pattern: ctx.userNamePattern, + }) %>
      • - <%= ctx.makePasswordInput({text: 'Password', id: 'user-password', name: 'user-password', placeholder: '5+ characters', required: true, pattern: ctx.passwordPattern}) %> + <%= ctx.makePasswordInput({ + text: 'Password', + name: 'password', + placeholder: '5+ characters', + required: true, + pattern: ctx.passwordPattern, + }) %>
      • - <%= ctx.makeEmailInput({text: 'Email', id: 'user-email', name: 'user-email', placeholder: 'optional'}) %> -

        Used for password reminder and to show a Gravatar. Leave blank for random Gravatar.

        + <%= ctx.makeEmailInput({ + text: 'Email', + name: 'email', + placeholder: 'optional', + }) %> +

        + Used for password reminder and to show a Gravatar. + Leave blank for random Gravatar. +

      diff --git a/client/js/controllers/settings_controller.js b/client/js/controllers/settings_controller.js index 237ad52f..a4fb1833 100644 --- a/client/js/controllers/settings_controller.js +++ b/client/js/controllers/settings_controller.js @@ -16,7 +16,7 @@ class SettingsController { _evtChange(e) { this._view.clearMessages(); - settings.save(e.detail.settings); + settings.save(e.detail); this._view.showSuccess('Settings saved.'); } }; diff --git a/client/js/tags.js b/client/js/tags.js index 3d62640e..9ed3a681 100644 --- a/client/js/tags.js +++ b/client/js/tags.js @@ -111,14 +111,14 @@ function getSuggestions(tagName) { return actualTag.suggestions || []; } -module.exports = { - getAllCategories: getAllCategories, - getAllTags: getAllTags, - getTagByName: getTagByName, - getCategoryByName: getCategoryByName, - getNameToTagMap: getNameToTagMap, - getOriginalTagName: getOriginalTagName, - refreshExport: refreshExport, - getAllImplications: getAllImplications, - getSuggestions: getSuggestions, -}; +module.exports = misc.arrayToObject([ + getAllCategories, + getAllTags, + getTagByName, + getCategoryByName, + getNameToTagMap, + getOriginalTagName, + refreshExport, + getAllImplications, + getSuggestions, +], func => func.name); diff --git a/client/js/util/misc.js b/client/js/util/misc.js index 5c05d738..629db902 100644 --- a/client/js/util/misc.js +++ b/client/js/util/misc.js @@ -260,21 +260,35 @@ function arraysDiffer(source1, source2) { source2.filter(value => !source1.includes(value)).length > 0); } -module.exports = { - range: range, - formatUrlParameters: formatUrlParameters, - parseUrlParameters: parseUrlParameters, - parseUrlParametersRoute: parseUrlParametersRoute, - formatRelativeTime: formatRelativeTime, - formatFileSize: formatFileSize, - formatMarkdown: formatMarkdown, - unindent: unindent, - enableExitConfirmation: enableExitConfirmation, - disableExitConfirmation: disableExitConfirmation, - confirmPageExit: confirmPageExit, - escapeHtml: escapeHtml, - makeCssName: makeCssName, - splitByWhitespace: splitByWhitespace, - arraysDiffer: arraysDiffer, - decamelize: decamelize, -}; +function arrayToObject(array, keySelector, valueSelector) { + if (keySelector === undefined) { + keySelector = item => item; + } + if (valueSelector === undefined) { + valueSelector = item => item; + } + return array.reduce((obj, item) => { + obj[keySelector(item)] = valueSelector(item); + return obj; + }, {}); +} + +module.exports = arrayToObject([ + range, + formatUrlParameters, + parseUrlParameters, + parseUrlParametersRoute, + formatRelativeTime, + formatFileSize, + formatMarkdown, + unindent, + enableExitConfirmation, + disableExitConfirmation, + confirmPageExit, + escapeHtml, + makeCssName, + splitByWhitespace, + arraysDiffer, + decamelize, + arrayToObject, +], func => func.name); diff --git a/client/js/util/views.js b/client/js/util/views.js index 49a62c7b..a98e4c05 100644 --- a/client/js/util/views.js +++ b/client/js/util/views.js @@ -204,7 +204,7 @@ function makeUserLink(user) { } function makeFlexboxAlign(options) { - return Array.from(misc.range(20)) + return [...misc.range(20)] .map(() => '
    • ').join(''); } @@ -326,31 +326,31 @@ function getTemplate(templatePath) { if (!ctx) { ctx = {}; } - Object.assign(ctx, { - getPostUrl: getPostUrl, - getPostEditUrl: getPostEditUrl, - makeRelativeTime: makeRelativeTime, - makeFileSize: makeFileSize, - makeMarkdown: makeMarkdown, - makeThumbnail: makeThumbnail, - makeRadio: makeRadio, - makeCheckbox: makeCheckbox, - makeSelect: makeSelect, - makeInput: makeInput, - makeButton: makeButton, - makeTextarea: makeTextarea, - makeTextInput: makeTextInput, - makePasswordInput: makePasswordInput, - makeEmailInput: makeEmailInput, - makeColorInput: makeColorInput, - makePostLink: makePostLink, - makeTagLink: makeTagLink, - makeUserLink: makeUserLink, - makeFlexboxAlign: makeFlexboxAlign, - makeAccessKey: makeAccessKey, - makeCssName: misc.makeCssName, - makeNumericInput: makeNumericInput, - }); + Object.assign(ctx, misc.arrayToObject([ + getPostUrl, + getPostEditUrl, + makeRelativeTime, + makeFileSize, + makeMarkdown, + makeThumbnail, + makeRadio, + makeCheckbox, + makeSelect, + makeInput, + makeButton, + makeTextarea, + makeTextInput, + makePasswordInput, + makeEmailInput, + makeColorInput, + makePostLink, + makeTagLink, + makeUserLink, + makeFlexboxAlign, + makeAccessKey, + misc.makeCssName, + makeNumericInput, + ], func => func.name)); return htmlToDom(templateFactory(ctx)); }; } @@ -389,7 +389,7 @@ function replaceContent(target, source) { target.removeChild(target.lastChild); } if (source instanceof NodeList) { - for (let child of Array.from(source)) { + for (let child of [...source]) { target.appendChild(child); } } else if (source instanceof Node) { @@ -468,21 +468,21 @@ document.addEventListener('input', e => { } }); -module.exports = { - htmlToDom: htmlToDom, - getTemplate: getTemplate, - replaceContent: replaceContent, - enableForm: enableForm, - disableForm: disableForm, - decorateValidator: decorateValidator, - makeVoidElement: makeVoidElement, - makeNonVoidElement: makeNonVoidElement, - syncScrollPosition: syncScrollPosition, - slideDown: slideDown, - slideUp: slideUp, - monitorNodeRemoval: monitorNodeRemoval, - clearMessages: clearMessages, - showError: showError, - showSuccess: showSuccess, - showInfo: showInfo, -}; +module.exports = misc.arrayToObject([ + htmlToDom, + getTemplate, + replaceContent, + enableForm, + disableForm, + decorateValidator, + makeVoidElement, + makeNonVoidElement, + syncScrollPosition, + slideDown, + slideUp, + monitorNodeRemoval, + clearMessages, + showError, + showSuccess, + showInfo, +], func => func.name); diff --git a/client/js/views/login_view.js b/client/js/views/login_view.js index 96d6d7d0..7d97982c 100644 --- a/client/js/views/login_view.js +++ b/client/js/views/login_view.js @@ -19,15 +19,15 @@ class LoginView extends events.EventTarget { views.syncScrollPosition(); views.decorateValidator(this._formNode); - this._userNameFieldNode.setAttribute('pattern', config.userNameRegex); - this._passwordFieldNode.setAttribute('pattern', config.passwordRegex); + this._userNameInputNode.setAttribute('pattern', config.userNameRegex); + this._passwordInputNode.setAttribute('pattern', config.passwordRegex); this._formNode.addEventListener('submit', e => { e.preventDefault(); this.dispatchEvent(new CustomEvent('submit', { detail: { - name: this._userNameFieldNode.value, - password: this._passwordFieldNode.value, - remember: this._rememberFieldNode.checked, + name: this._userNameInputNode.value, + password: this._passwordInputNode.value, + remember: this._rememberInputNode.checked, }, })); }); @@ -37,16 +37,16 @@ class LoginView extends events.EventTarget { return this._hostNode.querySelector('form'); } - get _userNameFieldNode() { - return this._formNode.querySelector('#user-name'); + get _userNameInputNode() { + return this._formNode.querySelector('[name=name]'); } - get _passwordFieldNode() { - return this._formNode.querySelector('#user-password'); + get _passwordInputNode() { + return this._formNode.querySelector('[name=password]'); } - get _rememberFieldNode() { - return this._formNode.querySelector('#remember-user'); + get _rememberInputNode() { + return this._formNode.querySelector('[name=remember-user]'); } disableForm() { diff --git a/client/js/views/password_reset_view.js b/client/js/views/password_reset_view.js index ddb9785e..d817a044 100644 --- a/client/js/views/password_reset_view.js +++ b/client/js/views/password_reset_view.js @@ -49,7 +49,7 @@ class PasswordResetView extends events.EventTarget { } get _userNameOrEmailFieldNode() { - return this._formNode.querySelector('#user-name'); + return this._formNode.querySelector('[name=user-name]'); } } diff --git a/client/js/views/registration_view.js b/client/js/views/registration_view.js index d7405144..fb924c2f 100644 --- a/client/js/views/registration_view.js +++ b/client/js/views/registration_view.js @@ -51,15 +51,15 @@ class RegistrationView extends events.EventTarget { } get _userNameFieldNode() { - return this._formNode.querySelector('#user-name'); + return this._formNode.querySelector('[name=name]'); } get _passwordFieldNode() { - return this._formNode.querySelector('#user-password'); + return this._formNode.querySelector('[name=password]'); } get _emailFieldNode() { - return this._formNode.querySelector('#user-email'); + return this._formNode.querySelector('[name=email]'); } } diff --git a/client/js/views/settings_view.js b/client/js/views/settings_view.js index 6b534c18..f8c83a01 100644 --- a/client/js/views/settings_view.js +++ b/client/js/views/settings_view.js @@ -30,20 +30,12 @@ class SettingsView extends events.EventTarget { e.preventDefault(); this.dispatchEvent(new CustomEvent('change', { detail: { - settings: { - upscaleSmallPosts: this._formNode.querySelector( - '#upscale-small-posts').checked, - endlessScroll: this._formNode.querySelector( - '#endless-scroll').checked, - keyboardShortcuts: this._formNode.querySelector( - '#keyboard-shortcuts').checked, - transparencyGrid: this._formNode.querySelector( - '#transparency-grid').checked, - tagSuggestions: this._formNode.querySelector( - '#tag-suggestions').checked, - postsPerPage: this._formNode.querySelector( - '#posts-per-page').value, - }, + upscaleSmallPosts: this._find('upscale-small-posts').checked, + endlessScroll: this._find('endless-scroll').checked, + keyboardShortcuts: this._find('keyboard-shortcuts').checked, + transparencyGrid: this._find('transparency-grid').checked, + tagSuggestions: this._find('tag-suggestions').checked, + postsPerPage: this._find('posts-per-page').value, }, })); } @@ -51,6 +43,10 @@ class SettingsView extends events.EventTarget { get _formNode() { return this._hostNode.querySelector('form'); } + + _find(nodeName) { + return this._formNode.querySelector('[name=' + nodeName + ']'); + } } module.exports = SettingsView; diff --git a/client/js/views/user_edit_view.js b/client/js/views/user_edit_view.js index 77f2ed9b..45dc3559 100644 --- a/client/js/views/user_edit_view.js +++ b/client/js/views/user_edit_view.js @@ -20,9 +20,9 @@ class UserEditView extends events.EventTarget { views.decorateValidator(this._formNode); this._avatarContent = null; - if (this._avatarContentFieldNode) { + if (this._avatarContentInputNode) { new FileDropperControl( - this._avatarContentFieldNode, + this._avatarContentInputNode, { lock: true, resolve: files => { @@ -62,24 +62,24 @@ class UserEditView extends events.EventTarget { detail: { user: this._user, - name: this._userNameFieldNode ? - this._userNameFieldNode.value : + name: this._userNameInputNode ? + this._userNameInputNode.value : undefined, - email: this._emailFieldNode ? - this._emailFieldNode.value : + email: this._emailInputNode ? + this._emailInputNode.value : undefined, - rank: this._rankFieldNode ? - this._rankFieldNode.value : + rank: this._rankInputNode ? + this._rankInputNode.value : undefined, - avatarStyle: this._avatarStyleFieldNode ? - this._avatarStyleFieldNode.value : + avatarStyle: this._avatarStyleInputNode ? + this._avatarStyleInputNode.value : undefined, - password: this._passwordFieldNode ? - this._passwordFieldNode.value : + password: this._passwordInputNode ? + this._passwordInputNode.value : undefined, avatarContent: this._avatarContent, @@ -91,27 +91,27 @@ class UserEditView extends events.EventTarget { return this._hostNode.querySelector('form'); } - get _rankFieldNode() { - return this._formNode.querySelector('#user-rank'); + get _rankInputNode() { + return this._formNode.querySelector('[name=rank]'); } - get _emailFieldNode() { - return this._formNode.querySelector('#user-email'); + get _emailInputNode() { + return this._formNode.querySelector('[name=email]'); } - get _userNameFieldNode() { - return this._formNode.querySelector('#user-name'); + get _userNameInputNode() { + return this._formNode.querySelector('[name=name]'); } - get _passwordFieldNode() { - return this._formNode.querySelector('#user-password'); + get _passwordInputNode() { + return this._formNode.querySelector('[name=password]'); } - get _avatarContentFieldNode() { + get _avatarContentInputNode() { return this._formNode.querySelector('#avatar-content'); } - get _avatarStyleFieldNode() { + get _avatarStyleInputNode() { return this._formNode.querySelector('[name=avatar-style]:checked'); } }