From 3407c3f11883bdd6800a81bcd0caacbf74704035 Mon Sep 17 00:00:00 2001 From: Fred Every Date: Fri, 17 Aug 2018 16:40:25 +0200 Subject: [PATCH 1/4] #15 - Custom color config & handling --- README.md | 9 +++ src/scripts/config/styles.js | 8 +++ src/scripts/containers/UIContainer.js | 6 +- src/scripts/modules/Config.js | 13 +++- src/scripts/modules/Styles.js | 92 +++++++++++++++++++++++++++ src/templates/inputForm.html | 2 +- test/server/html/index.html | 8 +++ 7 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 src/scripts/config/styles.js create mode 100644 src/scripts/modules/Styles.js diff --git a/README.md b/README.md index 57a0526..2ead444 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,15 @@ new Typester({ configs: { toolbar: { buttons: ['bold', 'italic', 'h1', 'h2', 'orderedlist', 'unorderedlist', 'quote', 'link'] + }, + + styles: { + colors: { + flyoutBg: 'rgb(32, 31, 32)', + menuItemIcon: 'rgb(255, 255, 255)', + menuItemHover: 'rgb(0, 174, 239)', + menuItemActive: 'rgb(0, 156, 215)' + } } } }); diff --git a/src/scripts/config/styles.js b/src/scripts/config/styles.js new file mode 100644 index 0000000..7494347 --- /dev/null +++ b/src/scripts/config/styles.js @@ -0,0 +1,8 @@ +export default { + colors: { + flyoutBg: 'rgb(32, 31, 32)', + menuItemIcon: 'rgb(255, 255, 255)', + menuItemHover: 'rgb(0, 174, 239)', + menuItemActive: 'rgb(0, 156, 215)' + } +}; diff --git a/src/scripts/containers/UIContainer.js b/src/scripts/containers/UIContainer.js index 39183f9..194ba0b 100644 --- a/src/scripts/containers/UIContainer.js +++ b/src/scripts/containers/UIContainer.js @@ -19,6 +19,7 @@ import Container from '../core/Container'; import Toolbar from '../modules/Toolbar'; import Flyout from '../modules/Flyout'; import Mouse from '../modules/Mouse'; +import Styles from '../modules/Styles'; /** * @constructor UIContainer @@ -32,7 +33,7 @@ const UIContainer = Container({ /** * Child Modules: [{@link modules/Flyout}, {@link modules/Toolbar}] * Note: The Toobar is instantiated with the document body set as it's dom.el. - * @enum {Array<{class:Module}>} modules + * @enum {Array<{class:Module}>} modules */ modules: [ { @@ -48,6 +49,9 @@ const UIContainer = Container({ }, { class: Mouse + }, + { + class: Styles } ] }); diff --git a/src/scripts/modules/Config.js b/src/scripts/modules/Config.js index 3b045c0..b66d82c 100644 --- a/src/scripts/modules/Config.js +++ b/src/scripts/modules/Config.js @@ -1,11 +1,12 @@ import Module from '../core/Module'; import toolbarConfig from '../config/toolbar'; import config from '../config/config'; +import stylesConfig from '../config/styles'; const Config = Module({ name: 'Config', props: {}, - acceptsConfigs: ['toolbar'], + acceptsConfigs: ['toolbar', 'styles'], handlers: { requests: { @@ -16,7 +17,8 @@ const Config = Module({ 'config:toolbar:listTags' : 'getToolbarListTags', 'config:toolbar:preventNewlineDefault' : 'getToolbarPreventNewlineDefault', 'config:blockElementNames' : 'getConfigBlockElementNames', - 'config:defaultBlock' : 'getDefaultBlock' + 'config:defaultBlock' : 'getDefaultBlock', + 'config:styles': 'getStyles' } }, @@ -70,6 +72,13 @@ const Config = Module({ getDefaultBlock () { return config.defaultBlock; + }, + + getStyles () { + const { configs } = this; + return { + colors: Object.assign({}, stylesConfig.colors, configs.styles.colors) + }; } } }); diff --git a/src/scripts/modules/Styles.js b/src/scripts/modules/Styles.js new file mode 100644 index 0000000..93500c0 --- /dev/null +++ b/src/scripts/modules/Styles.js @@ -0,0 +1,92 @@ +// jshint strict: false + +/** + * Styles - + * Handle the creation and embedding of custom styles. + * @access protected + * @module modules/Styles + */ + +import Module from '../core/Module'; + +const Styles = Module({ + name: 'Styles', + + props: { + stylesheet: null, + }, + + handlers: {}, + + methods: { + setup () { + this.createStylesheet(); + }, + + init () { + const { mediator } = this; + const config = mediator.get('config:styles'); + let stylesheetContent = this.stylesTemplate(config); + + this.appendStylesheet(); + this.updateStylesheet(stylesheetContent); + }, + + stylesTemplate (config) { + return ` + .typester-toolbar .typester-menu-item, + .typester-input-form input[type=text], + .typester-link-display a, + .typester-input-form button { + color: ${config.colors.menuItemIcon}; + } + + .typester-toolbar .typester-menu-item svg, + .typester-link-display .typester-link-edit svg, + .typester-input-form button svg { + fill: ${config.colors.menuItemIcon}; + } + + .typester-input-form button svg { + stroke: ${config.colors.menuItemIcon}; + } + + .typester-toolbar .typester-menu-item:hover, + .typester-link-display .typester-link-edit:hover + .typester-input-form button:hover { + background: ${config.colors.menuItemHover}; + } + + .typester-toolbar .typester-menu-item.s--active { + background: ${config.colors.menuItemActive}; + } + + .typester-flyout .typester-flyout-content { + background: ${config.colors.flyoutBg}; + } + + .typester-flyout.place-above .typester-flyout-arrow { + border-top-color: ${config.colors.flyoutBg}; + } + + .typester-flyout.place-below .typester-flyout-arrow { + border-bottom-color: ${config.colors.flyoutBg}; + } + `; + }, + + createStylesheet () { + this.stylesheet = document.createElement('style'); + }, + + appendStylesheet () { + document.head.appendChild(this.stylesheet); + }, + + updateStylesheet (stylesheetContent) { + this.stylesheet.textContent = stylesheetContent; + } + } +}); + +export default Styles; diff --git a/src/templates/inputForm.html b/src/templates/inputForm.html index 5c6abd0..8d7b77c 100644 --- a/src/templates/inputForm.html +++ b/src/templates/inputForm.html @@ -3,7 +3,7 @@ +
Inspect Content Inspect Canvas @@ -114,7 +117,7 @@

Typester test server

From 05e71fd473fa3281115c568e73a1f65f74329307 Mon Sep 17 00:00:00 2001 From: Fred Every Date: Mon, 20 Aug 2018 16:38:04 +0200 Subject: [PATCH 3/4] #15 - Wire in destroy flow --- src/scripts/core/Mediator.js | 23 +++++++++++++++++++++++ src/scripts/core/Module.js | 31 ++++++++++++++++++++++++++++++- src/scripts/modules/Styles.js | 14 +++++++++++++- test/server/html/index.html | 1 - 4 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/scripts/core/Mediator.js b/src/scripts/core/Mediator.js index 34a7cd6..216f0b2 100644 --- a/src/scripts/core/Mediator.js +++ b/src/scripts/core/Mediator.js @@ -122,6 +122,10 @@ const Mediator = function (opts={}) { if (requestHandler) { return requestHandler(options); } + }, + + destroy () { + requests.handlers = {}; } }; @@ -152,6 +156,10 @@ const Mediator = function (opts={}) { if (commandHandler) { commandHandler(options); } + }, + + destroy () { + commands.handlers = {}; } }; @@ -176,9 +184,18 @@ const Mediator = function (opts={}) { emit (eventKey, options) { const eventHandlers = events.getHandlers(eventKey); + if (eventHandlers.length) { eventHandlers.forEach((eventHandler) => eventHandler(options)); } + + if (eventKey === 'app:destroy') { + fn.destroy(); + } + }, + + destroy () { + events.handlers = {}; } }; @@ -370,6 +387,12 @@ const Mediator = function (opts={}) { getId () { return internal.id; + }, + + destroy () { + requests.destroy(); + commands.destroy(); + events.destroy(); } }; diff --git a/src/scripts/core/Module.js b/src/scripts/core/Module.js index 33d07e9..2bb8104 100644 --- a/src/scripts/core/Module.js +++ b/src/scripts/core/Module.js @@ -112,6 +112,11 @@ const Module = function (moduleObj) { moduleUtils.bindDomEvents(handlerMethods, context); }, + deregisterDomHandlers (domHandlersMap, context) { + let handlerMethods = moduleUtils.getHandlerMethods(domHandlersMap, context); + moduleUtils.unbindDomEvents(handlerMethods, context); + }, + getHandlerMethods (handlerMap, context) { let routedHandlers = {}; @@ -171,6 +176,22 @@ const Module = function (moduleObj) { }); }, + unbindDomEvents (handlers, context) { + const { dom } = context; + + if (!dom) { + return; + } + + Object.keys(handlers).forEach((eventElKey) => { + const [eventKey, elemKey] = eventElKey.split(' @'); + const elem = elemKey ? dom[elemKey][0] : dom.el[0]; + const eventHandler = handlers[eventElKey]; + + elem.removeEventListener(eventKey, eventHandler); + }); + }, + mergeProps (defaultProps, props={}) { let mergedProps = {}; @@ -248,6 +269,10 @@ const Module = function (moduleObj) { context.setup(); } + context.mediator.registerHandler('event', 'app:destroy', function () { + moduleProto.destroyModule(opts); + }); + if (moduleHandlers) { moduleUtils.registerHandlers(opts.mediator, moduleHandlers, context); } @@ -280,8 +305,12 @@ const Module = function (moduleObj) { } }, - destroyModule () { + destroyModule (opts) { + const { context } = opts; + if (moduleHandlers.domEvents) { + moduleUtils.deregisterDomHandlers(moduleHandlers.domEvents, context); + } } }; diff --git a/src/scripts/modules/Styles.js b/src/scripts/modules/Styles.js index 93500c0..fdc9017 100644 --- a/src/scripts/modules/Styles.js +++ b/src/scripts/modules/Styles.js @@ -16,7 +16,11 @@ const Styles = Module({ stylesheet: null, }, - handlers: {}, + handlers: { + events: { + 'app:destroy': 'destroy' + } + }, methods: { setup () { @@ -85,6 +89,14 @@ const Styles = Module({ updateStylesheet (stylesheetContent) { this.stylesheet.textContent = stylesheetContent; + }, + + removeStylesheet () { + document.head.removeChild(this.stylesheet); + }, + + destroy () { + this.removeStylesheet(); } } }); diff --git a/test/server/html/index.html b/test/server/html/index.html index 5dafe76..bd58a23 100644 --- a/test/server/html/index.html +++ b/test/server/html/index.html @@ -133,7 +133,6 @@

} } }); - console.log(typesterInstance); diff --git a/test/e2e/test/pages/index.js b/test/e2e/test/pages/index.js index e16c727..8c3a5d4 100644 --- a/test/e2e/test/pages/index.js +++ b/test/e2e/test/pages/index.js @@ -174,6 +174,24 @@ var pageCommands = { }, [], function (response) { console.log(response); }); + return this; + }, + + destroy: function () { + var api = this.api; + + api.execute(function () { + try { + window.typesterInstance.destroy(); + return 'Destroyed!'; + } catch (e) { + return e.message; + } + }, [], function (response) { + console.log('Destroy:'); + console.log(response); + }); + return this; } }; diff --git a/test/e2e/test/specs/core/core.js b/test/e2e/test/specs/core/core.js index c19800b..600d31e 100644 --- a/test/e2e/test/specs/core/core.js +++ b/test/e2e/test/specs/core/core.js @@ -12,5 +12,16 @@ module.exports = { .waitForElementPresent('.typester-canvas', 1000) .assert.attributeEquals('.content-editable', 'contenteditable', 'true') .end(); + }, + + 'Destroy': function (browser) { + var page = browser.page.index(); + + page.navigate() + .assert.elementPresent('.typester-toolbar') + .assert.elementPresent('.typester-canvas') + .destroy() + .assert.elementNotPresent('.typester-toolbar') + .assert.elementNotPresent('.typester-canvas'); } };