/** * Contains the logic for the sidebar. * @param graph the graph that belongs to these controls * @returns {{}} */ module.exports = function ( graph ){ var sidebar = {}, languageTools = webvowl.util.languageTools(), elementTools = webvowl.util.elementTools(), // Required for reloading when the language changes ontologyInfo, visibleSidebar = 1, lastSelectedElement, detailArea = d3.select("#detailsArea"), graphArea = d3.select("#canvasArea"), menuArea = d3.select("#swipeBarContainer"), collapseButton = d3.select("#sidebarExpandButton"); /** * Setup the menu bar. */ function setupCollapsing(){ // adapted version of this example: http://www.normansblog.de/simple-jquery-accordion/ function collapseContainers( containers ){ containers.classed("hidden", true); } function expandContainers( containers ){ containers.classed("hidden", false); } var triggers = d3.selectAll(".accordion-trigger"); // Collapse all inactive triggers on startup collapseContainers(d3.selectAll(".accordion-trigger:not(.accordion-trigger-active) + div")); triggers.on("click", function (){ var selectedTrigger = d3.select(this), activeTriggers = d3.selectAll(".accordion-trigger-active"); if ( selectedTrigger.classed("accordion-trigger-active") ) { // Collapse the active (which is also the selected) trigger collapseContainers(d3.select(selectedTrigger.node().nextElementSibling)); selectedTrigger.classed("accordion-trigger-active", false); } else { // Collapse the other trigger ... collapseContainers(d3.selectAll(".accordion-trigger-active + div")); activeTriggers.classed("accordion-trigger-active", false); // ... and expand the selected one expandContainers(d3.select(selectedTrigger.node().nextElementSibling)); selectedTrigger.classed("accordion-trigger-active", true); } }); } sidebar.clearOntologyInformation = function (){ d3.select("#ontology-panel").selectAll("*").remove(); clearSelectedNodePanel(); }; /** * Updates the information of the passed ontology. * @param data the graph data * @param statistics the statistics module */ sidebar.updateOntologyInformation = function ( data, statistics ){ data = data || {}; ontologyInfo = data.header || {}; var panel = d3.select("#ontology-panel"); panel.selectAll("*").remove(); renderPair(panel, "IRI", ontologyInfo.iri, ontologyInfo.iri); var title = languageTools.textInLanguage(ontologyInfo.title, graph.language()); renderPair(panel, "Title", title); renderPair(panel, "Version", ontologyInfo.version); var authors = ontologyInfo.author; if ( authors instanceof Array ) authors = authors.join(", "); renderPair(panel, "Author", authors); var description = languageTools.textInLanguage(ontologyInfo.description, graph.language()); renderPair(panel, "Description", description); var other = ontologyInfo.other || {}; for ( var key in other ) { if ( other.hasOwnProperty(key) ) { var ann = other[key][0]; if ( ann ) { renderPair(panel, ann.identifier, ann.value, ann.type === "iri" ? ann.value : undefined); } } } if ( panel.selectAll(".annotation-row").size() === 0 ) { panel.append("p").classed("no-selection-hint", true).text("No ontology information available."); } sidebar.updateSelectionInformation(undefined); setLanguages(ontologyInfo.languages); }; function setLanguages( languages ){ languages = languages || []; // Put the default and unset label on top of the selection labels languages.sort(function ( a, b ){ if ( a === webvowl.util.constants().LANG_IRIBASED ) { return -1; } else if ( b === webvowl.util.constants().LANG_IRIBASED ) { return 1; } if ( a === webvowl.util.constants().LANG_UNDEFINED ) { return -1; } else if ( b === webvowl.util.constants().LANG_UNDEFINED ) { return 1; } return a.localeCompare(b); }); var languageSelection = d3.select("#language") .on("change", function (){ graph.language(d3.event.target.value); updateGraphInformation(); sidebar.updateSelectionInformation(lastSelectedElement); }); languageSelection.selectAll("option").remove(); languageSelection.selectAll("option") .data(languages) .enter().append("option") .attr("value", function ( d ){ return d; }) .text(function ( d ){ return d; }); if ( !trySelectDefaultLanguage(languageSelection, languages, "en") ) { if ( !trySelectDefaultLanguage(languageSelection, languages, webvowl.util.constants().LANG_UNDEFINED) ) { trySelectDefaultLanguage(languageSelection, languages, webvowl.util.constants().LANG_IRIBASED); } } } function trySelectDefaultLanguage( selection, languages, language ){ var langIndex = languages.indexOf(language); if ( langIndex >= 0 ) { selection.property("selectedIndex", langIndex); graph.language(language); return true; } return false; } function renderPair( container, name, value, iri ){ if ( !value && value !== 0 ) return; var row = container.append("div").classed("annotation-row", true); row.append("span").classed("annotation-name", true).text(name); var valSpan = row.append("span").classed("annotation-value", true); appendIriLabel(valSpan, value, iri); } function clearSelectedNodePanel(){ var panel = d3.select("#selected-node-panel"); panel.selectAll("*").remove(); panel.append("p").classed("no-selection-hint", true).text("Select an element in the visualization."); } /** * Update the information of the selected node. * @param selectedElement the selection or null if nothing is selected */ sidebar.updateSelectionInformation = function ( selectedElement ){ lastSelectedElement = selectedElement; if ( d3.event && d3.event.defaultPrevented ) { return; } if ( !selectedElement ) { clearSelectedNodePanel(); return; } if ( elementTools.isProperty(selectedElement) ) { displayPropertyInformation(selectedElement); } else if ( elementTools.isNode(selectedElement) ) { displayNodeInformation(selectedElement); } }; function displayPropertyInformation( property ){ var panel = d3.select("#selected-node-panel"); panel.selectAll("*").remove(); renderPair(panel, "IRI", property.iri(), property.iri()); renderPair(panel, "Label", property.labelForCurrentLanguage()); renderPair(panel, "Type", property.type()); if ( property.domain() ) renderPair(panel, "Domain", property.domain().labelForCurrentLanguage(), property.domain().iri()); if ( property.range() ) renderPair(panel, "Range", property.range().labelForCurrentLanguage(), property.range().iri()); if ( property.inverse() ) renderPair(panel, "Inverse", property.inverse().labelForCurrentLanguage(), property.inverse().iri()); renderNodeArrayPairs(panel, "Equivalent", property.equivalents()); renderNodeArrayPairs(panel, "Subproperty", property.subproperties()); renderNodeArrayPairs(panel, "Superproperty", property.superproperties()); if ( property.minCardinality() !== undefined ) { renderPair(panel, "Min. cardinality", property.minCardinality()); renderPair(panel, "Max. cardinality", property.maxCardinality() !== undefined ? property.maxCardinality() : "*"); } else if ( property.cardinality() !== undefined ) { renderPair(panel, "Cardinality", property.cardinality()); } var attrs = getAttributes(property.attributes()); if ( attrs ) renderPair(panel, "Characteristics", attrs); renderPair(panel, "Description", property.descriptionForCurrentLanguage()); renderPair(panel, "Comment", property.commentForCurrentLanguage()); renderAnnotationPairs(panel, property.annotations()); } function getAttributes( attributes ){ if ( !attributes || attributes.length === 0 ) return null; var filtered = attributes.filter(function ( a ){ return a !== "object" && a !== "datatype" && a !== "rdf"; }); return filtered.length > 0 ? filtered.join(", ") : null; } function renderNodeArrayPairs( panel, label, nodes ){ if ( !nodes || nodes.length === 0 ) return; nodes.forEach(function ( el ){ renderPair(panel, label, el.labelForCurrentLanguage(), el.iri()); }); } function renderAnnotationPairs( panel, annotationObject ){ annotationObject = annotationObject || {}; for ( var key in annotationObject ) { if ( annotationObject.hasOwnProperty(key) ) { var ann = annotationObject[key][0]; if ( ann ) renderPair(panel, ann.identifier, ann.value, ann.type === "iri" ? ann.value : undefined); } } } function appendIriLabel( element, name, iri ){ var tag; if ( iri ) { tag = element.append("a") .attr("href", iri) .attr("title", iri) .attr("target", "_blank"); } else { tag = element.append("span"); } tag.text(name); } function displayNodeInformation( node ){ var panel = d3.select("#selected-node-panel"); panel.selectAll("*").remove(); renderPair(panel, "IRI", node.iri(), node.iri()); renderPair(panel, "Label", node.labelForCurrentLanguage()); renderPair(panel, "Type", node.type()); renderNodeArrayPairs(panel, "Equivalent", node.equivalents()); renderNodeArrayPairs(panel, "Disjoint with", node.disjointWith()); renderNodeArrayPairs(panel, "Individual", node.individuals()); var attrs = getAttributes(node.attributes()); if ( attrs ) renderPair(panel, "Characteristics", attrs); renderPair(panel, "Description", node.descriptionForCurrentLanguage()); renderPair(panel, "Comment", node.commentForCurrentLanguage()); renderAnnotationPairs(panel, node.annotations()); } /** Collapsible Sidebar functions; **/ sidebar.showSidebar = function ( val, init ){ // make val to bool if ( val === 1 ) { visibleSidebar = true; collapseButton.node().innerHTML = ">"; detailArea.classed("hidden", true); if ( init === true ) { detailArea.classed("hidden", !visibleSidebar); graphArea.style("width", "78%"); graphArea.style("-webkit-animation-name", "none"); menuArea.style("width", "78%"); menuArea.style("-webkit-animation-name", "none"); d3.select("#WarningErrorMessagesContainer").style("width", "78%"); d3.select("#WarningErrorMessagesContainer").style("-webkit-animation-name", "none"); } else { graphArea.style("width", "78%"); graphArea.style("-webkit-animation-name", "sbCollapseAnimation"); graphArea.style("-webkit-animation-duration", "0.5s"); menuArea.style("width", "78%"); menuArea.style("-webkit-animation-name", "sbCollapseAnimation"); menuArea.style("-webkit-animation-duration", "0.5s"); d3.select("#WarningErrorMessagesContainer").style("width", "78%"); d3.select("#WarningErrorMessagesContainer").style("-webkit-animation-name", "warn_ExpandRightBarAnimation"); d3.select("#WarningErrorMessagesContainer").style("-webkit-animation-duration", "0.5s"); } graph.options().width(window.innerWidth - (window.innerWidth * 0.22)); graph.options().navigationMenu().updateScrollButtonVisibility(); } if ( val === 0 ) { visibleSidebar = false; detailArea.classed("hidden", true); collapseButton.node().innerHTML = "<"; // adjust the layout if ( init === true ) { graphArea.style("width", "100%"); graphArea.style("-webkit-animation-name", "none"); menuArea.style("width", "100%"); menuArea.style("-webkit-animation-name", "none"); d3.select("#WarningErrorMessagesContainer").style("width", "100%"); d3.select("#WarningErrorMessagesContainer").style("-webkit-animation-name", "none"); } else { graphArea.style("width", "100%"); graphArea.style("-webkit-animation-name", "sbExpandAnimation"); graphArea.style("-webkit-animation-duration", "0.5s"); menuArea.style("width", "100%"); menuArea.style("-webkit-animation-name", "sbExpandAnimation"); menuArea.style("-webkit-animation-duration", "0.5s"); d3.select("#WarningErrorMessagesContainer").style("width", "100%"); d3.select("#WarningErrorMessagesContainer").style("-webkit-animation-name", "warn_CollapseRightBarAnimation"); d3.select("#WarningErrorMessagesContainer").style("-webkit-animation-duration", "0.5s"); } graph.options().width(window.innerWidth); graph.updateCanvasContainerSize(); graph.options().navigationMenu().updateScrollButtonVisibility(); } }; sidebar.isSidebarVisible = function (){ return visibleSidebar; }; sidebar.updateSideBarVis = function ( init ){ var vis = sidebar.getSidebarVisibility(); sidebar.showSidebar(parseInt(vis), init); }; sidebar.getSidebarVisibility = function (){ var isHidden = detailArea.classed("hidden"); if ( isHidden === false ) return String(1); if ( isHidden === true ) return String(0); }; sidebar.initSideBarAnimation = function (){ graphArea.node().addEventListener("animationend", function (){ detailArea.classed("hidden", !visibleSidebar); graph.updateCanvasContainerSize(); graph.options().navigationMenu().updateScrollButtonVisibility(); }); }; sidebar.setup = function (){ setupCollapsing(); sidebar.initSideBarAnimation(); collapseButton.on("click", function (){ graph.options().navigationMenu().hideAllMenus(); var settingValue = parseInt(sidebar.getSidebarVisibility()); if ( settingValue === 1 ) sidebar.showSidebar(0); else sidebar.showSidebar(1); }); }; sidebar.updateShowedInformation = function (){ var editMode = graph.editorMode(); d3.select("#generalDetails").classed("hidden", editMode); d3.select("#generalDetailsEdit").classed("hidden", !editMode); // store the meta information in graph.options() // todo: update edit meta info graph.options().editSidebar().updateGeneralOntologyInfo(); // todo: update showed meta info; graph.options().sidebar().updateGeneralOntologyInfo(); }; sidebar.updateGeneralOntologyInfo = function (){ // get it from graph.options var generalMetaObj = graph.options().getGeneralMetaObject(); var preferredLanguage = graph && graph.language ? graph.language() : null; if ( generalMetaObj.hasOwnProperty("title") ) { // title has language to it -.- if ( typeof generalMetaObj.title === "object" ) { d3.select("#title").node().value = languageTools.textInLanguage(generalMetaObj.title, preferredLanguage); } else { d3.select("#title").node().innerHTML = generalMetaObj.title; } } if ( generalMetaObj.hasOwnProperty("iri") ) d3.select("#about").node().innerHTML = generalMetaObj.iri; if ( generalMetaObj.hasOwnProperty("iri") ) d3.select("#about").node().href = generalMetaObj.iri; if ( generalMetaObj.hasOwnProperty("version") ) d3.select("#version").node().innerHTML = generalMetaObj.version; if ( generalMetaObj.hasOwnProperty("author") ) d3.select("#authors").node().innerHTML = generalMetaObj.author; // this could also be an object >> if ( generalMetaObj.hasOwnProperty("description") ) { if ( typeof generalMetaObj.description === "object" ) { d3.select("#description").node().innerHTML = languageTools.textInLanguage(generalMetaObj.description, preferredLanguage); } else { d3.select("#description").node().innerHTML = generalMetaObj.description; } } }; return sidebar; };