Commit 79407bcd authored by Romain Loth's avatar Romain Loth

WIP better reldb entries and logic 4: js structure

read db.json conf for all sourcemodes, better reset graph at init, pass db.json node names conf to parsing for sortNodeTypes
parent b8a4907e
......@@ -90,12 +90,23 @@
"CortextDB": {
"file": "wos_climate-change_title_2014-2015.db",
"qtable": "ISItermsWhitelistV2Oct_5",
"reltemplate": "cortext_with_link"
"template": "cortext_with_link"
},
"twitter": {}
}
}
}
}
},
"graphapi": {
"__comment__": "special subproject for api sourcemode",
"__comment__": "allows setting nodetypes and reldocs for api graph sources",
"__comment__": "POSS can be avoided if 2 files; filemenu.json, nodeconfs.json",
"graphs": {
"default": {
"node0": { "name": "NGram", "reldbs": { "twitter": {} } },
"node1": { "name": "Document" }
}
}
}
}
......@@ -475,9 +475,13 @@
<!-- One tab pane
(only one with topPapers, we change content ourselves)
-->
<div class="tab-content">
<div id="topPapers" role="tabpanel" class="tab-pane active">
</div>
<div id="reldocs-boxes" class="tab-content">
<!--
exemple:
<div id="rd-0-csv" role="tabpanel" class="topPapers tab-pane active">
</div>
-->
</div>
</div>
......@@ -764,7 +768,7 @@
<script src="twlibs3/freshslider/freshslider.1.0.js" type="text/javascript" ></script>
<script src="twlibs3/readmore.js" type="text/javascript"></script>
<script src="twlibs3/tweets/widgets.js" type="text/javascript" language="javascript"></script>
<script src="twlibs3/bootstrap-native/bootstrap-native.min.js"></script>
<script src="twlibs3/bootstrap-native/bootstrap-native.js"></script>
<!-- new sigma 1.2 imports -->
<!-- <script src="twlibs3/sigma_v1.2/sigma.min.js" type="text/javascript" language="javascript"></script> -->
<script src="twlibs3/sigma_v1.2/sigma.noIndexes.js" type="text/javascript" language="javascript"></script>
......
......@@ -863,7 +863,7 @@ var TinaWebJS = function ( sigmacanvas ) {
// to init local, instance-related listeners (need to run at new sigma instance)
// args: @partialGraph = a sigma instance
this.initSigmaListeners = function(partialGraph, initialActivetypes, initialActivereltypes) {
this.initSigmaListeners = function(partialGraph, initialActivetypes, initialActivereltypes, optionalConfEntry) {
// console.log("initSigmaListeners TW.categories / types array / reltypeskeys array: ", TW.categories, initialActivetypes, initialActivereltypes)
......@@ -1053,71 +1053,100 @@ var TinaWebJS = function ( sigmacanvas ) {
}
});
// initialize reldocs tabs
// initialize reldocs tabs if declared in additionalConf
if (TW.conf.getRelatedDocs) {
let moreConfKey = optionalConfEntry || TW.File
let ul = document.getElementById('reldocs-tabs')
let divs = document.getElementById('reldocs-boxes')
// remove any previous tabs
ul.innerHTML=""
ul.innerHTML = ""
divs.innerHTML = ""
TW.gui.reldocTabs = [{},{}]
// for all existing nodetypes
for (let nodetypeId in initialActivetypes) {
let additionalConf = TW.gmenuInfos[moreConfKey][nodetypeId]
for (var possibleAPI in TW.gmenuInfos[TW.File][nodetypeId]["reldbs"]){
// create valid tabs
let newLi = document.createElement('li')
newLi.setAttribute("role", "presentation")
let newRDTab = document.createElement('a')
newRDTab.text = `${possibleAPI} (${nodetypeId==0?'sem':'soc'})`
newRDTab.href = '#topPapers'
newRDTab.setAttribute("role", "tab")
newRDTab.dataset.toggle = 'tab'
newRDTab.dataset.reldocstype = possibleAPI
newRDTab.dataset.nodetype = nodetypeId
newRDTab.setAttribute("class", `for-nodecategory-${nodetypeId}`)
if (possibleAPI == TW.conf.relatedDocsType) {
newLi.setAttribute("class", "active")
}
// add to DOM
ul.append(newLi)
newLi.append(newRDTab)
if (TW.conf.debug.logSettings)
console.log ("additionalConf for this source", additionalConf)
// keep access
TW.gui.reldocTabs[nodetypeId][possibleAPI] = newRDTab
let possibleAPIs = []
if (additionalConf.reldbs) {
possibleAPIs = additionalConf.reldbs
console.log("Tabs init from db.json")
}
// afterwards to already have all initialized rdtypes in DOM
for (let rdtype in TW.gui.reldocTabs[nodetypeId]) {
console.log("init for type", rdtype)
let tab = TW.gui.reldocTabs[nodetypeId][rdtype]
// init toggle mecanisms (bootstrap.native/#componentTab)
// (just used for the tabs active/inactive handling,
// content is *always* topPapers and we modify it ourselves)
new Tab(tab);
// add handler to switch relatedDocsType
tab.addEventListener('click', function(e){
let reldType = e.target.dataset.reldocstype
let nodeType = e.target.dataset.nodetype
let qWords = queryForType(nodeType)
console.log("getTopPapers", qWords, nodeType, reldType)
getTopPapers(qWords, nodeType, reldType, 'topPapers')
})
else {
possibleAPIs = [TW.conf.relatedDocsType]
console.log("Tabs init from default")
}
// select currently preferred reldoc tabs
if (initialActivetypes[nodetypeId]) {
TW.gui.reldocTabs[nodetypeId][TW.conf.relatedDocsType].Tab.show()
if (additionalConf.reldbs) {
for (var possibleAPI in possibleAPIs){
// the tab's id
let tabref = `rd-${nodetypeId}-${possibleAPI}`
// create valid tabs
let newLi = document.createElement('li')
newLi.setAttribute("role", "presentation")
let newRDTab = document.createElement('a')
newRDTab.text = `${possibleAPI} (${nodetypeId==0?'sem':'soc'})`
newRDTab.href = "#"+tabref
newRDTab.setAttribute("role", "tab")
newRDTab.dataset.toggle = 'tab'
newRDTab.dataset.reldocstype = possibleAPI
newRDTab.dataset.nodetype = nodetypeId
newRDTab.setAttribute("class", `for-nodecategory-${nodetypeId}`)
// keep access
TW.gui.reldocTabs[nodetypeId][possibleAPI] = newRDTab
// create corresponding content box
let newContentDiv = document.createElement('div')
newContentDiv.setAttribute("role", "tabpanel")
newContentDiv.setAttribute("class", "topPapers tab-pane")
newContentDiv.id = tabref
// add to DOM
ul.append(newLi)
newLi.append(newRDTab)
divs.append(newContentDiv)
// select currently preferred reldoc tabs
if (possibleAPI == TW.conf.relatedDocsType) {
newLi.classList.add("active")
newContentDiv.classList.add("active")
}
}
// afterwards to already have all initialized rdtypes in DOM
for (let rdtype in TW.gui.reldocTabs[nodetypeId]) {
let tab = TW.gui.reldocTabs[nodetypeId][rdtype]
// init toggle mecanisms (bootstrap.native/#componentTab)
// (just used for the tabs active/inactive handling,
// content is *always* topPapers and we modify it ourselves)
new Tab(tab);
// add handler to switch relatedDocsType
tab.addEventListener('click', function(e){
let reldType = e.target.dataset.reldocstype
let nodeType = e.target.dataset.nodetype
let qWords = queryForType(nodeType)
console.log('tab click', `rd-${nodeType}-${reldType}`)
getTopPapers(qWords, nodeType, reldType, `rd-${nodeType}-${reldType}`)
})
}
}
}
}
// select currently active sliders
if (TW.conf.filterSliders) {
// also for all active cats
......
......@@ -248,7 +248,9 @@ function createFilechooserEl () {
TW.resetGraph()
// run
mainStartGraph(theFormat, rdr.result, TW.instance)
mainStartGraph(theFormat, rdr.result, null, TW.instance)
// NB 3rd arg null = we got no additional conf for this "unknown" file
writeLabel(`Local file: ${clientLocalGraphFile.name}`)
}
......@@ -1141,20 +1143,8 @@ function jsActionOnGexfSelector(graphBasename){
// remove any previous instance and flags
TW.resetGraph()
// override default categories with the ones from db.json
if (TW.gmenuInfos[graphPath]) {
if (TW.gmenuInfos[graphPath][0] && TW.gmenuInfos[graphPath][0].name) {
TW.conf.catSem = TW.gmenuInfos[graphPath][0].name
console.log("new catSem:", TW.conf.catSem)
}
if (TW.gmenuInfos[graphPath][1] && TW.gmenuInfos[graphPath][1].name) {
TW.conf.catSoc = TW.gmenuInfos[graphPath][1].name
console.log("new catSoc:", TW.conf.catSoc)
}
}
mainStartGraph(newDataRes["format"], newDataRes["data"], TW.instance)
writeLabel(graphBasename)
TW.File = graphPath
mainStartGraph(newDataRes["format"], newDataRes["data"], TW.File, TW.instance)
writeLabel(graphBasename)
}
//============================= </OTHER ACTIONS > =============================//
......@@ -329,7 +329,7 @@ function set_ClustersLegend ( daclass, groupedByTicks ) {
// queryForType:
// prepare query words from selections of a given nodetype
// prepare query words from "selections of a given nodetype"
function queryForType(ntypeId){
let subSels = TW.SystemState().selectionNids.filter(function(nid) {
return TW.catDict[TW.Nodes[nid].type] == ntypeId
......@@ -370,6 +370,7 @@ function getTopPapers(qWords, nodetypeId, chosenAPI, tgtDivId) {
}
let cbDisplay = function(jsonData) {
// console.log("cbDisplay", jsonData)
return displayTopPapers(jsonData, nodetypeId, chosenAPI, tgtDivId)
}
......@@ -412,9 +413,10 @@ function getTopPapers(qWords, nodetypeId, chosenAPI, tgtDivId) {
// cf. the php code for these url args:
// - type: the node type id (0 or 1)
// - dbtype: 'CortextDB' or 'csv' decided by php read of the same conf file
// (we send it as param because phpAPI supports different dbtypes)
// POSS object + join.map(join)
let urlParams = "type="+nodetypeId+"&query="+joinedQ+"&gexf="+TW.File+"&n="+TW.conf.relatedDocsMax ;
let urlParams = "ndtype="+nodetypeId+"&dbtype="+chosenAPI+"&query="+joinedQ+"&gexf="+TW.File+"&n="+TW.conf.relatedDocsMax ;
$.ajax({
type: 'GET',
......@@ -469,14 +471,9 @@ function displayTopPapers(jsonHits, ndtypeId, chosenAPI, targetDiv) {
if (chosenAPI == 'twitter') {
toHtmlFun = renderTweet
}
else if (chosenAPI == "LocalDB") {
else if (chosenAPI == "CortextDB" || chosenAPI == "csv") {
let thisRelDocsConf = TW.gmenuInfos[TW.File][ndtypeId]["reldbs"]
let localDBType = Object.keys(thisRelDocsConf)[0]
console.log("1", thisRelDocsConf)
console.log("2", thisRelDocsConf[chosenAPI])
console.log("3", thisRelDocsConf[chosenAPI].template)
if (thisRelDocsConf && thisRelDocsConf[chosenAPI] && thisRelDocsConf[chosenAPI].template) {
console.log(">>>>>>>>>>> template >>>>>>", thisRelDocsConf[chosenAPI].template)
toHtmlFun = makeRendererFromTemplate(thisRelDocsConf[chosenAPI].template)
}
else {
......@@ -487,9 +484,6 @@ function displayTopPapers(jsonHits, ndtypeId, chosenAPI, targetDiv) {
}
}
console.log("my rendering fun", toHtmlFun)
console.log("my jsonHits", jsonHits)
for (var k in jsonHits) {
let hitJson = jsonHits[k]
if (hitJson.error) {
......
......@@ -77,9 +77,22 @@ if (window.location.protocol == 'file:' || sourcemode == 'localfile') {
}
// traditional cases: remote read from API or prepared server-side file
else {
try {
// we'll first retrieve the menu of available sources in db.json, then get the real data in a second ajax via API or server file
[TW.gmenuPaths, TW.gmenuInfos] = readMenu(TW.conf.paths.sourceMenu)
// NB: this menu used to be a file list for only one sourcemode
// but now also contains settings for nodetypes and for
// companion APIs (reldocs searches)
// => we read it for all cases now
}
catch(e) {
console.error(`Couldn't read ${TW.conf.paths.sourceMenu}, trying to start with settings_explorer defaults.`)
}
// NB it will use global urlParams and TW.settings to choose the source
var [inFormat, inData, mapLabel] = syncRemoteGraphData()
mainStartGraph(inFormat, inData, TW.instance)
var [inFormat, inData, inConfKey, mapLabel] = syncRemoteGraphData()
mainStartGraph(inFormat, inData, inConfKey, TW.instance)
writeLabel(mapLabel)
}
......@@ -89,10 +102,11 @@ else {
function syncRemoteGraphData () {
var inFormat; // = { db|api.json , somefile.json|gexf }
var inData; // = {nodes: [....], edges: [....], cats:...}
var inFormat; // = { db|api.json , somefile.json|gexf }
var inData; // = {nodes: [....], edges: [....], cats:...}
var inConfKey; // = source name for entry in db.json
var mapLabel; // user displayed label for this input dataset
var mapLabel; // user displayed label for this input dataset
// case (1) read from remote DB via API bridge fetching
// ex: /services/api/graph?q=filters...
......@@ -101,6 +115,7 @@ function syncRemoteGraphData () {
// the only API format, cf. inData
inFormat = 'json'
inConfKey = 'graphapi/default'
// TODO-rename: s/nodeidparam/srcparams
var sourceinfo = getUrlParam.nodeidparam
......@@ -202,8 +217,8 @@ function syncRemoteGraphData () {
}
// cases (2) and (3) : we'll read a file from server
// sourcemode == "serverfile" or "servermenu" (several files with <select>)
// sourcemode == "serverfile" or "servermenu"
// cases (2) and (3) : read a file from server
else {
console.log("input case: server-side file, using TW.conf.paths.sourceMenu or getUrlParam.file or TW.conf.paths.sourceFile")
......@@ -217,76 +232,14 @@ function syncRemoteGraphData () {
// menufile case : a list of source files in ./db.json
if (sourcemode == 'servermenu') {
console.log("reading from FILEMENU TW.conf.paths.sourceMenu")
// we'll first retrieve the menu of available files in db.json, then get the real data in a second ajax
var infofile = TW.conf.paths.sourceMenu
if (TW.conf.debug.logFetchers) console.info(`attempting to load filemenu ${infofile}`)
var preRES = AjaxSync({ url: infofile, datatype:"json" });
if (preRES['OK'] && preRES.data) {
if (TW.conf.debug.logFetchers) console.log('initial AjaxSync result preRES', preRES)
}
var first_file = "" , first_path = ""
for( var path in preRES.data ) {
if (TW.conf.debug.logFetchers) console.log("db.json path", path)
first_file = preRES.data[path]["first"]
first_path = path
break;
}
// the first or a specified one (ie both mode and file params are present)
if( isUndef(getUrlParam.file) ) {
TW.File = first_path+"/"+first_file
mapLabel = first_file
} else {
// £POSS; match on the full paths from db.json
TW.File = first_path+"/"+getUrlParam.file
mapLabel = getUrlParam.file
}
console.log("using entire FILEMENU TW.conf.paths.sourceMenu")
// chooser menu
var files_selector = '<select onchange="jsActionOnGexfSelector(this.value);">'
for( var path in preRES.data ) {
var theGraphs = preRES.data[path]["graphs"]
for(var aGraph in theGraphs) {
var graphBasename = aGraph.replace(/\.gexf$/, "") // more human-readable in the menu
TW.gmenuPaths[graphBasename] = path+"/"+aGraph
// ex : "RiskV2PageRank1000.gexf":data/AXA/RiskV2PageRank1000.gexf
// (we assume there's no duplicate basenames)
if (TW.conf.debug.logFetchers)
console.log("\t\t\t"+graphBasename)
// for associated LocalDB php queries: CSV (or CortextDBs sql)
if (theGraphs[aGraph]) {
let gSrcEntry = theGraphs[aGraph]
TW.gmenuInfos[path+"/"+aGraph] = new Array(2)
if (gSrcEntry.node0) {
TW.gmenuInfos[path+"/"+aGraph][0] = gSrcEntry.node0
}
if (gSrcEntry.node1) {
TW.gmenuInfos[path+"/"+aGraph][1] = gSrcEntry.node1
}
}
else {
TW.gmenuInfos[path+"/"+aGraph] = null
}
let cssFileSelected = (TW.File==(path+"/"+aGraph))?"selected":""
files_selector += '<option '+cssFileSelected+'>'+graphBasename+'</option>'
}
// console.log( files_selector )
for (let shortname in TW.gmenuPaths) {
let fullPath = TW.gmenuPaths[shortname]
let cssFileSelected = (TW.File==fullPath)?"selected":""
files_selector += '<option '+cssFileSelected+'>'+shortname+'</option>'
}
files_selector += "</select>"
$("#network").html(files_selector)
......@@ -308,6 +261,7 @@ function syncRemoteGraphData () {
var finalRes = AjaxSync({ url: TW.File });
inData = finalRes["data"]
inFormat = finalRes["format"]
inConfKey = TW.File
if (TW.conf.debug.logFetchers) {
console.warn('@TW.File', finalRes["OK"], TW.File)
......@@ -317,7 +271,7 @@ function syncRemoteGraphData () {
}
}
return [inFormat, inData, mapLabel]
return [inFormat, inData, inConfKey, mapLabel]
}
......@@ -326,12 +280,19 @@ function syncRemoteGraphData () {
// ===============
// main function (once we have some gexf or json data)
// ===============
// 0 - read optional additional conf
// 1 - parses the graph data
// 2 - starts the sigma instance in TW.partialGraph
// 3 - starts the tinaweb instance
// 4 - finishes setting up the environment
// (NB inspired by Samuel's legacy bringTheNoise() function)
function mainStartGraph(inFormat, inData, twInstance) {
//
// args:
// inFormat: 'json' or 'gexf'
// inData: source data as str
// inConfKey: optional entry in db.json to declare nodetypes and reldbs
// twInstance: a tinaweb object (gui, methods) to bind the graph to
function mainStartGraph(inFormat, inData, inConfKey, twInstance) {
// Graph-related vars
// ------------------
......@@ -354,10 +315,15 @@ function mainStartGraph(inFormat, inData, twInstance) {
alert("error on data load")
}
else {
// override default categories with the ones from db.json if present
let additionalConf = []
if (TW.gmenuInfos[inConfKey]) {
additionalConf = TW.gmenuInfos[inConfKey]
}
// parse the data
if (TW.conf.debug.logParsers) console.log("parsing the data")
let start = new ParseCustom( inFormat , inData );
let start = new ParseCustom( inFormat , inData, additionalConf );
let catsInfos = start.scanFile();
TW.categories = catsInfos.categories
......@@ -374,8 +340,8 @@ function mainStartGraph(inFormat, inData, twInstance) {
// activetypes: the node categorie(s) that is (are) currently displayed
// ex: [true,false] = [nodes of type 0 shown ; nodes of type 1 not drawn]
var initialActivetypes = TW.instance.initialActivetypes( TW.categories )
var initialActivereltypes = TW.instance.inferActivereltypes( initialActivetypes )
var initialActivetypes = twInstance.initialActivetypes( TW.categories )
var initialActivereltypes = twInstance.inferActivereltypes( initialActivetypes )
// XML parsing from ParseCustom into dicts of nodes by type or rels by etype
var dicts = start.makeDicts(TW.categories); // > parse json or gexf, dictfy
......@@ -493,10 +459,11 @@ function mainStartGraph(inFormat, inData, twInstance) {
// renderer position depend on viewpoint/zoom (like ~ html absolute positions of the node in the div)
// now that we have a sigma instance, let's bind our click handlers to it
TW.instance.initSigmaListeners(
twInstance.initSigmaListeners(
TW.partialGraph,
initialActivetypes, // to init node sliders and .class gui elements
initialActivereltypes // to init edge sliders
initialActivereltypes, // to init edge sliders
inConfKey // to init relatedDocs
)
// set the initial color
......
......@@ -97,6 +97,103 @@ TW.resetGraph = function() {
}
// read all sources' detailed confs
// -> list of source paths available
// -> declared nodetypes
// -> declared rDocs conf
function readMenu(infofile) {
// exemple entry
// "data/gargistex": {
// "first" : "shale_and_ice.gexf",
// "graphs":{
// "shale_and_ice.gexf": {
// "node0": {
// "name": "terms",
// "reldbs": {
// "csv": {
// "file": "shale_and_ice.csv",
// "qcols": ["title"],
// "template": "bib_details"
// },
// "twitter": {}
// }
// }
// }
// }
// }
let paths = {}
let details = {}
if (TW.conf.debug.logFetchers) console.info(`attempting to load filemenu ${infofile}`)
var preRES = AjaxSync({ url: infofile, datatype:"json" });
if (preRES['OK'] && preRES.data) {
if (TW.conf.debug.logFetchers) console.log('initial AjaxSync result preRES', preRES)
}
var first_file = "" , first_path = ""
for( var path in preRES.data ) {
if (TW.conf.debug.logFetchers) console.log("db.json path", path)
first_file = preRES.data[path]["first"]
first_path = path
break;
}
// the first or a specified one (ie both mode and file params are present)
if( isUndef(getUrlParam.file) ) {
TW.File = first_path+"/"+first_file
mapLabel = first_file
} else {
// £POSS; match on the full paths from db.json
TW.File = first_path+"/"+getUrlParam.file
mapLabel = getUrlParam.file
}
for( var path in preRES.data ) {
var theGraphs = preRES.data[path]["graphs"]
for(var aGraph in theGraphs) {
var graphBasename = aGraph.replace(/\.gexf$/, "") // more human-readable in the menu
paths[graphBasename] = path+"/"+aGraph
// ex : "RiskV2PageRank1000.gexf":data/AXA/RiskV2PageRank1000.gexf
// (we assume there's no duplicate basenames)
if (TW.conf.debug.logSettings)
console.log("db conf entry: "+graphBasename)
// for associated LocalDB php queries: CSV (or CortextDBs sql)
if (theGraphs[aGraph]) {
let gSrcEntry = theGraphs[aGraph]
details[path+"/"+aGraph] = new Array(2)
if (gSrcEntry.node0) {
details[path+"/"+aGraph][0] = gSrcEntry.node0
}
if (gSrcEntry.node1) {
details[path+"/"+aGraph][1] = gSrcEntry.node1
}
}
else {
details[path+"/"+aGraph] = null
}
}
// console.log( files_selector )
}
return [paths, details]
}
// settings: {norender: Bool}
function cancelSelection (fromTagCloud, settings) {
if (TW.conf.debug.logSelections) { console.log("\t***in cancelSelection"); }
......@@ -178,20 +275,6 @@ function getNActive(someState) {
return TW.SystemState().activetypes.filter(function(bool){return bool}).length
}
// transitional function:
// ----------------------
// Goal: determine if a single nodetype or global activetype is semantic or social
// Explanation: some older functions (eg topPapers) used this distinction
// (via semi-deprecated global swclickActual),
// but the specification changed twice since then:
// - 1st change: types described as type 0 and type 1 and possible default type
// - 2nd change default type of monopartite case changed from document to semantic
function swActual(aNodetype) {
return (aNodetype == TW.categories[0]) ? 'semantic' : 'social'
}
// changes attributes of nodes and edges to remove active, highlight and activeEdge flags
// NB: "low-level" <=> by design, does NOT change the state, gui nor global flag
......@@ -302,6 +385,7 @@ function clearHover() {
// nodes information div
// POSS: merge with hit_templates from additional conf
function htmlfied_nodesatts(elems){
var socnodes=[]
......@@ -316,7 +400,7 @@ function htmlfied_nodesatts(elems){
var id=elems[i]
var node = TW.Nodes[id]
if(swActual(node.type) == 'social'){
if(TW.catDict[node.type] == 1){
information += '<li><b>' + node.label + '</b></li>';
if(node.htmlCont==""){
if (!isUndef(node.level)) {
......@@ -327,14 +411,13 @@ function htmlfied_nodesatts(elems){
}
socnodes.push(information)
}
if(swActual(node.type) == 'semantic'){
information += '<li><b>' + node.label + '</b></li>';
let google='<a href=http://www.google.com/#hl=en&source=hp&q=%20'+node.label.replace(" ","+")+'%20><img src="'+TW.conf.paths.ourlibs+'/img/google.png"></img></a>';
let wiki = '<a href=http://en.wikipedia.org/wiki/'+node.label.replace(" ","_")+'><img src="'+TW.conf.paths.ourlibs+'/img/wikipedia.png"></img></a>';
let flickr= '<a href=http://www.flickr.com/search/?w=all&q='+node.label.replace(" ","+")+'><img src="'+TW.conf.paths.ourlibs+'/img/flickr.png"></img></a>';
information += '<li>'+google+"&nbsp;"+wiki+"&nbsp;"+flickr+'</li><br>';
semnodes.push(information)
else {
information += '<li><b>' + node.label + '</b></li>';
let google='<a href=http://www.google.com/#hl=en&source=hp&q=%20'+node.label.replace(" ","+")+'%20><img src="'+TW.conf.paths.ourlibs+'/img/google.png"></img></a>';
let wiki = '<a href=http://en.wikipedia.org/wiki/'+node.label.replace(" ","_")+'><img src="'+TW.conf.paths.ourlibs+'/img/wikipedia.png"></img></a>';
let flickr= '<a href=http://www.flickr.com/search/?w=all&q='+node.label.replace(" ","+")+'><img src="'+TW.conf.paths.ourlibs+'/img/flickr.png"></img></a>';
information += '<li>'+google+"&nbsp;"+wiki+"&nbsp;"+flickr+'</li><br>';
semnodes.push(information)
}
}
......@@ -438,11 +521,21 @@ function updateRelatedNodesPanel( sels , same, oppos ) {
if (TW.conf.getRelatedDocs) {
$("#reldocs-tabs-wrapper").show();
$("#topPapers").show();
// getTopPapers()
// update all related docs tabs
for (let ntId in TW.SystemState().activetypes) {
if (TW.SystemState().activetypes[ntId]) {
let qWords = queryForType(ntId)
console.log("available topPapers tabs:", TW.gui.reldocTabs[ntId])
for (let relDbType in TW.gui.reldocTabs[ntId]) {
getTopPapers(qWords, ntId, relDbType, `rd-${ntId}-${relDbType}`)
}
}
}
}
else {
$("#topPapers").hide()
$("#reldocs-tabs-wrapper").hide();
}
}
......
......@@ -3,7 +3,7 @@
// (for instance loop on full gexf in scanGexf then again in dictfyGexf)
// Level-01
var ParseCustom = function ( format , data ) {
var ParseCustom = function ( format , data, optionalConf ) {
if (format == 'gexf') {
this.data = $.parseXML(data)
......@@ -14,9 +14,13 @@ var ParseCustom = function ( format , data ) {
this.format = format;
this.nbCats = 0;
this.additionalConf = optionalConf
// input = GEXFstring
this.getGEXFCategories = function() {
return scanGexf( this.data );
let observedCategories = scanGexf(this.data)
let finalCategories = sortNodeTypes(observedCategories, this.additionalConf)
return finalCategories;
}// output = {'cats':[ "cat1" , "cat2" , ...], 'rev': {cat1: 0, cat2: 1...}}
......@@ -29,7 +33,9 @@ var ParseCustom = function ( format , data ) {
// input = JSONstring
this.getJSONCategories = function(json) {
return scanJSON( this.data );
let observedCategories = scanJSON(this.data)
let finalCategories = sortNodeTypes(observedCategories, this.additionalConf)
return finalCategories;
}// output = {'cats':[ "cat1" , "cat2" , ...], 'rev': {cat1: 0, cat2: 1...}}
......@@ -201,8 +207,7 @@ function scanGexf(gexfContent) {
}
}
// sorting observed json node types into Sem (=> 1)/Soc (=> 0)
return sortNodeTypes(categoriesDict)
return categoriesDict
}
// sorting observed node types into Sem/Soc
......@@ -212,10 +217,25 @@ function scanGexf(gexfContent) {
// expected content: usually a just a few cats over all nodes
// ex: terms
// ex: ISItermsriskV2_140 & ISItermsriskV2_140
function sortNodeTypes(observedTypesDict) {
function sortNodeTypes(observedTypesDict, optConf) {
var observedTypes = Object.keys(observedTypesDict)
observedTypes.sort(function(a,b) {return observedTypesDict[b] - observedTypesDict[a]})
let nbNodeTypes = 2
var declaredTypes = []
for (var i = 0 ; i < nbNodeTypes ; i++ ) {
if (optConf[i] && optConf[i].name) {
declaredTypes[i] = optConf[i].name
if (TW.conf.debug.logSettings)
console.log("expected cat (from db.json addtional conf)", i, declaredTypes[i])
}
else {
declaredTypes[i] = TW.conf[i == 0 ? 'catSem' : 'catSoc']
if (TW.conf.debug.logSettings)
console.log("expected cat (from settings_explorer defaults)", i, declaredTypes[i])
}
}
var newcats = []
var catDict = {}
......@@ -236,13 +256,14 @@ function sortNodeTypes(observedTypesDict) {
// allows multiple node types, with an "all the rest" node1
// try stipulated cats, then fallbacks
if (observedTypesDict[TW.conf.catSem]) {
newcats[0] = TW.conf.catSem;
catDict[TW.conf.catSem] = 0;
// possible: loop
if (observedTypesDict[declaredTypes[0]]) {
newcats[0] = declaredTypes[0];
catDict[declaredTypes[0]] = 0;
}
if (observedTypesDict[TW.conf.catSoc]) {
newcats[1] = TW.conf.catSoc;
catDict[TW.conf.catSoc] = 1;
if (observedTypesDict[declaredTypes[1]]) {
newcats[1] = declaredTypes[1];
catDict[declaredTypes[1]] = 1;
}
// NB: type for nodes0 will be the majoritary by default, unless taken
......@@ -1018,8 +1039,7 @@ function scanJSON( data ) {
}
}
// sorting observed json node types into Sem (=> 1)/Soc (=> 0)
return sortNodeTypes(categoriesDict);
return categoriesDict
}
// Level-00
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment