hadron-document
Advanced tools
Comparing version 0.13.0 to 0.14.0
@@ -5,5 +5,4 @@ 'use strict'; | ||
const keys = require('lodash.keys'); | ||
const map = require('lodash.map'); | ||
const some = require('lodash.some'); | ||
const Element = require('./element'); | ||
const LinkedList = Element.LinkedList; | ||
const ObjectGenerator = require('./object-generator'); | ||
@@ -32,4 +31,3 @@ | ||
add(key, value) { | ||
var newElement = new Element(key, value, true, this); | ||
this.elements.push(newElement); | ||
var newElement = this.elements.insertEnd(key, value, true, this); | ||
this.emit(Element.Events.Added); | ||
@@ -39,2 +37,8 @@ return newElement; | ||
insertAfter(element, key, value) { | ||
var newElement = this.elements.insertAfter(element, key, value, true, this); | ||
this.emit(Element.Events.Added); | ||
return newElement; | ||
} | ||
/** | ||
@@ -83,5 +87,8 @@ * Send cancel event. | ||
isModified() { | ||
return some(this.elements, (element) => { | ||
return element.isModified(); | ||
}); | ||
for (let element of this.elements) { | ||
if (element.isModified()) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
@@ -99,2 +106,16 @@ | ||
/** | ||
* Handle the next element in the document. | ||
*/ | ||
next() { | ||
var lastElement = this.elements.lastElement; | ||
if (lastElement && lastElement.isAdded()) { | ||
if (lastElement.currentKey === '' && lastElement.currentValue === '') { | ||
lastElement.remove(); | ||
} | ||
} else { | ||
this.add('', ''); | ||
} | ||
} | ||
/** | ||
* Generates a sequence of elements. | ||
@@ -105,5 +126,7 @@ * | ||
_generateElements() { | ||
return map(keys(this.doc), (key) => { | ||
return new Element(key, this.doc[key], this.cloned, this); | ||
}); | ||
var elements = new LinkedList(); | ||
for (let key of keys(this.doc)) { | ||
elements.insertEnd(key, this.doc[key], this.cloned, this); | ||
} | ||
return elements; | ||
} | ||
@@ -110,0 +133,0 @@ } |
@@ -5,9 +5,6 @@ 'use strict'; | ||
const keys = require('lodash.keys'); | ||
const map = require('lodash.map'); | ||
const isObject = require('lodash.isplainobject'); | ||
const isArray = require('lodash.isarray'); | ||
const some = require('lodash.some'); | ||
const removeValues = require('lodash.remove'); | ||
const includes = require('lodash.includes'); | ||
const indexOf = require('lodash.indexof'); | ||
const Iterator = require('./iterator'); | ||
const ObjectGenerator = require('./object-generator'); | ||
@@ -44,4 +41,10 @@ const TypeChecker = require('hadron-type-checker'); | ||
/** | ||
* Curly brace constant. | ||
*/ | ||
const CURLY = '{'; | ||
/** | ||
* Bracket constant. | ||
*/ | ||
const BRACKET = '['; | ||
@@ -63,4 +66,3 @@ | ||
add(key, value) { | ||
var newElement = new Element(key, value, true, this); | ||
this.elements.push(newElement); | ||
var newElement = this.elements.insertEnd(key, value, true, this); | ||
this._bubbleUp(Events.Added); | ||
@@ -70,9 +72,6 @@ return newElement; | ||
/** | ||
* Get the absolute key, ie (contact.emails.work) for the element. | ||
* | ||
* @returns {String} The absolute path. | ||
*/ | ||
get absolutePath() { | ||
return !this.parentElement.isRoot() ? `${this.parentElement.absolutePath}.${this.key}` : this.key; | ||
insertAfter(element, key, value) { | ||
var newElement = this.elements.insertAfter(element, key, value, true, this); | ||
this._bubbleUp(Events.Added); | ||
return newElement; | ||
} | ||
@@ -86,5 +85,7 @@ | ||
* @param {Boolean} added - Is the element a new 'addition'? | ||
* @param {Element} parentElement - The parent element. | ||
* @param {Element} parent - The parent element. | ||
* @param {Element} previousElement - The previous element in the list. | ||
* @param {Element} nextElement - The next element in the list. | ||
*/ | ||
constructor(key, value, added, parentElement) { | ||
constructor(key, value, added, parent, previousElement, nextElement) { | ||
super(); | ||
@@ -94,3 +95,5 @@ this.uuid = uuid.v4(); | ||
this.currentKey = key; | ||
this.parentElement = parentElement; | ||
this.parent = parent; | ||
this.previousElement = previousElement; | ||
this.nextElement = nextElement; | ||
this.added = added; | ||
@@ -136,3 +139,3 @@ this.removed = false; | ||
} | ||
return this._addToParent(); | ||
return this._next(); | ||
} | ||
@@ -171,3 +174,3 @@ | ||
isAdded() { | ||
return this.added || (this.parentElement && this.parentElement.isAdded()); | ||
return this.added || (this.parent && this.parent.isAdded()); | ||
} | ||
@@ -186,5 +189,8 @@ | ||
} | ||
return some(this.parentElement.elements, (element) => { | ||
return element.currentKey === value; | ||
}); | ||
for (let element of this.parent.elements) { | ||
if (element.currentKey === value) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
@@ -209,4 +215,3 @@ | ||
isLast() { | ||
return indexOf(this.parentElement.elements, this) === | ||
(this.parentElement.elements.length - 1); | ||
return this.parent.elements.lastElement === this; | ||
} | ||
@@ -239,5 +244,7 @@ | ||
if (this.elements) { | ||
return some(this.elements, (element) => { | ||
return element.isModified(); | ||
}); | ||
for (let element of this.elements) { | ||
if (element.isModified()) { | ||
return true; | ||
} | ||
} | ||
} | ||
@@ -279,7 +286,5 @@ return this.isAdded() || this.isEdited() || this.isRemoved(); | ||
if (this.isAdded()) { | ||
removeValues(this.parentElement.elements, (element) => { | ||
return element === this; | ||
}); | ||
this.parentElement.emit(Events.Removed); | ||
this.parentElement = null; | ||
this.parent.elements.remove(this); | ||
this.parent.emit(Events.Removed); | ||
this.parent = null; | ||
} else { | ||
@@ -318,14 +323,27 @@ if (this.currentValue === null && this.value !== null) { | ||
_generateElements(object) { | ||
return map(keys(object), (key) => { | ||
return new Element(key, object[key], this.added, this); | ||
}); | ||
var elements = new LinkedList(); // eslint-disable-line no-use-before-define | ||
for (let key of keys(object)) { | ||
elements.insertEnd(this._key(key), object[key], this.added, this); | ||
} | ||
return elements; | ||
} | ||
/** | ||
* Get the key for the element. | ||
*/ | ||
_key(key) { | ||
return this.currentType === 'Array' ? '' : key; | ||
} | ||
/** | ||
* Removes the added elements from the element. | ||
*/ | ||
_removeAddedElements() { | ||
removeValues(this.elements, (element) => { | ||
return element.isAdded(); | ||
}); | ||
if (this.elements) { | ||
for (let element of this.elements) { | ||
if (element.isAdded()) { | ||
this.elements.remove(element); | ||
} | ||
} | ||
} | ||
} | ||
@@ -340,3 +358,3 @@ | ||
this.emit(evt); | ||
var element = this.parentElement; | ||
var element = this.parent; | ||
if (element) { | ||
@@ -364,3 +382,3 @@ if (element.isRoot()) { | ||
this.edit([]); | ||
this.add('0', ''); | ||
this.add('', ''); | ||
} | ||
@@ -371,15 +389,169 @@ | ||
*/ | ||
_addToParent() { | ||
if (this.isLast()) { | ||
if (this.parentElement.currentType === 'Array') { | ||
var length = this.parentElement.elements.length; | ||
this.parentElement.add(String(length), ''); | ||
} else { | ||
this.parentElement.add('', ''); | ||
_next() { | ||
if (this._isElementEmpty(this.nextElement)) { | ||
this.parent.elements.remove(this.nextElement); | ||
this.parent.emit(Events.Removed); | ||
} else if (this._isElementEmpty(this)) { | ||
this.parent.elements.remove(this); | ||
this.parent.emit(Events.Removed); | ||
} else { | ||
this.parent.insertAfter(this, '', ''); | ||
} | ||
} | ||
_isElementEmpty(element) { | ||
return element && element.isAdded() && element.currentKey === '' && element.currentValue === ''; | ||
} | ||
} | ||
/** | ||
* Represents a doubly linked list. | ||
*/ | ||
class LinkedList { | ||
/** | ||
* Get the element at the provided index. | ||
* | ||
* @param {Integer} index - The index. | ||
* | ||
* @returns {Element} The matching element. | ||
*/ | ||
at(index) { | ||
var element = this.firstElement; | ||
for (var i = 0; i < index; i++) { | ||
if (!element) { | ||
return null; | ||
} | ||
element = element.nextElement; | ||
} | ||
return element; | ||
} | ||
/** | ||
* Instantiate the new doubly linked list. | ||
*/ | ||
constructor() { | ||
this.firstElement = null; | ||
this.lastElement = null; | ||
this.size = 0; | ||
} | ||
/** | ||
* Insert data after the provided element. | ||
* | ||
* @param {Element} element - The element to insert after. | ||
* @param {String} key - The element key. | ||
* @param {Object} value - The element value. | ||
* @param {Boolean} added - If the element is new. | ||
* @param {Element,Document} parent - The parent. | ||
* | ||
* @returns {Element} The inserted element. | ||
*/ | ||
insertAfter(element, key, value, added, parent) { | ||
var newElement = new Element(key, value, added, parent, element, element.nextElement); | ||
if (element.nextElement) { | ||
element.nextElement.previousElement = newElement; | ||
} else { | ||
this.lastElement = newElement; | ||
} | ||
element.nextElement = newElement; | ||
this.size += 1; | ||
return newElement; | ||
} | ||
/** | ||
* Insert data before the provided element. | ||
* | ||
* @param {Element} element - The element to insert before. | ||
* @param {String} key - The element key. | ||
* @param {Object} value - The element value. | ||
* @param {Boolean} added - If the element is new. | ||
* @param {Element,Document} parent - The parent. | ||
* | ||
* @returns {Element} The inserted element. | ||
*/ | ||
insertBefore(element, key, value, added, parent) { | ||
var newElement = new Element(key, value, added, parent, element.previousElement, element); | ||
if (element.previousElement) { | ||
element.previousElement.nextElement = newElement; | ||
} else { | ||
this.firstElement = newElement; | ||
} | ||
element.previousElement = newElement; | ||
this.size += 1; | ||
return newElement; | ||
} | ||
/** | ||
* Insert data at the beginning of the list. | ||
* | ||
* @param {String} key - The element key. | ||
* @param {Object} value - The element value. | ||
* @param {Boolean} added - If the element is new. | ||
* @param {Element,Document} parent - The parent. | ||
* | ||
* @returns {Element} The data element. | ||
*/ | ||
insertBeginning(key, value, added, parent) { | ||
if (!this.firstElement) { | ||
var element = new Element(key, value, added, parent, null, null); | ||
this.firstElement = this.lastElement = element; | ||
this.size += 1; | ||
return element; | ||
} | ||
return this.insertBefore(this.firstElement, key, value, added, parent); | ||
} | ||
/** | ||
* Insert data at the end of the list. | ||
* | ||
* @param {String} key - The element key. | ||
* @param {Object} value - The element value. | ||
* @param {Boolean} added - If the element is new. | ||
* @param {Element,Document} parent - The parent. | ||
* | ||
* @returns {Element} The data element. | ||
*/ | ||
insertEnd(key, value, added, parent) { | ||
if (!this.lastElement) { | ||
return this.insertBeginning(key, value, added, parent); | ||
} | ||
return this.insertAfter(this.lastElement, key, value, added, parent); | ||
} | ||
/** | ||
* Get an iterator for the list. | ||
* | ||
* @returns {Iterator} The iterator. | ||
*/ | ||
[Symbol.iterator]() { | ||
return new Iterator(this.firstElement); | ||
} | ||
/** | ||
* Remove the element from the list. | ||
* | ||
* @param {Element} element - The element to remove. | ||
* | ||
* @returns {DoublyLinkedList} The list with the element removed. | ||
*/ | ||
remove(element) { | ||
if (element.previousElement) { | ||
element.previousElement.nextElement = element.nextElement; | ||
} else { | ||
this.firstElement = element.nextElement; | ||
} | ||
if (element.nextElement) { | ||
element.nextElement.previousElement = element.previousElement; | ||
} else { | ||
this.lastElement = element.previousElement; | ||
} | ||
element.nextElement = element.previousElement = null; | ||
this.size -= 1; | ||
return this; | ||
} | ||
} | ||
module.exports = Element; | ||
module.exports.LinkedList = LinkedList; | ||
module.exports.Events = Events; |
'use strict'; | ||
const each = require('lodash.foreach'); | ||
const map = require('lodash.map'); | ||
const compact = require('lodash.compact'); | ||
/** | ||
@@ -21,7 +17,7 @@ * Generates javascript objects from elements. | ||
var object = {}; | ||
each(elements, (element) => { | ||
for (let element of elements) { | ||
if (!element.isRemoved()) { | ||
object[element.currentKey] = element.generateObject(); | ||
} | ||
}); | ||
} | ||
return object; | ||
@@ -38,11 +34,13 @@ } | ||
generateArray(elements) { | ||
return compact(map(elements, (element) => { | ||
if (element.isRemoved()) { | ||
return null; | ||
var array = []; | ||
for (let element of elements) { | ||
if (!element.isRemoved()) { | ||
if (element.elements) { | ||
array.push(element.generateObject()); | ||
} else { | ||
array.push(element.currentValue); | ||
} | ||
} | ||
if (element.elements) { | ||
return element.generateObject(); | ||
} | ||
return element.currentValue; | ||
})); | ||
} | ||
return array; | ||
} | ||
@@ -49,0 +47,0 @@ } |
@@ -7,3 +7,3 @@ { | ||
"homepage": "https://github.com/mongodb-js/hadron-document", | ||
"version": "0.13.0", | ||
"version": "0.14.0", | ||
"repository": { | ||
@@ -29,12 +29,7 @@ "type": "git", | ||
"hadron-type-checker": "^0.1.0", | ||
"lodash.compact": "^3.0.1", | ||
"lodash.foreach": "^4.3.0", | ||
"lodash.includes": "^4.1.3", | ||
"lodash.indexof": "^4.0.3", | ||
"lodash.isarray": "^4.0.0", | ||
"lodash.isplainobject": "^4.0.4", | ||
"lodash.keys": "^4.0.7", | ||
"lodash.map": "^4.4.0", | ||
"lodash.remove": "^4.5.0", | ||
"lodash.some": "^4.4.0", | ||
"node-uuid": "^1.4.7" | ||
@@ -41,0 +36,0 @@ }, |
29810
8
11
686
- Removedlodash.compact@^3.0.1
- Removedlodash.indexof@^4.0.3
- Removedlodash.map@^4.4.0
- Removedlodash.remove@^4.5.0
- Removedlodash.some@^4.4.0
- Removedlodash.compact@3.0.1(transitive)
- Removedlodash.indexof@4.0.5(transitive)
- Removedlodash.map@4.6.0(transitive)
- Removedlodash.remove@4.7.0(transitive)
- Removedlodash.some@4.6.0(transitive)