Сохранить и загрузить блок-схему на jsPlumb
каков наилучший подход для сохранения и загрузки блок-схемы на jsPlumb?
5 ответов
мне удалось сохранить диаграмму, просто имея все элементы внутри массив объектов, где каждый объект имеет источник и целевые узлы, координаты x, y.
при сохранении, просто делать JSON.stringify(whole_object)
, и если загрузка, просто JSON.parse()
и вручную расположите узлы, а также подключите их.
мое решение сохранить и загрузить 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/
Примечание: если демо не работает в JsFiddle, убедитесь, что он указывает на существующую ссылку jsPlumb (ссылки перечислены в пункте меню "внешние ресурсы" jsfiddle
мои функции сохранения делают немного больше, чем просто сохранить положение X, y элемента и его соединений. Я также добавил сохранение наложения метки соединения, а также пользовательский текст для каждого элемента. Вы можете адаптировать это решение в соответствии с вашими требованиями, но здесь это в основном:
//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;
}
я инициирую все это, когда пользователь нажимает кнопку сохранения, вызов ajax возвращается на сервер, в этом случае Django перехватывает запрос ajax и сохраняет данные в база данных.
//ajax вызов при нажатии кнопки сохранения $save_btn.щелкните (функция () {
//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?
});
загрузить все это еще проще, и есть много способов сделать это. В Django вы можете просто генерировать html прямо в своем шаблоне, а также js для соединений или вы можете создать объект JSON в javascript для всего, а затем javascript нарисовать все это на основе массива. Для этого я использовал jquery.
//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 %}
вы может значительно упростить это, но mine также получает фон для элемента, а также метку и форму элемента для использования с анкерами периметра. Это решение работает и тестируется. Я скоро выпущу приложение Djago с открытым исходным кодом для этого на PyPi.
недавно я написал это сообщение в блоге о том, почему у jsPlumb нет функции сохранения (и что я рекомендую вам сделать):
http://jsplumb.tumblr.com/post/11297005239/why-doesnt-jsplumb-offer-a-save-function
...может, кому-нибудь это пригодится.
Я использую YUI с ним. Я сохраняю положение каждого элемента коробки, подключенного в таблице. У них есть отдельная таблица, в которой хранится отношение родителя к потомку между элементами, которое используется для определения линий jsPlumb. Я определяю это с помощью процесса выбора, в котором первый выбранный элемент является родительским, а все остальные элементы-дочерними. При нажатии кнопки "подключить" Родительский / дочерний выбор элементов очищается. Я также переключаю это, если вы нажмите на выбранный Родительский - понять выбор ребенка.