//= require ./lib/patterns //= require ./lib/extensions // See how that must be resolved without compromising the builder pattern var esPhinx, Iterable, SearchContext, Search; // IIFE (function($module) { "use strict"; // closure (private static attribute) var NAME = "esPhinx", selectInBreadth = function(iterable, callback) { var strategy; if (iterable instanceof window.Node) { strategy = SearchContext.Proxy.new(Search.Graphs.BFS.Element .new(iterable)); } else { strategy = SearchContext.Proxy.new(Search.Graphs.BFS.Object .new(iterable)); } return strategy.research(callback); }, resolveContext = function(context) { if (typeof context == "object") { if (context instanceof window.esPhinx || context instanceof Element) { return context; } } else if (typeof context == "string") { // recursivity return window.esPhinx(context); } return window.document; }, Extender = { extend: function(object, final, structure) { var context, strategy, verbose = false, propertyDescriptors = { enumerable: true, configurable: false }, // create or mount the context. If there is trace and object type is an Object, but it doesn't exists, it will be created, else it will be mounted. mountContext = function(methodName, trace, originalObject) { var context = originalObject, callback = function(v) { if (!context[v]) { context[v] = {}; } context = context[v]; }, isAnAccessor = function(methodName, trace) { return (methodName == "get" || methodName == "set") && trace.length; }; if ((trace.length && !isAnAccessor(methodName, trace)) || methodName != "get" && methodName != "set") { trace.forEach(callback); } return context; }, informeIf = function(verbose) { if (verbose) { console.warn("Property \"" + name + "\" of class \"" + Object.className(context) + "\" can't be redefined because " + "it's configured as read-only."); } }, hasAnyAccessor = function(body) { return Object.implementsMethods(body, "get") || Object.implementsMethods(body, "set"); }, callback = function(body, name, trace) { if (!Object.belongToClass(body, Object) || // otherwise it will arrive there still Object.empty(body) || hasAnyAccessor(body)) { context = mountContext(name, trace, object); // propertyDescriptors = JSON // .parse(JSON.parse(JSON.stringify("{\"" + name + // "\":" + JSON.stringify(propertyDescriptors) + "}"))); if (Object.belongToClass(body, Object)){ if (hasAnyAccessor(body)) { delete propertyDescriptors.writable; delete propertyDescriptors.configurable; propertyDescriptors.get = body.get || function() {}; propertyDescriptors.set = body.set || function() {}; } else if (Object.empty(body)) { propertyDescriptors.value = {}; } } else { if (typeof body == "function") { delete propertyDescriptors.enumerable; } propertyDescriptors.value = body; } try { Object.defineProperty(context, name, propertyDescriptors); } catch (e) { informeIf(verbose); } // restart propertyDescriptors propertyDescriptors = { enumerable: true, configurable: false, writable: !final }; } }; if (!structure && (typeof final == "object" || typeof final == "function")) { structure = final; } if (typeof final != "boolean") { final = false; } propertyDescriptors.writable = !final; propertyDescriptors.configurable = false; strategy = SearchContext.Proxy.new(Search.Graphs.BFS.Object .new(structure)); strategy.research(callback); } }; if (!$module.esPhinx) { Extender.extend($module, { esPhinx: function(selector, context) { var parsed, self = window.esPhinx, mainReference = this, collection = [], callback = function(node) { collection = collection.concat(Array .from(node .querySelectorAll(selector))) .flatten(); }, hasElement = function(iterable) { var iterator, response = false, callback = function(object) { if (object instanceof window.Element) { this.finalize(); response = true; } }; iterator = Iterable.Proxy.new(iterable); iterator.each(callback); return response; }; if (!(mainReference instanceof self)) { return new self(selector, context); } context = resolveContext(context); if (selector) { if (selector instanceof self) { return selector; } else if (typeof selector == "function") { // don't never pass a autoexecutable function as parameter return window.document .addEventListener("DOMContentLoaded", function(e) { selector.call(self, self, e); }); // get children "".match(/(>)(<.(?=(<\/)))/)[0] // add support to XPath } else if (typeof selector == "string") { parsed = (new window.DOMParser()) .parseFromString(selector, "text/html"); if (parsed.head.childElementCount) { collection = Array.from(parsed.head .childNodes); } else { collection = Array.from(parsed.body .childNodes); } if (!hasElement(collection)) { collection = []; if (Iterable.isIterable(context)) { Array.from(context) .forEach(callback); } else { try { collection = Array.from(context .querySelectorAll(selector)); } catch (e) {} } } } else if (selector instanceof window.Node) { collection = [selector]; } else if (selector instanceof Object) { collection = Array.from(selector); if (!Object.belongToClass(selector, window.HTMLCollection) && collection.length) { mainReference[0] = selector; if (selector == window) { collection = []; } } } Object.assign(mainReference, collection); } Extender.extend(mainReference, { splice: Array.prototype.splice, toString: function() { return "[object " + NAME + "]"; } }); Iterable.toIterable(mainReference); return mainReference; }, }); Extender.extend(esPhinx, { Extender: {} }); Extender.extend(esPhinx.Extender, { extend: function(object, final, structure) { Extender.extend(object, final, structure); } }); } esPhinx.Extender.extend(esPhinx, true, { extend: function() { this.Extender.extend(this, arguments[0], arguments[1]); } }); esPhinx.Extender.extend(esPhinx.prototype, true, { extend: function() { esPhinx.Extender.extend(this, arguments[0], arguments[1]); } }); esPhinx.extend(true, { selectByText: function(text, context) { var collection = [], callback = function(element) { collection = collection.concat(document.evaluate( "descendant-or-self::*[normalize-space(text())='" + text.trim() + "']", element).elements()).flatten(); }; this.select(this(resolveContext(context)), callback); return esPhinx(collection); }, isIterable: function(object) { return Iterable.isIterable(object); }, selectInBreadth: function(collection, callback) { return selectInBreadth(collection, callback); }, each: function(collection, startingIndex, finalIndex, callback) { var iterator = Iterable.Proxy.new(collection); iterator.each(startingIndex, finalIndex, callback); }, reverseEach: function(collection, startingIndex, callback) { var iterator = Iterable.Proxy.new(collection); if (typeof startingIndex == "function") { callback = startingIndex; } iterator.reverseEach(startingIndex, callback); }, select: function(collection, callback) { var iterator = Iterable.Proxy.new(collection); return iterator.select(callback); } }); })(window); // recognize a element // (^( *<)[a-z]+ *)( *((\/)|(>.*<\/[a-z]+))(> *)$) // recognize attributes and values // It's not possible capture attributes and their values, because their values can be given any character, which forces them to use ".+".