blob: b607f2c85567676857b3202108e02aae5d32cf1e [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 Diewald709f52f2015-05-21 18:32:58 +000019 TODO: Implement vec-Type for document-id vectors
20 like docID in [1,2,3,4 ...]
Nils Diewald86dad5b2015-01-28 15:09:07 +000021
Nils Diewaldd599d542015-01-08 20:41:34 +000022 Error codes:
Nils Diewaldd0770492014-12-19 03:55:00 +000023 701: "JSON-LD group has no @type attribute"
24 704: "Operation needs operand list"
Nils Diewald3a2d8022014-12-16 02:45:41 +000025 802: "Match type is not supported by value type"
26 804: "Unknown value type"
27 805: "Value is invalid"
28 806: "Value is not a valid date string"
29 807: "Value is not a valid regular expression"
Nils Diewald3a2d8022014-12-16 02:45:41 +000030 810: "Unknown document group operation" (like 711)
31 811: "Document group expects operation" (like 703)
32 812: "Operand not supported in document group" (like 744)
Nils Diewaldd0770492014-12-19 03:55:00 +000033 813: "Collection type is not supported" (like 713)
Nils Diewald86dad5b2015-01-28 15:09:07 +000034 814: "Unknown rewrite operation"
35 815: "Rewrite expects source"
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000036
37 Localization strings:
38 KorAP.Locale = {
39 EMPTY : '...',
40 AND : 'and',
41 OR : 'or',
42 DELETE : 'x'
43 }
Nils Diewald4c221252015-04-21 20:19:25 +000044 and various field names with the prefix 'VC_'
Nils Diewaldd0770492014-12-19 03:55:00 +000045*/
46
Nils Diewald0e6992a2015-04-14 20:13:52 +000047define([
48 'vc/unspecified',
49 'vc/doc',
50 'vc/docgroup',
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000051 'vc/menu',
Nils Diewald87507832015-05-01 23:36:41 +000052 'datepicker',
Nils Diewald0e6992a2015-04-14 20:13:52 +000053 'util'
Nils Diewald87507832015-05-01 23:36:41 +000054], function (unspecDocClass, docClass, docGroupClass, menuClass, dpClass) {
Nils Diewald3a2d8022014-12-16 02:45:41 +000055 "use strict";
56
Nils Diewald359a72c2015-04-20 17:40:29 +000057 // ???
Nils Diewald86dad5b2015-01-28 15:09:07 +000058 KorAP._validStringMatchRE = new RegExp("^(?:eq|ne|contains|excludes)$");
Nils Diewaldd0770492014-12-19 03:55:00 +000059 KorAP._validDateMatchRE = new RegExp("^[lg]?eq$");
Nils Diewald3a2d8022014-12-16 02:45:41 +000060 KorAP._validDateRE = new RegExp("^(?:\\d{4})(?:-\\d\\d(?:-\\d\\d)?)?$");
Nils Diewald359a72c2015-04-20 17:40:29 +000061 KorAP._overrideStyles = false;
Nils Diewald3a2d8022014-12-16 02:45:41 +000062
Nils Diewald359a72c2015-04-20 17:40:29 +000063 var loc = KorAP.Locale;
Nils Diewaldd599d542015-01-08 20:41:34 +000064
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000065 KorAP._vcKeyMenu = undefined;
Nils Diewald87507832015-05-01 23:36:41 +000066 KorAP._vcDatePicker = dpClass.create();
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000067
Nils Diewaldd599d542015-01-08 20:41:34 +000068 /**
69 * Virtual Collection
70 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000071 return {
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000072
73 /**
74 * The JSON-LD type of the virtual collection
75 */
Nils Diewaldf219eb82015-01-07 20:15:42 +000076 ldType : function () {
77 return null;
78 },
Nils Diewaldd599d542015-01-08 20:41:34 +000079
Nils Diewald1fcb2ad2015-04-20 19:19:18 +000080 // Initialize virtual collection
81 _init : function (keyList) {
82
83 // Inject localized css styles
Nils Diewald359a72c2015-04-20 17:40:29 +000084 if (!KorAP._overrideStyles) {
85 var sheet = KorAP.newStyleSheet();
86
87 // Add css rule for OR operations
88 sheet.insertRule(
89 '.vc .docGroup[data-operation=or] > .doc::before,' +
90 '.vc .docGroup[data-operation=or] > .docGroup::before ' +
91 '{ content: "' + loc.OR + '" }',
92 0
93 );
94
95 // Add css rule for AND operations
96 sheet.insertRule(
97 '.vc .docGroup[data-operation=and] > .doc::before,' +
98 '.vc .docGroup[data-operation=and] > .docGroup::before ' +
99 '{ content: "' + loc.AND + '" }',
100 1
101 );
102
Nils Diewald359a72c2015-04-20 17:40:29 +0000103 KorAP._overrideStyles = true;
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000104
105 // Create key menu
106 KorAP._vcKeyMenu = menuClass.create(keyList);
Nils Diewald4c221252015-04-21 20:19:25 +0000107 KorAP._vcKeyMenu.limit(6);
108
109 // Create match menus ....
110 KorAP._vcMatchopMenu = {
111 'string' : menuClass.create([
112 ['eq', null],
Akron179c8ac2015-06-30 19:30:50 +0200113 ['ne', null]
114/*
115 ,
Nils Diewald4c221252015-04-21 20:19:25 +0000116 ['contains', null],
117 ['excludes', null]
Akron179c8ac2015-06-30 19:30:50 +0200118*/
Nils Diewald4c221252015-04-21 20:19:25 +0000119 ]),
120 'date' : menuClass.create([
121 ['eq', null],
122 ['geq', null],
123 ['leq', null]
124 ]),
125 'regex' : menuClass.create([
126 ['eq', null],
Akron179c8ac2015-06-30 19:30:50 +0200127 ['ne', null]/*,
Nils Diewald4c221252015-04-21 20:19:25 +0000128 ['contains', null],
Akron179c8ac2015-06-30 19:30:50 +0200129 ['excludes', null]*/
Nils Diewald4c221252015-04-21 20:19:25 +0000130 ])
131 };
Nils Diewald359a72c2015-04-20 17:40:29 +0000132 };
133
134 return this;
135 },
136
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000137 /**
138 * Create a new virtual collection.
139 */
140 create : function (keyList) {
Nils Diewald6283d692015-04-23 20:32:53 +0000141 var obj = Object.create(this)._init(keyList);
142 obj._root = unspecDocClass.create(obj);
143 return obj;
Nils Diewald4019bd22015-01-08 19:57:50 +0000144 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000145
Nils Diewald7148c6f2015-05-04 15:07:53 +0000146
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000147 /**
148 * Create and render a new virtual collection
149 * based on a KoralQuery collection document
150 */
Nils Diewald6283d692015-04-23 20:32:53 +0000151 fromJson : function (json) {
Nils Diewaldd0770492014-12-19 03:55:00 +0000152
153 if (json !== undefined) {
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000154 // Parse root document
Nils Diewald2fe12e12015-03-06 16:47:06 +0000155 if (json['@type'] == 'koral:doc') {
Nils Diewald6283d692015-04-23 20:32:53 +0000156 this._root = docClass.create(this, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000157 }
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000158 // parse root group
Nils Diewald2fe12e12015-03-06 16:47:06 +0000159 else if (json['@type'] == 'koral:docGroup') {
Nils Diewald6283d692015-04-23 20:32:53 +0000160 this._root = docGroupClass.create(this, json);
Nils Diewaldd0770492014-12-19 03:55:00 +0000161 }
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000162 // Unknown collection type
Nils Diewaldd0770492014-12-19 03:55:00 +0000163 else {
164 KorAP.log(813, "Collection type is not supported");
165 return;
166 };
167 }
168
169 else {
170 // Add unspecified object
Nils Diewald6283d692015-04-23 20:32:53 +0000171 this._root = unspecDocClass.create(this);
Nils Diewaldd0770492014-12-19 03:55:00 +0000172 };
173
Nils Diewald8e7182e2015-01-08 15:02:07 +0000174 // Init element and update
Nils Diewald6283d692015-04-23 20:32:53 +0000175 this.update();
Nils Diewaldd0770492014-12-19 03:55:00 +0000176
Nils Diewald6283d692015-04-23 20:32:53 +0000177 return this;
178 },
179
Nils Diewald7148c6f2015-05-04 15:07:53 +0000180
181 /**
182 * Clean the virtual document to uspecified doc.
183 */
Nils Diewald6283d692015-04-23 20:32:53 +0000184 clean : function () {
185 if (this._root.ldType() !== "non") {
186 this._root.destroy();
187 this.root(unspecDocClass.create(this));
188 };
189 return this;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000190 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000191
Nils Diewald7148c6f2015-05-04 15:07:53 +0000192
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000193 /**
194 * Get or set the root object of the
195 * virtual collection.
196 */
Nils Diewaldf219eb82015-01-07 20:15:42 +0000197 root : function (obj) {
Nils Diewald8e7182e2015-01-08 15:02:07 +0000198 if (arguments.length === 1) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000199 var e = this.element();
Nils Diewald845282c2015-05-14 07:53:03 +0000200
Nils Diewald8f6b6102015-01-08 18:25:33 +0000201 if (e.firstChild !== null) {
Nils Diewaldd5070b02015-01-11 01:44:47 +0000202 if (e.firstChild !== obj.element()) {
Nils Diewald8f6b6102015-01-08 18:25:33 +0000203 e.replaceChild(obj.element(), e.firstChild);
Nils Diewaldd5070b02015-01-11 01:44:47 +0000204 };
Nils Diewald8f6b6102015-01-08 18:25:33 +0000205 }
206
207 // Append root element
208 else {
209 e.appendChild(obj.element());
210 };
211
212 // Update parent child relations
Nils Diewaldf219eb82015-01-07 20:15:42 +0000213 this._root = obj;
Nils Diewald8f6b6102015-01-08 18:25:33 +0000214 obj.parent(this);
215
Nils Diewald8e7182e2015-01-08 15:02:07 +0000216 this.update();
217 };
Nils Diewaldd0770492014-12-19 03:55:00 +0000218 return this._root;
Nils Diewald3a2d8022014-12-16 02:45:41 +0000219 },
Nils Diewald8f6b6102015-01-08 18:25:33 +0000220
Nils Diewald7148c6f2015-05-04 15:07:53 +0000221
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000222 /**
223 * Get the element associated with the virtual collection
224 */
Nils Diewaldd0770492014-12-19 03:55:00 +0000225 element : function () {
226 if (this._element !== undefined)
227 return this._element;
228
229 this._element = document.createElement('div');
230 this._element.setAttribute('class', 'vc');
Nils Diewald8e7182e2015-01-08 15:02:07 +0000231
Nils Diewald8f6b6102015-01-08 18:25:33 +0000232 // Initialize root
233 this._element.appendChild(this._root.element());
Nils Diewald845282c2015-05-14 07:53:03 +0000234
Nils Diewaldd0770492014-12-19 03:55:00 +0000235 return this._element;
Nils Diewaldf219eb82015-01-07 20:15:42 +0000236 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000237
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000238
239 /**
240 * Update the whole object based on the underlying
241 * data structure
242 */
Nils Diewaldd599d542015-01-08 20:41:34 +0000243 update : function () {
244 this._root.update();
245 return this;
246 },
247
Nils Diewald845282c2015-05-14 07:53:03 +0000248 /**
249 * Make the vc persistant by injecting the current timestamp
250 * as a creation date limit criterion.
251 */
252 makePersistant : function () {
253// this.root().wrapOnRoot('and');
254 var todayStr = KorAP._vcDatePicker.today();
255 var doc = docClass.create();
256 var root = this.root();
257
258 if (root.ldType() === 'docGroup' &&
259 root.operation === 'and') {
260 root.append(cond);
261 }
262 else {
263 root.wrapOnRoot('and');
264 root.append(doc);
265 };
266
267 doc.key("creationDate");
268 doc.type("date");
269 doc.matchop("leq");
270 doc.value(todayStr);
271
272/*
273 {
274 "@type" : "koral:doc",
275 "key" : "creationDate",
276 "type" : "type:date",
277 "match" : "match:leq",
278 "value" : todayStr
279 }
280 this.root().append(cond);
281*/
282 this.update();
283 },
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000284
285 /**
286 * Get the generated json string
287 */
Nils Diewaldf219eb82015-01-07 20:15:42 +0000288 toJson : function () {
289 return this._root.toJson();
290 },
Nils Diewaldd599d542015-01-08 20:41:34 +0000291
Nils Diewald1fcb2ad2015-04-20 19:19:18 +0000292
293 /**
294 * Get the generated query string
295 */
Nils Diewaldd599d542015-01-08 20:41:34 +0000296 toQuery : function () {
297 return this._root.toQuery();
Nils Diewald3a2d8022014-12-16 02:45:41 +0000298 }
299 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000300});