src/js/libs/spiritual-edb.js
function(newnode, oldnode, ids) {
		var updates = [];
		var news = this._assistant.index(newnode.childNodes);
		var olds = this._assistant.index(oldnode.childNodes);
		/*
		 * Add elements?
		 */
		var child = newnode.lastElementChild,
			topid = this._assistant.id(oldnode),
			oldid = null,
			newid = null;
		while (child) {
			newid = this._assistant.id(child);
			if (!olds[newid]) {
				if (oldid) {
					updates.push(
						new edbml.InsertUpdate(this._doc).setup(oldid, child)
					);
				} else {
					updates.push(
						new edbml.AppendUpdate(this._doc).setup(topid, child)
					);
				}
			} else {
				oldid = newid;
			}
			child = child.previousElementSibling;
		}
		/*
		 * Remove elements?
		 */
		Object.keys(olds).forEach(function(id) {
			if (!news[id]) {
				updates.push(
					new edbml.RemoveUpdate(this._doc).setup(id)
				);
				updates.push(
					new edbml.FunctionUpdate(this._doc).setup(id)
				);
			} else { // note that crawling continues here...
				var n1 = news[id];
				var n2 = olds[id];
				this._scan(n1, n2, n1, id, ids);
			}
		}, this);
		/*
		 * Register updates
		 */
		updates.reverse().forEach(function(update) {
			this._updates.collect(update, ids);
		}, this);
	}
function(newnode, oldnode, ids) {
		var updates = [];
		var news = this._assistant.index(newnode.childNodes);
		var olds = this._assistant.index(oldnode.childNodes);
		/*
		 * Add elements?
		 */
		var child = newnode.lastElementChild,
			topid = this._assistant.id(oldnode),
			oldid = null,
			newid = null;
		while (child) {
			newid = this._assistant.id(child);
			if (!olds[newid]) {
				if (oldid) {
					updates.push(
						new edbml.InsertUpdate(this._doc).setup(oldid, child)
					);
				} else {
					updates.push(
						new edbml.AppendUpdate(this._doc).setup(topid, child)
					);
				}
			} else {
				oldid = newid;
			}
			child = child.previousElementSibling;
		}
		/*
		 * Remove elements?
		 */
		Object.keys(olds).forEach(function(id) {
			if (!news[id]) {
				updates.push(
					new edbml.RemoveUpdate(this._doc).setup(id)
				);
				updates.push(
					new edbml.FunctionUpdate(this._doc).setup(id)
				);
			} else { // note that crawling continues here...
				var n1 = news[id];
				var n2 = olds[id];
				this._scan(n1, n2, n1, id, ids);
			}
		}, this);
		/*
		 * Register updates
		 */
		updates.reverse().forEach(function(update) {
			this._updates.collect(update, ids);
		}, this);
	}
function ( newnode , oldnode , ids ) { var updates = [ ] ; var news = this . _assistant . index ( newnode . childNodes ) ; var olds = this . _assistant . index ( oldnode . childNodes ) ; /*
		 * Add elements?
		 */ var child = newnode . lastElementChild , topid = this . _assistant . id ( oldnode ) , oldid = null , newid = null ; while ( child ) { newid = this . _assistant . id ( child ) ; if ( ! olds [ newid ] ) { if ( oldid ) { updates . push ( new edbml . InsertUpdate ( this . _doc ) . setup ( oldid , child ) ) ; } else { updates . push ( new edbml . AppendUpdate ( this . _doc ) . setup ( topid , child ) ) ; } } else { oldid = newid ; } child = child . previousElementSibling ; } /*
		 * Remove elements?
		 */ Object . keys ( olds ) . forEach ( function ( id ) { if ( ! news [ id ] ) { updates . push ( new edbml . RemoveUpdate ( this . _doc ) . setup ( id ) ) ; updates . push ( new edbml . FunctionUpdate ( this . _doc ) . setup ( id ) ) ; } else { // note that crawling continues here... var n1 = news [ id ] ; var n2 = olds [ id ] ; this . _scan ( n1 , n2 , n1 , id , ids ) ; } } , this ) ; /*
		 * Register updates
		 */ updates . reverse ( ) . forEach ( function ( update ) { this . _updates . collect ( update , ids ) ; } , this ) ; }
Update "soft" siblings.
@param {Element} newnode
@param {Element} oldnode
@param {Map<String,boolean>} ids
@return {boolean}
Update soft siblings .