data-joint
Version:
Perform data joins with any type of JS objects
452 lines (439 loc) • 16 kB
JavaScript
// Version 1.3.3 data-joint - https://github.com/vasturiano/data-joint
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.dataJoint = factory());
})(this, (function () { 'use strict';
function _arrayLikeToArray$1(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles$1(r) {
if (Array.isArray(r)) return r;
}
function _arrayWithoutHoles$1(r) {
if (Array.isArray(r)) return _arrayLikeToArray$1(r);
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey$1(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
function _iterableToArray$1(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _iterableToArrayLimit$1(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = !0,
o = !1;
try {
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = !0, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest$1() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableSpread$1() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})), t.push.apply(t, o);
}
return t;
}
function _objectSpread2(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
_defineProperty(e, r, t[r]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
});
}
return e;
}
function _objectWithoutProperties$1(e, t) {
if (null == e) return {};
var o,
r,
i = _objectWithoutPropertiesLoose$1(e, t);
if (Object.getOwnPropertySymbols) {
var s = Object.getOwnPropertySymbols(e);
for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
}
return i;
}
function _objectWithoutPropertiesLoose$1(r, e) {
if (null == r) return {};
var t = {};
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
if (e.includes(n)) continue;
t[n] = r[n];
}
return t;
}
function _slicedToArray$1(r, e) {
return _arrayWithHoles$1(r) || _iterableToArrayLimit$1(r, e) || _unsupportedIterableToArray$1(r, e) || _nonIterableRest$1();
}
function _toConsumableArray$1(r) {
return _arrayWithoutHoles$1(r) || _iterableToArray$1(r) || _unsupportedIterableToArray$1(r) || _nonIterableSpread$1();
}
function _toPrimitive$1(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _toPropertyKey$1(t) {
var i = _toPrimitive$1(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _unsupportedIterableToArray$1(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray$1(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$1(r, a) : void 0;
}
}
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles(r) {
if (Array.isArray(r)) return r;
}
function _arrayWithoutHoles(r) {
if (Array.isArray(r)) return _arrayLikeToArray(r);
}
function _iterableToArray(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _iterableToArrayLimit(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = !0,
o = !1;
try {
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = !0, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _objectWithoutProperties(e, t) {
if (null == e) return {};
var o,
r,
i = _objectWithoutPropertiesLoose(e, t);
if (Object.getOwnPropertySymbols) {
var s = Object.getOwnPropertySymbols(e);
for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
}
return i;
}
function _objectWithoutPropertiesLoose(r, e) {
if (null == r) return {};
var t = {};
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
if (e.includes(n)) continue;
t[n] = r[n];
}
return t;
}
function _slicedToArray(r, e) {
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r );
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (String )(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
var index = (function () {
var list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var keyAccessors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var multiItem = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
var flattenKeys = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
var keys = (keyAccessors instanceof Array ? keyAccessors.length ? keyAccessors : [undefined] : [keyAccessors]).map(function (key) {
return {
keyAccessor: key,
isProp: !(key instanceof Function)
};
});
var indexedResult = list.reduce(function (res, item) {
var iterObj = res;
var itemVal = item;
keys.forEach(function (_ref, idx) {
var keyAccessor = _ref.keyAccessor,
isProp = _ref.isProp;
var key;
if (isProp) {
var _itemVal = itemVal,
propVal = _itemVal[keyAccessor],
rest = _objectWithoutProperties(_itemVal, [keyAccessor].map(_toPropertyKey));
key = propVal;
itemVal = rest;
} else {
key = keyAccessor(itemVal, idx);
}
if (idx + 1 < keys.length) {
if (!iterObj.hasOwnProperty(key)) {
iterObj[key] = {};
}
iterObj = iterObj[key];
} else {
// Leaf key
if (multiItem) {
if (!iterObj.hasOwnProperty(key)) {
iterObj[key] = [];
}
iterObj[key].push(itemVal);
} else {
iterObj[key] = itemVal;
}
}
});
return res;
}, {});
if (multiItem instanceof Function) {
// Reduce leaf multiple values
(function reduce(node) {
var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
if (level === keys.length) {
Object.keys(node).forEach(function (k) {
return node[k] = multiItem(node[k]);
});
} else {
Object.values(node).forEach(function (child) {
return reduce(child, level + 1);
});
}
})(indexedResult); // IIFE
}
var result = indexedResult;
if (flattenKeys) {
// flatten into array
result = [];
(function flatten(node) {
var accKeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
if (accKeys.length === keys.length) {
result.push({
keys: accKeys,
vals: node
});
} else {
Object.entries(node).forEach(function (_ref2) {
var _ref3 = _slicedToArray(_ref2, 2),
key = _ref3[0],
val = _ref3[1];
return flatten(val, [].concat(_toConsumableArray(accKeys), [key]));
});
}
})(indexedResult); //IIFE
if (keyAccessors instanceof Array && keyAccessors.length === 0 && result.length === 1) {
// clear keys if there's no key accessors (single result)
result[0].keys = [];
}
}
return result;
});
var _excluded = ["createObj", "updateObj", "exitObj", "objBindAttr", "dataBindAttr"];
function diffArrays(prev, next, idAccessor) {
var result = {
enter: [],
update: [],
exit: []
};
if (!idAccessor) {
// use object references for comparison
var prevSet = new Set(prev);
var nextSet = new Set(next);
new Set([].concat(_toConsumableArray$1(prevSet), _toConsumableArray$1(nextSet))).forEach(function (item) {
var type = !prevSet.has(item) ? 'enter' : !nextSet.has(item) ? 'exit' : 'update';
result[type].push(type === 'update' ? [item, item] : item);
});
} else {
// compare by id (duplicate keys are ignored)
var prevById = index(prev, idAccessor, false);
var nextById = index(next, idAccessor, false);
var byId = Object.assign({}, prevById, nextById);
Object.entries(byId).forEach(function (_ref) {
var _ref2 = _slicedToArray$1(_ref, 2),
id = _ref2[0],
item = _ref2[1];
var type = !prevById.hasOwnProperty(id) ? 'enter' : !nextById.hasOwnProperty(id) ? 'exit' : 'update';
result[type].push(type === 'update' ? [prevById[id], nextById[id]] : item);
});
}
return result;
}
function dataBindDiff(data, existingObjs, _ref3) {
var _ref3$objBindAttr = _ref3.objBindAttr,
objBindAttr = _ref3$objBindAttr === void 0 ? '__obj' : _ref3$objBindAttr,
_ref3$dataBindAttr = _ref3.dataBindAttr,
dataBindAttr = _ref3$dataBindAttr === void 0 ? '__data' : _ref3$dataBindAttr,
idAccessor = _ref3.idAccessor,
_ref3$purge = _ref3.purge,
purge = _ref3$purge === void 0 ? false : _ref3$purge;
var isObjValid = function isObjValid(obj) {
return obj.hasOwnProperty(dataBindAttr);
};
var removeObjs = existingObjs.filter(function (obj) {
return !isObjValid(obj);
});
var prevD = existingObjs.filter(isObjValid).map(function (obj) {
return obj[dataBindAttr];
});
var nextD = data;
var diff = purge ? {
enter: nextD,
exit: prevD,
update: []
} // don't diff data in purge mode
: diffArrays(prevD, nextD, idAccessor);
diff.update = diff.update.map(function (_ref4) {
var _ref5 = _slicedToArray$1(_ref4, 2),
prevD = _ref5[0],
nextD = _ref5[1];
if (prevD !== nextD) {
// transfer obj to new data point (if different)
nextD[objBindAttr] = prevD[objBindAttr];
nextD[objBindAttr][dataBindAttr] = nextD;
}
return nextD;
});
diff.exit = diff.exit.concat(removeObjs.map(function (obj) {
return _defineProperty({}, objBindAttr, obj);
}));
return diff;
}
function viewDigest(data, existingObjs,
// list
appendObj,
// item => {...} function
removeObj, // item => {...} function
_ref7) {
var _ref7$createObj = _ref7.createObj,
createObj = _ref7$createObj === void 0 ? function (d) {
return {};
} : _ref7$createObj,
_ref7$updateObj = _ref7.updateObj,
updateObj = _ref7$updateObj === void 0 ? function (obj, d) {} : _ref7$updateObj,
_ref7$exitObj = _ref7.exitObj,
exitObj = _ref7$exitObj === void 0 ? function (obj) {} : _ref7$exitObj,
_ref7$objBindAttr = _ref7.objBindAttr,
objBindAttr = _ref7$objBindAttr === void 0 ? '__obj' : _ref7$objBindAttr,
_ref7$dataBindAttr = _ref7.dataBindAttr,
dataBindAttr = _ref7$dataBindAttr === void 0 ? '__data' : _ref7$dataBindAttr,
dataDiffOptions = _objectWithoutProperties$1(_ref7, _excluded);
var _dataBindDiff = dataBindDiff(data, existingObjs, _objectSpread2({
objBindAttr: objBindAttr,
dataBindAttr: dataBindAttr
}, dataDiffOptions)),
enter = _dataBindDiff.enter,
update = _dataBindDiff.update,
exit = _dataBindDiff.exit;
// Remove exiting points
exit.forEach(function (d) {
var obj = d[objBindAttr];
delete d[objBindAttr]; // unbind obj
exitObj(obj);
removeObj(obj);
});
var newObjs = createObjs(enter);
var pointsData = [].concat(_toConsumableArray$1(enter), _toConsumableArray$1(update));
updateObjs(pointsData);
// Add new points
newObjs.forEach(appendObj);
//
function createObjs(data) {
var newObjs = [];
data.forEach(function (d) {
var obj = createObj(d);
if (obj) {
obj[dataBindAttr] = d;
d[objBindAttr] = obj;
newObjs.push(obj);
}
});
return newObjs;
}
function updateObjs(data) {
data.forEach(function (d) {
var obj = d[objBindAttr];
if (obj) {
obj[dataBindAttr] = d;
updateObj(obj, d);
}
});
}
}
return viewDigest;
}));
//# sourceMappingURL=data-joint.js.map