solid-ui 2.4.23 → 2.4.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +2159 -5039
- package/dist/main.js.map +1 -1
- package/lib/acl/access-controller.js +4 -67
- package/lib/acl/access-controller.js.map +1 -1
- package/lib/acl/access-groups.js +59 -137
- package/lib/acl/access-groups.js.map +1 -1
- package/lib/acl/acl-control.js +14 -54
- package/lib/acl/acl-control.js.map +1 -1
- package/lib/acl/acl.js +32 -107
- package/lib/acl/acl.js.map +1 -1
- package/lib/acl/add-agent-buttons.js +0 -92
- package/lib/acl/add-agent-buttons.js.map +1 -1
- package/lib/acl/index.js +1 -3
- package/lib/acl/index.js.map +1 -1
- package/lib/acl/styles.js +1 -2
- package/lib/acl/styles.js.map +1 -1
- package/lib/chat/bookmarks.js +8 -80
- package/lib/chat/bookmarks.js.map +1 -1
- package/lib/chat/chatLogic.js +109 -180
- package/lib/chat/chatLogic.js.map +1 -1
- package/lib/chat/dateFolder.js +6 -91
- package/lib/chat/dateFolder.js.map +1 -1
- package/lib/chat/infinite.js +33 -185
- package/lib/chat/infinite.js.map +1 -1
- package/lib/chat/message.js +37 -150
- package/lib/chat/message.js.map +1 -1
- package/lib/chat/messageTools.js +23 -96
- package/lib/chat/messageTools.js.map +1 -1
- package/lib/chat/thread.js +33 -91
- package/lib/chat/thread.js.map +1 -1
- package/lib/create/create.js +19 -51
- package/lib/create/create.js.map +1 -1
- package/lib/create/index.js +0 -2
- package/lib/create/index.js.map +1 -1
- package/lib/debug.js +0 -8
- package/lib/debug.js.map +1 -1
- package/lib/folders.js +4 -27
- package/lib/folders.js.map +1 -1
- package/lib/footer/index.js +2 -24
- package/lib/footer/index.js.map +1 -1
- package/lib/footer/styleMap.js.map +1 -1
- package/lib/header/empty-profile.js.map +1 -1
- package/lib/header/index.js +3 -72
- package/lib/header/index.js.map +1 -1
- package/lib/header/styleMap.js +4 -3
- package/lib/header/styleMap.js.map +1 -1
- package/lib/iconBase.js +3 -4
- package/lib/iconBase.js.map +1 -1
- package/lib/index.js +5 -46
- package/lib/index.js.map +1 -1
- package/lib/jss/index.js +3 -9
- package/lib/jss/index.js.map +1 -1
- package/lib/log.js +15 -51
- package/lib/log.js.map +1 -1
- package/lib/login/login.js +74 -303
- package/lib/login/login.js.map +1 -1
- package/lib/matrix/index.js +0 -2
- package/lib/matrix/index.js.map +1 -1
- package/lib/matrix/matrix.js +7 -55
- package/lib/matrix/matrix.js.map +1 -1
- package/lib/media/index.js +0 -2
- package/lib/media/index.js.map +1 -1
- package/lib/media/media-capture.js +13 -33
- package/lib/media/media-capture.js.map +1 -1
- package/lib/messageArea.js +23 -64
- package/lib/messageArea.js.map +1 -1
- package/lib/noun_Camera_1618446_000000.js.map +1 -1
- package/lib/ns.js +5 -7
- package/lib/ns.js.map +1 -1
- package/lib/pad.js +48 -234
- package/lib/pad.js.map +1 -1
- package/lib/participation.js +10 -65
- package/lib/participation.js.map +1 -1
- package/lib/preferences.js +21 -42
- package/lib/preferences.js.map +1 -1
- package/lib/signup/config-default.js +1 -8
- package/lib/signup/config-default.js.map +1 -1
- package/lib/signup/signup.js +6 -13
- package/lib/signup/signup.js.map +1 -1
- package/lib/stories/decorators.js +0 -2
- package/lib/stories/decorators.js.map +1 -1
- package/lib/style.js +8 -5
- package/lib/style.js.map +1 -1
- package/lib/style_multiSelect.js +1 -5
- package/lib/style_multiSelect.js.map +1 -1
- package/lib/table.js +309 -322
- package/lib/table.js.map +1 -1
- package/lib/tabs.js +20 -100
- package/lib/tabs.js.map +1 -1
- package/lib/utils/headerFooterHelpers.js +4 -52
- package/lib/utils/headerFooterHelpers.js.map +1 -1
- package/lib/utils/index.js +41 -135
- package/lib/utils/index.js.map +1 -1
- package/lib/utils/label.js +13 -34
- package/lib/utils/label.js.map +1 -1
- package/lib/versionInfo.js +4 -4
- package/lib/versionInfo.js.map +1 -1
- package/lib/widgets/buttons/iconLinks.js +0 -8
- package/lib/widgets/buttons/iconLinks.js.map +1 -1
- package/lib/widgets/buttons.js +115 -291
- package/lib/widgets/buttons.js.map +1 -1
- package/lib/widgets/dragAndDrop.js +12 -41
- package/lib/widgets/dragAndDrop.js.map +1 -1
- package/lib/widgets/error.js +3 -9
- package/lib/widgets/error.js.map +1 -1
- package/lib/widgets/forms/autocomplete/autocompleteBar.js +8 -71
- package/lib/widgets/forms/autocomplete/autocompleteBar.js.map +1 -1
- package/lib/widgets/forms/autocomplete/autocompleteField.js +13 -65
- package/lib/widgets/forms/autocomplete/autocompleteField.js.map +1 -1
- package/lib/widgets/forms/autocomplete/autocompletePicker.js +15 -107
- package/lib/widgets/forms/autocomplete/autocompletePicker.js.map +1 -1
- package/lib/widgets/forms/autocomplete/language.js +6 -55
- package/lib/widgets/forms/autocomplete/language.js.map +1 -1
- package/lib/widgets/forms/autocomplete/publicData.js +12 -131
- package/lib/widgets/forms/autocomplete/publicData.js.map +1 -1
- package/lib/widgets/forms/basic.js +12 -55
- package/lib/widgets/forms/basic.js.map +1 -1
- package/lib/widgets/forms/comment.js +1 -15
- package/lib/widgets/forms/comment.js.map +1 -1
- package/lib/widgets/forms/fieldFunction.js +3 -16
- package/lib/widgets/forms/fieldFunction.js.map +1 -1
- package/lib/widgets/forms/fieldParams.js +0 -12
- package/lib/widgets/forms/fieldParams.js.map +1 -1
- package/lib/widgets/forms/formStyle.js +1 -14
- package/lib/widgets/forms/formStyle.js.map +1 -1
- package/lib/widgets/forms.js +70 -474
- package/lib/widgets/forms.js.map +1 -1
- package/lib/widgets/index.js +0 -21
- package/lib/widgets/index.js.map +1 -1
- package/lib/widgets/multiSelect.js +48 -171
- package/lib/widgets/multiSelect.js.map +1 -1
- package/lib/widgets/peoplePicker.js +20 -90
- package/lib/widgets/peoplePicker.js.map +1 -1
- package/lib/widgets/widgetHelpers.js +2 -9
- package/lib/widgets/widgetHelpers.js.map +1 -1
- package/package.json +28 -28
package/lib/table.js
CHANGED
|
@@ -1,32 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
4
|
-
|
|
5
4
|
Object.defineProperty(exports, "__esModule", {
|
|
6
5
|
value: true
|
|
7
6
|
});
|
|
8
7
|
exports.renderTableViewPane = renderTableViewPane;
|
|
9
|
-
|
|
10
8
|
var debug = _interopRequireWildcard(require("./debug"));
|
|
11
|
-
|
|
12
9
|
var _iconBase = require("./iconBase");
|
|
13
|
-
|
|
14
10
|
var _solidLogic = require("solid-logic");
|
|
15
|
-
|
|
16
11
|
var log = _interopRequireWildcard(require("./log"));
|
|
17
|
-
|
|
18
12
|
var ns = _interopRequireWildcard(require("./ns"));
|
|
19
|
-
|
|
20
13
|
var rdf = _interopRequireWildcard(require("rdflib"));
|
|
21
|
-
|
|
22
14
|
var utils = _interopRequireWildcard(require("./utils"));
|
|
23
|
-
|
|
24
15
|
var widgets = _interopRequireWildcard(require("./widgets"));
|
|
25
|
-
|
|
26
16
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
27
|
-
|
|
28
17
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
29
|
-
|
|
30
18
|
// Table Widget: Format an array of RDF statements as an HTML table.
|
|
31
19
|
//
|
|
32
20
|
// This can operate in one of three modes: when the class of object is given
|
|
@@ -41,15 +29,18 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
41
29
|
// 2008 Written, Ilaria Liccardi as the tableViewPane.js
|
|
42
30
|
// 2014 Core table widget moved into common/table.js - timbl
|
|
43
31
|
//
|
|
32
|
+
|
|
44
33
|
// pull in first avoid cross-refs
|
|
34
|
+
|
|
45
35
|
var UI = {
|
|
46
36
|
icons: _iconBase.icons,
|
|
47
37
|
log: log,
|
|
48
38
|
ns: ns,
|
|
49
39
|
utils: utils,
|
|
50
40
|
widgets: widgets
|
|
51
|
-
};
|
|
41
|
+
};
|
|
52
42
|
|
|
43
|
+
// UI.widgets.renderTableViewPane
|
|
53
44
|
function renderTableViewPane(doc, options) {
|
|
54
45
|
var sourceDocument = options.sourceDocument;
|
|
55
46
|
var tableClass = options.tableClass;
|
|
@@ -58,12 +49,15 @@ function renderTableViewPane(doc, options) {
|
|
|
58
49
|
var ns = UI.ns;
|
|
59
50
|
var kb = _solidLogic.store;
|
|
60
51
|
var rowsLookup = {}; // Persistent mapping of subject URI to dom TR
|
|
52
|
+
|
|
61
53
|
// Predicates that are never made into columns:
|
|
62
54
|
|
|
63
55
|
var FORBIDDEN_COLUMNS = {
|
|
64
56
|
'http://www.w3.org/2002/07/owl#sameAs': true,
|
|
65
57
|
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': true
|
|
66
|
-
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Number types defined in the XML schema:
|
|
67
61
|
|
|
68
62
|
var XSD_NUMBER_TYPES = {
|
|
69
63
|
'http://www.w3.org/2001/XMLSchema#decimal': true,
|
|
@@ -86,12 +80,16 @@ function renderTableViewPane(doc, options) {
|
|
|
86
80
|
var XSD_DATE_TYPES = {
|
|
87
81
|
'http://www.w3.org/2001/XMLSchema#dateTime': true,
|
|
88
82
|
'http://www.w3.org/2001/XMLSchema#date': true
|
|
89
|
-
};
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Classes that indicate an image:
|
|
90
86
|
|
|
91
87
|
var IMAGE_TYPES = {
|
|
92
88
|
'http://xmlns.com/foaf/0.1/Image': true,
|
|
93
89
|
'http://purl.org/dc/terms/Image': true
|
|
94
|
-
};
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Name of the column used as a "key" value to look up the row.
|
|
95
93
|
// This is necessary because in the normal view, the columns are
|
|
96
94
|
// all "optional" values, meaning that we will get a result set
|
|
97
95
|
// for every individual value that is found. The row key acts
|
|
@@ -101,8 +99,9 @@ function renderTableViewPane(doc, options) {
|
|
|
101
99
|
var keyVariable = options.keyVariable || '?_row';
|
|
102
100
|
var subjectIdCounter = 0;
|
|
103
101
|
var allType, types;
|
|
104
|
-
var typeSelectorDiv, addColumnDiv;
|
|
102
|
+
var typeSelectorDiv, addColumnDiv;
|
|
105
103
|
|
|
104
|
+
// The last SPARQL query used:
|
|
106
105
|
var lastQuery = null;
|
|
107
106
|
var mostCommonType = null;
|
|
108
107
|
var resultDiv = doc.createElement('div');
|
|
@@ -110,40 +109,39 @@ function renderTableViewPane(doc, options) {
|
|
|
110
109
|
resultDiv.appendChild(generateControlBar()); // sets typeSelectorDiv
|
|
111
110
|
|
|
112
111
|
var tableDiv = doc.createElement('div');
|
|
113
|
-
resultDiv.appendChild(tableDiv);
|
|
112
|
+
resultDiv.appendChild(tableDiv);
|
|
114
113
|
|
|
114
|
+
// Save a refresh function for use by caller
|
|
115
115
|
resultDiv.refresh = function () {
|
|
116
|
-
runQuery(table.query, table.logicalRows, table.columns, table);
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
runQuery(table.query, table.logicalRows, table.columns, table);
|
|
117
|
+
// updateTable(givenQuery, mostCommonType) // This could be a lot more incremental and efficient
|
|
118
|
+
};
|
|
119
119
|
|
|
120
|
+
// A specifically asked-for query
|
|
120
121
|
var table;
|
|
121
|
-
|
|
122
122
|
if (givenQuery) {
|
|
123
|
-
table = renderTableForQuery(givenQuery);
|
|
124
|
-
|
|
123
|
+
table = renderTableForQuery(givenQuery);
|
|
124
|
+
// lastQuery = givenQuery
|
|
125
125
|
tableDiv.appendChild(table);
|
|
126
126
|
} else {
|
|
127
127
|
// Find the most common type and select it by default
|
|
128
|
+
|
|
128
129
|
var s = calculateTable();
|
|
129
130
|
allType = s[0];
|
|
130
131
|
types = s[1];
|
|
131
|
-
|
|
132
132
|
if (!tableClass) {
|
|
133
133
|
typeSelectorDiv.appendChild(generateTypeSelector(allType, types));
|
|
134
134
|
}
|
|
135
|
-
|
|
136
135
|
mostCommonType = getMostCommonType(types);
|
|
137
|
-
|
|
138
136
|
if (mostCommonType) {
|
|
139
137
|
buildFilteredTable(mostCommonType);
|
|
140
138
|
} else {
|
|
141
139
|
buildFilteredTable(allType);
|
|
142
140
|
}
|
|
143
141
|
}
|
|
142
|
+
return resultDiv;
|
|
144
143
|
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
// /////////////////////////////////////////////////////////////////
|
|
147
145
|
/*
|
|
148
146
|
function closeDialog (dialog) {
|
|
149
147
|
dialog.parentNode.removeChild(dialog)
|
|
@@ -196,58 +194,60 @@ function renderTableViewPane(doc, options) {
|
|
|
196
194
|
var result = doc.createElement('table');
|
|
197
195
|
result.setAttribute('class', 'toolbar');
|
|
198
196
|
var tr = doc.createElement('tr');
|
|
197
|
+
|
|
199
198
|
/* @@ Add in later -- not debugged yet
|
|
200
199
|
var sparqlButtonDiv = doc.createElement("td")
|
|
201
200
|
sparqlButtonDiv.appendChild(generateSparqlButton())
|
|
202
201
|
tr.appendChild(sparqlButtonDiv)
|
|
203
202
|
*/
|
|
204
|
-
|
|
205
203
|
typeSelectorDiv = doc.createElement('td');
|
|
206
204
|
tr.appendChild(typeSelectorDiv);
|
|
207
205
|
addColumnDiv = doc.createElement('td');
|
|
208
206
|
tr.appendChild(addColumnDiv);
|
|
209
207
|
result.appendChild(tr);
|
|
210
208
|
return result;
|
|
211
|
-
}
|
|
209
|
+
}
|
|
212
210
|
|
|
211
|
+
// Add the SELECT details to the query being built.
|
|
213
212
|
|
|
214
213
|
function addSelectToQuery(query, type) {
|
|
215
214
|
var selectedColumns = type.getColumns();
|
|
216
|
-
|
|
217
215
|
for (var i = 0; i < selectedColumns.length; ++i) {
|
|
218
216
|
// TODO: autogenerate nicer names for variables
|
|
219
217
|
// variables have to be unambiguous
|
|
218
|
+
|
|
220
219
|
var variable = kb.variable('_col' + i);
|
|
221
220
|
query.vars.push(variable);
|
|
222
221
|
selectedColumns[i].setVariable(variable);
|
|
223
222
|
}
|
|
224
|
-
}
|
|
223
|
+
}
|
|
225
224
|
|
|
225
|
+
// Add WHERE details to the query being built.
|
|
226
226
|
|
|
227
227
|
function addWhereToQuery(query, rowVar, type) {
|
|
228
228
|
var queryType = type.type;
|
|
229
|
-
|
|
230
229
|
if (!queryType) {
|
|
231
230
|
queryType = kb.variable('_any');
|
|
232
|
-
}
|
|
233
|
-
|
|
231
|
+
}
|
|
234
232
|
|
|
233
|
+
// _row a type
|
|
235
234
|
query.pat.add(rowVar, UI.ns.rdf('type'), queryType);
|
|
236
|
-
}
|
|
235
|
+
}
|
|
237
236
|
|
|
237
|
+
// Generate OPTIONAL column selectors.
|
|
238
238
|
|
|
239
239
|
function addColumnsToQuery(query, rowVar, type) {
|
|
240
240
|
var selectedColumns = type.getColumns();
|
|
241
|
-
|
|
242
241
|
for (var i = 0; i < selectedColumns.length; ++i) {
|
|
243
242
|
var column = selectedColumns[i];
|
|
244
243
|
var formula = kb.formula();
|
|
245
244
|
formula.add(rowVar, column.predicate, column.getVariable());
|
|
246
245
|
query.pat.optional.push(formula);
|
|
247
246
|
}
|
|
248
|
-
}
|
|
249
|
-
// object.
|
|
247
|
+
}
|
|
250
248
|
|
|
249
|
+
// Generate a query object from the currently-selected type
|
|
250
|
+
// object.
|
|
251
251
|
|
|
252
252
|
function generateQuery(type) {
|
|
253
253
|
var query = new rdf.Query();
|
|
@@ -257,112 +257,130 @@ function renderTableViewPane(doc, options) {
|
|
|
257
257
|
addWhereToQuery(query, rowVar, type);
|
|
258
258
|
addColumnsToQuery(query, rowVar, type);
|
|
259
259
|
return query;
|
|
260
|
-
}
|
|
261
|
-
// to the specified type.
|
|
260
|
+
}
|
|
262
261
|
|
|
262
|
+
// Build the contents of the tableDiv element, filtered according
|
|
263
|
+
// to the specified type.
|
|
263
264
|
|
|
264
265
|
function buildFilteredTable(type) {
|
|
265
266
|
// Generate "add column" cell.
|
|
267
|
+
|
|
266
268
|
clearElement(addColumnDiv);
|
|
267
269
|
addColumnDiv.appendChild(generateColumnAddDropdown(type));
|
|
268
270
|
var query = generateQuery(type);
|
|
269
271
|
updateTable(query, type);
|
|
270
272
|
}
|
|
271
|
-
|
|
272
273
|
function updateTable(query, type) {
|
|
273
274
|
// Stop the previous query from doing any updates.
|
|
275
|
+
|
|
274
276
|
if (lastQuery) {
|
|
275
277
|
lastQuery.running = false;
|
|
276
|
-
}
|
|
278
|
+
}
|
|
277
279
|
|
|
280
|
+
// Render the HTML table.
|
|
278
281
|
|
|
279
|
-
var htmlTable = renderTableForQuery(query, type);
|
|
282
|
+
var htmlTable = renderTableForQuery(query, type);
|
|
283
|
+
|
|
284
|
+
// Clear the tableDiv element, and replace with the new table.
|
|
280
285
|
|
|
281
286
|
clearElement(tableDiv);
|
|
282
|
-
tableDiv.appendChild(htmlTable);
|
|
287
|
+
tableDiv.appendChild(htmlTable);
|
|
288
|
+
|
|
289
|
+
// Save the query for the edit dialog.
|
|
283
290
|
|
|
284
291
|
lastQuery = query;
|
|
285
|
-
}
|
|
292
|
+
}
|
|
286
293
|
|
|
294
|
+
// Remove all subelements of the specified element.
|
|
287
295
|
|
|
288
296
|
function clearElement(element) {
|
|
289
297
|
while (element.childNodes.length > 0) {
|
|
290
298
|
element.removeChild(element.childNodes[0]);
|
|
291
299
|
}
|
|
292
|
-
}
|
|
300
|
+
}
|
|
293
301
|
|
|
302
|
+
// A SubjectType is created for each rdf:type discovered.
|
|
294
303
|
|
|
295
304
|
function SubjectType(type) {
|
|
296
305
|
this.type = type;
|
|
297
306
|
this.columns = null;
|
|
298
307
|
this.allColumns = [];
|
|
299
|
-
this.useCount = 0;
|
|
308
|
+
this.useCount = 0;
|
|
309
|
+
|
|
310
|
+
// Get a list of all columns used by this type.
|
|
300
311
|
|
|
301
312
|
this.getAllColumns = function () {
|
|
302
313
|
return this.allColumns;
|
|
303
|
-
};
|
|
304
|
-
// (subset of allColumns)
|
|
314
|
+
};
|
|
305
315
|
|
|
316
|
+
// Get a list of the current columns used by this type
|
|
317
|
+
// (subset of allColumns)
|
|
306
318
|
|
|
307
319
|
this.getColumns = function () {
|
|
308
320
|
// The first time through, get a list of all the columns
|
|
309
321
|
// and select only the six most popular columns.
|
|
322
|
+
|
|
310
323
|
if (!this.columns) {
|
|
311
324
|
var allColumns = this.getAllColumns();
|
|
312
325
|
this.columns = allColumns.slice(0, 7);
|
|
313
326
|
}
|
|
314
|
-
|
|
315
327
|
return this.columns;
|
|
316
|
-
};
|
|
328
|
+
};
|
|
317
329
|
|
|
330
|
+
// Get a list of unused columns
|
|
318
331
|
|
|
319
332
|
this.getUnusedColumns = function () {
|
|
320
333
|
var allColumns = this.getAllColumns();
|
|
321
334
|
var columns = this.getColumns();
|
|
322
335
|
var result = [];
|
|
323
|
-
|
|
324
336
|
for (var i = 0; i < allColumns.length; ++i) {
|
|
325
337
|
if (columns.indexOf(allColumns[i]) === -1) {
|
|
326
338
|
result.push(allColumns[i]);
|
|
327
339
|
}
|
|
328
340
|
}
|
|
329
|
-
|
|
330
341
|
return result;
|
|
331
342
|
};
|
|
332
|
-
|
|
333
343
|
this.addColumn = function (column) {
|
|
334
344
|
this.columns.push(column);
|
|
335
345
|
};
|
|
336
|
-
|
|
337
346
|
this.removeColumn = function (column) {
|
|
338
347
|
this.columns = this.columns.filter(function (x) {
|
|
339
348
|
return x !== column;
|
|
340
349
|
});
|
|
341
350
|
};
|
|
342
|
-
|
|
343
351
|
this.getLabel = function () {
|
|
344
352
|
return utils.label(this.type);
|
|
345
353
|
};
|
|
346
|
-
|
|
347
354
|
this.addUse = function () {
|
|
348
355
|
this.useCount += 1;
|
|
349
356
|
};
|
|
350
|
-
}
|
|
357
|
+
}
|
|
351
358
|
|
|
359
|
+
// Class representing a column in the table.
|
|
352
360
|
|
|
353
361
|
function Column() {
|
|
354
|
-
this.useCount = 0;
|
|
362
|
+
this.useCount = 0;
|
|
363
|
+
|
|
364
|
+
// Have we checked any values for this column yet?
|
|
355
365
|
|
|
356
|
-
this.checkedAnyValues = false;
|
|
366
|
+
this.checkedAnyValues = false;
|
|
367
|
+
|
|
368
|
+
// If the range is unknown, but we just get literals in this
|
|
357
369
|
// column, then we can generate a literal selector.
|
|
358
370
|
|
|
359
|
-
this.possiblyLiteral = true;
|
|
371
|
+
this.possiblyLiteral = true;
|
|
372
|
+
|
|
373
|
+
// If the range is unknown, but we just get literals and they
|
|
360
374
|
// match the regular expression for numbers, we can generate
|
|
361
375
|
// a number selector.
|
|
362
376
|
|
|
363
|
-
this.possiblyNumber = true;
|
|
377
|
+
this.possiblyNumber = true;
|
|
378
|
+
|
|
379
|
+
// We accumulate classes which things in the column must be a member of
|
|
364
380
|
|
|
365
|
-
this.constraints = [];
|
|
381
|
+
this.constraints = [];
|
|
382
|
+
|
|
383
|
+
// Check values as they are read. If we don't know what the
|
|
366
384
|
// range is, we might be able to infer that it is a literal
|
|
367
385
|
// if all of the values are literals. Similarly, we might
|
|
368
386
|
// be able to determine if the literal values are actually
|
|
@@ -370,7 +388,6 @@ function renderTableViewPane(doc, options) {
|
|
|
370
388
|
|
|
371
389
|
this.checkValue = function (term) {
|
|
372
390
|
var termType = term.termType;
|
|
373
|
-
|
|
374
391
|
if (this.possiblyLiteral && termType !== 'Literal' && termType !== 'NamedNode') {
|
|
375
392
|
this.possiblyNumber = false;
|
|
376
393
|
this.possiblyLiteral = false;
|
|
@@ -379,45 +396,35 @@ function renderTableViewPane(doc, options) {
|
|
|
379
396
|
this.possiblyNumber = false;
|
|
380
397
|
} else {
|
|
381
398
|
var literalValue = term.value;
|
|
382
|
-
|
|
383
399
|
if (!literalValue.match(/^-?\d+(\.\d*)?$/)) {
|
|
384
400
|
this.possiblyNumber = false;
|
|
385
401
|
}
|
|
386
402
|
}
|
|
387
403
|
}
|
|
388
|
-
|
|
389
404
|
this.checkedAnyValues = true;
|
|
390
405
|
};
|
|
391
|
-
|
|
392
406
|
this.getVariable = function () {
|
|
393
407
|
return this.variable;
|
|
394
408
|
};
|
|
395
|
-
|
|
396
409
|
this.setVariable = function (variable) {
|
|
397
410
|
this.variable = variable;
|
|
398
411
|
};
|
|
399
|
-
|
|
400
412
|
this.getKey = function () {
|
|
401
413
|
return this.variable.toString();
|
|
402
414
|
};
|
|
403
|
-
|
|
404
415
|
this.addUse = function () {
|
|
405
416
|
this.useCount += 1;
|
|
406
417
|
};
|
|
407
|
-
|
|
408
418
|
this.getHints = function () {
|
|
409
419
|
if (options && options.hints && this.variable && options.hints[this.variable.toNT()]) {
|
|
410
420
|
return options.hints[this.variable.toNT()];
|
|
411
421
|
}
|
|
412
|
-
|
|
413
422
|
return {};
|
|
414
423
|
};
|
|
415
|
-
|
|
416
424
|
this.getLabel = function () {
|
|
417
425
|
if (this.getHints().label) {
|
|
418
426
|
return this.getHints().label;
|
|
419
427
|
}
|
|
420
|
-
|
|
421
428
|
if (this.predicate) {
|
|
422
429
|
if (this.predicate.sameTerm(ns.rdf('type')) && this.superClass) {
|
|
423
430
|
return utils.label(this.superClass, true); // do initial cap
|
|
@@ -430,13 +437,11 @@ function renderTableViewPane(doc, options) {
|
|
|
430
437
|
return 'unlabeled column?';
|
|
431
438
|
}
|
|
432
439
|
};
|
|
433
|
-
|
|
434
440
|
this.setPredicate = function (predicate, inverse, other) {
|
|
435
441
|
if (inverse) {
|
|
436
442
|
// variable is in the subject pos
|
|
437
443
|
this.inverse = predicate;
|
|
438
444
|
this.constraints = this.constraints.concat(kb.each(predicate, UI.ns.rdfs('domain')));
|
|
439
|
-
|
|
440
445
|
if (predicate.sameTerm(ns.rdfs('subClassOf')) && other.termType === 'NamedNode') {
|
|
441
446
|
this.superClass = other;
|
|
442
447
|
this.alternatives = kb.each(undefined, ns.rdfs('subClassOf'), other);
|
|
@@ -447,83 +452,76 @@ function renderTableViewPane(doc, options) {
|
|
|
447
452
|
this.constraints = this.constraints.concat(kb.each(predicate, UI.ns.rdfs('range')));
|
|
448
453
|
}
|
|
449
454
|
};
|
|
450
|
-
|
|
451
455
|
this.getConstraints = function () {
|
|
452
456
|
return this.constraints;
|
|
453
457
|
};
|
|
454
|
-
|
|
455
458
|
this.filterFunction = function () {
|
|
456
459
|
return true;
|
|
457
460
|
};
|
|
458
|
-
|
|
459
461
|
this.sortKey = function () {
|
|
460
462
|
return this.getLabel().toLowerCase();
|
|
461
463
|
};
|
|
462
|
-
|
|
463
464
|
this.isImageColumn = function () {
|
|
464
465
|
for (var i = 0; i < this.constraints.length; i++) {
|
|
465
466
|
if (this.constraints[i].uri in IMAGE_TYPES) return true;
|
|
466
467
|
}
|
|
467
|
-
|
|
468
468
|
return false;
|
|
469
469
|
};
|
|
470
|
-
}
|
|
470
|
+
}
|
|
471
471
|
|
|
472
|
+
// Convert an object to an array.
|
|
472
473
|
|
|
473
474
|
function objectToArray(obj, filter) {
|
|
474
475
|
var result = [];
|
|
475
|
-
|
|
476
476
|
for (var property in obj) {
|
|
477
477
|
// @@@ have to guard against methods
|
|
478
478
|
var value = obj[property];
|
|
479
|
-
|
|
480
479
|
if (!filter || filter(property, value)) {
|
|
481
480
|
result.push(value);
|
|
482
481
|
}
|
|
483
482
|
}
|
|
484
|
-
|
|
485
483
|
return result;
|
|
486
|
-
}
|
|
484
|
+
}
|
|
487
485
|
|
|
486
|
+
// Generate an <option> in a drop-down list.
|
|
488
487
|
|
|
489
488
|
function optionElement(label, value) {
|
|
490
489
|
var result = doc.createElement('option');
|
|
491
490
|
result.setAttribute('value', value);
|
|
492
491
|
result.appendChild(doc.createTextNode(label));
|
|
493
492
|
return result;
|
|
494
|
-
}
|
|
493
|
+
}
|
|
495
494
|
|
|
495
|
+
// Generate drop-down list box for choosing type of data displayed
|
|
496
496
|
|
|
497
497
|
function generateTypeSelector(allType, types) {
|
|
498
498
|
var resultDiv = doc.createElement('div');
|
|
499
499
|
resultDiv.appendChild(doc.createTextNode('Select type: '));
|
|
500
500
|
var dropdown = doc.createElement('select');
|
|
501
501
|
dropdown.appendChild(optionElement('All types', 'null'));
|
|
502
|
-
|
|
503
502
|
for (var uri in types) {
|
|
504
503
|
dropdown.appendChild(optionElement(types[uri].getLabel(), uri));
|
|
505
504
|
}
|
|
506
|
-
|
|
507
505
|
dropdown.addEventListener('click', function () {
|
|
508
506
|
var type;
|
|
509
|
-
|
|
510
507
|
if (dropdown.value === 'null') {
|
|
511
508
|
type = allType;
|
|
512
509
|
} else {
|
|
513
510
|
type = types[dropdown.value];
|
|
514
511
|
}
|
|
515
|
-
|
|
516
512
|
typeSelectorChanged(type);
|
|
517
513
|
}, false);
|
|
518
514
|
resultDiv.appendChild(dropdown);
|
|
519
515
|
return resultDiv;
|
|
520
|
-
}
|
|
516
|
+
}
|
|
521
517
|
|
|
518
|
+
// Callback invoked when the type selector drop-down list is changed.
|
|
522
519
|
|
|
523
520
|
function typeSelectorChanged(selectedType) {
|
|
524
521
|
buildFilteredTable(selectedType);
|
|
525
|
-
}
|
|
522
|
+
}
|
|
526
523
|
|
|
524
|
+
// Build drop-down list to add a new column
|
|
527
525
|
|
|
528
526
|
function generateColumnAddDropdown(type) {
|
|
529
527
|
var resultDiv = doc.createElement('div');
|
|
@@ -532,53 +530,55 @@ function renderTableViewPane(doc, options) {
|
|
|
532
530
|
var aLabel = a.sortKey();
|
|
533
531
|
var bLabel = b.sortKey();
|
|
534
532
|
return (aLabel > bLabel) - (aLabel < bLabel);
|
|
535
|
-
});
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
// If there are no unused columns, the div is empty.
|
|
536
536
|
|
|
537
537
|
if (unusedColumns.length > 0) {
|
|
538
|
-
resultDiv.appendChild(doc.createTextNode('Add column: '));
|
|
538
|
+
resultDiv.appendChild(doc.createTextNode('Add column: '));
|
|
539
|
+
|
|
540
|
+
// Build dropdown list of unused columns.
|
|
539
541
|
|
|
540
542
|
var dropdown = doc.createElement('select');
|
|
541
543
|
dropdown.appendChild(optionElement('', '-1'));
|
|
542
|
-
|
|
543
544
|
for (var i = 0; i < unusedColumns.length; ++i) {
|
|
544
545
|
var column = unusedColumns[i];
|
|
545
546
|
dropdown.appendChild(optionElement(column.getLabel(), '' + i));
|
|
546
547
|
}
|
|
548
|
+
resultDiv.appendChild(dropdown);
|
|
547
549
|
|
|
548
|
-
|
|
550
|
+
// Invoke callback when the dropdown is changed, to add
|
|
549
551
|
// the column and reload the table.
|
|
550
552
|
|
|
551
553
|
dropdown.addEventListener('click', function () {
|
|
552
554
|
var columnIndex = Number(dropdown.value);
|
|
553
|
-
|
|
554
555
|
if (columnIndex >= 0) {
|
|
555
556
|
type.addColumn(unusedColumns[columnIndex]);
|
|
556
557
|
buildFilteredTable(type);
|
|
557
558
|
}
|
|
558
559
|
}, false);
|
|
559
560
|
}
|
|
560
|
-
|
|
561
561
|
return resultDiv;
|
|
562
|
-
}
|
|
562
|
+
}
|
|
563
563
|
|
|
564
|
+
// Find the column for a given variable
|
|
564
565
|
|
|
565
566
|
function getColumnForVariable(columns, variableNT) {
|
|
566
567
|
for (var predicateUri in columns) {
|
|
567
568
|
var column = columns[predicateUri];
|
|
568
|
-
|
|
569
569
|
if (column.variable.toNT() === variableNT) {
|
|
570
570
|
return column;
|
|
571
571
|
}
|
|
572
572
|
}
|
|
573
|
+
throw new Error("getColumnForVariable: no column for variable ".concat(variableNT));
|
|
574
|
+
// return null
|
|
575
|
+
}
|
|
573
576
|
|
|
574
|
-
|
|
575
|
-
} // Find the column for a given predicate, creating a new column object
|
|
577
|
+
// Find the column for a given predicate, creating a new column object
|
|
576
578
|
// if necessary.
|
|
577
579
|
|
|
578
|
-
|
|
579
580
|
function getColumnForPredicate(columns, predicate) {
|
|
580
581
|
var column;
|
|
581
|
-
|
|
582
582
|
if (predicate.uri in columns) {
|
|
583
583
|
column = columns[predicate.uri];
|
|
584
584
|
} else {
|
|
@@ -586,134 +586,139 @@ function renderTableViewPane(doc, options) {
|
|
|
586
586
|
column.setPredicate(predicate);
|
|
587
587
|
columns[predicate.uri] = column;
|
|
588
588
|
}
|
|
589
|
-
|
|
590
589
|
return column;
|
|
591
|
-
}
|
|
592
|
-
// necessary.
|
|
590
|
+
}
|
|
593
591
|
|
|
592
|
+
// Find a type by its URI, creating a new SubjectType object if
|
|
593
|
+
// necessary.
|
|
594
594
|
|
|
595
595
|
function getTypeForObject(types, type) {
|
|
596
596
|
var subjectType;
|
|
597
|
-
|
|
598
597
|
if (type.uri in types) {
|
|
599
598
|
subjectType = types[type.uri];
|
|
600
599
|
} else {
|
|
601
600
|
subjectType = new SubjectType(type);
|
|
602
601
|
types[type.uri] = subjectType;
|
|
603
602
|
}
|
|
604
|
-
|
|
605
603
|
return subjectType;
|
|
606
|
-
}
|
|
604
|
+
}
|
|
607
605
|
|
|
606
|
+
// Discover types and subjects for search.
|
|
608
607
|
|
|
609
608
|
function discoverTypes() {
|
|
610
609
|
// rdf:type properties of subjects, indexed by URI for the type.
|
|
611
|
-
|
|
610
|
+
|
|
611
|
+
var types = {};
|
|
612
|
+
|
|
613
|
+
// Get a list of statements that match: ? rdfs:type ?
|
|
612
614
|
// From this we can get a list of subjects and types.
|
|
613
615
|
|
|
614
|
-
var subjectList = kb.statementsMatching(undefined, UI.ns.rdf('type'), tableClass,
|
|
616
|
+
var subjectList = kb.statementsMatching(undefined, UI.ns.rdf('type'), tableClass,
|
|
617
|
+
// can be undefined OR
|
|
615
618
|
sourceDocument); // can be undefined
|
|
619
|
+
|
|
616
620
|
// Subjects for later lookup. This is a mapping of type URIs to
|
|
617
621
|
// lists of subjects (it is necessary to record the type of
|
|
618
622
|
// a subject).
|
|
619
623
|
|
|
620
624
|
var subjects = {};
|
|
621
|
-
|
|
622
625
|
for (var i = 0; i < subjectList.length; ++i) {
|
|
623
626
|
var type = subjectList[i].object;
|
|
624
|
-
|
|
625
627
|
if (type.termType !== 'NamedNode') {
|
|
626
628
|
// @@ no bnodes?
|
|
627
629
|
continue;
|
|
628
630
|
}
|
|
629
|
-
|
|
630
631
|
var typeObj = getTypeForObject(types, type);
|
|
631
|
-
|
|
632
632
|
if (!(type.uri in subjects)) {
|
|
633
633
|
subjects[type.uri] = [];
|
|
634
634
|
}
|
|
635
|
-
|
|
636
635
|
subjects[type.uri].push(subjectList[i].subject);
|
|
637
636
|
typeObj.addUse();
|
|
638
637
|
}
|
|
639
|
-
|
|
640
638
|
return [subjects, types];
|
|
641
|
-
}
|
|
639
|
+
}
|
|
642
640
|
|
|
641
|
+
// Get columns for the given subject.
|
|
643
642
|
|
|
644
643
|
function getSubjectProperties(subject, columns) {
|
|
645
644
|
// Get a list of properties of this subject.
|
|
645
|
+
|
|
646
646
|
var properties = kb.statementsMatching(subject, undefined, undefined, sourceDocument);
|
|
647
647
|
var result = {};
|
|
648
|
-
|
|
649
648
|
for (var j = 0; j < properties.length; ++j) {
|
|
650
649
|
var predicate = properties[j].predicate;
|
|
651
|
-
|
|
652
650
|
if (predicate.uri in FORBIDDEN_COLUMNS) {
|
|
653
651
|
continue;
|
|
654
|
-
}
|
|
652
|
+
}
|
|
655
653
|
|
|
654
|
+
// Find/create a column for this predicate.
|
|
656
655
|
|
|
657
656
|
var column = getColumnForPredicate(columns, predicate);
|
|
658
657
|
column.checkValue(properties[j].object);
|
|
659
658
|
result[predicate.uri] = column;
|
|
660
659
|
}
|
|
661
|
-
|
|
662
660
|
return result;
|
|
663
|
-
}
|
|
661
|
+
}
|
|
664
662
|
|
|
663
|
+
// Identify the columns associated with a type.
|
|
665
664
|
|
|
666
665
|
function identifyColumnsForType(type, subjects) {
|
|
667
|
-
var allColumns = {};
|
|
666
|
+
var allColumns = {};
|
|
667
|
+
|
|
668
|
+
// Process each subject of this type to build up the
|
|
668
669
|
// column list.
|
|
669
670
|
|
|
670
671
|
for (var i = 0; i < subjects.length; ++i) {
|
|
671
672
|
var columns = getSubjectProperties(subjects[i], allColumns);
|
|
672
|
-
|
|
673
673
|
for (var predicateUri in columns) {
|
|
674
674
|
var column = columns[predicateUri];
|
|
675
675
|
column.addUse();
|
|
676
676
|
}
|
|
677
|
-
}
|
|
677
|
+
}
|
|
678
678
|
|
|
679
|
+
// Generate the columns list
|
|
679
680
|
|
|
680
681
|
var allColumnsList = objectToArray(allColumns);
|
|
681
682
|
sortColumns(allColumnsList);
|
|
682
683
|
type.allColumns = allColumnsList;
|
|
683
|
-
}
|
|
684
|
+
}
|
|
684
685
|
|
|
686
|
+
// Build table information from parsing RDF statements.
|
|
685
687
|
|
|
686
688
|
function calculateTable() {
|
|
687
689
|
// Find the types that we will display in the dropdown
|
|
688
690
|
// list box, and associated objects of those types.
|
|
689
|
-
var subjects, types;
|
|
690
|
-
var s = discoverTypes(); // eslint-disable-next-line prefer-const
|
|
691
|
-
|
|
692
|
-
subjects = s[0]; // eslint-disable-next-line prefer-const
|
|
693
691
|
|
|
692
|
+
var subjects, types;
|
|
693
|
+
var s = discoverTypes();
|
|
694
|
+
// eslint-disable-next-line prefer-const
|
|
695
|
+
subjects = s[0];
|
|
696
|
+
// eslint-disable-next-line prefer-const
|
|
694
697
|
types = s[1]; // no [ ] on LHS
|
|
695
698
|
|
|
696
699
|
for (var typeUrl in subjects) {
|
|
697
700
|
var subjectList = subjects[typeUrl];
|
|
698
701
|
var type = types[typeUrl];
|
|
699
702
|
identifyColumnsForType(type, subjectList);
|
|
700
|
-
}
|
|
701
|
-
// Combine columns from all types
|
|
703
|
+
}
|
|
702
704
|
|
|
705
|
+
// TODO: Special type that captures all rows.
|
|
706
|
+
// Combine columns from all types
|
|
703
707
|
|
|
704
708
|
var allType = new SubjectType(null);
|
|
705
709
|
return [allType, objectToArray(types)];
|
|
706
|
-
}
|
|
710
|
+
}
|
|
707
711
|
|
|
712
|
+
// Sort the list of columns by the most common columns.
|
|
708
713
|
|
|
709
714
|
function sortColumns(columns) {
|
|
710
715
|
function sortFunction(a, b) {
|
|
711
716
|
return (a.useCount < b.useCount) - (a.useCount > b.useCount);
|
|
712
717
|
}
|
|
713
|
-
|
|
714
718
|
columns.sort(sortFunction);
|
|
715
|
-
}
|
|
719
|
+
}
|
|
716
720
|
|
|
721
|
+
// Create the delete button for a column.
|
|
717
722
|
|
|
718
723
|
function renderColumnDeleteButton(type, column) {
|
|
719
724
|
var button = doc.createElement('a');
|
|
@@ -723,76 +728,78 @@ function renderTableViewPane(doc, options) {
|
|
|
723
728
|
buildFilteredTable(type);
|
|
724
729
|
}, false);
|
|
725
730
|
return button;
|
|
726
|
-
}
|
|
731
|
+
}
|
|
727
732
|
|
|
733
|
+
// Render the table header for the HTML table.
|
|
728
734
|
|
|
729
735
|
function renderTableHeader(columns, type) {
|
|
730
736
|
var tr = doc.createElement('tr');
|
|
731
|
-
/* Empty header for link column */
|
|
732
737
|
|
|
738
|
+
/* Empty header for link column */
|
|
733
739
|
var linkTd = doc.createElement('th');
|
|
734
740
|
tr.appendChild(linkTd);
|
|
735
|
-
|
|
736
741
|
for (var i = 0; i < columns.length; ++i) {
|
|
737
742
|
var th = doc.createElement('th');
|
|
738
743
|
var column = columns[i];
|
|
739
|
-
th.appendChild(doc.createTextNode(column.getLabel()));
|
|
740
|
-
// proper interface and have a type to delete from:
|
|
744
|
+
th.appendChild(doc.createTextNode(column.getLabel()));
|
|
741
745
|
|
|
746
|
+
// We can only add a delete button if we are using the
|
|
747
|
+
// proper interface and have a type to delete from:
|
|
742
748
|
if (type) {
|
|
743
749
|
th.appendChild(renderColumnDeleteButton(type, column));
|
|
744
750
|
}
|
|
745
|
-
|
|
746
751
|
tr.appendChild(th);
|
|
747
752
|
}
|
|
748
|
-
|
|
749
753
|
return tr;
|
|
750
|
-
}
|
|
751
|
-
// column, using the provided sort function to compare values.
|
|
754
|
+
}
|
|
752
755
|
|
|
756
|
+
// Sort the rows in the rendered table by data from a specific
|
|
757
|
+
// column, using the provided sort function to compare values.
|
|
753
758
|
|
|
754
759
|
function applyColumnSort(rows, column, sortFunction, reverse) {
|
|
755
|
-
var columnKey = column.getKey();
|
|
760
|
+
var columnKey = column.getKey();
|
|
756
761
|
|
|
762
|
+
// Sort the rows array.
|
|
757
763
|
rows.sort(function (row1, row2) {
|
|
758
764
|
var row1Value = null;
|
|
759
765
|
var row2Value = null;
|
|
760
|
-
|
|
761
766
|
if (columnKey in row1.values) {
|
|
762
767
|
row1Value = row1.values[columnKey][0];
|
|
763
768
|
}
|
|
764
|
-
|
|
765
769
|
if (columnKey in row2.values) {
|
|
766
770
|
row2Value = row2.values[columnKey][0];
|
|
767
771
|
}
|
|
768
|
-
|
|
769
772
|
var result = sortFunction(row1Value, row2Value);
|
|
770
|
-
|
|
771
773
|
if (reverse) {
|
|
772
774
|
return -result;
|
|
773
775
|
} else {
|
|
774
776
|
return result;
|
|
775
777
|
}
|
|
776
|
-
});
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
// Remove all rows from the table:
|
|
777
781
|
|
|
778
782
|
if (rows.length) {
|
|
779
783
|
var parentTable = rows[0]._htmlRow.parentNode;
|
|
780
|
-
|
|
781
784
|
for (var i = 0; i < rows.length; ++i) {
|
|
782
785
|
parentTable.removeChild(rows[i]._htmlRow);
|
|
783
|
-
}
|
|
786
|
+
}
|
|
784
787
|
|
|
788
|
+
// Add back the rows in the new sorted order:
|
|
785
789
|
|
|
786
790
|
for (var _i = 0; _i < rows.length; ++_i) {
|
|
787
791
|
parentTable.appendChild(rows[_i]._htmlRow);
|
|
788
792
|
}
|
|
789
793
|
}
|
|
790
|
-
}
|
|
791
|
-
// columns.
|
|
794
|
+
}
|
|
792
795
|
|
|
796
|
+
// Filter the list of rows based on the selectors for the
|
|
797
|
+
// columns.
|
|
793
798
|
|
|
794
799
|
function applyColumnFiltersToRow(row, columns) {
|
|
795
|
-
var rowDisplayed = true;
|
|
800
|
+
var rowDisplayed = true;
|
|
801
|
+
|
|
802
|
+
// Check the filter functions for every column.
|
|
796
803
|
// The row should only be displayed if the filter functions
|
|
797
804
|
// for all of the columns return true.
|
|
798
805
|
|
|
@@ -800,39 +807,41 @@ function renderTableViewPane(doc, options) {
|
|
|
800
807
|
var column = columns[c];
|
|
801
808
|
var columnKey = column.getKey();
|
|
802
809
|
var columnValue = null;
|
|
803
|
-
|
|
804
810
|
if (columnKey in row.values) {
|
|
805
811
|
columnValue = row.values[columnKey][0];
|
|
806
812
|
}
|
|
807
|
-
|
|
808
813
|
if (!column.filterFunction(columnValue)) {
|
|
809
814
|
rowDisplayed = false;
|
|
810
815
|
break;
|
|
811
816
|
}
|
|
812
|
-
}
|
|
813
|
-
// from the filter function.
|
|
817
|
+
}
|
|
814
818
|
|
|
819
|
+
// Show or hide the HTML row according to the result
|
|
820
|
+
// from the filter function.
|
|
815
821
|
|
|
816
822
|
var htmlRow = row._htmlRow;
|
|
817
|
-
|
|
818
823
|
if (rowDisplayed) {
|
|
819
824
|
htmlRow.style.display = '';
|
|
820
825
|
} else {
|
|
821
826
|
htmlRow.style.display = 'none';
|
|
822
827
|
}
|
|
823
|
-
}
|
|
824
|
-
// columns.
|
|
828
|
+
}
|
|
825
829
|
|
|
830
|
+
// Filter the list of rows based on the selectors for the
|
|
831
|
+
// columns.
|
|
826
832
|
|
|
827
833
|
function applyColumnFilters(rows, columns) {
|
|
828
834
|
// Apply filterFunction to each row.
|
|
835
|
+
|
|
829
836
|
for (var r = 0; r < rows.length; ++r) {
|
|
830
837
|
var row = rows[r];
|
|
831
838
|
applyColumnFiltersToRow(row, columns);
|
|
832
839
|
}
|
|
833
|
-
}
|
|
834
|
-
// Sort by literal value
|
|
840
|
+
}
|
|
835
841
|
|
|
842
|
+
// /////////////////////////////////// Literal column handling
|
|
843
|
+
|
|
844
|
+
// Sort by literal value
|
|
836
845
|
|
|
837
846
|
function literalSort(rows, column, reverse) {
|
|
838
847
|
function literalToString(colValue) {
|
|
@@ -842,17 +851,14 @@ function renderTableViewPane(doc, options) {
|
|
|
842
851
|
} else if (colValue.termType === 'NamedNode') {
|
|
843
852
|
return utils.label(colValue).toLowerCase();
|
|
844
853
|
}
|
|
845
|
-
|
|
846
854
|
return colValue.value.toLowerCase();
|
|
847
855
|
} else {
|
|
848
856
|
return '';
|
|
849
857
|
}
|
|
850
858
|
}
|
|
851
|
-
|
|
852
859
|
function literalCompare(value1, value2) {
|
|
853
860
|
var strValue1 = literalToString(value1);
|
|
854
861
|
var strValue2 = literalToString(value2);
|
|
855
|
-
|
|
856
862
|
if (strValue1 < strValue2) {
|
|
857
863
|
return -1;
|
|
858
864
|
} else if (strValue1 > strValue2) {
|
|
@@ -861,10 +867,10 @@ function renderTableViewPane(doc, options) {
|
|
|
861
867
|
return 0;
|
|
862
868
|
}
|
|
863
869
|
}
|
|
864
|
-
|
|
865
870
|
applyColumnSort(rows, column, literalCompare, reverse);
|
|
866
|
-
}
|
|
871
|
+
}
|
|
867
872
|
|
|
873
|
+
// Generates a selector for an RDF literal column.
|
|
868
874
|
|
|
869
875
|
function renderLiteralSelector(rows, columns, column) {
|
|
870
876
|
var result = doc.createElement('div');
|
|
@@ -884,7 +890,9 @@ function renderTableViewPane(doc, options) {
|
|
|
884
890
|
literalSort(rows, column, true);
|
|
885
891
|
}, false);
|
|
886
892
|
result.appendChild(sort2);
|
|
887
|
-
var substring = null;
|
|
893
|
+
var substring = null;
|
|
894
|
+
|
|
895
|
+
// Filter the table to show only rows that have a particular
|
|
888
896
|
// substring in the specified column.
|
|
889
897
|
|
|
890
898
|
column.filterFunction = function (colValue) {
|
|
@@ -894,7 +902,6 @@ function renderTableViewPane(doc, options) {
|
|
|
894
902
|
return false;
|
|
895
903
|
} else {
|
|
896
904
|
var literalValue;
|
|
897
|
-
|
|
898
905
|
if (colValue.termType === 'Literal') {
|
|
899
906
|
literalValue = colValue.value;
|
|
900
907
|
} else if (colValue.termType === 'NamedNode') {
|
|
@@ -902,22 +909,22 @@ function renderTableViewPane(doc, options) {
|
|
|
902
909
|
} else {
|
|
903
910
|
literalValue = '';
|
|
904
911
|
}
|
|
905
|
-
|
|
906
912
|
return literalValue.toLowerCase().indexOf(substring) >= 0;
|
|
907
913
|
}
|
|
908
914
|
};
|
|
909
|
-
|
|
910
915
|
textBox.addEventListener('keyup', function () {
|
|
911
916
|
if (textBox.value !== '') {
|
|
912
917
|
substring = textBox.value.toLowerCase();
|
|
913
918
|
} else {
|
|
914
919
|
substring = null;
|
|
915
920
|
}
|
|
916
|
-
|
|
917
921
|
applyColumnFilters(rows, columns);
|
|
918
922
|
}, false);
|
|
919
923
|
return result;
|
|
920
|
-
}
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// /////////////////////////////////// Enumeration
|
|
927
|
+
|
|
921
928
|
// Generates a dropdown selector for enumeration types include
|
|
922
929
|
//
|
|
923
930
|
// @param rows,
|
|
@@ -925,41 +932,35 @@ function renderTableViewPane(doc, options) {
|
|
|
925
932
|
// @param column,
|
|
926
933
|
// @param list, List of alternative terms
|
|
927
934
|
//
|
|
928
|
-
|
|
929
|
-
|
|
930
935
|
function renderEnumSelector(rows, columns, column, list) {
|
|
931
936
|
var doMultiple = true;
|
|
932
937
|
var result = doc.createElement('div');
|
|
933
938
|
var dropdown = doc.createElement('select');
|
|
934
939
|
var searchValue = {}; // Defualt to all enabled
|
|
935
|
-
|
|
936
940
|
for (var i = 0; i < list.length; ++i) {
|
|
937
941
|
var value = list[i];
|
|
938
942
|
searchValue[value.uri] = true;
|
|
939
943
|
}
|
|
940
|
-
|
|
941
944
|
var initialSelection = getHints(column).initialSelection;
|
|
942
945
|
if (initialSelection) searchValue = initialSelection;
|
|
943
946
|
if (doMultiple) dropdown.setAttribute('multiple', 'true');else dropdown.appendChild(optionElement('(All)', '-1'));
|
|
944
|
-
|
|
945
947
|
for (var _i2 = 0; _i2 < list.length; ++_i2) {
|
|
946
948
|
var _value = list[_i2];
|
|
947
949
|
var ele = optionElement(utils.label(_value), _i2);
|
|
948
950
|
if (searchValue[_value.uri]) ele.selected = true;
|
|
949
951
|
dropdown.appendChild(ele);
|
|
950
952
|
}
|
|
953
|
+
result.appendChild(dropdown);
|
|
951
954
|
|
|
952
|
-
|
|
955
|
+
// Select based on an enum value.
|
|
953
956
|
|
|
954
957
|
column.filterFunction = function (colValue) {
|
|
955
958
|
return !searchValue || colValue && searchValue[colValue.uri];
|
|
956
959
|
};
|
|
957
|
-
|
|
958
960
|
dropdown.addEventListener('click', function () {
|
|
959
961
|
if (doMultiple) {
|
|
960
962
|
searchValue = {};
|
|
961
963
|
var opt = dropdown.options;
|
|
962
|
-
|
|
963
964
|
for (var _i3 = 0; _i3 < opt.length; _i3++) {
|
|
964
965
|
var option = opt[_i3];
|
|
965
966
|
var index = Number(option.value);
|
|
@@ -967,8 +968,6 @@ function renderTableViewPane(doc, options) {
|
|
|
967
968
|
}
|
|
968
969
|
} else {
|
|
969
970
|
var _index = Number(dropdown.value); // adjusted in Standard tweaks 2018-01
|
|
970
|
-
|
|
971
|
-
|
|
972
971
|
if (_index < 0) {
|
|
973
972
|
searchValue = null;
|
|
974
973
|
} else {
|
|
@@ -976,15 +975,15 @@ function renderTableViewPane(doc, options) {
|
|
|
976
975
|
searchValue[list[_index].uri] = true;
|
|
977
976
|
}
|
|
978
977
|
}
|
|
979
|
-
|
|
980
978
|
applyColumnFilters(rows, columns);
|
|
981
979
|
}, true);
|
|
982
980
|
return result;
|
|
983
|
-
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// //////////////////////////////////// Numeric
|
|
984
984
|
//
|
|
985
985
|
// Selector for XSD number types.
|
|
986
986
|
|
|
987
|
-
|
|
988
987
|
function renderNumberSelector(rows, columns, column) {
|
|
989
988
|
var result = doc.createElement('div');
|
|
990
989
|
var minSelector = doc.createElement('input');
|
|
@@ -994,28 +993,27 @@ function renderTableViewPane(doc, options) {
|
|
|
994
993
|
var maxSelector = doc.createElement('input');
|
|
995
994
|
maxSelector.setAttribute('type', 'text');
|
|
996
995
|
maxSelector.style.width = '40px';
|
|
997
|
-
result.appendChild(maxSelector);
|
|
996
|
+
result.appendChild(maxSelector);
|
|
997
|
+
|
|
998
|
+
// Select based on minimum/maximum limits.
|
|
998
999
|
|
|
999
1000
|
var min = null;
|
|
1000
1001
|
var max = null;
|
|
1001
|
-
|
|
1002
1002
|
column.filterFunction = function (colValue) {
|
|
1003
1003
|
if (colValue) {
|
|
1004
1004
|
colValue = Number(colValue);
|
|
1005
1005
|
}
|
|
1006
|
-
|
|
1007
1006
|
if (min && (!colValue || colValue < min)) {
|
|
1008
1007
|
return false;
|
|
1009
1008
|
}
|
|
1010
|
-
|
|
1011
1009
|
if (max && (!colValue || colValue > max)) {
|
|
1012
1010
|
return false;
|
|
1013
1011
|
}
|
|
1014
|
-
|
|
1015
1012
|
return true;
|
|
1016
|
-
};
|
|
1017
|
-
// displayed columns.
|
|
1013
|
+
};
|
|
1018
1014
|
|
|
1015
|
+
// When the values in the boxes are changed, update the
|
|
1016
|
+
// displayed columns.
|
|
1019
1017
|
|
|
1020
1018
|
function eventListener() {
|
|
1021
1019
|
if (minSelector.value === '') {
|
|
@@ -1023,86 +1021,93 @@ function renderTableViewPane(doc, options) {
|
|
|
1023
1021
|
} else {
|
|
1024
1022
|
min = Number(minSelector.value);
|
|
1025
1023
|
}
|
|
1026
|
-
|
|
1027
1024
|
if (maxSelector.value === '') {
|
|
1028
1025
|
max = null;
|
|
1029
1026
|
} else {
|
|
1030
1027
|
max = Number(maxSelector.value);
|
|
1031
1028
|
}
|
|
1032
|
-
|
|
1033
1029
|
applyColumnFilters(rows, columns);
|
|
1034
1030
|
}
|
|
1035
|
-
|
|
1036
1031
|
minSelector.addEventListener('keyup', eventListener, false);
|
|
1037
1032
|
maxSelector.addEventListener('keyup', eventListener, false);
|
|
1038
1033
|
return result;
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// /////////////////////////////////////////////////////////////////
|
|
1041
1037
|
|
|
1038
|
+
// Fallback attempts at generating a selector if other attempts fail.
|
|
1042
1039
|
|
|
1043
1040
|
function fallbackRenderTableSelector(rows, columns, column) {
|
|
1044
1041
|
// Have all values matched as numbers?
|
|
1042
|
+
|
|
1045
1043
|
if (column.checkedAnyValues && column.possiblyNumber) {
|
|
1046
1044
|
return renderNumberSelector(rows, columns, column);
|
|
1047
|
-
}
|
|
1045
|
+
}
|
|
1048
1046
|
|
|
1047
|
+
// Have all values been literals?
|
|
1049
1048
|
|
|
1050
1049
|
if (column.possiblyLiteral) {
|
|
1051
1050
|
return renderLiteralSelector(rows, columns, column);
|
|
1052
1051
|
}
|
|
1053
|
-
|
|
1054
1052
|
return null;
|
|
1055
|
-
}
|
|
1053
|
+
}
|
|
1056
1054
|
|
|
1055
|
+
// Render a selector for a given row.
|
|
1057
1056
|
|
|
1058
1057
|
function renderTableSelector(rows, columns, column) {
|
|
1059
1058
|
// What type of data is in this column? Check the constraints for
|
|
1060
1059
|
// this predicate.
|
|
1060
|
+
|
|
1061
1061
|
// If this is a class which can be one of various sibling classes?
|
|
1062
1062
|
if (column.superClass && column.alternatives.length > 0) {
|
|
1063
1063
|
return renderEnumSelector(rows, columns, column, column.alternatives);
|
|
1064
1064
|
}
|
|
1065
|
-
|
|
1066
1065
|
var cs = column.getConstraints();
|
|
1067
1066
|
var range;
|
|
1068
|
-
|
|
1069
1067
|
for (var i = 0; i < cs.length; i++) {
|
|
1070
|
-
range = cs[i];
|
|
1068
|
+
range = cs[i];
|
|
1069
|
+
|
|
1070
|
+
// Is this a number type?
|
|
1071
1071
|
// Alternatively, is this an rdf:Literal type where all of
|
|
1072
1072
|
// the values match as numbers?
|
|
1073
1073
|
|
|
1074
1074
|
if (column.checkedAnyValues && column.possiblyNumber || range.uri in XSD_NUMBER_TYPES) {
|
|
1075
1075
|
return renderNumberSelector(rows, columns, column);
|
|
1076
|
-
}
|
|
1076
|
+
}
|
|
1077
1077
|
|
|
1078
|
+
// rdf:Literal? Assume a string at this point
|
|
1078
1079
|
|
|
1079
1080
|
if (range.uri === RDFS_LITERAL) {
|
|
1080
1081
|
return renderLiteralSelector(rows, columns, column);
|
|
1081
|
-
}
|
|
1082
|
-
// Also ToDo: @@@ Handle membership of classes whcih are disjointUnions
|
|
1082
|
+
}
|
|
1083
1083
|
|
|
1084
|
+
// Is this an enumeration type?
|
|
1084
1085
|
|
|
1085
|
-
|
|
1086
|
+
// Also ToDo: @@@ Handle membership of classes whcih are disjointUnions
|
|
1086
1087
|
|
|
1088
|
+
var choices = kb.each(range, UI.ns.owl('oneOf'));
|
|
1087
1089
|
if (choices.length > 0) {
|
|
1088
1090
|
return renderEnumSelector(rows, columns, column, choices.elements);
|
|
1089
1091
|
}
|
|
1090
1092
|
}
|
|
1091
|
-
|
|
1092
1093
|
return fallbackRenderTableSelector(rows, columns, column);
|
|
1093
|
-
}
|
|
1094
|
+
}
|
|
1094
1095
|
|
|
1096
|
+
// Generate the search selectors for the table columns.
|
|
1095
1097
|
|
|
1096
1098
|
function renderTableSelectors(rows, columns) {
|
|
1097
1099
|
var tr = doc.createElement('tr');
|
|
1098
|
-
tr.className = 'selectors';
|
|
1100
|
+
tr.className = 'selectors';
|
|
1101
|
+
|
|
1102
|
+
// Empty link column
|
|
1103
|
+
|
|
1104
|
+
tr.appendChild(doc.createElement('td'));
|
|
1099
1105
|
|
|
1100
|
-
|
|
1106
|
+
// Generate selectors.
|
|
1101
1107
|
|
|
1102
1108
|
for (var i = 0; i < columns.length; ++i) {
|
|
1103
1109
|
var td = doc.createElement('td');
|
|
1104
1110
|
var selector = renderTableSelector(rows, columns, columns[i]);
|
|
1105
|
-
|
|
1106
1111
|
if (selector) {
|
|
1107
1112
|
td.appendChild(selector);
|
|
1108
1113
|
}
|
|
@@ -1112,21 +1117,16 @@ function renderTableViewPane(doc, options) {
|
|
|
1112
1117
|
td.appendChild(document.createTextNode(columns[i].predicate.uri))
|
|
1113
1118
|
}
|
|
1114
1119
|
*/
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
1120
|
tr.appendChild(td);
|
|
1118
1121
|
}
|
|
1119
|
-
|
|
1120
1122
|
return tr;
|
|
1121
1123
|
}
|
|
1122
|
-
|
|
1123
1124
|
function linkTo(uri, linkText, hints) {
|
|
1124
1125
|
hints = hints || {};
|
|
1125
1126
|
var result = doc.createElement('a');
|
|
1126
1127
|
var linkFunction = hints.linkFunction;
|
|
1127
1128
|
result.setAttribute('href', uri);
|
|
1128
1129
|
result.appendChild(doc.createTextNode(linkText));
|
|
1129
|
-
|
|
1130
1130
|
if (!linkFunction) {
|
|
1131
1131
|
result.addEventListener('click', UI.widgets.openHrefInOutlineMode, true);
|
|
1132
1132
|
} else {
|
|
@@ -1139,56 +1139,51 @@ function renderTableViewPane(doc, options) {
|
|
|
1139
1139
|
linkFunction(uri);
|
|
1140
1140
|
}, true);
|
|
1141
1141
|
}
|
|
1142
|
-
|
|
1143
1142
|
return result;
|
|
1144
1143
|
}
|
|
1145
|
-
|
|
1146
1144
|
function linkToObject(obj, hints) {
|
|
1147
1145
|
var match = false;
|
|
1148
|
-
|
|
1149
1146
|
if (obj.uri) {
|
|
1150
1147
|
match = obj.uri.match(/^mailto:(.*)/);
|
|
1151
1148
|
}
|
|
1152
|
-
|
|
1153
1149
|
if (match) {
|
|
1154
1150
|
return linkTo(obj.uri, match[1], hints);
|
|
1155
1151
|
} else {
|
|
1156
1152
|
return linkTo(obj.uri, utils.label(obj), hints);
|
|
1157
1153
|
}
|
|
1158
|
-
}
|
|
1154
|
+
}
|
|
1159
1155
|
|
|
1156
|
+
// Render an image
|
|
1160
1157
|
|
|
1161
1158
|
function renderImage(obj) {
|
|
1162
1159
|
var result = doc.createElement('img');
|
|
1163
|
-
result.setAttribute('src', obj.uri);
|
|
1160
|
+
result.setAttribute('src', obj.uri);
|
|
1164
1161
|
|
|
1162
|
+
// Set the height, so it appears as a thumbnail.
|
|
1165
1163
|
result.style.height = '40px';
|
|
1166
1164
|
return result;
|
|
1167
|
-
}
|
|
1168
|
-
// in a table cell.
|
|
1165
|
+
}
|
|
1169
1166
|
|
|
1167
|
+
// Render an individual RDF object to an HTML object displayed
|
|
1168
|
+
// in a table cell.
|
|
1170
1169
|
|
|
1171
1170
|
function getHints(column) {
|
|
1172
1171
|
if (options && options.hints && column.variable && options.hints[column.variable.toNT()]) {
|
|
1173
1172
|
return options.hints[column.variable.toNT()];
|
|
1174
1173
|
}
|
|
1175
|
-
|
|
1176
1174
|
return {};
|
|
1177
1175
|
}
|
|
1178
|
-
|
|
1179
1176
|
function renderValue(obj, column) {
|
|
1180
1177
|
// hint
|
|
1181
1178
|
var hints = getHints(column);
|
|
1182
1179
|
var cellFormat = hints.cellFormat;
|
|
1183
|
-
|
|
1184
1180
|
if (cellFormat) {
|
|
1185
1181
|
switch (cellFormat) {
|
|
1186
1182
|
case 'shortDate':
|
|
1187
1183
|
return doc.createTextNode(UI.widgets.shortDate(obj.value));
|
|
1188
1184
|
// break
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1185
|
+
default:
|
|
1186
|
+
// drop through
|
|
1192
1187
|
}
|
|
1193
1188
|
} else {
|
|
1194
1189
|
if (obj.termType === 'Literal') {
|
|
@@ -1202,7 +1197,6 @@ function renderTableViewPane(doc, options) {
|
|
|
1202
1197
|
return span;
|
|
1203
1198
|
}
|
|
1204
1199
|
}
|
|
1205
|
-
|
|
1206
1200
|
return doc.createTextNode(obj.value);
|
|
1207
1201
|
} else if (obj.termType === 'NamedNode' && column.isImageColumn()) {
|
|
1208
1202
|
return renderImage(obj);
|
|
@@ -1210,38 +1204,34 @@ function renderTableViewPane(doc, options) {
|
|
|
1210
1204
|
return linkToObject(obj, hints);
|
|
1211
1205
|
} else if (obj.termType === 'Collection') {
|
|
1212
1206
|
var _span = doc.createElement('span');
|
|
1213
|
-
|
|
1214
1207
|
_span.appendChild(doc.createTextNode('['));
|
|
1215
|
-
|
|
1216
1208
|
obj.elements.forEach(function (x) {
|
|
1217
1209
|
_span.appendChild(renderValue(x, column));
|
|
1218
|
-
|
|
1219
1210
|
_span.appendChild(doc.createTextNode(', '));
|
|
1220
1211
|
});
|
|
1221
|
-
|
|
1222
1212
|
_span.removeChild(_span.lastChild);
|
|
1223
|
-
|
|
1224
1213
|
_span.appendChild(doc.createTextNode(']'));
|
|
1225
|
-
|
|
1226
1214
|
return _span;
|
|
1227
1215
|
} else {
|
|
1228
1216
|
return doc.createTextNode("unknown termtype '" + obj.termType + "'!");
|
|
1229
1217
|
}
|
|
1230
1218
|
}
|
|
1231
|
-
}
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
// Render a row of the HTML table, from the given row structure.
|
|
1232
1222
|
// Note that unlike other functions, this renders into a provided
|
|
1233
1223
|
// row (<tr>) element.
|
|
1234
1224
|
|
|
1235
|
-
|
|
1236
1225
|
function renderTableRowInto(tr, row, columns, _downstream) {
|
|
1237
1226
|
/* Link column, for linking to this subject. */
|
|
1238
|
-
var linkTd = doc.createElement('td');
|
|
1239
1227
|
|
|
1228
|
+
var linkTd = doc.createElement('td');
|
|
1240
1229
|
if (row._subject && 'uri' in row._subject) {
|
|
1241
1230
|
linkTd.appendChild(linkTo(row._subject.uri, "\u2192"));
|
|
1242
1231
|
}
|
|
1232
|
+
tr.appendChild(linkTd);
|
|
1243
1233
|
|
|
1244
|
-
|
|
1234
|
+
// Create a <td> for each column (whether the row has data for that
|
|
1245
1235
|
// column or not).
|
|
1246
1236
|
|
|
1247
1237
|
for (var i = 0; i < columns.length; ++i) {
|
|
@@ -1249,34 +1239,26 @@ function renderTableViewPane(doc, options) {
|
|
|
1249
1239
|
var td = doc.createElement('td');
|
|
1250
1240
|
var orig = void 0;
|
|
1251
1241
|
var columnKey = column.getKey();
|
|
1252
|
-
|
|
1253
1242
|
if (columnKey in row.values) {
|
|
1254
1243
|
var objects = row.values[columnKey];
|
|
1255
1244
|
var different = false;
|
|
1256
|
-
|
|
1257
1245
|
if (row.originalValues && row.originalValues[columnKey]) {
|
|
1258
1246
|
if (objects.length !== row.originalValues[columnKey].length) {
|
|
1259
1247
|
different = true;
|
|
1260
1248
|
}
|
|
1261
1249
|
}
|
|
1262
|
-
|
|
1263
1250
|
for (var j = 0; j < objects.length; ++j) {
|
|
1264
1251
|
var obj = objects[j];
|
|
1265
|
-
|
|
1266
1252
|
if (row.originalValues && row.originalValues[columnKey] && row.originalValues[columnKey].length > j) {
|
|
1267
1253
|
orig = row.originalValues[columnKey][j];
|
|
1268
|
-
|
|
1269
1254
|
if (obj.toString() !== orig.toString()) {
|
|
1270
1255
|
different = true;
|
|
1271
1256
|
}
|
|
1272
1257
|
}
|
|
1273
|
-
|
|
1274
1258
|
td.appendChild(renderValue(obj, column));
|
|
1275
|
-
|
|
1276
1259
|
if (j !== objects.length - 1) {
|
|
1277
1260
|
td.appendChild(doc.createTextNode(',\n'));
|
|
1278
1261
|
}
|
|
1279
|
-
|
|
1280
1262
|
if (different) {
|
|
1281
1263
|
td.style.background = '#efe'; // green = new changed
|
|
1282
1264
|
}
|
|
@@ -1284,71 +1266,77 @@ function renderTableViewPane(doc, options) {
|
|
|
1284
1266
|
}
|
|
1285
1267
|
|
|
1286
1268
|
tr.appendChild(td);
|
|
1287
|
-
}
|
|
1269
|
+
}
|
|
1288
1270
|
|
|
1271
|
+
// Save a reference to the HTML row in the row object.
|
|
1289
1272
|
|
|
1290
1273
|
row._htmlRow = tr;
|
|
1291
1274
|
return tr;
|
|
1292
|
-
}
|
|
1293
|
-
// a cell (the query can sometimes find it multiple times)
|
|
1275
|
+
}
|
|
1294
1276
|
|
|
1277
|
+
// Check if a value is already stored in the list of values for
|
|
1278
|
+
// a cell (the query can sometimes find it multiple times)
|
|
1295
1279
|
|
|
1296
1280
|
function valueInList(value, list) {
|
|
1297
1281
|
var key = null;
|
|
1298
|
-
|
|
1299
1282
|
if (value.termType === 'Literal') {
|
|
1300
1283
|
key = 'value';
|
|
1301
1284
|
} else if (value.termType === 'NamedNode') {
|
|
1302
1285
|
key = 'uri';
|
|
1303
1286
|
} else {
|
|
1304
1287
|
return list.indexOf(value) >= 0;
|
|
1305
|
-
}
|
|
1288
|
+
}
|
|
1306
1289
|
|
|
1290
|
+
// Check the list and compare keys:
|
|
1307
1291
|
|
|
1308
1292
|
var i;
|
|
1309
|
-
|
|
1310
1293
|
for (i = 0; i < list.length; ++i) {
|
|
1311
1294
|
if (list[i].termType === value.termType && list[i][key] === value[key]) {
|
|
1312
1295
|
return true;
|
|
1313
1296
|
}
|
|
1314
|
-
}
|
|
1297
|
+
}
|
|
1315
1298
|
|
|
1299
|
+
// Not found?
|
|
1316
1300
|
|
|
1317
1301
|
return false;
|
|
1318
|
-
}
|
|
1319
|
-
// containing the values.
|
|
1302
|
+
}
|
|
1320
1303
|
|
|
1304
|
+
// Update a row, add new values, and regenerate the HTML element
|
|
1305
|
+
// containing the values.
|
|
1321
1306
|
|
|
1322
1307
|
function updateRow(row, columns, values) {
|
|
1323
1308
|
var key;
|
|
1324
1309
|
var needUpdate = false;
|
|
1325
|
-
|
|
1326
1310
|
for (key in values) {
|
|
1327
|
-
var value = values[key];
|
|
1311
|
+
var value = values[key];
|
|
1312
|
+
|
|
1313
|
+
// If this key is not already in the row, create a new entry
|
|
1328
1314
|
// for it:
|
|
1329
1315
|
|
|
1330
1316
|
if (!(key in row.values)) {
|
|
1331
1317
|
row.values[key] = [];
|
|
1332
|
-
}
|
|
1333
|
-
// add it if we have already added it:
|
|
1318
|
+
}
|
|
1334
1319
|
|
|
1320
|
+
// Possibly add this new value to the list, but don't
|
|
1321
|
+
// add it if we have already added it:
|
|
1335
1322
|
|
|
1336
1323
|
if (!valueInList(value, row.values[key])) {
|
|
1337
1324
|
row.values[key].push(value);
|
|
1338
1325
|
needUpdate = true;
|
|
1339
1326
|
}
|
|
1340
|
-
}
|
|
1327
|
+
}
|
|
1341
1328
|
|
|
1329
|
+
// Regenerate the HTML row?
|
|
1342
1330
|
|
|
1343
1331
|
if (needUpdate) {
|
|
1344
1332
|
clearElement(row._htmlRow);
|
|
1345
1333
|
renderTableRowInto(row._htmlRow, row, columns);
|
|
1346
1334
|
}
|
|
1347
|
-
|
|
1348
1335
|
applyColumnFiltersToRow(row, columns); // Hide immediately if nec
|
|
1349
|
-
}
|
|
1350
|
-
// URI; if the subject has no URI, a unique ID is assigned.
|
|
1336
|
+
}
|
|
1351
1337
|
|
|
1338
|
+
// Get a unique ID for the given subject. This is normally the
|
|
1339
|
+
// URI; if the subject has no URI, a unique ID is assigned.
|
|
1352
1340
|
|
|
1353
1341
|
function getSubjectId(subject) {
|
|
1354
1342
|
if ('uri' in subject) {
|
|
@@ -1361,27 +1349,26 @@ function renderTableViewPane(doc, options) {
|
|
|
1361
1349
|
++subjectIdCounter;
|
|
1362
1350
|
return result;
|
|
1363
1351
|
}
|
|
1364
|
-
}
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// Run a query and populate the table.
|
|
1365
1355
|
// Populates also an array of logical rows. This will be empty when the function
|
|
1366
1356
|
// first returns (as the query is performed in the background)
|
|
1367
1357
|
|
|
1368
|
-
|
|
1369
1358
|
function runQuery(query, rows, columns, table) {
|
|
1370
1359
|
query.running = true;
|
|
1371
1360
|
var startTime = Date.now();
|
|
1372
1361
|
var progressMessage = doc.createElement('tr');
|
|
1373
1362
|
table.appendChild(progressMessage);
|
|
1374
1363
|
progressMessage.textContent = 'Loading ...';
|
|
1375
|
-
|
|
1376
1364
|
for (var i = 0; i < rows.length; i++) {
|
|
1377
1365
|
rows[i].original = true;
|
|
1378
|
-
|
|
1379
1366
|
if (!rows[i].originalValues) {
|
|
1380
1367
|
// remember first set
|
|
1381
1368
|
rows[i].originalValues = rows[i].values;
|
|
1382
1369
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1370
|
+
rows[i].values = {};
|
|
1371
|
+
// oldStyle = rows[i]._htmlRow.getAttribute('style') || ''
|
|
1385
1372
|
// rows[i]._htmlRow.style.background = '#ffe'; //setAttribute('style', ' background-color: #ffe;')// yellow
|
|
1386
1373
|
}
|
|
1387
1374
|
|
|
@@ -1389,23 +1376,27 @@ function renderTableViewPane(doc, options) {
|
|
|
1389
1376
|
if (!query.running) {
|
|
1390
1377
|
return;
|
|
1391
1378
|
}
|
|
1392
|
-
|
|
1393
1379
|
progressMessage.textContent += '.'; // give a progress bar
|
|
1394
1380
|
|
|
1395
1381
|
var row = null;
|
|
1396
1382
|
var rowKey = null;
|
|
1397
|
-
var rowKeyId;
|
|
1383
|
+
var rowKeyId;
|
|
1384
|
+
|
|
1385
|
+
// If the query has a row key, use it to look up the row.
|
|
1398
1386
|
|
|
1399
1387
|
if (keyVariable in values) {
|
|
1400
1388
|
rowKey = values[keyVariable];
|
|
1401
|
-
rowKeyId = getSubjectId(rowKey);
|
|
1389
|
+
rowKeyId = getSubjectId(rowKey);
|
|
1390
|
+
|
|
1391
|
+
// Do we have a row for this already?
|
|
1402
1392
|
// If so, reuse it; otherwise, we must create a new row.
|
|
1403
1393
|
|
|
1404
1394
|
if (rowKeyId in rowsLookup) {
|
|
1405
1395
|
row = rowsLookup[rowKeyId];
|
|
1406
1396
|
}
|
|
1407
|
-
}
|
|
1397
|
+
}
|
|
1408
1398
|
|
|
1399
|
+
// Create a new row?
|
|
1409
1400
|
|
|
1410
1401
|
if (!row) {
|
|
1411
1402
|
var tr = doc.createElement('tr');
|
|
@@ -1416,27 +1407,23 @@ function renderTableViewPane(doc, options) {
|
|
|
1416
1407
|
values: {}
|
|
1417
1408
|
};
|
|
1418
1409
|
rows.push(row);
|
|
1419
|
-
|
|
1420
1410
|
if (rowKey) {
|
|
1421
1411
|
rowsLookup[rowKeyId] = row;
|
|
1422
1412
|
}
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1413
|
+
}
|
|
1425
1414
|
|
|
1415
|
+
// Add the new values to this row.
|
|
1426
1416
|
delete row.original; // This is included in the new data
|
|
1427
|
-
|
|
1428
1417
|
updateRow(row, columns, values);
|
|
1429
1418
|
};
|
|
1430
|
-
|
|
1431
1419
|
var onDone = function onDone() {
|
|
1432
1420
|
if (progressMessage && progressMessage.parentNode && progressMessage.parentNode.removeChild) {
|
|
1433
1421
|
progressMessage.parentNode.removeChild(progressMessage);
|
|
1434
1422
|
progressMessage = null;
|
|
1435
1423
|
}
|
|
1436
|
-
|
|
1437
1424
|
var elapsedTimeMS = Date.now() - startTime;
|
|
1438
|
-
debug.log('Query done: ' + rows.length + ' rows, ' + elapsedTimeMS + 'ms');
|
|
1439
|
-
|
|
1425
|
+
debug.log('Query done: ' + rows.length + ' rows, ' + elapsedTimeMS + 'ms');
|
|
1426
|
+
// Delete rows which were from old values not new
|
|
1440
1427
|
for (var _i4 = rows.length - 1; _i4 >= 0; _i4--) {
|
|
1441
1428
|
// backwards
|
|
1442
1429
|
if (rows[_i4].original) {
|
|
@@ -1447,27 +1434,27 @@ function renderTableViewPane(doc, options) {
|
|
|
1447
1434
|
rows.splice(_i4, 1);
|
|
1448
1435
|
}
|
|
1449
1436
|
}
|
|
1450
|
-
|
|
1451
1437
|
if (options.sortBy) {
|
|
1452
1438
|
// @@ for each column check needs sorting
|
|
1453
1439
|
var column = getColumnForVariable(columns, options.sortBy);
|
|
1454
1440
|
literalSort(rows, column, options.sortReverse);
|
|
1455
1441
|
}
|
|
1456
|
-
|
|
1457
1442
|
if (options.onDone) options.onDone(resultDiv); // return div makes testing easier
|
|
1458
1443
|
};
|
|
1459
1444
|
|
|
1460
1445
|
kb.query(query, onResult, undefined, onDone);
|
|
1461
|
-
}
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
// Given the formula object which is the query pattern,
|
|
1462
1449
|
// deduce from where the variable occurs constraints on
|
|
1463
1450
|
// what values it can take.
|
|
1464
1451
|
|
|
1465
|
-
|
|
1466
1452
|
function inferColumnsFromFormula(columns, formula) {
|
|
1467
1453
|
UI.log.debug('>> processing formula');
|
|
1468
|
-
|
|
1469
1454
|
for (var i = 0; i < formula.statements.length; ++i) {
|
|
1470
|
-
var statement = formula.statements[i];
|
|
1455
|
+
var statement = formula.statements[i];
|
|
1456
|
+
// UI.log.debug("processing statement " + i)
|
|
1457
|
+
|
|
1471
1458
|
// Does it match this?:
|
|
1472
1459
|
// <something> <predicate> ?var
|
|
1473
1460
|
// If so, we can use the predicate as the predicate for the
|
|
@@ -1475,40 +1462,37 @@ function renderTableViewPane(doc, options) {
|
|
|
1475
1462
|
|
|
1476
1463
|
if (statement.predicate.termType === 'NamedNode' && statement.object.termType === 'Variable') {
|
|
1477
1464
|
var variable = statement.object.toString();
|
|
1478
|
-
|
|
1479
1465
|
if (variable in columns) {
|
|
1480
1466
|
var column = columns[variable];
|
|
1481
1467
|
column.setPredicate(statement.predicate, false, statement.subject);
|
|
1482
1468
|
}
|
|
1483
1469
|
}
|
|
1484
|
-
|
|
1485
1470
|
if (statement.predicate.termType === 'NamedNode' && statement.subject.termType === 'Variable') {
|
|
1486
1471
|
var _variable = statement.subject.toString();
|
|
1487
|
-
|
|
1488
1472
|
if (_variable in columns) {
|
|
1489
1473
|
var _column = columns[_variable];
|
|
1490
|
-
|
|
1491
1474
|
_column.setPredicate(statement.predicate, true, statement.object);
|
|
1492
1475
|
}
|
|
1493
1476
|
}
|
|
1494
|
-
}
|
|
1477
|
+
}
|
|
1495
1478
|
|
|
1479
|
+
// Apply to OPTIONAL formulas:
|
|
1496
1480
|
|
|
1497
1481
|
for (var _i5 = 0; _i5 < formula.optional.length; ++_i5) {
|
|
1498
1482
|
UI.log.debug('recurse to optional subformula ' + _i5);
|
|
1499
1483
|
inferColumnsFromFormula(columns, formula.optional[_i5]);
|
|
1500
1484
|
}
|
|
1501
|
-
|
|
1502
1485
|
UI.log.debug('<< finished processing formula');
|
|
1503
|
-
}
|
|
1504
|
-
// predicates based on the contents of the query
|
|
1486
|
+
}
|
|
1505
1487
|
|
|
1488
|
+
// Generate a list of column structures and infer details about the
|
|
1489
|
+
// predicates based on the contents of the query
|
|
1506
1490
|
|
|
1507
1491
|
function inferColumns(query) {
|
|
1508
1492
|
// Generate the columns list:
|
|
1493
|
+
|
|
1509
1494
|
var result = [];
|
|
1510
1495
|
var columns = {};
|
|
1511
|
-
|
|
1512
1496
|
for (var i = 0; i < query.vars.length; ++i) {
|
|
1513
1497
|
var column = new Column();
|
|
1514
1498
|
var queryVar = query.vars[i];
|
|
@@ -1517,58 +1501,60 @@ function renderTableViewPane(doc, options) {
|
|
|
1517
1501
|
columns[queryVar] = column;
|
|
1518
1502
|
result.push(column);
|
|
1519
1503
|
}
|
|
1520
|
-
|
|
1521
1504
|
inferColumnsFromFormula(columns, query.pat);
|
|
1522
1505
|
return result;
|
|
1523
|
-
}
|
|
1506
|
+
}
|
|
1524
1507
|
|
|
1508
|
+
// Generate a table from a query.
|
|
1525
1509
|
|
|
1526
1510
|
function renderTableForQuery(query, type) {
|
|
1527
1511
|
// infer columns from query, to allow generic queries
|
|
1528
1512
|
var columns;
|
|
1529
|
-
|
|
1530
1513
|
if (!givenQuery) {
|
|
1531
1514
|
columns = type.getColumns();
|
|
1532
1515
|
} else {
|
|
1533
1516
|
columns = inferColumns(query);
|
|
1534
|
-
}
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
// Start with an empty list of rows; this will be populated
|
|
1535
1520
|
// by the query.
|
|
1536
1521
|
|
|
1522
|
+
var rows = [];
|
|
1537
1523
|
|
|
1538
|
-
|
|
1524
|
+
// Create table element and header.
|
|
1539
1525
|
|
|
1540
1526
|
var table = doc.createElement('table');
|
|
1541
1527
|
table.appendChild(renderTableHeader(columns, type));
|
|
1542
|
-
table.appendChild(renderTableSelectors(rows, columns));
|
|
1528
|
+
table.appendChild(renderTableSelectors(rows, columns));
|
|
1529
|
+
|
|
1530
|
+
// Run query. Note that this is perform asynchronously; the
|
|
1543
1531
|
// query runs in the background and this call does not block.
|
|
1544
1532
|
|
|
1545
1533
|
table.logicalRows = rows; // Save for refresh
|
|
1546
|
-
|
|
1547
1534
|
table.columns = columns;
|
|
1548
1535
|
table.query = query;
|
|
1549
1536
|
runQuery(query, rows, columns, table);
|
|
1550
1537
|
return table;
|
|
1551
|
-
}
|
|
1538
|
+
}
|
|
1552
1539
|
|
|
1540
|
+
// Find the most common type of row
|
|
1553
1541
|
|
|
1554
1542
|
function getMostCommonType(types) {
|
|
1555
1543
|
var bestCount = -1;
|
|
1556
1544
|
var best = null;
|
|
1557
1545
|
var typeUri;
|
|
1558
|
-
|
|
1559
1546
|
for (typeUri in types) {
|
|
1560
1547
|
var type = types[typeUri];
|
|
1561
|
-
|
|
1562
1548
|
if (type.useCount > bestCount) {
|
|
1563
1549
|
best = type;
|
|
1564
1550
|
bestCount = type.useCount;
|
|
1565
1551
|
}
|
|
1566
1552
|
}
|
|
1567
|
-
|
|
1568
1553
|
return best;
|
|
1569
|
-
}
|
|
1570
|
-
// specified rows.
|
|
1554
|
+
}
|
|
1571
1555
|
|
|
1556
|
+
// Filter list of columns to only those columns used in the
|
|
1557
|
+
// specified rows.
|
|
1572
1558
|
/*
|
|
1573
1559
|
function filterColumns (columns, rows) {
|
|
1574
1560
|
var filteredColumns = {}
|
|
@@ -1585,7 +1571,8 @@ function renderTableViewPane(doc, options) {
|
|
|
1585
1571
|
return filteredColumns
|
|
1586
1572
|
}
|
|
1587
1573
|
*/
|
|
1574
|
+
}
|
|
1575
|
+
// ///////////////////////////////////////////////////////////////////
|
|
1588
1576
|
|
|
1589
|
-
} // ///////////////////////////////////////////////////////////////////
|
|
1590
1577
|
// ENDS
|
|
1591
1578
|
//# sourceMappingURL=table.js.map
|