angular-multi-select
Version:
A multi select dropdown directive for AngularJS
962 lines (812 loc) • 55.5 kB
JavaScript
'use strict';
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var angular_multi_select_engine = angular.module('angular-multi-select-engine', ['angular-multi-select-utils', 'angular-multi-select-constants']);
angular_multi_select_engine.factory('angularMultiSelectEngine', ['angularMultiSelectUtils', 'angularMultiSelectConstants', function (angularMultiSelectUtils, angularMultiSelectConstants) {
'use strict';
/*
██████ ██████ ███ ██ ███████ ████████ ██████ ██ ██ ██████ ████████ ██████ ██████
██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ███████ ██ ██████ ██ ██ ██ ██ ██ ██ ██████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██████ ██ ████ ███████ ██ ██ ██ ██████ ██████ ██ ██████ ██ ██
*/
var Engine = function Engine(ops) {
this.amsu = new angularMultiSelectUtils();
_extends(this, this.amsu.sanitize_ops(ops));
/*
* Initiate the database and setup index fields.
*/
this.db = new loki();
this.on_data_change_fn = null;
this.on_visual_change_fn = null;
};
/*
██████ ███ ██ ██████ █████ ████████ █████ ██████ ██ ██ █████ ███ ██ ██████ ███████
██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ███████ ██ ███████ ██ ███████ ███████ ██ ██ ██ ██ ███ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ████ ██████ ██ ██ ██ ██ ██ ██████ ██ ██ ██ ██ ██ ████ ██████ ███████
*/
Engine.prototype.on_data_change = function (ops) {
/*
* Will be executed when the data in one or more of the items in the
* tree are changed. Changes such as open/close (visibility related)
* won't trigger this function.
*
* Note that this method will be ran only once after applying
* multiple data updates if there are more than one, like for example
* when checking a node that has multiple children.
*/
var default_ops = {
skip_internal: false
};
ops = ops || {};
for (var k in default_ops) {
if (!ops.hasOwnProperty(k)) {
ops[k] = default_ops[k];
}
}
if (ops.skip_internal === false) {
/*
* Handle situation where a maximum amount of checked leafs has been specified.
*/
if (this.MAX_CHECKED_LEAFS > -1 && this.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS] > this.MAX_CHECKED_LEAFS) {
this.uncheck_first(this.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS] - this.MAX_CHECKED_LEAFS);
}
}
if (typeof this.on_data_change_fn === 'function') {
this.on_data_change_fn();
}
};
/*
██████ ███ ██ ██ ██ ██ ███████ ██ ██ █████ ██ ██████ ██ ██ █████ ███ ██ ██████ ███████
██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ███████ ██ ██ ███████ ██ ██ ███████ ███████ ██ ██ ██ ██ ███ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ████ ████ ██ ███████ ██████ ██ ██ ███████ ██████ ██ ██ ██ ██ ██ ████ ██████ ███████
*/
Engine.prototype.on_visual_change = function (ops) {
/*
* Will be executed when the tree changed somehow, visually speaking.
* This function could be triggered by an open/close action for example.
* Changes such as un/checking an item won't trigger this function.
*
* Note that this method will be ran only once, after applying all the
* visual changes required by the action, like for example when closing
* a node that has multiple children.
*/
var default_ops = {
skip_internal: false
};
ops = ops || {};
for (var k in default_ops) {
if (!ops.hasOwnProperty(k)) {
ops[k] = default_ops[k];
}
}
if (ops.skip_internal === false) {
//Do something here?
}
if (typeof this.on_visual_change_fn === 'function') {
this.on_visual_change_fn();
}
};
/*
██████ ██████ ███████ █████ ████████ ███████ ██████ ██████ ██ ██ ███████ ██████ ████████ ██ ██████ ███ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
██ ██████ █████ ███████ ██ █████ ██ ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ██ ███████ ██ ██ ██ ███████ ██████ ██████ ███████ ███████ ███████ ██████ ██ ██ ██████ ██ ████
*/
Engine.prototype.create_collection = function (name) {
/*
* Create a collection in the database and create indices.
*/
if (this.DEBUG === true) console.time(this.NAME + " -> create_collection");
this.collection = this.db.addCollection(name, {
indices: [this.ID_PROPERTY, this.CHECKED_PROPERTY, angularMultiSelectConstants.INTERNAL_KEY_LEVEL, angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID, angularMultiSelectConstants.INTERNAL_KEY_TREE_VISIBILITY]
});
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> create_collection");
};
/*
██████ ███████ ███ ███ ██████ ██ ██ ███████ ██████ ██████ ██ ██ ███████ ██████ ████████ ██ ██████ ███ ██
██ ██ ██ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
██████ █████ ██ ████ ██ ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ███████ ██ ██ ██████ ████ ███████ ██████ ██████ ███████ ███████ ███████ ██████ ██ ██ ██████ ██ ████
*/
Engine.prototype.remove_collection = function (name) {
/*
* Remove a collection from the database.
*/
if (this.DEBUG === true) console.time(this.NAME + " -> remove_collection");
name = name || this.NAME;
this.db.removeCollection(name);
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> remove_collection");
};
/*
██ ███ ██ ███████ ███████ ██████ ████████
██ ████ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ███████ █████ ██████ ██
██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ████ ███████ ███████ ██ ██ ██
*/
Engine.prototype.insert = function (items) {
/*
* Iterate over an array of items and insert them.
*/
if (this.DEBUG === true) console.time(this.NAME + " -> insert");
this.remove_collection(this.NAME);
this.create_collection(this.NAME);
this.reset_stats();
items = items || [];
if (Array.isArray(items)) {
for (var i = 0; i < items.length; i++) {
this.collection.insert(items[i]);
this.update_stats(items[i]);
}
} else {
this.collection.insert(items);
this.update_stats(items);
}
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> insert");
this.on_data_change();
};
/*
██████ ███████ ████████ ███████ ████████ █████ ████████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██
██ ███ █████ ██ ███████ ██ ███████ ██ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ███████ ██ ███████ ██ ██ ██ ██ ███████
*/
Engine.prototype.get_stats = function () {
return this.stats;
};
/*
██ ██ ██████ ██████ █████ ████████ ███████ ███████ ████████ █████ ████████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██████ ██ ██ ███████ ██ █████ ███████ ██ ███████ ██ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ██████ ██ ██ ██ ███████ ███████ ██ ██ ██ ██ ███████
*/
Engine.prototype.update_stats = function (item) {
switch (item[this.CHECKED_PROPERTY]) {
case angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED:
this.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES]++;
this.stats[angularMultiSelectConstants.INTERNAL_STATS_TOTAL_NODES]++;
break;
case angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED:
this.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES]++;
this.stats[angularMultiSelectConstants.INTERNAL_STATS_TOTAL_NODES]++;
break;
case angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED:
this.stats[angularMultiSelectConstants.INTERNAL_STATS_TOTAL_NODES]++;
break;
case angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED:
this.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS]++;
this.stats[angularMultiSelectConstants.INTERNAL_STATS_TOTAL_LEAFS]++;
break;
case angularMultiSelectConstants.INTERNAL_DATA_LEAF_UNCHECKED:
this.stats[angularMultiSelectConstants.INTERNAL_STATS_TOTAL_LEAFS]++;
break;
}
};
/*
██████ ███████ ███████ ███████ ████████ ███████ ████████ █████ ████████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ █████ ███████ █████ ██ ███████ ██ ███████ ██ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ███████ ███████ ███████ ██ ███████ ██ ██ ██ ██ ███████
*/
Engine.prototype.reset_stats = function () {
var _stats;
this.stats = (_stats = {}, _defineProperty(_stats, angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS, 0), _defineProperty(_stats, angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES, 0), _defineProperty(_stats, angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES, 0), _defineProperty(_stats, angularMultiSelectConstants.INTERNAL_STATS_TOTAL_LEAFS, 0), _defineProperty(_stats, angularMultiSelectConstants.INTERNAL_STATS_TOTAL_NODES, 0), _stats);
};
/*
██████ ███████ ████████ ███████ ██ ██ ██ ██ ████████ ██████ ███████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ███ █████ ██ █████ ██ ██ ██ ██ ██ ██████ █████ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ███████ ██ ██ ██████ ███████ ███████ ██ ██ ██ ███████ ███████
*/
Engine.prototype.get_full_tree = function () {
/*
* Get the entire set of data currently inserted in Loki.
*/
if (this.DEBUG === true) console.time(this.NAME + " -> get_full_tree");
//TODO: Strip LokiJS metadata. https://github.com/techfort/LokiJS/issues/346
var tree = this.collection.chain().find({}).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, false).data();
if (this.DEBUG === true) console.time(this.NAME + " -> get_full_tree");
return tree;
};
/*
██████ ███████ ████████ ██ ██ ██ ███████ ██ ██████ ██ ███████ ████████ ██████ ███████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ███ █████ ██ ██ ██ ██ ███████ ██ ██████ ██ █████ ██ ██████ █████ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ███████ ██ ████ ██ ███████ ██ ██████ ███████ ███████ ██ ██ ██ ███████ ███████
*/
Engine.prototype.get_visible_tree = function () {
/*
* Get only the visible elements from Loki.
*/
if (this.DEBUG === true) console.time(this.NAME + " -> get_visible_tree");
//TODO: Strip LokiJS metadata. https://github.com/techfort/LokiJS/issues/346
var tree = this.collection.chain().find(_defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_TREE_VISIBILITY, angularMultiSelectConstants.INTERNAL_DATA_VISIBLE)).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, false).data();
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> get_visible_tree");
return tree;
};
/*
██████ ███████ ████████ ███████ ██ ██ ████████ ███████ ██████ ███████ ██████ ████████ ██████ ███████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ███ █████ ██ █████ ██ ██ ██ █████ ██████ █████ ██ ██ ██ ██████ █████ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ███████ ██ ██ ██ ███████ ██ ███████ ██ ██ ███████ ██████ ██ ██ ██ ███████ ███████
*/
Engine.prototype.get_filtered_tree = function (query) {
if (this.DEBUG === true) console.time(this.NAME + " -> get_filtered_tree");
var filter = [];
for (var i = 0; i < query.length; i++) {
var item = query[i];
filter.push(_defineProperty({}, item.field, {
'$contains': item.query
}));
}
//TODO: Strip LokiJS metadata. https://github.com/techfort/LokiJS/issues/346
var tree = this.collection.chain().find({
'$and': filter
}).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, false).data();
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> get_filtered_tree");
return tree;
};
/*
██████ ███████ ████████ ██████ ██ ██ ███████ ██████ ██ ██ ███████ ██████ ████████ ██████ ███████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ███ █████ ██ ██ ███████ █████ ██ █████ █████ ██ ██ ██ ██████ █████ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ███████ ██ ██████ ██ ██ ███████ ██████ ██ ██ ███████ ██████ ██ ██ ██ ███████ ███████
*/
Engine.prototype.get_checked_tree = function (filter) {
/*
* Get only the checked elements from Loki.
*/
if (this.DEBUG === true) console.time(this.NAME + " -> get_checked_tree");
var query_filter;
switch (filter) {
case angularMultiSelectConstants.FIND_LEAFS:
query_filter = [angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED];
break;
case angularMultiSelectConstants.FIND_LEAFS_MIXED_NODES:
query_filter = [angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED, angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED];
break;
case angularMultiSelectConstants.FIND_LEAFS_CHECKED_NODES:
query_filter = [angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED, angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED];
break;
case angularMultiSelectConstants.FIND_LEAFS_MIXED_CHECKED_NODES:
query_filter = [angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED, angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED, angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED];
break;
case angularMultiSelectConstants.FIND_MIXED_NODES:
query_filter = [angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED];
break;
case angularMultiSelectConstants.FIND_CHECKED_NODES:
query_filter = [angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED];
break;
case angularMultiSelectConstants.FIND_MIXED_CHECKED_NODES:
query_filter = [angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED, angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED];
break;
default:
query_filter = [angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED];
break;
}
//TODO: Strip LokiJS metadata. https://github.com/techfort/LokiJS/issues/346
var tree = this.collection.chain().find(_defineProperty({}, this.CHECKED_PROPERTY, {
'$in': query_filter
})).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, false).data();
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> get_checked_tree");
return tree;
};
/*
██████ ███████ ████████ ██ ████████ ███████ ███ ███
██ ██ ██ ██ ██ ██ ████ ████
██ ███ █████ ██ ██ ██ █████ ██ ████ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ███████ ██ ██ ██ ███████ ██ ██
*/
Engine.prototype.get_item = function (item) {
if ((typeof item === 'undefined' ? 'undefined' : _typeof(item)) !== 'object' || Object.keys(item).length === 0) return {};
var filter = [];
for (var k in item) {
filter.push(_defineProperty({}, k, item[k]));
}
var res = this.collection.find({
'$and': filter
});
if (Array.isArray(res) && res.length > 0) {
return res[0];
} else {
return {};
}
};
/*
████████ ██████ ██████ ██████ ██ ███████ ██████ ██████ ███████ ███ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
██ ██ ██ ██ ███ ██ ███ ██ █████ ██ ██ ██████ █████ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ██████ ██████ ███████ ███████ ██████ ██ ███████ ██ ████
*/
Engine.prototype.toggle_open_node = function (item) {
/*
* Toggle the open/closed state of an element.
* Note that leafs are not supposed to be toggleable.
*/
if (item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === 0) return;
if (item[this.OPEN_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_OPEN) {
this.close_node(item);
} else {
this.open_node(item);
}
this.on_visual_change();
};
/*
██████ ██████ ███████ ███ ██ ███ ██ ██████ ██████ ███████
██ ██ ██ ██ ██ ████ ██ ████ ██ ██ ██ ██ ██ ██
██ ██ ██████ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ███████ ██ ████ ██ ████ ██████ ██████ ███████
*/
Engine.prototype.open_node = function (item) {
var _this = this;
/*
* Open an item.
* First, mark the item itself as open, then find all
* the children items of that item and iterate over the
* results. For each item:
*
* If the item is a node and it's closed, we'll create
* a rule such that it will skip the next N items on the
* result. Else mark the item as visible.
*/
if (this.DEBUG === true) console.time(this.NAME + " -> open_node");
var skip = 0;
this.collection.chain().find(_defineProperty({}, this.ID_PROPERTY, item[this.ID_PROPERTY])).update(function (obj) {
obj[_this.OPEN_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_OPEN;
});
this.collection.chain().find({
'$and': [_defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID, {
'$contains': item[this.ID_PROPERTY]
}), _defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_LEVEL, {
'$gte': item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] + 1
})]
}).limit(item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] + item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_NODES]).update(function (obj) {
if (skip > 0) {
skip--;
return;
}
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] > 0 && obj[_this.OPEN_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_CLOSED) {
skip = obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] + obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_NODES];
}
obj[angularMultiSelectConstants.INTERNAL_KEY_TREE_VISIBILITY] = angularMultiSelectConstants.INTERNAL_DATA_VISIBLE;
});
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> open_node");
};
/*
██████ ██ ██████ ███████ ███████ ███ ██ ██████ ██████ ███████
██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ███████ █████ ██ ██ ██ ██ ██ ██ ██ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ███████ ██████ ███████ ███████ ██ ████ ██████ ██████ ███████
*/
Engine.prototype.close_node = function (item) {
var _this2 = this;
/*
* Close an item.
* First, mark the item itself as closed, then find all
* children and mark then as invisible.
*/
if (this.DEBUG === true) console.time(this.NAME + " -> close_node");
this.collection.chain().find(_defineProperty({}, this.ID_PROPERTY, item[this.ID_PROPERTY])).update(function (obj) {
obj[_this2.OPEN_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_CLOSED;
});
this.collection.chain().find({
'$and': [_defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID, {
'$contains': item[this.ID_PROPERTY]
}), _defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_LEVEL, {
'$gte': item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] + 1
})]
}).limit(item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] + item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_NODES]).update(function (obj) {
obj[angularMultiSelectConstants.INTERNAL_KEY_TREE_VISIBILITY] = angularMultiSelectConstants.INTERNAL_DATA_INVISIBLE;
});
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> close_node");
};
/*
██████ ██ ██ ███████ ██████ ██ ██ █████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ███████ █████ ██ █████ ███████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ██ ███████ ██████ ██ ██ ██ ██ ███████ ███████
*/
Engine.prototype.check_all = function () {
var _this3 = this;
if (this.DEBUG === true) console.time(this.NAME + " -> check_all");
this.collection.chain().find({}).update(function (obj) {
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === 0) {
obj[_this3.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED;
} else {
obj[_this3.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED;
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] = obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS];
}
});
this.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES] = 0;
this.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS] = this.stats[angularMultiSelectConstants.INTERNAL_STATS_TOTAL_LEAFS];
this.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES] = this.stats[angularMultiSelectConstants.INTERNAL_STATS_TOTAL_NODES];
if (this.DEBUG === true) console.time(this.NAME + " -> check_all");
this.on_data_change();
};
/*
██ ██ ███ ██ ██████ ██ ██ ███████ ██████ ██ ██ █████ ██ ██
██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ███████ █████ ██ █████ ███████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ████ ██████ ██ ██ ███████ ██████ ██ ██ ██ ██ ███████ ███████
*/
Engine.prototype.uncheck_all = function () {
var _this4 = this;
if (this.DEBUG === true) console.time(this.NAME + " -> uncheck_all");
this.collection.chain().find({}).update(function (obj) {
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === 0) {
obj[_this4.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_LEAF_UNCHECKED;
} else {
obj[_this4.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED;
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] = 0;
}
});
this.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS] = 0;
this.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES] = 0;
this.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES] = this.stats[angularMultiSelectConstants.INTERNAL_STATS_TOTAL_NODES];
if (this.DEBUG === true) console.time(this.NAME + " -> uncheck_all");
this.on_data_change();
};
/*
████████ ██████ ██████ ██████ ██ ███████ ██████ ██ ██ ███████ ██████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ███ ██ ███ ██ █████ ██ ███████ █████ ██ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ██████ ██████ ███████ ███████ ██████ ██ ██ ███████ ██████ ██ ██
*/
Engine.prototype.toggle_check_node = function (item, ops) {
/*
* Toggle the checked state on an item.
* Note that there are, in total, 5 different states:
*
* true: checked leaf.
* false: unchecked leaf.
* -1: all children leafs of the node are unchecked.
* 0: at least one children leaf of the node is checked.
* 1: all children leafs of the node are checked.
*
* If the node/item is (fully) checked, uncheck, else check.
*/
switch (item[this.CHECKED_PROPERTY]) {
case angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED:
case angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED:
this.uncheck_node(item, ops);
break;
case angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED:
case angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED:
case angularMultiSelectConstants.INTERNAL_DATA_LEAF_UNCHECKED:
this.check_node(item, ops);
break;
}
};
/*
██████ ██ ██ ███████ ██████ ██ ██ ███ ██ ██████ ██████ ███████ ██████ ██ ██
██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ███████ █████ ██ █████ ██ ██ ██ ██ ██ ██ ██ █████ ██████ ████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ██ ███████ ██████ ██ ██ ██ ████ ██████ ██████ ███████ ██████ ██
*/
Engine.prototype.check_node_by = function (where) {
if (this.DEBUG === true) console.time(this.NAME + " -> check_node_by");
var _where = _slicedToArray(where, 2);
var key = _where[0];
var value = _where[1];
var item = this.collection.findOne({
"$and": [_defineProperty({}, key, value), _defineProperty({}, this.CHECKED_PROPERTY, {
'$nin': [angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED, angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED]
})]
});
if (item !== null) {
this.check_node(item);
}
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> check_node_by");
};
/*
██████ ██ ██ ███████ ██████ ██ ██ ███ ██ ██████ ██████ ███████
██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██
██ ███████ █████ ██ █████ ██ ██ ██ ██ ██ ██ ██ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ██ ███████ ██████ ██ ██ ██ ████ ██████ ██████ ███████
*/
Engine.prototype.check_node = function (item, ops) {
var _this5 = this;
if (this.DEBUG === true) console.time(this.NAME + " -> check_node");
var default_ops = {
call_on_data_change: true
};
ops = ops || {};
for (var k in default_ops) {
if (!ops.hasOwnProperty(k)) {
ops[k] = default_ops[k];
}
}
/*
* Used for internal calculations.
*/
var time = new Date();
var diff_checked_children = 0;
var currently_checked_children = item[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN];
//TODO: Optimize when MAX_CHECKED_LEAFS is set?
/*
* If the item is a leaf, mark it as checked.
* If the item is a note, set it's counter of checked leafs to the number of leafs it contains.
*/
this.collection.chain().find(_defineProperty({}, this.ID_PROPERTY, item[this.ID_PROPERTY])).update(function (obj) {
if (item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === 0) {
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS]++;
obj[_this5.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED;
} else {
if (obj[_this5.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED) {
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES]--;
}
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES]++;
obj[_this5.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED;
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] = obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS];
diff_checked_children = obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] - currently_checked_children;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time.getTime();
});
/*
* If the passed item is a leaf, search all parent nodes,
* add 1 to their checked_children counter and set their
* checked state based on the checked_children counter.
*
*/
if (item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === 0) {
this.collection.chain().find(_defineProperty({}, this.ID_PROPERTY, {
'$in': item[angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID]
})).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, true).update(function (obj) {
if (obj[_this5.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED) {
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES]--;
}
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] + 1 === obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS]) {
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES]++;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN]++; // We can't overflow this as we're checking an unchecked item
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] === obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS]) {
obj[_this5.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED;
} else {
obj[_this5.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time.getTime();
});
/*
* If it's a node:
* 1. Search all children leafs and nodes and mark them as checked.
* 2. Search all parent nodes,
* add N to their checked_children counter and
* set their checked state based on the checked_children counter.
* N is the difference between the checked leafs of the nodes we're checking
* before and after the operation.
*/
} else {
this.collection.chain().find({
'$and': [_defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID, {
'$contains': item[this.ID_PROPERTY]
}), _defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_LEVEL, {
'$gte': item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] + 1
}), _defineProperty({}, this.CHECKED_PROPERTY, {
'$in': [angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED, angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED, angularMultiSelectConstants.INTERNAL_DATA_LEAF_UNCHECKED]
})]
}).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, false).update(function (obj) {
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === 0) {
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS]++;
obj[_this5.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED;
} else {
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES]++;
if (obj[_this5.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED) {
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES]--;
}
obj[_this5.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED;
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] = obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS];
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time.getTime();
});
this.collection.chain().find(_defineProperty({}, this.ID_PROPERTY, {
'$in': item[angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID]
})).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, true).update(function (obj) {
if (obj[_this5.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED) {
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES]--;
}
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] + diff_checked_children === obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS]) {
_this5.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES]++;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] += diff_checked_children;
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] === obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS]) {
obj[_this5.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED;
} else {
obj[_this5.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time.getTime();
});
}
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> check_node");
if (ops.call_on_data_change) {
this.on_data_change();
}
};
/*
██ ██ ███ ██ ██████ ██ ██ ███████ ██████ ██ ██ ███ ██ ██████ ██████ ███████
██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ███████ █████ ██ █████ ██ ██ ██ ██ ██ ██ ██ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ████ ██████ ██ ██ ███████ ██████ ██ ██ ██ ████ ██████ ██████ ███████
*/
Engine.prototype.uncheck_node = function (item, ops) {
var _this6 = this;
if (this.DEBUG === true) console.time(this.NAME + " -> uncheck_node");
var default_ops = {
call_on_data_change: true
};
ops = ops || {};
for (var k in default_ops) {
if (!ops.hasOwnProperty(k)) {
ops[k] = default_ops[k];
}
}
/*
* Used for internal calculations.
*/
var time = new Date();
var diff_checked_children = 0;
var currently_checked_children = item[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN];
/*
* If the item is a leaf, mark it as unchecked.
* If the item is a note, set it's counter of checked leafs to the number of leafs it contains.
*/
this.collection.chain().find(_defineProperty({}, this.ID_PROPERTY, item[this.ID_PROPERTY])).update(function (obj) {
if (item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === 0) {
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS]--;
obj[_this6.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_LEAF_UNCHECKED;
} else {
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES]--;
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES]++;
obj[_this6.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED;
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] = 0;
diff_checked_children = currently_checked_children - obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN];
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time.getTime();
});
/*
* If the passed item is a leaf, search all parent nodes,
* substract 1 from their checked_children counter and set their
* checked state based on the checked_children counter.
*/
if (item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === 0) {
this.collection.chain().find(_defineProperty({}, this.ID_PROPERTY, {
'$in': item[angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID]
})).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, true).update(function (obj) {
if (obj[_this6.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED) {
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES]--;
}
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] - 1 === 0) {
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES]++;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN]--; // We can't underflow this as we're unchecking a checked item
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] === 0) {
obj[_this6.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED;
} else {
obj[_this6.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time.getTime();
});
/*
* If it's a node:
* 1. Search all children leafs and nodes and mark them as unchecked.
* 2. Search all parent nodes,
* substract N from their checked_children counter and
* set their checked state based on the checked_children counter.
* N is the difference between the checked leafs of the nodes we're checking
* before and after the operation.
*/
} else {
this.collection.chain().find({
'$and': [_defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID, {
'$contains': item[this.ID_PROPERTY]
}), _defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_LEVEL, {
'$gte': item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] + 1
}), _defineProperty({}, this.CHECKED_PROPERTY, {
'$in': [angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED, angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED, angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED]
})]
}).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, false).update(function (obj) {
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === 0) {
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_LEAFS]--;
obj[_this6.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_LEAF_UNCHECKED;
} else {
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES]++;
if (obj[_this6.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED) {
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES]--;
}
obj[_this6.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED;
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] = 0;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time.getTime();
});
this.collection.chain().find(_defineProperty({}, this.ID_PROPERTY, {
'$in': item[angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID]
})).simplesort(angularMultiSelectConstants.INTERNAL_KEY_ORDER, true).update(function (obj) {
if (obj[_this6.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED) {
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_CHECKED_NODES]--;
}
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] - diff_checked_children === 0) {
_this6.stats[angularMultiSelectConstants.INTERNAL_STATS_UNCHECKED_NODES]++;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] -= diff_checked_children;
if (obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] === 0) {
obj[_this6.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED;
} else {
obj[_this6.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED;
}
obj[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time.getTime();
});
}
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> uncheck_node");
if (ops.call_on_data_change) {
this.on_data_change();
}
};
/*
██ ██ ███ ██ ██████ ██ ██ ███████ ██████ ██ ██ ███████ ██ ██████ ███████ ████████
██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ███████ █████ ██ █████ █████ ██ ██████ ███████ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ████ ██████ ██ ██ ███████ ██████ ██ ██ ██ ██ ██ ██ ███████ ██
*/
Engine.prototype.uncheck_first = function (n) {
/*
* Find the oldest n leaf that have been marked as checked and uncheck them.
* This function is used to control the maximum amount of checked leafs.
*/
if (this.DEBUG === true) console.time(this.NAME + " -> uncheck_first");
n = n || 1;
var leaf = this.collection.chain().find({
'$and': [_defineProperty({}, this.CHECKED_PROPERTY, angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED), _defineProperty({}, angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS, 0)]
})
/*
* Each element is guaranteed to have an INTERNAL_KEY_CHECKED_MODIFICATION
* field that contains a unixtime date of the last time the item has
* changed it's checked state.
* If the fields of two elements match, then sort by the order field.
* This exception should happen only when this method is called on a verbatim
* tree that hasn't been modified in any way, meaning, right after a
* call to this.insert().
*/
.sort(function (a, b) {
var diff = a[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] - b[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION];
if (diff === 0) {
return a[angularMultiSelectConstants.INTERNAL_KEY_ORDER] - b[angularMultiSelectConstants.INTERNAL_KEY_ORDER];
} else {
return diff;
}
}).limit(n).data();
for (var i = 0; i < leaf.length; i++) {
this.toggle_check_node(leaf[i], {
call_on_data_change: false
});
}
if (this.DEBUG === true) console.timeEnd(this.NAME + " -> uncheck_first");
};
return Engine;
}]);