import { composeProps } from '@/core/modules/refs'
import eventBus from '@/core/modules/eventBus'
import * as Actions from '@/core/router/actions'
/**
* @namespace dom
*/
class MixinBuilder {
constructor(superclass) {
this.superclass = superclass
}
with(...mixins) {
return mixins.reduce((c, mixin) => mixin(c), this.superclass)
}
}
export const mix = superclass => new MixinBuilder(superclass)
/**
*
* @namespace Behavior
* @description Behavior class to handle adding/removing functionality from the dom.
* Use the mixins to add enhancements
*
* @class Behavior
*
* @param {HTMLElement} el - the html element to bind the behaviour too
* @param {String} name - a name to give the behaviour
*
* @property {String} Behaviour.$name - The name given to the behaviour
* @property {HTMLElement} Behaviour.$el - The element the behaviour is attached to
* @property {HTMLElement} Behaviour.$body - the body element
* @property {HTMLElement} Behaviour.$html - the html element
* @property {Object} Behaviour.$data - any data attributes on the $el
* @property {Function} Behaviour.$$$eventBus.on - global event emitter, listen to events
* @property {Function} Behaviour.$$$eventBus.off - global event emitter, remove to events
* @property {Function} Behaviour.$$$eventBus.emit - global event emitter, emit event
* @property {Object} Behavior.KEY_CODES
* @property {Number} Behaviour.KEY_CODS.DELETE_KEY - delete
* @property {Number} Behaviour.KEY_CODS.SHIFT_KEY - shift
* @property {Number} Behaviour.KEY_CODS.CTRL_KEY - control
* @property {Number} Behaviour.KEY_CODS.ALT_KEY - alt
* @property {Number} Behaviour.KEY_CODS.RETURN_KEY - return
* @property {Number} Behaviour.KEY_CODS.ESC_KEY - escape
* @property {Number} Behaviour.KEY_CODS.SPACE_KEY - space
* @property {Number} Behaviour.KEY_CODS.LEFT_KEY - left
* @property {Number} Behaviour.KEY_CODS.UP_KEY - up
* @property {Number} Behaviour.KEY_CODS.RIGHT_KEY - right
* @property {Number} Behaviour.KEY_CODS.DOWN_KEY - down
* @property {Number} Behaviour.KEY_CODS.CMD_KEY - command
* @example
* import Behaviour from '@/core/Behaviour'
*
* export default class ExampleWithAllTheThings Behaviour {
* mount = () => {
* // this.$el === the node with the data-behaviour
* this.$el.classList.add('mount')
* // this.$body === <body></body>
* // this.$html === <html></html>
* // this.KEY_CODES === common key codes
* // this.$data === any data attributes on this.$el
* }
*
* unmount = () => {}
* }
*
* @return {Behavior}
*/
export default (() => {
const $html = document.getElementsByTagName('html')[0]
const $body = document.body
const KEY_CODES = {
DELETE_KEY: 8,
SHIFT_KEY: 16,
CTRL_KEY: 17,
ALT_KEY: 18,
RETURN_KEY: 13,
ESC_KEY: 27,
SPACE_KEY: 32,
LEFT_KEY: 37,
UP_KEY: 38,
RIGHT_KEY: 39,
DOWN_KEY: 40,
A_KEY: 65,
S_KEY: 83,
CMD_KEY: 91
}
return class Behaviour {
constructor(el = document, name = '') {
this.$name = name
this.$el = el
this.$body = $body
this.$html = $html
this.$$eventBus = eventBus
this.KEY_CODES = KEY_CODES
this.$data = this.$el.attributes
? composeProps([...this.$el.attributes])
: null // here lies a bug
}
/**
* Create a router
* @memberof Behavior
*
* @method init
* @description initialise the router events
* @return {void}
*/
init() {
if (this.routes) {
if (this.routes.enter)
this.$$eventBus.on(Actions.ROUTE_TRANSITION_ENTER, this.routes.enter)
if (this.routes.exit)
this.$$eventBus.on(Actions.ROUTE_TRANSITION_EXIT, this.routes.exit)
}
}
/**
* Create a router
* @memberof Behavior
*
* @method mount
* @description called after instantiation
* @return {void}
*/
mount() {} // eslint-disable-line class-methods-use-this
/**
* Create a router
* @memberof Behavior
*
* @method unmount
* @description called when destroying
* @return {void}
*/
unmount() {} // eslint-disable-line class-methods-use-this
/**
* Create a router
* @memberof Behavior
*
* @method destroy
* @description kill the current behaviour
* @return {void}
*/
destroy() {
this.unmount()
if (this.routes) {
if (this.routes.enter)
this.$$eventBus.off(Actions.ROUTE_TRANSITION_ENTER, this.routes.enter)
if (this.routes.exit)
this.$$eventBus.off(Actions.ROUTE_TRANSITION_EXIT, this.routes.exit)
}
}
}
})()