'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; };
var _templateObject = _taggedTemplateLiteral(['\n\n\t\t
\n\n\t\t\n\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t
\n\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t
\n\n\t\t\t\t\t\n\t\t\t\t\t
\n\n\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\n\t\t
\n\n\t'], ['\n\n\t\t\n\n\t\t\n\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t
\n\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t
\n\n\t\t\t\t\t\n\t\t\t\t\t
\n\n\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\n\t\t
\n\n\t']);
function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
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_consts = angular.module('angular-multi-select-constants', []);
angular_multi_select_consts.constant("angularMultiSelectConstants", {
/*
* Default key names of the input data
*/
ID_PROPERTY: 'id',
OPEN_PROPERTY: 'open',
CHECKED_PROPERTY: 'checked',
CHILDREN_PROPERTY: 'children',
/*
* Internal data keys
*/
INTERNAL_KEY_LEVEL: '$ams_level',
INTERNAL_KEY_ORDER: '$ams_order',
INTERNAL_KEY_PARENTS_ID: '$ams_parents_id',
INTERNAL_KEY_CHILDREN_LEAFS: '$ams_children_leafs',
INTERNAL_KEY_CHILDREN_NODES: '$ams_children_nodes',
INTERNAL_KEY_CHECKED_CHILDREN: '$ams_checked_children',
INTERNAL_KEY_TREE_VISIBILITY: '$ams_tree_visibility',
INTERNAL_KEY_CHECKED_MODIFICATION: '$ams_checked_modification',
/*
* Possible values of the input/internal data
*/
INPUT_DATA_OPEN: true,
INPUT_DATA_CLOSED: false,
INTERNAL_DATA_OPEN: true,
INTERNAL_DATA_CLOSED: false,
INPUT_DATA_CHECKED: true,
INPUT_DATA_UNCHECKED: false,
INTERNAL_DATA_LEAF_CHECKED: true,
INTERNAL_DATA_LEAF_UNCHECKED: false,
INTERNAL_DATA_NODE_CHECKED: 1,
INTERNAL_DATA_NODE_MIXED: 0,
INTERNAL_DATA_NODE_UNCHECKED: -1,
INTERNAL_DATA_NODE_CHECK_UNDEFINED: null,
INTERNAL_DATA_VISIBLE: true,
INTERNAL_DATA_INVISIBLE: false,
INTERNAL_DATA_VISIBILITY_UNDEFINED: null,
INTERNAL_STATS_CHECKED_LEAFS: '$ams_stats_checked_leafs',
INTERNAL_STATS_CHECKED_NODES: '$ams_stats_checked_nodes',
INTERNAL_STATS_UNCHECKED_NODES: '$ams_stats_unchecked_nodes',
INTERNAL_STATS_TOTAL_LEAFS: '$ams_stats_total_leafs',
INTERNAL_STATS_TOTAL_NODES: '$ams_stats_total_nodes',
/*
* Possible values of the output type of data
*/
OUTPUT_DATA_TYPE_OBJECTS: 'objects',
OUTPUT_DATA_TYPE_ARRAYS: 'arrays',
OUTPUT_DATA_TYPE_OBJECT: 'object',
OUTPUT_DATA_TYPE_ARRAY: 'array',
OUTPUT_DATA_TYPE_VALUE: 'value',
/*
* CSS classes helpers
*/
CSS_OPEN: 'open',
CSS_CLOSED: 'closed',
CSS_LEAF_CHECKED: 'checked',
CSS_LEAF_UNCHECKED: 'unchecked',
CSS_NODE_MIXED: 'mixed',
CSS_NODE_CHECKED: 'checked',
CSS_NODE_UNCHECKED: 'unchecked',
CSS_LEAF: 'leaf',
CSS_NODE: 'node',
/*
* Possible values for the output data query
*/
FIND_LEAFS: 'leafs',
FIND_LEAFS_MIXED_NODES: 'leafs_mixed_nodes',
FIND_LEAFS_CHECKED_NODES: 'leafs_checked_nodes',
FIND_LEAFS_MIXED_CHECKED_NODES: 'leafs_mixed_checked_nodes',
FIND_MIXED_NODES: 'midex_nodes',
FIND_CHECKED_NODES: 'checked_nodes',
FIND_MIXED_CHECKED_NODES: 'mixed_checked_nodes'
});
var angular_multi_select_data_converter = angular.module('angular-multi-select-data-converter', ['angular-multi-select-utils', 'angular-multi-select-constants']);
angular_multi_select_data_converter.factory('angularMultiSelectDataConverter', ['angularMultiSelectUtils', 'angularMultiSelectConstants', function (angularMultiSelectUtils, angularMultiSelectConstants) {
'use strict';
/*
██████ ██████ ███ ██ ███████ ████████ ██████ ██ ██ ██████ ████████ ██████ ██████
██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ███████ ██ ██████ ██ ██ ██ ██ ██ ██ ██████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██████ ██ ████ ███████ ██ ██ ██ ██████ ██████ ██ ██████ ██ ██
*/
var DataConverter = function DataConverter(ops) {
this.amsu = new angularMultiSelectUtils();
_extends(this, this.amsu.sanitize_ops(ops));
};
/*
██████ ██ ██ ███████ ██████ ██ ██ ██████ ██████ ███████ ██████ ███████ ██████ ██ ██ ██ ███████ ██ ████████ ███████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ███████ █████ ██ █████ ██████ ██████ █████ ██████ █████ ██ ██ ██ ██ ██ ███████ ██ ██ █████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ▄▄ ██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ██ ███████ ██████ ██ ██ ██ ██ ██ ███████ ██ ██ ███████ ██████ ██████ ██ ███████ ██ ██ ███████ ███████
▀▀
*/
DataConverter.prototype.check_prerequisites = function (data) {
/*
* Takes an array of data and walks through each element object
* and checks if each object has:
*
* - a valid ID. If it doesn't, it generates one.
* - open property. If it's not 'true' (strictly compared), it
* creates one and set's it to false.
* - children property. If it's not an array or if it's empty,
* it deletes the property, else it will delete the checked
* property. Note that nodes can't have a checked property at
* this step of the process.
* - checked property. If it's not 'true' (strictly compared),
* creates one and set's it to false.
*
* Note that you can completely skip this step (thus saving some
* CPU cycles) if you are sure that all objects in your input data:
*
* - have valid and unique ID.
* - have open property, which is boolean and false for leafs
* - children properties are non-empty arrays
* - only leafs have a checked property and it's a boolean
*/
if (this.DEBUG === true) console.time(this.NAME + ' -> check_prerequisites');
if (!Array.isArray(data)) return false;
var ids = [];
var ctx = this;
var last_id = 1;
var correct = true;
function gen_id() {
while (ids.indexOf(last_id) !== -1) {
last_id++;
}
return last_id;
}
function process_items(items) {
if (correct === false) return;
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (item.constructor.toString().indexOf('Array') !== -1) {
return correct = false;
}
// Check for id field.
// If not present, assign one
if (!(ctx.ID_PROPERTY in item) || ids.indexOf(item[ctx.ID_PROPERTY]) !== -1) {
item[ctx.ID_PROPERTY] = gen_id();
}
ids.push(item[ctx.ID_PROPERTY]);
// Check for open field.
// If open field doesn't exist or is not "true", set to false
if (!(ctx.OPEN_PROPERTY in item) || item[ctx.OPEN_PROPERTY] !== angularMultiSelectConstants.INPUT_DATA_OPEN) {
item[ctx.OPEN_PROPERTY] = angularMultiSelectConstants.INPUT_DATA_CLOSED;
}
// Check for children field.
// If not an array or empty array, remove it.
if (ctx.CHILDREN_PROPERTY in item && (!Array.isArray(item[ctx.CHILDREN_PROPERTY]) || item[ctx.CHILDREN_PROPERTY].length === 0)) {
delete item[ctx.CHILDREN_PROPERTY];
}
// If children field is present, remove "checked" field.
// If checked field is present, but value is not boolean or 1,
// set to false.
if (ctx.CHILDREN_PROPERTY in item) {
delete item[ctx.CHECKED_PROPERTY];
}
if (ctx.CHECKED_PROPERTY in item && item[ctx.CHECKED_PROPERTY] !== angularMultiSelectConstants.INPUT_DATA_CHECKED) {
item[ctx.CHECKED_PROPERTY] = angularMultiSelectConstants.INPUT_DATA_UNCHECKED;
}
if (!(ctx.CHILDREN_PROPERTY in item) && !(ctx.CHECKED_PROPERTY in item)) {
item[ctx.CHECKED_PROPERTY] = angularMultiSelectConstants.INPUT_DATA_UNCHECKED;
}
if (ctx.CHILDREN_PROPERTY in item) {
process_items(item[ctx.CHILDREN_PROPERTY]);
}
}
}
process_items(data);
if (this.DEBUG === true) console.timeEnd(this.NAME + ' -> check_prerequisites');
// Return data array or false if something is wrong.
return correct ? data : correct;
};
/*
████████ ██████ ██ ███ ██ ████████ ███████ ██████ ███ ██ █████ ██
██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ █████ ██████ ██ ██ ██ ███████ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ██ ██ ████ ██ ███████ ██ ██ ██ ████ ██ ██ ███████
*/
DataConverter.prototype.to_internal = function (data) {
/*
* Takes an array of (nested) objects and flattens it, while
* also adding some internal properties required for faster
* un/check and state actions.
*
* Note that you can skip this step (thus saving some CPU cycles)
* only if you're completely sure how this method works, what and
* how it does what it does.
*/
if (this.DEBUG === true) console.time(this.NAME + ' -> to_internal');
var order = 1;
var ctx = this;
var i, j, item;
var final_data = [];
function process_items(items, level) {
for (var i = 0; i < items.length; i++) {
item = items[i];
var final_item = angular.copy(item);
delete final_item[ctx.CHECKED_PROPERTY];
delete final_item[ctx.CHILDREN_PROPERTY];
if (ctx.CHECKED_PROPERTY in item && typeof item[ctx.CHECKED_PROPERTY] === 'boolean') {
final_item[ctx.CHECKED_PROPERTY] = item[ctx.CHECKED_PROPERTY];
} else {
final_item[ctx.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECK_UNDEFINED;
}
//Assigned in order
final_item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] = level;
final_item[angularMultiSelectConstants.INTERNAL_KEY_ORDER] = order++;
//Required to be present for further calculation
final_item[angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID] = [];
final_item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] = 0;
final_item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_NODES] = 0;
final_item[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] = 0;
final_item[angularMultiSelectConstants.INTERNAL_KEY_TREE_VISIBILITY] = angularMultiSelectConstants.INTERNAL_DATA_VISIBILITY_UNDEFINED;
final_item[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = 0;
final_data.push(final_item);
if (ctx.CHILDREN_PROPERTY in item) {
process_items(item[ctx.CHILDREN_PROPERTY], level + 1);
}
}
}
process_items(data, 0);
// Create parents_id values
var time = new Date();
for (i = 0; i < final_data.length; i++) {
item = final_data[i];
item[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time.getTime();
if (item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] === 0) continue;
var parents = [];
var last_level = item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL];
for (j = i; j > 0; j--) {
var possible_parent = final_data[j];
if (possible_parent[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] >= last_level) continue;
last_level = possible_parent[angularMultiSelectConstants.INTERNAL_KEY_LEVEL];
parents.push(possible_parent[this.ID_PROPERTY]);
if (possible_parent[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] === 0) break;
}
item[angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID] = parents.reverse();
}
// calculate visibility, children and checked properties
for (i = 0; i < final_data.length; i++) {
item = final_data[i];
// If this is a root element, it should be visible
if (item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] === 0) item[angularMultiSelectConstants.INTERNAL_KEY_TREE_VISIBILITY] = angularMultiSelectConstants.INTERNAL_DATA_VISIBLE;
// we are guaranteed to have a checked property for leafs
// if the current item is a leaf, it won't have children, hence skip
if (typeof item[this.CHECKED_PROPERTY] === 'boolean') continue;
var counter_checked = 0;
var counter_unchecked = 0;
var counter_null = 0;
for (j = i + 1; j < final_data.length; j++) {
var child = final_data[j];
// Decide if children should be visible in the tree
if (item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] === child[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] - 1) {
child[angularMultiSelectConstants.INTERNAL_KEY_TREE_VISIBILITY] = item[this.OPEN_PROPERTY];
}
if (item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] >= child[angularMultiSelectConstants.INTERNAL_KEY_LEVEL]) break;
// Logic that decides the checked state of node items
if (child[this.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_LEAF_CHECKED) {
counter_checked++;
item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS]++;
} else if (child[this.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_LEAF_UNCHECKED) {
counter_unchecked++;
item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS]++;
} else if (child[this.CHECKED_PROPERTY] === angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECK_UNDEFINED) {
counter_null++;
item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_NODES]++;
}
}
// If the number of checked or unchecked elements equals to
// the number of children, then the current item should be
// either 1 or -1 (checked or unchecked). Else, it should be
// marked as 0 (mixed state).
if (item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === counter_checked) {
item[this.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_CHECKED;
} else if (item[angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS] === counter_unchecked) {
item[this.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_UNCHECKED;
} else {
item[this.CHECKED_PROPERTY] = angularMultiSelectConstants.INTERNAL_DATA_NODE_MIXED;
}
item[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN] = counter_checked;
}
if (this.DEBUG === true) console.timeEnd(this.NAME + ' -> to_internal');
return final_data;
};
/*
████████ ██████ ███████ ██ ██ ████████ ███████ ██████ ███ ██ █████ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██
██ ██ ██ █████ ███ ██ █████ ██████ ██ ██ ██ ███████ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ███████ ██ ██ ██ ███████ ██ ██ ██ ████ ██ ██ ███████
*/
DataConverter.prototype.to_external = function (data) {
/*
* This is the opposite of what 'to_internal' is supposed to do.
* This will take an array of objects, usually the output of
* get_*_tree and delete all the metadata of the engine, leaving
* only the data that the user cares about.
*/
if (!Array.isArray(data) || data.length === 0) {
return [];
}
if (this.DEBUG === true) console.time(this.NAME + ' -> to_external');
for (var i = 0; i < data.length; i++) {
//AMS engine metadata
delete data[i][angularMultiSelectConstants.INTERNAL_KEY_LEVEL];
delete data[i][angularMultiSelectConstants.INTERNAL_KEY_ORDER];
delete data[i][angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID];
delete data[i][angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_LEAFS];
delete data[i][angularMultiSelectConstants.INTERNAL_KEY_CHILDREN_NODES];
delete data[i][angularMultiSelectConstants.INTERNAL_KEY_CHECKED_CHILDREN];
delete data[i][angularMultiSelectConstants.INTERNAL_KEY_TREE_VISIBILITY];
delete data[i][angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION];
//TODO: Remove after https://github.com/techfort/LokiJS/issues/346
delete data[i].meta;
delete data[i].$loki;
}
if (this.DEBUG === true) console.timeEnd(this.NAME + ' -> to_external');
return data;
};
/*
████████ ██████ █████ ██████ ██████ █████ ██ ██ ██████ ███████ ██████ ██████ ██ ███████ ██████ ████████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ███████ ██████ ██████ ███████ ████ ██ ██ █████ ██ ██ ██████ ██ █████ ██ ██ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ██ ██████ ██████ █████ ███████ ██████ ██ ███████
*/
DataConverter.prototype.to_array_of_objects = function (data, keys) {
/*
* Takes an array of objects (the result of get_checked_tree usually)
* and returns it as is if the "keys" argument hasn't been passed or
* an array of objects, each object containing only the keys in the
* "key" argument.
*/
if (!Array.isArray(data) || data.length === 0) {
return [];
}
if (this.DEBUG === true) console.time(this.NAME + ' -> to_array_of_objects');
if (keys === undefined) {
keys = [];
}
var new_data = [];
for (var i = 0; i < data.length; i++) {
var new_obj = {};
var obj = data[i];
if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' || Array.isArray(obj)) {
continue;
}
if (keys.length === 0) {
new_data.push(obj);
} else {
for (var j = 0; j < keys.length; j++) {
if (!(keys[j] in obj)) {
continue;
}
new_obj[keys[j]] = obj[keys[j]];
}
new_data.push(new_obj);
}
}
if (this.DEBUG === true) console.timeEnd(this.NAME + ' -> to_array_of_objects');
return new_data;
};
/*
████████ ██████ █████ ██████ ██████ █████ ██ ██ ██████ ███████ █████ ██████ ██████ █████ ██ ██ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ███████ ██████ ██████ ███████ ████ ██ ██ █████ ███████ ██████ ██████ ███████ ████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███████
*/
DataConverter.prototype.to_array_of_arrays = function (data, keys) {
/*
* Takes an array of objects (the result of get_checked_tree usually)
* and returns an array of arrays. Each array inside the returned
* array contains the values of the keys that result of the
* intersection of the object's keys and the argument "keys". The
* array will contain the values in the order they have in the "key"
* argument.
*/
if (!Array.isArray(data) || data.length === 0) {
return [];
}
if (this.DEBUG === true) console.time(this.NAME + ' -> to_array_of_arrays');
if (keys === undefined) {
keys = [];
}
function vals(obj) {
return Object.keys(obj).map(function (key) {
return obj[key];
});
}
var new_data = [];
for (var i = 0; i < data.length; i++) {
var new_arr = [];
var obj = data[i];
if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' || Array.isArray(obj)) {
continue;
}
if (keys.length === 0) {
new_data.push(vals(obj));
} else {
for (var j = 0; j < keys.length; j++) {
if (!(keys[j] in obj)) {
continue;
}
new_arr.push(obj[keys[j]]);
}
new_data.push(new_arr);
}
}
if (this.DEBUG === true) console.timeEnd(this.NAME + ' -> to_array_of_arrays');
return new_data;
};
/*
████████ ██████ █████ ██████ ██████ █████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ███████ ██████ ██████ ███████ ████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██
*/
DataConverter.prototype.to_array = function (data, keys) {
/*
* Takes an array of objects (the result of get_checked_tree usually)
* and returns a single array filled with the values of all the
* objects's keys that are contained in the "keys" argument.
* This usually doesn't make much sense when more than 1 item in the
* tree is selected, but you're free to use it however you like.
*/
if (!Array.isArray(data) || data.length === 0) {
return [];
}
if (this.DEBUG === true) console.time(this.NAME + ' -> to_array');
if (keys === undefined) {
keys = [];
}
function vals(obj) {
return Object.keys(obj).map(function (key) {
return obj[key];
});
}
var j;
var obj = data[0];
var ret = [];
if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' || Array.isArray(obj)) {
//do nothing
} else {
if (keys.length === 0) {
var obj_vals = vals(obj);
for (j = 0; j < obj_vals.length; j++) {
ret.push(obj_vals[j]);
}
} else {
for (j = 0; j < keys.length; j++) {
if (!(keys[j] in obj)) {
continue;
}
ret.push(obj[keys[j]]);
}
}
}
if (this.DEBUG === true) console.timeEnd(this.NAME + ' -> to_array');
return ret;
};
/*
████████ ██████ ██████ ██████ ██ ███████ ██████ ████████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██████ ██ █████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ██████ ██████ █████ ███████ ██████ ██
*/
DataConverter.prototype.to_object = function (data, keys) {
/*
* Takes an array of objects (the result of get_checked_tree usually)
* and returns the first object.
* If the "keys" argument is passed, only the keys of the object that
* match the values in the "keys" argument will be returned.
* This usually doesn't make much sense when more than 1 item in the tree
* is selected, but you're free to use it however you like.
*/
if (!Array.isArray(data) || data.length === 0) {
return {};
}
if (this.DEBUG === true) console.time(this.NAME + ' -> to_object');
if (keys === undefined) {
keys = [];
}
var ret;
var obj = data[0];
if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' || Array.isArray(obj)) {
ret = {};
} else {
if (keys.length === 0) {
ret = obj;
} else {
var new_obj = {};
for (var i = 0; i < keys.length; i++) {
if (!(keys[i] in obj)) {
continue;
}
new_obj[keys[i]] = obj[keys[i]];
}
ret = new_obj;
}
}
if (this.DEBUG === true) console.timeEnd(this.NAME + ' -> to_object');
return ret;
};
/*
████████ ██████ ██ ██ █████ ██ ██ ██ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ███████ ██ ██ ██ █████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ████ ██ ██ ███████ ██████ ███████
*/
DataConverter.prototype.to_value = function (data, key) {
/*
* Takes an array of one object (the result of get_checked_tree usually)
* and returns the value of the key in the object that is passed as the
* "key" argument.
* If "key" hasn't been passed, the first available value in the object
* will be returned.
*/
if (!Array.isArray(data) || data.length === 0) {
return undefined;
}
if (this.DEBUG === true) console.time(this.NAME + ' -> to_value');
var ret;
var obj = data[0];
if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' || Array.isArray(obj)) {
ret = undefined;
} else {
if (key === undefined) {
var keys = Object.keys(obj);
if (keys.length === 0) {
ret = undefined;
} else {
key = keys[0];
ret = key in obj ? obj[key] : undefined;
}
} else {
key = Array.isArray(key) ? key[0] : key;
ret = key in obj ? obj[key] : undefined;
}
}
if (this.DEBUG === true) console.timeEnd(this.NAME + ' -> to_value');
return ret;
};
return DataConverter;
}]);
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],
clone: true
});
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.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;
}]);
var angular_multi_select_styles_helper = angular.module('angular-multi-select-styles-helper', ['angular-multi-select-utils', 'angular-multi-select-constants']);
angular_multi_select_styles_helper.run([function () {
'use strict';
/*
* This is used to generate some CSS styling at runtime.
* This code as ran after everything else is loaded and
* uses "document.styleSheets" to read the loaded CSS styling.
*
* * The right padding of each element is extended with as many
* pixels as the width of the check marker.
*
* * 20 levels of indent classes are generated based on the
* width of the first level.
*/
var inject = angular.element("