blob: 8a5c6b852e40e875ec16bbf1f78815226da2f229 [file] [log] [blame]
/**
* Create virtual collections with a visual user interface. This resembles the
* collection type objects of a KoralQuery "collection" object.
*
* KoralQuery v0.3 is expected.
*
* @author Nils Diewald
*/
/*
* This replaces a previous version written by Mengfei Zhou
*/
/*
* TODO: Disable "and" or "or" in case it's followed by an unspecified document
* TODO: Add "and"-method to root to add further constraints based on match-
* input (like clicking on a pubDate timestamp in a match) TODO: Implement
* "persistence"-Option, injecting the current creation date stamp TODO:
* Implement vec-Type for document-id vectors like docID in [1,2,3,4 ...]
*
* 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" 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) 814: "Unknown rewrite
* operation" 815: "Rewrite expects source"
*
* Localization strings: KorAP.Locale = { EMPTY : '...', AND : 'and', OR : 'or',
* DELETE : 'x' } and various field names with the prefix 'VC_'
*/
define([ 'vc/unspecified', 'vc/doc', 'vc/docgroup', 'vc/menu', 'vc/statistic',
'datepicker', 'buttongroup', 'panel', 'view/corpstatv', 'util', ],
function(unspecDocClass, docClass, docGroupClass, menuClass, statClass,
dpClass, buttonGrClass, panelClass, corpStatVClass) {
"use strict";
KorAP._validUnspecMatchRE = new RegExp(
"^(?:eq|ne|contains(?:not)?|excludes)$");
KorAP._validStringMatchRE = new RegExp("^(?:eq|ne)$");
KorAP._validTextMatchRE = KorAP._validUnspecMatchRE;
KorAP._validTextOnlyMatchRE = new RegExp(
"^(?:contains(?:not)?|excludes)$");
KorAP._overrideStyles = false;
// KorAP._validDateMatchRE is defined in datepicker.js!
const loc = KorAP.Locale;
loc.SHOW_STAT = loc.SHOW_STAT || 'Statistics';
loc.VERB_SHOWSTAT = loc.VERB_SHOWSTAT || 'Corpus Statistics';
KorAP._vcKeyMenu = undefined;
KorAP._vcDatePicker = dpClass.create();
// Create match menus ....
KorAP._vcMatchopMenu = {
'string' : menuClass.create([ [ 'eq', null ], [ 'ne', null ] ]),
'text' : menuClass.create([ [ 'eq', null ], // Requires exact match
[ 'ne', null ], [ 'contains', null ], // Requires token sequence match
[ 'containsnot', null ] ]),
'date' : menuClass.create([ [ 'eq', null ], [ 'ne', null ],
[ 'geq', null ], [ 'leq', null ] ]),
'regex' : menuClass.create([ [ 'eq', null ], [ 'ne', null ] ])
};
/**
* Virtual Collection
*/
return {
/**
* The JSON-LD type of the virtual collection
*/
ldType : function() {
return null;
},
// Initialize virtual collection
_init : function(keyList) {
// Inject localized css styles
if (!KorAP._overrideStyles) {
var sheet = KorAP.newStyleSheet();
// Add css rule for OR operations
sheet.insertRule('.vc .docGroup[data-operation=or] > .doc::before,'
+ '.vc .docGroup[data-operation=or] > .docGroup::before '
+ '{ content: "' + loc.OR + '" }', 0);
// Add css rule for AND operations
sheet.insertRule(
'.vc .docGroup[data-operation=and] > .doc::before,'
+ '.vc .docGroup[data-operation=and] > .docGroup::before '
+ '{ content: "' + loc.AND + '" }', 1);
KorAP._overrideStyles = true;
}
;
// Create key menu
KorAP._vcKeyMenu = menuClass.create(keyList);
KorAP._vcKeyMenu.limit(6);
return this;
},
/**
* Create a new virtual collection.
*/
create : function(keyList) {
var obj = Object.create(this)._init(keyList);
obj._root = unspecDocClass.create(obj);
return obj;
},
/**
* Create and render a new virtual collection based on a KoralQuery
* collection document
*/
fromJson : function(json) {
if (json !== undefined) {
// Parse root document
if (json['@type'] == 'koral:doc') {
this._root = docClass.create(this, json);
}
// parse root group
else if (json['@type'] == 'koral:docGroup') {
this._root = docGroupClass.create(this, json);
}
// Unknown collection type
else {
KorAP.log(813, "Collection type is not supported");
return;
}
;
}
else {
// Add unspecified object
this._root = unspecDocClass.create(this);
}
;
// Init element and update
this.update();
return this;
},
// Check if the virtual corpus contains a rewrite
// This is a class method
checkRewrite : function(json) {
// There is a rewrite attribute
if (json['rewrites'] !== undefined) {
return true;
}
// There is a group to check for rewrites
else if (json['@type'] === 'koral:docGroup') {
var ops = json['operands'];
if (ops === undefined)
return false;
for ( var i in ops) {
// "this" is the class
if (this.checkRewrite(ops[i])) {
return true;
}
;
}
;
}
;
return false;
},
/**
* Clean the virtual document to uspecified doc.
*/
clean : function() {
if (this._root.ldType() !== "non") {
this._root.destroy();
this.root(unspecDocClass.create(this));
}
;
return this;
},
/**
* Get or set the root object of the virtual collection.
*/
root : function(obj) {
if (arguments.length === 1) {
var e = this.element();
if (e.firstChild !== null) {
if (e.firstChild !== obj.element()) {
e.replaceChild(obj.element(), e.firstChild);
}
;
}
// Append root element
else {
e.appendChild(obj.element());
}
;
// Update parent child relations
this._root = obj;
obj.parent(this);
this.update();
}
;
return this._root;
},
/**
* Get the element associated with the virtual collection
*/
element : function() {
if (this._element !== undefined) {
return this._element;
}
;
this._element = document.createElement('div');
this._element.setAttribute('class', 'vc');
// Initialize root
this._element.appendChild(this._root.element());
/*
* TODO by Helge Hack! additional div, because statistic button is
* removed after choosing and/or/x in vc builder. REMOVE this lines
* after solving the problem!!!!
*/
this._element.addE('div');
this._element.addE('div');
this._element.addE('div');
// Add panel to display corpus statistic, ...
this.addVcInfPanel();
return this._element;
},
/**
* Update the whole object based on the underlying data structure
*/
update : function() {
this._root.update();
return this;
},
/**
* Make the vc persistant by injecting the current timestamp as a
* creation date limit criterion.
*/
makePersistant : function() {
// this.root().wrapOnRoot('and');
var todayStr = KorAP._vcDatePicker.today();
var doc = docClass.create();
var root = this.root();
if (root.ldType() === 'docGroup' && root.operation === 'and') {
root.append(cond);
} else {
root.wrapOnRoot('and');
root.append(doc);
}
;
doc.key("creationDate");
doc.type("date");
doc.matchop("leq");
doc.value(todayStr);
/*
* { "@type" : "koral:doc", "key" : "creationDate", "type" :
* "type:date", "match" : "match:leq", "value" : todayStr }
* this.root().append(cond);
*/
this.update();
},
/**
* Get the generated json string
*/
toJson : function() {
return this._root.toJson();
},
/**
* Get the generated query string
*/
toQuery : function() {
return this._root.toQuery();
},
/*
* Add panel to display virtual corpus information
*/
addVcInfPanel : function() {
var dv = this._element.addE('div');
var panel = panelClass.create([ 'vcinfo' ]);
dv.appendChild(panel.element());
var that = this;
var actions = panel.actions;
var statView;
actions.add(loc.SHOW_STAT, [ 'statistic' ], function() {
if (statView === undefined || !statView.shown()) {
statView = corpStatVClass.create(that);
panel.add(statView);
}
});
}
};
});