solid-panes
Version:
Solid-compatible Panes: applets and views for the mashlib and databrowser
294 lines (235 loc) • 9.88 kB
JavaScript
"use strict";
/* Data content Pane
**
** This pane shows the content of a particular RDF resource
** or at least the RDF semantics we attribute to that resource.
*/
// To do: - Only take data from one graph
// - Only do forwards not backward?
// - Expand automatically all the way down
// - original source view? Use ffox view source
var UI = require('solid-ui');
var $rdf = require('rdflib');
var ns = UI.ns;
module.exports = {
icon: UI.icons.originalIconBase + 'rdf_flyer.24.gif',
name: 'dataContents',
audience: [ns.solid('Developer')],
label: function label(subject, context) {
if ('http://www.w3.org/2007/ont/link#ProtocolEvent' in context.session.store.findTypeURIs(subject)) {
return null;
}
var n = context.session.store.statementsMatching(undefined, undefined, undefined, subject).length;
if (n === 0) return null;
return 'Data (' + n + ')';
},
/*
shouldGetFocus: function(subject) {
return UI.store.whether(subject, UI.ns.rdf('type'), UI.ns.link('RDFDocument'))
},
*/
statementsAsTables: function statementsAsTables(sts, context, initialRoots) {
var myDocument = context.dom; // var outliner = context.getOutliner(myDocument)
var rep = myDocument.createElement('table');
var sz = UI.rdf.Serializer(context.session.store);
var res = sz.rootSubjects(sts);
var roots = res.roots;
var subjects = res.subjects;
var loopBreakers = res.loopBreakers;
for (var x in loopBreakers) {
console.log('\tdataContentPane: loopbreaker:' + x);
}
var doneBnodes = {}; // For preventing looping
var referencedBnodes = {}; // Bnodes which need to be named alas
// The property tree for a single subject or anonymous node
function propertyTree(subject) {
// print('Proprty tree for '+subject)
var rep = myDocument.createElement('table');
var lastPred = null;
var sts = subjects[sz.toStr(subject)]; // relevant statements
if (!sts) {
// No statements in tree
rep.appendChild(myDocument.createTextNode('...')); // just empty bnode as object
return rep;
}
sts.sort();
var same = 0;
var predicateTD; // The cell which holds the predicate
for (var i = 0; i < sts.length; i++) {
var st = sts[i];
var tr = myDocument.createElement('tr');
if (st.predicate.uri !== lastPred) {
if (lastPred && same > 1) {
predicateTD.setAttribute('rowspan', '' + same);
}
predicateTD = myDocument.createElement('td');
predicateTD.setAttribute('class', 'pred');
var anchor = myDocument.createElement('a');
anchor.setAttribute('href', st.predicate.uri);
anchor.addEventListener('click', UI.widgets.openHrefInOutlineMode, true);
anchor.appendChild(myDocument.createTextNode(UI.utils.predicateLabelForXML(st.predicate)));
predicateTD.appendChild(anchor);
tr.appendChild(predicateTD);
lastPred = st.predicate.uri;
same = 0;
}
same++;
var objectTD = myDocument.createElement('td');
objectTD.appendChild(objectTree(st.object));
tr.appendChild(objectTD);
rep.appendChild(tr);
}
if (lastPred && same > 1) predicateTD.setAttribute('rowspan', '' + same);
return rep;
} // Convert a set of statements into a nested tree of tables
function objectTree(obj) {
var res, anchor;
switch (obj.termType) {
case 'NamedNode':
anchor = myDocument.createElement('a');
anchor.setAttribute('href', obj.uri);
anchor.addEventListener('click', UI.widgets.openHrefInOutlineMode, true);
anchor.appendChild(myDocument.createTextNode(UI.utils.label(obj)));
return anchor;
case 'Literal':
if (!obj.datatype || !obj.datatype.uri) {
res = myDocument.createElement('div');
res.setAttribute('style', 'white-space: pre-wrap;');
res.textContent = obj.value;
return res;
} else if (obj.datatype.uri === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral') {
res = myDocument.createElement('div');
res.setAttribute('class', 'embeddedXHTML');
res.innerHTML = obj.value; // Try that @@@ beware embedded dangerous code
return res;
}
return myDocument.createTextNode(obj.value);
// placeholder - could be smarter,
case 'BlankNode':
if (obj.toNT() in doneBnodes) {
// Break infinite recursion
referencedBnodes[obj.toNT()] = true;
var _anchor = myDocument.createElement('a');
_anchor.setAttribute('href', '#' + obj.toNT().slice(2));
_anchor.setAttribute('class', 'bnodeRef');
_anchor.textContent = '*' + obj.toNT().slice(3);
return _anchor;
}
doneBnodes[obj.toNT()] = true; // Flag to prevent infinite recursion in propertyTree
var newTable = propertyTree(obj);
doneBnodes[obj.toNT()] = newTable; // Track where we mentioned it first
if (UI.utils.ancestor(newTable, 'TABLE') && UI.utils.ancestor(newTable, 'TABLE').style.backgroundColor === 'white') {
newTable.style.backgroundColor = '#eee';
} else {
newTable.style.backgroundColor = 'white';
}
return newTable;
case 'Collection':
res = myDocument.createElement('table');
res.setAttribute('class', 'collectionAsTables');
for (var i = 0; i < obj.elements.length; i++) {
var tr = myDocument.createElement('tr');
res.appendChild(tr);
tr.appendChild(objectTree(obj.elements[i]));
}
return res;
case 'Graph':
res = context.session.paneRegistry.byName('dataContents').statementsAsTables(obj.statements, context);
res.setAttribute('class', 'nestedFormula');
return res;
case 'Variable':
res = myDocument.createTextNode('?' + obj.uri);
return res;
}
throw new Error('Unhandled node type: ' + obj.termType);
} // roots.sort()
if (initialRoots) {
roots = initialRoots.concat(roots.filter(function (x) {
for (var i = 0; i < initialRoots.length; i++) {
// Max 2
if (x.sameTerm(initialRoots[i])) return false;
}
return true;
}));
}
for (var i = 0; i < roots.length; i++) {
var tr = myDocument.createElement('tr');
rep.appendChild(tr);
var subjectTD = myDocument.createElement('td');
tr.appendChild(subjectTD);
var TDTree = myDocument.createElement('td');
tr.appendChild(TDTree);
var root = roots[i];
if (root.termType === 'BlankNode') {
subjectTD.appendChild(myDocument.createTextNode(UI.utils.label(root))); // Don't recurse!
} else {
subjectTD.appendChild(objectTree(root)); // won't have tree
}
TDTree.appendChild(propertyTree(root));
}
for (var bNT in referencedBnodes) {
// Add number to refer to
var table = doneBnodes[bNT]; // let tr = myDocument.createElement('tr')
var anchor = myDocument.createElement('a');
anchor.setAttribute('id', bNT.slice(2));
anchor.setAttribute('class', 'bnodeDef');
anchor.textContent = bNT.slice(3) + ')';
table.insertBefore(anchor, table.firstChild);
}
return rep;
},
// statementsAsTables
// View the data in a file in user-friendly way
render: function render(subject, context) {
var myDocument = context.dom;
function alternativeRendering() {
var sz = UI.rdf.Serializer(context.session.store);
var res = sz.rootSubjects(sts);
var roots = res.roots;
var p = {};
p.render = function (s2) {
var div = myDocument.createElement('div');
div.setAttribute('class', 'withinDocumentPane');
var plist = kb.statementsMatching(s2, undefined, undefined, subject);
outliner.appendPropertyTRs(div, plist, false, function (_pred, _inverse) {
return true;
});
return div;
};
for (var i = 0; i < roots.length; i++) {
var tr = myDocument.createElement('TR');
var root = roots[i];
tr.style.verticalAlign = 'top';
var td = outliner.outlineObjectTD(root, undefined, tr);
tr.appendChild(td);
div.appendChild(tr);
outliner.outlineExpand(td, root, {
pane: p
});
}
}
function mainRendering() {
var initialRoots = []; // Ordering: start with stuff about this doc
if (kb.holds(subject, undefined, undefined, subject)) {
initialRoots.push(subject);
} // Then about the primary topic of the document if any
var ps = kb.any(subject, UI.ns.foaf('primaryTopic'), undefined, subject);
if (ps) initialRoots.push(ps);
div.appendChild(context.session.paneRegistry.byName('dataContents').statementsAsTables(sts, context, initialRoots));
}
var outliner = context.getOutliner(myDocument);
var kb = context.session.store;
var div = myDocument.createElement('div');
div.setAttribute('class', 'dataContentPane'); // Because of smushing etc, this will not be a copy of the original source
// We could instead either fetch and re-parse the source,
// or we could keep all the pre-smushed triples.
var sts = kb.statementsMatching(undefined, undefined, undefined, subject); // @@ slow with current store!
if ($rdf.keepThisCodeForLaterButDisableFerossConstantConditionPolice) {
alternativeRendering();
} else {
mainRendering();
}
return div;
}
};
//# sourceMappingURL=dataContentPane.js.map