//= require ./reflect var Iterable; (function($) { "use strict"; var areEquivalents = function(object1, object2) { var object1Attributes, object2Attributes, object1Methods, object2Methods, object1AttributeValue, object2AttributeValue, iterator, amount = 0, primitiveTypes = /(number|string|boolean|null|undefined|symbol)/, callback = function(attribute) { object1AttributeValue = object1[attribute]; object2AttributeValue = object2[attribute]; if ($.hasSameClass(object1AttributeValue, object2AttributeValue)) { if (typeof object1AttributeValue == "object") { // recursivity if ($.areEquivalents( object1AttributeValue, object2AttributeValue)) { amount += 1; } } else if (object1AttributeValue == object2AttributeValue) { amount += 1; } } }; if (object1 === object2) { return true; } else if ($.hasSameClass(object1, object2)) { if (typeof object1 == "object") { if (object1 instanceof Node) { if (object1.isEqualNode(object2)) { return true; } } else { object1Attributes = $.attributes(object1); object2Attributes = $.attributes(object2); object1Methods = $.methods(object1); object2Methods = $.methods(object2); // if doesn't have attributes if (!object1Attributes.length) { if (object1Methods.length == object2Methods.length && // recursivity $.areEquivalents(object1Methods, object2Methods)) { return true; } } else if (object1Attributes.length == object2Attributes.length) { iterator = Iterable.Proxy.new(object1Attributes); iterator.each(callback); return amount == object1Attributes.length; } } } else { if (primitiveTypes.test(typeof object1)) { return object1 === object2; } } } return false; }; try { $.defineProperties($, { areEquivalents: { value: areEquivalents }, empty: { value: function(object) { return $.amount(object) === 0; } }, some: { value: function(object) { return !$.empty(object); } }, hasSameClass: { value: function(objects) { var argumentsAsArray = Array.from(arguments), compared = argumentsAsArray[0], amount = 0, callback = function(object) { if (!object) { if ($.className(object) == $.className(compared)) { amount++; } } else if ($.getPrototypeOf(compared) == $.getPrototypeOf(object)) { amount++; } }; argumentsAsArray = argumentsAsArray.slice(1, argumentsAsArray.length); argumentsAsArray.forEach(callback); return amount == argumentsAsArray.length; } }, belongToClass: { value: function(objects, classFunction) { var iterator, argumentsAsArray = Array.from(arguments), amount = 0, callback = function(object) { if (Reflect.constructorForName($ .className(object)) == classFunction) { amount++; } }; classFunction = argumentsAsArray.last(); argumentsAsArray.pop(); iterator = Iterable.Proxy.new(argumentsAsArray); iterator.each(callback); return amount == argumentsAsArray.length; } }, hasAttribute: { value: function(object, attributeName) { return $.attributes(object, true).includes(attributeName); } }, implementsMethod: { value: function(object, methodName) { return $.methods(object).includes(methodName); } }, clone: { value: function(object, includeNonEnumerable) { if (typeof includeNonEnumerable != "boolean") { includeNonEnumerable = true; } var clone = {}, properties = $.getOwnPropertyNames(object), callback = function(p) { clone[p] = object[p]; }; if (!includeNonEnumerable) { return Object.assign(clone, object); } try { properties.forEach(callback); } catch(e) {} return clone; } }, className: { value: function(object) { var pattern = /[a-zA-Z$_][^\]]+/g, string = $.prototype.toString.call(object); if (typeof object == "object" && // executar/verificar name ao invés de toString $.implementsMethod(object, "toString")) { // if implements, then calls it string = object.toString(); } return pattern.exec(string)[0].split(" ")[1]; } }, firstKey: { value: function(object) { var // Object: javascript literal object keys = Object.keys(object); return keys[0]; } }, lastKey: { value: function(object) { var keys = Object.keys(object); return keys[keys.length - 1]; } }, normalizedAsLowerCase: { value: function(object) { var iterator, attributes = Object.attributes(object), clone = {}, callback = function(v, k) { if (typeof v == "string") { clone[k] = v.toLowerCase(); } }; Object.assign(clone, object); object.length = attributes.length; iterator = Iterable.Proxy.new(clone); iterator.each(callback); return clone; } }, firstFromASlice: { value: function(object, slice, startingIndex, caseSensitive) { var iterator, key, regexp, attributes = Object.attributes(object), callback = function(k, i) { if (!isNaN(i)) { if (typeof object[k] == "string" && i >= startingIndex) { if (object[k].search(regexp) != -1) { key = k; this.finalize(); } } } else if (typeof object[k] == "string") { if (object[k].search(regexp) != -1) { key = k; this.finalize(); } } }; if (typeof startingIndex != "number") { if (typeof startingIndex == "boolean") { caseSensitive = startingIndex; } else if (!caseSensitive || typeof caseSensitive != "boolean") { caseSensitive = false; } startingIndex = 0; } slice = slice.trim(); if (!caseSensitive) { regexp = new RegExp(slice, "i"); } else { regexp = new RegExp(slice); } iterator = Iterable.Proxy.new(attributes); iterator.each(callback); if (key) { return key; } return undefined; } }, asCountableLiteral: { value: function(collection) { return Iterable.parse(collection); } }, // The keys of associative arrays in JS only can be of integer or string kind. The associations that keys are of Integer kind, the items is sorted according the keys (works as HashSet of the Java); the associations that keys are String kind, works as LinkedHashMap, it implements a associative array and maintains the order of entrance on iterate. // TreeMap implements a structure based red-black tree (binary search). indexOf: { value: function(object, value) { var key, iterator, properties = $.keys(object), callback = function(p) { if ($.areEquivalents(object[p], value)) { key = p; this.finalize(); } }; iterator = Iterable.Proxy.new(properties); iterator.each(callback); if (key) { return key; } return undefined; } }, amount: { value: function(object, item) { var amount; if (item) { amount = $.values(object).amount(item); } else { amount = $.keys(object).length; } return amount; } }, delete: { value: function(index, object) { if (delete object[index]) { if (object.hasOwnProperty("length")) { object.length -= 1; } return true; } return false; } }, reverse: { value: function(object) { var newObject = {}, callback = function(k) { newObject[k] = object[k]; }; $.keys(object).reverse().forEach(callback); return newObject; } }, attributes: { value: function(object, includeNonEnumerable) { if (typeof includeNonEnumerable != "boolean") { includeNonEnumerable = false; } var clone, properties, attributes = [], callback = function(p) { return typeof object[p] != "function"; }; if (!object) { return []; } clone = Object.clone(object, includeNonEnumerable); if (typeof object != "object" && typeof object != "function" && Object.getPrototypeOf(object)) { clone = Object.getPrototypeOf(object); } properties = $.keys(clone); if (includeNonEnumerable) { properties = $.getOwnPropertyNames(clone); } try { attributes = properties.filter(callback); } catch(e) {} return attributes; } }, methods: { value: function(object, includeNonEnumerable) { if (typeof includeNonEnumerable != "boolean") { includeNonEnumerable = true; } var clone, properties; // otherwise it will give a cascade error if (!object) { return []; } clone = Object.clone(object, includeNonEnumerable); if (typeof object != "object" && typeof object != "function" && Object.getPrototypeOf(object)) { clone = Object.getPrototypeOf(object); } properties = $.keys(clone); if (includeNonEnumerable) { properties = $.getOwnPropertyNames(clone); } return properties.difference($.attributes(object, true)); } } }); } catch(e) {} })(Object);