UNPKG

angular-multi-select

Version:
1,132 lines (959 loc) 158 kB
"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<div class=\"ams-button\" ng-click=\"open = !open\">\n\t\t\t<div class=\"ams-button-text\" ng-bind-html=\"amssh.create_dropdown_label(stats, outputModelNotFormatted, self.output_type)\"></div>\n\t\t\t<div class=\"ams-caret\"></div>\n\t\t</div>\n\n\t\t<div class=\"ams-container ng-cloak\" ng-show=\"open\">\n\n\t\t\t<div class=\"ams-helpers\">\n\t\t\t\t<div class=\"selects\">\n\t\t\t\t\t<button class=\"all ams-btn\" type=\"button\" accesskey=\"a\" ng-click=\"amse.check_all()\" ng-hide=\"hide_helpers.indexOf('check_all') > -1\">{{ 'CHECK_ALL' | translate }}</button>\n\t\t\t\t\t<button class=\"none ams-btn\" type=\"button\" accesskey=\"n\" ng-click=\"amse.uncheck_all()\" ng-hide=\"hide_helpers.indexOf('check_none') > -1\">{{ 'CHECK_NONE' | translate }}</button>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"resets\">\n\t\t\t\t\t<button class=\"reset ams-btn\" type=\"button\" accesskey=\"r\" ng-click=\"reset()\" ng-hide=\"hide_helpers.indexOf('reset') > -1\">{{ 'RESET' | translate }}</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"ams-search\" ng-show=\"search_field !== null\">\n\t\t\t\t<input class=\"ams-search-field\" type=\"text\" name=\"ams-search-field\" value=\"\" placeholder=\"{{ 'SEARCH' | translate }}\" ng-model=\"search\" autofocus>\n\t\t\t\t<div class=\"ams-spinner\" ng-show=\"search_spinner_visible\"></div>\n\t\t\t\t<button class=\"clear ams-btn\" type=\"button\" accesskey=\"c\" name=\"clear\" title=\"{{ 'CLEAR' | translate }}\" ng-click=\"search = ''\"></button>\n\t\t\t</div>\n\n\t\t\t<div class=\"ams-items\">\n\t\t\t\t<div\n\t\t\t\t\tng-repeat=\"item in items track by item[ops.ID_PROPERTY]\"\n\t\t\t\t\tclass=\"ams-item {{ amssh.get_level_class(item) }} {{ amssh.get_type_class(item) }} {{ amssh.get_open_class(item) }} {{ $index === focused_index ? 'ams-item-focused' : '' }}\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Caret -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"ams-caret {{ amssh.get_open_class(item) }}\"\n\t\t\t\t\t\tng-click=\"toggle_open_node(item)\"\n\t\t\t\t\t></div>\n\n\t\t\t\t\t<!-- Text of the element -->\n\t\t\t\t\t<div class=\"ams-item-text\" ng-bind-html=\"amssh.create_label(item)\"></div>\n\n\t\t\t\t\t<!-- Check holder -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"check {{ amssh.get_checked_class(item) }}\"\n\t\t\t\t\t\tng-click=\"toggle_check_node(item)\"\n\t\t\t\t\t>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</div>\n\n\t"], ["\n\n\t\t<div class=\"ams-button\" ng-click=\"open = !open\">\n\t\t\t<div class=\"ams-button-text\" ng-bind-html=\"amssh.create_dropdown_label(stats, outputModelNotFormatted, self.output_type)\"></div>\n\t\t\t<div class=\"ams-caret\"></div>\n\t\t</div>\n\n\t\t<div class=\"ams-container ng-cloak\" ng-show=\"open\">\n\n\t\t\t<div class=\"ams-helpers\">\n\t\t\t\t<div class=\"selects\">\n\t\t\t\t\t<button class=\"all ams-btn\" type=\"button\" accesskey=\"a\" ng-click=\"amse.check_all()\" ng-hide=\"hide_helpers.indexOf('check_all') > -1\">{{ 'CHECK_ALL' | translate }}</button>\n\t\t\t\t\t<button class=\"none ams-btn\" type=\"button\" accesskey=\"n\" ng-click=\"amse.uncheck_all()\" ng-hide=\"hide_helpers.indexOf('check_none') > -1\">{{ 'CHECK_NONE' | translate }}</button>\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"resets\">\n\t\t\t\t\t<button class=\"reset ams-btn\" type=\"button\" accesskey=\"r\" ng-click=\"reset()\" ng-hide=\"hide_helpers.indexOf('reset') > -1\">{{ 'RESET' | translate }}</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div class=\"ams-search\" ng-show=\"search_field !== null\">\n\t\t\t\t<input class=\"ams-search-field\" type=\"text\" name=\"ams-search-field\" value=\"\" placeholder=\"{{ 'SEARCH' | translate }}\" ng-model=\"search\" autofocus>\n\t\t\t\t<div class=\"ams-spinner\" ng-show=\"search_spinner_visible\"></div>\n\t\t\t\t<button class=\"clear ams-btn\" type=\"button\" accesskey=\"c\" name=\"clear\" title=\"{{ 'CLEAR' | translate }}\" ng-click=\"search = ''\"></button>\n\t\t\t</div>\n\n\t\t\t<div class=\"ams-items\">\n\t\t\t\t<div\n\t\t\t\t\tng-repeat=\"item in items track by item[ops.ID_PROPERTY]\"\n\t\t\t\t\tclass=\"ams-item {{ amssh.get_level_class(item) }} {{ amssh.get_type_class(item) }} {{ amssh.get_open_class(item) }} {{ $index === focused_index ? 'ams-item-focused' : '' }}\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Caret -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"ams-caret {{ amssh.get_open_class(item) }}\"\n\t\t\t\t\t\tng-click=\"toggle_open_node(item)\"\n\t\t\t\t\t></div>\n\n\t\t\t\t\t<!-- Text of the element -->\n\t\t\t\t\t<div class=\"ams-item-text\" ng-bind-html=\"amssh.create_label(item)\"></div>\n\n\t\t\t\t\t<!-- Check holder -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"check {{ amssh.get_checked_class(item) }}\"\n\t\t\t\t\t\tng-click=\"toggle_check_node(item)\"\n\t\t\t\t\t>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t</div>\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; } (function (e) { function f(a, c) { function b(a) { if (!this || this.constructor !== b) return new b(a);this._keys = [];this._values = [];this._itp = [];this.objectOnly = c;a && v.call(this, a); }c || w(a, "size", { get: x });a.constructor = b;b.prototype = a;return b; }function v(a) { this.add ? a.forEach(this.add, this) : a.forEach(function (a) { this.set(a[0], a[1]); }, this); }function d(a) { this.has(a) && (this._keys.splice(b, 1), this._values.splice(b, 1), this._itp.forEach(function (a) { b < a[0] && a[0]--; }));return -1 < b; }function m(a) { return this.has(a) ? this._values[b] : void 0; }function n(a, c) { if (this.objectOnly && c !== Object(c)) throw new TypeError("Invalid value used as weak collection key");if (c != c || 0 === c) for (b = a.length; b-- && !y(a[b], c);) {} else b = a.indexOf(c);return -1 < b; }function p(a) { return n.call(this, this._values, a); }function q(a) { return n.call(this, this._keys, a); }function r(a, c) { this.has(a) ? this._values[b] = c : this._values[this._keys.push(a) - 1] = c;return this; }function t(a) { this.has(a) || this._values.push(a);return this; }function h() { (this._keys || 0).length = this._values.length = 0; }function z() { return k(this._itp, this._keys); }function l() { return k(this._itp, this._values); }function A() { return k(this._itp, this._keys, this._values); }function B() { return k(this._itp, this._values, this._values); }function k(a, c, b) { var g = [0], e = !1;a.push(g);return { next: function next() { var f, d = g[0];!e && d < c.length ? (f = b ? [c[d], b[d]] : c[d], g[0]++) : (e = !0, a.splice(a.indexOf(g), 1));return { done: e, value: f }; } }; }function x() { return this._values.length; }function u(a, c) { for (var b = this.entries();;) { var d = b.next();if (d.done) break; a.call(c, d.value[1], d.value[0], this); } }var b, w = Object.defineProperty, y = function y(a, b) { return isNaN(a) ? isNaN(b) : a === b; };"undefined" == typeof WeakMap && (e.WeakMap = f({ "delete": d, clear: h, get: m, has: q, set: r }, !0));"undefined" != typeof Map && "function" === typeof new Map().values && new Map().values().next || (e.Map = f({ "delete": d, has: q, get: m, set: r, keys: z, values: l, entries: A, forEach: u, clear: h }));"undefined" != typeof Set && "function" === typeof new Set().values && new Set().values().next || (e.Set = f({ has: p, add: t, "delete": d, clear: h, keys: l, values: l, entries: B, forEach: u }));"undefined" == typeof WeakSet && (e.WeakSet = f({ "delete": d, add: t, clear: h, has: p }, !0)); })("undefined" != typeof exports && "undefined" != typeof global ? global : window); 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', /* * This gets injected while processing the stats, in the dropdown * label. This allows us to iterate over the output model when * generating the dropdown label. */ INTERNAL_KEY_OUTPUT_MODEL_HACK: '$ams_output_model_hack', INTERNAL_KEY_OUTPUT_TYPE_HACK: '$ams_output_type_hack', /* * 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_VALUES: 'values', 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 = new Set(); var ctx = this; var correct = true; var id_seed = Date.now(); 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.has(item[ctx.ID_PROPERTY])) { while (ids.has(id_seed)) { id_seed++; } item[ctx.ID_PROPERTY] = id_seed++; } ids.add(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 = _extends({}, 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); // calculate parents_id, visibility, children and checked properties var parents = []; var time_seed = Date.now(); for (i = 0; i < final_data.length; i++) { item = final_data[i]; item[angularMultiSelectConstants.INTERNAL_KEY_CHECKED_MODIFICATION] = time_seed++; // Assign all the parent node IDs parents[item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL]] = item[ctx.ID_PROPERTY]; if (item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL] !== 0) { item[angularMultiSelectConstants.INTERNAL_KEY_PARENTS_ID] = parents.slice(0, item[angularMultiSelectConstants.INTERNAL_KEY_LEVEL]); } // 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'); data = JSON.parse(JSON.stringify(data)); 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_format = function (data, format, keys) { /* * Converts the input data to the desired output. */ var res; switch (format) { case angularMultiSelectConstants.OUTPUT_DATA_TYPE_OBJECTS: res = this.to_array_of_objects(data, keys); break; case angularMultiSelectConstants.OUTPUT_DATA_TYPE_ARRAYS: res = this.to_array_of_arrays(data, keys); break; case angularMultiSelectConstants.OUTPUT_DATA_TYPE_OBJECT: res = this.to_object(data, keys); break; case angularMultiSelectConstants.OUTPUT_DATA_TYPE_ARRAY: res = this.to_array(data, keys); break; case angularMultiSelectConstants.OUTPUT_DATA_TYPE_VALUES: res = this.to_values(data, keys); break; case angularMultiSelectConstants.OUTPUT_DATA_TYPE_VALUE: res = this.to_value(data, keys); break; } return res; }; /* ████████ ██████ █████ ██████ ██████ █████ ██ ██ ██████ ███████ ██████ ██████ ██ ███████ ██████ ████████ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███████ ██████ ██████ ███████ ████ ██ ██ █████ ██ ██ ██████ ██ █████ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ██ ██████ ██████ █████ ███████ ██████ ██ ███████ */ 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_values = function (data, keys) { /* * 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 []; } if (this.DEBUG === true) console.time(this.NAME + ' -> to_values'); if (keys === undefined) { keys = []; } var ret = []; if ((typeof data === "undefined" ? "undefined" : _typeof(data)) !== 'object' || !Array.isArray(data) || keys.length === 0) { //do nothing } else { for (var i = 0; i < data.length; i++) { for (var j = 0; j < keys.length; j++) { if (!(keys[j] in data[i])) { continue; } ret.push(data[i][keys[j]]); } } } if (this.DEBUG === true) console.timeEnd(this.NAME + ' -> to_values'); 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] }); 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 =