Commit f6cec553 authored by Romain Loth's avatar Romain Loth

finish main vars repackaging + fix old bugs

renamed to TW.states and TW.gui + fixed old sliders caching bug + fixed node normalization in parsing
parent a6eb472f
...@@ -31,7 +31,7 @@ This will still evolve but the main steps for any graph initialization messily u ...@@ -31,7 +31,7 @@ This will still evolve but the main steps for any graph initialization messily u
- prepares TW.Clusters: bins and facet index (node attr vals => nodes) - prepares TW.Clusters: bins and facet index (node attr vals => nodes)
4. [`main.js`] mainStartGraph() function runs all the rest 4. [`main.js`] mainStartGraph() function runs all the rest
1. precomputes display properties (grey color, etc.) 1. precomputes display properties (grey color, etc.)
2. calls [`sigmaUtils`] where the function `FillGraph()` was a central point for filtering and preparing properties but now with 2 and 3 it just copies the nodes and edges to a new structure that groups them together 2. calls [`sigmaUtils`] where the function `FillGraph()` was a central point for filtering and preparing properties but now with 2 and 3 it just creates a filtered copy of the nodes and edges of the current active types to a new structure that groups them together (POSSIBLE remove this extra step)
3. back in [`main.js`], finally all sigma settings (user + defaults) are merged and we initialize the sigma instance (`new sigma` etc.) 3. back in [`main.js`], finally all sigma settings (user + defaults) are merged and we initialize the sigma instance (`new sigma` etc.)
4. finally a call to [`TinawebJS`] initializes the action listeners and this phase should crucially initialize items that need the sigma instance (because they may depend the displayed categories, the number of displayed nodes, etc) 4. finally a call to [`TinawebJS`] initializes the action listeners and this phase should crucially initialize items that need the sigma instance (because they may depend the displayed categories, the number of displayed nodes, etc)
......
...@@ -210,7 +210,7 @@ function SomeEffect( ValueclassCode ) { ...@@ -210,7 +210,7 @@ function SomeEffect( ValueclassCode ) {
// TW.partialGraph.graph.nodes(ID).customAttrs.forceLabel = true; // TW.partialGraph.graph.nodes(ID).customAttrs.forceLabel = true;
// } // }
// TW.selectionActive=true; // TW.gui.selectionActive=true;
TW.partialGraph.refresh() TW.partialGraph.refresh()
} }
...@@ -507,7 +507,7 @@ function RenderTweet( tweet) { ...@@ -507,7 +507,7 @@ function RenderTweet( tweet) {
//FOR UNI-PARTITE //FOR UNI-PARTITE
// function selectionUni(currentNode){ // function selectionUni(currentNode){
// console.log("\tin selectionUni:"+currentNode.id); // console.log("\tin selectionUni:"+currentNode.id);
// if(TW.checkBox==false && TW.circleSize==0) { // if(TW.gui.checkBox==false && TW.gui.circleSize==0) {
// highlightSelectedNodes(false); // highlightSelectedNodes(false);
// opossites = []; // opossites = [];
// selections = []; // selections = [];
...@@ -684,7 +684,7 @@ function circleTrackMouse(e) { ...@@ -684,7 +684,7 @@ function circleTrackMouse(e) {
// } // }
// } // }
ctx.arc(x, y, TW.circleSize, 0, Math.PI * 2, true); ctx.arc(x, y, TW.gui.circleSize, 0, Math.PI * 2, true);
ctx.closePath(); ctx.closePath();
ctx.fill(); ctx.fill();
ctx.stroke(); ctx.stroke();
...@@ -695,7 +695,7 @@ function circleTrackMouse(e) { ...@@ -695,7 +695,7 @@ function circleTrackMouse(e) {
// exact subset of nodes under circle // exact subset of nodes under circle
function circleGetAreaNodes(camX0, camY0) { function circleGetAreaNodes(camX0, camY0) {
var cursor_ray = TW.circleSize * TW.cam.ratio // converting TW.circleSize to cam units var cursor_ray = TW.gui.circleSize * TW.cam.ratio // converting TW.gui.circleSize to cam units
// prepare an approximate neighborhood // prepare an approximate neighborhood
var slightlyLargerNodeset = circleLocalSubset( var slightlyLargerNodeset = circleLocalSubset(
......
...@@ -68,6 +68,11 @@ TW.conf = (function(TW){ ...@@ -68,6 +68,11 @@ TW.conf = (function(TW){
TWConf.nodeClusAtt = "modularity_class" TWConf.nodeClusAtt = "modularity_class"
// to normalize node sizes: (NB not very useful because tina normalizes them at display)
TWConf.desirableNodeSizeMin=1;
TWConf.desirableNodeSizeMax=12;
// ============= // =============
// TINA BEHAVIOR // TINA BEHAVIOR
// ============= // =============
...@@ -216,9 +221,9 @@ TW.conf = (function(TW){ ...@@ -216,9 +221,9 @@ TW.conf = (function(TW){
// show verbose console logs... // show verbose console logs...
logFetchers: false, // ...about ajax/fetching of graph data logFetchers: false, // ...about ajax/fetching of graph data
logParsers: false, // ...about parsing said data logParsers: false, // ...about parsing said data
logFacets: true, // ...about parsing node attribute:value facets logFacets: false, // ...about parsing node attribute:value facets
logSettings: false, // ...about settings at Tina and Sigma init time logSettings: false, // ...about settings at Tina and Sigma init time
logSelections: true logSelections: false
} }
......
...@@ -89,7 +89,7 @@ function SelectionEngine() { ...@@ -89,7 +89,7 @@ function SelectionEngine() {
coincd.push(results[i].id) coincd.push(results[i].id)
} }
var targeted = this.SelectorEngine( { var targeted = this.SelectorEngine( {
addvalue:TW.checkBox, addvalue:TW.gui.checkBox,
prevsels:selections, prevsels:selections,
currsels:coincd currsels:coincd
} ) } )
...@@ -170,7 +170,7 @@ function SelectionEngine() { ...@@ -170,7 +170,7 @@ function SelectionEngine() {
var sameSideNeighbors = {} var sameSideNeighbors = {}
var oppositeSideNeighbors = {} var oppositeSideNeighbors = {}
// TW.partialGraph.states.slice(-1)[0] is the present graph state // TW.states.slice(-1)[0] is the present graph state
// eg // eg
// {categories: ["someNodeCat"] // {categories: ["someNodeCat"]
// categoriesDict: {"someNodeCat":0} // where val 0 or 1 is type sem or soc // categoriesDict: {"someNodeCat":0} // where val 0 or 1 is type sem or soc
...@@ -284,7 +284,7 @@ function SelectionEngine() { ...@@ -284,7 +284,7 @@ function SelectionEngine() {
console.error("NaN selection key error") console.error("NaN selection key error")
} }
TW.partialGraph.states.slice(-1)[0].selections = the_new_sels; TW.states.slice(-1)[0].selections = the_new_sels;
TW.setState( { sels: the_new_sels} ) TW.setState( { sels: the_new_sels} )
// alert("MultipleSelection2=======\nthe_new_sels:" + JSON.stringify(the_new_sels)) // alert("MultipleSelection2=======\nthe_new_sels:" + JSON.stringify(the_new_sels))
...@@ -337,7 +337,7 @@ function SelectionEngine() { ...@@ -337,7 +337,7 @@ function SelectionEngine() {
} }
// global flag // global flag
TW.selectionActive = true TW.gui.selectionActive = true
TW.partialGraph.render(); TW.partialGraph.render();
...@@ -591,7 +591,7 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -591,7 +591,7 @@ var TinaWebJS = function ( sigmacanvas ) {
setTimeout( setTimeout(
function (){ function (){
targeted = selInst.SelectorEngine( { targeted = selInst.SelectorEngine( {
addvalue:TW.checkBox, addvalue:TW.gui.checkBox,
clicktype:"double", clicktype:"double",
prevsels:selections, prevsels:selections,
currsels:coincidences currsels:coincidences
...@@ -599,12 +599,12 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -599,12 +599,12 @@ var TinaWebJS = function ( sigmacanvas ) {
// tricky stuff for simulating a multiple selection D: // tricky stuff for simulating a multiple selection D:
// ... to be improved in the future ... // ... to be improved in the future ...
var prev_cursor_size = TW.circleSize; var prev_cursor_size = TW.gui.circleSize;
if(targeted.length>0) { if(targeted.length>0) {
TW.circleSize = (TW.circleSize==0)? 1 : TW.circleSize; TW.gui.circleSize = (TW.gui.circleSize==0)? 1 : TW.gui.circleSize;
cancelSelection(false); cancelSelection(false);
this.selInst.MultipleSelection2({nodes:targeted}); this.selInst.MultipleSelection2({nodes:targeted});
TW.circleSize = prev_cursor_size; TW.gui.circleSize = prev_cursor_size;
} }
$("input#searchinput").val(""); $("input#searchinput").val("");
...@@ -638,7 +638,7 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -638,7 +638,7 @@ var TinaWebJS = function ( sigmacanvas ) {
setTimeout( setTimeout(
function() { function() {
targeted = selInst.SelectorEngine( { targeted = selInst.SelectorEngine( {
addvalue:TW.checkBox, addvalue:TW.gui.checkBox,
clicktype:"double", clicktype:"double",
prevsels:selections, prevsels:selections,
currsels:[exfnd.id] currsels:[exfnd.id]
...@@ -808,10 +808,10 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -808,10 +808,10 @@ var TinaWebJS = function ( sigmacanvas ) {
step: 1, step: 1,
min:TW.conf.circleSizeMin, min:TW.conf.circleSizeMin,
max:TW.conf.circleSizeMax, max:TW.conf.circleSizeMax,
value:TW.circleSize, value:TW.gui.circleSize,
onchange:function(value){ onchange:function(value){
// console.log("en cursorsize: "+value); // console.log("en cursorsize: "+value);
TW.circleSize=value; TW.gui.circleSize=value;
} }
}); });
...@@ -872,10 +872,10 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -872,10 +872,10 @@ var TinaWebJS = function ( sigmacanvas ) {
// general listener: shift key in the window <=> add to selection // general listener: shift key in the window <=> add to selection
$(document).on('keyup keydown', function(e){ $(document).on('keyup keydown', function(e){
// changes the global boolean ("add node to selection" status) if keydown and SHIFT // changes the global boolean ("add node to selection" status) if keydown and SHIFT
TW.checkBox = TW.manuallyChecked || e.shiftKey TW.gui.checkBox = TW.gui.manuallyChecked || e.shiftKey
// show it in the real TW.checkBox too // show it in the real TW.gui.checkBox too
$('#checkboxdiv').prop("checked", TW.manuallyChecked || e.shiftKey) $('#checkboxdiv').prop("checked", TW.gui.manuallyChecked || e.shiftKey)
} ); } );
} // finish envListeners } // finish envListeners
...@@ -894,7 +894,7 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -894,7 +894,7 @@ var TinaWebJS = function ( sigmacanvas ) {
// cases: // cases:
// 'click' - simple click, early event // 'click' - simple click, early event
// used for area (with global: TW.circleSize) // used for area (with global: TW.gui.circleSize)
// 'clickNode'- simple click, second event if one node // 'clickNode'- simple click, second event if one node
// POSS easy in new sigma.js: // POSS easy in new sigma.js:
...@@ -908,7 +908,7 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -908,7 +908,7 @@ var TinaWebJS = function ( sigmacanvas ) {
// console.log("sigma click event e", e) // console.log("sigma click event e", e)
// case with a selector circle cursor handled here // case with a selector circle cursor handled here
if (TW.circleSize > 0) { if (TW.gui.circleSize > 0) {
// actual click position, but in graph coords // actual click position, but in graph coords
var x = e.data.x var x = e.data.x
var y = e.data.y var y = e.data.y
...@@ -916,19 +916,19 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -916,19 +916,19 @@ var TinaWebJS = function ( sigmacanvas ) {
// convert // convert
var camCoords = TW.cam.cameraPosition(x,y) var camCoords = TW.cam.cameraPosition(x,y)
// retrieve area nodes, using indexed quadtree and global TW.circleSize // retrieve area nodes, using indexed quadtree and global TW.gui.circleSize
var circleNodes = circleGetAreaNodes( var circleNodes = circleGetAreaNodes(
camCoords.x, camCoords.x,
camCoords.y camCoords.y
) )
// 1) clear previous while keeping its list (useful iff 'Add' TW.checkBox) // 1) clear previous while keeping its list (useful iff 'Add' TW.gui.checkBox)
var previousSelection = selections var previousSelection = selections
cancelSelection(false) cancelSelection(false)
// 2) show selection + do all related effects // 2) show selection + do all related effects
var targeted = selInst.SelectorEngine( { var targeted = selInst.SelectorEngine( {
addvalue:TW.checkBox, addvalue:TW.gui.checkBox,
currsels:circleNodes, currsels:circleNodes,
prevsels:previousSelection prevsels:previousSelection
} ) } )
...@@ -950,9 +950,9 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -950,9 +950,9 @@ var TinaWebJS = function ( sigmacanvas ) {
var previousSelection = selections var previousSelection = selections
cancelSelection(false, {norender:true}); // no need to render before MS2 cancelSelection(false, {norender:true}); // no need to render before MS2
if (TW.circleSize == 0) { if (TW.gui.circleSize == 0) {
var targeted = selInst.SelectorEngine( { var targeted = selInst.SelectorEngine( {
addvalue:TW.checkBox, addvalue:TW.gui.checkBox,
currsels:[theNodeId], currsels:[theNodeId],
prevsels:previousSelection prevsels:previousSelection
} ) } )
...@@ -972,7 +972,7 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -972,7 +972,7 @@ var TinaWebJS = function ( sigmacanvas ) {
if (! e.data.captor.isDragging if (! e.data.captor.isDragging
&& Object.keys(selections).length && Object.keys(selections).length
&& ! TW.circleSize) { && ! TW.gui.circleSize) {
// we clear selections and all its effects // we clear selections and all its effects
cancelSelection(false); cancelSelection(false);
...@@ -1003,7 +1003,7 @@ var TinaWebJS = function ( sigmacanvas ) { ...@@ -1003,7 +1003,7 @@ var TinaWebJS = function ( sigmacanvas ) {
.mousemove(function(e){ .mousemove(function(e){
if(!isUndef(partialGraph)) { if(!isUndef(partialGraph)) {
// show/move selector circle cursor // show/move selector circle cursor
if(TW.circleSize>0) circleTrackMouse(e); if(TW.gui.circleSize>0) circleTrackMouse(e);
} }
}) })
......
...@@ -78,9 +78,9 @@ function createFilechooserEl () { ...@@ -78,9 +78,9 @@ function createFilechooserEl () {
// Documentation Level: ***** // Documentation Level: *****
function changeType() { function changeType() {
var present = TW.partialGraph.states.slice(-1)[0]; // Last var present = TW.states.slice(-1)[0]; // Last
var past = TW.partialGraph.states.slice(-2)[0] // avant Last var past = TW.states.slice(-2)[0] // avant Last
var lastpos = TW.partialGraph.states.length-1; var lastpos = TW.states.length-1;
var avantlastpos = lastpos-1; var avantlastpos = lastpos-1;
...@@ -327,15 +327,15 @@ function changeType() { ...@@ -327,15 +327,15 @@ function changeType() {
// edgesDict:edges_2_colour // edgesDict:edges_2_colour
// }); // });
TW.instance.selNgn.MultipleSelection2({ nodes: sels }); TW.instance.selNgn.MultipleSelection2({ nodes: sels });
TW.selectionActive=true; TW.gui.selectionActive=true;
} }
TW.partialGraph.states[avantlastpos] = {}; TW.states[avantlastpos] = {};
TW.partialGraph.states[avantlastpos].LouvainFait = false; TW.states[avantlastpos].LouvainFait = false;
TW.partialGraph.states[avantlastpos].level = present.level; TW.states[avantlastpos].level = present.level;
TW.partialGraph.states[avantlastpos].selections = selsbackup; TW.states[avantlastpos].selections = selsbackup;
TW.partialGraph.states[avantlastpos].activetypes = present.activetypes; TW.states[avantlastpos].activetypes = present.activetypes;
TW.partialGraph.states[avantlastpos].opposites = present.opposites; TW.states[avantlastpos].opposites = present.opposites;
TW.setState({ TW.setState({
activetypes: nextState, activetypes: nextState,
...@@ -365,7 +365,7 @@ function changeType() { ...@@ -365,7 +365,7 @@ function changeType() {
// v // v
// local selection SysSt = {level: false, type:XY} // local selection SysSt = {level: false, type:XY}
// //
// where SysSt is the last state aka TW.partialGraph.states.slice(-1)[0] // where SysSt is the last state aka TW.states.slice(-1)[0]
// and SysSt.level is aka swMacro // and SysSt.level is aka swMacro
function changeLevel() { function changeLevel() {
...@@ -374,13 +374,13 @@ function changeLevel() { ...@@ -374,13 +374,13 @@ function changeLevel() {
// let the waiting cursor appear // let the waiting cursor appear
setTimeout(function() { setTimeout(function() {
var present = TW.partialGraph.states.slice(-1)[0]; // Last var present = TW.states.slice(-1)[0]; // Last
var past = TW.partialGraph.states.slice(-2)[0] // avant Last var past = TW.states.slice(-2)[0] // avant Last
var lastpos = TW.partialGraph.states.length-1; var lastpos = TW.states.length-1;
var avantlastpos = lastpos-1; var avantlastpos = lastpos-1;
var level = present.level; var level = present.level;
var sels = present.selections;//[144, 384, 543]//TW.partialGraph.states.selections; var sels = present.selections;//[144, 384, 543]//TW.states.selections;
// type "grammar" // type "grammar"
...@@ -473,18 +473,18 @@ function changeLevel() { ...@@ -473,18 +473,18 @@ function changeLevel() {
nodesDict:nodes_2_colour, nodesDict:nodes_2_colour,
edgesDict:edges_2_colour edgesDict:edges_2_colour
}); });
TW.selectionActive=true; TW.gui.selectionActive=true;
} }
} }
// console.log("enviroment changeLevel nodes_2_colour", nodes_2_colour) // console.log("enviroment changeLevel nodes_2_colour", nodes_2_colour)
TW.partialGraph.states[avantlastpos] = {}; TW.states[avantlastpos] = {};
TW.partialGraph.states[avantlastpos].level = present.level; TW.states[avantlastpos].level = present.level;
TW.partialGraph.states[avantlastpos].selections = present.selections; TW.states[avantlastpos].selections = present.selections;
TW.partialGraph.states[avantlastpos].activetypes = present.activetypes; TW.states[avantlastpos].activetypes = present.activetypes;
TW.partialGraph.states[avantlastpos].opposites = present.opposites; TW.states[avantlastpos].opposites = present.opposites;
TW.setState({ TW.setState({
activetypes: present.activetypes, activetypes: present.activetypes,
...@@ -580,11 +580,11 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) { ...@@ -580,11 +580,11 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) {
} }
var lastvalue=("0-"+(steps-1)); // cache initial value
var initialValue=("0-"+(steps-1));
TW.gui.lastFilters[sliderDivID] = initialValue
pushFilterValue( sliderDivID , lastvalue ) var present = TW.states.slice(-1)[0];
var present = TW.partialGraph.states.slice(-1)[0];
// console.log('init freshslider for edges, steps:', steps, sliderDivID) // console.log('init freshslider for edges, steps:', steps, sliderDivID)
...@@ -606,7 +606,7 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) { ...@@ -606,7 +606,7 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) {
onchange:function(low, high) { onchange:function(low, high) {
theHtml.classList.add('waiting'); theHtml.classList.add('waiting');
// 500ms timeout to let the waiting cursor appear // 40ms timeout to let the waiting cursor appear
setTimeout(function() { setTimeout(function() {
var totalDeletingTime = 0 var totalDeletingTime = 0
...@@ -619,17 +619,14 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) { ...@@ -619,17 +619,14 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) {
// scheduled: costly graph rm edges // scheduled: costly graph rm edges
edgeSlideTimeout = setTimeout ( function () { edgeSlideTimeout = setTimeout ( function () {
var filtervalue = low+"-"+high
if(filtervalue!=lastFilter[sliderDivID]["last"]) {
// £TODO better memoize the last filter value
// $.doTimeout(sliderDivID+"_"+lastFilter[sliderDivID]["last"]);
var filtervalue = low+"-"+high
var lastvalue = TW.gui.lastFilters[sliderDivID]
// sliderDivID+"_"+filtervalue
// sliderDivID+"_"+filtervalue // console.debug("\nprevious value "+lastvalue+" | current value "+filtervalue)
console.log("\nprevious value "+lastvalue+" | current value "+filtervalue) if(filtervalue!=lastvalue) {
// [ Stopping FA2 ] // [ Stopping FA2 ]
if (TW.partialGraph.isForceAtlas2Running()) if (TW.partialGraph.isForceAtlas2Running())
...@@ -643,7 +640,6 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) { ...@@ -643,7 +640,6 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) {
var iterarr = [] var iterarr = []
if(mint0!=mint1) { if(mint0!=mint1) {
if(mint0<mint1) { if(mint0<mint1) {
delflag = true; delflag = true;
...@@ -760,19 +756,23 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) { ...@@ -760,19 +756,23 @@ function EdgeWeightFilter(sliderDivID , typestr , criteria) {
}, 10) }, 10)
// [ / Starting FA2 ] // [ / Starting FA2 ]
lastvalue = filtervalue; console.log("lastvalue===", lastvalue)
pushFilterValue( sliderDivID , filtervalue ) TW.gui.lastFilters[sliderDivID] = lastvalue
// pushFilterValue( sliderDivID , lastvalue )
}
else {
// console.log('edges:::same position')
} }
// in any case
setTimeout( function() { setTimeout( function() {
theHtml.classList.remove('waiting') theHtml.classList.remove('waiting')
}, 20) }, 20)
}, 700) // large-ish debounce timeout }, 1500) // large-ish debounce timeout
}, 40) // wait cursor timeout
}, 500) // wait cursor timeout
} }
}); });
...@@ -824,7 +824,10 @@ function NodeWeightFilter( sliderDivID , tgtNodeType , criteria) { ...@@ -824,7 +824,10 @@ function NodeWeightFilter( sliderDivID , tgtNodeType , criteria) {
var nodeSlideTimeout = null var nodeSlideTimeout = null
//finished // cache initial value
TW.gui.lastFilters[sliderDivID] = `0-${steps-1}`
// freshslider widget
$(sliderDivID).freshslider({ $(sliderDivID).freshslider({
range: true, range: true,
step: 1, step: 1,
...@@ -832,61 +835,57 @@ function NodeWeightFilter( sliderDivID , tgtNodeType , criteria) { ...@@ -832,61 +835,57 @@ function NodeWeightFilter( sliderDivID , tgtNodeType , criteria) {
max:steps-1, max:steps-1,
bgcolor:( tgtNodeType==TW.categories[0] )?"#27c470":"#FFA500" , bgcolor:( tgtNodeType==TW.categories[0] )?"#27c470":"#FFA500" ,
value:[0,steps-1], value:[0,steps-1],
// handler
onchange:function(low, high){ onchange:function(low, high){
var filtervalue = low+"-"+high var filtervalue = low+"-"+high
if(filtervalue!=lastFilter[sliderDivID]["last"]) { // [ Stopping FA2 ]
if(lastFilter[sliderDivID]["orig"]=="-") { if (TW.partialGraph.isForceAtlas2Running())
pushFilterValue( sliderDivID , filtervalue ) sigma_utils.ourStopFA2();
return false // [ / Stopping FA2 ]
}
// [ Stopping FA2 ] // debounced
if (TW.partialGraph.isForceAtlas2Running()) if (nodeSlideTimeout){
sigma_utils.ourStopFA2(); clearTimeout(nodeSlideTimeout)
// [ / Stopping FA2 ] }
// scheduled: graph rm nodes
nodeSlideTimeout = setTimeout ( function () {
// debounced // check memoized value to see if any changes needed
if (nodeSlideTimeout){ if(filtervalue!=TW.gui.lastFilters[sliderDivID]) {
// console.log('clearing updated function', nodeSlideTimeout)
clearTimeout(nodeSlideTimeout)
}
// scheduled: graph rm nodes for(var i in stepToIdsArr) {
nodeSlideTimeout = setTimeout ( function () { ids = stepToIdsArr[i]
if(i>=low && i<=high){
for(var i in stepToIdsArr) { for(var id in ids) {
ids = stepToIdsArr[i] ID = ids[id]
if(i>=low && i<=high){ TW.Nodes[ID].lock = false;
for(var id in ids) { if(TW.partialGraph.graph.nodes(ID))
ID = ids[id] TW.partialGraph.graph.nodes(ID).hidden = false;
TW.Nodes[ID].lock = false; }
if(TW.partialGraph.graph.nodes(ID)) } else {
TW.partialGraph.graph.nodes(ID).hidden = false; for(var id in ids) {
} ID = ids[id]
} else { TW.Nodes[ID].lock = true;
for(var id in ids) { if(TW.partialGraph.graph.nodes(ID))
ID = ids[id] TW.partialGraph.graph.nodes(ID).hidden = true;
TW.Nodes[ID].lock = true; }
if(TW.partialGraph.graph.nodes(ID)) }
TW.partialGraph.graph.nodes(ID).hidden = true; }
} TW.gui.lastFilters[sliderDivID] = filtervalue
}
}
pushFilterValue(sliderDivID,filtervalue)
TW.partialGraph.render() TW.partialGraph.render()
// [ Starting FA2 ] // [ Starting FA2 ]
setTimeout(function() { setTimeout(function() {
sigma_utils.smartForceAtlas(2000) // shorter FA2 sufficient sigma_utils.smartForceAtlas(2000) // shorter FA2 sufficient
}, 10) }, 10)
// [ / Starting FA2 ] // [ / Starting FA2 ]
}
}, 300) }, 1000)
}
} }
}); });
} }
......
'use strict'; 'use strict';
// ======= [ variable initialization ] ======== // // ======= [ main TW properties initialization ] ======== //
// INITIALIZED VARS
// ================
TW.Nodes = []; TW.Nodes = [];
TW.Edges = []; TW.Edges = [];
TW.Relations = {} TW.Relations = {} // edges sorted by source/target type
TW.Clusters = []; // A "by value" index, built in parseCustom, (aka facets) TW.Clusters = []; // "by value" facet index built in parseCustom
TW.gexfPaths={}; TW.partialGraph = null // will contain the sigma visible graph instance
TW.labels=[];
// FIXME should become TW.* TW.labels=[]; // fulltext search list
TW.gexfPaths={}; // for file selectors iff servermenu
TW.categories = []; // possible node types and their inverted map
TW.catDict = {};
// SystemState is a summary of current situation
TW.SystemState = {}
TW.SystemState.level = true;
TW.SystemState.activetypes = [] // will be filled from TW.categories
TW.SystemState.selections = [];
TW.SystemState.opposites = [];
TW.SystemState.LouvainFait = false;
// states[] is an array of SystemStates for future CTRL+Z or usage track
TW.states = []
TW.states[0] = false;
TW.states[1] = TW.SystemState
// £TODO should become TW.* or TW.SystemState.*
var selections = []; var selections = [];
var deselections={}; var deselections={};
var opossites = {}; var opossites = {};
...@@ -26,51 +43,27 @@ var nodes2 = {}; ...@@ -26,51 +43,27 @@ var nodes2 = {};
var bipartiteD2N = {}; var bipartiteD2N = {};
var bipartiteN2D = {}; var bipartiteN2D = {};
// possible node types and their inverted map
TW.categories = [];
TW.catDict = {};
var gexfFile;
//var zoom=0;
TW.checkBox=false;
TW.shiftKey=false;
TW.manuallyChecked = false;
TW.SystemState = {}
TW.SystemState.level = true;
TW.SystemState.type = [ true, false ] // usually overridden by initialActivetypes
TW.SystemState.selections = [];
TW.SystemState.opposites = [];
// GUI vars
TW.gui = {}
TW.gui.selectionActive = false // <== changes rendering mode
TW.gui.circleSize = 0;
TW.gui.checkBox=false;
TW.gui.shiftKey=false;
TW.gui.manuallyChecked = false;
TW.gui.lastFilters = {}
TW.colorList = ["#000000", "#FFFF00", "#1CE6FF", "#FF34FF", "#FF4A46", "#008941", "#006FA6", "#A30059", "#FFDBE5", "#7A4900", "#0000A6", "#63FFAC", "#B79762", "#004D43", "#8FB0FF", "#997D87", "#5A0007", "#809693", "#FEFFE6", "#1B4400", "#4FC601", "#3B5DFF", "#4A3B53", "#FF2F80", "#61615A", "#BA0900", "#6B7900", "#00C2A0", "#FFAA92", "#FF90C9", "#B903AA", "#D16100", "#DDEFFF", "#000035", "#7B4F4B", "#A1C299", "#300018", "#0AA6D8", "#013349", "#00846F", "#372101", "#FFB500", "#C2FFED", "#A079BF", "#CC0744", "#C0B9B2", "#C2FF99", "#001E09", "#00489C", "#6F0062", "#0CBD66", "#EEC3FF", "#456D75", "#B77B68", "#7A87A1", "#788D66", "#885578", "#FAD09F", "#FF8A9A", "#D157A0", "#BEC459", "#456648", "#0086ED", "#886F4C","#34362D", "#B4A8BD", "#00A6AA", "#452C2C", "#636375", "#A3C8C9", "#FF913F", "#938A81", "#575329", "#00FECF", "#B05B6F", "#8CD0FF", "#3B9700", "#04F757", "#C8A1A1", "#1E6E00", "#7900D7", "#A77500", "#6367A9", "#A05837", "#6B002C", "#772600", "#D790FF", "#9B9700", "#549E79", "#FFF69F", "#201625", "#72418F", "#BC23FF", "#99ADC0", "#3A2465", "#922329", "#5B4534", "#FDE8DC", "#404E55", "#0089A3", "#CB7E98", "#A4E804", "#324E72", "#6A3A4C", "#83AB58", "#001C1E", "#D1F7CE", "#004B28", "#C8D0F6", "#A3A489", "#806C66", "#222800", "#BF5650", "#E83000", "#66796D", "#DA007C", "#FF1A59", "#8ADBB4", "#1E0200", "#5B4E51", "#C895C5", "#320033", "#FF6832", "#66E1D3", "#CFCDAC", "#D0AC94", "#7ED379", "#012C58"]; TW.colorList = ["#000000", "#FFFF00", "#1CE6FF", "#FF34FF", "#FF4A46", "#008941", "#006FA6", "#A30059", "#FFDBE5", "#7A4900", "#0000A6", "#63FFAC", "#B79762", "#004D43", "#8FB0FF", "#997D87", "#5A0007", "#809693", "#FEFFE6", "#1B4400", "#4FC601", "#3B5DFF", "#4A3B53", "#FF2F80", "#61615A", "#BA0900", "#6B7900", "#00C2A0", "#FFAA92", "#FF90C9", "#B903AA", "#D16100", "#DDEFFF", "#000035", "#7B4F4B", "#A1C299", "#300018", "#0AA6D8", "#013349", "#00846F", "#372101", "#FFB500", "#C2FFED", "#A079BF", "#CC0744", "#C0B9B2", "#C2FF99", "#001E09", "#00489C", "#6F0062", "#0CBD66", "#EEC3FF", "#456D75", "#B77B68", "#7A87A1", "#788D66", "#885578", "#FAD09F", "#FF8A9A", "#D157A0", "#BEC459", "#456648", "#0086ED", "#886F4C","#34362D", "#B4A8BD", "#00A6AA", "#452C2C", "#636375", "#A3C8C9", "#FF913F", "#938A81", "#575329", "#00FECF", "#B05B6F", "#8CD0FF", "#3B9700", "#04F757", "#C8A1A1", "#1E6E00", "#7900D7", "#A77500", "#6367A9", "#A05837", "#6B002C", "#772600", "#D790FF", "#9B9700", "#549E79", "#FFF69F", "#201625", "#72418F", "#BC23FF", "#99ADC0", "#3A2465", "#922329", "#5B4534", "#FDE8DC", "#404E55", "#0089A3", "#CB7E98", "#A4E804", "#324E72", "#6A3A4C", "#83AB58", "#001C1E", "#D1F7CE", "#004B28", "#C8D0F6", "#A3A489", "#806C66", "#222800", "#BF5650", "#E83000", "#66796D", "#DA007C", "#FF1A59", "#8ADBB4", "#1E0200", "#5B4E51", "#C895C5", "#320033", "#FF6832", "#66E1D3", "#CFCDAC", "#D0AC94", "#7ED379", "#012C58"];
// £TODO à ranger
TW.circleSize= 0;
var lastFilter = []
lastFilter["#slidercat0nodesweight"] = {"orig":"-" , "last":"-"}
lastFilter["#slidercat1nodesweight"] = {"orig":"-" , "last":"-"}
lastFilter["#slidercat0edgesweight"] = {"orig":"-" , "last":"-"}
lastFilter["#slidercat1edgesweight"] = {"orig":"-" , "last":"-"}
var desirableNodeSizeMIN=1;
var desirableNodeSizeMAX=12;
// These variables will be updated in sigma.parseCustom.js
var minNodeSize
var maxNodeSize
// ======== [ what to do at start ] ========= // // ======== [ what to do at start ] ========= //
console.log("Starting TWJS") console.log("Starting TWJS")
// NB this method-holding instance could be initialized just once or even removed? // NB this method-holding instance could be initialized just once or even removed?
var sigma_utils = new SigmaUtils(); var sigma_utils = new SigmaUtils();
// POSS: ideally this should take a TW.settings as parameter // POSS: ideally this should take a TW.conf as parameter
TW.instance = new TinaWebJS('#sigma-contnr'); TW.instance = new TinaWebJS('#sigma-contnr');
// add once our tw rendering and index customizations into sigma module // add once our tw rendering and index customizations into sigma module
...@@ -241,7 +234,7 @@ function syncRemoteGraphData () { ...@@ -241,7 +234,7 @@ function syncRemoteGraphData () {
console.log("input case: server-side file, using TW.conf.sourceMenu or getUrlParam.file or TW.conf.sourceFile") console.log("input case: server-side file, using TW.conf.sourceMenu or getUrlParam.file or TW.conf.sourceFile")
// -> @mode is servermenu, files are listed in db.json file (preRes ajax) // -> @mode is servermenu, files are listed in db.json file (preRes ajax)
// --> if @file also in url, choose the db.json one matching <=== £TODO THIS CASE STILL TO FIX // --> if @file also in url, choose the db.json one matching
// --> otherwise, choose the "first_file" from db.json list // --> otherwise, choose the "first_file" from db.json list
// -> @mode is serverfile // -> @mode is serverfile
...@@ -300,7 +293,6 @@ function syncRemoteGraphData () { ...@@ -300,7 +293,6 @@ function syncRemoteGraphData () {
if (TW.conf.debug.logFetchers) if (TW.conf.debug.logFetchers)
console.log("\t\t\t"+gexfBasename+ " -> table:" +theGexfs[aGexf]["semantic"]["table"] ) console.log("\t\t\t"+gexfBasename+ " -> table:" +theGexfs[aGexf]["semantic"]["table"] )
// -------------------------->8------------------------------------------ // -------------------------->8------------------------------------------
// £TODO this part is underspecified // £TODO this part is underspecified
// if used in some usecases, port it to nodetypes // if used in some usecases, port it to nodetypes
...@@ -316,7 +308,6 @@ function syncRemoteGraphData () { ...@@ -316,7 +308,6 @@ function syncRemoteGraphData () {
// console.log( files_selector ) // console.log( files_selector )
} }
files_selector += "</select>" files_selector += "</select>"
console.log("files_selector HTML", files_selector)
$("#network").html(files_selector) $("#network").html(files_selector)
} }
...@@ -381,14 +372,15 @@ function mainStartGraph(inFormat, inData, twInstance) { ...@@ -381,14 +372,15 @@ function mainStartGraph(inFormat, inData, twInstance) {
if (! TW.categories) { if (! TW.categories) {
console.warn ('ParseCustom scanFile found no categories!!') console.warn ('ParseCustom scanFile found no categories!!')
TW.categories = []
TW.catDict = {}
} }
// activetypes: the node categorie(s) that is (are) currently displayed
// ex: [true,false] = [nodes of type 0 shown ; nodes of type 1 not drawn] // ex: [true,false] = [nodes of type 0 shown ; nodes of type 1 not drawn]
var initialActivetypes = TW.instance.initialActivetypes( TW.categories ) var initialActivetypes = TW.instance.initialActivetypes( TW.categories )
var possibleActivetypes = TW.instance.allPossibleActivetypes( TW.categories ) var possibleActivetypes = TW.instance.allPossibleActivetypes( TW.categories )
// remember it
TW.states[1].activetypes = initialActivetypes ;
// XML parsing from ParseCustom // XML parsing from ParseCustom
var dicts = start.makeDicts(TW.categories); // > parse json or gexf, dictfy var dicts = start.makeDicts(TW.categories); // > parse json or gexf, dictfy
...@@ -405,8 +397,6 @@ function mainStartGraph(inFormat, inData, twInstance) { ...@@ -405,8 +397,6 @@ function mainStartGraph(inFormat, inData, twInstance) {
prepareNodesRenderingProperties(TW.Nodes) prepareNodesRenderingProperties(TW.Nodes)
prepareEdgesRenderingProperties(TW.Edges, TW.Nodes) prepareEdgesRenderingProperties(TW.Edges, TW.Nodes)
TW.selectionActive = false // changes rendering mode
if (inData.clusters) TW.Clusters = inData.clusters if (inData.clusters) TW.Clusters = inData.clusters
// £TODO remove from parseCustom or start using // £TODO remove from parseCustom or start using
...@@ -445,7 +435,8 @@ function mainStartGraph(inFormat, inData, twInstance) { ...@@ -445,7 +435,8 @@ function mainStartGraph(inFormat, inData, twInstance) {
// [ Poblating the Sigma-Graph ] // [ Poblating the Sigma-Graph ]
// preparing the data and settings // preparing the data (TW.Nodes and TW.Edges filtered by initial type)
// POSS: avoid this step and use the filters at rendering time!
TW.graphData = {nodes: [], edges: []} TW.graphData = {nodes: [], edges: []}
TW.graphData = sigma_utils.FillGraph( initialActivetypes , TW.catDict , TW.Nodes , TW.Edges , TW.graphData ); TW.graphData = sigma_utils.FillGraph( initialActivetypes , TW.catDict , TW.Nodes , TW.Edges , TW.graphData );
...@@ -547,110 +538,11 @@ function mainStartGraph(inFormat, inData, twInstance) { ...@@ -547,110 +538,11 @@ function mainStartGraph(inFormat, inData, twInstance) {
// NB : camera positions are fix if the node is fixed => they only depend on layout // NB : camera positions are fix if the node is fixed => they only depend on layout
// renderer position depend on viewpoint/zoom (like ~ html absolute positions of the node in the div) // renderer position depend on viewpoint/zoom (like ~ html absolute positions of the node in the div)
// POSS make it TW.states
TW.partialGraph.states = []
TW.partialGraph.states[0] = false;
// from settings_explorer (everything except the type)
TW.partialGraph.states[1] = TW.SystemState
// activetypes: the node categorie(s) that is (are) currently displayed
TW.partialGraph.states[1].activetypes = initialActivetypes ;
TW.partialGraph.states[1].LouvainFait = false;
// NB specs: categories don't change within a given 'states' array so we don't include them
// (new graph => new categories combinations => new array)
// now that we have a sigma instance, let's bind our click handlers to it // now that we have a sigma instance, let's bind our click handlers to it
TW.instance.initSigmaListeners(TW.partialGraph, initialActivetypes) TW.instance.initSigmaListeners(TW.partialGraph, initialActivetypes)
// [ / Poblating the Sigma-Graph ] // [ / Poblating the Sigma-Graph ]
// @args is an object with 4 possible properties that define the new state
// ex: new selections: {sels: [268]}
// ex: new activetypes: {activetypes:[false, true]}
// ex: new level: {level:false}
TW.setState = function( args ) {
var bistate=false, typesKey=false;
// £TODO we could append the new state in this function too
var present = TW.partialGraph.states.slice(-1)[0]; // Last
var past = TW.partialGraph.states.slice(-2)[0] // avant Last
console.log("IN THE SET STATE METHOD:", this)
console.log(" % % % % % % % % % % ")
console.log("setState args: ", args);
if(!isUndef(args.activetypes)) {
// record into last state
present.activetypes = args.activetypes;
bistate= present.activetypes.map(Number).reduce(
function(a, b){return a+b;}
)
typesKey = present.activetypes.map(Number).join("|")
}
// console.log("printing the typesKey:", typesKey)
if(!isUndef(args.level)) present.level = args.level;
if(!isUndef(args.sels)) present.selections = args.sels;
if(!isUndef(args.oppos)) present.opposites = args.oppos;
present.LouvainFait = false;
// change level needs a selection
LevelButtonDisable(false); // £TODO rename toggleLevelButton
if( present.level
&& present.selections
&& present.selections.length==0)
LevelButtonDisable(true);
// case to go back
if(present.level==false && bistate>1)
LevelButtonDisable(true)
// recreate sliders after activetype or level changes
if (TW.conf.filterSliders
&& (present.level != past.level
|| present.activetypes.map(Number).join("|") != past.activetypes.map(Number).join("|"))) {
// terms
if(typesKey=="0|1") {
$(".for-nodecategory-0").hide()
$(".for-nodecategory-1").show();
NodeWeightFilter( "#slidercat1nodesweight" , TW.categories[1], "size");
EdgeWeightFilter("#slidercat1edgesweight", typesKey, "weight");
}
// docs
if(typesKey=="1|0") {
$(".for-nodecategory-0").show()
$(".for-nodecategory-1").hide();
NodeWeightFilter( "#slidercat0nodesweight" , TW.categories[0], "size");
EdgeWeightFilter("#slidercat0edgesweight", typesKey, "weight");
}
// terms and docs
if(typesKey=="1|1") {
$(".for-nodecategory-0").show()
$(".for-nodecategory-1").show();
NodeWeightFilter( "#slidercat0nodesweight" , TW.categories[0], "size");
NodeWeightFilter( "#slidercat1nodesweight" , TW.categories[1], "size");
EdgeWeightFilter("#slidercat0edgesweight", "1|0", "weight");
EdgeWeightFilter("#slidercat1edgesweight", "0|1", "weight");
}
}
};
if (!TW.conf.filterSliders) { if (!TW.conf.filterSliders) {
var filterEls = document.getElementsByClassName('weight-selectors') var filterEls = document.getElementsByClassName('weight-selectors')
......
'use strict'; 'use strict';
// @args is an object with 4 possible properties that define the new state
// ex: new selections: {sels: [268]}
// ex: new activetypes: {activetypes:[false, true]}
// ex: new level: {level:false}
TW.setState = function( args ) {
var bistate=false, typesKey=false;
// £TODO we could append the new state in this function too
var present = TW.states.slice(-1)[0]; // Last
var past = TW.states.slice(-2)[0] // avant Last
console.log("setState args: ", args);
if(!isUndef(args.activetypes)) {
// record into last state
present.activetypes = args.activetypes;
bistate= present.activetypes.map(Number).reduce(
function(a, b){return a+b;}
)
typesKey = present.activetypes.map(Number).join("|")
}
// console.log("printing the typesKey:", typesKey)
if(!isUndef(args.level)) present.level = args.level;
if(!isUndef(args.sels)) present.selections = args.sels;
if(!isUndef(args.oppos)) present.opposites = args.oppos;
present.LouvainFait = false;
// change level needs a selection
LevelButtonDisable(false); // £TODO rename toggleLevelButton
if( present.level
&& present.selections
&& present.selections.length==0)
LevelButtonDisable(true);
// case to go back
if(present.level==false && bistate>1)
LevelButtonDisable(true)
// recreate sliders after activetype or level changes
if (TW.conf.filterSliders
&& (present.level != past.level
|| present.activetypes.map(Number).join("|") != past.activetypes.map(Number).join("|"))) {
// terms
if(typesKey=="0|1") {
$(".for-nodecategory-0").hide()
$(".for-nodecategory-1").show();
NodeWeightFilter( "#slidercat1nodesweight" , TW.categories[1], "size");
EdgeWeightFilter("#slidercat1edgesweight", typesKey, "weight");
}
// docs
if(typesKey=="1|0") {
$(".for-nodecategory-0").show()
$(".for-nodecategory-1").hide();
NodeWeightFilter( "#slidercat0nodesweight" , TW.categories[0], "size");
EdgeWeightFilter("#slidercat0edgesweight", typesKey, "weight");
}
// terms and docs
if(typesKey=="1|1") {
$(".for-nodecategory-0").show()
$(".for-nodecategory-1").show();
NodeWeightFilter( "#slidercat0nodesweight" , TW.categories[0], "size");
NodeWeightFilter( "#slidercat1nodesweight" , TW.categories[1], "size");
EdgeWeightFilter("#slidercat0edgesweight", "1|0", "weight");
EdgeWeightFilter("#slidercat1edgesweight", "0|1", "weight");
}
}
};
// settings: {norender: Bool} // settings: {norender: Bool}
function cancelSelection (fromTagCloud, settings) { function cancelSelection (fromTagCloud, settings) {
if (TW.conf.debug.logSelections) { console.log("\t***in cancelSelection"); } if (TW.conf.debug.logSelections) { console.log("\t***in cancelSelection"); }
...@@ -12,10 +93,10 @@ function cancelSelection (fromTagCloud, settings) { ...@@ -12,10 +93,10 @@ function cancelSelection (fromTagCloud, settings) {
//selections.length = 0; //selections.length = 0;
selections.splice(0, selections.length); selections.splice(0, selections.length);
TW.partialGraph.states.slice(-1)[0].selections=[] TW.states.slice(-1)[0].selections=[]
// global flag // global flag
TW.selectionActive = false TW.gui.selectionActive = false
//Edges colors go back to normal //Edges colors go back to normal
...@@ -75,7 +156,7 @@ function cancelSelection (fromTagCloud, settings) { ...@@ -75,7 +156,7 @@ function cancelSelection (fromTagCloud, settings) {
deselections={}; deselections={};
if(TW.partialGraph.states.slice(-1)[0].level) if(TW.states.slice(-1)[0].level)
LevelButtonDisable(true); LevelButtonDisable(true);
if (!settings.norender) { if (!settings.norender) {
...@@ -91,7 +172,7 @@ function cancelSelection (fromTagCloud, settings) { ...@@ -91,7 +172,7 @@ function cancelSelection (fromTagCloud, settings) {
function getActivetypes() { function getActivetypes() {
let currentTypes = [] let currentTypes = []
let currentTypeIdx let currentTypeIdx
let lastState = TW.partialGraph.states.slice(-1)[0] let lastState = TW.states.slice(-1)[0]
for (var possType in TW.catDict) { for (var possType in TW.catDict) {
currentTypeIdx = TW.catDict[possType] currentTypeIdx = TW.catDict[possType]
...@@ -105,7 +186,7 @@ function getActivetypes() { ...@@ -105,7 +186,7 @@ function getActivetypes() {
} }
function getActivetypesKey() { function getActivetypesKey() {
let lastState = TW.partialGraph.states.slice(-1)[0] let lastState = TW.states.slice(-1)[0]
// ex: '1' or '0|1' or '1|1' // ex: '1' or '0|1' or '1|1'
return lastState.activetypes.map(Number).join('|') return lastState.activetypes.map(Number).join('|')
...@@ -142,11 +223,11 @@ function highlightSelectedNodes(flag){ ...@@ -142,11 +223,11 @@ function highlightSelectedNodes(flag){
function alertCheckBox(eventCheck){ function alertCheckBox(eventCheck){
// NB: we use 2 booleans to adapt to SHIFT checking // NB: we use 2 booleans to adapt to SHIFT checking
// - var TW.checkBox ---------> has the real box state // - var TW.gui.checkBox ---------> has the real box state
// - var TW.manuallyChecked --> remembers if it was changed here // - var TW.gui.manuallyChecked --> remembers if it was changed here
if(!isUndef(eventCheck.checked)) { if(!isUndef(eventCheck.checked)) {
TW.checkBox=eventCheck.checked; TW.gui.checkBox=eventCheck.checked;
TW.manuallyChecked = eventCheck.checked TW.gui.manuallyChecked = eventCheck.checked
} }
} }
...@@ -403,14 +484,16 @@ function htmlProportionalLabels(elems , limit, selectableFlag) { ...@@ -403,14 +484,16 @@ function htmlProportionalLabels(elems , limit, selectableFlag) {
let frecMax = elems[0].value let frecMax = elems[0].value
let frecMin = elems.slice(-1)[0].value let frecMin = elems.slice(-1)[0].value
let sourceRange = frecMax - frecMin
let targetRange = TW.conf.tagcloudFontsizeMax - TW.conf.tagcloudFontsizeMin
for(var i in elems){ for(var i in elems){
if(i==limit) if(i==limit)
break break
let id=elems[i].key let id=elems[i].key
let frec=elems[i].value let frec=elems[i].value
// FIXME: works but is optimizable (precompute stable part) fontSize = ((frec - frecMin) * (targetRange) / (sourceRange)) + TW.conf.tagcloudFontsizeMin
fontSize = ((frec - frecMin) * (TW.conf.tagcloudFontsizeMax - TW.conf.tagcloudFontsizeMin) / (frecMax - frecMin)) + TW.conf.tagcloudFontsizeMin
// debug // debug
// console.log('htmlfied_tagcloud (',id, TW.Nodes[id].label,') freq',frec,' fontSize', fontSize) // console.log('htmlfied_tagcloud (',id, TW.Nodes[id].label,') freq',frec,' fontSize', fontSize)
...@@ -588,21 +671,21 @@ function graphTagCloudElem(nodes) { ...@@ -588,21 +671,21 @@ function graphTagCloudElem(nodes) {
nodesDict:nodes_2_colour, nodesDict:nodes_2_colour,
edgesDict:edges_2_colour edgesDict:edges_2_colour
}); });
TW.selectionActive = true TW.gui.selectionActive = true
} }
var present = TW.partialGraph.states.slice(-1)[0]; // Last var present = TW.states.slice(-1)[0]; // Last
var level = present.level; var level = present.level;
var lastpos = TW.partialGraph.states.length-1; var lastpos = TW.states.length-1;
// like pushing down in a lifo state present becomes state penultimate // like pushing down in a lifo state present becomes state penultimate
// £TODO setState should be doing this shifting // £TODO setState should be doing this shifting
var avantlastpos = lastpos-1; var avantlastpos = lastpos-1;
TW.partialGraph.states[avantlastpos] = {}; TW.states[avantlastpos] = {};
TW.partialGraph.states[avantlastpos].selections = present.selections; TW.states[avantlastpos].selections = present.selections;
TW.partialGraph.states[avantlastpos].level = present.level; TW.states[avantlastpos].level = present.level;
TW.partialGraph.states[avantlastpos].activetypes = present.activetypes; TW.states[avantlastpos].activetypes = present.activetypes;
TW.partialGraph.states[avantlastpos].opposites = present.opposites; TW.states[avantlastpos].opposites = present.opposites;
// recording the new state // recording the new state
TW.setState({ TW.setState({
...@@ -839,16 +922,6 @@ function add1Elem(id) { ...@@ -839,16 +922,6 @@ function add1Elem(id) {
} }
} }
function pushFilterValue(filtername,arg){
if(lastFilter[filtername]["orig"]=="-") {
lastFilter[filtername]["orig"] = arg;
lastFilter[filtername]["last"] = arg;
return;
} else {
lastFilter[filtername]["last"] = arg;
return;
}
}
function saveGraph() { function saveGraph() {
......
...@@ -37,6 +37,7 @@ var ParseCustom = function ( format , data ) { ...@@ -37,6 +37,7 @@ var ParseCustom = function ( format , data ) {
this.parseJSON = function(categories ) { this.parseJSON = function(categories ) {
return dictfyJSON( this.data , categories ); return dictfyJSON( this.data , categories );
}// output = [ nodes, edges, nodes1, ... ] }// output = [ nodes, edges, nodes1, ... ]
}; };
// Level-02 // Level-02
...@@ -457,8 +458,10 @@ function dictfyGexf( gexf , categories ){ ...@@ -457,8 +458,10 @@ function dictfyGexf( gexf , categories ){
var elsNodes = gexf.getElementsByTagName('nodes') // The list of xml nodes 'nodes' (plural) var elsNodes = gexf.getElementsByTagName('nodes') // The list of xml nodes 'nodes' (plural)
TW.labels = []; TW.labels = [];
minNodeSize=10000000;
maxNodeSize=0; // vars for stats => used in a posteriori normalization
let minNodeSize = Infinity
let maxNodeSize = 0
// debug: for local stats // debug: for local stats
// let allSizes = [] // let allSizes = []
...@@ -561,7 +564,7 @@ function dictfyGexf( gexf , categories ){ ...@@ -561,7 +564,7 @@ function dictfyGexf( gexf , categories ){
node.attributes = atts; node.attributes = atts;
let node_cat = "" let node_cat = ""
// nodew=parseInt(attributes["weight"]);
if ( atts["category"] ) { if ( atts["category"] ) {
node_cat = atts["category"]; node_cat = atts["category"];
} }
...@@ -585,11 +588,11 @@ function dictfyGexf( gexf , categories ){ ...@@ -585,11 +588,11 @@ function dictfyGexf( gexf , categories ){
// save record // save record
nodes[node.id] = node nodes[node.id] = node
if(parseInt(node.size) < parseInt(minNodeSize)) if(parseFloat(node.size) < minNodeSize)
minNodeSize= node.size; minNodeSize= parseFloat(node.size);
if(parseInt(node.size) > parseInt(maxNodeSize)) if(parseFloat(node.size) > maxNodeSize)
maxNodeSize= node.size; maxNodeSize= parseFloat(node.size);
// console.debug("node.attributes", node.attributes) // console.debug("node.attributes", node.attributes)
// creating a faceted index from node.attributes // creating a faceted index from node.attributes
...@@ -620,13 +623,15 @@ function dictfyGexf( gexf , categories ){ ...@@ -620,13 +623,15 @@ function dictfyGexf( gexf , categories ){
TW.Clusters = facetsBinning(tmpVals, Atts_2_Exclude) TW.Clusters = facetsBinning(tmpVals, Atts_2_Exclude)
//New scale for node size: now, between 2 and 5 instead [1,70] // linear rescale node sizes
for(var nid in nodes){ if (!isUndef(TW.conf.desirableNodeSizeMin) && !isUndef(TW.conf.desirableNodeSizeMax)) {
// console.log("dictfyGexf node", nid) let desiSizeRange = TW.conf.desirableNodeSizeMax-TW.conf.desirableNodeSizeMin
nodes[nid].size = desirableNodeSizeMIN+ (parseInt(nodes[nid].size)-1)*((desirableNodeSizeMAX-desirableNodeSizeMIN) / (maxNodeSize-minNodeSize)); let realSizeRange = maxNodeSize - minNodeSize
for(var nid in nodes){
nodes[nid].size = parseInt(1000 * ((parseFloat(nodes[nid].size) - minNodeSize) / realSizeRange * desiSizeRange + TW.conf.desirableNodeSizeMin)) / 1000
}
} }
// looping source edges to conforming edge // looping source edges to conforming edge
// then updateRelations // then updateRelations
var edgeId = 0; var edgeId = 0;
...@@ -908,6 +913,10 @@ function dictfyJSON( data , categories ) { ...@@ -908,6 +913,10 @@ function dictfyJSON( data , categories ) {
nodes2={}, bipartiteD2N={}, bipartiteN2D={} nodes2={}, bipartiteD2N={}, bipartiteN2D={}
} }
// normalization, same as parseGexf
let minNodeSize = Infinity
let maxNodeSize = 0
// if scanClusters, we'll also use: // if scanClusters, we'll also use:
var tmpVals = {} var tmpVals = {}
var Atts_2_Exclude = {} var Atts_2_Exclude = {}
...@@ -936,6 +945,12 @@ function dictfyJSON( data , categories ) { ...@@ -936,6 +945,12 @@ function dictfyJSON( data , categories ) {
node.size = Math.sqrt(Number(n.term_occ)) node.size = Math.sqrt(Number(n.term_occ))
} }
if(parseFloat(node.size) < minNodeSize)
minNodeSize= parseFloat(node.size);
if(parseFloat(node.size) > maxNodeSize)
maxNodeSize= parseFloat(node.size);
if (!catCount[node.type]) catCount[node.type] = 0 if (!catCount[node.type]) catCount[node.type] = 0
catCount[node.type]++; catCount[node.type]++;
...@@ -952,6 +967,17 @@ function dictfyJSON( data , categories ) { ...@@ -952,6 +967,17 @@ function dictfyJSON( data , categories ) {
TW.Clusters = facetsBinning (tmpVals, Atts_2_Exclude) TW.Clusters = facetsBinning (tmpVals, Atts_2_Exclude)
// £TODO ask if wanted
// if we wanted linear rescale node sizes like dictfyGexf:
// if (!isUndef(TW.conf.desirableNodeSizeMin) && !isUndef(TW.conf.desirableNodeSizeMax)) {
// let desiSizeRange = TW.conf.desirableNodeSizeMax-TW.conf.desirableNodeSizeMin
// let realSizeRange = maxNodeSize - minNodeSize
// for(var nid in nodes){
// nodes[nid].size = parseInt(1000 * ((parseFloat(nodes[nid].size) - minNodeSize) / realSizeRange * desiSizeRange + TW.conf.desirableNodeSizeMin)) / 1000
// }
// }
TW.colorList.sort(function(){ return Math.random()-0.5; }); TW.colorList.sort(function(){ return Math.random()-0.5; });
for (var i in nodes ){ for (var i in nodes ){
if (nodes[i].color=="#FFFFFF") { if (nodes[i].color=="#FFFFFF") {
......
...@@ -292,7 +292,7 @@ var SigmaUtils = function () { ...@@ -292,7 +292,7 @@ var SigmaUtils = function () {
var nodeColor = node.color || settings('defaultNodeColor') var nodeColor = node.color || settings('defaultNodeColor')
// mode variants // mode variants
if (TW.selectionActive) { if (TW.gui.selectionActive) {
// passive nodes should blend in the grey of twEdgeGreyColor // passive nodes should blend in the grey of twEdgeGreyColor
// cf settings_explorerjs, defgrey_color and greyEverything() // cf settings_explorerjs, defgrey_color and greyEverything()
if (node.customAttrs.grey) { if (node.customAttrs.grey) {
...@@ -1180,9 +1180,9 @@ function colorsBy(daclass) { ...@@ -1180,9 +1180,9 @@ function colorsBy(daclass) {
// louvain needs preparation // louvain needs preparation
if(daclass=="clust_louvain") { if(daclass=="clust_louvain") {
if(!TW.partialGraph.states.slice(-1)[0].LouvainFait) { if(!TW.states.slice(-1)[0].LouvainFait) {
RunLouvain() RunLouvain()
TW.partialGraph.states.slice(-1)[0].LouvainFait = true TW.states.slice(-1)[0].LouvainFait = true
} }
} }
......
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