12
|
1 /**
|
|
2 * URL used to access Neo4j REST API to execute queries.
|
|
3 * Update this parameter to your running server instance.
|
|
4 *
|
|
5 * For more information on Neo4J REST API the documentation is available here: http://neo4j.com/docs/stable/rest-api-cypher.html
|
|
6 */
|
|
7 popoto.rest.CYPHER_URL = "https://ismi-dev.mpiwg-berlin.mpg.de/neo4j-ismi/db/data/transaction/commit";
|
|
8 //popoto.rest.CYPHER_URL = "http://localhost:7474/db/data/transaction/commit";
|
|
9
|
|
10 /**
|
|
11 * Add this authorization property if your Neo4j server uses basic HTTP authentication.
|
|
12 * The value of this property must be "Basic <payload>", where "payload" is a base64 encoded string of "username:password".
|
|
13 *
|
|
14 * "btoa" is a JavaScript function that can be used to encode the user and password value in base64 but it is recommended to directly use the Base64 value.
|
|
15 *
|
|
16 * For example Base64 encoding value of "neo4j:password" is "bmVvNGo6cGFzc3dvcmQ="
|
|
17 */
|
|
18 popoto.rest.AUTHORIZATION = "Basic " + btoa("neo4j:neo5j");
|
|
19 //popoto.rest.AUTHORIZATION = "Basic " + btoa("neo4j:eagrussell");
|
|
20
|
|
21 /**
|
|
22 * These functions fill the predefinedConstraints array for "PERSON"
|
|
23 * Called when the filter button is hit
|
|
24 *
|
|
25 * Uses the text box implementation currently
|
|
26 */
|
|
27 // TODO: finish textbox implementation as backup
|
|
28 // have single filter button which on click sets constraints equal to d3.select("#constraintNUMBS)[0][0].value
|
|
29 // for a bunch of spots in the array
|
|
30 // will have to create only 1 d3.select
|
|
31 // the d3.select will need to know what constraints to pull from input boxes based on ids related to whether they
|
|
32 // are person/codex/witness/etc attributes and put them into the corresponding arrays
|
|
33 // personPredefinedConstraints codexPreDef
|
|
34 var personPredefinedConstraints = [];
|
|
35 var codexPredefinedConstraints = [];
|
|
36 var witnessPredefinedConstraints = [];
|
|
37 d3.select("#filter-button").on("click", function (d) {
|
|
38 personPredefinedConstraints = [];
|
|
39 codexPredefinedConstraints = [];
|
|
40 witnessPredefinedConstraints = [];
|
|
41
|
|
42 var person1 = d3.select("#person-constraint")[0][0].value;
|
|
43 var person2 = d3.select("#person-constraint2")[0][0].value;
|
|
44
|
|
45 var codex1 = d3.select("#codex-constraint")[0][0].value;
|
|
46 var codex2 = d3.select("#codex-constraint2")[0][0].value;
|
|
47
|
|
48 var witness1 = d3.select("#witness-constraint")[0][0].value;
|
|
49 var witness2 = d3.select("#witness-constraint2")[0][0].value;
|
|
50
|
|
51 if (person1.substring(person1.indexOf('"')+1,person1.lastIndexOf('"'))) personPredefinedConstraints.push(person1);
|
|
52 if (person2.substring(person2.indexOf('"')+1,person2.lastIndexOf('"'))) personPredefinedConstraints.push(person2);
|
|
53
|
|
54 if (codex1.substring(codex1.indexOf('"')+1,codex1.lastIndexOf('"'))) codexPredefinedConstraints.push(codex1);
|
|
55 if (codex2.substring(codex2.indexOf('"')+1,codex2.lastIndexOf('"'))) codexPredefinedConstraints.push(codex2);
|
|
56
|
|
57 if (witness1.substring(witness1.indexOf('"')+1,witness1.lastIndexOf('"'))) witnessPredefinedConstraints.push(witness1);
|
|
58 if (witness2.substring(witness2.indexOf('"')+1,witness2.lastIndexOf('"'))) witnessPredefinedConstraints.push(witness2);
|
|
59
|
|
60 // Recreate taxonomies panel
|
|
61 d3.select("#" + popoto.taxonomy.containerId).selectAll("ul").data([]).exit().remove();
|
|
62 popoto.taxonomy.createTaxonomyPanel();
|
|
63
|
|
64 popoto.tools.reset();
|
|
65 });
|
|
66
|
|
67 d3.select("#clear-button").on("click", function (d) {
|
|
68 personPredefinedConstraints = [];
|
|
69 codexPredefinedConstraints = [];
|
|
70 witnessPredefinedConstraints = [];
|
|
71
|
|
72 // Recreate taxonomies panel
|
|
73 d3.select("#" + popoto.taxonomy.containerId).selectAll("ul").data([]).exit().remove();
|
|
74 popoto.taxonomy.createTaxonomyPanel();
|
|
75
|
|
76 popoto.tools.reset();
|
|
77 });
|
|
78
|
|
79
|
|
80 /**
|
|
81 * Define the Label provider you need for your application.
|
|
82 * This configuration is mandatory and should contain at least all the labels you could find in your graph model.
|
|
83 *
|
|
84 * In this alpha version only nodes with a label are supported.
|
|
85 *
|
|
86 * By default If no attributes are specified Neo4j internal ID will be used.
|
|
87 * These label provider configuration can be used to customize the node display in the graph.
|
|
88 * See www.popotojs.com or example for more details on available configuration options.
|
|
89 */
|
|
90 // TODO: add in predefined constraint functions for other nodeProviders
|
|
91 popoto.provider.nodeProviders = {
|
|
92 "CODEX": {
|
|
93 "returnAttributes": ["label", "ismi_id", "identifier"],
|
|
94 "displayAttribute": "label",
|
|
95 "getPredefinedConstraints": function (node) {
|
|
96 return codexPredefinedConstraints;
|
|
97 },
|
|
98 },
|
|
99 "WITNESS": {
|
|
100 "returnAttributes": ["label", "ismi_id", "folios"],
|
|
101 "displayAttribute": "label",
|
|
102 "getPredefinedConstraints": function (node) {
|
|
103 return witnessPredefinedConstraints;
|
|
104 },
|
|
105 },
|
|
106 "TEXT": {
|
|
107 "returnAttributes": ["label", "full_title", "ismi_id"],
|
|
108 "displayAttribute": "label",
|
|
109 //"getPredefinedConstraints": function (node) {
|
|
110 // return textPredefinedConstraints;
|
|
111 //},
|
|
112 },
|
|
113 "PERSON": {
|
|
114 "returnAttributes": ["label", "ismi_id", "death_date_text", "url"],
|
|
115 "displayAttribute": "label",
|
|
116 "getPredefinedConstraints": function (node) {
|
|
117 return personPredefinedConstraints;
|
|
118 },
|
|
119 },
|
|
120 "REPOSITORY": {
|
|
121 "returnAttributes": ["label", "ismi_id"],
|
|
122 "displayAttribute": "label",
|
|
123 //"getPredefinedConstraints": function (node) {
|
|
124 // return repositoryPredefinedConstraints;
|
|
125 //},
|
|
126 },
|
|
127 "FLORUIT_DATE": {
|
|
128 "isSearchable": false,
|
|
129 //"getPredefinedConstraints": function (node) {
|
|
130 // return floruitPredefinedConstraints;
|
|
131 //},
|
|
132 }
|
|
133 };
|
|
134
|
|
135 /**
|
|
136 * Popoto label provider
|
|
137 * Define the label provider used to customize the link displayed text:
|
|
138 */
|
|
139 // TODO: ensure these cover all the different relations. Commented out for now.
|
|
140 /*
|
|
141 popoto.provider.linkProvider = {
|
|
142
|
|
143 // Customize the text displayed on links:
|
|
144 "getLinkTextValue": function (link) {
|
|
145
|
|
146 // The links labels are just changed in lower case in this example.
|
|
147 // But it is possible to use a localization mechanism here to replace values.
|
|
148 if (link.type === popoto.graph.link.LinkTypes.RELATION) {
|
|
149
|
|
150 if (link.source.label == "PERSON") {
|
|
151 switch (link.label) {
|
|
152 case "was_student_of":
|
|
153 return "was student of";
|
|
154 case "is_prime_alias_name_of":
|
|
155 return "is prime alias name of";
|
|
156 case "was_born_in":
|
|
157 return "was born in";
|
|
158 case "lived_in":
|
|
159 return "lived in";
|
|
160 case "has_role":
|
|
161 return "has role";
|
|
162 case "has_floruit_date":
|
|
163 return "has floruit date";
|
|
164 case "died_in":
|
|
165 return "died in";
|
|
166 default :
|
|
167 return ""
|
|
168 }
|
|
169 }
|
|
170 if (link.source.label == "CODEX") {
|
|
171 switch (link.label) {
|
|
172 case "owned_by":
|
|
173 return "owned by";
|
|
174 case "is_alias_of":
|
|
175 return "is alias of";
|
|
176 case "is_part_of":
|
|
177 return "is part of";
|
|
178 }
|
|
179 }
|
|
180 if (link.source.label == "WITNESS") {
|
|
181 switch (link.label) {
|
|
182 case "was_copied_in":
|
|
183 return "was copied in";
|
|
184 case "was_studied_by":
|
|
185 return "was studied by";
|
|
186 case "had_patron":
|
|
187 return "had patron";
|
|
188 case "is_part_of":
|
|
189 return "is part of";
|
|
190 case "is_exemplar_of":
|
|
191 return "is exemplar of";
|
|
192 case "has_title_written_as":
|
|
193 return "has title written as";
|
|
194 case "has_author_written_as":
|
|
195 return "as author written as";
|
|
196 case "was_copied_by":
|
|
197 return "was copied by";
|
|
198 }
|
|
199 }
|
|
200 if (link.source.label == "PLACE") {
|
|
201 switch (link.label) {
|
|
202 case "is_part_of":
|
|
203 return "is part of";
|
|
204 case "is_in":
|
|
205 return "is in";
|
|
206 }
|
|
207 }
|
|
208 } else {
|
|
209 return popoto.provider.getSemanticValue(link.target);
|
|
210 }
|
|
211 }
|
|
212
|
|
213 };
|
|
214 */
|
|
215
|
|
216
|
|
217
|
|
218
|
|
219
|
|
220
|
|
221
|
|
222 //d3.select("#clear-button").on("click", function (d) {
|
|
223 // popoto.graph.node.expandNode()
|
|
224 //});
|
|
225
|
|
226 //take d3.select of any click that calls popoto.graph.node.expandNode()
|
|
227 // make sure to search in popoto.js what kind of events trigger the expandNode fn
|
|
228 //
|
|
229 // on these events, instead of executing the normal expandNode function, call a modified function that will generate an
|
|
230 // html table with the required results. Still maintaining the info being sent to results but ensuring that what is
|
|
231 // displayed is thrown into a table.
|
|
232
|
|
233 // to override the popoto.graph.node.expandNode() fn just use:
|
|
234
|
|
235 // Expand Override
|
|
236 var tableArray = [];
|
|
237 (function() {
|
|
238 var oldVersionExpand = popoto.graph.node.expandNode;
|
|
239 popoto.graph.node.expandNode = function(clickedNode) {
|
|
240 console.log("NODES OPEN");
|
|
241 //var result = oldVersionExpand.apply(this, arguments);
|
|
242 // do some more stuff
|
|
243 //return result;
|
|
244
|
|
245 var dataToAdd = clickedNode.data;
|
|
246 // Then each node is created
|
|
247 var i = 1;
|
|
248 dataToAdd.forEach(function (d) {
|
|
249 // for each of these bits of data make sure to add the id and the attributes into the html list
|
|
250 var nx = clickedNode.x;
|
|
251 var ny = clickedNode.y;
|
|
252
|
|
253 var node = {
|
|
254 "id": (++popoto.graph.node.idgen),
|
|
255 "parent": clickedNode,
|
|
256 "attributes": d,
|
|
257 "type": popoto.graph.node.NodeTypes.VALUE,
|
|
258 "label": clickedNode.label,
|
|
259 "count": d.count,
|
|
260 "x": nx,
|
|
261 "y": ny,
|
|
262 "internalID": d[popoto.query.NEO4J_INTERNAL_ID.queryInternalName]
|
|
263 };
|
|
264
|
|
265 popoto.graph.force.nodes().push(node);
|
|
266 // add this node to an array of node values
|
|
267 // popoto.graph.force.nodes().push(node);
|
|
268 tableArray.push(node);
|
|
269
|
|
270 var dd = document.getElementById("dropdown");
|
|
271 var newListOption = document.createElement("option");
|
|
272
|
|
273 // TODO: Haven't been able to
|
|
274 newListOption.text = node.internalID;
|
|
275 console.log(node.internalID);
|
|
276 dd.add(newListOption);
|
|
277
|
|
278 i++;
|
|
279 });
|
|
280
|
|
281 $('#dropdown').attr('style','visibility: visible; overflow: scroll; position: fixed; left: '+clickedNode.x+'px; bottom: '+clickedNode.y+'px; z-index: 10;');
|
|
282 //$('#dropdown').attr('style','visibility: visible; overflow: scroll; position: fixed;');
|
|
283
|
|
284 // Pin clicked node and its parent to avoid the graph to move for selection, only new value nodes will blossom around the clicked node.
|
|
285 clickedNode.fixed = true;
|
|
286
|
|
287 if (clickedNode.parent && clickedNode.parent.type !== popoto.graph.node.NodeTypes.ROOT) {
|
|
288 clickedNode.parent.fixed = true;
|
|
289 }
|
|
290 // Change node state
|
|
291 clickedNode.valueExpanded = true;
|
|
292 popoto.update();
|
|
293
|
|
294 };
|
|
295 })();
|
|
296
|
|
297 // Collapse Override
|
|
298 (function() {
|
|
299 popoto.graph.node.collapseNode = function(clickedNode) {
|
|
300
|
|
301 if (clickedNode.valueExpanded) { // node is collapsed only if it has been expanded first
|
|
302 console.log("NODES CLOSED");
|
|
303
|
|
304 popoto.logger.debug("collapseNode (" + clickedNode.label + ")");
|
|
305
|
|
306 // Node has been fixed when expanded so we unfix it back here.
|
|
307 if (clickedNode.type !== popoto.graph.node.NodeTypes.ROOT) {
|
|
308 clickedNode.fixed = false;
|
|
309 }
|
|
310
|
|
311 // Parent node too if not root
|
|
312 if (clickedNode.parent && clickedNode.parent.type !== popoto.graph.node.NodeTypes.ROOT) {
|
|
313 clickedNode.parent.fixed = false;
|
|
314 }
|
|
315
|
|
316 clickedNode.valueExpanded = false;
|
|
317 popoto.update();
|
|
318
|
|
319 $('#dropdown').attr('style','visibility: hidden; overflow: scroll; position: fixed;');
|
|
320 //TODO: need to delete existing options
|
|
321 var x = document.getElementById("dropdown");
|
|
322 for (i=x.length; i > 0; i--) {
|
|
323 if (x.length > 1) {
|
|
324 x.remove(x.length-1);
|
|
325 }
|
|
326 }
|
|
327
|
|
328 } else {
|
|
329 popoto.logger.debug("collapseNode called on an unexpanded node");
|
|
330 }
|
|
331 };
|
|
332 })();
|
|
333
|
|
334
|
|
335 d3.select("#dropdown").on("change", function (d) {
|
|
336 if (document.getElementById('dropdown').value != '- Select -') {
|
|
337 console.log(document.getElementById('dropdown').value);
|
|
338 popoto.graph.node.valueNodeClick(document.getElementById('dropdown').value);
|
|
339 }
|
|
340 });
|
|
341 // Value click override
|
|
342 (function() {
|
|
343 popoto.graph.node.valueNodeClick = function(selectValue) {
|
|
344 console.log("NODE SELECTED");
|
|
345
|
|
346 popoto.logger.debug("valueNodeClick (" + selectValue.label + ")");
|
|
347 // change this next line to take the node id from the table and pull it from the nodes list
|
|
348
|
|
349 var clickedNode;
|
|
350 for (i in tableArray) {
|
|
351 if (i.label == selectValue) {
|
|
352 clickedNode = i;
|
|
353 }
|
|
354 }
|
|
355
|
|
356 clickedNode.parent.value = clickedNode;
|
|
357 popoto.result.hasChanged = true;
|
|
358 popoto.graph.hasGraphChanged = true;
|
|
359
|
|
360 popoto.graph.node.collapseNode(clickedNode.parent);
|
|
361 };
|
|
362 })();
|
|
363
|
|
364
|
|
365 /**
|
|
366 * Here a listener is used to retrieve the total results count and update the page accordingly.
|
|
367 * This listener will be called on every graph modification.
|
|
368 */
|
|
369 popoto.result.onTotalResultCount(function (count) {
|
|
370 document.getElementById("result-total-count").innerHTML = "(" + count + ")";
|
|
371 });
|
|
372
|
|
373 /**
|
|
374 * The number of results returned can be changed with the following parameter.
|
|
375 * Default value is 100.
|
|
376 *
|
|
377 * Note that in this current alpha version no pagination mechanism is available in displayed results
|
|
378 */
|
|
379 popoto.query.RESULTS_PAGE_SIZE = 1000;
|
|
380
|
|
381
|
|
382 /**
|
|
383 * For the alpha version, popoto.js has been generated with debug traces you can activate with the following properties:
|
|
384 * The value can be one in DEBUG, INFO, WARN, ERROR, NONE.
|
|
385 *
|
|
386 * With INFO level all the executed cypher query can be seen in the navigator console.
|
|
387 * Default is NONE
|
|
388 */
|
|
389 popoto.logger.LEVEL = popoto.logger.LogLevels.INFO;
|
|
390
|
|
391 /**
|
|
392 * Start popoto.js generation.
|
|
393 * The function requires the label to use as root element in the graph.
|
|
394 */
|
|
395 popoto.start("PERSON");
|
|
396
|
|
397 /* do not zoom with scroll wheel */
|
|
398 popoto.graph.WHEEL_ZOOM_ENABLED = false;
|
|
399
|
|
400 /* show source and target relations */
|
|
401 popoto.query.USE_RELATION_DIRECTION = true;
|