Wie speichert und lädt man am besten ein Flussdiagramm auf jsPlumb ?
Antworten
Zu viele Anzeigen?Ich habe es geschafft, das Diagramm zu speichern, indem ich einfach alle Elemente in einem Array von Objekten gespeichert habe, wobei jedes Objekt eine 根源 y Zielknoten, x- und y-Koordinaten .
Wenn Sie speichern, tun Sie einfach JSON.stringify(whole_object)
und beim Laden einfach JSON.parse()
und positionieren Sie die Knoten manuell und verbinden Sie sie.
Meine Lösung speichert und lädt jsPlumb:
function Save() {
$(".node").resizable("destroy");
Objs = [];
$('.node').each(function() {
Objs.push({id:$(this).attr('id'), html:$(this).html(),left:$(this).css('left'),top:$(this).css('top'),width:$(this).css('width'),height:$(this).css('height')});
});
console.log(Objs);
}
function Load() {
var s="";
for(var i in Objs) {
var o = Objs[i];
console.log(o);
s+='<div id="'+ o.id+'" class="node" style="left:'+ o.left+'; top:'+ o.top+'; width:'+ o.width +'; height:'+ o.height +' "> '+ o.html+'</div>';
}
$('#main').html(s);
}
UPD-Demo: http://jsfiddle.net/Rra6Y/137/
Hinweis: Wenn die Demo in JsFiddle nicht funktioniert, vergewissern Sie sich, dass sie auf einen bestehenden jsPlumb-Link verweist (Links sind im JsFiddle-Menüpunkt "Externe Ressourcen" aufgeführt)
Meine Speicherfunktionalität tut ein bisschen mehr als nur die x- und y-Position des Elements und seine Verbindungen zu speichern. Ich habe auch das Speichern einer Verbindung Label Overlay sowie benutzerdefinierten Text für jedes Element. Sie können diese Lösung wie pro Ihre Anforderungen anpassen, aber hier ist es im Grunde:
//save functionality
function IterateDrawnElements(){ //part of save
var dict = {};
$('#id_diagram_container').children('div.window').each(function () {
var pos = $(this).position()
var diagram_label = $(this).children('div.asset-label').children('div.asset-diagram-label').text()
if (diagram_label == null || diagram_label == ''){
diagram_label='';
}
dict[this.id] = [pos.left, pos.top, diagram_label];
});
return dict;
}
function IterateConnections(){ //part of save
var list = [];
var conns = jsPlumb.getConnections()
for (var i = 0; i < conns.length; i++) {
var source = conns[i].source.id;
var target = conns[i].target.id;
try{
var label = conns[i].getOverlay("label-overlay").labelText;
}
catch(err) {
label = null
}
//list.push([source, target])
if (source != null && target != null){
list.push([source, target, label]);
};
}
return list;
}
Ich initiiere all dies, wenn der Benutzer auf die Schaltfläche "Speichern" drückt, wird ein Ajax-Aufruf zurück an den Server gemacht, in diesem Fall ist Django die Ajax-Anfrage abfangen und speichert die Daten in der Datenbank.
//Ajax-Aufruf bei Betätigung der Schaltfläche "Speichern $save_btn.click(function() {
//drawn elements
var d_elements = IterateDrawnElements();
var d_conns = IterateConnections();
var d_name =$('#id_diagram_name').val();
$.ajax({
url : ".",
type : "POST",
dataType: "json",
data : {
drawn_elements: JSON.stringify(d_elements),
conns: JSON.stringify(d_conns),
diagram_name: d_name,
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (result) {
if (result.success == true){
save_status.html(result.message)
}
//console.log(JSON.stringify(result));
$save_btn.attr('disabled','disabled');
if (result.old_name != false){
//alert()
$('#id_diagram_name').val(result.old_name)
}
},
error: function(xhr, textStatus, errorThrown) {
alert("Please report this error: "+errorThrown+xhr.status+xhr.responseText);
}
});
//return false; // always return error?
});
All dies zu laden ist noch einfacher und es gibt viele Möglichkeiten, dies zu tun. In Django können Sie einfach die html direkt in Ihrer Vorlage sowie die js für die Verbindungen generieren oder Sie können ein JSON-Objekt in Javascript für alles erstellen und dann haben Javascript zeichnen sie alle auf der Grundlage des Arrays. Ich habe jquery für diese.
//js & connections load
var asset_conns = [
{% for conn in diagram_conns %}
[ {{ conn.source.id }}, {{ conn.target.id }}, '{{ conn.name }}' ],
{% endfor %}
]
// Takes loaded connections and connects them
for (var i = 0; i< asset_conns.length; i++){
var source = asset_conns[i][0].toString();
var target = asset_conns[i][1].toString();
var label = asset_conns[i][2];
var c = jsPlumb.connect({source: source, target: target, detachable:true, reattach: true }); //on init already know what kind of anchor to use!
if (label != null && label != 'None'){
c.addOverlay([ "Label", { label: label, id:"label-overlay"} ]);
}
}
//html right into django template to draw elements, asset element interchangeable terms
{% for element in drawn_elements %}
<div id="{{ element.asset.id }}" class="window" style="left:{{ element.left }}px;top:{{ element.top }}px;background-image: url('{% static element.asset.asset_mold.image.url %}'); width: {{ element.asset.asset_mold.image.width }}px;height: {{ element.asset.asset_mold.image.height }}px;">
<div class="asset-label" id="label-{{ element.asset.id }}">
{#{{ element.asset }}#}<a class="lbl-link" id="lbl-link-{{ element.asset.id }}" href="{{ element.asset.get_absolute_url }}">{{ element.asset }}</a>
<div class='asset-diagram-label' id="lbl-{{ element.asset.id }}">{% if element.asset.diagram_label %}{{ element.asset.diagram_label }}{% endif %}</div>
</div>
<div class='ep' id="ep-{{ element.asset.id }}"></div>
</div>
{% endfor %}
Sie können dies stark vereinfachen, aber meine erhält auch einen Hintergrund für das Element sowie eine Beschriftung und die Form des Elements zur Verwendung mit Begrenzungsankern. Diese Lösung funktioniert und ist getestet. Ich werde demnächst eine Open-Source-Djago-Anwendung für diese Lösung auf PyPi veröffentlichen.
Ich verwende YUI damit. Ich speichere die Position jedes Feldes Element in einer Tabelle verbunden werden. Ich habe sie eine separate Tabelle die speichert eine Eltern-Kind-Beziehung zwischen den Elementen, die verwendet wird, um die Linien jsPlumb zeichnen sollte zu bestimmen. Ich bestimme dies durch einen Auswahlprozess, bei dem das erste ausgewählte Element das übergeordnete Element ist und alle anderen Elemente untergeordnete Elemente sind. Wenn die Schaltfläche "Verbinden" angeklickt wird, wird die Eltern/Kind-Auswahl der Elemente aufgehoben. Wenn Sie auf das ausgewählte übergeordnete Element klicken, wird auch die Auswahl der untergeordneten Elemente gelöscht.
Ich habe kürzlich diesen Blogbeitrag darüber geschrieben, warum jsPlumb keine Speicherfunktion hat (und was ich Ihnen empfehle):
http://jsplumb.tumblr.com/post/11297005239/why-doesnt-jsplumb-offer-a-save-function
...vielleicht findet sie ja jemand nützlich.