コード例 #1
0
ファイル: Adapter.js プロジェクト: felixhayashi/TW5-TiddlyMap
  /**
   * Returns all edges stored in a given tiddler. Any edge stored in a
   * tiddler is orginally an outgoing edge. Depending on how the user
   * changes the arrow head (by manipulating the Visjs edge-type style),
   * the edge may change its orientation and become an incoming edge or
   * bi-directional. Therefore, the edges retrieved may be incoming,
   * outgoing or both!
   *
   * Returned edges may be of the following type:
   *
   * - Edges stored in the tiddler text (=links).
   * - Edges stored in fields denoted by magic edge-types.
   * - TiddlyMap edges stored in a json format
   *
   * @param {Tiddler} tiddler - A tiddler reference or object from
   *     which to retrieve the edges.
   * @param {Hashmap<TiddlerReference, boolean>} [toWL]
   *     A hashmap on which basis it is decided, whether to include
   *     an edge that leads to a certain tiddler in the result or not.
   *     In this case, all edges stored in the tiddler are treated as
   *     outgoing and the arrow head is ignored. If not specified,
   *     all edges are included.
   * @param {Hashmap<string, boolean>} [typeWL]
   *     A hashmap on which basis it is decided, whether to include
   *     an edge of a given type in the result or not. If not
   *     specified, all edges are included.
   */
  getEdges(tiddler, toWL, typeWL) {

    const tObj = utils.getTiddler(tiddler);

    if (!tObj || utils.isSystemOrDraft(tObj)) {
      return;
    }

    const { allETy } = this.indeces;
    const edges = utils.makeHashMap();
    const eTySubscribers = this.edgeTypeSubscriberRegistry.getAll();

    for (let i = 0, l = eTySubscribers.length; i < l; i++) {
      Object.assign(edges, (eTySubscribers[i]).loadEdges(tObj, toWL, typeWL));
    }

    for (let id in edges) {

      const edge = edges[id];

      // check exists for historical reasons...
      if (!edge.from || !edge.to) {
        continue;
      }

      const type = allETy[edge.type] || EdgeType.getInstance(edge.type);
      addStyleToEdge(edges[id], type);

      edges[id] = edge;
    }

    return edges;

  }
コード例 #2
0
ファイル: lib.adapter.js プロジェクト: EdDixon/TW5-TiddlyMap
Adapter.prototype.selectEdgesByType = function(type) {

  var typeWL = utils.makeHashMap();
  typeWL[new EdgeType(type).id] = true; 
  return this.getEdgesForSet(this.getAllPotentialNodes(), null, typeWL);
  
};
コード例 #3
0
ファイル: Adapter.js プロジェクト: felixhayashi/TW5-TiddlyMap
  /**
   * Select all edges of a given type.
   *
   * @param {string|EdgeType} type - Either the edge type id (name) or an EdgeType object.
   */
  selectEdgesByType(type) {

    const typeWL = utils.makeHashMap({
      [EdgeType.getInstance(type).id]: true,
    });

    return this.getEdgesForSet(this.getAllPotentialNodes(), null, typeWL);

  }
コード例 #4
0
ファイル: Adapter.js プロジェクト: felixhayashi/TW5-TiddlyMap
  /**
   * The method will return all outgoing edges for a subset of tiddlers.
   *
   * @param {Array<Tiddler>} tiddlers - The set of tiddlers to consider.
   * @param toWL
   * @param typeWL
   * @return {Hashmap<Id, Edge>} An edge collection.
   */
  getEdgesForSet(tiddlers, toWL, typeWL) {

    const edges = utils.makeHashMap();
    for (let i = tiddlers.length; i--;) {
      Object.assign(edges, this.getEdges(tiddlers[i], toWL, typeWL));
    }

    return edges;

  }
コード例 #5
0
ファイル: lib.adapter.js プロジェクト: EdDixon/TW5-TiddlyMap
Adapter.prototype.getEdgesForSet = function(tiddlers, toWL, typeWL) {

  var edges = utils.makeHashMap();
  for(var i = tiddlers.length; i--;) {
    $tw.utils.extend(edges, this.getEdges(tiddlers[i], toWL, typeWL));
  }
  
  return edges;

};
コード例 #6
0
ファイル: lib.adapter.js プロジェクト: EdDixon/TW5-TiddlyMap
Adapter.prototype.getEdges = function(tiddler, toWL, typeWL) {

  var tObj = utils.getTiddler(tiddler);
  if(!tObj || utils.isSystemOrDraft(tObj)) return;
  
  var edges = utils.makeHashMap();
  this._addTmapEdges(edges, tObj, toWL, typeWL);
  this._addBodyAndFieldEdges(edges, tObj, toWL, typeWL);

  return edges;

};
コード例 #7
0
    const filter = $tw.wiki.getCacheForTiddler(this.nodeFilterTRef, "tmap-nodeFilter", () => {

      let filter = utils.makeHashMap();
      const tObj = $tw.wiki.getTiddler(this.nodeFilterTRef);

      filter.raw = (tObj && tObj.fields.filter) || '';
      filter.pretty = utils.getPrettyFilter(filter.raw);
      filter.compiled = $tw.wiki.compileFilter(filter.raw);

      return filter;

    });
コード例 #8
0
  /**
   * @inheritDoc
   */
  constructor(allEdgeTypes, options) {

    super(allEdgeTypes, options);

    // later used for edge retrieval to identify those fields that hold connections
    this.edgeTypesByFieldName = utils.makeHashMap();

    for (let id in allEdgeTypes) {

      const edgeType = allEdgeTypes[id];
      if (this.canHandle(edgeType)) {
        this.edgeTypesByFieldName[edgeType.name] = edgeType;
      }
    }

  }
コード例 #9
0
ファイル: Adapter.js プロジェクト: felixhayashi/TW5-TiddlyMap
  /**
   * Returns a set of nodes that corresponds to a set of tiddlers.
   *
   * @param {TiddlerCollection} tiddlers - A collection of tiddlers.
   * @param {Hashmap} [addProperties] - a hashmap
   * @param {CollectionTypeString} [outputType='dataset'] - The result type.
   *
   * @return {NodeCollection} A collection of a type specified in the options.
   */
  selectNodesByReferences(tiddlers, { addProperties, outputType } = {}) {

    const result = utils.makeHashMap();
    const keys = Object.keys(tiddlers);

    for (let i = keys.length; i--;) {

      const node = this.makeNode(tiddlers[keys[i]], addProperties);
      if (node) {
        result[node.id] = node;
      }

    }

    return utils.convert(result, outputType);

  }
コード例 #10
0
ファイル: lib.adapter.js プロジェクト: EdDixon/TW5-TiddlyMap
Adapter.prototype.selectNodesByReferences = function(tiddlers, options) {

  options = options || {};

  var protoNode = options.addProperties;
  var result = utils.makeHashMap();
  var keys = Object.keys(tiddlers);
  
  for(var i = keys.length; i--;) {
    
    var node = this.makeNode(tiddlers[keys[i]], protoNode);
    if(node) { result[node.id] = node; }  // ATTENTION: edges may be obsolete
        
  }
    
  return utils.convert(result, options.outputType);
  
};
コード例 #11
0
  /**
   * @inheritDoc
   */
  getReferences(tObj, toWL, typeWL) {

    const refsGroupedByType = utils.makeHashMap();
    const fieldNames = tObj.fields;

    for (let fieldName in fieldNames) {


      const type = this.edgeTypesByFieldName[fieldName];

      if (!type || (typeWL && !typeWL[type.id])) continue;


      const toRefs = this.getReferencesFromField(tObj, fieldName, toWL);

      if (toRefs && toRefs.length) {
        refsGroupedByType[type.id] = toRefs;
      }

    }

    return refsGroupedByType;

  }
コード例 #12
0
ファイル: Adapter.js プロジェクト: felixhayashi/TW5-TiddlyMap
  /**
   * This function will return all neighbours of a graph denoted by
   * a set of tiddlers.
   *
   * @todo parts of this code may be outsourced into a function to
   * prevent repeating code.
   *
   * @param {Array<TiddlerReference>} matches - The original set that
   *     defines the starting point for the neighbourhood discovery
   * @param {Hashmap} [opts] - An optional options object.
   * @param {Hashmap} [opts.typeWL] - A whitelist lookup-table
   *    that restricts which edges are travelled to reach a neighbour.
   * @param {Hashmap} [opts.edges] - An initial set of edges that is
   *    used in the first step to reach immediate neighbours, if no
   *    set of edges is specified, all exsisting edges will be considered.
   * @param {number} [opts.steps] - An integer value that specifies
   *    the scope of the neighbourhood. A node is considered a neighbour
   *    if it can be reached within the given number of steps starting
   *    from original set of tiddlers returned by the node filter.
   * @param {Hashmap} [opts.addProperties] - a hashmap
   *     containing properties to be added to each node.
   *     For example:
   *     {
   *       group: 'g1',
   *       color: 'red'
   *     }
   * @return {Object} An object of the form:
   *     {
   *       nodes: { *all neighbouring nodes* },
   *       edges: { *all edges connected to neighbours* },
   *     }
   */
  getNeighbours(matches, opts = {}) {

    $tm.start('Get neighbours');

    const { addProperties, toWL, typeWL, steps } = opts;
    const { allETy } = this.indeces;

    // index of all tiddlers have already are been visited, either by
    // having been included in the original set, or by having been
    // recorded as neighbour during the discovery.
    const visited = utils.getArrayValuesAsHashmapKeys(matches);
    const view = ViewAbstraction.exists(opts.view) ? new ViewAbstraction(opts.view) : null;
    const allEdgesLeadingToNeighbours = utils.makeHashMap();
    const allNeighbours = utils.makeHashMap();
    const maxSteps = (parseInt(steps) > 0 ? steps : 1);
    const direction = (opts.direction || (view && view.getConfig('neighbourhood_directions')));
    const isWalkBoth = (!direction || direction === 'both');
    const isWalkIn = (isWalkBoth || direction === 'in');
    const isWalkOut = (isWalkBoth || direction === 'out');

    // in order to apply the node-filter also to neighbours we need to make it
    // include all tiddlers in the filter's source (e.g. a tiddler and a few neighbours)
    // and then apply the filter – which now has the chance to take away tiddlers
    // a few filters from the set
    const neighFilter = view && `[all[]] ${view.getNodeFilter('raw')}`;

    // adjacency receives whitelists through opts
    const adjList = this.getAdjacencyList('to', opts);

    const addAsNeighbour = (edge, role, neighboursOfThisStep) => {
      allEdgesLeadingToNeighbours[edge.id] = edge;
      const tRef = this.getTiddlerById(edge[role]);

      if (
        view
        && utils.isTrue($tm.config.sys.nodeFilterNeighbours)
        && !utils.isMatch(tRef, neighFilter)) {
        return;
      }

      if (!visited[tRef]) {
        visited[tRef] = true;
        const node = this.makeNode(tRef, addProperties);
        if (node) { // saveguard against obsolete edges or other problems
          // record node
          allNeighbours[node.id] = node;
          neighboursOfThisStep.push(tRef);
        }
      }
    };

    // needed later
    let step;

    // loop if still steps to be taken and we have a non-empty starting set
    for (step = 0; step < maxSteps && matches.length; step++) {

      // neighbours that are discovered in the current step;
      // starting off from the current set of matches;
      const neighboursOfThisStep = [];

      // loop over all nodes in the original set
      for (let i = matches.length; i--;) {

        if (utils.isSystemOrDraft(matches[i])) {
          // = this might happen if the user manually created edges
          // that link to a system/draft tiddler or if the original
          // set contained system/draft tiddlers.
          continue;
        }

        // get all outgoing edges
        // = edges originating from the starting set and point outwards
        const outgoing = this.getEdges(matches[i], toWL, typeWL);
        for (let id in outgoing) {

          const t = allETy[outgoing[id].type];
          if (isWalkBoth || isWalkOut && t.toArrow || isWalkIn && t.invertedArrow) {

            addAsNeighbour(outgoing[id], 'to', neighboursOfThisStep);
          }
        }

        // get all incoming edges
        // = edges originating from outside pointing to the starting set
        const incoming = adjList[this.getId(matches[i])];
        if (!incoming) {
          continue;
        }

        for (let j = incoming.length; j--;) {
          const t = allETy[incoming[j].type];
          if (isWalkBoth || isWalkIn && t.toArrow || isWalkOut && t.invertedArrow) {
            addAsNeighbour(incoming[j], 'from', neighboursOfThisStep);
          }
        }
      }

      // the current set of newly discovered neighbours forms the
      // starting point for the next discovery
      matches = neighboursOfThisStep;

    }

    const neighbourhood = {
      nodes: allNeighbours,
      edges: allEdgesLeadingToNeighbours
    };

    $tm.logger('debug', 'Retrieved neighbourhood', neighbourhood, 'steps', step);

    $tm.stop('Get neighbours');

    return neighbourhood;

  }
コード例 #13
0
ファイル: lib.adapter.js プロジェクト: EdDixon/TW5-TiddlyMap
Adapter.prototype.getNeighbours = function(matches, opts) {
  
  $tm.start("Get neighbours");
  
  opts = opts || {};
    
  // index of all tiddlers have already are been visited, either by
  // having been included in the original set, or by having been
  // recorded as neighbour during the discovery.
  var visited = utils.getArrayValuesAsHashmapKeys(matches); 
  var view = new ViewAbstraction(opts.view);
  var protoNode = opts.addProperties;
  var allEdgesLeadingToNeighbours = utils.makeHashMap();
  var allETy = $tm.indeces.allETy;
  var allNeighbours = utils.makeHashMap();
  var toWL = opts.toWL;
  var typeWL = opts.typeWL;
  var tById = $tm.indeces.tById;
  var idByT = $tm.indeces.idByT;
  var maxSteps = (parseInt(opts.steps) > 0 ? opts.steps : 1);
  var direction = (opts.direction
                   || (view.exists()
                       && view.getConfig("neighbourhood_directions")));
  var isWalkBoth = (!direction || direction === "both");
  var isWalkIn = (isWalkBoth || direction === "in");
  var isWalkOut = (isWalkBoth || direction === "out");
  
  // adjacency receives whitelists through opts
  var adjList = this.getAdjacencyList("to", opts);
  
  var addAsNeighbour = function(edge, role) {
    allEdgesLeadingToNeighbours[edge.id] = edge;
    var tRef = tById[edge[role]];
    if(!visited[tRef]) {
      visited[tRef] = true;
      var node = this.makeNode(tRef, protoNode);
      if(node) { // saveguard against obsolete edges or other problems  
        // record node
        allNeighbours[node.id] = node;
        neighboursOfThisStep.push(tRef);              
      }
    }
  }.bind(this);

  // loop if still steps to be taken and we have a non-empty starting set
  for(var step = 0; step < maxSteps && matches.length; step++) {
        
    // neighbours that are discovered in the current step;
    // starting off from the current set of matches;
    var neighboursOfThisStep = []; 
    
    // loop over all nodes in the original set
    for(var i = matches.length; i--;) {
      
      if(utils.isSystemOrDraft(matches[i])) {
        // = this might happen if the user manually created edges
        // that link to a system/draft tiddler or if the original
        // set contained system/draft tiddlers.
        continue;
      }
              
      // get all outgoing edges
      // = edges originating from the starting set and point outwards
      var outgoing = this.getEdges(matches[i], toWL, typeWL);
      for(var id in outgoing) {
        var t = allETy[outgoing[id].type];
        if(isWalkBoth || isWalkOut && t.toArrow || isWalkIn && t.invertedArrow) {
          addAsNeighbour(outgoing[id], "to");
        }
      }
      
      // get all incoming edges
      // = edges originating from outside pointing to the starting set
      var incoming = adjList[idByT[matches[i]]];
      if(!incoming) continue;
      
      for(var j = incoming.length; j--;) {
        var t = allETy[incoming[j].type];
        if(isWalkBoth || isWalkIn && t.toArrow || isWalkOut && t.invertedArrow) {
          addAsNeighbour(incoming[j], "from");
        }
      }
    }
    
    // the current set of newly discovered neighbours forms the
    // starting point for the next discovery
    matches = neighboursOfThisStep;
    
  }
  
  var neighbourhood = {
    nodes: allNeighbours,
    edges: allEdgesLeadingToNeighbours
  };
  
  $tm.logger("debug", "Retrieved neighbourhood", neighbourhood, "steps", step);
  
  $tm.stop("Get neighbours");
  
  return neighbourhood;
  
};
コード例 #14
0
ファイル: lib.adapter.js プロジェクト: EdDixon/TW5-TiddlyMap
"use strict";module.exports=Adapter;var ViewAbstraction=require("$:/plugins/felixhayashi/tiddlymap/js/ViewAbstraction");var EdgeType=require("$:/plugins/felixhayashi/tiddlymap/js/EdgeType");var NodeType=require("$:/plugins/felixhayashi/tiddlymap/js/NodeType");var utils=require("$:/plugins/felixhayashi/tiddlymap/js/utils");var vis=require("$:/plugins/felixhayashi/vis/vis.js");var getContrastColour=require("$:/core/modules/macros/contrastcolour.js").run;function Adapter(){this.visShapesWithTextInside=utils.getLookupTable(["ellipse","circle","database","box","text"]);this.isTransTypeEnabled=typeof $tw.wiki.getTiddlerTranscludes==="function"}Adapter.prototype.deleteEdge=function(e){return this._processEdge(e,"delete")};Adapter.prototype.deleteEdges=function(e){e=utils.convert(e,"array");for(var t=e.length;t--;){this.deleteEdge(e[t])}};Adapter.prototype.insertEdge=function(e){return this._processEdge(e,"insert")};Adapter.prototype._processEdge=function(e,t){$tm.logger("debug","Edge",t,e);if(typeof e!=="object"||!t||!e.from)return;if(t==="insert"&&!e.to)return;var i=$tm.indeces.tById[e.from];if(!i||!utils.tiddlerExists(i))return;var r=new EdgeType(e.type);var s=utils.getTiddler(i);var a=r.namespace;if(a==="tw-list"){if(!e.to)return;return this._processListEdge(s,e,r,t)}else if(a==="tw-field"){if(!e.to)return;return this._processFieldEdge(s,e,r,t)}else if(a==="tw-body"){return null}else{return this._processTmapEdge(s,e,r,t)}return e};Adapter.prototype._processTmapEdge=function(e,t,i,r){if(r==="delete"&&!t.id)return;var s=utils.parseFieldData(e,"tmap.edges",{});if(r==="insert"){t.id=t.id||utils.genUUID();s[t.id]={to:t.to,type:i.id};if(!i.exists()){i.save()}}else{delete s[t.id]}utils.writeFieldData(e,"tmap.edges",s);return t};Adapter.prototype._processListEdge=function(e,t,i,r){var s=i.name;var a=utils.getTiddler(e);var o=$tw.utils.parseStringArray(e.fields[s]);o=(o||[]).slice();var d=$tm.indeces.tById[t.to];if(r==="insert"){o.push(d);if(!i.exists()){i.save()}}else{var n=o.indexOf(d);if(n>-1){o.splice(n,1)}}utils.setField(a,s,$tw.utils.stringifyList(o));return t};Adapter.prototype._processFieldEdge=function(e,t,i,r){var s=$tm.indeces.tById[t.to];if(s==null)return;var a=r==="insert"?s:"";utils.setField(e,i.name,a);if(!i.exists()){i.save()}return t};Adapter.prototype.getAdjacencyList=function(e,t){$tm.start("Creating adjacency list");t=t||{};if(!t.edges){var i=utils.getMatches($tm.selector.allPotentialNodes);t.edges=this.getEdgesForSet(i,t.toWL,t.typeWL)}var r=utils.groupByProperty(t.edges,e||"to");$tm.stop("Creating adjacency list");return r};Adapter.prototype.getNeighbours=function(e,t){$tm.start("Get neighbours");t=t||{};var i=utils.getArrayValuesAsHashmapKeys(e);var r=new ViewAbstraction(t.view);var s=t.addProperties;var a=utils.makeHashMap();var o=$tm.indeces.allETy;var d=utils.makeHashMap();var n=t.toWL;var l=t.typeWL;var p=$tm.indeces.tById;var u=$tm.indeces.idByT;var f=parseInt(t.steps)>0?t.steps:1;var g=t.direction||r.exists()&&r.getConfig("neighbourhood_directions");var c=!g||g==="both";var v=c||g==="in";var y=c||g==="out";var h=this.getAdjacencyList("to",t);var m=function(e,t){a[e.id]=e;var r=p[e[t]];if(!i[r]){i[r]=true;var o=this.makeNode(r,s);if(o){d[o.id]=o;A.push(r)}}}.bind(this);for(var w=0;w<f&&e.length;w++){var A=[];for(var b=e.length;b--;){if(utils.isSystemOrDraft(e[b])){continue}var T=this.getEdges(e[b],n,l);for(var $ in T){var E=o[T[$].type];if(c||y&&E.toArrow||v&&E.invertedArrow){m(T[$],"to")}}var N=h[u[e[b]]];if(!N)continue;for(var x=N.length;x--;){var E=o[N[x].type];if(c||v&&E.toArrow||y&&E.invertedArrow){m(N[x],"from")}}}e=A}var k={nodes:d,edges:a};$tm.logger("debug","Retrieved neighbourhood",k,"steps",w);$tm.stop("Get neighbours");return k};Adapter.prototype.getGraph=function(e){$tm.start("Assembling Graph");e=e||{};var t=new ViewAbstraction(e.view);var i=utils.getMatches(e.filter||t.exists()&&t.getNodeFilter("compiled"));var r=utils.getArrayValuesAsHashmapKeys(i);var s=e.edgeTypeWL||t.exists()&&t.getEdgeTypeFilter("whitelist");var a=parseInt(e.neighbourhoodScope||t.exists()&&t.getConfig("neighbourhood_scope"));var o={edges:this.getEdgesForSet(i,r,s),nodes:this.selectNodesByReferences(i,{view:t,outputType:"hashmap"})};if(a){var d=this.getNeighbours(i,{steps:a,view:t,typeWL:s,addProperties:{group:"tmap:neighbour"}});utils.merge(o,d);if(t.exists()&&t.isEnabled("show_inter_neighbour_edges")){var n=this.getTiddlersById(d.nodes);var r=utils.getArrayValuesAsHashmapKeys(n);$tw.utils.extend(o.edges,this.getEdgesForSet(n,r))}}this._removeObsoleteViewData(o.nodes,t);this.attachStylesToNodes(o.nodes,t);$tm.stop("Assembling Graph");$tm.logger("debug","Assembled graph:",o);return o};Adapter.prototype.getEdges=function(e,t,i){var r=utils.getTiddler(e);if(!r||utils.isSystemOrDraft(r))return;var s=utils.makeHashMap();this._addTmapEdges(s,r,t,i);this._addBodyAndFieldEdges(s,r,t,i);return s};Adapter.prototype._addBodyAndFieldEdges=function(e,t,i,r){var s=t.fields;var a=utils.getTiddlerRef(t);var o=$tm.indeces;var d=o.maETyFiNa;var n=utils.makeHashMap();if(!r||r["tw-body:link"]){n["tw-body:link"]=$tw.wiki.getTiddlerLinks(a)}if(this.isTransTypeEnabled&&(!r||r["tw-body:transclude"])){n["tw-body:transclude"]=$tw.wiki.getTiddlerTranscludes(a)}for(var l in s){var p=d[l];if(!p||r&&!r[p.id])continue;if(p.namespace==="tw-field"){n[p.id]=[s[l]]}else if(p.namespace==="tw-list"){n[p.id]=$tw.utils.parseStringArray(s[l])}else if(p.namespace==="tw-filter"){var u=s[l];n[p.id]=utils.getMatches(u,i)}}if(!n)return;var f=t.fields["tmap.id"];var g=o.idByT;var c=o.allETy;for(var v in n){var y=n[v];if(!y)continue;var p=c[v];for(var h=y.length;h--;){var m=y[h];if(!m||!$tw.wiki.tiddlerExists(m)||utils.isSystemOrDraft(m)||i&&!i[m])continue;var w=p.id+$tw.utils.hashString(a+m);var A=this.makeEdge(f,g[m],p,w);if(A){e[A.id]=A}}}};Adapter.prototype._addTmapEdges=function(e,t,i,r){var s=utils.parseFieldData(t,"tmap.edges");if(!s)return;var a=$tm.indeces.tById;var o=t.fields["tmap.id"];for(var d in s){var n=s[d];var l=a[n.to];if(l&&(!i||i[l])&&(!r||r[n.type])){var p=this.makeEdge(o,n.to,n.type,d);if(p){e[d]=p}}}};Adapter.prototype.getEdgesForSet=function(e,t,i){var r=utils.makeHashMap();for(var s=e.length;s--;){$tw.utils.extend(r,this.getEdges(e[s],t,i))}return r};Adapter.prototype.selectEdgesByType=function(e){var t=utils.makeHashMap();t[new EdgeType(e).id]=true;return this.getEdgesForSet(this.getAllPotentialNodes(),null,t)};Adapter.prototype.getAllPotentialNodes=function(){return utils.getMatches($tm.selector.allPotentialNodes)};Adapter.prototype._processEdgesWithType=function(e,t){e=new EdgeType(e);$tm.logger("debug","Processing edges",e,t);var i=this.selectEdgesByType(e);if(t.action==="rename"){var r=new EdgeType(t.newName);r.load(e);r.save()}for(var s in i){this._processEdge(i[s],"delete");if(t.action==="rename"){i[s].type=t.newName;this._processEdge(i[s],"insert")}}$tw.wiki.deleteTiddler(e.fullPath)};Adapter.prototype.selectNodesByFilter=function(e,t){var i=utils.getMatches(e);return this.selectNodesByReferences(i,t)};Adapter.prototype.selectNodesByReferences=function(e,t){t=t||{};var i=t.addProperties;var r=utils.makeHashMap();var s=Object.keys(e);for(var a=s.length;a--;){var o=this.makeNode(e[s[a]],i);if(o){r[o.id]=o}}return utils.convert(r,t.outputType)};Adapter.prototype.selectNodesByIds=function(e,t){var i=this.getTiddlersById(e);return this.selectNodesByReferences(i,t)};Adapter.prototype.selectNodeById=function(e,t){t=utils.merge(t,{outputType:"hashmap"});var i=this.selectNodesByIds([e],t);return i[e]};Adapter.prototype.makeEdge=function(e,t,i,r){if(!e||!t)return;if(e instanceof $tw.Tiddler){e=e.fields["tmap.id"]}else if(typeof e==="object"){e=e.id}i=$tm.indeces.allETy[i]||new EdgeType(i);var s=i.getLabel();var a={id:r||utils.genUUID(),from:e,to:t,type:i.id};if(utils.isTrue(i["show-label"],true)){a.label=s}a=$tw.utils.extend(a,i.style);return a};Adapter.prototype.removeNodeType=function(e){var e=new NodeType(e);$tw.wiki.deleteTiddler(e.fullPath)};Adapter.prototype.makeNode=function(e,t){var i=utils.getTiddler(e);if(!i||utils.isSystemOrDraft(i))return;var r=utils.merge({},t);r.id=this.assignId(i);var s=i.fields[$tm.field.nodeLabel];r.label=s&&$tm.field.nodeLabel!=="title"?$tw.wiki.renderText("text/plain","text/vnd-tiddlywiki",s):i.fields.title;return r};Adapter.prototype.getInheritedNodeStyles=function(e){var t=this.getTiddlersById(e);var i={};var r=$tm.indeces.glNTy;for(var s=r.length;s--;){var a=r[s];if(a.id==="tmap:neighbour"){var o=$tm.indeces.tById;var d=[];for(var n in e){if(e[n].group==="tmap:neighbour"){d.push(o[n])}}}else{var d=a.getInheritors(t)}for(var l=d.length;l--;){var p=d[l];var u=i[p]=i[p]||{};u.style=utils.merge(u.style||{},a.style);if(a["fa-icon"]){u["fa-icon"]=a["fa-icon"]}else if(a["tw-icon"]){u["tw-icon"]=a["tw-icon"]}}}return i};Adapter.prototype.attachStylesToEdges=function(e,t){};Adapter.prototype._removeObsoleteViewData=function(e,t){t=new ViewAbstraction(t);if(!t.exists()||!e)return;var i=t.getNodeData();var r=0;for(var s in i){if(e[s]===undefined&&i[s]!=null){i[s]=undefined;r++}}if(r){$tm.logger("debug","[Cleanup]","Removed obsolete node data:",t.getLabel(),r);t.saveNodeData(i)}};Adapter.prototype.attachStylesToNodes=function(e,t){t=new ViewAbstraction(t);var i=this.getInheritedNodeStyles(e);var r=t.exists()?t.getNodeData():utils.makeHashMap();var s=t.exists()&&!t.isEnabled("physics_mode");var a=$tm.field.nodeIcon;var o=$tm.indeces.tById;for(var d in e){var n=o[d];var l=$tw.wiki.getTiddler(n);var p=l.fields;var u=e[d];var f=null;var g=null;if(i[n]){if(i[n].style){utils.merge(u,i[n].style)}f=i[n]["fa-icon"];g=i[n]["tw-icon"]}if(p.color){u.color=p.color}if(p["tmap.style"]){utils.merge(u,utils.parseJSON(p["tmap.style"]))}f=p["tmap.fa-icon"]||f;g=p["icon"]||g;if(r[d]){utils.merge(u,r[d]);if(s){u.fixed={x:u.x!=null,y:u.y!=null}}f=r[d]["fa-icon"]||f;g=r[d]["tw-icon"]||g}var c=u.color!==null&&typeof u.color==="object";var v=c?u.color.background:u.color;u.color={background:v,border:c?u.color.border:undefined};this._addNodeIcon(u,f,g);u.font=u.font||{};if(u.shape&&!this.visShapesWithTextInside[u.shape]){u.font.color="black"}else if(!u.font.color&&v){u.font.color=getContrastColour(v,v,"black","white")}if(u.shape==="icon"&&typeof u.icon==="object"){u.icon.color=v}}};Adapter.prototype.deleteNode=function(e){if(!e)return;var t=typeof e==="object"?e.id:e;var i=$tm.indeces.tById[t];if(i){utils.deleteTiddlers([i])}var r=utils.getMatches($tm.selector.allViews);for(var s=r.length;s--;){var a=new ViewAbstraction(r[s]);a.removeNode(t);if(a.getNodeData(t)){a.saveNodeData(t,null)}}var o=this.getNeighbours([i]);this.deleteEdges(o.edges)};Adapter.prototype.deleteNodes=function(e){e=utils.convert(e,"array");for(var t=e.length;t--;){this.deleteNode(e[t])}};Adapter.prototype.storePositions=function(e,t){t=new ViewAbstraction(t);if(!t.exists())return;t.saveNodeData(e)};Adapter.prototype.assignId=function(e,t){var i=utils.getTiddler(e,true);if(!i)return;var r=i.fields["tmap.id"];if(!r||t){r=utils.genUUID();utils.setField(i,"tmap.id",r);$tm.logger("info","Assigning new id to",i.fields.title)}$tm.indeces.tById[r]=i.fields.title;$tm.indeces.idByT[i.fields.title]=r;return r};Adapter.prototype.insertNode=function(e,t,i){i=i||{};e=e||{};var r={"tmap.id":null};if(!i.fields||!i.fields.text){r.text=""}var s=$tw.wiki.generateNewTitle(e.label||utils.getRandomLabel());e.label=r.title=s;var a=new $tw.Tiddler(i.fields,r,$tw.wiki.getModificationFields(),$tw.wiki.getCreationFields());$tw.wiki.addTiddler(a);e=this.makeNode(a,e);var t=new ViewAbstraction(t);if(t.exists()){t.addNode(e)}return e};Adapter.prototype._getFAdigits=function(e){return e.length===4?e:e.substr(3,4)};Adapter.prototype.getTiddlersById=function(e){if(Array.isArray(e)){e=utils.getArrayValuesAsHashmapKeys(e)}else if(e instanceof vis.DataSet){e=utils.getLookupTable(e,"id")}var t=[];var i=$tm.indeces.tById;for(var r in e){if(i[r])t.push(i[r])}return t};Adapter.prototype.getId=function(e){return $tm.indeces.idByT[utils.getTiddlerRef(e)]};Adapter.prototype._addNodeIcon=function(e,t,i){if(t){e.shape="icon";e.icon={shape:"icon",face:"FontAwesome",color:e.color,code:String.fromCharCode("0x"+this._getFAdigits(t))};return}if(!i)return;var r=utils.getTiddler(i);if(!r)return;if(r.fields["_canonical_uri"]){e.image=r.fields["_canonical_uri"];e.shape="image";return}if(r.fields.text){e.image=utils.getDataUri(r);e.shape="image";return}};
コード例 #15
0
ファイル: lib.adapter.js プロジェクト: EdDixon/TW5-TiddlyMap
Adapter.prototype.attachStylesToNodes = function(nodes, view) {
  
  view = new ViewAbstraction(view);
  
  var inheritedStyles = this.getInheritedNodeStyles(nodes);

  var viewNodeData = view.exists() ? view.getNodeData() : utils.makeHashMap();
  var isStaticMode = view.exists() && !view.isEnabled("physics_mode");

  
  // shortcuts (for performance and readability)
  var nodeIconField = $tm.field.nodeIcon;
  var tById = $tm.indeces.tById;
  
  for(var id in nodes) {
    var tRef = tById[id];
    var tObj = $tw.wiki.getTiddler(tRef);
    var fields = tObj.fields;
    var node = nodes[id];
    var faIcon = null;
    var twIcon = null;
        
    // == group styles ==
    
    // will add local and global group styles
    if(inheritedStyles[tRef]) {
      
      if(inheritedStyles[tRef].style) {
        utils.merge(node, inheritedStyles[tRef].style);
      }
      faIcon = inheritedStyles[tRef]["fa-icon"];
      twIcon = inheritedStyles[tRef]["tw-icon"];
    }
        
    // == global node styles ==
         
    // background color
    if(fields.color) { node.color = fields.color }
        
    // global node style from vis editor
    if(fields["tmap.style"]) {
      utils.merge(node, utils.parseJSON(fields["tmap.style"]));
    }
    
    faIcon = fields["tmap.fa-icon"] || faIcon;
    twIcon = fields["icon"] || twIcon;
        
    // == local node styles ==
    
    // local node style and positions
    if(viewNodeData[id]) {
      utils.merge(node, viewNodeData[id]);
      if(isStaticMode) {
        // fix x if x-position is set; same for y
        node.fixed = {
          x: (node.x != null),
          y: (node.y != null)
        };
      }
      faIcon = viewNodeData[id]["fa-icon"] || faIcon;
      twIcon = viewNodeData[id]["tw-icon"] || twIcon;
    }
  
    // == tweaks ==
        
    var isColorObject = (node.color !== null
                         && typeof node.color === "object");
    // color/border-color may be undefined
    var color = (isColorObject ? node.color.background : node.color);

    node.color = {
      background: color,
      border: (isColorObject ? node.color.border : undefined)
    };
    
    // ATTENTION: this function needs to be called after color is assigned
    this._addNodeIcon(node, faIcon, twIcon);
  
    // determine font color if not defined via a group- or node-style;
    // in case of global and local default styles, the user is responsible
    // him- or herself to adjust the font
    node.font = node.font || {};
    
    if(node.shape && !this.visShapesWithTextInside[node.shape]) {
      node.font.color = "black"; // force a black color
    } else if(!node.font.color && color) {
      node.font.color = getContrastColour(color, color, "black", "white");
    }
    
    if(node.shape === "icon" && typeof node.icon === "object") {
      node.icon.color = color;
    }
    
  }
  
};
コード例 #16
0
ファイル: lib.adapter.js プロジェクト: EdDixon/TW5-TiddlyMap
Adapter.prototype._addBodyAndFieldEdges = function(edges, tObj, toWL, typeWL) {

  // never assign a default to the typeWL. if it is not assigned it means
  // all types!! NEVER: typeWL = typeWL || utils.makeHashMap();
    
  var fromTObjFields = tObj.fields;
  var fromTRef = utils.getTiddlerRef(tObj);
  var indeces = $tm.indeces;
  var maETyFiNa = indeces.maETyFiNa; // magic edge-type field names
  var refsByType = utils.makeHashMap();
  
  // 1) Prepare
  
  if(!typeWL || typeWL["tw-body:link"]) {
    refsByType["tw-body:link"] = $tw.wiki.getTiddlerLinks(fromTRef);
  }
  
  // hack to support
  // https://github.com/felixhayashi/TW5-TiddlyMap/issues/198
  if(this.isTransTypeEnabled && (!typeWL || typeWL["tw-body:transclude"])) {
    refsByType["tw-body:transclude"] = $tw.wiki.getTiddlerTranscludes(fromTRef);
  }

  for(var f in fromTObjFields) {
    
    var type = maETyFiNa[f];
      
    if(!type || (typeWL && !typeWL[type.id])) continue;
    
    if(type.namespace === "tw-field") {
      refsByType[type.id] = [ fromTObjFields[f] ];
    } else if(type.namespace === "tw-list") {
      refsByType[type.id] = $tw.utils.parseStringArray(fromTObjFields[f]);
    } else if(type.namespace === "tw-filter") {
      var filter = fromTObjFields[f];
      refsByType[type.id] = utils.getMatches(filter, toWL);
    }
  }
  
  if(!refsByType) return;
    
  // 2) Add edges to list
  
  var fromId = tObj.fields["tmap.id"];
  var idByT = indeces.idByT;
  var allETy = indeces.allETy;
  
  for(var typeId in refsByType) {
    var toRefs = refsByType[typeId];
    
    if(!toRefs) continue;
    
    var type = allETy[typeId];
    for(var i = toRefs.length; i--;) {
      var toTRef = toRefs[i];
      
      if(!toTRef
         || !$tw.wiki.tiddlerExists(toTRef)
         || utils.isSystemOrDraft(toTRef)
         || (toWL && !toWL[toTRef])) continue;

      var id = type.id + $tw.utils.hashString(fromTRef + toTRef); 
      var edge = this.makeEdge(fromId, idByT[toTRef], type, id);

      if(edge) {
        edges[edge.id] = edge;
      }
    }
  }
  
};
コード例 #17
0
ファイル: Adapter.js プロジェクト: felixhayashi/TW5-TiddlyMap
  /**
   * Adds styles to nodes.
   *
   * @param {Object<string, Node>} nodes
   * @param {ViewAbstraction|string} view
   */
  attachStylesToNodes(nodes, view) {

    view = ViewAbstraction.exists(view) ? new ViewAbstraction(view) : null;

    const inheritedStyles = this.getInheritedNodeStyles(nodes);
    const viewNodeData = view ? view.getNodeData() : utils.makeHashMap();
    const isStaticMode = view && !view.isEnabled('physics_mode');

    for (let id in nodes) {

      const tRef = this.getTiddlerById(id);
      const tObj = this.wiki.getTiddler(tRef);
      const fields = tObj.fields;
      const node = nodes[id];
      let icon;

      // == group styles ==

      const inheritedStyle = inheritedStyles[tRef];

      if (inheritedStyle) {

        utils.merge(node, inheritedStyle.style);
        icon = getIcon(inheritedStyle['fa-icon'], inheritedStyle['tw-icon']);
      }

      // == global node styles ==

      // background color
      if (fields.color) {
        node.color = fields.color;
      }

      // global node style from vis editor
      if (fields['tmap.style']) {
        utils.merge(node, utils.parseJSON(fields['tmap.style']));
      }

      icon = getIcon(fields['tmap.fa-icon'], fields['icon']) || icon;

      // == local node styles ==

      // local node style and positions

      const nodeData = viewNodeData[id];

      if (nodeData) {

        utils.merge(node, nodeData);
        if (isStaticMode) {
          // fix x if x-position is set; same for y
          node.fixed = {
            x: (node.x != null),
            y: (node.y != null)
          };
        }

        icon = getIcon(nodeData['fa-icon'], nodeData['tw-icon']) || icon;
      }

      // == tweaks ==

      const isColorObject = (node.color !== null && typeof node.color === 'object');
      // color/border-color may be undefined
      const color = (isColorObject ? node.color.background : node.color);

      node.color = {
        background: color,
        border: (isColorObject ? node.color.border : undefined)
      };

      // ATTENTION: this function needs to be called after color is assigned
      addNodeIcon(node, icon);

      // determine font color if not defined via a group- or node-style;
      // in case of global and local default styles, the user is responsible
      // him- or herself to adjust the font
      node.font = node.font || {};

      if (node.shape && !this.visShapesWithTextInside[node.shape]) {
        node.font.color = 'black'; // force a black color
      } else if (!node.font.color && color) {
        node.font.color = getContrastColour(color, color, 'black', 'white');
      }

      if (node.shape === 'icon' && typeof node.icon === 'object') {
        node.icon.color = color;
      }

    }

    if (view) {
      const node = nodes[view.getConfig('central-topic')];
      if (node) {
        utils.merge(node, this.indeces.glNTyById['tmap:central-topic'].style);
      }
    }

  }
コード例 #18
0
ファイル: widget.map.js プロジェクト: EdDixon/TW5-TiddlyMap
"use strict";exports.tiddlymap=MapWidget;exports.tmap=MapWidget;var utils=require("$:/plugins/felixhayashi/tiddlymap/js/utils");var DialogManager=require("$:/plugins/felixhayashi/tiddlymap/js/DialogManager");var CallbackManager=require("$:/plugins/felixhayashi/tiddlymap/js/CallbackManager");var ViewAbstraction=require("$:/plugins/felixhayashi/tiddlymap/js/ViewAbstraction");var EdgeType=require("$:/plugins/felixhayashi/tiddlymap/js/EdgeType");var NodeType=require("$:/plugins/felixhayashi/tiddlymap/js/NodeType");var Popup=require("$:/plugins/felixhayashi/tiddlymap/js/Popup");var vis=require("$:/plugins/felixhayashi/vis/vis.js");var Widget=require("$:/core/modules/widgets/widget.js").widget;function MapWidget(e,t){Widget.call(this,e,t);this.getAttr=this.getAttribute;this.isDebug=utils.isTrue($tm.config.sys.debug,false);utils.bind(this,["constructTooltip","handleResizeEvent","handleClickEvent","handleCanvasKeyup","handleCanvasKeydown","handleCanvasScroll","handleWidgetKeyup","handleWidgetKeydown","handleTriggeredRefresh"]);this.callbackManager=new CallbackManager;this.dialogManager=new DialogManager(this.callbackManager,this);this.computeAttributes();this.editorMode=this.getAttr("editor");this.clickToUse=utils.isTrue(this.getAttr("click-to-use"),false);this.id=this.getAttr("object-id")||this.getStateQualifier();this.widgetTempStatePath=$tm.path.tempStates+"/"+this.id;this.widgetPopupsPath=$tm.path.tempPopups+"/"+this.id;if(this.editorMode){utils.addTWlisteners({"tmap:tm-create-view":this.handleCreateView,"tmap:tm-rename-view":this.handleRenameView,"tmap:tm-delete-view":this.handleDeleteView,"tmap:tm-edit-view":this.handleEditView,"tmap:tm-store-position":this.handleStorePositions,"tmap:tm-generate-widget":this.handleGenerateWidget,"tmap:tm-save-canvas":this.handleSaveCanvas},this,this)}utils.addTWlisteners({"tmap:tm-focus-node":this.handleFocusNode,"tmap:tm-reset-focus":this.repaintGraph},this,this);this.visListeners={click:this.handleVisSingleClickEvent,doubleClick:this.handleVisDoubleClickEvent,stabilized:this.handleVisStabilizedEvent,selectNode:this.handleVisSelectNode,deselectNode:this.handleVisDeselectNode,dragStart:this.handleVisDragStart,dragEnd:this.handleVisDragEnd,hoverNode:this.handleVisHoverElement,hoverEdge:this.handleVisHoverElement,blurNode:this.handleVisBlurElement,blurEdge:this.handleVisBlurElement,oncontext:this.handleVisOnContext,beforeDrawing:this.handleVisBeforeDrawing,stabilizationProgress:this.handleVisLoading,stabilizationIterationsDone:this.handleVisLoadingDone};this.windowDomListeners={resize:[this.handleResizeEvent,false],click:[this.handleClickEvent,false]};this.canvasDomListeners={keyup:[this.handleCanvasKeyup,true],keydown:[this.handleCanvasKeydown,true],mousewheel:[this.handleCanvasScroll,true]};this.widgetDomListeners={keyup:[this.handleWidgetKeyup,true],keydown:[this.handleWidgetKeydown,true]}}MapWidget.prototype=Object.create(Widget.prototype);MapWidget.prototype.handleConnectionEvent=function(e,t){var i=this.view.getEdgeTypeFilter();var s={fromLabel:$tm.adapter.selectNodeById(e.from).label,toLabel:$tm.adapter.selectNodeById(e.to).label,viewNS:this.view.getConfig("edge_type_namespace"),eTyFilter:i.raw};var a="getEdgeType";this.dialogManager.open(a,s,function(s,a){if(s){var r=utils.getText(a);var o={namespace:this.view.getConfig("edge_type_namespace")};var r=new EdgeType(r,null,o);if(!r.exists())r.save();e.type=r.id;$tm.adapter.insertEdge(e);if(!this.view.isEdgeTypeVisible(r.id)){var n={type:r.id,view:this.view.getLabel(),eTyFilter:i.pretty};this.dialogManager.open("edgeNotVisible",n)}this.preventFitAfterRebuild=true}if(typeof t==="function"){t(s)}})};MapWidget.prototype.checkForFreshInstall=function(){var e=$tm.ref.sysMeta;if(!utils.getEntry(e,"showWelcomeMessage",true))return;utils.setEntry(e,"showWelcomeMessage",false);var t={};var i="welcome";this.dialogManager.open(i,t,function(e,t){if(utils.tiddlerExists("$:/plugins/felixhayashi/topstoryview")){utils.setText("$:/view","top");utils.setText("$:/config/Navigation/openLinkFromInsideRiver","above");utils.setText("$:/config/Navigation/openLinkFromOutsideRiver","top");utils.touch("$:/plugins/felixhayashi/topstoryview")}var i=$tm.misc.defaultViewLabel;var s={label:"Have fun with",x:0,y:0};var a=$tm.adapter.insertNode(s,i);var s={label:"TiddlyMap!!",x:100,y:100};var r=$tm.adapter.insertNode(s,i);$tm.adapter.insertEdge({from:a.id,to:r.id})})};MapWidget.prototype.openStandardConfirmDialog=function(e,t){var i={message:t};this.dialogManager.open("getConfirmation",i,e)};MapWidget.prototype.logger=function(e,t){if(this.isDebug){var i=Array.prototype.slice.call(arguments,1);i.unshift("@"+this.id);i.unshift(e);$tm.logger.apply(this,i)}};MapWidget.prototype.render=function(e,t){this.parentDomNode=e;this.domNode=this.document.createElement("div");e.insertBefore(this.domNode,t);this.registerClassNames(this.domNode);this.viewHolderRef=this.getViewHolderRef();this.view=this.getView();this.graphBarDomNode=this.document.createElement("div");$tw.utils.addClass(this.graphBarDomNode,"tmap-topbar");this.domNode.appendChild(this.graphBarDomNode);this.graphDomNode=this.document.createElement("div");this.domNode.appendChild(this.graphDomNode);$tw.utils.addClass(this.graphDomNode,"tmap-vis-graph");if(utils.isPreviewed(this)||this.domNode.isTiddlyWikiFakeDom){$tw.utils.addClass(this.domNode,"tmap-static-mode");this.renderPreview(this.graphBarDomNode,this.graphDomNode)}else{this.renderFullWidget(this.domNode,this.graphBarDomNode,this.graphDomNode)}};MapWidget.prototype.renderPreview=function(e,t){var i=this.view.getRoot()+"/snapshot";var s=utils.getTiddler(i);var a=this.document.createElement("span");a.innerHTML=this.view.getLabel();a.className="tmap-view-label";e.appendChild(a);if(s){var r=this.makeChildWidget({type:"transclude",attributes:{tiddler:{type:"string",value:i}}});r.renderChildren(t,null)}else{$tw.utils.addClass(t,"tmap-graph-placeholder")}};MapWidget.prototype.renderFullWidget=function(e,t,i){utils.setDomListeners("add",window,this.windowDomListeners);utils.setDomListeners("add",e,this.widgetDomListeners);this.addLoadingBar(this.domNode);var s={showDelay:$tm.config.sys.popups.delay};this.visTooltip=new Popup(this.domNode,s);this.sidebar=utils.getFirstElementByClassName("tc-sidebar-scrollable");this.isInSidebar=this.sidebar&&!this.domNode.isTiddlyWikiFakeDom&&this.sidebar.contains(this.domNode);this.doFitAfterStabilize=true;this.preventFitAfterRebuild=false;this.initAndRenderEditorBar(t);this.initAndRenderGraph(i);$tm.registry.push(this);this.reloadRefreshTriggers();this.checkForFreshInstall();if(this.id===$tm.misc.mainEditorId){var a=$tm.url;if(a&&a.query["tmap-enlarged"]){this.toggleEnlargedMode(a.query["tmap-enlarged"])}}};MapWidget.prototype.registerClassNames=function(e){var t=$tw.utils.addClass;t(e,"tmap-widget");if(this.clickToUse){t(e,"tmap-click-to-use")}if(this.getAttr("editor")==="advanced"){t(e,"tmap-advanced-editor")}if(this.getAttr("design")==="plain"){t(e,"tmap-plain-design")}if(!utils.isTrue(this.getAttr("show-buttons"),true)){t(e,"tmap-no-buttons")}if(this.getAttr("class")){t(e,this.getAttr("class"))}};MapWidget.prototype.addLoadingBar=function(e){this.graphLoadingBarDomNode=this.document.createElement("progress");$tw.utils.addClass(this.graphLoadingBarDomNode,"tmap-loading-bar");e.appendChild(this.graphLoadingBarDomNode)};MapWidget.prototype.initAndRenderEditorBar=function(e){this.rebuildEditorBar()};MapWidget.prototype.rebuildEditorBar=function(){var e=this.view;var t={widgetQualifier:this.getStateQualifier(),widgetTempPath:this.widgetTempPath,widgetPopupsPath:this.widgetPopupsPath,isViewBound:String(this.isViewBound()),viewRoot:e.getRoot(),viewLabel:e.getLabel(),viewHolder:this.getViewHolderRef(),edgeTypeFilter:e.getPaths().edgeTypeFilter,allEdgesFilter:$tm.selector.allEdgeTypes,neighScopeBtnClass:"tmap-neigh-scope-button"+(e.isEnabled("neighbourhood_scope")?" "+"tmap-active-button":"")};for(var i in t){this.setVariable(i,t[i])}var s={type:"tiddler",attributes:{tiddler:{type:"string",value:e.getRoot()}},children:[]};if(this.editorMode==="advanced"){s.children.push({type:"transclude",attributes:{tiddler:{type:"string",value:$tm.ref.graphBar}}})}else{s.children.push({type:"element",tag:"span",attributes:{"class":{type:"string",value:"tmap-view-label"}},children:[{type:"text",text:e.getLabel()}]})}s.children.push({type:"transclude",attributes:{tiddler:{type:"string",value:$tm.ref.focusButton}}});this.makeChildWidgets([s]);this.renderChildren(this.graphBarDomNode,this.graphBarDomNode.firstChild)};MapWidget.prototype.refresh=function(e){return false};MapWidget.prototype.update=function(e){if(!this.network||this.isZombieWidget()||utils.isPreviewed(this)){return}var t=e.changedTiddlers;var i=false;var s=false;var a=false;var r={};this.callbackManager.handleChanges(t);if(this.isViewSwitched(t)||this.hasChangedAttributes()||e[$tm.path.options]||e[$tm.path.nodeTypes]||t[this.view.getRoot()]){this.logger("warn","View switched (or main config change)");this.view=this.getView(true);this.reloadRefreshTriggers();i=true;a=true}else{var o=this.view.update(e);if(o&&!this.ignoreNextViewModification){this.logger("warn","View components modified");this.reloadBackgroundImage();i=true;s=true;r.resetEdgeTypeWL=true;if(!this.preventFitAfterRebuild){r.resetFocus={delay:0,duration:0}}}else{if(e[$tm.path.nodeTypes]){s=true}else if(this.hasChangedElements(t)){s=true}}}if(a){this.initAndRenderGraph(this.graphDomNode);this.visTooltip.hide(0,true)}else if(s){this.rebuildGraph(r);this.visTooltip.hide(0,true)}if(i){this.removeChildDomNodes();this.rebuildEditorBar()}else{this.refreshChildren(t)}this.ignoreNextViewModification=false};MapWidget.prototype.reloadRefreshTriggers=function(){this.callbackManager.remove(this.refreshTriggers);var e=this.getAttr("refresh-triggers")||this.view.getConfig("refresh-triggers");this.refreshTriggers=$tw.utils.parseStringArray(e)||[];this.logger("debug","Registering refresh trigger",this.refreshTriggers);for(var t=this.refreshTriggers.length;t--;){this.callbackManager.add(this.refreshTriggers[t],this.handleTriggeredRefresh,false)}};MapWidget.prototype.rebuildGraph=function(e){if(utils.isPreviewed(this))return;this.logger("debug","Rebuilding graph");e=e||{};this.hasNetworkStabilized=false;if(e.resetData){this.graphData.edges.clear();this.graphData.nodes.clear();this.graphData.edgesById=null;this.graphData.nodesById=null}if(!this.view.isEnabled("physics_mode")){var t=this.visOptions.physics;t[t.solver].centralGravity=.015}if(!e.resetFocus){this.doFitAfterStabilize=false}this.rebuildGraphData();if(!utils.hasElements(this.graphData.nodesById)){return}this.network.stabilize();if(e.resetFocus&&!this.preventFitAfterRebuild){this.doFitAfterStabilize=true;this.fitGraph(e.resetFocus.delay,e.resetFocus.duration)}this.preventFitAfterRebuild=false};MapWidget.prototype.getContainer=function(){return this.domNode};MapWidget.prototype.rebuildGraphData=function(e){$tm.start("Reloading Network");e=e||{};var t=$tm.adapter.getGraph({view:this.view});var i=t.nodes;var s=t.edges;this.graphData.nodes=this.getRefreshedDataSet(i,this.graphData.nodesById,this.graphData.nodes);this.graphData.edges=this.getRefreshedDataSet(s,this.graphData.edgesById,this.graphData.edges);this.graphData.nodesById=i;this.graphData.edgesById=s;utils.setField("$:/temp/tmap/nodes/"+this.view.getLabel(),"list",$tm.adapter.getTiddlersById(i));$tm.stop("Reloading Network");return this.graphData};MapWidget.prototype.isViewBound=function(){return utils.startsWith(this.getViewHolderRef(),$tm.path.localHolders)};MapWidget.prototype.isViewSwitched=function(e){return e[this.getViewHolderRef()]};MapWidget.prototype.hasChangedAttributes=function(){return Object.keys(this.computeAttributes()).length};MapWidget.prototype.hasChangedElements=function(e){var t=[];var i=this.graphData.nodesById;var s=this.view.isEnabled("neighbourhood_scope");var a=this.view.getEdgeTypeFilter("whitelist");for(var r in e){if(utils.isSystemOrDraft(r))continue;if(i[$tm.adapter.getId(r)]||s){return true}if(e[r].modified){t.push(r)}}if(t.length){var o=this.view.getNodeFilter("compiled");var n=utils.getMatches(o,t);return!!n.length}};MapWidget.prototype.initAndRenderGraph=function(e){if(this.network)this._destructVis();this.logger("info","Initializing and rendering the graph");if(!this.isInSidebar){this.callbackManager.add("$:/state/sidebar",this.handleResizeEvent)}this.visOptions=this.getVisOptions();this.graphData={nodes:new vis.DataSet,edges:new vis.DataSet,nodesById:utils.makeHashMap(),edgesById:utils.makeHashMap()};this.visTooltip.setEnabled(utils.isTrue($tm.config.sys.popups.enabled,true));this.network=new vis.Network(e,this.graphData,this.visOptions);this.canvas=e.getElementsByTagName("canvas")[0];this.canvas.tabIndex=0;for(var t in this.visListeners){this.network.on(t,this.visListeners[t].bind(this))}this.addGraphButtons({"fullscreen-button":function(){this.toggleEnlargedMode("fullscreen")},"halfscreen-button":function(){this.toggleEnlargedMode("halfscreen")}});utils.setDomListeners("add",this.canvas,this.canvasDomListeners);this.reloadBackgroundImage();this.rebuildGraph({resetFocus:{delay:0,duration:0}});this.handleResizeEvent();this.canvas.focus()};MapWidget.prototype.handleCanvasKeyup=function(){var e={from:null,to:null};return function(t){var i=this.network.getSelectedNodes();if(t.ctrlKey){t.preventDefault();if(t.keyCode===88){if(this.editorMode){this.handleAddNodesToClipboard("move")}else{$tm.notify("Map is read only!")}}else if(t.keyCode===67){this.handleAddNodesToClipboard("copy")}else if(t.keyCode===86){this.handlePasteNodesFromClipboard()}else if(t.keyCode===65){var s=Object.keys(this.graphData.nodesById);this.network.selectNodes(s)}else if(t.keyCode===49||t.keyCode===50){if(i.length!==1)return;var a=t.keyCode===49?"from":"to";$tm.notify(utils.ucFirst(a)+"-part selected");e[a]=i[0];if(e.from&&e.to){this.handleConnectionEvent(e,function(){e={from:null,to:null}})}}}else if(t.keyCode===13){if(i.length!==1)return;this.openTiddlerWithId(i[0])}}}();MapWidget.prototype.handleCanvasKeydown=function(e){if(e.keyCode===46){e.preventDefault();this.handleRemoveElements(this.network.getSelection())}};MapWidget.prototype.handleCanvasScroll=function(e){var t=!!(e.ctrlKey||this.isInSidebar||this.enlargedMode);if(t){e.preventDefault()}if(t!==this.visOptions.interaction.zoomView){e.preventDefault();e.stopPropagation();this.visOptions.interaction.zoomView=t;this.network.setOptions({interaction:{zoomView:t}});return false}};MapWidget.prototype.handleWidgetKeyup=function(e){};MapWidget.prototype.handleWidgetKeydown=function(e){if(e.ctrlKey){e.preventDefault();if(e.keyCode===70){e.preventDefault();var t=this.widgetPopupsPath+"/focus";utils.setText(t,utils.getText(t)?"":"1")}else{return}}else if(e.keyCode===120){e.preventDefault();this.toggleEnlargedMode("halfscreen")}else if(e.keyCode===121){e.preventDefault();this.toggleEnlargedMode("fullscreen")}else if(e.keyCode===27){e.preventDefault();utils.deleteByPrefix(this.widgetPopupsPath)}else{return}this.canvas.focus()};MapWidget.prototype.handlePasteNodesFromClipboard=function(){if(!this.editorMode||this.view.isLiveView()){$tm.notify("Map is read only!");return}if($tm.clipBoard){if($tm.clipBoard.type==="nodes"){var e=$tm.clipBoard.nodes;var t=Object.keys(e);if(t.length){for(var i in e){if(this.graphData.nodesById[i])continue;this.view.addNode(e[i]);this.graphData.nodes.update({id:i})}this.network.selectNodes(t);$tm.notify("pasted "+t.length+" nodes into map.")}return}}$tm.notify("TiddlyMap clipboad is empty!")};MapWidget.prototype.handleAddNodesToClipboard=function(e){var t=this.network.getSelectedNodes();if(!t.length)return;$tm.clipBoard={type:"nodes",nodes:this.graphData.nodes.get(t,{returnType:"Object"})};$tm.notify("Copied "+t.length+" nodes to clipboard");if(e==="move"){for(var i=t.length;i--;){this.view.removeNode(t[i])}}};MapWidget.prototype.isMobileMode=function(){var e=utils.getText($tm.ref.sidebarBreakpoint,960);return window.innerWidth<=parseInt(e)};MapWidget.prototype.getVisOptions=function(){var e=$tm.config.vis;var t=utils.parseJSON(this.view.getConfig("vis"));var i=utils.merge({},e,t);i.clickToUse=this.clickToUse;i.manipulation.enabled=!!this.editorMode;i.manipulation.deleteNode=function(e,t){this.handleRemoveElements(e);this.resetVisManipulationBar(t)}.bind(this);i.manipulation.deleteEdge=function(e,t){this.handleRemoveElements(e);this.resetVisManipulationBar(t)}.bind(this);i.manipulation.addEdge=function(e,t){this.handleConnectionEvent(e);this.resetVisManipulationBar(t)}.bind(this);i.manipulation.addNode=function(e,t){this.handleInsertNode(e);this.resetVisManipulationBar(t)}.bind(this);i.manipulation.editNode=function(e,t){this.handleEditNode(e);this.resetVisManipulationBar(t)}.bind(this);i.interaction.zoomView=!!(this.isInSidebar||this.enlargedMode);i.manipulation.editEdge=false;var s=i.physics;s[s.solver]=s[s.solver]||{};s.stabilization.iterations=1e3;this.logger("debug","Loaded graph options",i);return i};MapWidget.prototype.resetVisManipulationBar=function(e){if(e)e(null);this.network.disableEditMode();this.network.enableEditMode()};MapWidget.prototype.isVisInEditMode=function(){var e="vis-button vis-back";return this.graphDomNode.getElementsByClassName(e).length>0};MapWidget.prototype.handleCreateView=function(){var e={view:this.view.getLabel()};var t="createView";this.dialogManager.open(t,e,function(e,t){if(!e)return;var i=utils.getField(t,"name");var s=utils.getField(t,"clone",false);var a=new ViewAbstraction(i);if(a.exists()){$tm.notify("Forbidden! View already exists!");return}if(s&&this.view.isLiveView()){$tm.notify("Forbidden to clone the live view!");return}a=new ViewAbstraction(i,{isCreate:true,protoView:s?this.view:null});this.setView(a)})};MapWidget.prototype.handleRenameView=function(){if(this.view.isLocked()){$tm.notify("Forbidden!");return}var e=this.view.getOccurrences();var t={count:e.length.toString(),filter:utils.joinAndWrap(e,"[[","]]")};var i="renameView";this.dialogManager.open(i,t,function(e,t){if(e){var i=utils.getText(t);var s=new ViewAbstraction(i);if(!i){$tm.notify("Invalid name!")}else if(s.exists()){$tm.notify("Forbidden! View already exists!")}else{this.view.rename(i);this.setView(this.view)}}})};MapWidget.prototype.handleEditView=function(){var e=JSON.stringify($tm.config.vis);var t=this.graphData;var i=this.view.getConfig();var s={"filter.prettyNodeFltr":this.view.getNodeFilter("pretty"),"filter.prettyEdgeFltr":this.view.getEdgeTypeFilter("pretty"),"vis-inherited":e};var a={view:this.view.getLabel(),createdOn:this.view.getCreationDate(true),numberOfNodes:Object.keys(t.nodesById).length.toString(),numberOfEdges:Object.keys(t.edgesById).length.toString(),dialog:{preselects:$tw.utils.extend({},i,s)}};var r="configureView";this.dialogManager.open(r,a,function(e,t){if(!e)return;var i=utils.getPropertiesByPrefix(t.fields,"config.",true);var s=this.view.getConfig("background_image");this.view.setConfig(i);if(i["physics_mode"]&&!this.view.isEnabled("physics_mode")){this.handleStorePositions()}var a=this.view.getConfig("background_image");if(a&&a!==s){$tm.notify("Background changed! You may need to zoom out a bit.")}var r=utils.getField(t,"filter.prettyNodeFltr","");var o=utils.getField(t,"filter.prettyEdgeFltr","");this.view.setNodeFilter(r);this.view.setEdgeTypeFilter(o)})};MapWidget.prototype.handleSaveCanvas=function(){var e="$:/temp/tmap/snapshot";var t=this.createAndSaveSnapshot(e);var i=utils.getSnapshotTitle(this.view.getLabel(),"png");var s={dialog:{snapshot:e,width:this.canvas.width.toString(),height:this.canvas.height.toString(),preselects:{name:i,action:"download"}}};var a="saveCanvas";this.dialogManager.open(a,s,function(t,s){if(!t)return;i=s.fields.name||i;var a=s.fields.action;if(a==="download"){this.handleDownloadSnapshot(i)}else if(a==="wiki"){utils.cp(e,i,true);this.dispatchEvent({type:"tm-navigate",navigateTo:i})}else if(a==="placeholder"){this.view.addPlaceholder(e)}$tw.wiki.deleteTiddler("$:/temp/tmap/snapshot")})};MapWidget.prototype.handleDownloadSnapshot=function(e){var t=this.document.createElement("a");var i=this.view.getLabel();t.download=e||utils.getSnapshotTitle(i,"png");t.href=this.getSnapshot();var s=new MouseEvent("click");t.dispatchEvent(s)};MapWidget.prototype.createAndSaveSnapshot=function(e){var t=this.view.getLabel();var i=e||this.view.getRoot()+"/snapshot";$tw.wiki.addTiddler(new $tw.Tiddler({title:i,type:"image/png",text:this.getSnapshot(true),modified:new Date}));return i};MapWidget.prototype.getSnapshot=function(e){var t=this.canvas.toDataURL("image/png");return e?utils.getWithoutPrefix(t,"data:image/png;base64,"):t};MapWidget.prototype.handleDeleteView=function(){var e=this.view.getLabel();if(this.view.isLocked()){$tm.notify("Forbidden!");return}var t=this.view.getOccurrences();if(t.length){var i={count:t.length.toString(),filter:utils.joinAndWrap(t,"[[","]]")};this.dialogManager.open("cannotDeleteViewDialog",i);return}var s="You are about to delete the view "+"''"+e+"'' (no tiddler currently references this view).";this.openStandardConfirmDialog(function(t){if(t){this.view.destroy();this.setView($tm.misc.defaultViewLabel);this.logger("debug",'view "'+e+'" deleted ');$tm.notify('view "'+e+'" deleted ')}},s)};MapWidget.prototype.handleTriggeredRefresh=function(e){this.logger("log",e,"Triggered a refresh");if(this.id==="live_tab"){var t=utils.getTiddler(utils.getText(e));if(t){var i=t.fields["tmap.open-view"]||$tm.config.sys.liveTab.fallbackView;if(i&&i!==this.view.getLabel()){this.setView(i);return}}}this.rebuildGraph({resetFocus:{delay:1e3,duration:1e3}})};MapWidget.prototype.handleRemoveElements=function(e){if(e.nodes.length){this.handleRemoveNodes(e.nodes)}else if(e.edges.length){this.handleRemoveEdges(e.edges)}this.resetVisManipulationBar()};MapWidget.prototype.handleRemoveEdges=function(e){$tm.adapter.deleteEdges(this.graphData.edges.get(e));$tm.notify("edge"+(e.length>1?"s":"")+" removed");this.preventFitAfterRebuild=true};MapWidget.prototype.handleRemoveNodes=function(e){var t=$tm.adapter.getTiddlersById(e);var i={count:e.length.toString(),tiddlers:$tw.utils.stringifyList(t),dialog:{preselects:{"delete-from":"filter"}}};var s="deleteNodeDialog";this.dialogManager.open(s,i,function(t,i){if(!t)return;if(i.fields["delete-from"]==="system"){$tm.adapter.deleteNodes(e);var s=e.length}else{var s=0;for(var a=e.length;a--;){var r=this.view.removeNode(e[a]);if(r)s++}}this.preventFitAfterRebuild=true;$tm.notify("Removed "+s+" of "+e.length+" from "+i.fields["delete-from"])})};MapWidget.prototype.toggleEnlargedMode=function(e){if(!this.isInSidebar&&e==="halfscreen")return;this.logger("log","Toggled graph enlargement");var t=this.enlargedMode;if(t){this.network.setOptions({clickToUse:this.clickToUse});utils.findAndRemoveClassNames(["tmap-has-"+t+"-widget","tmap-"+t]);this.enlargedMode=null;document.body.scrollTop=this.scrollTop}if(!t||t!==e&&(e==="fullscreen"||e==="halfscreen"&&!this.isInSidebar)){var i=document.documentElement;this.scrollTop=document.body.scrollTop;this.enlargedMode=e;var s=this.isInSidebar?this.sidebar:utils.getFirstElementByClassName("tc-story-river");$tw.utils.addClass(this.document.body,"tmap-has-"+e+"-widget");$tw.utils.addClass(s,"tmap-has-"+e+"-widget");$tw.utils.addClass(this.domNode,"tmap-"+e);this.network.setOptions({clickToUse:false});$tm.notify("Toggled "+e+" mode")}this.handleResizeEvent()};MapWidget.prototype.handleGenerateWidget=function(e){$tw.rootWidget.dispatchEvent({type:"tmap:tm-generate-widget",paramObject:{view:this.view.getLabel()}})};MapWidget.prototype.handleStorePositions=function(e){var t=this.view.getNodeData();var i=this.network.getPositions();for(var s in i){t[s]=t[s]||{};t[s].x=i[s].x;t[s].y=i[s].y}this.view.saveNodeData(t);this.ignoreNextViewModification=true;if(e){$tm.notify("positions stored")}};MapWidget.prototype.handleVisStabilizedEvent=function(e){if(this.hasNetworkStabilized)return;this.hasNetworkStabilized=true;this.logger("log","Network stabilized after",e.iterations,"iterations");if(!this.view.isEnabled("physics_mode")){var t=this.graphData.nodesById;var i=[];for(var s in t){if(!t[s].x){i.push(s)}}if(i.length){this.setNodesMoveable(i,false);$tm.notify(i.length+" nodes were added to the graph");this.doFitAfterStabilize=true}var a=this.visOptions.physics;a[a.solver].centralGravity=0;this.network.setOptions(this.visOptions)}if(this.doFitAfterStabilize){this.doFitAfterStabilize=false;this.fitGraph(1e3,1e3)}};MapWidget.prototype.handleFocusNode=function(e){this.network.focus($tm.adapter.getId(e.param),{scale:1.5,animation:true})};MapWidget.prototype.isZombieWidget=function(){if(this.domNode.isTiddlyWikiFakeDom===true){return true}else{return!this.document.body.contains(this.getContainer())}};MapWidget.prototype.fitGraph=function(e,t){window.clearTimeout(this.activeFitTimeout);t=t||0;e=e||0;var i=function(){if(this.isZombieWidget())return;this.network.redraw();this.network.fit({animation:{duration:t,easingFunction:"easeOutQuart"}})};this.activeFitTimeout=window.setTimeout(i.bind(this),e)};MapWidget.prototype.handleInsertNode=function(e){var t="addNodeToMap";this.dialogManager.open(t,null,function(t,i){if(!t)return;var s=utils.getField(i,"draft.title");if(utils.tiddlerExists(s)){if(utils.isMatch(s,this.view.getNodeFilter("compiled"))){$tm.notify("Node already exists");return}else{e=$tm.adapter.makeNode(s,e);this.view.addNode(e)}}else{var a=new $tw.Tiddler(i,{"draft.title":null});e.label=s;$tm.adapter.insertNode(e,this.view,a)}this.preventFitAfterRebuild=true})};MapWidget.prototype.handleEditNode=function(e){var t=$tm.indeces.tById[e.id];var i=utils.getTiddler(t);var s=JSON.stringify($tm.config.vis);var a=this.view.getConfig("vis");var r={};r[e.id]=e;var o=$tm.adapter.getInheritedNodeStyles(r);var n=JSON.stringify(o[t]);var d=JSON.stringify(utils.merge({},{color:i.fields["color"]},utils.parseJSON(i.fields["tmap.style"])));var l=this.view.getLabel();var h={id:e.id};var g=this.view.getNodeData(e.id,true)||{};delete g.x;delete g.y;var p={view:l,tiddler:i.fields.title,tidColor:i.fields["color"],tidIcon:i.fields[$tm.field.nodeIcon]||i.fields["tmap.fa-icon"],tidLabelField:"global."+$tm.field.nodeLabel,tidIconField:"global."+$tm.field.nodeIcon,dialog:{preselects:{"inherited-global-default-style":s,"inherited-local-default-style":a,"inherited-group-styles":n,"global.tmap.style":d,"local-node-style":JSON.stringify(g)}}};var u=function(e,t,i){for(var s=i.length;s--;){p.dialog.preselects[e+"."+i[s]]=t[i[s]]||""}};u("local",g,["label","tw-icon","fa-icon","open-view"]);u("global",i.fields,[$tm.field.nodeLabel,$tm.field.nodeIcon,"tmap.fa-icon","tmap.open-view"]);this.dialogManager.open("editNode",p,function(i,s){if(!i)return;var a=s.fields;var r=utils.getPropertiesByPrefix(a,"global.",true);for(var o in r){utils.setField(t,o,r[o]||undefined)}var n=utils.getPropertiesByPrefix(a,"local.",true);var d=utils.parseJSON(a["local-node-style"],{});for(var o in n){d[o]=n[o]||undefined}this.view.saveNodeStyle(e.id,d);this.preventFitAfterRebuild=true})};MapWidget.prototype.handleVisSingleClickEvent=function(e){var t=utils.isTrue($tm.config.sys.singleClickMode);if(t&&!this.editorMode){this.handleOpenMapElementEvent(e)}};MapWidget.prototype.handleVisDoubleClickEvent=function(e){if(e.nodes.length||e.edges.length){if(this.editorMode||!utils.isTrue($tm.config.sys.singleClickMode)){this.handleOpenMapElementEvent(e)}}else{if(this.editorMode){this.handleInsertNode(e.pointer.canvas)}}};MapWidget.prototype.handleOpenMapElementEvent=function(e){if(e.nodes.length){var t=this.graphData.nodesById[e.nodes[0]];if(t["open-view"]){$tm.notify("Switching view");this.setView(t["open-view"])}else{this.openTiddlerWithId(e.nodes[0])}}else if(e.edges.length){this.logger("debug","Clicked on an Edge");var i=this.graphData.edgesById[e.edges[0]].type;this.handleEditEdgeType(i)}else{return}this.visTooltip.hide(0,true)};MapWidget.prototype.handleEditEdgeType=function(e){if(!this.editorMode)return;var t=$tm.config.sys.edgeClickBehaviour;if(t!=="manager")return;$tw.rootWidget.dispatchEvent({type:"tmap:tm-manage-edge-types",paramObject:{type:e}})};MapWidget.prototype.handleResizeEvent=function(e){if(this.isZombieWidget())return;var t=this.getAttr("height");var i=this.getAttr("width");if(this.isInSidebar){var s=this.domNode.getBoundingClientRect();var a=15;i=document.body.clientWidth-s.left-a+"px";var r=parseInt(this.getAttr("bottom-spacing"))||15;var o=window.innerHeight-s.top;t=o-r+"px"}this.domNode.style.height=t||"300px";this.domNode.style.width=i;this.repaintGraph()};MapWidget.prototype.handleClickEvent=function(e){if(this.isZombieWidget()||!this.network)return;if(!this.graphDomNode.contains(e.target)){var t=this.network.getSelection();if(t.nodes.length||t.edges.length){this.logger("debug","Clicked outside; deselecting nodes/edges");this.network.selectNodes([]);this.resetVisManipulationBar()}}else{this.canvas.focus()}};MapWidget.prototype.handleVisOnContext=function(e){};MapWidget.prototype.handleVisSelectNode=function(e){this.assignActiveStyle(e.nodes)};MapWidget.prototype.assignActiveStyle=function(e){if(!Array.isArray(e))e=[e];var t=this.visOptions.nodes.color;for(var i=e.length;i--;){var s=e[i];var a=this.graphData.nodesById[s];var r=utils.merge({},t,a.color);this.graphData.nodes.update({id:s,color:{highlight:r,hover:r}})}};MapWidget.prototype.handleVisDeselectNode=function(e){};MapWidget.prototype.handleVisDragEnd=function(e){if(!e.nodes.length)return;this.setNodesMoveable(e.nodes,false)};MapWidget.prototype.handleVisBeforeDrawing=function(e){if(this.backgroundImage){e.drawImage(this.backgroundImage,0,0)}};MapWidget.prototype.constructTooltip=function(e,t){var i=utils.parseJSON(e);var s=i.node||i.edge;var a=null;var r="text/html";var o="text/vnd-tiddlywiki";if(i.node){var n=$tm.indeces.tById[s];var d=utils.getTiddler(n);var l=d.fields[$tm.field.nodeInfo];if(l){t.innerHTML=$tw.wiki.renderText(r,o,l)}else if(d.fields.text){var h={type:"tiddler",attributes:{tiddler:{type:"string",value:n}},children:[{type:"transclude",attributes:{},isBlock:true}]};utils.removeArrayElement(this.children,this.tmpTooltipWidget);this.tmpTooltipWidget=this.makeChildWidget(h);this.tmpTooltipWidget.setVariable("tv-tiddler-preview","yes");this.tmpTooltipWidget.render(t,null);this.children.push(this.tmpTooltipWidget);return}else{t.innerHTML=n}}else{var g=this.graphData.edgesById[s];var p=$tm.indeces.allETy[g.type];if(p.description){a=$tw.wiki.renderText(r,o,p.description)}t.innerHTML=a||p.label||p.id}};MapWidget.prototype.handleVisHoverElement=function(e){if($tm.mouse.buttons)return;var t=e.node||e.edge;var i=JSON.stringify(e);if(e.node){this.assignActiveStyle(t)}if(!this.isVisInEditMode()){var s=this.constructTooltip;var i=JSON.stringify(e);this.visTooltip.show(i,s)}};MapWidget.prototype.handleVisBlurElement=function(e){this.visTooltip.hide()};MapWidget.prototype.handleVisLoading=function(e){this.graphLoadingBarDomNode.style.display="block";this.graphLoadingBarDomNode.setAttribute("max",e.total);this.graphLoadingBarDomNode.setAttribute("value",e.iterations)};MapWidget.prototype.handleVisLoadingDone=function(e){this.graphLoadingBarDomNode.style.display="none"};MapWidget.prototype.handleVisDragStart=function(e){if(e.nodes.length){this.visTooltip.hide(0,true);this.assignActiveStyle(e.nodes);this.setNodesMoveable(e.nodes,true)}};MapWidget.prototype.destruct=function(){utils.setDomListeners("remove",window,this.windowDomListeners);utils.setDomListeners("remove",this.domNode,this.widgetDomListeners);this._destructVis()};MapWidget.prototype._destructVis=function(){if(!this.network)return;utils.setDomListeners("remove",this.canvas,this.canvasDomListeners);this.network.destroy();this.network=null};MapWidget.prototype.openTiddlerWithId=function(e){var t=$tm.indeces.tById[e];this.logger("debug","Opening tiddler",t,"with id",e);if(this.enlargedMode==="fullscreen"){var i=this.wiki.findDraft(t);var s=!!i;if(!s){var a="tm-edit-tiddler";this.dispatchEvent({type:a,tiddlerTitle:t});i=this.wiki.findDraft(t)}var r={