Quantcast
Channel: GoJS - Northwoods Software
Viewing all articles
Browse latest Browse all 6969

Create decision tree, all collapsed but the root and its children

$
0
0

@rkaren wrote:

Hi, I am relatively new to this. below is adaped from your decision tree example. I am trying to get it to be drawn
with the top node and its 2 children visible and all else collapsed. nothing seems to work. It opens all collapsed- only root visible. can someone tell me
where to do that. I tried calling expandTree() and changing nodes to visible but it didnt' have any effect. thanks!

<script src="/gojs/release/go-debug.js"></script>
<link href='https://fonts.googleapis.com/css?family=Roboto:400,500' rel='stylesheet' type='text/css'>
<!-- <script src="https://load.crosstab.com/gojs/assets/js/goSamples.js"></script>--> <!-- this is only for the GoJS Samples framework -->
<script id="code">
  go.licenseKey = "73fe4fe7b01c28c702d95d76423d6cbc5cf07f21de8216a35d501da4ec5f69172199b87156d2dec9dbfc4ffa4e6fd0ded4956f29921f026ce732d0de10eb80fdb23e76b7460f468fa5042fc1cead2fa5af2f24f1c2a767a48f288af2b9f8c28e4cebf2d44ed507a42a70";
  function initDecTree() {
    var GO = go.GraphObject.make;  // for conciseness in defining templates

    myDiagram = GO(go.Diagram, "decisionTreeDiv",  // must name or refer to the DIV HTML element
              {
                //initialContentAlignment: go.Spot.Left,
                initialContentAlignment: go.Spot.Top,
                allowSelect: false,  // the user cannot select any part
                // create a TreeLayout for the decision tree
                layout: GO(go.TreeLayout,
                  {angle: 90})
              });

// custom behavior for expanding/collapsing half of the subtree from a node
function buttonExpandCollapse(e, port) {
  var node = port.part;
  node.diagram.startTransaction("expand/collapse");
  var portid = port.portId;
  node.findLinksOutOf(portid).each(function(l) {
      if (l.visible) {
        // collapse whole subtree recursively
        collapseTree(node, portid);
      } else {
        // only expands immediate children and their links
        var n = l.getOtherNode(node);
        if (n.text == null || n.text.length == 0) {
          // do not open this link
          var code = node.text + '-' + portid;
          if (code == '1-1-1-1-1')
            addressBook.openNewFileForStudyNYT('ipaffa17', 'Y', 'PRINT');
          else if (code == '1-1-1-1-2')
            addressBook.openNewFileForStudyNYT('ipaffa17', 'N', 'PRINT');
          else if (code == '1-1-2-1-1')
            addressBook.openNewFileForStudyNYT('ipaffa17', 'Y', 'DIGITAL');
          else if (code == '1-1-2-1-2')
            addressBook.openNewFileForStudyNYT('ipaffa17', 'N', 'DIGITAL');
          else if (code == '1-2-1-1-1')
            addressBook.openNewFileForStudyNYT('mrfa17', 'Y', '');
          else if (code == '1-2-1-1-2')
            addressBook.openNewFileForStudyNYT('mrfa17', 'N', '');
          else if (code == '1-2-2-1-1')
            addressBook.openNewFileForStudyNYT('mrsp17', 'Y', '');
          else if (code == '1-2-2-1-2')
            addressBook.openNewFileForStudyNYT('mrsp17', 'N', '');
          else if (code == '1-2-3-1-1')
            addressBook.openNewFileForStudyNYT('mrdb17', 'Y', '');
          else if (code == '1-2-3-1-2')
            addressBook.openNewFileForStudyNYT('mrdb17', 'N', '');
          else
            alert('open study with this: ' + buttonText(code));
          return;
        } else {
          l.visible = true;
          //window.console.log('expanding link from node ' + node.text + ' to node ' + n + ', text = ' + n.text);
          if (n !== null) {
            //n.location = node.getDocumentPoint(go.Spot.TopRight);
            n.location = node.getDocumentPoint(go.Spot.BottomLeft);
            n.visible = true;
          }
        }
      }
    });
  myDiagram.toolManager.hideToolTip();
  node.diagram.commitTransaction("expand/collapse");
}

// recursive function for collapsing complete subtree
function collapseTree(node, portid) {
  node.findLinksOutOf(portid).each(function(l) {
      l.visible = false;
      var n = l.getOtherNode(node);
      if (n !== null) {
        n.visible = false;
        collapseTree(n, null);  // null means all links, not just for a particular portId
      }
    });
}

// get the text for the tooltip from the data on the object being hovered over
function tooltipTextConverter(data) {
  var str = "";
  var e = myDiagram.lastInput;
  var currobj = e.targetObject;
  if (currobj !== null ) {
    if (currobj.name === "ButtonA" ||
                           (currobj.panel !== null && currobj.panel.name === "ButtonA")) {
      str = data.aToolTip;
    } else if (currobj.name === "ButtonB" ||
                           (currobj.panel !== null && currobj.panel.name === "ButtonB")) {
      str = data.bToolTip;
    } else if (currobj.name === "ButtonC" ||
                           (currobj.panel !== null && currobj.panel.name === "ButtonC")) {
      str = data.cToolTip;
    } else if (currobj.name === "ButtonD" ||
                           (currobj.panel !== null && currobj.panel.name === "ButtonD")) {
      str = data.dToolTip;
    }
  }
  return str;
}

// define tooltips for buttons
var tooltipTemplate =
  GO(go.Adornment, "Auto",
    GO(go.Shape, "Rectangle",
      { fill: "whitesmoke", stroke: "lightgray" }),
    GO(go.TextBlock,
      {
        font: "12pt sans-serif",
        wrap: go.TextBlock.None,
        alignment: go.Spot.Center,
        margin: 6
      },
      new go.Binding("text", "", tooltipTextConverter))
  );

// define the Node template for non-leaf nodes
myDiagram.nodeTemplateMap.add("decision",
  GO(go.Node, "Auto",
    new go.Binding("text", "key"),
    // define the node's outer shape, which will surround the Horizontal Panel
    GO(go.Shape, "Rectangle",
      { fill: "whitesmoke", stroke: "lightgray" }),
    // define a horizontal Panel to place the node's text alongside the buttons
    // RK: font below was 30px Roboto, sans-serif
    GO(go.Panel, "Horizontal",
      GO(go.TextBlock,
        { visible: false, font: "30px Roboto, sans-serif", margin: 5 },
        new go.Binding("text", "key")),
      GO(go.Panel, "Horizontal",
          { defaultStretch: go.GraphObject.Fill, margin: 3 },
          GO("Button",  // button A
            {
              name: "ButtonA",
              click: buttonExpandCollapse,
              toolTip: tooltipTemplate
            },
            new go.Binding("portId", "a"),
            // font settings was: font: '500 16px Roboto, sans-serif',
            GO(go.TextBlock,
              { font: '500 16px Roboto, sans-serif',
                wrap: go.TextBlock.None, margin: 5 },
              new go.Binding("visible", "aVisible"),
              new go.Binding("text", "aText"))
          ),  // end button A
          GO("Button",  // button B
            {
              name: "ButtonB",
              click: buttonExpandCollapse,
              toolTip: tooltipTemplate
            },
            new go.Binding("portId", "b"),
            new go.Binding("visible", "bVisible"),
            GO(go.TextBlock,
              { font: '500 16px Roboto, sans-serif',
                wrap: go.TextBlock.None, margin: 5 },
              new go.Binding("text", "bText"))
          ),  // end button B
          GO("Button",  // button C
            {
              name: "ButtonC",
              click: buttonExpandCollapse,
              toolTip: tooltipTemplate
            },
            new go.Binding("portId", "c"),
            new go.Binding("visible", "cVisible"),
            GO(go.TextBlock,
              { font: '500 16px Roboto, sans-serif',
                wrap: go.TextBlock.None, margin: 5 },
              new go.Binding("text", "cText"))
          ),  // end button C
          GO("Button",  // button D
            {
              name: "ButtonD",
              click: buttonExpandCollapse,
              toolTip: tooltipTemplate
            },
            new go.Binding("portId", "d"),
            new go.Binding("visible", "dVisible"),
            GO(go.TextBlock,
              { font: '500 16px Roboto, sans-serif',
                wrap: go.TextBlock.None, margin: 5 },
              new go.Binding("text", "dText"))
          )  // end button D
      )  // end Horizontal Panel
    )  // end Horizontal Panel
  ));  // end Node and call to add

// define the Node template for leaf nodes
myDiagram.nodeTemplateMap.add("personality",
  GO(go.Node, "Auto",
    new go.Binding("text", "key"),
    GO(go.Shape, "Rectangle",
      { fill: "whitesmoke", stroke: "lightgray"}
     ),
    // font below was 13px Roboto, sans-serif
    GO(go.TextBlock,
      { font: '13px Roboto, sans-serif',
        wrap: go.TextBlock.None, margin: 5,
        click: function(e,obj) {
               onClickEvent('e = ' + e + ' obj = ' + obj + ', text = ' + obj.text);
             }
      },
      new go.Binding("text", "text"))
  ));

// define the only Link template
myDiagram.linkTemplate =
  GO(go.Link, go.Link.Orthogonal,  // the whole link panel
    { fromPortId: "" },
    new go.Binding("fromPortId", "fromport"),
    GO(go.Shape,  // the link shape
      { stroke: "lightblue", strokeWidth: 2 })
  );

// create the model for the decision tree
var model =
  GO(go.GraphLinksModel,
    { linkFromPortIdProperty: "fromport" });
// set up the model with the node and link data
makeNodes(model);
makeLinks(model);
myDiagram.model = model;

// make all but the start node invisible
myDiagram.nodes.each(function(n) {
    if (n.text != "Is this for a luxury, affluent or upscale advertiser/client?" ) {
      n.visible = false;
    } else {
      n.visible = true;
      console.log('expanding tree from node ' + n.text );
      n.expandTree(2);
    }
  });
myDiagram.links.each(function(l) {
    l.visible = false;
  });
  }
  function buttonText(code) {
    var buttonTextArray = [
      { cd: '1', text: "Is this for a luxury, affluent or upscale advertiser/client?"},  // the root node
      { cd: '1-1', text: 'Yes'},
      { cd: '1-1-1', text: 'I need print research'},
      { cd: '1-1-1-1', text: 'Do you need research against competitors?'},
      { cd: '1-1-1-1-1', text: 'Yes'},
      { cd: '1-1-1-1-2', text: 'No'},
      { cd: '1-1-2', text: 'I need digital research'},
      { cd: '1-1-2-1', text: 'Do you need research against competitors?'},
      { cd: '1-1-2-1-1', text: 'Yes'},
      { cd: '1-1-2-1-2', text: 'No'},
      { cd: '1-2', text: 'No, I want MRI research (this is print data only)'},
      { cd: '1-2-1', text: 'Use MRI Fall 2017'},
      { cd: '1-2-2', text: 'Use MRI Spring 2017'},
      { cd: '1-2-3', text: 'Use MRI Doublebase 2017'},
      { cd: '1-2-1-1', text: 'Do you need research against competitors?'},
      { cd: '1-2-1-1-1', text: 'Yes'},
      { cd: '1-2-1-1-2', text: 'No'},
      { cd: '1-2-2-1', text: 'Do you need research against competitors?'},
      { cd: '1-2-2-1-1', text: 'Yes'},
      { cd: '1-2-2-1-2', text: 'No'},
      { cd: '1-2-3-1', text: 'Do you need research against competitors?'},
      { cd: '1-2-3-1-1', text: 'Yes'},
      { cd: '1-2-3-1-2', text: 'No'}
     ];
    var i = 0;
    while (i < buttonTextArray.length) {
      var obj = buttonTextArray[i];
      if (obj.cd === code) {
        return obj.text;
      } else {
        i++;
      }
    }
    return null;
  }

  function makeNodes(model) {
    var nodeDataArray = [
      { key: "Is this for a luxury, affluent or upscale advertiser/client?"},  // the root node
      { key: '1'},
      { key: '1-1'},
      { key: '1-1-1'},
      { key: '1-1-1-1'},
      { key: '1-1-1-1-1'},
      { key: '1-1-1-1-2'},
      { key: '1-1-2'},
      { key: '1-1-2-1'},
      { key: '1-1-2-1-1'},
      { key: '1-1-2-1-2'},
      { key: '1-2'},
      { key: '1-2-1'},
      { key: '1-2-2'},
      { key: '1-2-3'},
      { key: '1-2-1-1'},
      { key: '1-2-1-1-1'},
      { key: '1-2-1-1-2'},
      { key: '1-2-2-1'},
      { key: '1-2-2-1-1'},
      { key: '1-2-2-1-2'},
      { key: '1-2-3-1'},
      { key: '1-2-3-1-1'},
      { key: '1-2-3-1-2'}
    ];

    // Provide the same choice information for all of the nodes on each level.
// The level is implicit in the number of characters in the Key, except for the root node.
// In a different application, there might be different choices for each node, so the initialization would be above, where the Info's are created.
// But for this application, it makes sense to share the initialization code based on tree level.
for (var i = 0; i < nodeDataArray.length; i++) {
  var d = nodeDataArray[i];
  //window.console.log('d.key = ' + d.key);
  if (d.key === "Is this for a luxury, affluent or upscale advertiser/client?") {
    d.category = "decision";
    d.a = "1";
    d.aText = buttonText(d.a);
    d.aToolTip = d.aText;
    d.b = "2";
    d.bText = buttonText(d.b);
    d.bToolTip = d.bText;
    d.aVisible = true;
    d.bVisible = false; // if this many nodes do not exist , set the *Visible variables of extra ones to false.
    d.cVisible = false;
    d.dVisible = false;
  } else {
    d.aVisible = false;
    d.bVisible = false;
    d.cVisible = false;
    d.dVisible = false;
    if (buttonText(d.key + '-1') !== null) { // this checks for a child (append '-1' to the key).
                                             // if there is a child, this is not a leaf.
        d.category = "decision";
        d.a = "1";
        //d.aText = d.key + '-1';
        if (buttonText(d.key + '-1'))
          d.aText = buttonText(d.key + '-1');
        else
          d.aText = d.key + '-1';
        d.aToolTip = getToolTip(d.key + '-1', d.aText);
        d.aVisible = true;
        if (buttonText(d.key + '-2') != null) {
          d.b = "2";
          if (buttonText(d.key + '-2'))
            d.bText = buttonText(d.key + '-2');
          else
            d.bText = d.key + '-2';
          d.bToolTip = getToolTip(d.key + '-2', d.bText);
          d.bVisible = true;
        }
        if (buttonText(d.key + '-3') != null) {
          d.c = "3";
          if (buttonText(d.key + '-3'))
            d.cText = buttonText(d.key + '-3');
          else
            d.cText = d.key + '-3';
          d.cToolTip = d.cText;
          d.cToolTip = getToolTip(d.key + '-3', d.cText);
          d.cVisible = true;
        }
        if (buttonText(d.key + '-4') != null) {
          d.d = "4";
          if (buttonText(d.key + '-4'))
            d.dText = buttonText(d.key + '-4');
          else
            d.dText = d.key + '-4';
          d.dToolTip = d.dText;
          d.dToolTip = getToolTip(d.key + '-4', d.dText);
          d.dVisible = true;
        }
    }
  }
}
model.nodeDataArray = nodeDataArray;
  }

  function getToolTip(key, buttonTxt) {
    console.log ('d.key = ' + key + ', buttonTxt = ' + buttonTxt);
    if (key.substr(0, 3) == '1-1') return getFullStudyName('ipaffa17');
    else if (key.substr(0,5) == '1-2-1') return getFullStudyName('mrfa17');
    else if (key.substr(0,5) == '1-2-2') return getFullStudyName('mrsp17');
    else if (key.substr(0,5) == '1-2-3') return getFullStudyName('mrdb17');
    return buttonTxt;
  }

  function getFullStudyName(study) {
    var namesArr = [
      {study: 'pwsrao17', name: 'JD Power Auto Media and Marketing Summer 2017'},
      {study: 'empi16', name: 'Erdos & Morgan Purchase 2016'},
      {study: 'emol16', name: 'Erdos & Morgan Opinion Leaders 2016'},
      {study: 'emfa16', name: 'Erdos & Morgan Financial Adviser 2016'},
      {study: 'ipaffa17', name: 'Ipsos Affluent Survey Fall 2017'},
      {study: 'ipafsp17', name: 'Ipsos Affluent Survey Spring 2017'},
      {study: 'mrsp17', name: 'Mediamark Spring 2017'},
      {study: 'mrfa17', name: 'Mediamark Fall 2017'},
      {study: 'mrdb17', name: 'Mediamark Doublebase 2017'},
      {study: 'ipgb17', name: 'Ipsos Global Influencers 2017'}
    ];
    var i = 0;
    while (i < namesArr.length) {
      if (namesArr[i].study == study) return namesArr[i].name;
      i++;
    }
    return study;
  }

  function makeLinks(model) {
    var linkDataArray = [];
    var nda = model.nodeDataArray;
    for (var i = 0; i < nda.length; i++) {
      var key = nda[i].key;
      if (key === "Is this for a luxury, affluent or upscale advertiser/client?" || key.length === 0) continue;
      var prefix = key.slice(0, key.length-2);
      var letter = key.charAt(key.length-1);
      if (key.length === 1) prefix = "Is this for a luxury, affluent or upscale advertiser/client?";
      var obj = { from: prefix, fromport: letter, to: key };
      window.console.log('for key ' + key + ', make link from ' + obj.from + ', fromport: ' + obj.fromport + ', to: ' + obj.to);
      linkDataArray.push(obj);
    }
    model.linkDataArray = linkDataArray;
  }
  function onClickEvent (msg) {
    alert('msg = ' + msg);
  }
</script>

Posts: 2

Participants: 2

Read full topic


Viewing all articles
Browse latest Browse all 6969

Trending Articles