blob: 5cf2284b298ad0d3e860ea15721320082547b225 [file] [log] [blame]
Nils Diewald86dad5b2015-01-28 15:09:07 +00001/**
2 * Create virtual collections with a visual user interface.
Nils Diewald4c221252015-04-21 20:19:25 +00003 * This resembles the collection type objects of a KoralQuery
4 * "collection" object.
5 *
6 * KoralQuery v0.3 is expected.
Nils Diewald86dad5b2015-01-28 15:09:07 +00007 *
8 * @author Nils Diewald
9 */
Nils Diewald2fe12e12015-03-06 16:47:06 +000010/*
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000011 * This replaces a previous version written by Mengfei Zhou
Nils Diewald2fe12e12015-03-06 16:47:06 +000012 */
Nils Diewald2fe12e12015-03-06 16:47:06 +000013
Nils Diewaldd0770492014-12-19 03:55:00 +000014/*
Nils Diewald86dad5b2015-01-28 15:09:07 +000015 TODO: Disable "and" or "or" in case it's followed
16 by an unspecified document
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000017 TODO: Implement "persistence"-Option,
Nils Diewald6e43ffd2015-03-25 18:55:39 +000018 injecting the current creation date stamp
Nils Diewald86dad5b2015-01-28 15:09:07 +000019
Nils Diewaldd599d542015-01-08 20:41:34 +000020 Error codes:
Nils Diewaldd0770492014-12-19 03:55:00 +000021 701: "JSON-LD group has no @type attribute"
22 704: "Operation needs operand list"
Nils Diewald3a2d8022014-12-16 02:45:41 +000023 802: "Match type is not supported by value type"
24 804: "Unknown value type"
25 805: "Value is invalid"
26 806: "Value is not a valid date string"
27 807: "Value is not a valid regular expression"
Nils Diewald3a2d8022014-12-16 02:45:41 +000028 810: "Unknown document group operation" (like 711)
29 811: "Document group expects operation" (like 703)
30 812: "Operand not supported in document group" (like 744)
Nils Diewaldd0770492014-12-19 03:55:00 +000031 813: "Collection type is not supported" (like 713)
Nils Diewald86dad5b2015-01-28 15:09:07 +000032 814: "Unknown rewrite operation"
33 815: "Rewrite expects source"
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000034
35 Localization strings:
36 KorAP.Locale = {
37 EMPTY : '...',
38 AND : 'and',
39 OR : 'or',
40 DELETE : 'x'
41 }
Nils Diewald4c221252015-04-21 20:19:25 +000042 and various field names with the prefix 'VC_'
Nils Diewaldd0770492014-12-19 03:55:00 +000043*/
44
Nils Diewald0e6992a2015-04-14 20:13:52 +000045define([
46 'vc/unspecified',
47 'vc/doc',
48 'vc/docgroup',
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000049 'vc/menu',
Nils Diewald87507832015-05-01 23:36:41 +000050 'datepicker',
Nils Diewald0e6992a2015-04-14 20:13:52 +000051 'util'
Nils Diewald87507832015-05-01 23:36:41 +000052], function (unspecDocClass, docClass, docGroupClass, menuClass, dpClass) {
Nils Diewald3a2d8022014-12-16 02:45:41 +000053 "use strict";
54
Nils Diewald359a72c2015-04-20 17:40:29 +000055 // ???
Nils Diewald86dad5b2015-01-28 15:09:07 +000056 KorAP._validStringMatchRE = new RegExp("^(?:eq|ne|contains|excludes)$");
Nils Diewaldd0770492014-12-19 03:55:00 +000057 KorAP._validDateMatchRE = new RegExp("^[lg]?eq$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000058 KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
Nils Diewald359a72c2015-04-20 17:40:29 +000059 KorAP._overrideStyles = false;
Nils Diewald3a2d8022014-12-16 02:45:41 +000060
Nils Diewald359a72c2015-04-20 17:40:29 +000061 var loc = KorAP.Locale;
Nils Diewaldd599d542015-01-08 20:41:34 +000062
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000063 KorAP._vcKeyMenu = undefined;
Nils Diewald87507832015-05-01 23:36:41 +000064 KorAP._vcDatePicker = dpClass.create();
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000065
Nils Diewaldd599d542015-01-08 20:41:34 +000066 /**
67 * Virtual Collection
68 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000069 return {
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000070
71 /**
72 * The JSON-LD type of the virtual collection
73 */
Nils Diewaldf219eb82015-01-07 20:15:42 +000074 ldType : function () {
75 return null;
76 },
Nils Diewaldd599d542015-01-08 20:41:34 +000077
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000078 // Initialize virtual collection
79 _init : function (keyList) {
80
81 // Inject localized css styles
Nils Diewald359a72c2015-04-20 17:40:29 +000082 if (!KorAP._overrideStyles) {
83 var sheet = KorAP.newStyleSheet();
84
85 // Add css rule for OR operations
86 sheet.insertRule(
87 '.vc .docGroup[data-operation=or] > .doc::before,' +
88 '.vc .docGroup[data-operation=or] > .docGroup::before ' +
89 '{ content: "' + loc.OR + '" }',
90 0
91 );
92
93 // Add css rule for AND operations
94 sheet.insertRule(
95 '.vc .docGroup[data-operation=and] > .doc::before,' +
96 '.vc .docGroup[data-operation=and] > .docGroup::before ' +
97 '{ content: "' + loc.AND + '" }',
98 1
99 );
100
Nils Diewald359a72c2015-04-20 17:40:29 +0000101 KorAP._overrideStyles = true;
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000102
103 // Create key menu
104 KorAP._vcKeyMenu = menuClass.create(keyList);
Nils Diewald4c221252015-04-21 20:19:25 +0000105 KorAP._vcKeyMenu.limit(6);
106
107 // Create match menus ....
108 KorAP._vcMatchopMenu = {
109 'string' : menuClass.create([
110 ['eq', null],
111 ['ne', null],
112 ['contains', null],
113 ['excludes', null]
114 ]),
115 'date' : menuClass.create([
116 ['eq', null],
117 ['geq', null],
118 ['leq', null]
119 ]),
120 'regex' : menuClass.create([
121 ['eq', null],
122 ['ne', null],
123 ['contains', null],
124 ['excludes', null]
125 ])
126 };
Nils Diewald359a72c2015-04-20 17:40:29 +0000127 };
128
129 return this;
130 },
131
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000132 /**
133 * Create a new virtual collection.
134 */
135 create : function (keyList) {
Nils Diewald6283d692015-04-23 20:32:53 +0000136 var obj = Object.create(this)._init(keyList);
137 obj._root = unspecDocClass.create(obj);
138 return obj;
Nils Diewald4019bd22015-01-08 19:57:50 +0000139 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000140
Nils Diewald7148c6f2015-05-04 15:07:53 +0000141
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000142 /**
143 * Create and render a new virtual collection
144 * based on a KoralQuery collection document
145 */
Nils Diewald6283d692015-04-23 20:32:53 +0000146 fromJson : function (json) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000147
148 if (json !== undefined) {
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000149 // Parse root document
Nils Diewald2fe12e12015-03-06 16:47:06 +0000150 if (json['@type'] == 'koral:doc') {
Nils Diewald6283d692015-04-23 20:32:53 +0000151 this._root = docClass.create(this, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000152 }
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000153 // parse root group
Nils Diewald2fe12e12015-03-06 16:47:06 +0000154 else if (json['@type'] == 'koral:docGroup') {
Nils Diewald6283d692015-04-23 20:32:53 +0000155 this._root = docGroupClass.create(this, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000156 }
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000157 // Unknown collection type
Nils Diewaldd0770492014-12-19 03:55:00 +0000158 else {
159 KorAP.log(813, "Collection type is not supported");
160 return;
161 };
162 }
163
164 else {
165 // Add unspecified object
Nils Diewald6283d692015-04-23 20:32:53 +0000166 this._root = unspecDocClass.create(this);
Nils Diewaldd0770492014-12-19 03:55:00 +0000167 };
168
Nils Diewald8e7182e2015-01-08 15:02:07 +0000169 // Init element and update
Nils Diewald6283d692015-04-23 20:32:53 +0000170 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000171
Nils Diewald6283d692015-04-23 20:32:53 +0000172 return this;
173 },
174
Nils Diewald7148c6f2015-05-04 15:07:53 +0000175
176 /**
177 * Clean the virtual document to uspecified doc.
178 */
Nils Diewald6283d692015-04-23 20:32:53 +0000179 clean : function () {
180 if (this._root.ldType() !== "non") {
181 this._root.destroy();
182 this.root(unspecDocClass.create(this));
183 };
184 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000185 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000186
Nils Diewald7148c6f2015-05-04 15:07:53 +0000187
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000188 /**
189 * Get or set the root object of the
190 * virtual collection.
191 */
Nils Diewaldf219eb82015-01-07 20:15:42 +0000192 root : function (obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000193 if (arguments.length === 1) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000194 var e = this.element();
Nils Diewald845282c2015-05-14 07:53:03 +0000195
Nils Diewald8f6b6102015-01-08 18:25:33 +0000196 if (e.firstChild !== null) {
Nils Diewaldd5070b02015-01-11 01:44:47 +0000197 if (e.firstChild !== obj.element()) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000198 e.replaceChild(obj.element(), e.firstChild);
Nils Diewaldd5070b02015-01-11 01:44:47 +0000199 };
Nils Diewald8f6b6102015-01-08 18:25:33 +0000200 }
201
202 // Append root element
203 else {
204 e.appendChild(obj.element());
205 };
206
207 // Update parent child relations
Nils Diewaldf219eb82015-01-07 20:15:42 +0000208 this._root = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000209 obj.parent(this);
210
Nils Diewald8e7182e2015-01-08 15:02:07 +0000211 this.update();
212 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000213 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000214 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000215
Nils Diewald7148c6f2015-05-04 15:07:53 +0000216
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000217 /**
218 * Get the element associated with the virtual collection
219 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000220 element : function () {
221 if (this._element !== undefined)
222 return this._element;
223
224 this._element = document.createElement('div');
225 this._element.setAttribute('class', 'vc');
Nils Diewald8e7182e2015-01-08 15:02:07 +0000226
Nils Diewald8f6b6102015-01-08 18:25:33 +0000227 // Initialize root
228 this._element.appendChild(this._root.element());
Nils Diewald845282c2015-05-14 07:53:03 +0000229
Nils Diewaldd0770492014-12-19 03:55:00 +0000230 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000231 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000232
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000233
234 /**
235 * Update the whole object based on the underlying
236 * data structure
237 */
Nils Diewaldd599d542015-01-08 20:41:34 +0000238 update : function () {
239 this._root.update();
240 return this;
241 },
242
Nils Diewald845282c2015-05-14 07:53:03 +0000243 /**
244 * Make the vc persistant by injecting the current timestamp
245 * as a creation date limit criterion.
246 */
247 makePersistant : function () {
248// this.root().wrapOnRoot('and');
249 var todayStr = KorAP._vcDatePicker.today();
250 var doc = docClass.create();
251 var root = this.root();
252
253 if (root.ldType() === 'docGroup' &&
254 root.operation === 'and') {
255 root.append(cond);
256 }
257 else {
258 root.wrapOnRoot('and');
259 root.append(doc);
260 };
261
262 doc.key("creationDate");
263 doc.type("date");
264 doc.matchop("leq");
265 doc.value(todayStr);
266
267/*
268 {
269 "@type" : "koral:doc",
270 "key" : "creationDate",
271 "type" : "type:date",
272 "match" : "match:leq",
273 "value" : todayStr
274 }
275 this.root().append(cond);
276*/
277 this.update();
278 },
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000279
280 /**
281 * Get the generated json string
282 */
Nils Diewaldf219eb82015-01-07 20:15:42 +0000283 toJson : function () {
284 return this._root.toJson();
285 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000286
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000287
288 /**
289 * Get the generated query string
290 */
Nils Diewaldd599d542015-01-08 20:41:34 +0000291 toQuery : function () {
292 return this._root.toQuery();
Nils Diewald3a2d8022014-12-16 02:45:41 +0000293 }
294 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000295});