From 21c15f4cb94edb142a94f344db3bfc4c6322cbb1 Mon Sep 17 00:00:00 2001 From: rr- Date: Mon, 11 Apr 2016 22:38:59 +0200 Subject: [PATCH] client/settings: add accountless settings --- client/css/forms.css | 7 +++ client/css/main.css | 1 + client/css/users.css | 8 --- client/html/settings.hbs | 18 +++++++ client/js/controllers/settings_controller.js | 53 ++++++++++++++++++++ client/js/controllers/top_nav_controller.js | 2 + client/js/main.js | 1 + client/js/util/handlebars-helpers.js | 2 + client/js/views/settings_view.js | 30 +++++++++++ 9 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 client/html/settings.hbs create mode 100644 client/js/controllers/settings_controller.js create mode 100644 client/js/views/settings_view.js diff --git a/client/css/forms.css b/client/css/forms.css index 00cebc9..1d30e86 100644 --- a/client/css/forms.css +++ b/client/css/forms.css @@ -25,6 +25,13 @@ form .input li:first-child { padding-top: 0; margin-top: 0; } +form .hint { + margin-top: 0.5em; + margin-bottom: 0; + color: var(--inactive-link-color); + font-size: 80%; + line-height: 120%; +} form.tabular ul { display: table; diff --git a/client/css/main.css b/client/css/main.css index ad09687..bbec016 100644 --- a/client/css/main.css +++ b/client/css/main.css @@ -130,6 +130,7 @@ nav.text-nav ul li.active a { #top-nav ul li[data-name=register], #top-nav ul li[data-name=login], #top-nav ul li[data-name=logout], +#top-nav ul li[data-name=settings], #top-nav ul li[data-name=help] { float: none; } diff --git a/client/css/users.css b/client/css/users.css index 85e0e2f..0a30b42 100644 --- a/client/css/users.css +++ b/client/css/users.css @@ -26,14 +26,6 @@ #user-registration .info p:first-child { margin: 0 0 0.5em 0; } -#user .hint, -#user-registration .hint { - margin-top: 0.5em; - margin-bottom: 0; - color: var(--inactive-link-color); - font-size: 80%; - line-height: 120%; -} #login .buttons a { margin-left: 1em; diff --git a/client/html/settings.hbs b/client/html/settings.hbs new file mode 100644 index 0000000..aea5574 --- /dev/null +++ b/client/html/settings.hbs @@ -0,0 +1,18 @@ +
+
+ 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.

+
+
    +
  • + {{checkbox text='Endless scroll' id='endless-scroll' name='endless-scroll' checked=this.browsingSettings.endlessScroll}} +

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

    +
  • +
+
+
+
+ +
+
+
diff --git a/client/js/controllers/settings_controller.js b/client/js/controllers/settings_controller.js new file mode 100644 index 0000000..731ea2d --- /dev/null +++ b/client/js/controllers/settings_controller.js @@ -0,0 +1,53 @@ +'use strict'; + +const page = require('page'); +const events = require('../events.js'); +const topNavController = require('../controllers/top_nav_controller.js'); +const SettingsView = require('../views/settings_view.js'); + +class SettingsController { + constructor() { + this.settingsView = new SettingsView(); + } + + registerRoutes() { + page('/settings', (ctx, next) => { this.settingsRoute(); }); + } + + settingsRoute() { + topNavController.activate('settings'); + this.settingsView.render({ + getSettings: () => this.getSettings(), + saveSettings: newSettings => this.saveSettings(newSettings), + }); + } + + saveSettings(browsingSettings) { + localStorage.setItem('settings', JSON.stringify(browsingSettings)); + events.notify(events.Success, 'Settings saved'); + } + + getSettings(settings) { + const defaultSettings = { + endlessScroll: false, + }; + let ret = {}; + let userSettings = localStorage.getItem('settings'); + if (userSettings) { + userSettings = JSON.parse(userSettings); + } + if (!userSettings) { + userSettings = {}; + } + for (let key of Object.keys(defaultSettings)) { + if (key in userSettings) { + ret[key] = userSettings[key]; + } else { + ret[key] = defaultSettings[key]; + } + } + return ret; + } +}; + +module.exports = new SettingsController(); diff --git a/client/js/controllers/top_nav_controller.js b/client/js/controllers/top_nav_controller.js index a9c15ea..51d3002 100644 --- a/client/js/controllers/top_nav_controller.js +++ b/client/js/controllers/top_nav_controller.js @@ -31,6 +31,8 @@ class TopNavController { 'login': new NavigationItem('L', 'Log in', '/login'), 'logout': new NavigationItem('O', 'Logout', '/logout'), 'help': new NavigationItem('E', 'Help', '/help'), + 'settings': new NavigationItem( + null, '', '/settings'), }; const rerender = () => { diff --git a/client/js/main.js b/client/js/main.js index 6f9e275..366bc2f 100644 --- a/client/js/main.js +++ b/client/js/main.js @@ -10,6 +10,7 @@ controllers.push(require('./controllers/help_controller.js')); controllers.push(require('./controllers/comments_controller.js')); controllers.push(require('./controllers/history_controller.js')); controllers.push(require('./controllers/tags_controller.js')); +controllers.push(require('./controllers/settings_controller.js')); controllers.push(require('./controllers/home_controller.js')); diff --git a/client/js/util/handlebars-helpers.js b/client/js/util/handlebars-helpers.js index 514509a..712782f 100644 --- a/client/js/util/handlebars-helpers.js +++ b/client/js/util/handlebars-helpers.js @@ -47,6 +47,8 @@ handlebars.registerHelper('checkbox', function(options) { name: options.hash.name, value: options.hash.value, type: 'checkbox', + checked: options.hash.checked !== undefined ? + options.hash.checked : false, required: options.hash.required, }), views.makeNonVoidElement('label', { diff --git a/client/js/views/settings_view.js b/client/js/views/settings_view.js new file mode 100644 index 0000000..60de50a --- /dev/null +++ b/client/js/views/settings_view.js @@ -0,0 +1,30 @@ +'use strict'; + +const views = require('../util/views.js'); + +class SettingsView { + constructor() { + this.template = views.getTemplate('settings'); + } + + render(ctx) { + const target = document.getElementById('content-holder'); + const source = this.template({browsingSettings: ctx.getSettings()}); + + const form = source.querySelector('form'); + views.decorateValidator(form); + + form.addEventListener('submit', e => { + e.preventDefault(); + views.clearMessages(source); + ctx.saveSettings({ + endlessScroll: form.querySelector('#endless-scroll').checked, + }); + }); + + views.listenToMessages(target); + views.showView(target, source); + } +} + +module.exports = SettingsView;