Beispiel #1
0
  /**
   * Gets a Node representation for a tiddler.
   *
   * @param {Tiddler} tiddler - the tiddler to represent as node
   * @param {Object} protoNode - default node properties
   *
   * @return {Node|void}
   */
  makeNode(tiddler, protoNode) {

    const tObj = utils.getTiddler(tiddler);

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

    // merge(!) so later node manipulations do not affect other nodes
    const node = utils.merge({}, protoNode);

    // note: assignId() will not assign an id if the tiddler already has one
    node.id = this.assignId(tObj);

    // backreference to tiddler;
    // https://github.com/felixhayashi/TW5-TiddlyMap/issues/304
    node.tRef = tObj.fields.title;

    // add label
    const label = tObj.fields[$tm.field.nodeLabel];
    node.label = (
      label && $tm.field.nodeLabel !== 'title'
        ? this.wiki.renderText('text/plain', 'text/vnd-tiddlywiki', label)
        : tObj.fields.title
    ).replace('\\n', '\n');

    return node;

  }
Beispiel #2
0
Adapter.prototype._addNodeIcon = function(node, faIcon, twIcon) {
  
  // Font Awesome style
  if(faIcon) {
    node.shape = "icon";
    node.icon = {
      shape: "icon",
      face: "FontAwesome",
      color: node.color,
      code: String.fromCharCode("0x" + this._getFAdigits(faIcon))
    };
    //~ console.log(String.fromCharCode(parseInt(charCode, 16)));
    return;
  }
  
  // TiddlyWiki stored icons
  
  if(!twIcon) return;

  var imgTObj = utils.getTiddler(twIcon);
  if(!imgTObj) return;
  
  if(imgTObj.fields["_canonical_uri"]) { // image is a url address
    node.image = imgTObj.fields["_canonical_uri"];
    node.shape = "image";
    return;
  }
  
  if(imgTObj.fields.text) {
    node.image = utils.getDataUri(imgTObj);
    node.shape = "image";
    return;
  }
    
};
Beispiel #3
0
  /**
   * This method will assign an id to an *existing* tiddler that does
   * not already possess and id. Any assigned id will be registered
   * at the id->tiddler index.
   *
   * @param {Tiddler} tiddler - The tiddler to assign the id to.
   * @param {boolean} isForce - True if the id should be overridden,
   *     false otherwise. Only works if the id field is not set to title.
   *
   * @return {Id} The assigned or retrieved id.
   */
  assignId(tiddler, isForce) {

    // Note: always reload from store to avoid setting wrong ids on tiddler
    // being in the role of from and to at the same time.
    const tObj = utils.getTiddler(tiddler);

    if (!tObj) {
      throw new ResourceNotFoundException(tiddler);
    }

    let id = tObj.fields['tmap.id'];

    if (!id || isForce) {
      id = utils.genUUID();
      utils.setField(tObj, 'tmap.id', id);
      this.logger('info', 'Assigning new id to', tObj.fields.title);
    }

    // blindly update the index IN ANY CASE because tiddler may have
    // an id but it is not indexed yet (e.g. because of renaming operation)
    this.tById[id] = tObj.fields.title;
    this.idByT[tObj.fields.title] = id;

    return id;

  }
Beispiel #4
0
Adapter.prototype._processListEdge = function(tiddler, edge, type, action) {
      
  // get the name without the private marker or the namespace
  var name = type.name;
  
  var tObj = utils.getTiddler(tiddler);
  var list = $tw.utils.parseStringArray(tiddler.fields[name]);
  // we need to clone the array since tiddlywiki might directly
  // returned the auto-parsed field value (as in case of tags, or list)
  // and this array would be read only!
  list = (list || []).slice()
  
  // transform
  var toTRef = $tm.indeces.tById[edge.to];
      
  if(action === "insert") {
    list.push(toTRef);
    if(!type.exists()) {
      type.save();
    }
  } else { // delete
    var index = list.indexOf(toTRef);
    if(index > -1) {
      list.splice(index, 1);
    }
  }

  // save
  utils.setField(tObj, name, $tw.utils.stringifyList(list));
  
  return edge;
  
};
Beispiel #5
0
Adapter.prototype.assignId = function(tiddler, isForce) {

  // ALWAYS reload from store to avoid setting wrong ids on tiddler
  // being in the role of from and to at the same time.  
  // Therefore, do not use utils.getTiddler(tiddler)!
  var tObj = utils.getTiddler(tiddler, true);

  if(!tObj) return;
  
  var id = tObj.fields["tmap.id"];
  
  if(!id || isForce) {
    id = utils.genUUID();
    utils.setField(tObj, "tmap.id", id);
    $tm.logger("info", "Assigning new id to", tObj.fields.title);
  }
  
  // blindly update the index IN ANY CASE because tiddler may have
  // an id but it is not indexed yet (e.g. because of renaming operation)
  $tm.indeces.tById[id] = tObj.fields.title;
  $tm.indeces.idByT[tObj.fields.title] = id;
  
  return id;
  
};
Beispiel #6
0
Adapter.prototype._processEdge = function(edge, action) {
  
  $tm.logger("debug", "Edge", action, edge);

  if(typeof edge !== "object" || !action || !edge.from) return;
  if(action === "insert" && !edge.to) return;
  
  // get from-node and corresponding tiddler
  var fromTRef = $tm.indeces.tById[edge.from];
  if(!fromTRef || !utils.tiddlerExists(fromTRef)) return;

  var type = new EdgeType(edge.type);
  var tObj = utils.getTiddler(fromTRef);
  var namespace = type.namespace;
  
  if(namespace === "tw-list") {
    if(!edge.to) return;
    return this._processListEdge(tObj, edge, type, action);

  } else if(namespace === "tw-field") {
    if(!edge.to) return;
    return this._processFieldEdge(tObj, edge, type, action);
    
  } else if(namespace === "tw-body") {
    return null; // cannot delete links
    
  } else { // edge has no special meaning
    return this._processTmapEdge(tObj, edge, type, action);
    
  }

  return edge;
      
};
Beispiel #7
0
  /**
   * Private function to handle the insertion or deletion of an edge.
   * It prepares the process according to the action type and delegates
   * the task to more specific functions.
   *
   * @private
   * @return {Edge} The processed edge.
   */
  _processEdge(edge, action) {

    $tm.logger('debug', 'Edge', action, edge);

    // get from-node and corresponding tiddler
    const fromTRef = this.getTiddlerById(edge.from);

    if (!fromTRef || !utils.tiddlerExists(fromTRef)) {
      return;
    }

    const tObj = utils.getTiddler(fromTRef);
    const type = this.indeces.allETy[edge.type] || EdgeType.getInstance(edge.type);
    const handlers = this.edgeTypeSubscriberRegistry.getAllForType(type);
    const fn = `${action}Edge`;

    for (let i = handlers.length; i--;) {
      (handlers[i][fn])(tObj, edge, type);
    }

    // if type didn't exist yet, create it
    if (action === 'insert' && !type.exists()) {
      type.save();
    }

    return edge;

  }
Beispiel #8
0
  /**
   * 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;

  }
  /**
   * Enables the api user to modify the view's configuration.
   *
   * In case two arguments are provided, the first is assumed to be the property
   * name and the second the value to be set.
   *
   * In case a single object is provided as argument, it is treated as a key-value
   * collection and each property in this object is saved as config.
   *
   * @param {*} args
   */
  setConfig(...args) {

    if (args[0] == null) { // null or undefined

      return;
    }

    if (args.length === 1 && typeof args[0] === 'object') {

      for (let prop in args[0]) {
        this.setConfig(prop, args[0][prop]);
      }

    } else if (args.length === 2 && typeof args[0] === 'string') {

      const prop = utils.getWithoutPrefix(args[0], 'config.');
      let val = args[1];

      if (val === undefined) {

        return;
      }

      const config = this.getConfig();

      if (val === null) {

        $tm.logger('debug', 'Removing config', prop);
        delete config[`config.${prop}`];

      } else {

        if (prop === 'edge_type_namespace') {
          const match = val.match(/[^:]+/);
          val = (match ? match[0] : '');
        }

      }

      $tm.logger('log', 'Setting config', prop, val);
      config[`config.${prop}`] = val;

      // save
      $tw.wiki.addTiddler(new $tw.Tiddler(
        utils.getTiddler(this.configTRef),
        config
      ));

    } else { // not allowed

      throw new InvalidArgumentException(...args);

    }

  }
Beispiel #10
0
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;

};
Beispiel #11
0
const addNodeIcon = (node, icon) => {

  if (!icon) {
    return;
  }

  // Font Awesome style

  if (icon.fa) {

    node.shape = 'icon';
    node.icon = {
      shape: 'icon',
      face: 'FontAwesome',
      color: node.color,
      code: String.fromCharCode('0x' + getFAdigits(icon.fa)),
    };

    if (node.size) {
      node.icon.size = node.size;
    }

    return;
  }

  // TiddlyWiki stored icons

  if (icon.tw) {

    const imgTObj = utils.getTiddler(icon.tw);

    if (!imgTObj) {
      return;
    }

    if (imgTObj.fields['_canonical_uri']) { // image is a url address

      node.image = imgTObj.fields['_canonical_uri'];
      node.shape = 'image';

    } else if (imgTObj.fields.text) {

      node.image = utils.getDataUri(imgTObj);
      node.shape = 'image';
    }
  }

};
Beispiel #12
0
Adapter.prototype.makeNode = function(tiddler, protoNode) {

  var tObj = utils.getTiddler(tiddler);
    
  if(!tObj || utils.isSystemOrDraft(tObj)) return;
  
  var node = utils.merge({}, protoNode);
  
  // assignId() will not assign an id if the tiddler already has one
  node.id = this.assignId(tObj);
   
  // add label
  var label = tObj.fields[$tm.field.nodeLabel];
  node.label = (label && $tm.field.nodeLabel !== "title"
                ? $tw.wiki.renderText("text/plain", "text/vnd-tiddlywiki", label)
                : tObj.fields.title);
        
  return node;
  
};
  /**
   * Will create the config tiddler which means that the view will
   * start to exist.
   *
   * @private
   */
  _createView({ isForce, protoView, isHidden } = {}) {

    // destroy any former view that existed in this path
    if (ViewAbstraction.exists(this)) {

      if (!isForce) {

        return;

      }

      this.destroy();
    }

    if (ViewAbstraction.exists(protoView)) {
      utils.cp((new ViewAbstraction(protoView)).getRoot(), this.configTRef, true);
    }

    // create new view
    const fields = {
      title: this.configTRef,
      id: utils.genUUID(), // maybe useful for future purposes…
    };

    if (!isHidden) {
      fields[$tm.field.viewMarker] = true;
    }

    $tw.wiki.addTiddler(new $tw.Tiddler(
      utils.getTiddler(this.configTRef), // in case we cloned the view
      fields
    ));

    this.setEdgeTypeFilter(env.filter.defaultEdgeTypeFilter);

  }
Beispiel #14
0
"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}};
"use strict";exports.name="tmap.listener";exports.platforms=["browser"];exports.after=["rootwidget","tmap.caretaker"];exports.before=["story"];exports.synchronous=true;exports.startup=function(){new GlobalListener};var NodeType=require("$:/plugins/felixhayashi/tiddlymap/js/NodeType");var EdgeType=require("$:/plugins/felixhayashi/tiddlymap/js/EdgeType");var utils=require("$:/plugins/felixhayashi/tiddlymap/js/utils");var visDefConf=require("$:/plugins/felixhayashi/tiddlymap/js/config/vis");function GlobalListener(){this.wiki=$tw.wiki;utils.addTWlisteners({"tmap:tm-remove-edge":this.handleRemoveEdge,"tmap:tm-load-type-form":this.handleLoadTypeForm,"tmap:tm-save-type-form":this.handleSaveTypeForm,"tmap:tm-create-type":this.handleCreateType,"tmap:tm-create-edge":this.handleCreateEdge,"tmap:tm-suppress-dialog":this.handleSuppressDialog,"tmap:tm-generate-widget":this.handleGenerateWidget,"tmap:tm-download-graph":this.handleDownloadGraph,"tmap:tm-configure-system":this.handleConfigureSystem,"tmap:tm-manage-edge-types":this.handleOpenTypeManager,"tmap:tm-manage-node-types":this.handleOpenTypeManager,"tmap:tm-cancel-dialog":this.handleCancelDialog,"tmap:tm-clear-tiddler":this.handleClearTiddler,"tmap:tm-merge-tiddlers":this.handleMixTiddlers,"tmap:tm-confirm-dialog":this.handleConfirmDialog},$tw.rootWidget,this)}GlobalListener.prototype.handleCancelDialog=function(e){utils.setField(e.param,"text","")};GlobalListener.prototype.handleClearTiddler=function(e){var t=e.paramObject;if(!t||!t.title)return;var a=utils.getTiddler(t.title);var i=a?a.fields:{};var r=t.keep?t.keep.split():[];var d={title:t.title,text:""};for(var l=r.length;l--;){var s=r[l];d[s]=i[s]}$tw.wiki.deleteTiddler(t.title);$tw.wiki.addTiddler(new $tw.Tiddler(d))};GlobalListener.prototype.handleMixTiddlers=function(e){var t=e.paramObject;if(!t||!t.tiddlers)return;var a=$tw.utils.parseStringArray(t.tiddlers);var i=utils.getMergedTiddlers(a,t.output);$tw.wiki.addTiddler(i)};GlobalListener.prototype.handleConfirmDialog=function(e){utils.setField(e.param,"text","1")};GlobalListener.prototype.handleSuppressDialog=function(e){if(utils.isTrue(e.paramObject.suppress,false)){utils.setEntry($tm.ref.sysUserConf,"suppressedDialogs."+e.paramObject.dialog,true)}};GlobalListener.prototype.handleDownloadGraph=function(e){var t=$tm.adapter.getGraph({view:e.paramObject.view});t.nodes=utils.convert(t.nodes,"array");t.edges=utils.convert(t.edges,"array");var a="$:/temp/tmap/export";utils.setField(a,"text",JSON.stringify(t,null,2));$tw.rootWidget.dispatchEvent({type:"tm-download-file",param:a,paramObject:{filename:e.paramObject.view+".json"}})};GlobalListener.prototype.handleConfigureSystem=function(){var e=$tm.adapter.getAllPotentialNodes();var t=$tm.adapter.getEdgesForSet(e);var a=$tw.wiki.getTiddler($tm.path.pluginRoot).fields;var i=$tw.wiki.getTiddlerData($tm.ref.sysMeta);var r=utils.getTiddler($tm.ref.liveTab).hasTag("$:/tags/SideBar");var d={numberOfNodes:""+e.length,numberOfEdges:""+Object.keys(t).length,pluginVersion:"v"+a.version,dataStructureVersion:"v"+i.dataStructureState,dialog:{preselects:{liveTab:""+r,"vis-inherited":JSON.stringify(visDefConf),"config.vis":utils.getText($tm.ref.visUserConf),"config.sys":$tm.config.sys}}};var l="globalConfig";$tm.dialogManager.open(l,d,function(e,t){if(!e)return;var a=utils.getPropertiesByPrefix(t.fields,"config.sys.",true);$tw.wiki.setTiddlerData($tm.ref.sysUserConf,a);if(utils.isTrue(t.fields.liveTab,false)){utils.setField($tm.ref.liveTab,"tags","$:/tags/SideBar")}else{$tw.wiki.deleteTiddler($tm.ref.liveTab)}utils.setField($tm.ref.visUserConf,"text",t.fields["config.vis"])}.bind(this))};GlobalListener.prototype.handleGenerateWidget=function(e){if(!e.paramObject)e.paramObject={};var t={dialog:{preselects:{view:e.paramObject.view||$tm.misc.defaultViewLabel}}};$tm.dialogManager.open("widgetCodeGenerator",t)};GlobalListener.prototype.handleRemoveEdge=function(e){$tm.adapter.deleteEdge(e.paramObject)};GlobalListener.prototype.handleCreateEdge=function(e){var t=e.paramObject.from;var a=e.paramObject.to;var i=e.paramObject.force;if(!t||!a)return;if(utils.tiddlerExists(t)&&utils.tiddlerExists(a)||i){utils.addTiddler(a);utils.addTiddler(t);var r={from:$tm.adapter.makeNode(t).id,to:$tm.adapter.makeNode(a).id,type:e.paramObject.label,id:e.paramObject.id};$tm.adapter.insertEdge(r);$tm.notify("Edge inserted")}};GlobalListener.prototype.handleOpenTypeManager=function(e){if(!e.paramObject)e.paramObject={};var t=e.type.match(/tmap:tm-(.*)/)[1];if(t==="manage-edge-types"){var a="Edge-Type Manager";var i=$tm.selector.allEdgeTypes;var r=$tm.path.edgeTypes}else{var a="Node-Type Manager";var i=$tm.selector.allNodeTypes;var r=$tm.path.nodeTypes}var d={mode:t,topic:a,searchSelector:i,typeRootPath:r};var l=$tm.dialogManager.open("MapElementTypeManager",d);if(e.paramObject.type){this.handleLoadTypeForm({paramObject:{mode:t,id:e.paramObject.type,output:l.fields["output"]}})}};GlobalListener.prototype.handleLoadTypeForm=function(e){var t=e.paramObject.output;var a=e.paramObject.mode==="manage-edge-types"?new EdgeType(e.paramObject.id):new NodeType(e.paramObject.id);a.save(t);if(e.paramObject.mode==="manage-edge-types"){var i=$tm.adapter.selectEdgesByType(a);var r=Object.keys(i).length;utils.setField(t,"temp.usageCount",r)}$tw.wiki.addTiddler(new $tw.Tiddler(utils.getTiddler(t),{typeTRef:a.fullPath,"temp.idImmutable":a.isShipped?"true":"","temp.newId":a.id,"vis-inherited":JSON.stringify($tm.config.vis)}));utils.deleteByPrefix("$:/state/tabs/MapElementTypeManager")};GlobalListener.prototype.handleSaveTypeForm=function(e){var t=utils.getTiddler(e.paramObject.output);if(!t)return;var a=e.paramObject.mode;var i=a==="manage-edge-types"?new EdgeType(t.fields.id):new NodeType(t.fields.id);if(utils.isTrue(t.fields["temp.deleteType"],false)){this.deleteType(a,i,t)}else{this.saveType(a,i,t)}};GlobalListener.prototype.deleteType=function(e,t,a){$tm.logger("debug","Deleting type",t);if(e==="manage-edge-types"){$tm.adapter._processEdgesWithType(t,{action:"delete"})}else{$tm.adapter.removeNodeType(t)}this.wiki.addTiddler(new $tw.Tiddler({title:utils.getTiddlerRef(a)}));$tm.notify("Deleted type")};GlobalListener.prototype.saveType=function(e,t,a){var i=utils.getTiddler(a);t.loadFromTiddler(i);t.save();var r=i.fields["temp.newId"];if(r&&r!==i.fields["id"]){if(e==="manage-edge-types"){$tm.adapter._processEdgesWithType(t,{action:"rename",newName:r})}else{var d=new NodeType(r);d.load(t);d.save();$tw.wiki.deleteTiddler(t.fullPath)}utils.setField(i,"id",r)}$tm.notify("Saved type data")};GlobalListener.prototype.handleCreateType=function(e){var t=e.paramObject.id||"New type";var a=e.paramObject.mode==="manage-edge-types"?new EdgeType(t):new NodeType(t);a.save();this.handleLoadTypeForm({paramObject:{id:a.id,mode:e.paramObject.mode,output:e.paramObject.output}})};GlobalListener.prototype.getTypeFromEvent=function(e){return e.paramObject.mode==="manage-edge-types"?new EdgeType(e.paramObject.id):new NodeType(e.paramObject.id)};
DialogManager.prototype.open = function(templateId, param, callback) {
  
  if(utils.isTrue($tm.config.sys.suppressedDialogs[templateId], false)) {
    $tm.logger("warning", "Suppressed dialog", templateId);
    return;
  }
  
  param = param || {}
  
  $tm.logger("debug", "Dialog param object", param);

  if(typeof callback === "function" && this.context) {
    callback = callback.bind(this.context);
  }
  
  // create a temporary tiddler reference for the dialog
  var dialogTRef = $tm.path.tempRoot + "/dialog-" + utils.genUUID();
  
  // get the dialog template
  var skeleton = utils.getTiddler($tm.path.dialogs + "/" + templateId);
  
  // fields used to handle the dialog process
  var dialog = {
    title: dialogTRef,
    buttons: skeleton.fields["buttons"] || "ok_cancel",
    classes: "tmap-modal-content " + skeleton.fields["classes"],
    output: dialogTRef + "/output",
    result: dialogTRef + "/result",
    temp: dialogTRef + "/temp",
    template: skeleton.fields.title,
    templateId: templateId,
    currentTiddler: dialogTRef + "/output",
    text: utils.getText($tm.path.dialogs)
  };
      
  if(param.dialog) {
          
    if(param.dialog.preselects) {
      
      // register preselects
      $tw.wiki.addTiddler(new $tw.Tiddler(
        { title : dialog.output },
        utils.flatten(param.dialog.preselects)
      ));
      
      // remove preselects from param object
      delete param.dialog.preselects;
      
    }
    
    // extend the dialog object with parameters provided by the user
    utils.merge(dialog, param.dialog);

  }
  
  // force the footer to be set to the wrapper
  // the footer wrapper will determine the footer from the
  // buttons field/variable
  dialog.footer = utils.getText($tm.path.footers);
  
  // flatten dialog and param object
  dialog = utils.flatten(dialog);
  param = utils.flatten(param);
  
  var fn = function(t) {

    this.getElement("hidden-close-button").click();

    var triggerTObj = $tw.wiki.getTiddler(t);
    var isConfirmed = triggerTObj.fields.text;
    
    if(isConfirmed) {
      var outputTObj = $tw.wiki.getTiddler(dialog.output);
    } else {
      var outputTObj = null;
      $tm.notify("operation cancelled");
    }
    
    if(typeof callback === "function") {
      callback(isConfirmed, outputTObj);
    }
    
    // close and remove all tiddlers used by the dialog
    utils.deleteByPrefix(dialogTRef);
    
  }.bind(this);
  
  // add trigger 
  this.callbackManager.add(dialog.result, fn, true);
  

  // create dialog
  var dialogTiddler = new $tw.Tiddler(skeleton, param, dialog);
  $tw.wiki.addTiddler(dialogTiddler);
  
  $tm.logger("debug", "Opening dialog", dialogTiddler);
  
  $tw.rootWidget.dispatchEvent({
    type: "tm-modal",
    param : dialogTiddler.fields.title,
    paramObject: dialogTiddler.fields
  });
  
  this.addKeyBindings();
  
  return dialogTiddler;
  
};
  /**
   * This function opens a dialog based on a skeleton and some fields and eventually
   * calls a callback once the dialog is closed. The callback contains an indicator
   * whether the dialog subject was confirmed or the operation cancelled. In any
   * case the output tiddler is passed to the callback. Each dialog may write its
   * changes to this tiddler in order to store the dialog result and make it available
   * to the callback.
   *
   * How does it work?
   *
   * The output of the dialog process is stored in a temporary tiddler that is only known
   * to the current instance of the dialog. This way it is ensured that only the dialog process
   * that created the temporary tiddler will retrieve the result. Now we are able to
   * provide unambigous and unique correspondance to dialog callbacks.

   * Any dialog output is stored in a unique output-tiddler. Once there is a result,
   * a new result tiddler is created with indicators how to interpret the output.
   * The result tiddler can be understood as exit code that is independent of the output.
   * It is the result tiddler that triggers the dialog callback that was registered before.
   * the output is then read immediately from the output-tiddler.
   *
   * @param {string} templateId - The dialog id which is the basename of
   *     the template title.
   * @param {Hashmap} [param] - All properties (except those with special meanings)
   *     of param will be accessible as variables in the modal
   * @param {string} [param.subtitle] -
   * @param {string} [param.cancelButtonLabel] - The label of the cancel button.
   * @param {string} [param.confirmButtonLabel] - The label of the confirm button.
   * @param {function} [callback] - A function with the signature
   *     function(isConfirmed, outputTObj). `outputTObj` contains data
   *     produced by the dialog (can be undefined even if confirmed!).
   *     Be careful: the tiddler that outputTObj represents is deleted immediately.
   * @return {$tw.Tiddler} The dialog tddler object with all its fields.
   */
  open(templateId, param = {}, callback) {

    if (utils.isTrue($tm.config.sys.suppressedDialogs[templateId], false)) {
      $tm.logger('warning', 'Suppressed dialog', templateId);
      return;
    }

    $tm.logger('debug', 'Dialog param object', param);

    if (typeof callback === 'function' && this.context) {
      callback = callback.bind(this.context);
    }

    // create a temporary tiddler reference for the dialog
    const dialogTRef = `${$tm.path.tempRoot}/dialog-${utils.genUUID()}`;

    // get the dialog template
    const skeleton = utils.getTiddler(`${$tm.path.dialogs}/${templateId}`);

    // fields used to handle the dialog process
    let dialog = {
      title: dialogTRef,
      buttons: skeleton.fields['buttons'] || 'ok_cancel',
      classes: 'tmap-modal-content ' + skeleton.fields['classes'],
      output: dialogTRef + '/output',
      result: dialogTRef + '/result',
      temp: dialogTRef + '/temp',
      template: skeleton.fields.title,
      templateId: templateId,
      currentTiddler: dialogTRef + '/output',
      text: utils.getText($tm.path.dialogs)
    };

    utils.touch(dialog.output);

    if (param.dialog) {

      if (param.dialog.preselects) {

        // register preselects
        $tw.wiki.addTiddler(new $tw.Tiddler(
          {title: dialog.output},
          utils.flatten(param.dialog.preselects)
        ));

        // remove preselects from param object
        delete param.dialog.preselects;

      }

      // extend the dialog object with parameters provided by the user
      utils.merge(dialog, param.dialog);

    }

    // force the footer to be set to the wrapper
    // the footer wrapper will determine the footer from the
    // buttons field/variable
    dialog.footer = utils.getText($tm.path.footers);

    // flatten dialog and param object
    dialog = utils.flatten(dialog);
    param = utils.flatten(param);

    const fn = tRef => {

      DialogManager.getElement('hidden-close-button').click();

      const triggerTObj = $tw.wiki.getTiddler(tRef);
      const isConfirmed = triggerTObj.fields.text;

      let outputTObj = null;
      if (isConfirmed) {
        outputTObj = $tw.wiki.getTiddler(dialog.output);
      } else {
        $tm.notify('operation cancelled');
      }

      if (typeof callback === 'function') {
        callback(isConfirmed, outputTObj);
      }

      // close and remove all tiddlers used by the dialog
      utils.deleteByPrefix(dialogTRef);

    };

    // add trigger
    this.callbackManager.add(dialog.result, fn, true);


    // create dialog
    const dialogTiddler = new $tw.Tiddler(skeleton, param, dialog);
    $tw.wiki.addTiddler(dialogTiddler);

    $tm.logger('debug', 'Opening dialog', dialogTiddler);

    $tw.rootWidget.dispatchEvent({
      type: 'tm-modal',
      param: dialogTiddler.fields.title,
      paramObject: dialogTiddler.fields
    });

    DialogManager.addKeyBindings();

    return dialogTiddler;

  };
Beispiel #18
0
"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={
    const config = $tw.wiki.getCacheForTiddler(this.configTRef, "tmap-config", () => {

      const fields = utils.getTiddler(this.configTRef).fields;
      return utils.getPropertiesByPrefix(fields, 'config.');

    });
Beispiel #20
0
draftTRef:i,originalTRef:t};var o="fullscreenTiddlerEditor";this.dialogManager.open(o,r,function(e,a){if(e){var r="tm-save-tiddler";this.dispatchEvent({type:r,tiddlerTitle:i})}else if(!s){utils.deleteTiddlers([i])}var r="tm-close-tiddler";this.dispatchEvent({type:r,tiddlerTitle:t})})}else{var n=this.domNode.getBoundingClientRect();this.dispatchEvent({type:"tm-navigate",navigateTo:t,navigateFromTitle:this.getVariable("storyTiddler"),navigateFromNode:this,navigateFromClientRect:{top:n.top,left:n.left,width:n.width,right:n.right,bottom:n.bottom,height:n.height}})}};MapWidget.prototype.getViewHolderRef=function(){if(this.viewHolderRef){return this.viewHolderRef}this.logger("info","Retrieving or generating the view holder reference");var e=this.getAttr("view");if(e){this.logger("log",'User wants to bind view "'+e+'" to graph');var t=$tm.path.views+"/"+e;if(this.wiki.getTiddler(t)){var i=$tm.path.localHolders+"/"+utils.genUUID();this.logger("log",'Created an independent temporary view holder "'+i+'"');utils.setText(i,t);this.logger("log",'View "'+t+'" inserted into independend holder')}else{this.logger("log",'View "'+e+'" does not exist')}}if(typeof i==="undefined"){this.logger("log","Using default (global) view holder");var i=$tm.ref.defaultViewHolder}return i};MapWidget.prototype.setView=function(e,t){e=new ViewAbstraction(e);if(!e.exists())return;var i=e.getLabel();t=t||this.viewHolderRef;this.logger("info","Inserting view '"+i+"' into holder '"+t+"'");this.wiki.addTiddler(new $tw.Tiddler({title:t,text:i}))};MapWidget.prototype.getView=function(e){if(!e&&this.view){return this.view}var t=this.getViewHolderRef();var i=utils.getText(t);var s=new ViewAbstraction(i);this.logger("debug","Retrieved view from holder");if(!s.exists()){this.logger("debug",'Warning: View "'+i+"\" doesn't exist. Default is used instead.");s=new ViewAbstraction("Default")}return s};MapWidget.prototype.reloadBackgroundImage=function(e){this.backgroundImage=null;var t=this.view.getConfig("background_image");var i=utils.getTiddler(t);if(!i&&!t)return;var s=new Image;var a=function(e){s.src=e};s.onload=function(){this.backgroundImage=s;this.repaintGraph();if(e){$tm.notify(e)}}.bind(this);if(i){var r=i.fields["_canonical_uri"];if(r){utils.getImgFromWeb(r,a)}else if(i.fields.text){var o=$tw.utils.makeDataUri(i.fields.text,i.fields.type);s.src=o}}else if(t){utils.getImgFromWeb(t,a)}};MapWidget.prototype.getRefreshedDataSet=function(e,t,i){if(!i){return new vis.DataSet(utils.getValues(e))}if(t)i.remove(Object.keys(t));i.update(utils.getValues(e));return i};MapWidget.prototype.repaintGraph=function(){var e=$tw.utils.hasClass(this.document.body,"tmap-has-fullscreen-widget");if(this.network&&(!e||e&&this.enlargedMode)){this.logger("info","Repainting the whole graph");this.network.redraw();this.fitGraph(0,1e3)}};MapWidget.prototype.setGraphButtonEnabled=function(e,t){var i="vis-button"+" "+"tmap-"+e;var s=utils.getFirstElementByClassName(i,this.domNode);$tw.utils.toggleClass(s,"tmap-button-enabled",t)};MapWidget.prototype.dialogPostProcessor=function(){this.network.selectNodes([]);this.resetVisManipulationBar()};MapWidget.prototype.setNodesMoveable=function(e,t){if(!e||!e.length||this.view.isEnabled("physics_mode")){return}var i=[];var s=!t;for(var a=e.length;a--;){i.push({id:e[a],fixed:{x:s,y:s}})}this.graphData.nodes.update(i);if(s){this.logger("debug","Fixing",i.length,"nodes");this.handleStorePositions()}};MapWidget.prototype.addGraphButtons=function(e){var t=utils.getFirstElementByClassName("vis-navigation",this.domNode);for(var i in e){var s=this.document.createElement("div");s.className="vis-button "+" "+"tmap-"+i;s.addEventListener("click",e[i].bind(this),false);t.appendChild(s);this.setGraphButtonEnabled(i,true)}};