Replace minimal groups
diff --git a/public/js/demo/vc.html b/public/js/demo/vc.html
index d4924e4..853d07e 100644
--- a/public/js/demo/vc.html
+++ b/public/js/demo/vc.html
@@ -60,6 +60,14 @@
};
var vc = KorAP.VirtualCollection.render(json);
document.getElementById('vc').appendChild(vc.element());
+
+ function showJSON() {
+ document.getElementById("json").innerHTML = JSON.stringify(vc.root().toJson());
+ };
+
</script>
+
+ <p><a onclick="showJSON()" style="cursor:pointer">show JSON!</a></p>
+ <div id="json" style="background-color:white; color: black; padding: 1em; font-family: mono;"></div>
</body>
</html>
diff --git a/public/js/spec/vcSpec.js b/public/js/spec/vcSpec.js
index 2010adf..aa57b4f 100644
--- a/public/js/spec/vcSpec.js
+++ b/public/js/spec/vcSpec.js
@@ -628,9 +628,55 @@
expect(second.matchop()).toEqual('eq');
});
+
it('should be based on a nested docGroup', function () {
var vc = KorAP.VirtualCollection.render({
"@type" : "korap:docGroup",
+ "operation" : "operation:or",
+ "operands" : [
+ {
+ "@type": 'korap:doc',
+ "key" : 'author',
+ "match": 'match:eq',
+ "value": 'Max Birkendale',
+ "type": 'type:string'
+ },
+ {
+ "@type" : "korap:docGroup",
+ "operation" : "operation:and",
+ "operands" : [
+ {
+ "@type": 'korap:doc',
+ "key": 'pubDate',
+ "match": 'match:geq',
+ "value": '2014-05-12',
+ "type": 'type:date'
+ },
+ {
+ "@type": 'korap:doc',
+ "key": 'pubDate',
+ "match": 'match:leq',
+ "value": '2014-12-05',
+ "type": 'type:date'
+ }
+ ]
+ }
+ ]
+ });
+ expect(vc.element().getAttribute('class')).toEqual('vc');
+ expect(vc.element().firstChild.getAttribute('class')).toEqual('docGroup');
+ expect(vc.element().firstChild.children[0].getAttribute('class')).toEqual('doc');
+ var dg = vc.element().firstChild.children[1];
+ expect(dg.getAttribute('class')).toEqual('docGroup');
+ expect(dg.children[0].getAttribute('class')).toEqual('doc');
+ expect(dg.children[1].getAttribute('class')).toEqual('doc');
+ expect(dg.children[2].getAttribute('class')).toEqual('operators');
+ expect(vc.element().firstChild.children[2].getAttribute('class')).toEqual('operators');
+ });
+
+ it('should be modifiable by deletion', function () {
+ var vc = KorAP.VirtualCollection.render({
+ "@type" : "korap:docGroup",
"operation" : "operation:and",
"operands" : [
{
@@ -660,39 +706,21 @@
var docGroup = vc.root();
var doc = docGroup.getOperand(1);
expect(doc.key()).toEqual("pubDate");
- expect(docGroup.delOperand(doc)).toEqual(true);
+
+ // Remove operand 1
+ expect(docGroup.delOperand(doc)).not.toBeUndefined();
+ expect(doc._element).toEqual(undefined);
+
doc = docGroup.getOperand(1);
expect(doc.key()).toEqual("foo");
- });
- it('should be modifiable', function () {
- var vc = KorAP.VirtualCollection.render();
+ // Remove operand 1
+ expect(docGroup.delOperand(doc)).not.toBeUndefined();
+ expect(doc._element).toEqual(undefined);
- var vc = KorAP.VirtualCollection.render({
- "@type" : "korap:docGroup",
- "operation" : "operation:and",
- "operands" : [
- {
- "@type": 'korap:doc',
- "key" : 'author',
- "match": 'match:eq',
- "value": 'Max Birkendale',
- "type": 'type:string'
- },
- {
- "@type": 'korap:doc',
- "key": 'pubDate',
- "match": 'match:eq',
- "value": '2014-12-05',
- "type": 'type:date'
- }
- ]
- });
-
- expect(vc.element().getAttribute('class')).toEqual('vc');
- expect(vc.root().element().getAttribute('class')).toEqual('docGroup');
- expect(vc.root().operation()).toEqual('and');
- });
+ // Only one operand - but there shouldn't be a group anymore!
+ expect(docGroup.getOperand(1)).toBeUndefined();
+ });
});
describe('KorAP.Operators', function () {
diff --git a/public/js/src/vc.js b/public/js/src/vc.js
index fbdc118..31ddc85 100644
--- a/public/js/src/vc.js
+++ b/public/js/src/vc.js
@@ -170,6 +170,7 @@
this._parent = obj;
return this._parent;
},
+
element : function () {
// Return existing element
@@ -262,6 +263,7 @@
obj._parent = parent;
return obj;
},
+
update : function () {
if (this._element === undefined)
return this.element();
@@ -531,17 +533,26 @@
};
},
update : function () {
+ if (this._operands.length == 1) {
+ if (this.parent() !== undefined) {
+ return this.parent().replaceOperand(
+ this,
+ this.getOperand(0)
+ );
+ };
+ };
+
if (this._element === undefined)
- return this.element();
+ return this;
- var op = this._element;
- op.setAttribute('data-operation', this.operation());
+ var group = this._element;
+ group.setAttribute('data-operation', this.operation());
- _removeChildren(op);
+ _removeChildren(group);
// Append operands
- for (var i in this.operands()) {
- op.appendChild(
+ for (var i in this._operands) {
+ group.appendChild(
this.getOperand(i).element()
);
};
@@ -553,11 +564,11 @@
true
);
- this._element.appendChild(
+ group.appendChild(
op.element()
);
- return op;
+ return this;
},
element : function () {
if (this._element !== undefined)
@@ -589,19 +600,35 @@
return this._operands[index];
},
+ // Replace operand
+ replaceOperand : function (group, obj) {
+ for (var i in this._operands) {
+ if (this._operands[i] === group) {
+ this._operands[i] = obj;
+ group.destroy();
+ return this.update();
+ }
+ };
+ return false;
+ },
+
// Delete operand from group
delOperand : function (obj) {
for (var i in this._operands) {
if (this._operands[i] === obj) {
this._operands.splice(i,1);
+ // Destroy object for cyclic references
+ obj.destroy();
+
// Todo: Update has to check
// that this may mean the group is empty etc.
- this.update();
- return true;
+ return this.update();
};
};
- return false;
+
+ // Operand not found
+ return undefined;
},
// Deserialize from json
@@ -679,6 +706,26 @@
return this._parent;
},
+ // Destroy object - especially for
+ // acyclic structures!
+ // I'm a paranoid chicken!
+ destroy : function () {
+ if (this._ops != undefined) {
+ this._ops._parent = undefined;
+ if (this._ops._element !== undefined)
+ this._ops._element.refTo = undefined;
+ this._ops = undefined;
+ };
+ if (this._element !== undefined)
+ this._element = undefined;
+
+ // In case of a group, destroy all operands
+ if (this._operands !== undefined) {
+ for (var i in this._operands)
+ this.getOperand(i).destroy();
+ };
+ },
+
// Be aware! This may be cyclic
operators : function (and, or, del) {
if (arguments === 0)