├── .gitignore ├── .jshintrc ├── .travis.yml ├── LICENSE ├── README.md ├── dist ├── treeview.min.css ├── treeview.min.css.map ├── treeview.min.js └── treeview.min.js.map ├── example └── index.html ├── index.js ├── package-lock.json ├── package.json ├── src ├── treeview.css └── treeview.js └── test ├── index.html └── test-runner.js /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules 16 | 17 | *.swp 18 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // -------------------------------------------------------------------- 3 | // JSHint Configuration, Strict Edition 4 | // -------------------------------------------------------------------- 5 | // 6 | // This is a options template for [JSHint][1], using [JSHint example][2] 7 | // and [Ory Band's example][3] as basis and setting config values to 8 | // be most strict: 9 | // 10 | // * set all enforcing options to true 11 | // * set all relaxing options to false 12 | // * set all environment options to false, except the browser value 13 | // * set all JSLint legacy options to false 14 | // 15 | // [1]: http://www.jshint.com/ 16 | // [2]: https://github.com/jshint/node-jshint/blob/master/example/config.json 17 | // [3]: https://github.com/oryband/dotfiles/blob/master/jshintrc 18 | // 19 | // @author http://michael.haschke.biz/ 20 | // @license http://unlicense.org/ 21 | 22 | // == Enforcing Options =============================================== 23 | // 24 | // These options tell JSHint to be more strict towards your code. Use 25 | // them if you want to allow only a safe subset of JavaScript, very 26 | // useful when your codebase is shared with a big number of developers 27 | // with different skill levels. 28 | 29 | "bitwise" : true, // Prohibit bitwise operators (&, |, ^, etc.). 30 | "curly" : true, // Require {} for every new block or scope. 31 | "eqeqeq" : true, // Require triple equals i.e. `===`. 32 | "forin" : true, // Tolerate `for in` loops without `hasOwnPrototype`. 33 | "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` 34 | "latedef" : true, // Prohibit variable use before definition. 35 | "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`. 36 | "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`. 37 | "noempty" : true, // Prohibit use of empty blocks. 38 | "nonew" : true, // Prohibit use of constructors for side-effects. 39 | "plusplus" : true, // Prohibit use of `++` & `--`. 40 | "regexp" : true, // Prohibit `.` and `[^...]` in regular expressions. 41 | "undef" : true, // Require all non-global variables be declared before they are used. 42 | "strict" : true, // Require `use strict` pragma in every file. 43 | "trailing" : true, // Prohibit trailing whitespaces. 44 | 45 | // == Relaxing Options ================================================ 46 | // 47 | // These options allow you to suppress certain types of warnings. Use 48 | // them only if you are absolutely positive that you know what you are 49 | // doing. 50 | 51 | "asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons). 52 | "boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments. 53 | "debug" : false, // Allow debugger statements e.g. browser breakpoints. 54 | "eqnull" : false, // Tolerate use of `== null`. 55 | "es5" : false, // Allow EcmaScript 5 syntax. 56 | "esnext" : false, // Allow ES.next specific features such as `const` and `let`. 57 | "evil" : false, // Tolerate use of `eval`. 58 | "expr" : false, // Tolerate `ExpressionStatement` as Programs. 59 | "funcscope" : false, // Tolerate declarations of variables inside of control structures while accessing them later from the outside. 60 | "globalstrict" : false, // Allow global "use strict" (also enables 'strict'). 61 | "iterator" : false, // Allow usage of __iterator__ property. 62 | "lastsemic" : false, // Tolerat missing semicolons when the it is omitted for the last statement in a one-line block. 63 | "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons. 64 | "laxcomma" : false, // Suppress warnings about comma-first coding style. 65 | "loopfunc" : false, // Allow functions to be defined within loops. 66 | "multistr" : false, // Tolerate multi-line strings. 67 | "onecase" : false, // Tolerate switches with just one case. 68 | "proto" : false, // Tolerate __proto__ property. This property is deprecated. 69 | "regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`. 70 | "scripturl" : false, // Tolerate script-targeted URLs. 71 | "smarttabs" : false, // Tolerate mixed tabs and spaces when the latter are used for alignmnent only. 72 | "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`. 73 | "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. 74 | "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`. 75 | "validthis" : false, // Tolerate strict violations when the code is running in strict mode and you use this in a non-constructor function. 76 | 77 | // == Environments ==================================================== 78 | // 79 | // These options pre-define global variables that are exposed by 80 | // popular JavaScript libraries and runtime environments?such as 81 | // browser or node.js. 82 | 83 | "browser" : true, // Standard browser globals e.g. `window`, `document`. 84 | "couch" : false, // Enable globals exposed by CouchDB. 85 | "devel" : false, // Allow development statements e.g. `console.log();`. 86 | "dojo" : false, // Enable globals exposed by Dojo Toolkit. 87 | "jquery" : false, // Enable globals exposed by jQuery JavaScript library. 88 | "mootools" : false, // Enable globals exposed by MooTools JavaScript framework. 89 | "node" : true, // Enable globals available when code is running inside of the NodeJS runtime environment. 90 | "nonstandard" : false, // Define non-standard but widely adopted globals such as escape and unescape. 91 | "prototypejs" : false, // Enable globals exposed by Prototype JavaScript framework. 92 | "rhino" : false, // Enable globals available when your code is running inside of the Rhino runtime environment. 93 | "wsh" : false, // Enable globals available when your code is running as a script for the Windows Script Host. 94 | 95 | // == JSLint Legacy =================================================== 96 | // 97 | // These options are legacy from JSLint. Aside from bug fixes they will 98 | // not be improved in any way and might be removed at any point. 99 | 100 | "nomen" : false, // Prohibit use of initial or trailing underbars in names. 101 | "onevar" : false, // Allow only one `var` statement per function. 102 | "passfail" : false, // Stop on first error. 103 | "white" : false, // Check against strict whitespace and indentation rules. 104 | 105 | // == Undocumented Options ============================================ 106 | // 107 | // While I've found these options in [example1][2] and [example2][3] 108 | // they are not described in the [JSHint Options documentation][4]. 109 | // 110 | // [4]: http://www.jshint.com/options/ 111 | 112 | "maxerr" : 100, // Maximum errors before stopping. 113 | "predef" : [ // Extra globals. 114 | //"exampleVar", 115 | //"anotherCoolGlobal", 116 | //"iLoveDouglas" 117 | ], 118 | "indent" : 4 // Specify indentation spacing 119 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "5.2" 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Justin Chmura 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 all 13 | 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 THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vanilla JavaScript TreeView 2 | 3 | [![Build Status](https://travis-ci.org/justinchmura/js-treeview.svg?branch=master)](https://travis-ci.org/justinchmura/js-treeview)[![npm version](https://badge.fury.io/js/js-treeview.svg)](https://badge.fury.io/js/js-treeview) 4 | 5 | A stupid, simple tree view written with vanilla JS. I needed a lightweight control that just displayed data in a tree form and out popped this. I wrote a [post on my blog](http://justinchmura.com/2014/07/03/javascript-tree-view/) that goes into more depth. 6 | 7 | ## Dependencies 8 | 9 | None. I built this using only plain JavaScript so there's no external dependencies. Other than the CSS required for styling. 10 | 11 | ## Example Usage 12 | 13 | If used outside of NPM/require, it will attach a global `TreeVew` object to `window`. If done using NPM, then it can be included using `require` like everything else. To install it via NPM: 14 | 15 | ```bash 16 | npm install js-treeview 17 | ``` 18 | 19 | ### HTML 20 | 21 | ```html 22 |
23 | ``` 24 | 25 | ### JavaScript 26 | 27 | ```js 28 | 29 | // NPM 30 | var TreeView = require('js-treeview'); 31 | 32 | var tree = new TreeView([ 33 | { name: 'Item 1', children: [] }, 34 | { name: 'Item 2', expanded: true, children: [ 35 | { name: 'Sub Item 1', children: [] }, 36 | { name: 'Sub Item 2', children: [] } 37 | ] 38 | } 39 | ], 'tree'); 40 | ``` 41 | 42 | ## Options 43 | 44 | | Name | Type | Description | 45 | | ---- | ---- | ----------- | 46 | | `data` | `array` | The array of items to populate the tree with. Each item is required to have a `name` and a `children` array. An optional `expanded` option allows you to default the child to be expanded when created. | 47 | | `id` | `string|object` | ID of the DOM element, or the DOM element itself, to render the tree in. | 48 | 49 | ## Events 50 | 51 | | Name | Arguments | Description | 52 | | ----- | --------- | ----------- | 53 | | `expand` | `target` - The DOM node that initiated the expand
`leaves` - Array of leaf DOM nodes under the target | Fires when a leaf is expanded. | 54 | | `expandAll` | No arguments | Fires after the `expandAll` method is called. | 55 | | `collapse` | `target` - The DOM node that initiated the collapse
`leaves` - Array of leaf DOM nodes under the target | Fires when a leaf is collapsed. | 56 | | `collapseAll` | No arguments | Fires after the `collapseAll` method is called. | 57 | | `select` | `target` - The DOM node selected
`data` - Data node associated with the selected element | Fires when a outermost leaf is selected. Contains data item of the leaf selected. | 58 | 59 | ### Usage 60 | 61 | ```js 62 | tree.on('select', function (e) { 63 | console.log(JSON.stringify(e)); 64 | }); 65 | ``` 66 | 67 | [CodePen Example](http://codepen.io/justinchmura/pen/PZzBOP/) 68 | 69 | ## License 70 | 71 | This plugin is available under [the MIT license](http://mths.be/mit). 72 | -------------------------------------------------------------------------------- /dist/treeview.min.css: -------------------------------------------------------------------------------- 1 | .tree-leaf{position:relative}.tree-leaf .tree-child-leaves{display:block;margin-left:15px}.tree-leaf .hidden{display:none;visibility:hidden}.tree-leaf .tree-expando{background:#ddd;border-radius:3px;cursor:pointer;float:left;height:10px;line-height:10px;position:relative;text-align:center;top:5px;width:10px}.tree-leaf .tree-expando:hover{background:#aaa}.tree-leaf .tree-leaf-text{cursor:pointer;float:left;margin-left:5px}.tree-leaf .tree-leaf-text:hover{color:#00f}.tree-leaf .tree-leaf-content:after,.tree-leaf .tree-leaf-content:before{content:" ";display:table}.tree-leaf .tree-leaf-content:after{clear:both} 2 | /*# sourceMappingURL=treeview.min.css.map */ -------------------------------------------------------------------------------- /dist/treeview.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["src/treeview.css"],"names":[],"mappings":"AAAA,WAAa,SAAU,SACvB,8BAAgC,QAAS,MAAO,YAAa,KAC7D,mBAAqB,QAAS,KAET,WAAY,OADjC,yBAA2B,WAAY,KAAM,cAAe,IAAK,OAAQ,QAAS,MAAO,KAAM,OAAQ,KAAM,YAAa,KAAM,SAAU,SAAU,WAAY,OAAQ,IAAK,IAAK,MAAO,KAEzL,+BAAiC,WAAY,KAC7C,2BAA6B,OAAQ,QAAS,MAAO,KAAM,YAAa,IACxE,iCAAmC,MAAO,KACJ,oCAAtC,qCAA4E,QAAS,IAAK,QAAS,MACnG,oCAAsC,MAAO"} -------------------------------------------------------------------------------- /dist/treeview.min.js: -------------------------------------------------------------------------------- 1 | !function(e){"use strict";!function(t,n){"function"==typeof e&&e.amd?e(n):"object"==typeof exports?module.exports=n():t.TreeView=n()}(window,function(){return function(){function e(e){try{return e instanceof HTMLElement}catch(t){return"object"==typeof e&&1===e.nodeType&&"object"==typeof e.style&&"object"==typeof e.ownerDocument}}function t(e,t,n){var a,o=e.length;for(a=0;a-1))throw new Error(n+" event cannot be found on TreeView.");e.handlers[n]&&e.handlers[n]instanceof Array&&t(e.handlers[n],function(e){window.setTimeout(function(){e.callback.apply(e.context,a)},0)})}function a(a){var o,r=e(a.node)?a.node:document.getElementById(a.node),l=[],d=function(e){var n=document.createElement("div"),a=document.createElement("div"),o=document.createElement("div"),r=document.createElement("div");if(n.setAttribute("class","tree-leaf"),a.setAttribute("class","tree-leaf-content"),a.setAttribute("data-item",JSON.stringify(e)),o.setAttribute("class","tree-leaf-text"),o.textContent=e.name,r.setAttribute("class","tree-expando "+(e.expanded?"expanded":"")),r.textContent=e.expanded?"-":"+",a.appendChild(r),a.appendChild(o),n.appendChild(a),e.children&&e.children.length>0){var l=document.createElement("div");l.setAttribute("class","tree-child-leaves"),t(e.children,function(e){var t=d(e);l.appendChild(t)}),e.expanded||l.classList.add("hidden"),n.appendChild(l)}else r.classList.add("hidden");return n};t(a.data,function(e){l.push(d.call(a,e))}),r.innerHTML=l.map(function(e){return e.outerHTML}).join(""),o=function(e){var t=(e.target||e.currentTarget).parentNode,o=JSON.parse(t.getAttribute("data-item")),r=t.parentNode.querySelector(".tree-child-leaves");r?r.classList.contains("hidden")?a.expand(t,r):a.collapse(t,r):n(a,"select",{target:e,data:o})},t(r.querySelectorAll(".tree-leaf-text"),function(e){e.onclick=o}),t(r.querySelectorAll(".tree-expando"),function(e){e.onclick=o})}function o(e,t){this.handlers={},this.node=t,this.data=e,a(this)}var r=["expand","expandAll","collapse","collapseAll","select"];return o.prototype.expand=function(e,t,a){e.querySelector(".tree-expando").textContent="-",t.classList.remove("hidden"),a||n(this,"expand",{target:e,leaves:t})},o.prototype.expandAll=function(){var e=this;t(document.getElementById(e.node).querySelectorAll(".tree-expando"),function(t){var n=t.parentNode,a=n.parentNode.querySelector(".tree-child-leaves");n&&a&&n.hasAttribute("data-item")&&e.expand(n,a,!0)}),n(this,"expandAll",{})},o.prototype.collapse=function(e,t,a){e.querySelector(".tree-expando").textContent="+",t.classList.add("hidden"),a||n(this,"collapse",{target:e,leaves:t})},o.prototype.collapseAll=function(){var e=this;t(document.getElementById(e.node).querySelectorAll(".tree-expando"),function(t){var n=t.parentNode,a=n.parentNode.querySelector(".tree-child-leaves");n&&a&&n.hasAttribute("data-item")&&e.collapse(n,a,!0)}),n(this,"collapseAll",{})},o.prototype.on=function(e,t,n){if(!(r.indexOf(e)>-1))throw new Error(e+" is not supported by TreeView.");this.handlers[e]||(this.handlers[e]=[]),this.handlers[e].push({callback:t,context:n})},o.prototype.off=function(e,t){var n,a=!1;this.handlers[e]instanceof Array&&(this.handlers[e].forEach(function(e,o){n=o,e.callback!==t||a||(a=!0)}),a&&this.handlers[e].splice(n,1))},o}()})}(window.define); 2 | //# sourceMappingURL=dist/treeview.min.js.map -------------------------------------------------------------------------------- /dist/treeview.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["src/treeview.js"],"names":["define","root","factory","amd","exports","module","TreeView","window","isDOMElement","obj","HTMLElement","e","nodeType","style","ownerDocument","forEach","arr","callback","scope","i","len","length","call","emit","instance","name","args","slice","arguments","events","indexOf","Error","handlers","Array","handle","setTimeout","apply","context","render","self","click","container","node","document","getElementById","leaves","renderLeaf","item","leaf","createElement","content","text","expando","setAttribute","JSON","stringify","textContent","expanded","appendChild","children","child","childLeaf","classList","add","data","push","innerHTML","map","outerHTML","join","parent","target","currentTarget","parentNode","parse","getAttribute","querySelector","contains","expand","collapse","querySelectorAll","onclick","this","prototype","skipEmit","remove","expandAll","hasAttribute","collapseAll","on","off","index","found","splice"],"mappings":"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","file":"dist/treeview.min.js"} -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JS TreeView Example 4 | 5 | 6 |
7 | 8 | 9 | 10 | 75 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./src/treeview'); 2 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-treeview", 3 | "version": "1.1.5", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ajv": { 8 | "version": "4.11.8", 9 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", 10 | "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", 11 | "dev": true, 12 | "requires": { 13 | "co": "4.6.0", 14 | "json-stable-stringify": "1.0.1" 15 | } 16 | }, 17 | "align-text": { 18 | "version": "0.1.4", 19 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 20 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 21 | "dev": true, 22 | "requires": { 23 | "kind-of": "3.2.2", 24 | "longest": "1.0.1", 25 | "repeat-string": "1.6.1" 26 | } 27 | }, 28 | "amdefine": { 29 | "version": "1.0.1", 30 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 31 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", 32 | "dev": true 33 | }, 34 | "ansi-styles": { 35 | "version": "3.2.0", 36 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", 37 | "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", 38 | "dev": true, 39 | "requires": { 40 | "color-convert": "1.9.0" 41 | } 42 | }, 43 | "asn1": { 44 | "version": "0.2.3", 45 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", 46 | "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", 47 | "dev": true 48 | }, 49 | "assert-plus": { 50 | "version": "0.2.0", 51 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", 52 | "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", 53 | "dev": true 54 | }, 55 | "asynckit": { 56 | "version": "0.4.0", 57 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 58 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 59 | "dev": true 60 | }, 61 | "aws-sign2": { 62 | "version": "0.6.0", 63 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", 64 | "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", 65 | "dev": true 66 | }, 67 | "aws4": { 68 | "version": "1.6.0", 69 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", 70 | "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", 71 | "dev": true 72 | }, 73 | "balanced-match": { 74 | "version": "1.0.0", 75 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 76 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 77 | "dev": true 78 | }, 79 | "bcrypt-pbkdf": { 80 | "version": "1.0.1", 81 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", 82 | "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", 83 | "dev": true, 84 | "optional": true, 85 | "requires": { 86 | "tweetnacl": "0.14.5" 87 | } 88 | }, 89 | "boom": { 90 | "version": "2.10.1", 91 | "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", 92 | "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", 93 | "dev": true, 94 | "requires": { 95 | "hoek": "2.16.3" 96 | } 97 | }, 98 | "brace-expansion": { 99 | "version": "1.1.8", 100 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 101 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 102 | "dev": true, 103 | "requires": { 104 | "balanced-match": "1.0.0", 105 | "concat-map": "0.0.1" 106 | } 107 | }, 108 | "camelcase": { 109 | "version": "1.2.1", 110 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 111 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", 112 | "dev": true 113 | }, 114 | "caseless": { 115 | "version": "0.12.0", 116 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 117 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 118 | "dev": true 119 | }, 120 | "center-align": { 121 | "version": "0.1.3", 122 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 123 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 124 | "dev": true, 125 | "requires": { 126 | "align-text": "0.1.4", 127 | "lazy-cache": "1.0.4" 128 | } 129 | }, 130 | "chalk": { 131 | "version": "2.3.0", 132 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", 133 | "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", 134 | "dev": true, 135 | "requires": { 136 | "ansi-styles": "3.2.0", 137 | "escape-string-regexp": "1.0.5", 138 | "supports-color": "4.5.0" 139 | } 140 | }, 141 | "clean-css": { 142 | "version": "3.4.28", 143 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", 144 | "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", 145 | "dev": true, 146 | "requires": { 147 | "commander": "2.8.1", 148 | "source-map": "0.4.4" 149 | } 150 | }, 151 | "cli": { 152 | "version": "1.0.1", 153 | "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", 154 | "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", 155 | "dev": true, 156 | "requires": { 157 | "exit": "0.1.2", 158 | "glob": "7.1.2" 159 | } 160 | }, 161 | "cliui": { 162 | "version": "2.1.0", 163 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 164 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 165 | "dev": true, 166 | "requires": { 167 | "center-align": "0.1.3", 168 | "right-align": "0.1.3", 169 | "wordwrap": "0.0.2" 170 | } 171 | }, 172 | "co": { 173 | "version": "4.6.0", 174 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 175 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 176 | "dev": true 177 | }, 178 | "color-convert": { 179 | "version": "1.9.0", 180 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", 181 | "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", 182 | "dev": true, 183 | "requires": { 184 | "color-name": "1.1.3" 185 | } 186 | }, 187 | "color-name": { 188 | "version": "1.1.3", 189 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 190 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 191 | "dev": true 192 | }, 193 | "combined-stream": { 194 | "version": "1.0.5", 195 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", 196 | "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", 197 | "dev": true, 198 | "requires": { 199 | "delayed-stream": "1.0.0" 200 | } 201 | }, 202 | "commander": { 203 | "version": "2.8.1", 204 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", 205 | "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", 206 | "dev": true, 207 | "requires": { 208 | "graceful-readlink": "1.0.1" 209 | } 210 | }, 211 | "concat-map": { 212 | "version": "0.0.1", 213 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 214 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 215 | "dev": true 216 | }, 217 | "concat-stream": { 218 | "version": "1.6.0", 219 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", 220 | "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", 221 | "dev": true, 222 | "requires": { 223 | "inherits": "2.0.3", 224 | "readable-stream": "2.3.3", 225 | "typedarray": "0.0.6" 226 | }, 227 | "dependencies": { 228 | "isarray": { 229 | "version": "1.0.0", 230 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 231 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 232 | "dev": true 233 | }, 234 | "readable-stream": { 235 | "version": "2.3.3", 236 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", 237 | "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", 238 | "dev": true, 239 | "requires": { 240 | "core-util-is": "1.0.2", 241 | "inherits": "2.0.3", 242 | "isarray": "1.0.0", 243 | "process-nextick-args": "1.0.7", 244 | "safe-buffer": "5.1.1", 245 | "string_decoder": "1.0.3", 246 | "util-deprecate": "1.0.2" 247 | } 248 | }, 249 | "string_decoder": { 250 | "version": "1.0.3", 251 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 252 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 253 | "dev": true, 254 | "requires": { 255 | "safe-buffer": "5.1.1" 256 | } 257 | } 258 | } 259 | }, 260 | "console-browserify": { 261 | "version": "1.1.0", 262 | "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", 263 | "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", 264 | "dev": true, 265 | "requires": { 266 | "date-now": "0.1.4" 267 | } 268 | }, 269 | "core-util-is": { 270 | "version": "1.0.2", 271 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 272 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 273 | "dev": true 274 | }, 275 | "cryptiles": { 276 | "version": "2.0.5", 277 | "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", 278 | "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", 279 | "dev": true, 280 | "requires": { 281 | "boom": "2.10.1" 282 | } 283 | }, 284 | "csslint": { 285 | "version": "0.10.0", 286 | "resolved": "https://registry.npmjs.org/csslint/-/csslint-0.10.0.tgz", 287 | "integrity": "sha1-OmoE51Zcjp0ZvrSXZ8fslug2WAU=", 288 | "dev": true, 289 | "requires": { 290 | "parserlib": "0.2.5" 291 | } 292 | }, 293 | "dashdash": { 294 | "version": "1.14.1", 295 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 296 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 297 | "dev": true, 298 | "requires": { 299 | "assert-plus": "1.0.0" 300 | }, 301 | "dependencies": { 302 | "assert-plus": { 303 | "version": "1.0.0", 304 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 305 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 306 | "dev": true 307 | } 308 | } 309 | }, 310 | "date-now": { 311 | "version": "0.1.4", 312 | "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", 313 | "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", 314 | "dev": true 315 | }, 316 | "debug": { 317 | "version": "2.6.9", 318 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 319 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 320 | "dev": true, 321 | "requires": { 322 | "ms": "2.0.0" 323 | } 324 | }, 325 | "decamelize": { 326 | "version": "1.2.0", 327 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 328 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 329 | "dev": true 330 | }, 331 | "delayed-stream": { 332 | "version": "1.0.0", 333 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 334 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 335 | "dev": true 336 | }, 337 | "dom-serializer": { 338 | "version": "0.1.0", 339 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", 340 | "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", 341 | "dev": true, 342 | "requires": { 343 | "domelementtype": "1.1.3", 344 | "entities": "1.1.1" 345 | }, 346 | "dependencies": { 347 | "domelementtype": { 348 | "version": "1.1.3", 349 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", 350 | "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", 351 | "dev": true 352 | }, 353 | "entities": { 354 | "version": "1.1.1", 355 | "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", 356 | "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", 357 | "dev": true 358 | } 359 | } 360 | }, 361 | "domelementtype": { 362 | "version": "1.3.0", 363 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", 364 | "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", 365 | "dev": true 366 | }, 367 | "domhandler": { 368 | "version": "2.3.0", 369 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", 370 | "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", 371 | "dev": true, 372 | "requires": { 373 | "domelementtype": "1.3.0" 374 | } 375 | }, 376 | "domutils": { 377 | "version": "1.5.1", 378 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", 379 | "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", 380 | "dev": true, 381 | "requires": { 382 | "dom-serializer": "0.1.0", 383 | "domelementtype": "1.3.0" 384 | } 385 | }, 386 | "ecc-jsbn": { 387 | "version": "0.1.1", 388 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", 389 | "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", 390 | "dev": true, 391 | "optional": true, 392 | "requires": { 393 | "jsbn": "0.1.1" 394 | } 395 | }, 396 | "entities": { 397 | "version": "1.0.0", 398 | "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", 399 | "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", 400 | "dev": true 401 | }, 402 | "es6-promise": { 403 | "version": "4.0.5", 404 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz", 405 | "integrity": "sha1-eILzCt3lskDM+n99eMVIMwlRrkI=", 406 | "dev": true 407 | }, 408 | "escape-string-regexp": { 409 | "version": "1.0.5", 410 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 411 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 412 | "dev": true 413 | }, 414 | "exit": { 415 | "version": "0.1.2", 416 | "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", 417 | "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", 418 | "dev": true 419 | }, 420 | "extend": { 421 | "version": "3.0.1", 422 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", 423 | "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", 424 | "dev": true 425 | }, 426 | "extract-zip": { 427 | "version": "1.6.6", 428 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz", 429 | "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=", 430 | "dev": true, 431 | "requires": { 432 | "concat-stream": "1.6.0", 433 | "debug": "2.6.9", 434 | "mkdirp": "0.5.0", 435 | "yauzl": "2.4.1" 436 | } 437 | }, 438 | "extsprintf": { 439 | "version": "1.3.0", 440 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 441 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 442 | "dev": true 443 | }, 444 | "fd-slicer": { 445 | "version": "1.0.1", 446 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", 447 | "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", 448 | "dev": true, 449 | "requires": { 450 | "pend": "1.2.0" 451 | } 452 | }, 453 | "forever-agent": { 454 | "version": "0.6.1", 455 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 456 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 457 | "dev": true 458 | }, 459 | "form-data": { 460 | "version": "2.1.4", 461 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", 462 | "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", 463 | "dev": true, 464 | "requires": { 465 | "asynckit": "0.4.0", 466 | "combined-stream": "1.0.5", 467 | "mime-types": "2.1.17" 468 | } 469 | }, 470 | "fs-extra": { 471 | "version": "1.0.0", 472 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", 473 | "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", 474 | "dev": true, 475 | "requires": { 476 | "graceful-fs": "4.1.11", 477 | "jsonfile": "2.4.0", 478 | "klaw": "1.3.1" 479 | } 480 | }, 481 | "fs.realpath": { 482 | "version": "1.0.0", 483 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 484 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 485 | "dev": true 486 | }, 487 | "getpass": { 488 | "version": "0.1.7", 489 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 490 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 491 | "dev": true, 492 | "requires": { 493 | "assert-plus": "1.0.0" 494 | }, 495 | "dependencies": { 496 | "assert-plus": { 497 | "version": "1.0.0", 498 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 499 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 500 | "dev": true 501 | } 502 | } 503 | }, 504 | "glob": { 505 | "version": "7.1.2", 506 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 507 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 508 | "dev": true, 509 | "requires": { 510 | "fs.realpath": "1.0.0", 511 | "inflight": "1.0.6", 512 | "inherits": "2.0.3", 513 | "minimatch": "3.0.4", 514 | "once": "1.4.0", 515 | "path-is-absolute": "1.0.1" 516 | } 517 | }, 518 | "graceful-fs": { 519 | "version": "4.1.11", 520 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 521 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", 522 | "dev": true 523 | }, 524 | "graceful-readlink": { 525 | "version": "1.0.1", 526 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 527 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 528 | "dev": true 529 | }, 530 | "har-schema": { 531 | "version": "1.0.5", 532 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", 533 | "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", 534 | "dev": true 535 | }, 536 | "har-validator": { 537 | "version": "4.2.1", 538 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", 539 | "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", 540 | "dev": true, 541 | "requires": { 542 | "ajv": "4.11.8", 543 | "har-schema": "1.0.5" 544 | } 545 | }, 546 | "has-flag": { 547 | "version": "2.0.0", 548 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", 549 | "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", 550 | "dev": true 551 | }, 552 | "hasha": { 553 | "version": "2.2.0", 554 | "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", 555 | "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", 556 | "dev": true, 557 | "requires": { 558 | "is-stream": "1.1.0", 559 | "pinkie-promise": "2.0.1" 560 | } 561 | }, 562 | "hawk": { 563 | "version": "3.1.3", 564 | "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", 565 | "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", 566 | "dev": true, 567 | "requires": { 568 | "boom": "2.10.1", 569 | "cryptiles": "2.0.5", 570 | "hoek": "2.16.3", 571 | "sntp": "1.0.9" 572 | } 573 | }, 574 | "hoek": { 575 | "version": "2.16.3", 576 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", 577 | "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", 578 | "dev": true 579 | }, 580 | "htmlparser2": { 581 | "version": "3.8.3", 582 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", 583 | "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", 584 | "dev": true, 585 | "requires": { 586 | "domelementtype": "1.3.0", 587 | "domhandler": "2.3.0", 588 | "domutils": "1.5.1", 589 | "entities": "1.0.0", 590 | "readable-stream": "1.1.14" 591 | } 592 | }, 593 | "http-signature": { 594 | "version": "1.1.1", 595 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", 596 | "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", 597 | "dev": true, 598 | "requires": { 599 | "assert-plus": "0.2.0", 600 | "jsprim": "1.4.1", 601 | "sshpk": "1.13.1" 602 | } 603 | }, 604 | "inflight": { 605 | "version": "1.0.6", 606 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 607 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 608 | "dev": true, 609 | "requires": { 610 | "once": "1.4.0", 611 | "wrappy": "1.0.2" 612 | } 613 | }, 614 | "inherits": { 615 | "version": "2.0.3", 616 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 617 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 618 | "dev": true 619 | }, 620 | "is-buffer": { 621 | "version": "1.1.6", 622 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 623 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", 624 | "dev": true 625 | }, 626 | "is-stream": { 627 | "version": "1.1.0", 628 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 629 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 630 | "dev": true 631 | }, 632 | "is-typedarray": { 633 | "version": "1.0.0", 634 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 635 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 636 | "dev": true 637 | }, 638 | "isarray": { 639 | "version": "0.0.1", 640 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 641 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", 642 | "dev": true 643 | }, 644 | "isexe": { 645 | "version": "2.0.0", 646 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 647 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 648 | "dev": true 649 | }, 650 | "isstream": { 651 | "version": "0.1.2", 652 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 653 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 654 | "dev": true 655 | }, 656 | "jsbn": { 657 | "version": "0.1.1", 658 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 659 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 660 | "dev": true, 661 | "optional": true 662 | }, 663 | "jshint": { 664 | "version": "2.9.5", 665 | "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz", 666 | "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=", 667 | "dev": true, 668 | "requires": { 669 | "cli": "1.0.1", 670 | "console-browserify": "1.1.0", 671 | "exit": "0.1.2", 672 | "htmlparser2": "3.8.3", 673 | "lodash": "3.7.0", 674 | "minimatch": "3.0.4", 675 | "shelljs": "0.3.0", 676 | "strip-json-comments": "1.0.4" 677 | } 678 | }, 679 | "json-schema": { 680 | "version": "0.2.3", 681 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 682 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 683 | "dev": true 684 | }, 685 | "json-stable-stringify": { 686 | "version": "1.0.1", 687 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", 688 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", 689 | "dev": true, 690 | "requires": { 691 | "jsonify": "0.0.0" 692 | } 693 | }, 694 | "json-stringify-safe": { 695 | "version": "5.0.1", 696 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 697 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 698 | "dev": true 699 | }, 700 | "jsonfile": { 701 | "version": "2.4.0", 702 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", 703 | "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", 704 | "dev": true, 705 | "requires": { 706 | "graceful-fs": "4.1.11" 707 | } 708 | }, 709 | "jsonify": { 710 | "version": "0.0.0", 711 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 712 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", 713 | "dev": true 714 | }, 715 | "jsprim": { 716 | "version": "1.4.1", 717 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 718 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 719 | "dev": true, 720 | "requires": { 721 | "assert-plus": "1.0.0", 722 | "extsprintf": "1.3.0", 723 | "json-schema": "0.2.3", 724 | "verror": "1.10.0" 725 | }, 726 | "dependencies": { 727 | "assert-plus": { 728 | "version": "1.0.0", 729 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 730 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 731 | "dev": true 732 | } 733 | } 734 | }, 735 | "kew": { 736 | "version": "0.7.0", 737 | "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", 738 | "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", 739 | "dev": true 740 | }, 741 | "kind-of": { 742 | "version": "3.2.2", 743 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 744 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 745 | "dev": true, 746 | "requires": { 747 | "is-buffer": "1.1.6" 748 | } 749 | }, 750 | "klaw": { 751 | "version": "1.3.1", 752 | "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", 753 | "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", 754 | "dev": true, 755 | "requires": { 756 | "graceful-fs": "4.1.11" 757 | } 758 | }, 759 | "lazy-cache": { 760 | "version": "1.0.4", 761 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 762 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", 763 | "dev": true 764 | }, 765 | "lodash": { 766 | "version": "3.7.0", 767 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz", 768 | "integrity": "sha1-Nni9irmVBXwHreg27S7wh9qBHUU=", 769 | "dev": true 770 | }, 771 | "longest": { 772 | "version": "1.0.1", 773 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 774 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", 775 | "dev": true 776 | }, 777 | "mime-db": { 778 | "version": "1.30.0", 779 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 780 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", 781 | "dev": true 782 | }, 783 | "mime-types": { 784 | "version": "2.1.17", 785 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 786 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 787 | "dev": true, 788 | "requires": { 789 | "mime-db": "1.30.0" 790 | } 791 | }, 792 | "minimatch": { 793 | "version": "3.0.4", 794 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 795 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 796 | "dev": true, 797 | "requires": { 798 | "brace-expansion": "1.1.8" 799 | } 800 | }, 801 | "minimist": { 802 | "version": "1.2.0", 803 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 804 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", 805 | "dev": true 806 | }, 807 | "mkdirp": { 808 | "version": "0.5.0", 809 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", 810 | "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", 811 | "dev": true, 812 | "requires": { 813 | "minimist": "0.0.8" 814 | }, 815 | "dependencies": { 816 | "minimist": { 817 | "version": "0.0.8", 818 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 819 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 820 | "dev": true 821 | } 822 | } 823 | }, 824 | "ms": { 825 | "version": "2.0.0", 826 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 827 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 828 | "dev": true 829 | }, 830 | "node-qunit-phantomjs": { 831 | "version": "1.6.0", 832 | "resolved": "https://registry.npmjs.org/node-qunit-phantomjs/-/node-qunit-phantomjs-1.6.0.tgz", 833 | "integrity": "sha512-biPV9v2CSuDT6CxQyPOZj4baFdPftxbklcJREXmzxVdpngmI2VqZvAgnkKx5LAJXmJvrct078Al+vHHVBAn1kQ==", 834 | "dev": true, 835 | "requires": { 836 | "chalk": "2.3.0", 837 | "minimist": "1.2.0", 838 | "phantomjs-prebuilt": "2.1.15", 839 | "qunit-phantomjs-runner": "2.3.0" 840 | } 841 | }, 842 | "oauth-sign": { 843 | "version": "0.8.2", 844 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", 845 | "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", 846 | "dev": true 847 | }, 848 | "once": { 849 | "version": "1.4.0", 850 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 851 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 852 | "dev": true, 853 | "requires": { 854 | "wrappy": "1.0.2" 855 | } 856 | }, 857 | "parserlib": { 858 | "version": "0.2.5", 859 | "resolved": "https://registry.npmjs.org/parserlib/-/parserlib-0.2.5.tgz", 860 | "integrity": "sha1-hZB92GBaoGq7PdKV1QuyuPpN0Rc=", 861 | "dev": true 862 | }, 863 | "path-is-absolute": { 864 | "version": "1.0.1", 865 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 866 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 867 | "dev": true 868 | }, 869 | "pend": { 870 | "version": "1.2.0", 871 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 872 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", 873 | "dev": true 874 | }, 875 | "performance-now": { 876 | "version": "0.2.0", 877 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", 878 | "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", 879 | "dev": true 880 | }, 881 | "phantomjs-prebuilt": { 882 | "version": "2.1.15", 883 | "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.15.tgz", 884 | "integrity": "sha1-IPhugtM0nFBZF1J3RbekEeCLOQM=", 885 | "dev": true, 886 | "requires": { 887 | "es6-promise": "4.0.5", 888 | "extract-zip": "1.6.6", 889 | "fs-extra": "1.0.0", 890 | "hasha": "2.2.0", 891 | "kew": "0.7.0", 892 | "progress": "1.1.8", 893 | "request": "2.81.0", 894 | "request-progress": "2.0.1", 895 | "which": "1.2.14" 896 | } 897 | }, 898 | "pinkie": { 899 | "version": "2.0.4", 900 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 901 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 902 | "dev": true 903 | }, 904 | "pinkie-promise": { 905 | "version": "2.0.1", 906 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 907 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 908 | "dev": true, 909 | "requires": { 910 | "pinkie": "2.0.4" 911 | } 912 | }, 913 | "process-nextick-args": { 914 | "version": "1.0.7", 915 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 916 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", 917 | "dev": true 918 | }, 919 | "progress": { 920 | "version": "1.1.8", 921 | "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", 922 | "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", 923 | "dev": true 924 | }, 925 | "punycode": { 926 | "version": "1.4.1", 927 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 928 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", 929 | "dev": true 930 | }, 931 | "qs": { 932 | "version": "6.4.0", 933 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", 934 | "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", 935 | "dev": true 936 | }, 937 | "qunit-phantomjs-runner": { 938 | "version": "2.3.0", 939 | "resolved": "https://registry.npmjs.org/qunit-phantomjs-runner/-/qunit-phantomjs-runner-2.3.0.tgz", 940 | "integrity": "sha1-JwrLGXwPL8qvBmdqsKSP1aymapk=", 941 | "dev": true, 942 | "requires": { 943 | "qunit-reporter-junit": "1.1.1" 944 | } 945 | }, 946 | "qunit-reporter-junit": { 947 | "version": "1.1.1", 948 | "resolved": "https://registry.npmjs.org/qunit-reporter-junit/-/qunit-reporter-junit-1.1.1.tgz", 949 | "integrity": "sha1-7rYiZFeJaZPnlaEZQPGK9q+lebQ=", 950 | "dev": true 951 | }, 952 | "readable-stream": { 953 | "version": "1.1.14", 954 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 955 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 956 | "dev": true, 957 | "requires": { 958 | "core-util-is": "1.0.2", 959 | "inherits": "2.0.3", 960 | "isarray": "0.0.1", 961 | "string_decoder": "0.10.31" 962 | } 963 | }, 964 | "repeat-string": { 965 | "version": "1.6.1", 966 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 967 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", 968 | "dev": true 969 | }, 970 | "request": { 971 | "version": "2.81.0", 972 | "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", 973 | "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", 974 | "dev": true, 975 | "requires": { 976 | "aws-sign2": "0.6.0", 977 | "aws4": "1.6.0", 978 | "caseless": "0.12.0", 979 | "combined-stream": "1.0.5", 980 | "extend": "3.0.1", 981 | "forever-agent": "0.6.1", 982 | "form-data": "2.1.4", 983 | "har-validator": "4.2.1", 984 | "hawk": "3.1.3", 985 | "http-signature": "1.1.1", 986 | "is-typedarray": "1.0.0", 987 | "isstream": "0.1.2", 988 | "json-stringify-safe": "5.0.1", 989 | "mime-types": "2.1.17", 990 | "oauth-sign": "0.8.2", 991 | "performance-now": "0.2.0", 992 | "qs": "6.4.0", 993 | "safe-buffer": "5.1.1", 994 | "stringstream": "0.0.5", 995 | "tough-cookie": "2.3.3", 996 | "tunnel-agent": "0.6.0", 997 | "uuid": "3.1.0" 998 | } 999 | }, 1000 | "request-progress": { 1001 | "version": "2.0.1", 1002 | "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", 1003 | "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", 1004 | "dev": true, 1005 | "requires": { 1006 | "throttleit": "1.0.0" 1007 | } 1008 | }, 1009 | "right-align": { 1010 | "version": "0.1.3", 1011 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 1012 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 1013 | "dev": true, 1014 | "requires": { 1015 | "align-text": "0.1.4" 1016 | } 1017 | }, 1018 | "safe-buffer": { 1019 | "version": "5.1.1", 1020 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 1021 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", 1022 | "dev": true 1023 | }, 1024 | "shelljs": { 1025 | "version": "0.3.0", 1026 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", 1027 | "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", 1028 | "dev": true 1029 | }, 1030 | "sntp": { 1031 | "version": "1.0.9", 1032 | "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", 1033 | "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", 1034 | "dev": true, 1035 | "requires": { 1036 | "hoek": "2.16.3" 1037 | } 1038 | }, 1039 | "source-map": { 1040 | "version": "0.4.4", 1041 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 1042 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 1043 | "dev": true, 1044 | "requires": { 1045 | "amdefine": "1.0.1" 1046 | } 1047 | }, 1048 | "sshpk": { 1049 | "version": "1.13.1", 1050 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", 1051 | "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", 1052 | "dev": true, 1053 | "requires": { 1054 | "asn1": "0.2.3", 1055 | "assert-plus": "1.0.0", 1056 | "bcrypt-pbkdf": "1.0.1", 1057 | "dashdash": "1.14.1", 1058 | "ecc-jsbn": "0.1.1", 1059 | "getpass": "0.1.7", 1060 | "jsbn": "0.1.1", 1061 | "tweetnacl": "0.14.5" 1062 | }, 1063 | "dependencies": { 1064 | "assert-plus": { 1065 | "version": "1.0.0", 1066 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 1067 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 1068 | "dev": true 1069 | } 1070 | } 1071 | }, 1072 | "string_decoder": { 1073 | "version": "0.10.31", 1074 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1075 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", 1076 | "dev": true 1077 | }, 1078 | "stringstream": { 1079 | "version": "0.0.5", 1080 | "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", 1081 | "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", 1082 | "dev": true 1083 | }, 1084 | "strip-json-comments": { 1085 | "version": "1.0.4", 1086 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", 1087 | "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", 1088 | "dev": true 1089 | }, 1090 | "supports-color": { 1091 | "version": "4.5.0", 1092 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", 1093 | "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", 1094 | "dev": true, 1095 | "requires": { 1096 | "has-flag": "2.0.0" 1097 | } 1098 | }, 1099 | "throttleit": { 1100 | "version": "1.0.0", 1101 | "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", 1102 | "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", 1103 | "dev": true 1104 | }, 1105 | "tough-cookie": { 1106 | "version": "2.3.3", 1107 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", 1108 | "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", 1109 | "dev": true, 1110 | "requires": { 1111 | "punycode": "1.4.1" 1112 | } 1113 | }, 1114 | "tunnel-agent": { 1115 | "version": "0.6.0", 1116 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1117 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1118 | "dev": true, 1119 | "requires": { 1120 | "safe-buffer": "5.1.1" 1121 | } 1122 | }, 1123 | "tweetnacl": { 1124 | "version": "0.14.5", 1125 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1126 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 1127 | "dev": true, 1128 | "optional": true 1129 | }, 1130 | "typedarray": { 1131 | "version": "0.0.6", 1132 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1133 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 1134 | "dev": true 1135 | }, 1136 | "uglify-js": { 1137 | "version": "2.8.29", 1138 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 1139 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 1140 | "dev": true, 1141 | "requires": { 1142 | "source-map": "0.5.7", 1143 | "uglify-to-browserify": "1.0.2", 1144 | "yargs": "3.10.0" 1145 | }, 1146 | "dependencies": { 1147 | "source-map": { 1148 | "version": "0.5.7", 1149 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1150 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1151 | "dev": true 1152 | } 1153 | } 1154 | }, 1155 | "uglify-to-browserify": { 1156 | "version": "1.0.2", 1157 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 1158 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 1159 | "dev": true, 1160 | "optional": true 1161 | }, 1162 | "util-deprecate": { 1163 | "version": "1.0.2", 1164 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1165 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1166 | "dev": true 1167 | }, 1168 | "uuid": { 1169 | "version": "3.1.0", 1170 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", 1171 | "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", 1172 | "dev": true 1173 | }, 1174 | "verror": { 1175 | "version": "1.10.0", 1176 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1177 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1178 | "dev": true, 1179 | "requires": { 1180 | "assert-plus": "1.0.0", 1181 | "core-util-is": "1.0.2", 1182 | "extsprintf": "1.3.0" 1183 | }, 1184 | "dependencies": { 1185 | "assert-plus": { 1186 | "version": "1.0.0", 1187 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 1188 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 1189 | "dev": true 1190 | } 1191 | } 1192 | }, 1193 | "which": { 1194 | "version": "1.2.14", 1195 | "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", 1196 | "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", 1197 | "dev": true, 1198 | "requires": { 1199 | "isexe": "2.0.0" 1200 | } 1201 | }, 1202 | "window-size": { 1203 | "version": "0.1.0", 1204 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 1205 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", 1206 | "dev": true 1207 | }, 1208 | "wordwrap": { 1209 | "version": "0.0.2", 1210 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 1211 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", 1212 | "dev": true 1213 | }, 1214 | "wrappy": { 1215 | "version": "1.0.2", 1216 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1217 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1218 | "dev": true 1219 | }, 1220 | "yargs": { 1221 | "version": "3.10.0", 1222 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 1223 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 1224 | "dev": true, 1225 | "requires": { 1226 | "camelcase": "1.2.1", 1227 | "cliui": "2.1.0", 1228 | "decamelize": "1.2.0", 1229 | "window-size": "0.1.0" 1230 | } 1231 | }, 1232 | "yauzl": { 1233 | "version": "2.4.1", 1234 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", 1235 | "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", 1236 | "dev": true, 1237 | "requires": { 1238 | "fd-slicer": "1.0.1" 1239 | } 1240 | } 1241 | } 1242 | } 1243 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-treeview", 3 | "version": "1.1.5", 4 | "description": "TreeView implemented with vanilla JavaScript", 5 | "main": "index.js", 6 | "scripts": { 7 | "pretest": "npm run js:lint && npm run css:lint", 8 | "test": "node-qunit-phantomjs ./test/index.html", 9 | "build": "npm run js:min && npm run css:min", 10 | "js:lint": "jshint src", 11 | "js:min": "npm run js:lint && uglifyjs src/treeview.js -o dist/treeview.min.js --source-map dist/treeview.min.js.map --mangle --compress", 12 | "css:lint": "csslint src", 13 | "css:min": "npm run css:lint && cleancss src/treeview.css -o dist/treeview.min.css --source-map" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/justinchmura/js-treeview.git" 18 | }, 19 | "keywords": [ 20 | "tree", 21 | "treeview", 22 | "vanilla", 23 | "vanilla-js", 24 | "browser", 25 | "ui" 26 | ], 27 | "author": { 28 | "name": "Justin Chmura", 29 | "email": "justin.chmura@gmail.com", 30 | "url": "http://justinchmura.com/" 31 | }, 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/justinchmura/js-treeview/issues" 35 | }, 36 | "homepage": "https://github.com/justinchmura/js-treeview", 37 | "readmeFilename": "README.md", 38 | "devDependencies": { 39 | "clean-css": "^3.4.11", 40 | "csslint": "^0.10.0", 41 | "jshint": "^2.8.0", 42 | "node-qunit-phantomjs": "^1.4.0", 43 | "uglify-js": "^2.6.1" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/treeview.css: -------------------------------------------------------------------------------- 1 | .tree-leaf { position: relative; } 2 | .tree-leaf .tree-child-leaves { display: block; margin-left: 15px; } 3 | .tree-leaf .hidden { display: none; } 4 | .tree-leaf .tree-expando { background: #ddd; border-radius: 3px; cursor: pointer; float: left; height: 10px; line-height: 10px; position: relative; text-align: center; top: 5px; width: 10px; } 5 | .tree-leaf .hidden { visibility: hidden; } 6 | .tree-leaf .tree-expando:hover { background: #aaa; } 7 | .tree-leaf .tree-leaf-text { cursor: pointer; float: left; margin-left: 5px; } 8 | .tree-leaf .tree-leaf-text:hover { color: blue; } 9 | .tree-leaf .tree-leaf-content:before, .tree-leaf .tree-leaf-content:after { content: " "; display: table; } 10 | .tree-leaf .tree-leaf-content:after { clear: both; } 11 | -------------------------------------------------------------------------------- /src/treeview.js: -------------------------------------------------------------------------------- 1 | (function (define) { 2 | 'use strict'; 3 | 4 | (function (root, factory) { 5 | if (typeof define === 'function' && define.amd) { 6 | define(factory); 7 | } else if (typeof exports === 'object') { 8 | module.exports = factory(); 9 | } else { 10 | root.TreeView = factory(); 11 | } 12 | }(window, function () { 13 | return (function () { 14 | 15 | /** List of events supported by the tree view */ 16 | var events = [ 17 | 'expand', 18 | 'expandAll', 19 | 'collapse', 20 | 'collapseAll', 21 | 'select' 22 | ]; 23 | 24 | /** 25 | * A utilite function to check to see if something is a DOM object 26 | * @param {object} Object to test 27 | * @returns {boolean} If the object is a DOM object 28 | */ 29 | function isDOMElement(obj) { 30 | try { 31 | return obj instanceof HTMLElement; 32 | } catch (e) { 33 | // Some browsers don't support using the HTMLElement so some extra 34 | // checks are needed. 35 | return typeof obj === 'object' && obj.nodeType === 1 && typeof obj.style === 'object' && typeof obj.ownerDocument === 'object'; 36 | } 37 | } 38 | 39 | /** 40 | * A forEach that will work with a NodeList and generic Arrays 41 | * @param {array|NodeList} arr The array to iterate over 42 | * @param {function} callback Function that executes for each element. First parameter is element, second is index 43 | * @param {object} The context to execute callback with 44 | */ 45 | function forEach(arr, callback, scope) { 46 | var i, len = arr.length; 47 | for (i = 0; i < len; i += 1) { 48 | callback.call(scope, arr[i], i); 49 | } 50 | } 51 | 52 | /** 53 | * Emit an event from the tree view 54 | * @param {string} name The name of the event to emit 55 | */ 56 | function emit(instance, name) { 57 | var args = [].slice.call(arguments, 2); 58 | if (events.indexOf(name) > -1) { 59 | if (instance.handlers[name] && instance.handlers[name] instanceof Array) { 60 | forEach(instance.handlers[name], function (handle) { 61 | window.setTimeout(function () { 62 | handle.callback.apply(handle.context, args); 63 | }, 0); 64 | }); 65 | } 66 | } else { 67 | throw new Error(name + ' event cannot be found on TreeView.'); 68 | } 69 | } 70 | 71 | /** 72 | * Renders the tree view in the DOM 73 | */ 74 | function render(self) { 75 | var container = isDOMElement(self.node) ? self.node : document.getElementById(self.node); 76 | var leaves = [], click; 77 | var renderLeaf = function (item) { 78 | var leaf = document.createElement('div'); 79 | var content = document.createElement('div'); 80 | var text = document.createElement('div'); 81 | var expando = document.createElement('div'); 82 | 83 | leaf.setAttribute('class', 'tree-leaf'); 84 | content.setAttribute('class', 'tree-leaf-content'); 85 | content.setAttribute('data-item', JSON.stringify(item)); 86 | text.setAttribute('class', 'tree-leaf-text'); 87 | text.textContent = item.name; 88 | expando.setAttribute('class', 'tree-expando ' + (item.expanded ? 'expanded' : '')); 89 | expando.textContent = item.expanded ? '-' : '+'; 90 | content.appendChild(expando); 91 | content.appendChild(text); 92 | leaf.appendChild(content); 93 | if (item.children && item.children.length > 0) { 94 | var children = document.createElement('div'); 95 | children.setAttribute('class', 'tree-child-leaves'); 96 | forEach(item.children, function (child) { 97 | var childLeaf = renderLeaf(child); 98 | children.appendChild(childLeaf); 99 | }); 100 | if (!item.expanded) { 101 | children.classList.add('hidden'); 102 | } 103 | leaf.appendChild(children); 104 | } else { 105 | expando.classList.add('hidden'); 106 | } 107 | return leaf; 108 | }; 109 | 110 | forEach(self.data, function (item) { 111 | leaves.push(renderLeaf.call(self, item)); 112 | }); 113 | container.innerHTML = leaves.map(function (leaf) { 114 | return leaf.outerHTML; 115 | }).join(''); 116 | 117 | click = function (e) { 118 | var parent = (e.target || e.currentTarget).parentNode; 119 | var data = JSON.parse(parent.getAttribute('data-item')); 120 | var leaves = parent.parentNode.querySelector('.tree-child-leaves'); 121 | if (leaves) { 122 | if (leaves.classList.contains('hidden')) { 123 | self.expand(parent, leaves); 124 | } else { 125 | self.collapse(parent, leaves); 126 | } 127 | } else { 128 | emit(self, 'select', { 129 | target: e, 130 | data: data 131 | }); 132 | } 133 | }; 134 | 135 | forEach(container.querySelectorAll('.tree-leaf-text'), function (node) { 136 | node.onclick = click; 137 | }); 138 | forEach(container.querySelectorAll('.tree-expando'), function (node) { 139 | node.onclick = click; 140 | }); 141 | } 142 | 143 | /** 144 | * @constructor 145 | * @property {object} handlers The attached event handlers 146 | * @property {object} data The JSON object that represents the tree structure 147 | * @property {DOMElement} node The DOM element to render the tree in 148 | */ 149 | function TreeView(data, node) { 150 | this.handlers = {}; 151 | this.node = node; 152 | this.data = data; 153 | render(this); 154 | } 155 | 156 | /** 157 | * Expands a leaflet by the expando or the leaf text 158 | * @param {DOMElement} node The parent node that contains the leaves 159 | * @param {DOMElement} leaves The leaves wrapper element 160 | */ 161 | TreeView.prototype.expand = function (node, leaves, skipEmit) { 162 | var expando = node.querySelector('.tree-expando'); 163 | expando.textContent = '-'; 164 | leaves.classList.remove('hidden'); 165 | if (skipEmit) { return; } 166 | emit(this, 'expand', { 167 | target: node, 168 | leaves: leaves 169 | }); 170 | }; 171 | 172 | TreeView.prototype.expandAll = function () { 173 | var self = this; 174 | var nodes = document.getElementById(self.node).querySelectorAll('.tree-expando'); 175 | forEach(nodes, function (node) { 176 | var parent = node.parentNode; 177 | var leaves = parent.parentNode.querySelector('.tree-child-leaves'); 178 | if (parent && leaves && parent.hasAttribute('data-item')) { 179 | self.expand(parent, leaves, true); 180 | } 181 | }); 182 | emit(this, 'expandAll', {}); 183 | }; 184 | 185 | /** 186 | * Collapses a leaflet by the expando or the leaf text 187 | * @param {DOMElement} node The parent node that contains the leaves 188 | * @param {DOMElement} leaves The leaves wrapper element 189 | */ 190 | TreeView.prototype.collapse = function (node, leaves, skipEmit) { 191 | var expando = node.querySelector('.tree-expando'); 192 | expando.textContent = '+'; 193 | leaves.classList.add('hidden'); 194 | if (skipEmit) { return; } 195 | emit(this, 'collapse', { 196 | target: node, 197 | leaves: leaves 198 | }); 199 | }; 200 | 201 | /** 202 | */ 203 | TreeView.prototype.collapseAll = function () { 204 | var self = this; 205 | var nodes = document.getElementById(self.node).querySelectorAll('.tree-expando'); 206 | forEach(nodes, function (node) { 207 | var parent = node.parentNode; 208 | var leaves = parent.parentNode.querySelector('.tree-child-leaves'); 209 | if (parent && leaves && parent.hasAttribute('data-item')) { 210 | self.collapse(parent, leaves, true); 211 | } 212 | }); 213 | emit(this, 'collapseAll', {}); 214 | }; 215 | 216 | /** 217 | * Attach an event handler to the tree view 218 | * @param {string} name Name of the event to attach 219 | * @param {function} callback The callback to execute on the event 220 | * @param {object} scope The context to call the callback with 221 | */ 222 | TreeView.prototype.on = function (name, callback, scope) { 223 | if (events.indexOf(name) > -1) { 224 | if (!this.handlers[name]) { 225 | this.handlers[name] = []; 226 | } 227 | this.handlers[name].push({ 228 | callback: callback, 229 | context: scope 230 | }); 231 | } else { 232 | throw new Error(name + ' is not supported by TreeView.'); 233 | } 234 | }; 235 | 236 | /** 237 | * Deattach an event handler from the tree view 238 | * @param {string} name Name of the event to deattach 239 | * @param {function} callback The function to deattach 240 | */ 241 | TreeView.prototype.off = function (name, callback) { 242 | var index, found = false; 243 | if (this.handlers[name] instanceof Array) { 244 | this.handlers[name].forEach(function (handle, i) { 245 | index = i; 246 | if (handle.callback === callback && !found) { 247 | found = true; 248 | } 249 | }); 250 | if (found) { 251 | this.handlers[name].splice(index, 1); 252 | } 253 | } 254 | }; 255 | 256 | return TreeView; 257 | }()); 258 | })); 259 | }(window.define)); 260 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Treeview Test Suite 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

Treeview Test Suite

14 |

15 |
16 |

17 |
    18 |
    19 |
    20 |
    21 |
    22 | 23 | 24 | -------------------------------------------------------------------------------- /test/test-runner.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | 'use strict'; 3 | 4 | var tree; 5 | var data = [ 6 | { name: 'Vegetables', children: [] }, 7 | { name: 'Fruits', expanded: true, children: [ 8 | { name: 'Apple', children: [] }, 9 | { name: 'Orange', children: [] }, 10 | { name: 'Lemon', children: [] } 11 | ] 12 | }, 13 | { name: 'Candy', expanded: true, children: [ 14 | { name: 'Gummies', children: [] }, 15 | { name: 'Chocolate', expanded: true, children: [ 16 | { name: 'M & M\'s', children: [] }, 17 | { name: 'Hershey Bar', children: [] } 18 | ] 19 | } 20 | ] 21 | }, 22 | { name: 'Bread', children: [] } 23 | ]; 24 | 25 | function setup() { 26 | tree = new TreeView(data, 'treeview'); 27 | } 28 | 29 | module('init', { setup: setup }); 30 | 31 | test('creates leaf for each item', function () { 32 | var leafCount = $('#treeview .tree-leaf-text').length; 33 | equal(leafCount, 11, 'Proper amount of leaves'); 34 | }); 35 | 36 | test('creates expando for each item with children', function () { 37 | var expandoCount = $('#treeview .tree-expando').not('.hidden').length; 38 | equal(expandoCount, 3, 'Proper amount of expandos'); 39 | }); 40 | 41 | module('events', { setup: setup }); 42 | 43 | asyncTest('emits "expand" event when leaf is expanded', function () { 44 | var $expando = $('#treeview .tree-leaf-text:contains("Candy")').first().siblings('.tree-expando'); 45 | $expando.click(); // Collapse it first 46 | tree.on('expand', function (e) { 47 | ok(true, 'Expand emitted'); 48 | start(); 49 | }); 50 | $expando.click(); // Expand leaf 51 | }); 52 | 53 | asyncTest('emits "collapse" event when leaf is collapsed', function () { 54 | var $expando = $('#treeview .tree-leaf-text:contains("Candy")').first().siblings('.tree-expando'); 55 | tree.on('collapse', function (e) { 56 | ok(true, 'Collapse emitted'); 57 | start(); 58 | }); 59 | $expando.click(); // Collapse leaf 60 | }); 61 | 62 | asyncTest('emits "select" event when a leaf is clicked', function () { 63 | var $leaf = $('#treeview .tree-leaf-text:contains("Orange")'); 64 | tree.on('select', function (e) { 65 | ok(true, 'Select emitted'); 66 | equal(e.data.name, 'Orange', 'Proper leaf clicked'); 67 | equal(e.data.children.length, 0, 'No children on leaf'); 68 | start(); 69 | }); 70 | $leaf.click(); 71 | }); 72 | 73 | asyncTest('emits "expandAll" event when expandAll method is called', function () { 74 | tree.on('expandAll', function () { 75 | ok(true, 'expandAll emitted'); 76 | start(); 77 | }); 78 | tree.expandAll(); 79 | }); 80 | 81 | asyncTest('emits "collapseAll" event when collapseAll method is called', function () { 82 | tree.on('collapseAll', function () { 83 | ok(true, 'collapseAll emitted'); 84 | start(); 85 | }); 86 | tree.collapseAll(); 87 | }); 88 | 89 | test('supports passing in a DOM object', function () { 90 | var element = document.getElementById('dom-treeview'); 91 | var domTree = new TreeView(data, element); 92 | var leafCount = $('#dom-treeview .tree-leaf-text').length; 93 | equal(leafCount, 11, 'Proper amount of leaves'); 94 | var expandoCount = $('#dom-treeview .tree-expando').not('.hidden').length; 95 | equal(expandoCount, 3, 'Proper amount of expandos'); 96 | }); 97 | 98 | }(window.jQuery)); 99 | --------------------------------------------------------------------------------