2013-03-04 24 views
11

Próbuję ustalić sposób dodawania punktów końcowych punktów końcowych dynamicznie do kontenera jsPlumb.jsPlumb - dynamiczne punkty końcowe z każdej strony

Chciałbym mieć końcowe punkty źródłowe po lewej stronie i docelowe punkty końcowe tylko po prawej stronie.

Problem polega na tym, że nie byłem w stanie znaleźć żadnego sposobu, aby to zrobić, bez uciekania się do niektórych hacków, tak jak teraz.

jsPlumb obsługuje Continuous Anchors, ale pozycja poszczególnych kotwic zostanie ponownie obliczona na podstawie orientacji między łącznikami i liczby kotew ciągłych. Oznacza to, że zarówno źródłowe, jak i docelowe punkty końcowe mogą współdzielić tę samą stronę kontenera, jest to coś, czego chciałbym uniknąć.

Oto jsFiddler code I came up with

Oto część kodu używam włamać i przeliczyć kotwica pozycjonuje się (przy kliknięciu przycisku Dodaj), z niektórymi wynikami buggy :(

function fixEndpoints(endpoints) { 

      //there are 2 types - input and output 

      var inputAr = $.grep(endpoints, function (elementOfArray, indexInArray) { 
       return elementOfArray.isSource; //input 
      }); 

      var outputAr = $.grep(endpoints, function (elementOfArray, indexInArray) { 
       return elementOfArray.isTarget; //output 
      }); 

      calculateEndpoint(inputAr, true); 
      calculateEndpoint(outputAr, false); 
     } 

     function calculateEndpoint(endpointArray, isInput) { 

      //multiplyer 
      var mult = 1/endpointArray.length; 

      for (var i = 0; i < endpointArray.length; i++) { 

       if (isInput) { 
        endpointArray[i].anchor.x = 1; 
        endpointArray[i].anchor.y = mult * i;//, 1, 0] }; 
       } 
       else { 
        endpointArray[i].anchor.x = 0; 
        endpointArray[i].anchor.y = mult * i;//, -1, 0] }; 
       } 
      } 
     } 



     //Add additional anchor 
     $(".button_add").live("click", function() { 

      var parentnode = $(this)[0].parentNode.parentNode; 

      jsPlumb.addEndpoint(
       parentnode, 
       anEndpointSource 
      ); 

      jsPlumb.addEndpoint(
       parentnode, 
       anEndpointDestination 
      ); 

      //get list of current endpoints 
      var endpoints = jsPlumb.getEndpoints(parentnode); 

      //fix endpoints 
      fixEndpoints(endpoints); 

      jsPlumb.recalculateOffsets(); 
      jsPlumb.repaint(parentnode); 
     }); 

Expected result

Jak widać na powyższym obrazie, lewa strona ma tylko końcowe punkty źródłowe (Dot) i docelowe punkty końcowe tylko z prawej strony (Box), po dodaniu nowego punktu końcowego kotwice są ponownie obliczane na podstawie liczby zakotwiczeń na e stronie.

Działa to, ale nadal jest błędna: pozycja jest aktualizowana tylko raz, gdy przeniesię kontener, a połączenie między kontenerami również nie jest poprawne.

Co chciałbym mieć, jest sposobem na to, aby pracować i połączyć elementy prawidłowo (najlepiej przy użyciu prawidłowego kodu jsPlumb bez uciekania się do sztuczek)

Odpowiedz

11

I w końcu zorientowali się, jak to zrobić. To było łatwiejsze niż myślałem.

Code jest zasadniczo taka sama, z kilkoma zmianami, here is updated fiddler sample

<!DOCTYPE html> 
<html> 
<head> 
<title>JS plumb test</title> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script> 
    <script type="text/javascript" src="./include/jquery.jsPlumb-1.3.16-all-min.js"></script> 

<style> 
    .window { 
     background-color: #EEEEEF; 
     border: 1px solid #346789; 
     border-radius: 0.5em; 
     box-shadow: 2px 2px 5px #AAAAAA; 
     color: black; 
     height: 5em; 
     position: absolute; 
     width: 5em; 
    } 

    .window:hover { 
     box-shadow: 2px 2px 19px #AAAAAA; 
     cursor: pointer; 
    } 


    .button_add, .button_add_window, .button_remove, .button { 
     background-color: deepskyblue; 
     text-align: center; 
     border: 1px solid; 
    } 

    .button_container { 
     margin: 5px; 
     background-color: #aaaaaa 
    } 
</style> 

<script> 

    jsPlumb.ready(function() { 


     //FIX DOM: 
     $(("#container1"))[0].innerHTML = $(("#container0"))[0].innerHTML; 

     //all windows are draggable 
     jsPlumb.draggable($(".window")); 


     var anEndpointSource = { 
      endpoint: "Rectangle", 
      isSource: true, 
      isTarget: false, 
      maxConnections: 1, 

      anchor: [1, 0, 1, 0] 
     }; 

     var anEndpointDestination = { 
      endpoint: "Dot", 
      isSource: false, 
      isTarget: true, 
      maxConnections: 1, 

      anchor: [0, 1, -1, 0] 
     }; 


     //Fixes endpoints for specified target 
     function fixEndpoints(parentnode) { 

      //get list of current endpoints 
      var endpoints = jsPlumb.getEndpoints(parentnode); 

      //there are 2 types - input and output 

      var inputAr = $.grep(endpoints, function (elementOfArray, indexInArray) { 
       return elementOfArray.isSource; //input 
      }); 

      var outputAr = $.grep(endpoints, function (elementOfArray, indexInArray) { 
       return elementOfArray.isTarget; //output 
      }); 

      calculateEndpoint(inputAr, true); 
      calculateEndpoint(outputAr, false); 

      jsPlumb.repaintEverything(); 
     } 

     //recalculate endpoint anchor position manually 
     function calculateEndpoint(endpointArray, isInput) { 

      //multiplyer 
      var mult = 1/(endpointArray.length+1); 

      for (var i = 0; i < endpointArray.length; i++) { 

       if (isInput) { 

        //position 
        endpointArray[i].anchor.x = 1; 
        endpointArray[i].anchor.y = mult * (i + 1); 
       } 
       else { 

        //position 
        endpointArray[i].anchor.x = 0; 
        endpointArray[i].anchor.y = mult * (i + 1); 
       } 
      } 
     } 



     //Add additional anchor 
     $(".button_add").live("click", function() { 

      var parentnode = $(this)[0].parentNode.parentNode; 

      jsPlumb.addEndpoint(
       parentnode, 
       anEndpointSource 
      ); 

      jsPlumb.addEndpoint(
       parentnode, 
       anEndpointDestination 
      ); 

      fixEndpoints(parentnode); 
     }); 

     //Remove anchor 
     $(".button_remove").live("click", function() { 

      var parentnode = $(this)[0].parentNode.parentNode; 

      //get list of current endpoints 
      var endpoints = jsPlumb.getEndpoints(parentnode); 

      //remove 2 last one 

      if (endpoints.length > 1) { 
       jsPlumb.deleteEndpoint(endpoints[endpoints.length - 2]); 
      } 

      if (endpoints.length > 0) { 
       jsPlumb.deleteEndpoint(endpoints[endpoints.length - 1]); 
      } 

      fixEndpoints(parentnode); 
     }); 


     //adds new window 
     $(".button_add_window").click(function() { 

      var id = "dynamic_" + $(".window").length; 

      //create new window and add it to the body 
      $('<div class="window" id="' + id + '" >').appendTo('body').html($(("#container0"))[0].innerHTML); 

      //set jsplumb properties 
      jsPlumb.draggable($('#' + id)); 
     }); 
    }); 
</script> 

</head> 
<body > 

    <!-- Adds new windows to the page --> 
    <div class="window" style="left: 600px" id="details"> 
     <p style="text-align: center">Window</p> 
     <div class="button_container"> 
      <div class="button_add_window">Add</div> 
     </div> 
    </div> 

    <!-- Primary window - used as html templated for descendants --> 
    <div class="window" style="left: 20px" id="container0"> 
     <div class="button_container"> 
      <div class="button_add">Add</div> 
      <div class="button_remove">Remove</div> 
     </div> 
    </div> 

    <div class="window" style="left: 200px" id="container1"> 
    </div> 


</body> 
</html> 

Zmiany, które zrobiłem:

  1. Teraz określić punkt końcowy kotwica przesunięcie kiedy dodać, ja tylko obliczyć położenie kotwicy , więc przesunięcie nigdy się nie zmienia, zawsze jest poprawne od początku:

    var anEndpointSource = { 
        endpoint: "Rectangle", 
        isSource: true, 
        isTarget: false, 
        maxConnections: 1, 
    
        anchor: [1, 0, 1, 0] 
    }; 
    
  2. Po końcowym dodaje, ja obliczać pozycje kotwiczne i połączeń (to będzie przemalować połączenia):

    jsPlumb.repaintEverything();

Oto efekt końcowy:

endpoints correctly connected

+0

bardzo dobrze zrobione :) Czy istnieje sposób, aby "usunąć" również (wybrany) węzeł? I tr, aby utworzyć edytor maszyn stanowych w/jsplumb, ale po prostu walcząc w/dynamicznie dodawać/usuwać węzły i połączenia. A jsfiddle byłby taki świetny :) – Dominik

0

Ty można usuwać stany poprzez dwukrotne kliknięcie, dodając

     newState.dblclick(function(e) { 
         alert("This will delete the state and its connections"); 
         instance.detachAllConnections($(this)); 
         $(this).remove(); 
         e.stopPropagation(); 
        }); 

Funkcja do funkcji jsPlumb.ready.można dodać to do wszystkich państw dodając

var windows = jsPlumb.getSelector(".statemachine-demo .state"); 
      windows.dblclick(function(e) { 
      alert("This will delete the state and its connections"); 
      instance.detachAllConnections($(this)); 
      $(this).remove(); 
      e.stopPropagation(); 
     }); 

tutaj Statemachine-demo jest identyfikator div w contaner i stan jest klasa div państwowych.

0

dziękuję za rozwiązanie, działa dobrze, gdy strona kotwicy jest predefiniowana, tak jak tutaj źródła są zawsze po lewej stronie, a cele są zawsze po prawej stronie.

Ale jeśli są one dynamiczne, musimy również dokonać selekcji strony przez siebie?

Jako obejście ustawiłem więcej możliwych pozycji zakotwiczenia w domyślnej konfiguracji. Masz lepszy pomysł?

dziękuję

Powiązane problemy