blob: 771152d333b42c641282447eed6335a554904daa [file] [log] [blame]
Nils Diewald3a2d8022014-12-16 02:45:41 +00001var KorAP = KorAP || {};
Nils Diewald3a2d8022014-12-16 02:45:41 +00002
Nils Diewald8f4e2542014-12-19 04:42:09 +00003// TODO: Implement a working localization solution!
4// TODO: Support 'update' method to update elements on change
Nils Diewaldd0770492014-12-19 03:55:00 +00005
6/*
7 * Error codes:
8 701: "JSON-LD group has no @type attribute"
9 704: "Operation needs operand list"
Nils Diewald3a2d8022014-12-16 02:45:41 +000010 802: "Match type is not supported by value type"
11 804: "Unknown value type"
12 805: "Value is invalid"
13 806: "Value is not a valid date string"
14 807: "Value is not a valid regular expression"
Nils Diewald3a2d8022014-12-16 02:45:41 +000015 810: "Unknown document group operation" (like 711)
16 811: "Document group expects operation" (like 703)
17 812: "Operand not supported in document group" (like 744)
Nils Diewaldd0770492014-12-19 03:55:00 +000018 813: "Collection type is not supported" (like 713)
19*/
20
21
Nils Diewald3a2d8022014-12-16 02:45:41 +000022(function (KorAP) {
23 "use strict";
24
25 // Default log message
26 KorAP.log = KorAP.log || function (type, msg) {
27 console.log(type + ": " + msg);
28 };
29
30 KorAP._validStringMatchRE = new RegExp("^(?:eq|ne|contains)$");
31 KorAP._validRegexMatchRE = new RegExp("^(?:eq|ne)$");
Nils Diewaldd0770492014-12-19 03:55:00 +000032 KorAP._validDateMatchRE = new RegExp("^[lg]?eq$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000033 KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
34 KorAP._validGroupOpRE = new RegExp("^(?:and|or)$");
35
Nils Diewaldd0770492014-12-19 03:55:00 +000036 var loc = (KorAP.Locale = KorAP.Locale || {} );
37 loc.AND = loc.AND || 'and';
38 loc.OR = loc.OR || 'or';
39 loc.DEL = loc.DEL || '×';
40
Nils Diewald3a2d8022014-12-16 02:45:41 +000041 KorAP.VirtualCollection = {
Nils Diewaldd0770492014-12-19 03:55:00 +000042 _root : undefined,
Nils Diewald3a2d8022014-12-16 02:45:41 +000043 create : function () {
44 return Object.create(KorAP.VirtualCollection);
45 },
Nils Diewaldd0770492014-12-19 03:55:00 +000046 render : function (json) {
47 var obj = Object.create(KorAP.VirtualCollection);
48
49 if (json !== undefined) {
50 // Root object
51 if (json['@type'] == 'korap:doc') {
Nils Diewald8f4e2542014-12-19 04:42:09 +000052 obj._root = KorAP.Doc.create(undefined, json);
Nils Diewaldd0770492014-12-19 03:55:00 +000053 }
54 else if (json['@type'] == 'korap:docGroup') {
Nils Diewald8f4e2542014-12-19 04:42:09 +000055 obj._root = KorAP.DocGroup.create(undefined, json);
Nils Diewaldd0770492014-12-19 03:55:00 +000056 }
57 else {
58 KorAP.log(813, "Collection type is not supported");
59 return;
60 };
61 }
62
63 else {
64 // Add unspecified object
Nils Diewald8f4e2542014-12-19 04:42:09 +000065 obj._root = KorAP.UnspecifiedDoc.create();
Nils Diewaldd0770492014-12-19 03:55:00 +000066 };
67
68 // Add root element to root node
69 obj.element().appendChild(
70 obj._root.element()
71 );
72
73 return obj;
Nils Diewald3a2d8022014-12-16 02:45:41 +000074 },
Nils Diewaldd0770492014-12-19 03:55:00 +000075 root : function () {
76 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +000077 },
Nils Diewaldd0770492014-12-19 03:55:00 +000078 element : function () {
79 if (this._element !== undefined)
80 return this._element;
81
82 this._element = document.createElement('div');
83 this._element.setAttribute('class', 'vc');
84 return this._element;
Nils Diewald3a2d8022014-12-16 02:45:41 +000085 }
86 };
87
Nils Diewald8f4e2542014-12-19 04:42:09 +000088 /**
89 * Operators for criteria
90 */
Nils Diewaldd0770492014-12-19 03:55:00 +000091 KorAP.Operators = {
92 create : function (and, or, del) {
93 var op = Object.create(KorAP.Operators);
94 op.and(and);
95 op.or(or);
96 op.del(del);
97 return op;
98 },
99 update : function () {
100
101 // Init the element
102 if (this._element === undefined)
103 return this.element();
104
105 var op = this._element;
106
107 // Remove everything underneath
108 while (op.firstChild) {
109 op.removeChild(op.firstChild);
110 };
111
112 // Add and button
113 if (this._and === true) {
114 var andE = document.createElement('span');
115 andE.setAttribute('class', 'and');
116 andE.appendChild(document.createTextNode(KorAP.Locale.AND));
117 op.appendChild(andE);
118 };
119
120 // Add or button
121 if (this._or === true) {
122 var orE = document.createElement('span');
123 orE.setAttribute('class', 'or');
124 orE.appendChild(document.createTextNode(KorAP.Locale.OR));
125 op.appendChild(orE);
126 };
127
128 // Add delete button
129 if (this._del === true) {
130 var delE = document.createElement('span');
131 delE.setAttribute('class', 'delete');
132 delE.appendChild(document.createTextNode(KorAP.Locale.DEL));
133 op.appendChild(delE);
134 };
135 return true;
136 },
137 element : function () {
138
139 // Return existing element
140 if (this._element !== undefined)
141 return this._element;
142
143 this._element = document.createElement('div');
144 this._element.setAttribute('class', 'operators');
145
146 // Init elements
147 this.update();
148 return this._element;
149 },
150 and : function (bool) {
151 if (arguments.length === 1)
152 this._and = (bool === undefined || bool === false) ? false : true;
153 return this._and;
154 },
155 or : function (bool) {
156 if (arguments.length === 1)
157 this._or = (bool === undefined || bool === false) ? false : true;
158 return this._or;
159 },
160 del : function (bool) {
161 if (arguments.length === 1)
162 this._del = (bool === undefined || bool === false) ? false : true;
163 return this._del;
164 }
165 };
166
167
168 /**
169 * Unspecified criterion
170 */
Nils Diewald8f4e2542014-12-19 04:42:09 +0000171 KorAP.UnspecifiedDoc = {
Nils Diewaldd0770492014-12-19 03:55:00 +0000172 create : function (parent) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000173 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.UnspecifiedDoc);
Nils Diewaldd0770492014-12-19 03:55:00 +0000174 if (parent !== undefined)
175 obj._parent = parent;
176 return obj;
177 },
178 element : function () {
179 if (this._element !== undefined)
180 return this._element;
181 this._element = document.createElement('div');
182 this._element.setAttribute('class', 'undefined');
183 return this._element;
184 }
185 };
186
187
Nils Diewald8f4e2542014-12-19 04:42:09 +0000188 /**
189 * Virtual collection doc criterion.
190 */
191 KorAP.Doc = {
192 _ldType : "doc",
193 _obj : function () { return KorAP.Doc; },
Nils Diewaldd0770492014-12-19 03:55:00 +0000194
195 create : function (parent, json) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000196 var obj = Object(KorAP.JsonLD).create().upgradeTo(KorAP.Doc).fromJson(json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000197 if (parent !== undefined)
198 obj._parent = parent;
199 return obj;
200 },
201 element : function () {
202 if (this._element !== undefined)
203 return this._element;
204
205 this._element = document.createElement('div');
206 var e = this._element;
207 e.setAttribute('class', 'doc');
208
209 // Added key
210 var key = document.createElement('span');
211 key.setAttribute('class', 'key');
212 if (this.key())
213 key.appendChild(document.createTextNode(this.key()));
214
215 // Added match operator
216 var matchop = document.createElement('span');
217 matchop.setAttribute('data-type', this.type());
218 matchop.setAttribute('class', 'match');
219 matchop.appendChild(document.createTextNode(this.matchop()));
220
221 // Added match operator
222 var value = document.createElement('span');
223 value.setAttribute('data-type', this.type());
224 value.setAttribute('class', 'value');
225 if (this.value())
226 value.appendChild(document.createTextNode(this.value()));
227
228 // Add spans
229 e.appendChild(key);
230 e.appendChild(matchop);
231 e.appendChild(value);
232 return e;
233 },
234
Nils Diewaldd0770492014-12-19 03:55:00 +0000235 // Wrap a new operation around the doc element
236 wrap : function (op) {
Nils Diewald8f4e2542014-12-19 04:42:09 +0000237 var group = KorAP.DocGroup.create(undefined);
Nils Diewaldd0770492014-12-19 03:55:00 +0000238 group.appendOperand(this);
239 group.appendOperand(null);
240 this.parent(group);
241/*
242 var div = document.createElement('div');
243 div.setAttribute('data-operation', op);
244 var parent = this.element.parent;
245 parent.removeChild(this.element);
246 parent.appendChild(div);
247 div.appendChild(this.element);
248 return div;
249*/
Nils Diewaldd0770492014-12-19 03:55:00 +0000250 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000251 // Deserialize from json
252 fromJson : function (json) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000253 if (json === undefined)
Nils Diewaldd0770492014-12-19 03:55:00 +0000254 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000255
Nils Diewald3a2d8022014-12-16 02:45:41 +0000256 if (json["@type"] !== "korap:doc") {
257 KorAP.log(701, "JSON-LD group has no @type attribute");
258 return;
259 };
260
Nils Diewald3a2d8022014-12-16 02:45:41 +0000261 if (json["value"] === undefined ||
262 typeof json["value"] != 'string') {
263 KorAP.log(805, "Value is invalid");
264 return;
265 };
266
267 // There is a defined key
268 if (json["key"] !== undefined &&
269 typeof json["key"] === 'string') {
270
271 // Set key
Nils Diewaldd0770492014-12-19 03:55:00 +0000272 this.key(json["key"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000273
274 // Set match operation
275 if (json["match"] !== undefined) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000276 if (typeof json["match"] === 'string') {
277 this.matchop(json["match"]);
278 }
Nils Diewald3a2d8022014-12-16 02:45:41 +0000279 else {
280 KorAP.log(802, "Match type is not supported by value type");
281 return;
282 };
283 };
284
285 // Key is a string
286 if (json["type"] === undefined ||
287 json["type"] == "type:string") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000288 this.type("string");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000289
290 // Check match type
Nils Diewaldd0770492014-12-19 03:55:00 +0000291 if (!KorAP._validStringMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000292 KorAP.log(802, "Match type is not supported by value type");
293 return;
294 };
295
296 // Set string value
Nils Diewaldd0770492014-12-19 03:55:00 +0000297 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000298 }
299
300 // Key is a date
301 else if (json["type"] === "type:date") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000302 this.type("date");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000303
304 if (json["value"] !== undefined &&
305 KorAP._validDateRE.test(json["value"])) {
306
Nils Diewaldd0770492014-12-19 03:55:00 +0000307 if (!KorAP._validDateMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000308 KorAP.log(802, "Match type is not supported by value type");
309 return;
310 };
311
312 // Set value
Nils Diewaldd0770492014-12-19 03:55:00 +0000313 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000314 }
315 else {
316 KorAP.log(806, "Value is not a valid date string");
317 return;
318 };
319 }
320
321 // Key is a regular expression
322 else if (json["type"] === "type:regex") {
Nils Diewaldd0770492014-12-19 03:55:00 +0000323 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000324
325 try {
326
327 // Try to create a regular expression
328 var check = new RegExp(json["value"]);
329
Nils Diewaldd0770492014-12-19 03:55:00 +0000330 if (!KorAP._validRegexMatchRE.test(this.matchop())) {
Nils Diewald3a2d8022014-12-16 02:45:41 +0000331 KorAP.log(802, "Match type is not supported by value type");
332 return;
333 };
334
Nils Diewaldd0770492014-12-19 03:55:00 +0000335 this.value(json["value"]);
Nils Diewald3a2d8022014-12-16 02:45:41 +0000336 }
Nils Diewaldd0770492014-12-19 03:55:00 +0000337
Nils Diewald3a2d8022014-12-16 02:45:41 +0000338 catch (e) {
339 KorAP.log(807, "Value is not a valid regular expression");
340 return;
341 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000342 this.type("regex");
Nils Diewald3a2d8022014-12-16 02:45:41 +0000343 }
344
345 else {
346 KorAP.log(804, "Unknown value type");
347 return;
348 };
349 };
350
351 return this;
352 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000353 key : function (value) {
354 if (arguments.length === 1)
355 this._key = value;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000356 return this._key;
357 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000358 matchop : function (match) {
359 if (arguments.length === 1)
360 this._matchop = match.replace(/^match:/, '');
Nils Diewald3a2d8022014-12-16 02:45:41 +0000361 return this._matchop || "eq";
362 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000363 type : function (type) {
364 if (arguments.length === 1)
365 this._type = type;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000366 return this._type || "string";
367 },
Nils Diewaldd0770492014-12-19 03:55:00 +0000368 value : function (value) {
369 if (arguments.length === 1)
370 this._value = value;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000371 return this._value;
372 },
Nils Diewald3a2d8022014-12-16 02:45:41 +0000373 toJson : function () {
Nils Diewaldd0770492014-12-19 03:55:00 +0000374 if (!this.matchop() || !this.key())
Nils Diewald3a2d8022014-12-16 02:45:41 +0000375 return {};
376
377 return {
Nils Diewaldd0770492014-12-19 03:55:00 +0000378 "@type" : "korap:" + this.ldType(),
379 "key" : this.key(),
380 "match" : "match:" + this.matchop(),
381 "value" : this.value() || '',
382 "type" : "type:" + this.type()
Nils Diewald3a2d8022014-12-16 02:45:41 +0000383 };
384 }
385 };
Nils Diewald8f4e2542014-12-19 04:42:09 +0000386
387 /**
388 * Virtual collection group criterion.
389 */
390 KorAP.DocGroup = {
391 _ldType : "docGroup",
392
393 create : function (parent, json) {
394 var obj = Object.create(KorAP.JsonLD).upgradeTo(KorAP.DocGroup);
395 obj._operands = [];
396 obj.fromJson(json);
397 if (parent !== undefined)
398 obj._parent = parent;
399 return obj;
400 },
401 appendOperand : function (operand) {
402 switch (operand["@type"]) {
403 case undefined:
404 if (operand["ldType"] !== undefined) {
405 if (operand.ldType() !== 'doc' &&
406 operand.ldType() !== 'docGroup') {
407 KorAP.log(812, "Operand not supported in document group");
408 return;
409 };
410 this._operands.push(operand);
411 return operand;
412 };
413
414 KorAP.log(701, "JSON-LD group has no @type attribute");
415 return;
416
417 case "korap:doc":
418 var doc = KorAP.Doc.create().fromJson(operand);
419 if (doc === undefined)
420 return;
421 this._operands.push(doc);
422 return doc;
423
424 case "korap:docGroup":
425 var docGroup = KorAP.DocGroup.create().fromJson(operand);
426 if (docGroup === undefined)
427 return;
428 this._operands.push(docGroup);
429 return docGroup;
430
431 default:
432 KorAP.log(812, "Operand not supported in document group");
433 return;
434 };
435 },
436 element : function () {
437 if (this._element !== undefined)
438 return this._element;
439
440 this._element = document.createElement('div');
441 this._element.setAttribute('class', 'docGroup');
442 this._element.setAttribute('data-operation', this.operation());
443
444 for (var i in this.operands()) {
445 this._element.appendChild(
446 this.getOperand(i).element()
447 );
448 };
449
450 return this._element;
451 },
452 operation : function (op) {
453 if (arguments.length === 1) {
454 if (KorAP._validGroupOpRE.test(op)) {
455 this._op = op;
456 }
457 else {
458 KorAP.log(810, "Unknown operation type");
459 return;
460 };
461 };
462 return this._op || 'and';
463 },
464 operands : function () {
465 return this._operands;
466 },
467 getOperand : function (index) {
468 return this._operands[index];
469 },
470
471 // Deserialize from json
472 fromJson : function (json) {
473 if (json === undefined)
474 return this;
475
476 if (json["@type"] !== "korap:docGroup") {
477 KorAP.log(701, "JSON-LD group has no @type attribute");
478 return;
479 };
480
481 if (json["operation"] === undefined ||
482 typeof json["operation"] !== 'string') {
483 KorAP.log(811, "Document group expects operation");
484 return;
485 };
486
487 var operation = json["operation"];
488
489 this.operation(operation.replace(/^operation:/,''));
490
491 if (json["operands"] === undefined ||
492 !(json["operands"] instanceof Array)) {
493 KorAP.log(704, "Operation needs operand list")
494 return;
495 };
496
497 // Add all documents
498 for (var i in json["operands"]) {
499 var operand = json["operands"][i];
500 this.appendOperand(operand);
501 };
502
503 return this;
504 },
505 toJson : function () {
506 var opArray = new Array();
507 for (var i in this._operands) {
508 opArray.push(this._operands[i].toJson());
509 };
510 return {
511 "@type" : "korap:" + this.ldType(),
512 "operation" : "operation:" + this.operation(),
513 "operands" : opArray
514 };
515 }
516 };
517
518
519 // Abstract JsonLD object
520 KorAP.JsonLD = {
521 create : function () {
522 return Object.create(KorAP.JsonLD);
523 },
524
525 /**
526 * Upgrade this object to another object
527 * while private data stays intact
528 */
529 upgradeTo : function (props) {
530 for (var prop in props) {
531 this[prop] = props[prop];
532 };
533 return this;
534 },
535 ldType : function (type) {
536 if (arguments.length === 1)
537 this._ldType = type;
538 return this._ldType;
539 },
540 parent : function (obj) {
541 if (arguments.length === 1)
542 this._parent = obj;
543 return this._parent;
544 }
545 };
546
Nils Diewald3a2d8022014-12-16 02:45:41 +0000547}(this.KorAP));