1

I am playing with vis.js and have worked out how to get an array of all the currently selected nodes.

var TempNodes = network.getSelectedNodes();

My problem is that the getSelectedNodes() array is returned with all the nodes id's in numeric order from lowest to highest...There doesn't seem to be a way to tell what the last selected node id was or what the first selected node id was. I can only tell which node id's were selected.

Does anyone know a way to be able to find out from the getSelectedNodes array, what was the first or last selected node id ?

laaposto
  • 11,835
  • 15
  • 54
  • 71
Craig
  • 387
  • 4
  • 16

2 Answers2

1

The documentation specifically states that getSelection()

Returns an array with the ids of the selected nodes. Returns an empty array if no nodes are selected. The selections are not ordered.

Since at present, the way to select multiple nodes is to long-press them, you can keep selection-order yourself, by listening to the selection event:

var mySelectionOrder = [];
var previouslySelected = {};
network.on('select', function(p) {
      var selected = {};
      // add newly-selected nodes at end of mySelectionOrder
      p.nodes.forEach(function(n) {
            if ( ! previouslySelected[n]) { mySelectionOrder.push(n); }
            selected[n] = true;
      });
      // remove newly-unselected entries from mySelectionOrder
      mySelectionOrder = mySelectionOrder.filter(
            function(e, i, a) { return selected[e]; });
      // prepare for next run
      previouslySelected = selected;
      // output to console to make sure it works
      console.log("Selection updated", mySelectionOrder);
}); 

(Edited to fix JS code; tested to work with this example)

Community
  • 1
  • 1
tucuxi
  • 17,561
  • 2
  • 43
  • 74
  • Thanks Tucuxi, I'm not at my PC right now, but I'll try as soon as I get home. – Craig Apr 09 '15 at 09:44
  • Hi Tucixi, although I get a nice array of numbers...ie...0,1,2 etc...I do not get the id of the nodes that have been selected. – Craig Apr 10 '15 at 01:27
  • Just to clarify a bit more... Each node is stored as a json object like this.. {id: 123, label: 'Test Node',group: 'My Group' }...I need to get the id of each currently selected node in the order they were selected. – Craig Apr 10 '15 at 01:44
  • Also...contrary to documentation, getSelection() does indeed return all selected nodes but they are returned in a numerically ascending order based on the nodes id property. For example, selecting node id's in this order 3,1,2 - and then using getSelection() will return nodes id's in this order 1,2,3. – Craig Apr 10 '15 at 02:14
  • @Craig - if docs say "not ordered", this actually means "do not rely upon this being ordered, even if right now it is, as we may change it on a whim" – tucuxi Apr 10 '15 at 05:23
  • Fair enough, I guess it's your code and you can describe it any way you like. To me if something is ordered numerically ascending, then it is ordered. I'd suggest though that a more useful way of ordering the selected nodes in the getSelection() method would be in the order they are added by the user, or having an option in the method call like 'orderSelected', 'notOrdered', 'numericalAscending', 'numericalDescending'. Others may disagree! – Craig Apr 10 '15 at 06:57
  • @Craig I am in no way affiliated with the writers of the vis.js documentation (or vis.js for that matter). As a long-time developer, though, it is worth mentioning that when API docs say that "collection X is not ordered", you should treat "X" as having no specific order. – tucuxi Apr 10 '15 at 07:36
1

Using the concepts tucuxi put forward, I did come up with some working code to achieve this. Although tucuxi's code did not work 'straight out of the box' his idea was sound and he deserves credit for it.

Here is the code that eventually worked for me

 var PreviouslySelectedNodes = [];
    var SelectedNodesInOrder = [];

    network.on('select', function (properties) {      

      // itterate through each visjs selected nodes and see if any value is not present in our current ordered list
      // If it's not already present, push it to the top of our ordered list
      var SelectedNodeIDs = network.getSelection().nodes // First get all the visjs selected nodes

      // If only one Node is currently selected, then empty the SelectedNodesInOrder array ready for a new set
      if(SelectedNodeIDs.length == 1){
          SelectedNodesInOrder = [];
      }

      // Cycle through all current selected visjs nodes
      for(var t = 0; t <= SelectedNodeIDs.length; t++){

          // cycle through all currently selected ordered nodes in our ordered array
          var found = false; flag the default as this node not already in our ordered list
          for(var y = 0; y <= SelectedNodesInOrder.length; y++){
                if(SelectedNodesInOrder[y] == SelectedNodeIDs[t]){ // This node already exists in our ordered list
                    found = true;
                }         
          }

          // If the current visjs selected node doesn't already exist in the SelectedNodesInOrder, then add it
          if(found === false){
                SelectedNodesInOrder.push(SelectedNodeIDs[t]);
          }

      }

    console.log(SelectedNodesInOrder); // test by dumping our ordered array list to the console

    });
Craig
  • 387
  • 4
  • 16
  • I did not test my answer, it is true. However, it is customary to explain why answers fail, as I can edit it to improve it. Also, your answer is slow when many nodes are selected -- O(n^2); mine, when fixed, should be much faster: O(n) – tucuxi Apr 10 '15 at 05:28
  • Yep, you're probably right. If you fix it, I'll change it to the correct (and better by being faster) answer. No problem. – Craig Apr 10 '15 at 06:59