Demo for query storing

Change-Id: I947bcac841992c3f6cfd01ab337c265b0d01cb70
diff --git a/node_modules/css-select-base-adapter/index.js b/node_modules/css-select-base-adapter/index.js
new file mode 100644
index 0000000..6394cbd
--- /dev/null
+++ b/node_modules/css-select-base-adapter/index.js
@@ -0,0 +1,131 @@
+'use strict'
+
+module.exports = adapterFactory;
+
+function adapterFactory(implementation){
+	ensureImplementation(implementation);
+
+	var adapter = {}
+
+	var baseAdapter = {
+		removeSubsets: function (nodes){
+			return removeSubsets(adapter, nodes);
+		},
+		existsOne: function(test, elems){
+			return existsOne(adapter, test, elems);
+		},
+		getSiblings: function(elem){
+			return getSiblings(adapter, elem);
+		},
+		hasAttrib: function(elem, name){
+			return hasAttrib(adapter, elem, name);
+		},
+		findOne: function(test, arr){
+			return findOne(adapter, test, arr);
+		},
+		findAll: function(test, elems){
+			return findAll(adapter, test, elems)
+		}
+	};
+
+	Object.assign(adapter, baseAdapter, implementation);
+
+	return adapter;
+}
+
+var expectImplemented = [
+	"isTag", "getAttributeValue", "getChildren", "getName", "getParent",
+	"getText"
+];
+
+function ensureImplementation(implementation){
+	if(!implementation)	throw new TypeError("Expected implementation")
+
+	var notImplemented = expectImplemented.filter(function(fname){
+		return typeof implementation[fname] !== "function";
+	});
+
+	if(notImplemented.length){
+		var notList = "(" + notImplemented.join(", ") + ")";
+		var message = "Expected functions " + notList + " to be implemented";
+		throw new Error(message);
+	}
+}
+
+function removeSubsets(adapter, nodes){
+	var idx = nodes.length, node, ancestor, replace;
+
+	// Check if each node (or one of its ancestors) is already contained in the
+	// array.
+	while(--idx > -1){
+		node = ancestor = nodes[idx];
+
+		// Temporarily remove the node under consideration
+		nodes[idx] = null;
+		replace = true;
+
+		while(ancestor){
+			if(nodes.indexOf(ancestor) > -1){
+				replace = false;
+				nodes.splice(idx, 1);
+				break;
+			}
+			ancestor = adapter.getParent(ancestor)
+		}
+
+		// If the node has been found to be unique, re-insert it.
+		if(replace){
+			nodes[idx] = node;
+		}
+	}
+
+	return nodes;
+}
+
+function existsOne(adapter, test, elems){
+	return elems.some(function(elem){
+		return adapter.isTag(elem) ?
+			test(elem) || adapter.existsOne(test, adapter.getChildren(elem)) :
+			false;
+	});
+}
+
+function getSiblings(adapter, elem){
+	var parent = adapter.getParent(elem);
+	return parent && adapter.getChildren(parent);
+}
+
+
+function hasAttrib(adapter, elem, name){
+	return adapter.getAttributeValue(elem,name) !== undefined
+}
+
+function findOne(adapter, test, arr){
+	var elem = null;
+
+	for(var i = 0, l = arr.length; i < l && !elem; i++){
+		if(test(arr[i])){
+			elem = arr[i];
+		} else {
+			var childs = adapter.getChildren(arr[i]);
+			if(childs && childs.length > 0){
+				elem = adapter.findOne(test, childs);
+			}
+		}
+	}
+
+	return elem;
+}
+
+function findAll(adapter, test, elems){
+	var result = [];
+
+	for(var i = 0, j = elems.length; i < j; i++){
+		if(!adapter.isTag(elems[i])) continue;
+		if(test(elems[i])) result.push(elems[i]);
+		var childs = adapter.getChildren(elems[i]);
+		if(childs) result = result.concat(adapter.findAll(test, childs));
+	}
+
+	return result;
+}