├── .gitignore ├── .npmignore ├── coverage ├── lcov-report │ ├── sort-arrow-sprite.png │ ├── prettify.css │ ├── index.html │ ├── wrist │ │ ├── index.html │ │ ├── wrist.js.html │ │ └── test.js.html │ ├── sorter.js │ ├── base.css │ └── prettify.js ├── lcov.info └── coverage.json ├── .travis.yml ├── examples ├── index.html ├── post.html ├── post.js ├── main.js ├── sync-model.html ├── sync-model.js └── SyncModel.js ├── test ├── index.html └── test.js ├── LICENSE.txt ├── package.json ├── wrist.min.js ├── README.md └── wrist.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/* -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .travis.yml 3 | .gitignore 4 | coverage/* 5 | examples/* 6 | node_modules/* 7 | test/* -------------------------------------------------------------------------------- /coverage/lcov-report/sort-arrow-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebReflection/wrist/HEAD/coverage/lcov-report/sort-arrow-sprite.png -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.12 4 | - 4 5 | - 6 6 | - 7 7 | git: 8 | depth: 1 9 | branches: 10 | only: 11 | - master 12 | after_success: 13 | - "npm run coveralls" 14 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 |

wrist.js examples

15 | 16 | -------------------------------------------------------------------------------- /examples/post.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /coverage/lcov-report/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} 2 | -------------------------------------------------------------------------------- /examples/post.js: -------------------------------------------------------------------------------- 1 | var post = { 2 | title: '', 3 | published: false 4 | }; 5 | 6 | var title = document.querySelector('input[name=title]'); 7 | var published = document.querySelector('input[name=published]'); 8 | 9 | // bind post properties to related inputs 10 | wrist.watch(post, 'title', function (prop, old, val) { 11 | title.value = val; 12 | }); 13 | wrist.watch(post, 'published', function (prop, old, val) { 14 | published.checked = val; 15 | }); 16 | 17 | // bind inputs to post related properties 18 | wrist.watch(title, 'value', function (prop, old, val) { 19 | post.title = val; 20 | }); 21 | wrist.watch(published, 'checked', function (prop, old, val) { 22 | post.published = val; 23 | }); 24 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | 15 |

results in console

16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | var input1 = document.body.appendChild( 2 | document.createElement('input') 3 | ); 4 | 5 | var input2 = document.body.appendChild( 6 | document.createElement('input') 7 | ); 8 | 9 | function changeValue1(prop, prev, curr) { 10 | input1[prop] = curr; 11 | } 12 | 13 | function changeValue2(prop, prev, curr) { 14 | input2[prop] = curr; 15 | } 16 | 17 | function changeGlobalTest(prop, prev, curr) { 18 | window.test[prop] = curr; 19 | } 20 | 21 | window.test = {}; 22 | 23 | wrist.watch(input1, 'value', changeValue2); 24 | wrist.watch(input1, 'value', changeGlobalTest); 25 | 26 | wrist.watch(input2, 'value', changeValue1); 27 | wrist.watch(input2, 'value', changeGlobalTest); 28 | 29 | wrist.watch(window.test, 'value', changeValue1); 30 | wrist.watch(window.test, 'value', changeValue2); 31 | 32 | test.value = 'change value'; 33 | 34 | try { console.log('try: test.value = 132;'); } catch(o_O) {} 35 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2017 by Andrea Giammarchi - @WebReflection 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/sync-model.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 27 | 32 | 33 | 34 | 35 |
dump
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wrist", 3 | "version": "0.0.3", 4 | "description": "Easy way to bind or react to properties change.", 5 | "main": "wrist.js", 6 | "devDependencies": { 7 | "coveralls": "^2.11.16", 8 | "istanbul": "^0.4.5", 9 | "jsdom": "^9.10.0", 10 | "tressa": "^0.2.0", 11 | "uglify-js": "^2.7.5" 12 | }, 13 | "scripts": { 14 | "build": "npm test && npm run minify && npm run size;", 15 | "test": "istanbul cover test/test.js", 16 | "minify": "uglifyjs wrist.js --comments=/^!/ --compress --mangle -o wrist.min.js", 17 | "size": "cat wrist.js | wc -c;cat wrist.min.js | wc -c;gzip -c wrist.min.js | wc -c", 18 | "coveralls": "cat ./coverage/lcov.info | coveralls" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/WebReflection/wrist.git" 23 | }, 24 | "keywords": [ 25 | "observer", 26 | "mutation", 27 | "watch", 28 | "unwatch", 29 | "react", 30 | "properties", 31 | "changes" 32 | ], 33 | "author": "Andrea Giammarchi", 34 | "license": "MIT", 35 | "bugs": { 36 | "url": "https://github.com/WebReflection/wrist/issues" 37 | }, 38 | "homepage": "https://github.com/WebReflection/wrist#readme" 39 | } 40 | -------------------------------------------------------------------------------- /examples/sync-model.js: -------------------------------------------------------------------------------- 1 | 2 | var model = { 3 | person : "bob" 4 | } 5 | 6 | var sel1; 7 | var twoWay; 8 | var oneWay; 9 | var clickOneWay; 10 | var dump; 11 | var killer; 12 | 13 | var sync 14 | 15 | function test(){ 16 | 17 | sel1 = document.getElementById("sel1"); 18 | twoWay = document.getElementById("twoWay"); 19 | oneWay = document.getElementById("oneWay"); 20 | clickOneWay = document.getElementById("clickOneWay"); 21 | clickOneWay.addEventListener("click", doOneWay) 22 | dump = document.getElementById("dump"); 23 | killer = document.getElementById("destroy"); 24 | killer.addEventListener("click", destroy) 25 | 26 | sync = new gieson.SyncModel({ 27 | model : model, 28 | callback : changed 29 | }); 30 | 31 | sync.link("person", sel1, "value"); 32 | sync.link("person", twoWay, "value"); 33 | sync.link("person", callme); 34 | 35 | } 36 | 37 | function changed(prop, prev, curr){ 38 | dump.innerHTML = JSON.stringify(model, true, "\t"); 39 | } 40 | 41 | function callme(prop, prev, curr) { 42 | oneWay.value = curr; 43 | } 44 | 45 | function doOneWay(e){ 46 | model.person = oneWay.value; 47 | } 48 | 49 | function destroy(){ 50 | sync.destroy(); 51 | sync = null; 52 | } 53 | 54 | document.addEventListener("DOMContentLoaded", test); 55 | 56 | try { console.log('try: model.person = "tom";'); } catch(o_O) {} 57 | 58 | -------------------------------------------------------------------------------- /wrist.min.js: -------------------------------------------------------------------------------- 1 | /*! (C) 2017 Andrea Giammarchi - MIT Style License */ 2 | var wrist=function(e){"use strict";function t(){}function n(e){var n=new t;return p.set(e,n),n}function r(e,t,n){var r=function(t){var r,l,i;if(this===e){if(f!==t)for(i=f,f=t,c.call(e,f),r=0,l=a.length;r 2 | 3 | 4 | Code coverage report for All files 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | / 20 |

21 |
22 |
23 | 98.33% 24 | Statements 25 | 59/60 26 |
27 |
28 | 86.96% 29 | Branches 30 | 40/46 31 |
32 |
33 | 92.31% 34 | Functions 35 | 12/13 36 |
37 |
38 | 98.25% 39 | Lines 40 | 56/57 41 |
42 |
43 |
44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
FileStatementsBranchesFunctionsLines
wrist/
98.33%59/6086.96%40/4692.31%12/1398.25%56/57
76 |
77 |
78 | 82 | 83 | 84 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /coverage/lcov-report/wrist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Code coverage report for wrist/ 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | all files wrist/ 20 |

21 |
22 |
23 | 98.33% 24 | Statements 25 | 59/60 26 |
27 |
28 | 86.96% 29 | Branches 30 | 40/46 31 |
32 |
33 | 92.31% 34 | Functions 35 | 12/13 36 |
37 |
38 | 98.25% 39 | Lines 40 | 56/57 41 |
42 |
43 |
44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
FileStatementsBranchesFunctionsLines
wrist.js
98.33%59/6086.96%40/4692.31%12/1398.25%56/57
76 |
77 |
78 | 82 | 83 | 84 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /wrist.js: -------------------------------------------------------------------------------- 1 | /*! (C) 2017 Andrea Giammarchi - MIT Style License */ 2 | /* 3 | Copyright (C) 2017 by Andrea Giammarchi - @WebReflection 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | */ 23 | var wrist = (function (O) {'use strict'; 24 | var 25 | ADD_EVENT = 'addEventListener', 26 | REMOVE_EVENT = 'removeEventListener', 27 | SECRET = '__oO()' + Math.random(), 28 | empty = {}, 29 | hOP = empty.hasOwnProperty, 30 | dP = O.defineProperty, 31 | gOPD = O.getOwnPropertyDescriptor, 32 | gPO = O.getPrototypeOf, 33 | gD = function (o, p) { 34 | if (p in o) { 35 | while (o && !hOP.call(o, p)) o = gPO(o); 36 | if (o) return gOPD(o, p); 37 | } 38 | }, 39 | wm = typeof WeakMap == 'function' ? 40 | new WeakMap : 41 | { 42 | get: function (a, b) { 43 | return hOP.call(a, SECRET) ? 44 | a[SECRET] : b; 45 | }, 46 | set: function (a, b) { 47 | dP(a, SECRET, {value: b}); 48 | } 49 | } 50 | ; 51 | 52 | function Wrist() {} 53 | Wrist.prototype = Object.create(null); 54 | 55 | function createWrist(object) { 56 | var wrist = new Wrist; 57 | wm.set(object, wrist); 58 | return wrist; 59 | } 60 | 61 | function createWatcher(object, wrist, prop) { 62 | var 63 | set = function ($) { 64 | var i, length, old; 65 | if (this === object) { 66 | if (value !== $) { 67 | old = value; 68 | value = $; 69 | setter.call(object, value); 70 | i = 0; 71 | length = callbacks.length; 72 | while (i < length) 73 | callbacks[i++].call(object, prop, old, value); 74 | } 75 | } else { 76 | setter.call(this, $); 77 | } 78 | }, 79 | callbacks = [], 80 | descriptor = gD(object, prop) || empty, 81 | getter = descriptor.get || function () { return value; }, 82 | setter = descriptor.set || function ($) { value = $; }, 83 | value = hOP.call(descriptor, 'value') ? 84 | descriptor.value : getter.call(object) 85 | ; 86 | 87 | return (wrist[prop] = { 88 | // ignored descriptor properties 89 | _: callbacks, 90 | d: descriptor === empty ? null : descriptor, 91 | h: function (e) { set.call(e.target, object[prop]); }, 92 | // regular descriptors properties 93 | configurable: true, 94 | enumerable: hOP.call(descriptor, 'enumerable') ? 95 | descriptor.enumerable : 96 | (String(prop)[0] !== '_'), 97 | get: getter, 98 | set: set 99 | }); 100 | } 101 | 102 | function unwatch(object, prop, callback) { 103 | var wrist = wm.get(object), callbacks, i, watcher; 104 | if (wrist && prop in wrist) { 105 | watcher = wrist[prop]; 106 | callbacks = watcher._; 107 | i = callbacks.indexOf(callback); 108 | if (-1 < i) { 109 | callbacks.splice(i, 1); 110 | if (callbacks.length < 1) { 111 | delete wrist[prop]; 112 | if (watcher.d) { 113 | dP(object, prop, watcher.d); 114 | } else { 115 | delete object[prop]; 116 | object[prop] = watcher.get.call(object); 117 | } 118 | if (REMOVE_EVENT in object) { 119 | object[REMOVE_EVENT]('change', watcher.h, false); 120 | object[REMOVE_EVENT]('input', watcher.h, false); 121 | } 122 | } 123 | } 124 | } 125 | } 126 | 127 | return { 128 | watch: function watch(object, prop, callback) { 129 | var 130 | wrist = wm.get(object) || createWrist(object), 131 | watcher = wrist[prop] || createWatcher(object, wrist, prop), 132 | callbacks = watcher._ 133 | ; 134 | if (callbacks.indexOf(callback) < 0) { 135 | callbacks.push(callback); 136 | dP(object, prop, watcher); 137 | if (ADD_EVENT in object) { 138 | object[ADD_EVENT]('change', watcher.h, false); 139 | object[ADD_EVENT]('input', watcher.h, false); 140 | } 141 | } 142 | return {unwatch: unwatch.bind(null, object, prop, callback)}; 143 | }, 144 | unwatch: unwatch 145 | }; 146 | 147 | }(Object)); 148 | 149 | try { module.exports = wrist; } catch(o_O) {} 150 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var test = require('tressa'); 2 | 3 | if (typeof global === 'undefined') window.global = window; 4 | 5 | var WeakMap = global.WeakMap; 6 | delete global.WeakMap; 7 | var wrist = require('../wrist'); 8 | global.WeakMap = WeakMap; 9 | 10 | var obj = {defined: true}; 11 | 12 | test.title('wrist'); 13 | 14 | test(typeof wrist === 'object', 'module status'); 15 | 16 | 17 | test.async(function (done) { 18 | wrist.watch(obj, 'test', function watcher(prop, prev, curr) { 19 | test.log('## undefined property'); 20 | test(this === obj, 'correct context'); 21 | test(prop === 'test', 'correct name'); 22 | test(prev === undefined, 'correct old value'); 23 | test(curr === 123, 'correct new value'); 24 | wrist.unwatch(obj, 'test', watcher); 25 | obj.test = null; 26 | done(); 27 | }); 28 | }); 29 | 30 | test.async(function (done) { 31 | wrist.watch(obj, 'defined', function watcher(prop, prev, curr) { 32 | test.log('## defined property'); 33 | test(this === obj, 'correct context'); 34 | test(prop === 'defined', 'correct name'); 35 | test(prev === true, 'correct old value'); 36 | test(curr === false, 'correct old value'); 37 | wrist.unwatch(obj, 'defined', watcher); 38 | obj.defined = null; 39 | done(); 40 | }); 41 | }); 42 | 43 | test.async(function (done) { 44 | var watcher = wrist.watch(obj, 'self', function (prop, prev, curr) { 45 | test.log('## watcher.unwatch()'); 46 | test(this === obj, 'correct context'); 47 | test(prop === 'self', 'correct name'); 48 | test(prev === undefined, 'correct old value'); 49 | test(curr === false, 'correct new value'); 50 | watcher.unwatch(); 51 | obj.self = null; 52 | done(); 53 | }); 54 | }); 55 | 56 | obj.test = 123; 57 | obj.defined = false; 58 | obj.self = false; 59 | 60 | test.async(function (done) { 61 | test.log('## no duplicates'); 62 | var o = {prop: 123}; 63 | var i = 0; 64 | var watcher = wrist.watch(o, 'prop', function (prop, prev, curr) { 65 | i++; 66 | test(this === o, 'correct context'); 67 | test(prop === 'prop', 'correct name'); 68 | test(prev === 123, 'correct old value'); 69 | test(curr === 456, 'correct new value'); 70 | }); 71 | test(i === 0, 'not called yet'); 72 | o.prop = 456; 73 | o.prop = 456; 74 | test(i === 1, 'called only once'); 75 | watcher.unwatch(); 76 | done(); 77 | }); 78 | 79 | test.async(function (done) { 80 | test.log('## inherited setter'); 81 | function Class() {} 82 | function watch(prop, prev, curr) { 83 | test(this === o, 'correct context'); 84 | test(prop === 'test', 'correct name'); 85 | test(prev === 0, 'correct old value'); 86 | test(curr === 1, 'correct new value'); 87 | } 88 | var i = 0; 89 | Object.defineProperty(Class.prototype, 'test', { 90 | configurable: true, 91 | get: function () { return i; }, 92 | set: function (l) { i = l; } 93 | }); 94 | var o = new Class(); 95 | wrist.watch(o, 'test', watch); 96 | o.test += 1; 97 | wrist.unwatch(o, 'test', watch); 98 | done(); 99 | }); 100 | 101 | test.async(function (done) { 102 | test.log('## own setter'); 103 | function watch(prop, prev, curr) { 104 | test(this === o, 'correct context'); 105 | test(prop === 'test', 'correct name'); 106 | test(prev === 0, 'correct old value'); 107 | test(curr === 1, 'correct new value'); 108 | } 109 | var i = 0; 110 | var o = Object.defineProperty({}, 'test', { 111 | configurable: true, 112 | get: function () { return i; }, 113 | set: function (l) { i = l; } 114 | }); 115 | wrist.watch(o, 'test', watch); 116 | o.test += 1; 117 | wrist.unwatch(o, 'test', watch); 118 | done(); 119 | }); 120 | 121 | test.async(function (done) { 122 | test.log('## borrowed setter'); 123 | function watch(prop, prev, curr) { 124 | ++j; 125 | } 126 | var i = 0; 127 | var j = 0; 128 | var o = Object.defineProperty({}, 'test', { 129 | configurable: true, 130 | get: function () { return i; }, 131 | set: function (l) { i = l; } 132 | }); 133 | wrist.watch(o, 'test', watch); 134 | var z = Object.defineProperty({}, 'test', 135 | Object.getOwnPropertyDescriptor(o, 'test')); 136 | z.test = 456; 137 | test(j === 0, 'watcher not involved'); 138 | test(i === 456, 'setter called'); 139 | wrist.unwatch(o, 'test', watch); 140 | done(); 141 | }); 142 | 143 | 144 | test.async(function (done) { 145 | if (typeof document === 'undefined') { 146 | require('jsdom').env('', [], check); 147 | } else { 148 | document.body.appendChild(document.createElement('input')); 149 | check(null, window); 150 | } 151 | function check(err, window) { 152 | test.log('## DOM elements'); 153 | var input = window.document.body.getElementsByTagName('input')[0]; 154 | var value = ''; 155 | var watcher = wrist.watch(input, 'value', function (prop, prev, curr) { 156 | test(prop === 'value', 'correct name'); 157 | test(prev === value, 'correct old value'); 158 | test(curr === value + '0', 'correct new value'); 159 | value += '0'; 160 | }); 161 | input.value = '0'; 162 | setTimeout(function () { 163 | input.value += '0'; 164 | setTimeout(function () { 165 | watcher.unwatch(); 166 | done(); 167 | // for testing purpose only 168 | window.wrist = wrist; 169 | }, 1); 170 | }); 171 | } 172 | }); 173 | -------------------------------------------------------------------------------- /coverage/lcov-report/sorter.js: -------------------------------------------------------------------------------- 1 | var addSorting = (function () { 2 | "use strict"; 3 | var cols, 4 | currentSort = { 5 | index: 0, 6 | desc: false 7 | }; 8 | 9 | // returns the summary table element 10 | function getTable() { return document.querySelector('.coverage-summary'); } 11 | // returns the thead element of the summary table 12 | function getTableHeader() { return getTable().querySelector('thead tr'); } 13 | // returns the tbody element of the summary table 14 | function getTableBody() { return getTable().querySelector('tbody'); } 15 | // returns the th element for nth column 16 | function getNthColumn(n) { return getTableHeader().querySelectorAll('th')[n]; } 17 | 18 | // loads all columns 19 | function loadColumns() { 20 | var colNodes = getTableHeader().querySelectorAll('th'), 21 | colNode, 22 | cols = [], 23 | col, 24 | i; 25 | 26 | for (i = 0; i < colNodes.length; i += 1) { 27 | colNode = colNodes[i]; 28 | col = { 29 | key: colNode.getAttribute('data-col'), 30 | sortable: !colNode.getAttribute('data-nosort'), 31 | type: colNode.getAttribute('data-type') || 'string' 32 | }; 33 | cols.push(col); 34 | if (col.sortable) { 35 | col.defaultDescSort = col.type === 'number'; 36 | colNode.innerHTML = colNode.innerHTML + ''; 37 | } 38 | } 39 | return cols; 40 | } 41 | // attaches a data attribute to every tr element with an object 42 | // of data values keyed by column name 43 | function loadRowData(tableRow) { 44 | var tableCols = tableRow.querySelectorAll('td'), 45 | colNode, 46 | col, 47 | data = {}, 48 | i, 49 | val; 50 | for (i = 0; i < tableCols.length; i += 1) { 51 | colNode = tableCols[i]; 52 | col = cols[i]; 53 | val = colNode.getAttribute('data-value'); 54 | if (col.type === 'number') { 55 | val = Number(val); 56 | } 57 | data[col.key] = val; 58 | } 59 | return data; 60 | } 61 | // loads all row data 62 | function loadData() { 63 | var rows = getTableBody().querySelectorAll('tr'), 64 | i; 65 | 66 | for (i = 0; i < rows.length; i += 1) { 67 | rows[i].data = loadRowData(rows[i]); 68 | } 69 | } 70 | // sorts the table using the data for the ith column 71 | function sortByIndex(index, desc) { 72 | var key = cols[index].key, 73 | sorter = function (a, b) { 74 | a = a.data[key]; 75 | b = b.data[key]; 76 | return a < b ? -1 : a > b ? 1 : 0; 77 | }, 78 | finalSorter = sorter, 79 | tableBody = document.querySelector('.coverage-summary tbody'), 80 | rowNodes = tableBody.querySelectorAll('tr'), 81 | rows = [], 82 | i; 83 | 84 | if (desc) { 85 | finalSorter = function (a, b) { 86 | return -1 * sorter(a, b); 87 | }; 88 | } 89 | 90 | for (i = 0; i < rowNodes.length; i += 1) { 91 | rows.push(rowNodes[i]); 92 | tableBody.removeChild(rowNodes[i]); 93 | } 94 | 95 | rows.sort(finalSorter); 96 | 97 | for (i = 0; i < rows.length; i += 1) { 98 | tableBody.appendChild(rows[i]); 99 | } 100 | } 101 | // removes sort indicators for current column being sorted 102 | function removeSortIndicators() { 103 | var col = getNthColumn(currentSort.index), 104 | cls = col.className; 105 | 106 | cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); 107 | col.className = cls; 108 | } 109 | // adds sort indicators for current column being sorted 110 | function addSortIndicators() { 111 | getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; 112 | } 113 | // adds event listeners for all sorter widgets 114 | function enableUI() { 115 | var i, 116 | el, 117 | ithSorter = function ithSorter(i) { 118 | var col = cols[i]; 119 | 120 | return function () { 121 | var desc = col.defaultDescSort; 122 | 123 | if (currentSort.index === i) { 124 | desc = !currentSort.desc; 125 | } 126 | sortByIndex(i, desc); 127 | removeSortIndicators(); 128 | currentSort.index = i; 129 | currentSort.desc = desc; 130 | addSortIndicators(); 131 | }; 132 | }; 133 | for (i =0 ; i < cols.length; i += 1) { 134 | if (cols[i].sortable) { 135 | // add the click event handler on the th so users 136 | // dont have to click on those tiny arrows 137 | el = getNthColumn(i).querySelector('.sorter').parentElement; 138 | if (el.addEventListener) { 139 | el.addEventListener('click', ithSorter(i)); 140 | } else { 141 | el.attachEvent('onclick', ithSorter(i)); 142 | } 143 | } 144 | } 145 | } 146 | // adds sorting functionality to the UI 147 | return function () { 148 | if (!getTable()) { 149 | return; 150 | } 151 | cols = loadColumns(); 152 | loadData(cols); 153 | addSortIndicators(); 154 | enableUI(); 155 | }; 156 | })(); 157 | 158 | window.addEventListener('load', addSorting); 159 | -------------------------------------------------------------------------------- /coverage/lcov-report/base.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | margin:0; padding: 0; 3 | height: 100%; 4 | } 5 | body { 6 | font-family: Helvetica Neue, Helvetica, Arial; 7 | font-size: 14px; 8 | color:#333; 9 | } 10 | .small { font-size: 12px; } 11 | *, *:after, *:before { 12 | -webkit-box-sizing:border-box; 13 | -moz-box-sizing:border-box; 14 | box-sizing:border-box; 15 | } 16 | h1 { font-size: 20px; margin: 0;} 17 | h2 { font-size: 14px; } 18 | pre { 19 | font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; 20 | margin: 0; 21 | padding: 0; 22 | -moz-tab-size: 2; 23 | -o-tab-size: 2; 24 | tab-size: 2; 25 | } 26 | a { color:#0074D9; text-decoration:none; } 27 | a:hover { text-decoration:underline; } 28 | .strong { font-weight: bold; } 29 | .space-top1 { padding: 10px 0 0 0; } 30 | .pad2y { padding: 20px 0; } 31 | .pad1y { padding: 10px 0; } 32 | .pad2x { padding: 0 20px; } 33 | .pad2 { padding: 20px; } 34 | .pad1 { padding: 10px; } 35 | .space-left2 { padding-left:55px; } 36 | .space-right2 { padding-right:20px; } 37 | .center { text-align:center; } 38 | .clearfix { display:block; } 39 | .clearfix:after { 40 | content:''; 41 | display:block; 42 | height:0; 43 | clear:both; 44 | visibility:hidden; 45 | } 46 | .fl { float: left; } 47 | @media only screen and (max-width:640px) { 48 | .col3 { width:100%; max-width:100%; } 49 | .hide-mobile { display:none!important; } 50 | } 51 | 52 | .quiet { 53 | color: #7f7f7f; 54 | color: rgba(0,0,0,0.5); 55 | } 56 | .quiet a { opacity: 0.7; } 57 | 58 | .fraction { 59 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; 60 | font-size: 10px; 61 | color: #555; 62 | background: #E8E8E8; 63 | padding: 4px 5px; 64 | border-radius: 3px; 65 | vertical-align: middle; 66 | } 67 | 68 | div.path a:link, div.path a:visited { color: #333; } 69 | table.coverage { 70 | border-collapse: collapse; 71 | margin: 10px 0 0 0; 72 | padding: 0; 73 | } 74 | 75 | table.coverage td { 76 | margin: 0; 77 | padding: 0; 78 | vertical-align: top; 79 | } 80 | table.coverage td.line-count { 81 | text-align: right; 82 | padding: 0 5px 0 20px; 83 | } 84 | table.coverage td.line-coverage { 85 | text-align: right; 86 | padding-right: 10px; 87 | min-width:20px; 88 | } 89 | 90 | table.coverage td span.cline-any { 91 | display: inline-block; 92 | padding: 0 5px; 93 | width: 100%; 94 | } 95 | .missing-if-branch { 96 | display: inline-block; 97 | margin-right: 5px; 98 | border-radius: 3px; 99 | position: relative; 100 | padding: 0 4px; 101 | background: #333; 102 | color: yellow; 103 | } 104 | 105 | .skip-if-branch { 106 | display: none; 107 | margin-right: 10px; 108 | position: relative; 109 | padding: 0 4px; 110 | background: #ccc; 111 | color: white; 112 | } 113 | .missing-if-branch .typ, .skip-if-branch .typ { 114 | color: inherit !important; 115 | } 116 | .coverage-summary { 117 | border-collapse: collapse; 118 | width: 100%; 119 | } 120 | .coverage-summary tr { border-bottom: 1px solid #bbb; } 121 | .keyline-all { border: 1px solid #ddd; } 122 | .coverage-summary td, .coverage-summary th { padding: 10px; } 123 | .coverage-summary tbody { border: 1px solid #bbb; } 124 | .coverage-summary td { border-right: 1px solid #bbb; } 125 | .coverage-summary td:last-child { border-right: none; } 126 | .coverage-summary th { 127 | text-align: left; 128 | font-weight: normal; 129 | white-space: nowrap; 130 | } 131 | .coverage-summary th.file { border-right: none !important; } 132 | .coverage-summary th.pct { } 133 | .coverage-summary th.pic, 134 | .coverage-summary th.abs, 135 | .coverage-summary td.pct, 136 | .coverage-summary td.abs { text-align: right; } 137 | .coverage-summary td.file { white-space: nowrap; } 138 | .coverage-summary td.pic { min-width: 120px !important; } 139 | .coverage-summary tfoot td { } 140 | 141 | .coverage-summary .sorter { 142 | height: 10px; 143 | width: 7px; 144 | display: inline-block; 145 | margin-left: 0.5em; 146 | background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; 147 | } 148 | .coverage-summary .sorted .sorter { 149 | background-position: 0 -20px; 150 | } 151 | .coverage-summary .sorted-desc .sorter { 152 | background-position: 0 -10px; 153 | } 154 | .status-line { height: 10px; } 155 | /* dark red */ 156 | .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } 157 | .low .chart { border:1px solid #C21F39 } 158 | /* medium red */ 159 | .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } 160 | /* light red */ 161 | .low, .cline-no { background:#FCE1E5 } 162 | /* light green */ 163 | .high, .cline-yes { background:rgb(230,245,208) } 164 | /* medium green */ 165 | .cstat-yes { background:rgb(161,215,106) } 166 | /* dark green */ 167 | .status-line.high, .high .cover-fill { background:rgb(77,146,33) } 168 | .high .chart { border:1px solid rgb(77,146,33) } 169 | /* dark yellow (gold) */ 170 | .medium .chart { border:1px solid #f9cd0b; } 171 | .status-line.medium, .medium .cover-fill { background: #f9cd0b; } 172 | /* light yellow */ 173 | .medium { background: #fff4c2; } 174 | /* light gray */ 175 | span.cline-neutral { background: #eaeaea; } 176 | 177 | .cbranch-no { background: yellow !important; color: #111; } 178 | 179 | .cstat-skip { background: #ddd; color: #111; } 180 | .fstat-skip { background: #ddd; color: #111 !important; } 181 | .cbranch-skip { background: #ddd !important; color: #111; } 182 | 183 | 184 | .cover-fill, .cover-empty { 185 | display:inline-block; 186 | height: 12px; 187 | } 188 | .chart { 189 | line-height: 0; 190 | } 191 | .cover-empty { 192 | background: white; 193 | } 194 | .cover-full { 195 | border-right: none !important; 196 | } 197 | pre.prettyprint { 198 | border: none !important; 199 | padding: 0 !important; 200 | margin: 0 !important; 201 | } 202 | .com { color: #999 !important; } 203 | .ignore-none { color: #999; font-weight: normal; } 204 | 205 | .wrapper { 206 | min-height: 100%; 207 | height: auto !important; 208 | height: 100%; 209 | margin: 0 auto -48px; 210 | } 211 | .footer, .push { 212 | height: 48px; 213 | } 214 | -------------------------------------------------------------------------------- /coverage/coverage.json: -------------------------------------------------------------------------------- 1 | {"/home/webreflection/code/wrist/wrist.js":{"path":"/home/webreflection/code/wrist/wrist.js","s":{"1":1,"2":1,"3":8,"4":6,"5":2,"6":6,"7":6,"8":16,"9":6,"10":1,"11":1,"12":1,"13":6,"14":6,"15":6,"16":1,"17":8,"18":10,"19":10,"20":9,"21":8,"22":8,"23":8,"24":8,"25":8,"26":8,"27":8,"28":1,"29":4,"30":4,"31":8,"32":0,"33":1,"34":8,"35":8,"36":8,"37":8,"38":8,"39":8,"40":8,"41":8,"42":8,"43":8,"44":6,"45":2,"46":2,"47":8,"48":1,"49":1,"50":1,"51":8,"52":8,"53":8,"54":8,"55":8,"56":1,"57":1,"58":8,"59":1,"60":1},"b":{"1":[6,2],"2":[8,8],"3":[6,0],"4":[0,1],"5":[10,6],"6":[9,1],"7":[8,1],"8":[8,2],"9":[8,4],"10":[8,4],"11":[2,6],"12":[2,6],"13":[6,2],"14":[8,0],"15":[8,8],"16":[8,0],"17":[8,0],"18":[6,2],"19":[1,7],"20":[8,6],"21":[8,8],"22":[8,0],"23":[1,7]},"f":{"1":1,"2":8,"3":16,"4":6,"5":6,"6":6,"7":8,"8":10,"9":4,"10":4,"11":0,"12":8,"13":8},"fnMap":{"1":{"name":"(anonymous_1)","line":23,"loc":{"start":{"line":23,"column":13},"end":{"line":23,"column":26}}},"2":{"name":"(anonymous_2)","line":33,"loc":{"start":{"line":33,"column":9},"end":{"line":33,"column":25}}},"3":{"name":"(anonymous_3)","line":42,"loc":{"start":{"line":42,"column":13},"end":{"line":42,"column":29}}},"4":{"name":"(anonymous_4)","line":46,"loc":{"start":{"line":46,"column":13},"end":{"line":46,"column":29}}},"5":{"name":"Wrist","line":52,"loc":{"start":{"line":52,"column":2},"end":{"line":52,"column":19}}},"6":{"name":"createWrist","line":55,"loc":{"start":{"line":55,"column":2},"end":{"line":55,"column":31}}},"7":{"name":"createWatcher","line":61,"loc":{"start":{"line":61,"column":2},"end":{"line":61,"column":46}}},"8":{"name":"(anonymous_8)","line":63,"loc":{"start":{"line":63,"column":12},"end":{"line":63,"column":25}}},"9":{"name":"(anonymous_9)","line":81,"loc":{"start":{"line":81,"column":33},"end":{"line":81,"column":45}}},"10":{"name":"(anonymous_10)","line":82,"loc":{"start":{"line":82,"column":33},"end":{"line":82,"column":46}}},"11":{"name":"(anonymous_11)","line":91,"loc":{"start":{"line":91,"column":9},"end":{"line":91,"column":22}}},"12":{"name":"unwatch","line":102,"loc":{"start":{"line":102,"column":2},"end":{"line":102,"column":43}}},"13":{"name":"watch","line":128,"loc":{"start":{"line":128,"column":11},"end":{"line":128,"column":50}}}},"statementMap":{"1":{"start":{"line":23,"column":0},"end":{"line":147,"column":11}},"2":{"start":{"line":24,"column":2},"end":{"line":50,"column":3}},"3":{"start":{"line":34,"column":6},"end":{"line":37,"column":7}},"4":{"start":{"line":35,"column":8},"end":{"line":35,"column":48}},"5":{"start":{"line":35,"column":37},"end":{"line":35,"column":48}},"6":{"start":{"line":36,"column":8},"end":{"line":36,"column":33}},"7":{"start":{"line":36,"column":15},"end":{"line":36,"column":33}},"8":{"start":{"line":43,"column":10},"end":{"line":44,"column":26}},"9":{"start":{"line":47,"column":10},"end":{"line":47,"column":36}},"10":{"start":{"line":52,"column":2},"end":{"line":52,"column":21}},"11":{"start":{"line":53,"column":2},"end":{"line":53,"column":40}},"12":{"start":{"line":55,"column":2},"end":{"line":59,"column":3}},"13":{"start":{"line":56,"column":4},"end":{"line":56,"column":26}},"14":{"start":{"line":57,"column":4},"end":{"line":57,"column":26}},"15":{"start":{"line":58,"column":4},"end":{"line":58,"column":17}},"16":{"start":{"line":61,"column":2},"end":{"line":100,"column":3}},"17":{"start":{"line":62,"column":4},"end":{"line":85,"column":5}},"18":{"start":{"line":64,"column":8},"end":{"line":64,"column":27}},"19":{"start":{"line":65,"column":8},"end":{"line":77,"column":9}},"20":{"start":{"line":66,"column":10},"end":{"line":74,"column":11}},"21":{"start":{"line":67,"column":12},"end":{"line":67,"column":24}},"22":{"start":{"line":68,"column":12},"end":{"line":68,"column":22}},"23":{"start":{"line":69,"column":12},"end":{"line":69,"column":39}},"24":{"start":{"line":70,"column":12},"end":{"line":70,"column":18}},"25":{"start":{"line":71,"column":12},"end":{"line":71,"column":38}},"26":{"start":{"line":72,"column":12},"end":{"line":73,"column":60}},"27":{"start":{"line":73,"column":14},"end":{"line":73,"column":60}},"28":{"start":{"line":76,"column":10},"end":{"line":76,"column":31}},"29":{"start":{"line":81,"column":47},"end":{"line":81,"column":60}},"30":{"start":{"line":82,"column":48},"end":{"line":82,"column":58}},"31":{"start":{"line":87,"column":4},"end":{"line":99,"column":7}},"32":{"start":{"line":91,"column":24},"end":{"line":91,"column":57}},"33":{"start":{"line":102,"column":2},"end":{"line":125,"column":3}},"34":{"start":{"line":103,"column":4},"end":{"line":103,"column":54}},"35":{"start":{"line":104,"column":4},"end":{"line":124,"column":5}},"36":{"start":{"line":105,"column":6},"end":{"line":105,"column":28}},"37":{"start":{"line":106,"column":6},"end":{"line":106,"column":28}},"38":{"start":{"line":107,"column":6},"end":{"line":107,"column":38}},"39":{"start":{"line":108,"column":6},"end":{"line":123,"column":7}},"40":{"start":{"line":109,"column":8},"end":{"line":109,"column":31}},"41":{"start":{"line":110,"column":8},"end":{"line":122,"column":9}},"42":{"start":{"line":111,"column":10},"end":{"line":111,"column":29}},"43":{"start":{"line":112,"column":10},"end":{"line":117,"column":11}},"44":{"start":{"line":113,"column":12},"end":{"line":113,"column":40}},"45":{"start":{"line":115,"column":12},"end":{"line":115,"column":32}},"46":{"start":{"line":116,"column":12},"end":{"line":116,"column":52}},"47":{"start":{"line":118,"column":10},"end":{"line":121,"column":11}},"48":{"start":{"line":119,"column":12},"end":{"line":119,"column":61}},"49":{"start":{"line":120,"column":12},"end":{"line":120,"column":60}},"50":{"start":{"line":127,"column":2},"end":{"line":145,"column":4}},"51":{"start":{"line":129,"column":6},"end":{"line":133,"column":7}},"52":{"start":{"line":134,"column":6},"end":{"line":141,"column":7}},"53":{"start":{"line":135,"column":8},"end":{"line":135,"column":33}},"54":{"start":{"line":136,"column":8},"end":{"line":136,"column":34}},"55":{"start":{"line":137,"column":8},"end":{"line":140,"column":9}},"56":{"start":{"line":138,"column":10},"end":{"line":138,"column":56}},"57":{"start":{"line":139,"column":10},"end":{"line":139,"column":55}},"58":{"start":{"line":142,"column":6},"end":{"line":142,"column":67}},"59":{"start":{"line":149,"column":0},"end":{"line":149,"column":45}},"60":{"start":{"line":149,"column":6},"end":{"line":149,"column":29}}},"branchMap":{"1":{"line":34,"type":"if","locations":[{"start":{"line":34,"column":6},"end":{"line":34,"column":6}},{"start":{"line":34,"column":6},"end":{"line":34,"column":6}}]},"2":{"line":35,"type":"binary-expr","locations":[{"start":{"line":35,"column":15},"end":{"line":35,"column":16}},{"start":{"line":35,"column":20},"end":{"line":35,"column":35}}]},"3":{"line":36,"type":"if","locations":[{"start":{"line":36,"column":8},"end":{"line":36,"column":8}},{"start":{"line":36,"column":8},"end":{"line":36,"column":8}}]},"4":{"line":39,"type":"cond-expr","locations":[{"start":{"line":40,"column":6},"end":{"line":40,"column":17}},{"start":{"line":41,"column":6},"end":{"line":49,"column":7}}]},"5":{"line":43,"type":"cond-expr","locations":[{"start":{"line":44,"column":12},"end":{"line":44,"column":21}},{"start":{"line":44,"column":24},"end":{"line":44,"column":25}}]},"6":{"line":65,"type":"if","locations":[{"start":{"line":65,"column":8},"end":{"line":65,"column":8}},{"start":{"line":65,"column":8},"end":{"line":65,"column":8}}]},"7":{"line":66,"type":"if","locations":[{"start":{"line":66,"column":10},"end":{"line":66,"column":10}},{"start":{"line":66,"column":10},"end":{"line":66,"column":10}}]},"8":{"line":80,"type":"binary-expr","locations":[{"start":{"line":80,"column":19},"end":{"line":80,"column":35}},{"start":{"line":80,"column":39},"end":{"line":80,"column":44}}]},"9":{"line":81,"type":"binary-expr","locations":[{"start":{"line":81,"column":15},"end":{"line":81,"column":29}},{"start":{"line":81,"column":33},"end":{"line":81,"column":62}}]},"10":{"line":82,"type":"binary-expr","locations":[{"start":{"line":82,"column":15},"end":{"line":82,"column":29}},{"start":{"line":82,"column":33},"end":{"line":82,"column":60}}]},"11":{"line":83,"type":"cond-expr","locations":[{"start":{"line":84,"column":8},"end":{"line":84,"column":24}},{"start":{"line":84,"column":27},"end":{"line":84,"column":46}}]},"12":{"line":90,"type":"cond-expr","locations":[{"start":{"line":90,"column":32},"end":{"line":90,"column":36}},{"start":{"line":90,"column":39},"end":{"line":90,"column":49}}]},"13":{"line":94,"type":"cond-expr","locations":[{"start":{"line":95,"column":8},"end":{"line":95,"column":29}},{"start":{"line":96,"column":9},"end":{"line":96,"column":32}}]},"14":{"line":104,"type":"if","locations":[{"start":{"line":104,"column":4},"end":{"line":104,"column":4}},{"start":{"line":104,"column":4},"end":{"line":104,"column":4}}]},"15":{"line":104,"type":"binary-expr","locations":[{"start":{"line":104,"column":8},"end":{"line":104,"column":13}},{"start":{"line":104,"column":17},"end":{"line":104,"column":30}}]},"16":{"line":108,"type":"if","locations":[{"start":{"line":108,"column":6},"end":{"line":108,"column":6}},{"start":{"line":108,"column":6},"end":{"line":108,"column":6}}]},"17":{"line":110,"type":"if","locations":[{"start":{"line":110,"column":8},"end":{"line":110,"column":8}},{"start":{"line":110,"column":8},"end":{"line":110,"column":8}}]},"18":{"line":112,"type":"if","locations":[{"start":{"line":112,"column":10},"end":{"line":112,"column":10}},{"start":{"line":112,"column":10},"end":{"line":112,"column":10}}]},"19":{"line":118,"type":"if","locations":[{"start":{"line":118,"column":10},"end":{"line":118,"column":10}},{"start":{"line":118,"column":10},"end":{"line":118,"column":10}}]},"20":{"line":130,"type":"binary-expr","locations":[{"start":{"line":130,"column":16},"end":{"line":130,"column":30}},{"start":{"line":130,"column":34},"end":{"line":130,"column":53}}]},"21":{"line":131,"type":"binary-expr","locations":[{"start":{"line":131,"column":18},"end":{"line":131,"column":29}},{"start":{"line":131,"column":33},"end":{"line":131,"column":67}}]},"22":{"line":134,"type":"if","locations":[{"start":{"line":134,"column":6},"end":{"line":134,"column":6}},{"start":{"line":134,"column":6},"end":{"line":134,"column":6}}]},"23":{"line":137,"type":"if","locations":[{"start":{"line":137,"column":8},"end":{"line":137,"column":8}},{"start":{"line":137,"column":8},"end":{"line":137,"column":8}}]}}}} -------------------------------------------------------------------------------- /coverage/lcov-report/prettify.js: -------------------------------------------------------------------------------- 1 | window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); 2 | -------------------------------------------------------------------------------- /coverage/lcov-report/wrist/wrist.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Code coverage report for wrist/wrist.js 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | all files / wrist/ wrist.js 20 |

21 |
22 |
23 | 98.33% 24 | Statements 25 | 59/60 26 |
27 |
28 | 86.96% 29 | Branches 30 | 40/46 31 |
32 |
33 | 92.31% 34 | Functions 35 | 12/13 36 |
37 |
38 | 98.25% 39 | Lines 40 | 56/57 41 |
42 |
43 |
44 |
45 |

 46 | 
494 | 
1 47 | 2 48 | 3 49 | 4 50 | 5 51 | 6 52 | 7 53 | 8 54 | 9 55 | 10 56 | 11 57 | 12 58 | 13 59 | 14 60 | 15 61 | 16 62 | 17 63 | 18 64 | 19 65 | 20 66 | 21 67 | 22 68 | 23 69 | 24 70 | 25 71 | 26 72 | 27 73 | 28 74 | 29 75 | 30 76 | 31 77 | 32 78 | 33 79 | 34 80 | 35 81 | 36 82 | 37 83 | 38 84 | 39 85 | 40 86 | 41 87 | 42 88 | 43 89 | 44 90 | 45 91 | 46 92 | 47 93 | 48 94 | 49 95 | 50 96 | 51 97 | 52 98 | 53 99 | 54 100 | 55 101 | 56 102 | 57 103 | 58 104 | 59 105 | 60 106 | 61 107 | 62 108 | 63 109 | 64 110 | 65 111 | 66 112 | 67 113 | 68 114 | 69 115 | 70 116 | 71 117 | 72 118 | 73 119 | 74 120 | 75 121 | 76 122 | 77 123 | 78 124 | 79 125 | 80 126 | 81 127 | 82 128 | 83 129 | 84 130 | 85 131 | 86 132 | 87 133 | 88 134 | 89 135 | 90 136 | 91 137 | 92 138 | 93 139 | 94 140 | 95 141 | 96 142 | 97 143 | 98 144 | 99 145 | 100 146 | 101 147 | 102 148 | 103 149 | 104 150 | 105 151 | 106 152 | 107 153 | 108 154 | 109 155 | 110 156 | 111 157 | 112 158 | 113 159 | 114 160 | 115 161 | 116 162 | 117 163 | 118 164 | 119 165 | 120 166 | 121 167 | 122 168 | 123 169 | 124 170 | 125 171 | 126 172 | 127 173 | 128 174 | 129 175 | 130 176 | 131 177 | 132 178 | 133 179 | 134 180 | 135 181 | 136 182 | 137 183 | 138 184 | 139 185 | 140 186 | 141 187 | 142 188 | 143 189 | 144 190 | 145 191 | 146 192 | 147 193 | 148 194 | 149 195 | 150  196 |   197 |   198 |   199 |   200 |   201 |   202 |   203 |   204 |   205 |   206 |   207 |   208 |   209 |   210 |   211 |   212 |   213 |   214 |   215 |   216 |   217 | 218 | 219 |   220 |   221 |   222 |   223 |   224 |   225 |   226 |   227 |   228 | 229 | 230 | 231 |   232 |   233 |   234 |   235 |   236 |   237 | 16× 238 |   239 |   240 |   241 | 242 |   243 |   244 |   245 |   246 | 247 | 248 |   249 | 250 | 251 | 252 | 253 |   254 |   255 | 256 | 257 |   258 | 10× 259 | 10× 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 |   269 |   270 | 271 |   272 |   273 |   274 |   275 | 276 | 277 |   278 |   279 |   280 |   281 | 282 |   283 |   284 |   285 |   286 |   287 |   288 |   289 |   290 |   291 |   292 |   293 |   294 |   295 |   296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 |   309 | 310 | 311 |   312 | 313 | 314 | 315 |   316 |   317 |   318 |   319 |   320 |   321 | 322 |   323 | 324 |   325 |   326 |   327 |   328 | 329 | 330 | 331 | 332 | 333 | 334 |   335 |   336 | 337 |   338 |   339 |   340 |   341 |   342 |   343 | 344 |  
/*! (C) 2017 Andrea Giammarchi - MIT Style License */
345 | /*
346 |   Copyright (C) 2017 by Andrea Giammarchi - @WebReflection
347 |  
348 |   Permission is hereby granted, free of charge, to any person obtaining a copy
349 |   of this software and associated documentation files (the "Software"), to deal
350 |   in the Software without restriction, including without limitation the rights
351 |   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
352 |   copies of the Software, and to permit persons to whom the Software is
353 |   furnished to do so, subject to the following conditions:
354 |  
355 |   The above copyright notice and this permission notice shall be included in
356 |   all copies or substantial portions of the Software.
357 |  
358 |   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
359 |   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
360 |   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
361 |   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
362 |   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
363 |   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
364 |   THE SOFTWARE.
365 | */
366 | var wrist = (function (O) {'use strict';
367 |   var
368 |     ADD_EVENT = 'addEventListener',
369 |     REMOVE_EVENT = 'removeEventListener',
370 |     SECRET = '__oO()' + Math.random(),
371 |     empty = {},
372 |     hOP = empty.hasOwnProperty,
373 |     dP = O.defineProperty,
374 |     gOPD = O.getOwnPropertyDescriptor,
375 |     gPO = O.getPrototypeOf,
376 |     gD = function (o, p) {
377 |       if (p in o) {
378 |         while (o && !hOP.call(o, p)) o = gPO(o);
379 |         Eif (o) return gOPD(o, p);
380 |       }
381 |     },
382 |     wm = typeof WeakMap == 'function' ?
383 |       new WeakMap :
384 |       {
385 |         get: function (a, b) {
386 |           return hOP.call(a, SECRET) ?
387 |             a[SECRET] : b;
388 |         },
389 |         set: function (a, b) {
390 |           dP(a, SECRET, {value: b});
391 |         }
392 |       }
393 |   ;
394 |  
395 |   function Wrist() {}
396 |   Wrist.prototype = Object.create(null);
397 |  
398 |   function createWrist(object) {
399 |     var wrist = new Wrist;
400 |     wm.set(object, wrist);
401 |     return wrist;
402 |   }
403 |  
404 |   function createWatcher(object, wrist, prop) {
405 |     var
406 |       set = function ($) {
407 |         var i, length, old;
408 |         if (this === object) {
409 |           if (value !== $) {
410 |             old = value;
411 |             value = $;
412 |             setter.call(object, value);
413 |             i = 0;
414 |             length = callbacks.length;
415 |             while (i < length)
416 |               callbacks[i++].call(object, prop, old, value);
417 |           }
418 |         } else {
419 |           setter.call(this, $);
420 |         }
421 |       },
422 |       callbacks = [],
423 |       descriptor = gD(object, prop) || empty,
424 |       getter = descriptor.get || function () { return value; },
425 |       setter = descriptor.set || function ($) { value = $; },
426 |       value = hOP.call(descriptor, 'value') ?
427 |         descriptor.value : getter.call(object)
428 |     ;
429 |  
430 |     return (wrist[prop] = {
431 |       // ignored descriptor properties
432 |       _: callbacks,
433 |       d: descriptor === empty ? null : descriptor,
434 |       h: function (e) { set.call(e.target, object[prop]); },
435 |       // regular descriptors properties
436 |       configurable: true,
437 |       enumerable: hOP.call(descriptor, 'enumerable') ?
438 |         descriptor.enumerable :
439 |         (String(prop)[0] !== '_'),
440 |       get: getter,
441 |       set: set
442 |     });
443 |   }
444 |  
445 |   function unwatch(object, prop, callback) {
446 |     var wrist = wm.get(object), callbacks, i, watcher;
447 |     Eif (wrist && prop in wrist) {
448 |       watcher = wrist[prop];
449 |       callbacks = watcher._;
450 |       i = callbacks.indexOf(callback);
451 |       Eif (-1 < i) {
452 |         callbacks.splice(i, 1);
453 |         Eif (callbacks.length < 1) {
454 |           delete wrist[prop];
455 |           if (watcher.d) {
456 |             dP(object, prop, watcher.d);
457 |           } else {
458 |             delete object[prop];
459 |             object[prop] = watcher.get.call(object);
460 |           }
461 |           if (REMOVE_EVENT in object) {
462 |             object[REMOVE_EVENT]('change', watcher.h, false);
463 |             object[REMOVE_EVENT]('input', watcher.h, false);
464 |           }
465 |         }
466 |       }
467 |     }
468 |   }
469 |  
470 |   return {
471 |     watch: function watch(object, prop, callback) {
472 |       var
473 |         wrist = wm.get(object) || createWrist(object),
474 |         watcher = wrist[prop] || createWatcher(object, wrist, prop),
475 |         callbacks = watcher._
476 |       ;
477 |       Eif (callbacks.indexOf(callback) < 0) {
478 |         callbacks.push(callback);
479 |         dP(object, prop, watcher);
480 |         if (ADD_EVENT in object) {
481 |           object[ADD_EVENT]('change', watcher.h, false);
482 |           object[ADD_EVENT]('input', watcher.h, false);
483 |         }
484 |       }
485 |       return {unwatch: unwatch.bind(null, object, prop, callback)};
486 |     },
487 |     unwatch: unwatch
488 |   };
489 |  
490 | }(Object));
491 |  
492 | try { module.exports = wrist; } catch(o_O) {}
493 |  
495 |
496 |
497 | 501 | 502 | 503 | 510 | 511 | 512 | 513 | -------------------------------------------------------------------------------- /coverage/lcov-report/wrist/test.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Code coverage report for wrist/test.js 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 |
17 |
18 |

19 | all files / wrist/ test.js 20 |

21 |
22 |
23 | 96.88% 24 | Statements 25 | 124/128 26 |
27 |
28 | 50% 29 | Branches 30 | 2/4 31 |
32 |
33 | 96.15% 34 | Functions 35 | 25/26 36 |
37 |
38 | 97.64% 39 | Lines 40 | 124/127 41 |
42 |
43 |
44 |
45 |

 46 | 
563 | 
1 47 | 2 48 | 3 49 | 4 50 | 5 51 | 6 52 | 7 53 | 8 54 | 9 55 | 10 56 | 11 57 | 12 58 | 13 59 | 14 60 | 15 61 | 16 62 | 17 63 | 18 64 | 19 65 | 20 66 | 21 67 | 22 68 | 23 69 | 24 70 | 25 71 | 26 72 | 27 73 | 28 74 | 29 75 | 30 76 | 31 77 | 32 78 | 33 79 | 34 80 | 35 81 | 36 82 | 37 83 | 38 84 | 39 85 | 40 86 | 41 87 | 42 88 | 43 89 | 44 90 | 45 91 | 46 92 | 47 93 | 48 94 | 49 95 | 50 96 | 51 97 | 52 98 | 53 99 | 54 100 | 55 101 | 56 102 | 57 103 | 58 104 | 59 105 | 60 106 | 61 107 | 62 108 | 63 109 | 64 110 | 65 111 | 66 112 | 67 113 | 68 114 | 69 115 | 70 116 | 71 117 | 72 118 | 73 119 | 74 120 | 75 121 | 76 122 | 77 123 | 78 124 | 79 125 | 80 126 | 81 127 | 82 128 | 83 129 | 84 130 | 85 131 | 86 132 | 87 133 | 88 134 | 89 135 | 90 136 | 91 137 | 92 138 | 93 139 | 94 140 | 95 141 | 96 142 | 97 143 | 98 144 | 99 145 | 100 146 | 101 147 | 102 148 | 103 149 | 104 150 | 105 151 | 106 152 | 107 153 | 108 154 | 109 155 | 110 156 | 111 157 | 112 158 | 113 159 | 114 160 | 115 161 | 116 162 | 117 163 | 118 164 | 119 165 | 120 166 | 121 167 | 122 168 | 123 169 | 124 170 | 125 171 | 126 172 | 127 173 | 128 174 | 129 175 | 130 176 | 131 177 | 132 178 | 133 179 | 134 180 | 135 181 | 136 182 | 137 183 | 138 184 | 139 185 | 140 186 | 141 187 | 142 188 | 143 189 | 144 190 | 145 191 | 146 192 | 147 193 | 148 194 | 149 195 | 150 196 | 151 197 | 152 198 | 153 199 | 154 200 | 155 201 | 156 202 | 157 203 | 158 204 | 159 205 | 160 206 | 161 207 | 162 208 | 163 209 | 164 210 | 165 211 | 166 212 | 167 213 | 168 214 | 169 215 | 170 216 | 171 217 | 172 218 | 173 219 |   220 | 221 |   222 | 223 | 224 | 225 | 226 |   227 | 228 |   229 | 230 |   231 | 232 |   233 |   234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 |   245 |   246 |   247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 |   258 |   259 |   260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 |   271 |   272 |   273 | 274 | 275 | 276 |   277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 |   288 | 289 | 290 | 291 | 292 | 293 | 294 |   295 |   296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 |   305 | 306 | 307 |   308 | 309 | 310 |   311 | 312 | 313 | 314 | 315 | 316 |   317 |   318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 |   326 | 327 | 328 |   329 | 330 | 331 |   332 | 333 | 334 | 335 | 336 |   337 |   338 | 339 | 340 | 341 |   342 |   343 | 344 | 345 | 346 |   347 | 348 | 349 |   350 | 351 | 352 |   353 | 354 | 355 | 356 | 357 | 358 |   359 |   360 |   361 | 362 | 363 | 364 |   365 |   366 |   367 |   368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 |   378 | 379 | 380 | 381 | 382 | 383 | 384 |   385 | 386 |   387 |   388 |   389 |   390 |  
var test = require('tressa');
391 |  
392 | Iif (typeof global === 'undefined') window.global = window;
393 |  
394 | var WeakMap = global.WeakMap;
395 | delete global.WeakMap;
396 | var wrist = require('./wrist');
397 | global.WeakMap = WeakMap;
398 |  
399 | var obj = {defined: true};
400 |  
401 | test.title('wrist');
402 |  
403 | test(typeof wrist === 'object', 'module status');
404 |  
405 |  
406 | test.async(function (done) {
407 |   wrist.watch(obj, 'test', function watcher(prop, prev, curr) {
408 |     test.log('## undefined property');
409 |     test(this === obj, 'correct context');
410 |     test(prop === 'test', 'correct name');
411 |     test(prev === undefined, 'correct old value');
412 |     test(curr === 123, 'correct new value');
413 |     wrist.unwatch(obj, 'test', watcher);
414 |     obj.test = null;
415 |     done();
416 |   });
417 | });
418 |  
419 | test.async(function (done) {
420 |   wrist.watch(obj, 'defined', function watcher(prop, prev, curr) {
421 |     test.log('## defined property');
422 |     test(this === obj, 'correct context');
423 |     test(prop === 'defined', 'correct name');
424 |     test(prev === true, 'correct old value');
425 |     test(curr === false, 'correct old value');
426 |     wrist.unwatch(obj, 'defined', watcher);
427 |     obj.defined = null;
428 |     done();
429 |   });
430 | });
431 |  
432 | test.async(function (done) {
433 |   var watcher = wrist.watch(obj, 'self', function (prop, prev, curr) {
434 |     test.log('## watcher.unwatch()');
435 |     test(this === obj, 'correct context');
436 |     test(prop === 'self', 'correct name');
437 |     test(prev === undefined, 'correct old value');
438 |     test(curr === false, 'correct new value');
439 |     watcher.unwatch();
440 |     obj.self = null;
441 |     done();
442 |   });
443 | });
444 |  
445 | obj.test = 123;
446 | obj.defined = false;
447 | obj.self = false;
448 |  
449 | test.async(function (done) {
450 |   test.log('## no duplicates');
451 |   var o = {prop: 123};
452 |   var i = 0;
453 |   var watcher = wrist.watch(o, 'prop', function (prop, prev, curr) {
454 |     i++;
455 |     test(this === o, 'correct context');
456 |     test(prop === 'prop', 'correct name');
457 |     test(prev === 123, 'correct old value');
458 |     test(curr === 456, 'correct new value');
459 |   });
460 |   test(i === 0, 'not called yet');
461 |   o.prop = 456;
462 |   o.prop = 456;
463 |   test(i === 1, 'called only once');
464 |   watcher.unwatch();
465 |   done();
466 | });
467 |  
468 | test.async(function (done) {
469 |   test.log('## inherited setter');
470 |   function Class() {}
471 |   function watch(prop, prev, curr) {
472 |     test(this === o, 'correct context');
473 |     test(prop === 'test', 'correct name');
474 |     test(prev === 0, 'correct old value');
475 |     test(curr === 1, 'correct new value');
476 |   }
477 |   var i = 0;
478 |   Object.defineProperty(Class.prototype, 'test', {
479 |     configurable: true,
480 |     get: function () { return i; },
481 |     set: function (l) { i = l; }
482 |   });
483 |   var o = new Class();
484 |   wrist.watch(o, 'test', watch);
485 |   o.test += 1;
486 |   wrist.unwatch(o, 'test', watch);
487 |   done();
488 | });
489 |  
490 | test.async(function (done) {
491 |   test.log('## own setter');
492 |   function watch(prop, prev, curr) {
493 |     test(this === o, 'correct context');
494 |     test(prop === 'test', 'correct name');
495 |     test(prev === 0, 'correct old value');
496 |     test(curr === 1, 'correct new value');
497 |   }
498 |   var i = 0;
499 |   var o = Object.defineProperty({}, 'test', {
500 |     configurable: true,
501 |     get: function () { return i; },
502 |     set: function (l) { i = l; }
503 |   });
504 |   wrist.watch(o, 'test', watch);
505 |   o.test += 1;
506 |   wrist.unwatch(o, 'test', watch);
507 |   done();
508 | });
509 |  
510 | test.async(function (done) {
511 |   test.log('## borrowed setter');
512 |   function watch(prop, prev, curr) {
513 |     ++j;
514 |   }
515 |   var i = 0;
516 |   var j = 0;
517 |   var o = Object.defineProperty({}, 'test', {
518 |     configurable: true,
519 |     get: function () { return i; },
520 |     set: function (l) { i = l; }
521 |   });
522 |   wrist.watch(o, 'test', watch);
523 |   var z = Object.defineProperty({}, 'test',
524 |     Object.getOwnPropertyDescriptor(o, 'test'));
525 |   z.test = 456;
526 |   test(j === 0, 'watcher not involved');
527 |   test(i === 456, 'setter called');
528 |   wrist.unwatch(o, 'test', watch);
529 |   done();
530 | });
531 |  
532 |  
533 | test.async(function (done) {
534 |   Eif (typeof document === 'undefined') {
535 |     require('jsdom').env('<body><input></body>', [], check);
536 |   } else {
537 |     document.body.appendChild(document.createElement('input'));
538 |     check(null, window);
539 |   }
540 |   function check(err, window) {
541 |     test.log('## DOM elements');
542 |     var input = window.document.body.getElementsByTagName('input')[0];
543 |     var value = '';
544 |     var watcher = wrist.watch(input, 'value', function (prop, prev, curr) {
545 |       test(prop === 'value', 'correct name');
546 |       test(prev === value, 'correct old value');
547 |       test(curr === value + '0', 'correct new value');
548 |       value += '0';
549 |     });
550 |     input.value = '0';
551 |     setTimeout(function () {
552 |       input.value += '0';
553 |       setTimeout(function () {
554 |         watcher.unwatch();
555 |         done();
556 |         // for testing purpose only
557 |         window.wrist = wrist;
558 |       }, 1);
559 |     });
560 |   }
561 | });
562 |  
564 |
565 |
566 | 570 | 571 | 572 | 579 | 580 | 581 | 582 | --------------------------------------------------------------------------------