Added element objects and remove ecmascript 6 features, as they prevent easy inheritance
diff --git a/public/js/demo/vc.html b/public/js/demo/vc.html
new file mode 100644
index 0000000..054b969
--- /dev/null
+++ b/public/js/demo/vc.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Virtual Collection demo</title>
+ <script src="../src/vc.js"></script>
+ <style>
+div {
+ padding: 2pt;
+ padding-left: 10pt;
+ border: 2px solid black;
+}
+
+span {
+ margin: 2pt;
+ padding: 2pt;
+ color: white;
+ background-color: green;
+}
+
+div.undefined {
+ background-color: red;
+ height: 12pt;
+ min-width: 100px;
+}
+ </style>
+ </head>
+ <body>
+ <div id="vc"></div>
+ <script>
+ var json = {
+ "@type":"korap:docGroup",
+ "operation":"operation:or",
+ "operands":[
+ {
+ "@type":"korap:docGroup",
+ "operation":"operation:and",
+ "operands":[
+ {
+ "@type":"korap:doc",
+ "key":"Titel",
+ "value":"Baum",
+ "match":"match:eq"
+ },
+ {
+ "@type":"korap:doc",
+ "key":"Veröffentlichungsort",
+ "value":"hihi",
+ "match":"match:eq"
+ }
+ ]
+ },
+ {
+ "@type":"korap:doc",
+ "key":"Untertitel",
+ "value":"huhu",
+ "match":"match:eq"
+ }
+ ]
+ };
+
+// var vc = KorAP.VirtualCollection.render();
+ var vc = KorAP.VirtualCollection.render(json);
+ console.log(vc);
+ document.getElementById('vc').appendChild(vc.element());
+ </script>
+ </body>
+</html>
diff --git a/public/js/src/vc.js b/public/js/src/vc.js
index 26fa281..9ff6325 100644
--- a/public/js/src/vc.js
+++ b/public/js/src/vc.js
@@ -1,18 +1,27 @@
var KorAP = KorAP || {};
-/*
- 704: "Operation needs operand list"
- 701: "JSON-LD group has no @type attribute"
+// Todo: Implement a working localization solution!
+// Todo: Refactor out the distinction between DocElement and Doc,
+// DocGroupElement and DocGroup
+
+/*
+ * Error codes:
+ 701: "JSON-LD group has no @type attribute"
+ 704: "Operation needs operand list"
802: "Match type is not supported by value type"
804: "Unknown value type"
805: "Value is invalid"
806: "Value is not a valid date string"
807: "Value is not a valid regular expression"
-
-// new:
810: "Unknown document group operation" (like 711)
811: "Document group expects operation" (like 703)
812: "Operand not supported in document group" (like 744)
+ 813: "Collection type is not supported" (like 713)
+*/
+
+
+/*
+ - TODO: Support 'update' method to update elements on change
*/
(function (KorAP) {
@@ -25,58 +34,358 @@
KorAP._validStringMatchRE = new RegExp("^(?:eq|ne|contains)$");
KorAP._validRegexMatchRE = new RegExp("^(?:eq|ne)$");
- KorAP._validDateMatchRE = new RegExp("^(?:since|until|eq)$");
+ KorAP._validDateMatchRE = new RegExp("^[lg]?eq$");
KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
KorAP._validGroupOpRE = new RegExp("^(?:and|or)$");
- /*
+ var loc = (KorAP.Locale = KorAP.Locale || {} );
+ loc.AND = loc.AND || 'and';
+ loc.OR = loc.OR || 'or';
+ loc.DEL = loc.DEL || '×';
+
KorAP.VirtualCollection = {
+ _root : undefined,
create : function () {
return Object.create(KorAP.VirtualCollection);
},
- fromJson : function (json) {
+ render : function (json) {
+ var obj = Object.create(KorAP.VirtualCollection);
+
+ if (json !== undefined) {
+ // Root object
+ if (json['@type'] == 'korap:doc') {
+ obj._root = KorAP.DocElement.create(undefined, json);
+ }
+ else if (json['@type'] == 'korap:docGroup') {
+ obj._root = KorAP.DocGroupElement.create(undefined, json);
+ }
+ else {
+ KorAP.log(813, "Collection type is not supported");
+ return;
+ };
+ }
+
+ else {
+ // Add unspecified object
+ obj._root = KorAP.UnspecifiedDocElement.create();
+ };
+
+ // Add root element to root node
+ obj.element().appendChild(
+ obj._root.element()
+ );
+
+ return obj;
},
- render : function (element) {
- // ...
- }
- };
- */
- // Make KorAP.DocElement inherit from KorAP.Doc
- KorAP.DocElement = {
- create : function (param) {
- return Object.create(Korap.DocElement)._init(param);
+ root : function () {
+ return this._root;
},
- _init : function () {
- KorAP.Doc.create(param)
+ element : function () {
+ if (this._element !== undefined)
+ return this._element;
+
+ this._element = document.createElement('div');
+ this._element.setAttribute('class', 'vc');
+ return this._element;
}
};
+ KorAP.Operators = {
+ create : function (and, or, del) {
+ var op = Object.create(KorAP.Operators);
+ op.and(and);
+ op.or(or);
+ op.del(del);
+ return op;
+ },
+ update : function () {
+
+ // Init the element
+ if (this._element === undefined)
+ return this.element();
+
+ var op = this._element;
+
+ // Remove everything underneath
+ while (op.firstChild) {
+ op.removeChild(op.firstChild);
+ };
+
+ // Add and button
+ if (this._and === true) {
+ var andE = document.createElement('span');
+ andE.setAttribute('class', 'and');
+ andE.appendChild(document.createTextNode(KorAP.Locale.AND));
+ op.appendChild(andE);
+ };
+
+ // Add or button
+ if (this._or === true) {
+ var orE = document.createElement('span');
+ orE.setAttribute('class', 'or');
+ orE.appendChild(document.createTextNode(KorAP.Locale.OR));
+ op.appendChild(orE);
+ };
+
+ // Add delete button
+ if (this._del === true) {
+ var delE = document.createElement('span');
+ delE.setAttribute('class', 'delete');
+ delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
+ op.appendChild(delE);
+ };
+ return true;
+ },
+ element : function () {
+
+ // Return existing element
+ if (this._element !== undefined)
+ return this._element;
+
+ this._element = document.createElement('div');
+ this._element.setAttribute('class', 'operators');
+
+ // Init elements
+ this.update();
+ return this._element;
+ },
+ and : function (bool) {
+ if (arguments.length === 1)
+ this._and = (bool === undefined || bool === false) ? false : true;
+ return this._and;
+ },
+ or : function (bool) {
+ if (arguments.length === 1)
+ this._or = (bool === undefined || bool === false) ? false : true;
+ return this._or;
+ },
+ del : function (bool) {
+ if (arguments.length === 1)
+ this._del = (bool === undefined || bool === false) ? false : true;
+ return this._del;
+ }
+ };
+
+
+ /**
+ * Unspecified criterion
+ */
+ KorAP.UnspecifiedDocElement = {
+ _obj : function () { return KorAP.UnspecifiedDocElement; },
+ _objType : 'UnspecifiedDocElement',
+ create : function (parent) {
+ var obj = Object.create(KorAP.JsonLD).extend(KorAP.UnspecifiedDocElement);
+ if (parent !== undefined)
+ obj._parent = parent;
+ return obj;
+ },
+ element : function () {
+ if (this._element !== undefined)
+ return this._element;
+ this._element = document.createElement('div');
+ this._element.setAttribute('class', 'undefined');
+ return this._element;
+ }
+ };
+
+
+ KorAP.DocElement = {
+ _obj : function () { return KorAP.DocElement; },
+ _objType : 'DocElement',
+
+ create : function (parent, json) {
+ var obj = KorAP.Doc.create().extend(KorAP.DocElement).fromJson(json);
+ if (parent !== undefined)
+ obj._parent = parent;
+ return obj;
+ },
+ element : function () {
+ if (this._element !== undefined)
+ return this._element;
+
+ this._element = document.createElement('div');
+ var e = this._element;
+ e.setAttribute('class', 'doc');
+
+ // Added key
+ var key = document.createElement('span');
+ key.setAttribute('class', 'key');
+ if (this.key())
+ key.appendChild(document.createTextNode(this.key()));
+
+ // Added match operator
+ var matchop = document.createElement('span');
+ matchop.setAttribute('data-type', this.type());
+ matchop.setAttribute('class', 'match');
+ matchop.appendChild(document.createTextNode(this.matchop()));
+
+ // Added match operator
+ var value = document.createElement('span');
+ value.setAttribute('data-type', this.type());
+ value.setAttribute('class', 'value');
+ if (this.value())
+ value.appendChild(document.createTextNode(this.value()));
+
+ // Add spans
+ e.appendChild(key);
+ e.appendChild(matchop);
+ e.appendChild(value);
+ return e;
+ },
+
+ // parent, element
+ // Wrap a new operation around the doc element
+ wrap : function (op) {
+ var group = KorAP.DocGroupElement.create(undefined);
+ group.appendOperand(this);
+ group.appendOperand(null);
+ this.parent(group);
+/*
+ var div = document.createElement('div');
+ div.setAttribute('data-operation', op);
+ var parent = this.element.parent;
+ parent.removeChild(this.element);
+ parent.appendChild(div);
+ div.appendChild(this.element);
+ return div;
+*/
+ }
+ };
+
+ KorAP.DocGroupElement = {
+ _obj : function () { return KorAP.DocGroupElement; },
+ _objType : 'DocGroupElement',
+
+ create : function (parent, json) {
+ var obj = KorAP.DocGroup.create().extend(KorAP.DocGroupElement).fromJson(json);
+ if (parent !== undefined)
+ obj._parent = parent;
+ return obj;
+ },
+ appendOperand : function (operand) {
+ switch (operand["@type"]) {
+ case undefined:
+ if (operand["objType"]) {
+ if (operand.objType() === 'Doc') {
+ operand = operand.upgrade(KorAP.DocElement);
+ }
+ else if (operand.objType() === 'DocGroup') {
+ operand = operand.upgrade(KorAP.DocElementGroup);
+ }
+ else if (operand.objType() !== 'DocElement' &&
+ operand.objType() !== 'DocElementGroup') {
+ KorAP.log(812, "Operand not supported in document group");
+ return;
+ };
+ this._operands.push(operand);
+ return operand;
+ };
+
+ KorAP.log(701, "JSON-LD group has no @type attribute");
+ return;
+
+ case "korap:doc":
+ var doc = KorAP.DocElement.create().fromJson(operand);
+ if (doc === undefined)
+ return;
+ this._operands.push(doc);
+ return doc;
+
+ case "korap:docGroup":
+ var docGroup = KorAP.DocGroupElement.create().fromJson(operand);
+ if (docGroup === undefined)
+ return;
+ this._operands.push(docGroup);
+ return docGroup;
+
+ default:
+ KorAP.log(812, "Operand not supported in document group");
+ return;
+ };
+ },
+ element : function () {
+ if (this._element !== undefined)
+ return this._element;
+
+ this._element = document.createElement('div');
+ this._element.setAttribute('class', 'docGroup');
+ this._element.setAttribute('data-operation', this.operation());
+
+ for (var i in this.operands()) {
+ this._element.appendChild(
+ this.getOperand(i).element()
+ );
+ };
+
+ return this._element;
+ },
+ };
+
+
+ // Abstract JsonLD object
+ KorAP.JsonLD = {
+ _obj : function () { return KorAP.JsonLD; },
+ _objType : 'JsonLD',
+ create : function () {
+ return Object.create(KorAP.JsonLD);
+ },
+
+ // Extend this object with another object
+ // Private data will be lost
+ extend : function (props) {
+ var jld = this._obj().create();
+ for (var prop in props) {
+ jld[prop] = props[prop];
+ };
+ return jld;
+ },
+
+ // Upgrade this object to another object
+ // Private data stays intact
+ upgrade : function (props) {
+ for (var prop in props) {
+ this[prop] = props[prop];
+ };
+ return this;
+ },
+ ldType : function (type) {
+ if (arguments.length === 1)
+ this._ldType = type;
+ return this._ldType;
+ },
+ objType : function () {
+ return this._objType;
+ },
+ parent : function (obj) {
+ if (arguments.length === 1)
+ this._parent = obj;
+ return this._parent;
+ }
+ };
+
+
KorAP.DocGroup = {
+ _ldType : "docGroup",
+ _obj : function () { return KorAP.DocGroup; },
+ _objType : 'DocGroup',
create : function (type) {
- var docGroup = Object.create(KorAP.DocGroup);
- docGroup.operation = type;
+ var docGroup = Object.create(KorAP.JsonLD).extend(KorAP.DocGroup);
+ if (type !== undefined)
+ docGroup.operation(type);
docGroup._operands = [];
- docGroup.ldType = "docGroup";
return docGroup;
},
// Deserialize from json
fromJson : function (json) {
- return Object.create(KorAP.DocGroup)._init(json);
- },
-
- _init : function (json) {
-
if (json === undefined)
- return KorAP.DocGroup.create("and");
+ return this;
- if (json["@type"] != "korap:docGroup") {
+ if (json["@type"] !== "korap:docGroup") {
KorAP.log(701, "JSON-LD group has no @type attribute");
return;
};
- this.ldType = "docGroup";
-
if (json["operation"] === undefined ||
typeof json["operation"] !== 'string') {
KorAP.log(811, "Document group expects operation");
@@ -84,9 +393,8 @@
};
var operation = json["operation"];
- this.operation = operation.replace(/^operation:/,'');
- this._operands = [];
+ this.operation(operation.replace(/^operation:/,''));
if (json["operands"] === undefined ||
!(json["operands"] instanceof Array)) {
@@ -94,72 +402,72 @@
return;
};
- var operands = json["operands"];
-
// Add all documents
- for (var i in operands) {
- var operand = operands[i];
-
- switch (operand["@type"]) {
- case undefined:
- KorAP.log(701, "JSON-LD group has no @type attribute");
- return;
- case "korap:doc":
- var doc = KorAP.Doc.fromJson(operand);
- if (doc === undefined)
- return;
- this.appendOperand(doc);
- break;
- case "korap:docGroup":
- var docGroup = KorAP.DocGroup.fromJson(operand);
- if (docGroup === undefined)
- return;
- this.appendOperand(docGroup);
- break;
- default:
- KorAP.log(812, "Operand not supported in document group");
+ for (var i in json["operands"]) {
+ var operand = json["operands"][i];
+ this.appendOperand(operand);
+ };
+
+ return this;
+ },
+ operation : function (op) {
+ if (arguments.length === 1) {
+ if (KorAP._validGroupOpRE.test(op)) {
+ this._op = op;
+ }
+ else {
+ KorAP.log(810, "Unknown operation type");
return;
};
};
- return this;
- },
- set operation (op) {
- if (KorAP._validGroupOpRE.test(op)) {
- this._op = op;
- }
- else {
- KorAP.log(810, "Unknown operation type");
- return;
- };
- },
- get operation () {
return this._op || 'and';
},
- get operands () {
+ operands : function () {
return this._operands;
},
- appendOperand : function (obj) {
- this._operands.push(obj)
- return obj;
+ appendOperand : function (operand) {
+ switch (operand["@type"]) {
+ case undefined:
+ if (operand["objType"] && (
+ operand.objType() === 'Doc' ||
+ operand.objType() === 'DocGroup')) {
+ this._operands.push(operand);
+ return operand;
+ };
+ KorAP.log(701, "JSON-LD group has no @type attribute");
+ return;
+
+ case "korap:doc":
+ var doc = KorAP.Doc.create().fromJson(operand);
+ if (doc === undefined)
+ return;
+ this._operands.push(doc);
+ return doc;
+
+ case "korap:docGroup":
+ var docGroup = KorAP.DocGroup.create().fromJson(operand);
+ if (docGroup === undefined)
+ return;
+ this._operands.push(docGroup);
+ return docGroup;
+
+ default:
+ KorAP.log(812, "Operand not supported in document group");
+ return;
+ };
},
getOperand : function (index) {
return this._operands[index];
},
- set ldType (type) {
- this._ldtype = type;
- },
- get ldType () {
- return this._ldType || "docGroup";
- },
toJson : function () {
- var operands = new Array();
+ var opArray = new Array();
for (var i in this._operands) {
- operands.push(this._operands[i].toJson());
+ opArray.push(this._operands[i].toJson());
};
return {
- "@type" : "korap:" + this.ldType,
- "operation" : "operation:" + this.operation,
- "operands" : operands
+ "@type" : "korap:" + this.ldType(),
+ "operation" : "operation:" + this.operation(),
+ "operands" : opArray
};
}
};
@@ -168,31 +476,25 @@
* Virtual collection doc criterion.
*/
KorAP.Doc = {
-
+ _ldType : "doc",
+ _obj : function () { return KorAP.Doc; },
+ _objType : 'Doc',
// Create new
create : function () {
- var doc = Object.create(KorAP.Doc);
- doc.ldType = "doc";
- return doc;
+ return Object.create(KorAP.JsonLD).extend(KorAP.Doc);
},
// Deserialize from json
fromJson : function (json) {
- return Object.create(KorAP.Doc)._init(json);
- },
-
- // Init new doc criterion or deserialize fro JSON-LD
- _init : function (json) {
if (json === undefined)
- return this.create();
+ return this;
+ // return this.create();
if (json["@type"] !== "korap:doc") {
KorAP.log(701, "JSON-LD group has no @type attribute");
return;
};
- this.ldType = "doc";
-
if (json["value"] === undefined ||
typeof json["value"] != 'string') {
KorAP.log(805, "Value is invalid");
@@ -204,12 +506,13 @@
typeof json["key"] === 'string') {
// Set key
- this.key = json["key"];
+ this.key(json["key"]);
// Set match operation
if (json["match"] !== undefined) {
- if (typeof json["match"] === 'string')
- this.matchop = json["match"];
+ if (typeof json["match"] === 'string') {
+ this.matchop(json["match"]);
+ }
else {
KorAP.log(802, "Match type is not supported by value type");
return;
@@ -219,32 +522,32 @@
// Key is a string
if (json["type"] === undefined ||
json["type"] == "type:string") {
- this.type = "string";
+ this.type("string");
// Check match type
- if (!KorAP._validStringMatchRE.test(this.matchop)) {
+ if (!KorAP._validStringMatchRE.test(this.matchop())) {
KorAP.log(802, "Match type is not supported by value type");
return;
};
// Set string value
- this.value = json["value"];
+ this.value(json["value"]);
}
// Key is a date
else if (json["type"] === "type:date") {
- this.type = "date";
+ this.type("date");
if (json["value"] !== undefined &&
KorAP._validDateRE.test(json["value"])) {
- if (!KorAP._validDateMatchRE.test(this.matchop)) {
+ if (!KorAP._validDateMatchRE.test(this.matchop())) {
KorAP.log(802, "Match type is not supported by value type");
return;
};
// Set value
- this.value = json["value"];
+ this.value(json["value"]);
}
else {
KorAP.log(806, "Value is not a valid date string");
@@ -254,25 +557,26 @@
// Key is a regular expression
else if (json["type"] === "type:regex") {
- this.type = "regex";
+ this.type("regex");
try {
// Try to create a regular expression
var check = new RegExp(json["value"]);
- if (!KorAP._validRegexMatchRE.test(this.matchop)) {
+ if (!KorAP._validRegexMatchRE.test(this.matchop())) {
KorAP.log(802, "Match type is not supported by value type");
return;
};
- this.value = json["value"];
+ this.value(json["value"]);
}
+
catch (e) {
KorAP.log(807, "Value is not a valid regular expression");
return;
};
- this.type = "regex";
+ this.type("regex");
}
else {
@@ -283,48 +587,36 @@
return this;
},
- set key (value) {
- this._key = value;
- },
- get key () {
+ key : function (value) {
+ if (arguments.length === 1)
+ this._key = value;
return this._key;
},
- set matchop (match) {
- this._matchop = match.replace(/^match:/, '');
- },
- get matchop () {
+ matchop : function (match) {
+ if (arguments.length === 1)
+ this._matchop = match.replace(/^match:/, '');
return this._matchop || "eq";
},
- set type (type) {
- this._type = type;
- },
- get type () {
+ type : function (type) {
+ if (arguments.length === 1)
+ this._type = type;
return this._type || "string";
},
- set value (value) {
- this._value = value;
- },
- get value () {
+ value : function (value) {
+ if (arguments.length === 1)
+ this._value = value;
return this._value;
},
-
- // Todo: Redundant and should be inherited
- set ldType (type) {
- this._ldtype = type;
- },
- get ldType () {
- return this._ldType || "doc";
- },
toJson : function () {
- if (!this.matchop || !this.key)
+ if (!this.matchop() || !this.key())
return {};
return {
- "@type" : "korap:" + this.ldType,
- "key" : this.key,
- "match" : "match:" + this.matchop,
- "value" : this.value || '',
- "type" : "type:" + this.type
+ "@type" : "korap:" + this.ldType(),
+ "key" : this.key(),
+ "match" : "match:" + this.matchop(),
+ "value" : this.value() || '',
+ "type" : "type:" + this.type()
};
}
};