Autor Zpráva
návštěvník
Profil *
Pracuji na něčem takovém:
http://www.pedagogeeks.fr/wp-content/docs//2011/09/pearltrees.png
v a dělám to v javascriptu. Mám funkční strom, tzn. když najedu na ikonu, tak ta se označí a mohu ji vybrat (tj. vybrat uzel). Aktuálně je to tak, že var selected = node. A node je objekt s informacema o uzlu, jsou tam informace jako id, label, img... Aktuálně mám 150 ikon a ještě jich několik přibude.

Teď chci dál pokračovat tím že zezačátku zobrazím jen první a druhou úroveň ikon. Když kliknu na ikonu druhé úrovně, tak se zobrazí její potomci. Atd. Potřeboval bych vymyslet jak ukládat tada aby se daly snadno zpřístupnit a bylo to přehledné.

Nejdříve mě napadlo toto: udělat dvourozměrné pole, ve kterém na prvním indexu arr[0][0] by byl první uzel, v arr arr[1] by byly uzly druhé úrovně, v arr[2] uzly třetí úrovně atd. Ale pak už na čtvrté úrovni je tam těch ikon docela dost a tak při každém příkazu na vykreslení ikon bych neefektivně musel procházet spoustu objektů. A navíc to taky není moc přehledné. Nějaký tip jak si to zorganizovat? Zase dělat nepravidelné vícerozměrné pole mi přijde jako složité řešení.

Příklad:
První uzel se jmenuje "Moje okruhy"
Druhá úroveň obsahuje:
'Společnost', 'Venkovní aktivity', 'Domácí aktivity', 'Zdraví', 'Životní styl'....

Uzel "Společnost" obsahuje na třetí úrovni:
'Hudba a tanec', 'Kultura', 'Vzdělávání', 'Práce', 'Politika', 'Náboženství'

Práce bude obsahovat jen pár uzlů a tam to končí.
Ale třeba 'Náboženství' může obsahovat Křesťanství, Islám, Hinduismus atd. A Křesťanství může obsahovat různé církve cirkví....

Tzn. že hloubka zanoření je nepravidelná. Nejnižší zanoření je u Životního stylu, tam mám jen 'Vegetariánství', 'New age', 'Gothic', 'Emo', 'Grunge', 'Punk', 'Nudismus'


Jde mi o to že do toho objektu chci ukládat informace o tom, které větve jsou zabaleny. Takže když kliknu na ikonu, ta je rodičem těch zabalených čili schovaných ikon/uzlů.
juriad
Profil
návštěvník:
Vytvoř si stromovou strukturu pomocí objektů:
Živá ukázka

Toto můžeš libovolně rozšířit. Třeba, aby každý node znal ikonku.
Můžeš si všecny nody zabalit do třídy Tree, skrze kterou budeš s Nody pracovat (přidávání, odebírání, zavírání, otevírání). Ta si pak bude pamatovat statistiky ohledně počtu, které budou sloužit pro výpočet úhlů pro kreslení.
návštěvník
Profil *
živá ukázka mi asi nefunguje, ale dík za kód podívám se na to, analyzuju a vyzkouším
juriad
Profil
návštěvník:
Ale funguje. Spíš je to demonstrace kódu. Přece nechceš, abych vytvořil kompletní kreslení toho stromu. Pokud budeš mít nějaké otázky, určitě se ptej.

Začni tím, jaké operace s tím stromem budeš chtít a jaké vlastnosti by si měl každý uzel pamatovat.
návštěvník
Profil *
Jo funguje. Budu to muset přejmenovat, protože Node už v knihovně springy.js existuje:
http://getspringy.com/demo.html
Ideální název by byl Tree
návštěvník
Profil *
Tak začínám integrovat. Starý Node nahradím Tvým node, akorád rozšířím seznam argumentů.

http://paste.ofcode.org/UiBAy4NSY98ubkzmwZU3B2

Chyba:
TypeError: parent.addChild is not a function (9. řádek uvnitř definice funkce Springy.Node ...
juriad
Profil
návštěvník:
Když teď koukám na to Springy, tak si nemyslím, že je to vhodně zvolená platforma. Umí to sice kreslit grafy, ale ty chceš jen stromy a navíc jen zakořenéně ve středu a jednotlivé vrcholy chceš mít v soustredných kružnicích podle úrovně. Toto je mnohem jednodušší úloha.

Nejsem si jistý, že ti umím pomoct. Chceš se vrtat v nějaké knihovně, které nejspíš nerozumíš. Pokud bys jí rozumněl, věděl bys, že stačí implementovat jen svůj renderer a data jedntlivých nodů si budeš držet jinde. Na druhou stranu nejsi nejspíš schopný implementovat si to kreslení sám, přestože je to (při zadaných omezeních) práce na chvilku (řekněme den).

Pokud chceš skutečně ohýbat to Springy, tak to nejspíš budeš muset skoro celé přepsat. Netuším jaké úpravy jsi udělal ani zda máš vůbec nějaký návrh.
návštěvník
Profil *
To springy umí vykreslovat do kružnic. Všechno záleží na konfiguraci. Ty úrovně se tam taky dají udělat. Problém byl v jeho implementaci protože nejdříve hodil všechny nody do jednoho a pak je pospojoval čili vytvářel souvislosti mezi nody. Chci to udělat tak, že bude možné si vybrat jak to použít, takže ten zanořovaný systém bych použil pro sebe, ale v případě že se to vypne v springyui.js tak se použije ten jeho systém. Ve vykreslení problém nemám. Jde čistě jen o to monitorovat který nod je viditelný. S tou chybou mi jsi schopen pomoct nebo ne?
juriad
Profil
Nejspíš nejsem. Neznám celý rozsah tvých změn. Navíc si nejsem jistý, že chceš měnit datový model Springy. Sice to na první pohled vypadá jednoduše, ale Springy s jinou strukturou nepočítá. Můj návrh, který nepočítal s existencí Springy, například vůbec nepoužívá Edge, která je ve Springy nutná především z důvodu výpočtu rozmístění nodů do roviny.
Pokud se pokusíš o nějaký hybrid, bude to naprosto zmršené a nepřehledné. Nemyslím si, že je možné vytvořit něco rozumného zásahem do Springy. Buď to celé napsat znovu bez Springy, nebo nechat Springy tak jak je a dopsat si jen renderování a listenery - tak jak je Springy navržené.
návštěvník
Profil *
Jenže já Springy neměním. Já tam akorád přidávám několik polí. Co jsem udělal byla změna v indexaci polí. Místo názvu uzlu pro id používám id číslo. Jeho pole zachovávám, ale přidal jsem svoje pole. Takže se nejdená o žádné podstatné změny, které by ovlivnili chod aplikace. Co jsem přidal je funkce na přidávání obrázků. Opět žádný zázrak. Jenom do objektu data, který je vstupním parametrem předaným uživatelem jsem přidal img. Ten problém s addChild jsme vyřešil tak, že jsem to přidání zahrnul přímo do definice Node takto: parent.children.push(this); Následuje počítatlo children: this.childrenCount++;
Moje řešení spočívá v tom, že zachovávám jeho pole které monitoruje node(s). Do jeho node jsem přidal .children , .visible, .selected . To nemá vliv na chod aplikace, ale bude to sloužit k tomu abych mohl pomocí springyui.js .mousemove měnit parametr .visible . Ten renderer tam běží neustále, takže pokud změním .visible pomocí svojí funkce, tak ty určité nody se prostě nezobrazí a jiné se zobrazí. To bude mít velký přínos na výkon protože když používám ten .stoke() na podsvícení textu tak to moc vytěžuje. Jak budu vykreslovat jen malé množství nodů tak to bude v pohodě.

A teď s kódem, který mám hotový:

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {       
        define(function () {
            return (root.returnExportsGlobal = factory());
        });
    } else if (typeof exports === 'object') {
        module.exports = factory();
    } else {
        root.Springy = factory();
    }
}(this, function() {

    var Springy = {};
    var Graph = Springy.Graph = function(params) {
    this.nodeSet = {};
    this.nodeLabels = []; // id:    label
    this.nodeIds = [];    // label: id
    this.images = [];     // id:    src  autorovo pole
    this.nodes = [];
    this.nodeTrees = []; // moje pole s objekty které nemají rodiče
    this.edges = [];
    this.adjacency = {};
    this.imageType = params.imageType !== undefined ? params.imageType : ".jpg";
    this.imagePath = params.imagePath !== undefined ? params.imagePath : "";
    this.useNodeTree = params.useNodeTree !== undefined ? params.useNodeTree : true;
    this.nodeTreesCount = 0;
    
    this.nextNodeId = -1; // toto jsem přidal kvůli automatickému navyšování id
    this.nextEdgeId = 0;
    this.eventListeners = [];
    this.initAllNodesCompleted = false; // toto jsem přidal
    this.totalNodes = 0;  // toto jsem přidal
    };

  Springy.Graph.prototype.getTotalNodes = function(){       
    return this.totalNodes;
  }
    var Node = Springy.Node = function(parent, data, visible) {
          this.id = data.id;
      this.selected = false;
      this.visible = visible;
          this.data = (data !== undefined) ? data : {};
      this.children = [];
      this.childrenCount = 0;
  
      if (parent != null) {
          // add this node to its parent
          parent.children.push(this);
          console.log("ADDING CHILD");
          this.childrenCount++; 
          this.level = parent.level + 1;
          this.open = false;
      } else {
        console.log("ADD TREE");
          this.level = 0;
          this.open = true;
          return this;
      }
  };
  Springy.Graph.prototype.addTree = function(node) {
      this.nodeTrees.push(node);
  };
  
  Springy.Node.prototype.getNode = function(id){
    if (this.id == id)
      return this;
    for (var i=0;i<this.childrenCount-1;i++) 
      {
      if (this.children[i].id==id)
        return this.children[i];
      }
    // Node not found, try deep search
    var child;
    
    for (var i=0;i<this.childrenCount-1;i++) 
      {
      child = this.children[i].getNode(id);
      if (child !== null)          
        return this.child;
      }
    return null;    
  }
  

getNode slouží k nalezení rodiče. Následovala by tvoje funkce .getParents ale nepotřebuju ji zatím. .isVisible taky zatím nepotřebuju. Následuje jedna lehce upravená funkce a ta moje funkce na obrázky:

    var Edge = Springy.Edge = function(id, source, target, data) {
    this.id = id;
    this.source = source;
    this.target = target;
    this.data = (data !== undefined) ? data : {};
    };

    var ImagE = Springy.Image = function(id, src) {
        this.id = id;
        this.source = src;
    };

Pak jeho funkce addNode, tu jsem přejmenoval aby se mi to nepletlo s mojí funkcí:
    Graph.prototype.addNodeToArray = function(node) {
    // complete lists of nodes (type array)
    if (!(node.id in this.nodeSet)) {
            this.nodes.push(node);
        }
    this.nodeSet[this.nextNodeId] = node;
        this.notify();
        return node;
    };
možno přejmenovat jinak. Toto je jeho funkce, která přidává všechny nody do jednoho pole. Nutno zdůraznit že ji zachovávám v kódu, odkaz na všechny nody by měl být udržován v this.nodes ; teď si nevybavuju co je v this.nodeSet ale asi taky nějaký seznam nodů

Pak následuje AddNodes která volala AddNode nyní AddNodeToArray. To je ta moje hlavní funkce na přidávání nodů do stromu:

Graph.prototype.addNodes = function(parent_label, args, visible) {
    var parent = null;
    
    for (var i = 0; i < args.length; i++) {
      this.nextNodeId++;
      var label = args[i];
      this.nodeLabels[this.nextNodeId] = label;
      this.nodeIds[label] = this.nextNodeId;
      if (parent_label != null)
        var parent_id = this.nodeIds[parent_label];
      var parent;
      
      if (parent_label != null)
        {
        console.log("B");
        console.log("parent id: " + parent_id);
        for (var i=0; i<this.nodeTreesCount; i++){          
          parent = this.nodeTrees[i].getNode(parent_id);
          if (parent!=null) 
            break;
          }
        }

      console.log("C");
      var node = new Node(parent, {id: this.nextNodeId, label:label}, visible);
      
      if ( parent == null ){        
        // Add topmost node
        console.log("A");        
        this.addTree(node); // => this.nodeTrees.push(node);
        this.nodeTreesCount++;
        }
      else {
        console.log("E");
        throw new Error("TTT");
      }        
      this.addNodeToArray(node);
        }
    };

Použití:
var graph = new Springy.Graph(params);
graph.addNodes( null, ['Nejoblíbenější kruhy'], true);
graph.addNodes("Nejoblíbenější kruhy", ['Jedna', 'Dva'], true);
Vytvoř hlavní uzel Nejoblíbenější kruhy a pak jeho rodiče Jedna, Dva. Měly by pak být vidět, ale teď řeším problém se zacyklením. Zamrzne to a já nevím proč.

Výstup v konzole:
"C" springy.js:223
Error: TTT springy.js:235
Kódování znaků dokumentu HTML nebylo definováno. Pokud dokument obsahuje znaky mimo rozsah US-ASCII, může se při určitých nastavení prohlížeče zobrazovat se zkomoleným textem. Kódování znaků stránky je potřeba definovat na úrovni přenosového protokolu nebo v dokumentu. simple.html

Error: TTT
"C"
"ADD TREE" springy.js:120
"A" springy.js:228
"B" springy.js:212
"parent id: 0" springy.js:213
"C" springy.js:223
"ADDING CHILD" springy.js:115
"E"

Pokud bych zrušil
throw new Error("TTT");
tak se to zacyklí.


Pak následuje jeho funkce addEdge. Pak moje funkce na obrázky:

  Graph.prototype.addImage = function(image) {    
    if (typeof image !== 'object' )
      throw new TypeError("invalid argument #2, is wrong type. Expected 'object' in function newImage. id: " + id);
    var exists = false;
    this.images.forEach(function(i) {
            if (image.id === i.id) { exists = true; }
        });

        if (!exists) {
            this.images.push(image);
        }
    this.nodeSet[image.id].data.image={src:image.source};
    // console.log(this.nodeSet[image.id].data);
    
    this.notify();
    return image;
    };

Pak je tam jeho funkce addEdges a pak moje addImages:

Graph.prototype.addImages = function() {
    // accepts label as identificator and src string  
    for (var i = 0; i < arguments.length; i++) {
      // translate lable to id
      var label=arguments[i][0];
      var id = this.nodeIds[label];
      var src=this.imagePath + arguments[i][1] + this.imageType;
            this.newImage(id, src);
        }
    };

Pak jeho .newEdge a pak moje:
    Graph.prototype.newImage = function(id, source) {   
    var image = new ImagE(id, source);
        this.addImage(image);
        return image;
    };
To je myslím vše ze změn které jsem udělal. Pak už jen v springyui.js ohledně vykreslování a konfigurace.
návštěvník
Profil *
Teď jsem teprve zjistil že Firebug obsahuje debuger :-) Tak to je tada prima. Teď koukám na ten kód v debugeru, jak tam strkám zarážky a najednou to vidím úplně jasně. Mám tam dva vnořené cykly a oba používají stejnou proměnnou i. Ve funkci AddNodes. Tak jsem to opravil a už se to nezacyklovává.

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: