├── .travis.yml ├── index.js ├── package.json ├── readme.md └── test.js /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var events = ['onadd', 'onupdate', 'ondiscard'] 2 | 3 | module.exports = hooks 4 | 5 | function hooks (morphdom) { 6 | if (!callable(morphdom)) throw new Error('morphdom must be a function') 7 | 8 | return function main (fromNode, toNode, opts) { 9 | if (typeof opts === 'undefined') opts = {} 10 | 11 | return morphdom(fromNode, toNode, { 12 | onBeforeElUpdated: function (fromEl, toEl) { 13 | events.forEach(function (event) { 14 | if (callable(toEl[event])) { 15 | fromEl[event] = toEl[event] 16 | } else if (callable(fromEl[event])) { 17 | delete fromEl[event] 18 | } 19 | }) 20 | if (callable(opts.onBeforeElUpdated)) { 21 | return opts.onBeforeElUpdated(fromEl, toEl) 22 | } 23 | }, 24 | 25 | onNodeAdded: function (node) { 26 | if (callable(node.onadd)) node.onadd(node) 27 | if (callable(opts.onNodeAdded)) opts.onNodeAdded(node) 28 | }, 29 | 30 | onElUpdated: function (el) { 31 | if (callable(el.onupdate)) el.onupdate(el) 32 | if (callable(opts.onElUpdated)) opts.onElUpdated(el) 33 | }, 34 | 35 | onNodeDiscarded: function (node) { 36 | if (callable(node.ondiscard)) node.ondiscard(node) 37 | if (callable(opts.onNodeDiscarded)) opts.onNodeDiscarded(node) 38 | } 39 | }) 40 | } 41 | } 42 | 43 | function callable (fn) { 44 | return typeof fn === 'function' 45 | } 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "morphdom-hooks", 3 | "version": "0.0.2", 4 | "description": "Lifecycle hooks for morphdom", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/callum/morphdom-hooks.git" 12 | }, 13 | "keywords": [ 14 | "hook", 15 | "lifecycle", 16 | "morphdom" 17 | ], 18 | "author": "Callum Jefferies (http://callumj.uk/)", 19 | "license": "ISC", 20 | "bugs": { 21 | "url": "https://github.com/callum/morphdom-hooks/issues" 22 | }, 23 | "homepage": "https://github.com/callum/morphdom-hooks#readme", 24 | "peerDependencies": { 25 | "morphdom": ">=1.2.0" 26 | }, 27 | "devDependencies": { 28 | "tape": "^4.5.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # morphdom-hooks 2 | 3 | [![Build Status](https://travis-ci.org/callum/morphdom-hooks.svg?branch=master)](https://travis-ci.org/callum/morphdom-hooks) 4 | 5 | Lifecycle hooks for morphdom 6 | 7 | # example 8 | 9 | ```js 10 | const hooks = require('./') 11 | const morphdom = hooks(require('morphdom')) 12 | 13 | // create a button with some lifecycle handlers attached to it 14 | function button () { 15 | const b = document.createElement('button') 16 | b.onadd = console.log.bind(console, 'button added to page!') 17 | b.onupdate = console.log.bind(console, 'button updated in page!') 18 | b.ondiscard = console.log.bind(console, 'button discarded from page!') 19 | return b 20 | } 21 | 22 | const div0 = document.createElement('div') 23 | document.body.appendChild(div0) 24 | 25 | const div1 = document.createElement('div') 26 | const button0 = button() 27 | div1.appendChild(button0) 28 | morphdom(div0, div1) 29 | // logs 'button added to page!' 30 | 31 | const div2 = document.createElement('div') 32 | const button1 = button() 33 | button1.style.color = 'red' 34 | div2.appendChild(button1) 35 | morphdom(div0, div2) 36 | // logs 'button updated in page!' 37 | 38 | const div3 = document.createElement('div') 39 | morphdom(div0, div3) 40 | // logs 'button discarded from page!' 41 | ``` 42 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var hooks = require('./') 3 | 4 | test('throws', function (t) { 5 | t.plan(1) 6 | t.throws(hooks) 7 | }) 8 | 9 | test('wrapping morphdom', function (t) { 10 | t.plan(6) 11 | hooks(lib)('foo', 'bar', { 12 | onBeforeElUpdated: pass, 13 | onNodeAdded: pass, 14 | onElUpdated: pass, 15 | onNodeDiscarded: pass 16 | }) 17 | 18 | function lib (fr, to, opts) { 19 | t.equal(fr, 'foo') 20 | t.equal(to, 'bar') 21 | opts.onBeforeElUpdated({}, {}) 22 | opts.onNodeAdded({}) 23 | opts.onElUpdated({}) 24 | opts.onNodeDiscarded({}) 25 | } 26 | 27 | function pass () { 28 | t.pass('should call function') 29 | } 30 | }) 31 | 32 | test('events', function (t) { 33 | t.plan(3) 34 | var foo = {} 35 | var handleEvent = function (foo) { 36 | t.ok(foo, 'should call function') 37 | } 38 | foo.onadd = handleEvent 39 | foo.onupdate = handleEvent 40 | foo.ondiscard = handleEvent 41 | hooks(lib)() 42 | 43 | function lib (fr, to, opts) { 44 | opts.onNodeAdded(foo) 45 | opts.onElUpdated(foo) 46 | opts.onNodeDiscarded(foo) 47 | } 48 | }) 49 | 50 | test('copying events', function (t) { 51 | t.plan(6) 52 | var foo = {} 53 | var bar = {} 54 | bar.onadd = noop 55 | bar.onupdate = noop 56 | bar.ondiscard = noop 57 | var baz = {} 58 | 59 | var morphdom = hooks(lib) 60 | morphdom(foo, bar) 61 | t.equal(typeof foo.onadd, 'function') 62 | t.equal(typeof foo.onupdate, 'function') 63 | t.equal(typeof foo.ondiscard, 'function') 64 | morphdom(foo, baz) 65 | t.equal(typeof foo.onadd, 'undefined') 66 | t.equal(typeof foo.onupdate, 'undefined') 67 | t.equal(typeof foo.ondiscard, 'undefined') 68 | 69 | function lib (fr, to, opts) { 70 | opts.onBeforeElUpdated(fr, to) 71 | } 72 | 73 | function noop () {} 74 | }) 75 | --------------------------------------------------------------------------------