UNPKG

json-tree-view

Version:

A JSON Tree View Component, for browsering or editing JSON object. Fork from json-view writing by Richard Livingston.

2,028 lines (1,709 loc) 143 kB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ /** * Created by richard.livingston on 18/02/2017. */ 'use strict'; var util = require('util'), EE = require('events').EventEmitter; module.exports = JSONTreeView; util.inherits(JSONTreeView, EE); function JSONTreeView(name_, value_, parent_, isRoot_){ var self = this; if (typeof isRoot_ === 'undefined' && arguments.length < 4) { isRoot_ = true; } EE.call(self); if(arguments.length < 2){ value_ = name_; name_ = undefined; } var name, value, type, oldType = null, filterText = '', hidden = false, readonly = parent_ ? parent_.readonly : false, readonlyWhenFiltering = parent_ ? parent_.readonlyWhenFiltering : false, alwaysShowRoot = false, showCount = parent_ ? parent_.showCountOfObjectOrArray : true, includingRootName = true, domEventListeners = [], children = [], expanded = false, edittingName = false, edittingValue = false, nameEditable = true, valueEditable = true; var dom = { container : document.createElement('div'), collapseExpand : document.createElement('div'), name : document.createElement('div'), separator : document.createElement('div'), value : document.createElement('div'), spacing: document.createElement('div'), delete : document.createElement('div'), children : document.createElement('div'), insert : document.createElement('div') }; Object.defineProperties(self, { dom : { value : dom.container, enumerable : true }, isRoot: { get : function(){ return isRoot_; } }, parent: { get: function() { return parent_; } }, children: { get: function() { var result = null; if (type === 'array') { result = children; } else if (type === 'object') { result = {}; children.forEach(function(e) { result[e.name] = e; }); } return result; } }, readonly: { get: function() { return !!(readonly & 1); }, set: function(ro) { readonly = setBit(readonly, 0, +ro); !!(readonly & 1) ? dom.container.classList.add('readonly') : dom.container.classList.remove('readonly'); for (var i in children) { if (typeof children[i] === 'object') { children[i].readonly = setBit(readonly, 0, +ro); } } } }, readonlyWhenFiltering: { get: function() { return readonlyWhenFiltering; }, set: function(rowf) { readonly = setBit(readonly, 1, +rowf); readonlyWhenFiltering = rowf; (readonly && this.filterText) || !!(readonly & 1) ? dom.container.classList.add('readonly') : dom.container.classList.remove('readonly'); for (var i in children) { if (typeof children[i] === 'object') { children[i].readonly = setBit(readonly, 1, +rowf); children[i].readonlyWhenFiltering = rowf; } } } }, hidden: { get: function() { return hidden; }, set: function(h) { hidden = h; h ? dom.container.classList.add('hidden') : dom.container.classList.remove('hidden'); if (!h) { parent_ && (parent_.hidden = h); } } }, showCountOfObjectOrArray: { get: function() { return showCount; }, set: function(show) { showCount = show; for (var i in children) { if (typeof children[i] === 'object') { children[i].showCountOfObjectOrArray = show; } } (this.type === 'object' || this.type === 'array') && this.updateCount(); } }, filterText: { get: function() { return filterText; }, set: function(text) { filterText = text; if (text) { if (readonly > 0) { dom.container.classList.add('readonly'); } var key = this.name + ''; var value = this.value + ''; if (this.type === 'object' || this.type === 'array') { value = ''; } if (key.indexOf(text) > -1 || value.indexOf(text) > -1) { this.hidden = false; } else { if (!this.alwaysShowRoot || !isRoot_) { this.hidden = true; } } } else { !this.readonly && dom.container.classList.remove('readonly'); this.hidden = false; } for (var i in children) { if (typeof children[i] === 'object') { children[i].filterText = text; } } } }, alwaysShowRoot: { get: function() { return alwaysShowRoot; }, set: function(value) { if (isRoot_ && this.filterText) { this.hidden = !value; } alwaysShowRoot = value; for (var i in children) { if (typeof children[i] === 'object') { children[i].alwaysShowRoot = value; } } } }, withRootName: { get: function() { return includingRootName; }, set: function(value) { includingRootName = value; } }, name : { get : function(){ return name; }, set : setName, enumerable : true }, value : { get : function(){ return value; }, set : setValue, enumerable : true }, type : { get : function(){ return type; }, enumerable : true }, oldType: { get: function () { return oldType; }, enumerable: true }, nameEditable : { get : function(){ return nameEditable; }, set : function(value){ nameEditable = !!value; }, enumerable : true }, valueEditable : { get : function(){ return valueEditable; }, set : function(value){ valueEditable = !!value; }, enumerable : true }, refresh : { value : refresh, enumerable : true }, updateCount: { value: updateObjectChildCount, enumerable: true }, collapse : { value : collapse, enumerable : true }, expand : { value : expand, enumerable : true }, destroy : { value : destroy, enumerable : true }, editName : { value : editField.bind(null, 'name'), enumerable : true }, editValue : { value : editField.bind(null, 'value'), enumerable : true } }); Object.keys(dom).forEach(function(k){ if (k === 'delete' && self.isRoot) { return; } var element = dom[k]; if(k == 'container'){ return; } element.className = k; if (['name', 'separator', 'value', 'spacing'].indexOf(k) > -1) { element.className += ' item'; } dom.container.appendChild(element); }); dom.container.className = 'jsonView'; addDomEventListener(dom.collapseExpand, 'click', onCollapseExpandClick); addDomEventListener(dom.value, 'click', expand.bind(null, false)); addDomEventListener(dom.name, 'click', expand.bind(null, false)); addDomEventListener(dom.name, 'dblclick', editField.bind(null, 'name')); addDomEventListener(dom.name, 'click', itemClicked.bind(null, 'name')); addDomEventListener(dom.name, 'blur', editFieldStop.bind(null, 'name')); addDomEventListener(dom.name, 'keypress', editFieldKeyPressed.bind(null, 'name')); addDomEventListener(dom.name, 'keydown', editFieldTabPressed.bind(null, 'name')); addDomEventListener(dom.value, 'dblclick', editField.bind(null, 'value')); addDomEventListener(dom.value, 'click', itemClicked.bind(null, 'value')); addDomEventListener(dom.value, 'blur', editFieldStop.bind(null, 'value')); addDomEventListener(dom.value, 'keypress', editFieldKeyPressed.bind(null, 'value')); addDomEventListener(dom.value, 'keydown', editFieldTabPressed.bind(null, 'value')); addDomEventListener(dom.value, 'keydown', numericValueKeyDown); addDomEventListener(dom.insert, 'click', onInsertClick); addDomEventListener(dom.delete, 'click', onDeleteClick); setName(name_); setValue(value_); function setBit(n, i, b) { var j = 0; while ((n >> j << j)) { j++; } return i >= j ? (n | +b << i ) : (n >> (i + 1) << (i + 1)) | (n % (n >> i << i)) | (+b << i); } function squarebracketify(exp) { return typeof exp === 'string' ? exp.replace(/\.([0-9]+)/g, '[$1]') : exp + ''; } function refresh(silent){ var expandable = type == 'object' || type == 'array'; children.forEach(function(child){ child.refresh(true); }); dom.collapseExpand.style.display = expandable ? '' : 'none'; if(expanded && expandable){ expand(false, silent); } else{ collapse(false, silent); } if (!silent) { self.emit('refresh', self, [self.name], self.value); } } function collapse(recursive, silent){ if(recursive){ children.forEach(function(child){ child.collapse(true, true); }); } expanded = false; dom.children.style.display = 'none'; dom.collapseExpand.className = 'expand'; dom.container.classList.add('collapsed'); dom.container.classList.remove('expanded'); if (!silent && (type == 'object' || type == 'array')) { self.emit('collapse', self, [self.name], self.value); } } function expand(recursive, silent){ var keys; if(type == 'object'){ keys = Object.keys(value); } else if(type == 'array'){ keys = value.map(function(v, k){ return k; }); } else{ keys = []; } // Remove children that no longer exist for(var i = children.length - 1; i >= 0; i --){ var child = children[i]; if (!child) { break; } if(keys.indexOf(child.name) == -1){ children.splice(i, 1); removeChild(child); } } if(type != 'object' && type != 'array'){ return collapse(); } keys.forEach(function(key){ addChild(key, value[key]); }); if(recursive){ children.forEach(function(child){ child.expand(true, true); }); } expanded = true; dom.children.style.display = ''; dom.collapseExpand.className = 'collapse'; dom.container.classList.add('expanded'); dom.container.classList.remove('collapsed'); if (!silent && (type == 'object' || type == 'array')) { self.emit('expand', self, [self.name], self.value); } } function destroy(){ var child, event; while(event = domEventListeners.pop()){ event.element.removeEventListener(event.name, event.fn); } while(child = children.pop()){ removeChild(child); } } function setName(newName){ var nameType = typeof newName, oldName = name; if(newName === name){ return; } if(nameType != 'string' && nameType != 'number'){ throw new Error('Name must be either string or number, ' + newName); } dom.name.innerText = newName; name = newName; self.emit('rename', self, [name], oldName, newName, true); } function setValue(newValue){ var oldValue = value, str, len; if (isRoot_ && !oldValue) { oldValue = newValue; } type = getType(newValue); oldType = oldValue ? getType(oldValue) : type; switch(type){ case 'null': str = 'null'; break; case 'undefined': str = 'undefined'; break; case 'object': len = Object.keys(newValue).length; str = showCount ? 'Object[' + len + ']' : (len < 1 ? '{}' : ''); break; case 'array': len = newValue.length; str = showCount ? 'Array[' + len + ']' : (len < 1 ? '[]' : ''); break; default: str = newValue; break; } dom.value.innerText = str; dom.value.className = 'value item ' + type; if(newValue === value){ return; } value = newValue; if(type == 'array' || type == 'object'){ // Cannot edit objects as string because the formatting is too messy // Would have to either pass as JSON and force user to wrap properties in quotes // Or first JSON stringify the input before passing, this could allow users to reference globals // Instead the user can modify individual properties, or just delete the object and start again valueEditable = false; if(type == 'array'){ // Obviously cannot modify array keys nameEditable = false; } } self.emit('change', self, [name], oldValue, newValue); refresh(); } function updateObjectChildCount() { var str = '', len; if (type === 'object') { len = Object.keys(value).length; str = showCount ? 'Object[' + len + ']' : (len < 1 ? '{}' : ''); } if (type === 'array') { len = value.length; str = showCount ? 'Array[' + len + ']' : (len < 1 ? '[]' : ''); } dom.value.innerText = str; } function addChild(key, val){ var child; for(var i = 0, len = children.length; i < len; i ++){ if(children[i].name == key){ child = children[i]; break; } } if(child){ child.value = val; } else{ child = new JSONTreeView(key, val, self, false); child.on('rename', onChildRename); child.on('delete', onChildDelete); child.on('change', onChildChange); child.on('append', onChildAppend); child.on('click', onChildClick); child.on('expand', onChildExpand); child.on('collapse', onChildCollapse); child.on('refresh', onChildRefresh); children.push(child); child.emit('append', child, [key], 'value', val, true); } dom.children.appendChild(child.dom); return child; } function removeChild(child){ if(child.dom.parentNode){ dom.children.removeChild(child.dom); } child.destroy(); child.emit('delete', child, [child.name], child.value, child.parent.isRoot ? child.parent.oldType : child.parent.type, true); child.removeAllListeners(); } function editField(field){ if((readonly > 0 && filterText) || !!(readonly & 1)) { return; } if(field === 'value' && (type === 'object' || type === 'array')){ return; } if(parent_ && parent_.type == 'array'){ // Obviously cannot modify array keys nameEditable = false; } var editable = field == 'name' ? nameEditable : valueEditable, element = dom[field]; if(!editable && (parent_ && parent_.type === 'array')){ if (!parent_.inserting) { // throw new Error('Cannot edit an array index.'); return; } } if(field == 'value' && type == 'string'){ element.innerText = '"' + value + '"'; } if(field == 'name'){ edittingName = true; } if(field == 'value'){ edittingValue = true; } element.classList.add('edit'); element.setAttribute('contenteditable', true); element.focus(); document.execCommand('selectAll', false, null); } function itemClicked(field) { self.emit('click', self, !self.withRootName && self.isRoot ? [''] : [self.name], self.value); } function editFieldStop(field){ var element = dom[field]; if(field == 'name'){ if(!edittingName){ return; } edittingName = false; } if(field == 'value'){ if(!edittingValue){ return; } edittingValue = false; } if(field == 'name'){ var p = self.parent; var edittingNameText = element.innerText; if (p && p.type === 'object' && edittingNameText in p.value) { element.innerText = name; element.classList.remove('edit'); element.removeAttribute('contenteditable'); // throw new Error('Name exist, ' + edittingNameText); } else { setName.call(self, edittingNameText); } } else{ var text = element.innerText; try{ setValue(text === 'undefined' ? undefined : JSON.parse(text)); } catch(err){ setValue(text); } } element.classList.remove('edit'); element.removeAttribute('contenteditable'); } function editFieldKeyPressed(field, e){ switch(e.key){ case 'Escape': case 'Enter': editFieldStop(field); break; } } function editFieldTabPressed(field, e){ if(e.key == 'Tab'){ editFieldStop(field); if(field == 'name'){ e.preventDefault(); editField('value'); } else{ editFieldStop(field); } } } function numericValueKeyDown(e){ var increment = 0, currentValue; if(type != 'number'){ return; } switch(e.key){ case 'ArrowDown': case 'Down': increment = -1; break; case 'ArrowUp': case 'Up': increment = 1; break; } if(e.shiftKey){ increment *= 10; } if(e.ctrlKey || e.metaKey){ increment /= 10; } if(increment){ currentValue = parseFloat(dom.value.innerText); if(!isNaN(currentValue)){ setValue(Number((currentValue + increment).toFixed(10))); } } } function getType(value){ var type = typeof value; if(type == 'object'){ if(value === null){ return 'null'; } if(Array.isArray(value)){ return 'array'; } } if (type === 'undefined') { return 'undefined'; } return type; } function onCollapseExpandClick(){ if(expanded){ collapse(); } else{ expand(); } } function onInsertClick(){ var newName = type == 'array' ? value.length : undefined, child = addChild(newName, null); if (child.parent) { child.parent.inserting = true; } if(type == 'array'){ value.push(null); child.editValue(); child.emit('append', self, [value.length - 1], 'value', null, true); if (child.parent) { child.parent.inserting = false; } } else{ child.editName(); } } function onDeleteClick(){ self.emit('delete', self, [self.name], self.value, self.parent.isRoot ? self.parent.oldType : self.parent.type, false); } function onChildRename(child, keyPath, oldName, newName, original){ var allow = newName && type != 'array' && !(newName in value) && original; if(allow){ value[newName] = child.value; delete value[oldName]; if (self.inserting) { child.emit('append', child, [newName], 'name', newName, true); self.inserting = false; return; } } else if(oldName === undefined){ // A new node inserted via the UI original && removeChild(child); } else if (original){ // Cannot rename array keys, or duplicate object key names child.name = oldName; return; } // value[keyPath] = newName; // child.once('rename', onChildRename); if (self.withRootName || !self.isRoot) { keyPath.unshift(name); } else if (self.withRootName && self.isRoot) { keyPath.unshift(name); } if (oldName !== undefined) { self.emit('rename', child, keyPath, oldName, newName, false); } } function onChildAppend(child, keyPath, nameOrValue, newValue, sender){ if (self.withRootName || !self.isRoot) { keyPath.unshift(name); } self.emit('append', child, keyPath, nameOrValue, newValue, false); sender && updateObjectChildCount(); } function onChildChange(child, keyPath, oldValue, newValue, recursed){ if(!recursed){ value[keyPath] = newValue; } if (self.withRootName || !self.isRoot) { keyPath.unshift(name); } self.emit('change', child, keyPath, oldValue, newValue, true); } function onChildDelete(child, keyPath, deletedValue, parentType, passive){ var key = child.name; if (passive) { if (self.withRootName/* || !self.isRoot*/) { keyPath.unshift(name); } self.emit('delete', child, keyPath, deletedValue, parentType, passive); updateObjectChildCount(); } else { if (type == 'array') { value.splice(key, 1); } else { delete value[key]; } refresh(true); } } function onChildClick(child, keyPath, value) { if (self.withRootName || !self.isRoot) { keyPath.unshift(name); } self.emit('click', child, keyPath, value); } function onChildExpand(child, keyPath, value) { if (self.withRootName || !self.isRoot) { keyPath.unshift(name); } self.emit('expand', child, keyPath, value); } function onChildCollapse(child, keyPath, value) { if (self.withRootName || !self.isRoot) { keyPath.unshift(name); } self.emit('collapse', child, keyPath, value); } function onChildRefresh(child, keyPath, value) { if (self.withRootName || !self.isRoot) { keyPath.unshift(name); } self.emit('refresh', child, keyPath, value); } function addDomEventListener(element, name, fn){ element.addEventListener(name, fn); domEventListeners.push({element : element, name : name, fn : fn}); } } },{"events":3,"util":7}],2:[function(require,module,exports){ /** * Created by r1ch4 on 02/10/2016. */ var JSONTreeView = require('json-tree-view'); var view = new JSONTreeView('example', { hello : 'world', doubleClick : 'me to edit', a : null, b : true, c : false, d : 1, e : {nested : 'object'}, f : [1,2,3] }, null); view.expand(true); view.withRootName = true; view.on('change', function(self, keyPath, oldValue, newValue){ console.log('change', keyPath, oldValue, '=>', newValue); }); view.on('rename', function (self, keyPath, oldName, newName) { console.log('rename', keyPath, oldName, '=>', newName); }); view.on('delete', function (self, keyPath, value, parentType) { console.log('delete', keyPath, '=>', value, parentType); }); view.on('append', function (self, keyPath, nameOrValue, newValue) { console.log('append', keyPath, nameOrValue, '=>', newValue); }); view.on('click', function (self, keyPath, value) { console.log('click', keyPath, '=>', value); }); view.on('expand', function (self, keyPath, value) { console.log('expand', keyPath, '=>', value); }); view.on('collapse', function (self, keyPath, value) { console.log('collapse', keyPath, '=>', value); }); view.on('refresh', function (self, keyPath, value) { console.log('refresh', keyPath, '=>', value); }); document.body.appendChild(view.dom); window.view = view; view.value.f.pop() view.value.f.push(9) view.value.e.a = 'aaa'; view.value.e.d = 'ddd'; delete view.value.c; view.refresh(); /* view.alwaysShowRoot = true; view.readonlyWhenFiltering = true; view.filterText = 'a'; view.filterText = null; view.readonly = true; */ document.getElementById('filter').addEventListener('input', function() { view.filterText = this.value; }); document.getElementById('root').addEventListener('change', function() { view.alwaysShowRoot = !!this.checked; }); document.getElementById('rowf').addEventListener('change', function() { view.readonlyWhenFiltering = !!this.checked; }); document.getElementById('ro').addEventListener('change', function() { view.readonly = !!this.checked; }); document.getElementById('sc').addEventListener('change', function () { view.showCountOfObjectOrArray = !!this.checked; }); document.getElementById('wr').addEventListener('change', function () { view.withRootName = !!this.checked; }); },{"json-tree-view":1}],3:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. function EventEmitter() { this._events = this._events || {}; this._maxListeners = this._maxListeners || undefined; } module.exports = EventEmitter; // Backwards-compat with node 0.10.x EventEmitter.EventEmitter = EventEmitter; EventEmitter.prototype._events = undefined; EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. EventEmitter.defaultMaxListeners = 10; // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function(n) { if (!isNumber(n) || n < 0 || isNaN(n)) throw TypeError('n must be a positive number'); this._maxListeners = n; return this; }; EventEmitter.prototype.emit = function(type) { var er, handler, len, args, i, listeners; if (!this._events) this._events = {}; // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._events.error || (isObject(this._events.error) && !this._events.error.length)) { er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } else { // At least give some kind of context to the user var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); err.context = er; throw err; } } } handler = this._events[type]; if (isUndefined(handler)) return false; if (isFunction(handler)) { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: args = Array.prototype.slice.call(arguments, 1); handler.apply(this, args); } } else if (isObject(handler)) { args = Array.prototype.slice.call(arguments, 1); listeners = handler.slice(); len = listeners.length; for (i = 0; i < len; i++) listeners[i].apply(this, args); } return true; }; EventEmitter.prototype.addListener = function(type, listener) { var m; if (!isFunction(listener)) throw TypeError('listener must be a function'); if (!this._events) this._events = {}; // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (this._events.newListener) this.emit('newListener', type, isFunction(listener.listener) ? listener.listener : listener); if (!this._events[type]) // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; else if (isObject(this._events[type])) // If we've already got an array, just append. this._events[type].push(listener); else // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; // Check for listener leak if (isObject(this._events[type]) && !this._events[type].warned) { if (!isUndefined(this._maxListeners)) { m = this._maxListeners; } else { m = EventEmitter.defaultMaxListeners; } if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); if (typeof console.trace === 'function') { // not supported in IE 10 console.trace(); } } } return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener) { if (!isFunction(listener)) throw TypeError('listener must be a function'); var fired = false; function g() { this.removeListener(type, g); if (!fired) { fired = true; listener.apply(this, arguments); } } g.listener = listener; this.on(type, g); return this; }; // emits a 'removeListener' event iff the listener was removed EventEmitter.prototype.removeListener = function(type, listener) { var list, position, length, i; if (!isFunction(listener)) throw TypeError('listener must be a function'); if (!this._events || !this._events[type]) return this; list = this._events[type]; length = list.length; position = -1; if (list === listener || (isFunction(list.listener) && list.listener === listener)) { delete this._events[type]; if (this._events.removeListener) this.emit('removeListener', type, listener); } else if (isObject(list)) { for (i = length; i-- > 0;) { if (list[i] === listener || (list[i].listener && list[i].listener === listener)) { position = i; break; } } if (position < 0) return this; if (list.length === 1) { list.length = 0; delete this._events[type]; } else { list.splice(position, 1); } if (this._events.removeListener) this.emit('removeListener', type, listener); } return this; }; EventEmitter.prototype.removeAllListeners = function(type) { var key, listeners; if (!this._events) return this; // not listening for removeListener, no need to emit if (!this._events.removeListener) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) delete this._events[type]; return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { for (key in this._events) { if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = {}; return this; } listeners = this._events[type]; if (isFunction(listeners)) { this.removeListener(type, listeners); } else if (listeners) { // LIFO order while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); } delete this._events[type]; return this; }; EventEmitter.prototype.listeners = function(type) { var ret; if (!this._events || !this._events[type]) ret = []; else if (isFunction(this._events[type])) ret = [this._events[type]]; else ret = this._events[type].slice(); return ret; }; EventEmitter.prototype.listenerCount = function(type) { if (this._events) { var evlistener = this._events[type]; if (isFunction(evlistener)) return 1; else if (evlistener) return evlistener.length; } return 0; }; EventEmitter.listenerCount = function(emitter, type) { return emitter.listenerCount(type); }; function isFunction(arg) { return typeof arg === 'function'; } function isNumber(arg) { return typeof arg === 'number'; } function isObject(arg) { return typeof arg === 'object' && arg !== null; } function isUndefined(arg) { return arg === void 0; } },{}],4:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it // don't break things. But we need to wrap it in a try catch in case it is // wrapped in strict mode code which doesn't define any globals. It's inside a // function because try/catches deoptimize in certain engines. var cachedSetTimeout; var cachedClearTimeout; function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout () { throw new Error('clearTimeout has not been defined'); } (function () { try { if (typeof setTimeout === 'function') { cachedSetTimeout = setTimeout; } else { cachedSetTimeout = defaultSetTimout; } } catch (e) { cachedSetTimeout = defaultSetTimout; } try { if (typeof clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } else { cachedClearTimeout = defaultClearTimeout; } } catch (e) { cachedClearTimeout = defaultClearTimeout; } } ()) function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations return setTimeout(fun, 0); } // if setTimeout wasn't available but was latter defined if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedSetTimeout(fun, 0); } catch(e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedSetTimeout.call(null, fun, 0); } catch(e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { //normal enviroments in sane situations return clearTimeout(marker); } // if clearTimeout wasn't available but was latter defined if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedClearTimeout(marker); } catch (e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedClearTimeout.call(null, marker); } catch (e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. // Some versions of I.E. have different rules for clearTimeout vs setTimeout return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } }; // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.prependListener = noop; process.prependOnceListener = noop; process.listeners = function (name) { return [] } process.binding = function (name) { throw new Error('process.binding is not supported'); }; process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; },{}],5:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; } else { // old school shim for old browsers module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor var TempCtor = function () {} TempCtor.prototype = superCtor.prototype ctor.prototype = new TempCtor() ctor.prototype.constructor = ctor } } },{}],6:[function(require,module,exports){ module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } },{}],7:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. var formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (!isString(f)) { var objects = []; for (var i = 0; i < arguments.length; i++) { objects.push(inspect(arguments[i])); } return objects.join(' '); } var i = 1; var args = arguments; var len = args.length; var str = String(f).replace(formatRegExp, function(x) { if (x === '%%') return '%'; if (i >= len) return x; switch (x) { case '%s': return String(args[i++]); case '%d': return Number(args[i++]); case '%j': try { return JSON.stringify(args[i++]); } catch (_) { return '[Circular]'; } default: return x; } }); for (var x = args[i]; i < len; x = args[++i]) { if (isNull(x) || !isObject(x)) { str += ' ' + x; } else { str += ' ' + inspect(x); } } return str; }; // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. exports.deprecate = function(fn, msg) { // Allow for deprecating things in the process of starting up. if (isUndefined(global.process)) { return function() { return exports.deprecate(fn, msg).apply(this, arguments); }; } if (process.noDeprecation === true) { return fn; } var warned = false; function deprecated() { if (!warned) { if (process.throwDeprecation) { throw new Error(msg); } else if (process.traceDeprecation) { console.trace(msg); } else { console.error(msg); } warned = true; } return fn.apply(this, arguments); } return deprecated; }; var debugs = {}; var debugEnviron; exports.debuglog = function(set) { if (isUndefined(debugEnviron)) debugEnviron = process.env.NODE_DEBUG || ''; set = set.toUpperCase(); if (!debugs[set]) { if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { var pid = process.pid; debugs[set] = function() { var msg = exports.format.apply(exports, arguments); console.error('%s %d: %s', set, pid, msg); }; } else { debugs[set] = function() {}; } } return debugs[set]; }; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Object} opts Optional options object that alters the output. */ /* legacy: obj, showHidden, depth, colors*/ function inspect(obj, opts) { // default options var ctx = { seen: [], stylize: stylizeNoColor }; // legacy... if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if (isBoolean(opts)) { // legacy... ctx.showHidden = opts; } else if (opts) { // got an "options" object exports._extend(ctx, opts); } // set default options if (isUndefined(ctx.showHidden)) ctx.showHidden = false; if (isUndefined(ctx.depth)) ctx.depth = 2; if (isUndefined(ctx.colors)) ctx.colors = false; if (isUndefined(ctx.customInspect)) ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } exports.inspect = inspect; // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics inspect.colors = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; // Don't use 'blue' not visible on cmd.exe inspect.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }; function stylizeWithColor(str, styleType) { var style = inspect.styles[styleType]; if (style) { return '\u001b[' + inspect.colors[style][0] + 'm' + str + '\u001b[' + inspect.colors[style][1] + 'm'; } else { return str; } } function stylizeNoColor(str, styleType) { return str; } function arrayToHash(array) { var hash = {}; array.forEach(function(val, idx) { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect && value && isFunction(value.inspect) && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { var ret = value.inspect(recurseTimes, ctx); if (!isString(ret)) { ret = formatValue(ctx, ret, recurseTimes); } return ret; } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // Look up the keys of the object. var keys = Object.keys(value); var visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = Object.getOwnPropertyNames(value); } // IE doesn't make error fields non-enumerable // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx if (isError(value) && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { return formatError(value); } // Some type of object without properties can be shortcutted. if (keys.length === 0) { if (isFunction(value)) { var name = value.name ? ': ' + value.name : ''; return ctx.stylize('[Function' + name + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (isFunction(value)) { var n = value.name ? ': ' + value.name : ''; base = ' [Function' + n + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { base = ' ' + formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { if (isUndefined(value)) return ctx.stylize('undefined', 'undefined'); if (isString(value)) { var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); } if (isNumber(value)) return ctx.stylize('' + value, 'number'); if (isBoolean(value)) return ctx.stylize('' + value, 'boolean'); // For some reason typeof null is "object", so special case here. if (isNull(value)) return ctx.stylize('null', 'null'); } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str, desc; desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty(visibleKeys, key)) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(desc.value) < 0) { if (isNull(recurseTimes)) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (isUndefined(name)) { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. function isArray(ar) { return Array.isArray(ar); } exports.isArray = isArray; function isBoolean(arg) { return typeof arg === 'boolean'; } exports.isBoolean = isBoolean; function isNull(arg) { return arg === null; } exports.isNull = isNull; function isNullOrUndefined(arg) { return arg == null; } exports.isNullOrUndefined = isNullOrUndefined; function isNumber(arg) { return typeof arg === 'number'; } exports.isNumber = isNumber; function isString(arg) { return typeof arg === 'string'; } exports.isString =