UNPKG

solid-panes

Version:

Solid-compatible Panes: applets and views for the mashlib and databrowser

294 lines (235 loc) • 9.88 kB
"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