/
var
/
www
/
barefootlaw.org
/
bios2
/
manager
/
reports
/
src
/
Upload File
HOME
// Model CLASS // =============================== /** * Main object storing data model and emitting events * --------- * Access Node object stored in jQuery objects * @param el {jQuery|Node} * @return {Node} */ function Model(el) { if (!(this instanceof Model)) { return Model.getModel(el); } this.root = null; this.$ = $(this); } $.extend(Model.prototype, { trigger: function(type) { this.$.triggerHandler(type, Array.prototype.slice.call(arguments, 1)); return this; }, on: function() { this.$.on.apply(this.$, Array.prototype.slice.call(arguments)); return this; }, off: function() { this.$.off.apply(this.$, Array.prototype.slice.call(arguments)); return this; }, once: function() { this.$.one.apply(this.$, Array.prototype.slice.call(arguments)); return this; } }); /** * Access Node object stored in jQuery objects * @param el {jQuery|Node} * @return {Node} */ Model.getModel = function(el) { if (!el) { return null; } else if (el instanceof Node) { return el; } else { return $(el).data('queryBuilderModel'); } }; /* * Define Node properties with getter and setter * Update events are emitted in the setter through root Model (if any) */ function defineModelProperties(obj, fields) { fields.forEach(function(field) { Object.defineProperty(obj.prototype, field, { enumerable: true, get: function() { return this.__[field]; }, set: function(value) { var oldValue = (this.__[field] !== null && typeof this.__[field] == 'object') ? $.extend({}, this.__[field]) : this.__[field]; this.__[field] = value; if (this.model !== null) { this.model.trigger('update', this, field, value, oldValue); } } }); }); } // Node abstract CLASS // =============================== /** * @param {Node} * @param {jQuery} */ var Node = function(parent, $el) { if (!(this instanceof Node)) { return new Node(); } Object.defineProperty(this, '__', { value: {} }); $el.data('queryBuilderModel', this); this.__.level = 1; this.__.error = null; this.__.data = undefined; this.$el = $el; this.id = $el[0].id; this.model = null; this.parent = parent; }; defineModelProperties(Node, ['level', 'error', 'data', 'flags']); Object.defineProperty(Node.prototype, 'parent', { enumerable: true, get: function() { return this.__.parent; }, set: function(value) { this.__.parent = value; this.level = value === null ? 1 : value.level + 1; this.model = value === null ? null : value.model; } }); /** * Check if this Node is the root * @return {boolean} */ Node.prototype.isRoot = function() { return (this.level === 1); }; /** * Return node position inside parent * @return {int} */ Node.prototype.getPos = function() { if (this.isRoot()) { return -1; } else { return this.parent.getNodePos(this); } }; /** * Delete self */ Node.prototype.drop = function() { var model = this.model; if (!this.isRoot()) { this.parent._removeNode(this); } if (model !== null) { model.trigger('drop', this); } }; /** * Move itself after another Node * @param {Node} * @return {Node} self */ Node.prototype.moveAfter = function(node) { if (this.isRoot()) return; this._move(node.parent, node.getPos() + 1); return this; }; /** * Move itself at the beginning of parent or another Group * @param {Group,optional} * @return {Node} self */ Node.prototype.moveAtBegin = function(target) { if (this.isRoot()) return; if (target === undefined) { target = this.parent; } this._move(target, 0); return this; }; /** * Move itself at the end of parent or another Group * @param {Group,optional} * @return {Node} self */ Node.prototype.moveAtEnd = function(target) { if (this.isRoot()) return; if (target === undefined) { target = this.parent; } this._move(target, target.length() === 0 ? 0 : target.length() - 1); return this; }; /** * Move itself at specific position of Group * @param {Group} * @param {int} */ Node.prototype._move = function(group, index) { this.parent._removeNode(this); group._appendNode(this, index, false); if (this.model !== null) { this.model.trigger('move', this, group, index); } }; // GROUP CLASS // =============================== /** * @param {Group} * @param {jQuery} */ var Group = function(parent, $el) { if (!(this instanceof Group)) { return new Group(parent, $el); } Node.call(this, parent, $el); this.rules = []; this.__.condition = null; }; Group.prototype = Object.create(Node.prototype); Group.prototype.constructor = Group; defineModelProperties(Group, ['condition']); /** * Empty the Group */ Group.prototype.empty = function() { this.each('reverse', function(rule) { rule.drop(); }, function(group) { group.drop(); }); }; /** * Delete self */ Group.prototype.drop = function() { this.empty(); Node.prototype.drop.call(this); }; /** * Return the number of children * @return {int} */ Group.prototype.length = function() { return this.rules.length; }; /** * Add a Node at specified index * @param {Node} * @param {int,optional} * @param {boolean,optional} * @return {Node} the inserted node */ Group.prototype._appendNode = function(node, index, trigger) { if (index === undefined) { index = this.length(); } this.rules.splice(index, 0, node); node.parent = this; if (trigger && this.model !== null) { this.model.trigger('add', node, index); } return node; }; /** * Add a Group by jQuery element at specified index * @param {jQuery} * @param {int,optional} * @return {Group} the inserted group */ Group.prototype.addGroup = function($el, index) { return this._appendNode(new Group(this, $el), index, true); }; /** * Add a Rule by jQuery element at specified index * @param {jQuery} * @param {int,optional} * @return {Rule} the inserted rule */ Group.prototype.addRule = function($el, index) { return this._appendNode(new Rule(this, $el), index, true); }; /** * Delete a specific Node * @param {Node} * @return {Group} self */ Group.prototype._removeNode = function(node) { var index = this.getNodePos(node); if (index !== -1) { node.parent = null; this.rules.splice(index, 1); } return this; }; /** * Return position of a child Node * @param {Node} * @return {int} */ Group.prototype.getNodePos = function(node) { return this.rules.indexOf(node); }; /** * Iterate over all Nodes * @param {boolean,optional} iterate in reverse order, required if you delete nodes * @param {function} callback for Rules * @param {function,optional} callback for Groups * @return {boolean} */ Group.prototype.each = function(reverse, cbRule, cbGroup, context) { if (typeof reverse == 'function') { context = cbGroup; cbGroup = cbRule; cbRule = reverse; reverse = false; } context = context === undefined ? null : context; var i = reverse ? this.rules.length - 1 : 0; var l = reverse ? 0 : this.rules.length - 1; var c = reverse ? -1 : 1; var next = function() { return reverse ? i >= l : i <= l; }; var stop = false; for (; next(); i+= c) { if (this.rules[i] instanceof Group) { if (cbGroup !== undefined) { stop = cbGroup.call(context, this.rules[i]) === false; } } else { stop = cbRule.call(context, this.rules[i]) === false; } if (stop) { break; } } return !stop; }; /** * Return true if the group contains a particular Node * @param {Node} * @param {boolean,optional} recursive search * @return {boolean} */ Group.prototype.contains = function(node, deep) { if (this.getNodePos(node) !== -1) { return true; } else if (!deep) { return false; } else { // the loop will return with false as soon as the Node is found return !this.each(function(rule) { return true; }, function(group) { return !group.contains(node, true); }); } }; // RULE CLASS // =============================== /** * @param {Group} * @param {jQuery} */ var Rule = function(parent, $el) { if (!(this instanceof Rule)) { return new Rule(parent, $el); } Node.call(this, parent, $el); this.__.filter = null; this.__.operator = null; this.__.flags = {}; this.__.value = undefined; }; Rule.prototype = Object.create(Node.prototype); Rule.prototype.constructor = Rule; defineModelProperties(Rule, ['filter', 'operator', 'value']); // EXPORT // =============================== QueryBuilder.Group = Group; QueryBuilder.Rule = Rule;