215 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
define(function () {
 | 
						|
  return function () {
 | 
						|
    var self = this;
 | 
						|
    var objects = { nodes: {}, links: {} };
 | 
						|
    var targets = [];
 | 
						|
    var views = {};
 | 
						|
    var currentView;
 | 
						|
    var currentObject;
 | 
						|
    var running = false;
 | 
						|
 | 
						|
    function saveState() {
 | 
						|
      var e = [];
 | 
						|
 | 
						|
      if (currentView)
 | 
						|
        e.push("v:" + currentView);
 | 
						|
 | 
						|
      if (currentObject) {
 | 
						|
        if ("node" in currentObject)
 | 
						|
          e.push("n:" + encodeURIComponent(currentObject.node.nodeinfo.node_id));
 | 
						|
 | 
						|
        if ("link" in currentObject)
 | 
						|
          e.push("l:" + encodeURIComponent(currentObject.link.id));
 | 
						|
      }
 | 
						|
 | 
						|
      var s = "#!" + e.join(";");
 | 
						|
 | 
						|
      window.history.pushState(s, undefined, s);
 | 
						|
    }
 | 
						|
 | 
						|
    function resetView(push) {
 | 
						|
      push = trueDefault(push);
 | 
						|
 | 
						|
      targets.forEach( function (t) {
 | 
						|
        t.resetView();
 | 
						|
      });
 | 
						|
 | 
						|
      if (push) {
 | 
						|
        currentObject = undefined;
 | 
						|
        saveState();
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    function gotoNode(d) {
 | 
						|
      if (!d)
 | 
						|
        return false;
 | 
						|
 | 
						|
      targets.forEach( function (t) {
 | 
						|
        t.gotoNode(d);
 | 
						|
      });
 | 
						|
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
 | 
						|
    function gotoLink(d) {
 | 
						|
      if (!d)
 | 
						|
        return false;
 | 
						|
 | 
						|
      targets.forEach( function (t) {
 | 
						|
        t.gotoLink(d);
 | 
						|
      });
 | 
						|
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
 | 
						|
    function gotoLocation(d) {
 | 
						|
      if (!d)
 | 
						|
        return false;
 | 
						|
 | 
						|
      targets.forEach( function (t) {
 | 
						|
        if(!t.gotoLocation)console.warn("has no gotoLocation", t);
 | 
						|
        t.gotoLocation(d);
 | 
						|
      });
 | 
						|
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
 | 
						|
    function loadState(s) {
 | 
						|
      if (!s)
 | 
						|
        return false;
 | 
						|
 | 
						|
      s = decodeURIComponent(s);
 | 
						|
 | 
						|
      if (!s.startsWith("#!"))
 | 
						|
        return false;
 | 
						|
 | 
						|
      var targetSet = false;
 | 
						|
 | 
						|
      s.slice(2).split(";").forEach(function (d) {
 | 
						|
        var args = d.split(":");
 | 
						|
 | 
						|
        if (args[0] === "v" && args[1] in views) {
 | 
						|
          currentView = args[1];
 | 
						|
          views[args[1]]();
 | 
						|
        }
 | 
						|
 | 
						|
        var id;
 | 
						|
 | 
						|
        if (args[0] === "n") {
 | 
						|
          id = args[1];
 | 
						|
          if (id in objects.nodes) {
 | 
						|
            currentObject = { node: objects.nodes[id] };
 | 
						|
            gotoNode(objects.nodes[id]);
 | 
						|
            targetSet = true;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (args[0] === "l") {
 | 
						|
          id = args[1];
 | 
						|
          if (id in objects.links) {
 | 
						|
            currentObject = { link: objects.links[id] };
 | 
						|
            gotoLink(objects.links[id]);
 | 
						|
            targetSet = true;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      });
 | 
						|
 | 
						|
      return targetSet;
 | 
						|
    }
 | 
						|
 | 
						|
    self.start = function () {
 | 
						|
      running = true;
 | 
						|
 | 
						|
      if (!loadState(window.location.hash))
 | 
						|
        resetView(false);
 | 
						|
 | 
						|
      window.onpopstate = function (d) {
 | 
						|
        if (!loadState(d.state))
 | 
						|
          resetView(false);
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    self.view = function (d) {
 | 
						|
      if (d in views) {
 | 
						|
        views[d]();
 | 
						|
 | 
						|
        if (!currentView || running)
 | 
						|
          currentView = d;
 | 
						|
 | 
						|
        if (!running)
 | 
						|
          return;
 | 
						|
 | 
						|
        saveState();
 | 
						|
 | 
						|
        if (!currentObject) {
 | 
						|
          resetView(false);
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        if ("node" in currentObject)
 | 
						|
          gotoNode(currentObject.node);
 | 
						|
 | 
						|
        if ("link" in currentObject)
 | 
						|
          gotoLink(currentObject.link);
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    self.node = function (d) {
 | 
						|
      return function () {
 | 
						|
        if (gotoNode(d)) {
 | 
						|
          currentObject = { node: d };
 | 
						|
          saveState();
 | 
						|
        }
 | 
						|
 | 
						|
        return false;
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    self.link = function (d) {
 | 
						|
      return function () {
 | 
						|
        if (gotoLink(d)) {
 | 
						|
          currentObject = { link: d };
 | 
						|
          saveState();
 | 
						|
        }
 | 
						|
 | 
						|
        return false;
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    self.gotoLocation = gotoLocation;
 | 
						|
 | 
						|
    self.reset = function () {
 | 
						|
      resetView();
 | 
						|
    };
 | 
						|
 | 
						|
    self.addTarget = function (d) {
 | 
						|
      targets.push(d);
 | 
						|
    };
 | 
						|
 | 
						|
    self.removeTarget = function (d) {
 | 
						|
      targets = targets.filter( function (e) {
 | 
						|
        return d !== e;
 | 
						|
      });
 | 
						|
    };
 | 
						|
 | 
						|
    self.addView = function (k, d) {
 | 
						|
      views[k] = d;
 | 
						|
    };
 | 
						|
 | 
						|
    self.setData = function (data) {
 | 
						|
      objects.nodes = {};
 | 
						|
      objects.links = {};
 | 
						|
 | 
						|
      data.nodes.all.forEach( function (d) {
 | 
						|
        objects.nodes[d.nodeinfo.node_id] = d;
 | 
						|
      });
 | 
						|
 | 
						|
      data.graph.links.forEach( function (d) {
 | 
						|
        objects.links[d.id] = d;
 | 
						|
      });
 | 
						|
    };
 | 
						|
 | 
						|
    return self;
 | 
						|
  };
 | 
						|
});
 |