Commit fa89e89d authored by Jérome Perrin's avatar Jérome Perrin

update static version

parent 84ce9458
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
(function(window, rJS, RSVP, loopEventListener) { (function(window, rJS, RSVP, loopEventListener) {
"use strict"; "use strict";
var gadget_klass = rJS(window); var gadget_klass = rJS(window);
// TODO: save on parent gadget
function saveGraph(evt) { function saveGraph(evt) {
var gadget = this; var gadget = this;
return new RSVP.Queue().push(function() { return new RSVP.Queue().push(function() {
...@@ -11,23 +12,12 @@ ...@@ -11,23 +12,12 @@
} }
return gadget.getDeclaredGadget("productionline_graph"); return gadget.getDeclaredGadget("productionline_graph");
}).push(function(graph_gadget) { }).push(function(graph_gadget) {
return graph_gadget.getData(); return graph_gadget.getContent();
}).push(function(data) {
graph_data = data;
// Always get a fresh version, to prevent deleting spreadsheet & co
return gadget.aq_getAttachment({
_id: gadget.props.jio_key,
_attachment: "body.json"
});
}).push(function(body) { }).push(function(body) {
var data = JSON.parse(body), json_graph_data = JSON.parse(graph_data);
data.nodes = json_graph_data.nodes;
data.edges = json_graph_data.edges;
data.preference = json_graph_data.preference;
return gadget.aq_putAttachment({ return gadget.aq_putAttachment({
_id: gadget.props.jio_key, _id: gadget.props.jio_key,
_attachment: "body.json", _attachment: "body.json",
_data: JSON.stringify(data, null, 2), _data: JSON.stringify(JSON.parse(body), null, 2),
_mimetype: "application/json" _mimetype: "application/json"
}); });
}).push(function() { }).push(function() {
...@@ -56,7 +46,7 @@ ...@@ -56,7 +46,7 @@
} }
this.timeout = window.setTimeout(saveGraph.bind(this), 100); this.timeout = window.setTimeout(saveGraph.bind(this), 100);
}).declareMethod("render", function(options) { }).declareMethod("render", function(options) {
var jio_key = options.id, gadget = this; var jio_key = options.id, gadget = this, data;
gadget.props.jio_key = jio_key; gadget.props.jio_key = jio_key;
return new RSVP.Queue().push(function() { return new RSVP.Queue().push(function() {
/*jslint nomen: true*/ /*jslint nomen: true*/
...@@ -65,11 +55,12 @@ ...@@ -65,11 +55,12 @@
_attachment: "body.json" _attachment: "body.json"
}), gadget.getDeclaredGadget("productionline_graph") ]); }), gadget.getDeclaredGadget("productionline_graph") ]);
}).push(function(result_list) { }).push(function(result_list) {
return result_list[1].render(result_list[0]); data = result_list[0];
return result_list[1].render(data);
}).push(function() { }).push(function() {
return gadget.getDeclaredGadget("productionline_toolbox"); return gadget.getDeclaredGadget("productionline_toolbox");
}).push(function(toolbox_gadget) { }).push(function(toolbox_gadget) {
toolbox_gadget.render(); toolbox_gadget.render(data);
}); });
}).declareMethod("startService", function() { }).declareMethod("startService", function() {
var g = this, graph; var g = this, graph;
......
...@@ -9,47 +9,39 @@ ...@@ -9,47 +9,39 @@
// Precompile the templates while loading the first gadget instance // Precompile the templates while loading the first gadget instance
var gadget_klass = rJS(window), source = gadget_klass.__template_element.getElementById("label-template").innerHTML, label_template = Handlebars.compile(source); var gadget_klass = rJS(window), source = gadget_klass.__template_element.getElementById("label-template").innerHTML, label_template = Handlebars.compile(source);
initGadgetMixin(gadget_klass); initGadgetMixin(gadget_klass);
gadget_klass.declareMethod("render", function(property_list, data, key) { gadget_klass.declareMethod("render", function(options, node_id) {
var gadget = this, queue, value, property; // XXX node_id is added like a property so that one can change the node
gadget.key = key; // id
var gadget = this, queue;
gadget.props.key = options.key;
// used for recursive fieldsets // used for recursive fieldsets
gadget.props.field_gadget_list = []; gadget.props.field_gadget_list = [];
function addField(property, value) { function addField(property_id, property_definition, value) {
var sub_gadget; var sub_gadget;
queue.push(function() { queue.push(function() {
// XXX this is incorrect for recursive fieldsets. // XXX this is incorrect for recursive fieldsets.
// we should use nested fieldset with legend // we should use nested fieldset with legend
gadget.props.element.insertAdjacentHTML("beforeend", label_template({ gadget.props.element.insertAdjacentHTML("beforeend", label_template({
"for": property.id, "for": property_id,
name: property.name || property.id name: property_definition.name || property_id
})); }));
if (property._class === "Dream.PropertyList") { if (property_definition.type === "object") {
// Create a recursive fieldset for this key. // Create a recursive fieldset for this key.
return gadget.declareGadget("../fieldset/index.html"); return gadget.declareGadget("../fieldset/index.html");
} }
if (property.type === "number") { if (property_definition.type === "number") {
return gadget.declareGadget("../number_field/index.html"); return gadget.declareGadget("../number_field/index.html");
} }
if (property.choice) { if (property_definition.enum) {
return gadget.declareGadget("../list_field/index.html"); return gadget.declareGadget("../list_field/index.html");
} }
return gadget.declareGadget("../string_field/index.html"); return gadget.declareGadget("../string_field/index.html");
}).push(function(gg) { }).push(function(gg) {
sub_gadget = gg; sub_gadget = gg;
var choice = property.choice || [], default_opt = choice[0] ? [ choice[0][1] ] : [ "" ];
value = data[property.id] === undefined ? value : data[property.id];
if (gg.__title === "Fieldset") {
// XXX there must be a better way instead of using __title ?
return gg.render(property.property_list, value, property.id);
}
return sub_gadget.render({ return sub_gadget.render({
field_json: { key: property_id,
title: property.description || "",
key: property.id,
value: value, value: value,
items: choice, property_definition: property_definition
"default": default_opt
}
}); });
}).push(function() { }).push(function() {
return sub_gadget.getElement(); return sub_gadget.getElement();
...@@ -59,10 +51,17 @@ ...@@ -59,10 +51,17 @@
}); });
} }
queue = new RSVP.Queue().push(function() { queue = new RSVP.Queue().push(function() {
Object.keys(property_list).forEach(function(i) { if (node_id) {
property = property_list[i]; addField("id", {
value = property._default === undefined ? "" : property._default; type: "string"
addField(property, value); }, node_id);
}
Object.keys(options.property_definition.properties).forEach(function(property_name) {
var property_definition = options.property_definition.properties[property_name], value = (options.value || {})[property_name] === undefined ? property_definition._default : options.value[property_name];
// XXX some properties are not editable
if (property_name !== "coordinate" && property_name !== "_class") {
addField(property_name, property_definition, value);
}
}); });
}); });
return queue; return queue;
...@@ -75,8 +74,8 @@ ...@@ -75,8 +74,8 @@
return RSVP.all(promise_list); return RSVP.all(promise_list);
}).push(function(result_list) { }).push(function(result_list) {
var name, result = {}, content = result; var name, result = {}, content = result;
if (gadget.key) { if (gadget.props.key) {
content = result[gadget.key] = {}; content = result[gadget.props.key] = {};
} }
for (i = 0; i < result_list.length; i += 1) { for (i = 0; i < result_list.length; i += 1) {
for (name in result_list[i]) { for (name in result_list[i]) {
......
...@@ -7,9 +7,10 @@ ...@@ -7,9 +7,10 @@
<script src="../lib/jquery.js"></script> <script src="../lib/jquery.js"></script>
<script src="../lib/jquery-ui.js"></script> <script src="../lib/jquery-ui.js"></script>
<script src="../lib/jquerymobile.js"></script>
<script src="../lib/rsvp.min.js"></script> <script src="../lib/rsvp.min.js"></script>
<script src="../lib/renderjs.min.js"></script> <script src="../lib/renderjs.min.js"></script>
<script src="../lib/jquery.jsplumb.min.js"></script> <script src="../lib/jquery.jsplumb.js"></script>
<script src="../lib/handlebars.min.js"></script> <script src="../lib/handlebars.min.js"></script>
<script id="node-template" type="text/x-handlebars-template"> <script id="node-template" type="text/x-handlebars-template">
......
...@@ -18,10 +18,26 @@ ...@@ -18,10 +18,26 @@
* ==========================================================================*/ * ==========================================================================*/
/*global RSVP, rJS, $, jsPlumb, Handlebars, initGadgetMixin, /*global RSVP, rJS, $, jsPlumb, Handlebars, initGadgetMixin,
loopEventListener, promiseEventListener, DOMParser, confirm */ loopEventListener, promiseEventListener, DOMParser, confirm */
/*jslint unparam: true */ /*jslint unparam: true todo: true */
(function(RSVP, rJS, $, jsPlumb, Handlebars, initGadgetMixin, loopEventListener, promiseEventListener, DOMParser) { (function(RSVP, rJS, $, jsPlumb, Handlebars, initGadgetMixin, loopEventListener, promiseEventListener, DOMParser) {
"use strict"; "use strict";
/*jslint nomen: true*/ /*jslint nomen: true */
/* TODO:
* - make node edition popup a gadget ?
* - add function to turn event handlers in promise ?
*
* tests:
* - loading & saving DONE
* - dropping a new node from palette DONE
* - dragging a node
* - editing node properties with popup (make sure we can display after
* edit)
* - connecting two nodes
* - removing a connection
* - removing a node ( make sure connections are removed )
* - changing a node id ( make sure connections are updated ) ( make sure
* we can display after edit )
*/
var gadget_klass = rJS(window), node_template_source = gadget_klass.__template_element.getElementById("node-template").innerHTML, node_template = Handlebars.compile(node_template_source), popup_edit_template = gadget_klass.__template_element.getElementById("popup-edit-template"), domParser = new DOMParser(); var gadget_klass = rJS(window), node_template_source = gadget_klass.__template_element.getElementById("node-template").innerHTML, node_template = Handlebars.compile(node_template_source), popup_edit_template = gadget_klass.__template_element.getElementById("popup-edit-template"), domParser = new DOMParser();
function loopJsplumbBind(gadget, type, callback) { function loopJsplumbBind(gadget, type, callback) {
////////////////////////// //////////////////////////
...@@ -40,7 +56,7 @@ ...@@ -40,7 +56,7 @@
} }
cancelResolver(); cancelResolver();
} }
function itsANonResolvableTrap(resolve, reject) { function resolver(resolve, reject) {
handle_event_callback = function() { handle_event_callback = function() {
var args = arguments; var args = arguments;
cancelResolver(); cancelResolver();
...@@ -55,29 +71,29 @@ ...@@ -55,29 +71,29 @@
}; };
jsplumb_instance.bind(type, handle_event_callback); jsplumb_instance.bind(type, handle_event_callback);
} }
return new RSVP.Promise(itsANonResolvableTrap, canceller); return new RSVP.Promise(resolver, canceller);
} }
function getNodeId(node_container, element_id) { function getNodeId(gadget, element_id) {
// returns the ID of the node in the graph from its DOM element id
var node_id; var node_id;
$.each(node_container, function(k, v) { $.each(gadget.props.node_id_to_dom_element_id, function(k, v) {
if (v.element_id === element_id) { if (v === element_id) {
node_id = k; node_id = k;
return false; return false;
} }
}); });
return node_id; return node_id;
} }
function getElementId(node_container, node_id) { function generateNodeId(gadget, element) {
return node_container[node_id].element_id; // Generate a node id
} var n = 1, class_def = gadget.props.data.class_definition[element._class], id = class_def.short_id || element._class;
function generateNodeId(gadget, element_type, option) { while (gadget.props.data.graph.node[id + n] !== undefined) {
var n = 1;
while (gadget.props.node_container[(option.short_id || element_type) + n] !== undefined) {
n += 1; n += 1;
} }
return (option.short_id || element_type) + n; return id + n;
} }
function generateElementId(gadget_element) { function generateDomElementId(gadget_element) {
// Generate a probably unique DOM element ID.
var n = 1; var n = 1;
while ($(gadget_element).find("#DreamNode_" + n).length > 0) { while ($(gadget_element).find("#DreamNode_" + n).length > 0) {
n += 1; n += 1;
...@@ -86,9 +102,14 @@ ...@@ -86,9 +102,14 @@
} }
function updateConnectionData(gadget, connection, remove, edge_data) { function updateConnectionData(gadget, connection, remove, edge_data) {
if (remove) { if (remove) {
delete gadget.props.edge_container[connection.id]; delete gadget.props.data.graph.edge[connection.id];
} else { } else {
gadget.props.edge_container[connection.id] = [ getNodeId(gadget.props.node_container, connection.sourceId), getNodeId(gadget.props.node_container, connection.targetId), edge_data || {} ]; edge_data = edge_data || {
_class: "Dream.Edge"
};
edge_data.source = getNodeId(gadget, connection.sourceId);
edge_data.destination = getNodeId(gadget, connection.targetId);
gadget.props.data.graph.edge[connection.id] = edge_data;
} }
gadget.notifyDataChanged(); gadget.notifyDataChanged();
} }
...@@ -105,6 +126,7 @@ ...@@ -105,6 +126,7 @@
}); });
} }
function waitForConnectionClick(gadget) { function waitForConnectionClick(gadget) {
// TODO: dialog to edit connection properties
loopJsplumbBind(gadget, "click", function(connection) { loopJsplumbBind(gadget, "click", function(connection) {
if (confirm("Delete connection ?")) { if (confirm("Delete connection ?")) {
gadget.props.jsplumb_instance.detach(connection); gadget.props.jsplumb_instance.detach(connection);
...@@ -112,30 +134,30 @@ ...@@ -112,30 +134,30 @@
}); });
} }
function convertToAbsolutePosition(gadget, x, y) { function convertToAbsolutePosition(gadget, x, y) {
var zoom_level = (gadget.props.preference_container.zoom_level || 1) * 1.1111, canvas_size_x = $(gadget.props.element).find("#main").width(), canvas_size_y = $(gadget.props.element).find("#main").height(), size_x = $(gadget.props.element).find(".dummy_window").width() * zoom_level, size_y = $(gadget.props.element).find(".dummy_window").height() * zoom_level, top = Math.floor(y * (canvas_size_y - size_y)) + "px", left = Math.floor(x * (canvas_size_x - size_x)) + "px"; var zoom_level = gadget.props.zoom_level * 1.1111, canvas_size_x = $(gadget.props.element).find("#main").width(), canvas_size_y = $(gadget.props.element).find("#main").height(), size_x = $(gadget.props.element).find(".dummy_window").width() * zoom_level, size_y = $(gadget.props.element).find(".dummy_window").height() * zoom_level, top = Math.floor(y * (canvas_size_y - size_y)) + "px", left = Math.floor(x * (canvas_size_x - size_x)) + "px";
return [ left, top ]; return [ left, top ];
} }
function convertToRelativePosition(gadget, x, y) { function convertToRelativePosition(gadget, x, y) {
var zoom_level = (gadget.props.preference_container.zoom_level || 1) * 1.1111, canvas_size_x = $(gadget.props.element).find("#main").width(), canvas_size_y = $(gadget.props.element).find("#main").height(), size_x = $(gadget.props.element).find(".dummy_window").width() * zoom_level, size_y = $(gadget.props.element).find(".dummy_window").height() * zoom_level, top = Math.max(Math.min(y.replace("px", "") / (canvas_size_y - size_y), 1), 0), left = Math.max(Math.min(x.replace("px", "") / (canvas_size_x - size_x), 1), 0); var zoom_level = gadget.props.zoom_level * 1.1111, canvas_size_x = $(gadget.props.element).find("#main").width(), canvas_size_y = $(gadget.props.element).find("#main").height(), size_x = $(gadget.props.element).find(".dummy_window").width() * zoom_level, size_y = $(gadget.props.element).find(".dummy_window").height() * zoom_level, top = Math.max(Math.min(y.replace("px", "") / (canvas_size_y - size_y), 1), 0), left = Math.max(Math.min(x.replace("px", "") / (canvas_size_x - size_x), 1), 0);
return [ left, top ]; return [ left, top ];
} }
function updateElementCoordinate(gadget, node_id, coordinate) { function updateElementCoordinate(gadget, node_id, coordinate) {
var element_id = gadget.props.node_container[node_id].element_id, coordinates = gadget.props.preference_container.coordinates || {}, element, relative_position; var element_id = gadget.props.node_id_to_dom_element_id[node_id], element, relative_position;
if (coordinate === undefined) { if (coordinate === undefined) {
coordinate = {};
element = $(gadget.props.element).find("#" + element_id); element = $(gadget.props.element).find("#" + element_id);
relative_position = convertToRelativePosition(gadget, element.css("left"), element.css("top")); relative_position = convertToRelativePosition(gadget, element.css("left"), element.css("top"));
coordinate.top = relative_position[1]; coordinate = {
coordinate.left = relative_position[0]; left: relative_position[0],
top: relative_position[1]
};
} }
coordinates[node_id] = coordinate; gadget.props.data.graph.node[node_id].coordinate = coordinate;
gadget.props.preference_container.coordinates = coordinates;
gadget.notifyDataChanged(); gadget.notifyDataChanged();
return coordinate; return coordinate;
} }
function draggable(gadget) { function draggable(gadget) {
var jsplumb_instance = gadget.props.jsplumb_instance, stop = function(element) { var jsplumb_instance = gadget.props.jsplumb_instance, stop = function(element) {
updateElementCoordinate(gadget, getNodeId(gadget.props.node_container, element.target.id)); updateElementCoordinate(gadget, getNodeId(gadget, element.target.id));
}; };
jsplumb_instance.draggable(jsplumb_instance.getSelector(".window"), { jsplumb_instance.draggable(jsplumb_instance.getSelector(".window"), {
containment: "parent", containment: "parent",
...@@ -196,27 +218,14 @@ ...@@ -196,27 +218,14 @@
draggable(gadget); draggable(gadget);
} }
function updateNodeStyle(gadget, element_id) { function updateNodeStyle(gadget, element_id) {
var zoom_level = (gadget.props.preference_container.zoom_level || 1) * 1.1111, element = $(gadget.props.element).find("#" + element_id), new_value; // Update node size according to the zoom level
// XXX does nothing for now
var zoom_level = gadget.props.zoom_level * 1.1111, element = $(gadget.props.element).find("#" + element_id), new_value;
$.each(gadget.props.style_attr_list, function(i, j) { $.each(gadget.props.style_attr_list, function(i, j) {
new_value = $(gadget.props.element).find(".dummy_window").css(j).replace("px", "") * zoom_level + "px"; new_value = $(gadget.props.element).find(".dummy_window").css(j).replace("px", "") * zoom_level + "px";
element.css(j, new_value); element.css(j, new_value);
}); });
} }
function addElementToContainer(node_container, element) {
// Now update the container of elements
/*jslint nomen: true*/
var element_data = {
_class: element._class,
name: element.name,
element_id: element.element_id
};
Object.keys(element).forEach(function(k) {
if (k !== "_class" && k !== "name" && k !== "element_id") {
element_data[k] = element[k];
}
});
node_container[element.id] = element_data;
}
// function redraw(gadget) { // function redraw(gadget) {
// var coordinates = gadget.props.preference_container.coordinates || {}, // var coordinates = gadget.props.preference_container.coordinates || {},
// absolute_position, // absolute_position,
...@@ -228,7 +237,7 @@ ...@@ -228,7 +237,7 @@
// v.top // v.top
// ); // );
// element = $(gadget.props.element).find( // element = $(gadget.props.element).find(
// '#' + getElementId(gadget.props.node_container, node_id) // '#' + gadget.props.node_id_to_dom_element_id[node_id];
// ); // );
// element.css('top', absolute_position[1]); // element.css('top', absolute_position[1]);
// element.css('left', absolute_position[0]); // element.css('left', absolute_position[0]);
...@@ -259,107 +268,91 @@ ...@@ -259,107 +268,91 @@
// } // }
// ); // );
// } // }
// function setZoom(gadget, zoom_level) {
// $.each(gadget.props.style_attr_list, function (i, j) {
// var new_value = $(gadget.props.element).find('.dummy_window')
// .css(j).replace('px', '') * zoom_level + 'px';
// $(gadget.props.element).find('.window').css(j, new_value);
// });
// }
// function zoom_in(gadget) {
// var zoom_level = (gadget.props.preference_container.zoom_level || 1.0) *
// 1.1111;
// setZoom(gadget, zoom_level);
// gadget.props.preference_container.zoom_level = zoom_level;
// gadget.notifyDataChanged();
// redraw(gadget);
// }
// function zoom_out(gadget) {
// var zoom_level = (gadget.props.preference_container.zoom_level || 1.0) *
// 0.9;
// setZoom(gadget, zoom_level);
// gadget.props.preference_container.zoom_level = zoom_level;
// gadget.notifyDataChanged();
// redraw(gadget);
// }
function removeElement(gadget, node_id) { function removeElement(gadget, node_id) {
var element_id = gadget.props.node_container[node_id].element_id; var element_id = gadget.props.node_id_to_dom_element_id[node_id];
gadget.props.jsplumb_instance.removeAllEndpoints($(gadget.props.element).find("#" + element_id)); gadget.props.jsplumb_instance.removeAllEndpoints($(gadget.props.element).find("#" + element_id));
$(gadget.props.element).find("#" + element_id).remove(); $(gadget.props.element).find("#" + element_id).remove();
delete gadget.props.node_container[node_id]; delete gadget.props.data.graph.node[node_id];
delete gadget.props.preference_container.coordinates[node_id]; $.each(gadget.props.data.graph.edge, function(k, v) {
$.each(gadget.props.edge_container, function(k, v) { if (node_id === v.source || node_id === v.destination) {
if (node_id === v[0] || node_id === v[1]) { delete gadget.props.data.graph.edge[k];
delete gadget.props.edge_container[k];
} }
}); });
gadget.notifyDataChanged(); gadget.notifyDataChanged();
} }
function updateElementData(gadget, node_id, data) { function updateElementData(gadget, node_id, data) {
var element_id = gadget.props.node_container[node_id].element_id, new_id = data.id; var element_id = gadget.props.node_id_to_dom_element_id[node_id], new_id = data.id;
if (data.data.name) { if (data.data.name) {
$(gadget.props.element).find("#" + element_id).text(data.data.name).append('<div class="ep"></div></div>'); $(gadget.props.element).find("#" + element_id).text(data.data.name).append('<div class="ep"></div></div>');
gadget.props.node_container[node_id].name = data.data.name; gadget.props.data.graph.node[node_id].name = data.data.name;
} }
delete data.id; delete data.id;
$.extend(gadget.props.node_container[node_id], data.data); $.extend(gadget.props.data.graph.node[node_id], data.data);
if (new_id && new_id !== node_id) { if (new_id && new_id !== node_id) {
gadget.props.node_container[new_id] = gadget.props.node_container[node_id]; gadget.props.data.graph.node[new_id] = gadget.props.data.graph.node[node_id];
delete gadget.props.node_container[node_id]; delete gadget.props.data.graph.node[node_id];
delete gadget.props.node_container[new_id].id; gadget.props.node_id_to_dom_element_id[new_id] = gadget.props.node_id_to_dom_element_id[node_id];
$.each(gadget.props.edge_container, function(k, v) { delete gadget.props.node_id_to_dom_element_id[node_id];
if (v[0] === node_id) { delete gadget.props.data.graph.node[new_id].id;
v[0] = new_id; $.each(gadget.props.data.graph.edge, function(k, v) {
} if (v.source === node_id) {
if (v[1] === node_id) { v.source = new_id;
v[1] = new_id; }
if (v.destination === node_id) {
v.destination = new_id;
} }
}); });
gadget.props.preference_container.coordinates[new_id] = gadget.props.preference_container.coordinates[node_id];
delete gadget.props.preference_container.coordinates[node_id];
} }
gadget.notifyDataChanged(); gadget.notifyDataChanged();
} }
// function clearAll(gadget) {
// $.each(gadget.props.node_container, function (node_id) {
// removeElement(gadget, node_id);
// });
// // delete anything if still remains
// $(gadget.props.element).find("#main").children().remove();
// gadget.props.node_container = {};
// gadget.props.edge_container = {};
// gadget.props.preference_container = {};
// gadget.props.general_container = {};
// gadget.props.initGeneralProperties();
// gadget.props.prepareDialogForGeneralProperties();
// }
function addEdge(gadget, edge_id, edge_data) { function addEdge(gadget, edge_id, edge_data) {
var source_id = edge_data[0], target_id = edge_data[1], data = edge_data[2], overlays = [], connection; var overlays = [], connection;
if (data && data.title) { if (edge_data.name) {
overlays = [ [ "Label", { overlays = [ [ "Label", {
cssClass: "l1 component label", cssClass: "l1 component label",
label: data.title label: edge_data.name
} ] ]; } ] ];
} }
connection = gadget.props.jsplumb_instance.connect({ connection = gadget.props.jsplumb_instance.connect({
source: getElementId(gadget.props.node_container, source_id), source: gadget.props.node_id_to_dom_element_id[edge_data.source],
target: getElementId(gadget.props.node_container, target_id), target: gadget.props.node_id_to_dom_element_id[edge_data.destination],
Connector: [ "Bezier", { Connector: [ "Bezier", {
curviness: 75 curviness: 75
} ], } ],
overlays: overlays overlays: overlays
}); });
// call again updateConnectionData to set the connection data that // jsplumb assigned an id, but we are controlling ids ourselves.
// was not passed to the connection hook connection.id = edge_id;
updateConnectionData(gadget, connection, 0, data); }
} function expandSchema(class_definition, full_schema) {
// function setPreferences(gadget, preferences) { // minimal expanding of json schema, supports merging allOf and $ref
// gadget.props.preference_container = preferences; // references
// var zoom_level = gadget.props.preference_container.zoom_level || 1.0; // TODO: check for a library with full support
// setZoom(gadget, zoom_level); var property, referenced, i, expanded_class_definition = {
// } properties: class_definition.properties || {}
function openNodeDialog(gadget, element, config_dict) { };
var node_id = getNodeId(gadget.props.node_container, element.id), node_data = gadget.props.node_container[node_id], element_type = node_data._class.replace(".", "-"), property_list = config_dict[element_type].property_list || [], node_edit_popup = $(gadget.props.element).find("#popup-edit-template"), fieldset_element, delete_promise; if (class_definition.allOf) {
for (i = 0; i < class_definition.allOf.length; i += 1) {
referenced = class_definition.allOf[i];
if (referenced.$ref) {
referenced = expandSchema(full_schema.class_definition[referenced.$ref.substr(1, referenced.$ref.length)], full_schema);
}
if (referenced.properties) {
for (property in referenced.properties) {
if (referenced.properties.hasOwnProperty(property)) {
if (referenced.properties[property].type) {
expanded_class_definition.properties[property] = referenced.properties[property];
}
}
}
}
}
}
return expanded_class_definition;
}
// TODO: remove class_definition from this function and callees signature
function openNodeDialog(gadget, element, class_definition) {
var node_id = getNodeId(gadget, element.id), node_data = gadget.props.data.graph.node[node_id], node_edit_popup = $(gadget.props.element).find("#popup-edit-template"), schema = expandSchema(class_definition, gadget.props.data), fieldset_element, delete_promise;
if (node_edit_popup.length !== 0) { if (node_edit_popup.length !== 0) {
node_edit_popup.remove(); node_edit_popup.remove();
} }
...@@ -370,21 +363,7 @@ ...@@ -370,21 +363,7 @@
fieldset_element = node_edit_popup.find("fieldset")[0]; fieldset_element = node_edit_popup.find("fieldset")[0];
node_edit_popup.popup(); node_edit_popup.popup();
node_data.id = node_id; node_data.id = node_id;
if (property_list.length === 0 || property_list[0].id !== "id") { // XXX
// XXX name & id should not be handled differently in form.
property_list.unshift({
_class: "Dream.Property",
id: "name",
name: "Name",
type: "string"
});
property_list.unshift({
_class: "Dream.Property",
id: "id",
name: "ID",
type: "string"
});
}
function save_promise(fieldset_gadget, node_id) { function save_promise(fieldset_gadget, node_id) {
return RSVP.Queue().push(function() { return RSVP.Queue().push(function() {
return promiseEventListener(node_edit_popup.find("form")[0], "submit", false); return promiseEventListener(node_edit_popup.find("form")[0], "submit", false);
...@@ -405,12 +384,15 @@ ...@@ -405,12 +384,15 @@
}).push(function() { }).push(function() {
return removeElement(gadget, node_id); return removeElement(gadget, node_id);
}); });
// XXX the gadget to use on node click should be an option
return gadget.declareGadget("../fieldset/index.html", { return gadget.declareGadget("../fieldset/index.html", {
element: fieldset_element, element: fieldset_element,
scope: "fieldset" scope: "fieldset"
}).push(function(fieldset_gadget) { }).push(function(fieldset_gadget) {
// XXX those promises can probably be merged return RSVP.all([ fieldset_gadget, fieldset_gadget.render({
return RSVP.all([ fieldset_gadget, fieldset_gadget.render(property_list, node_data) ]); value: node_data,
property_definition: schema
}, node_id) ]);
}).push(function(fieldset_gadget) { }).push(function(fieldset_gadget) {
node_edit_popup.enhanceWithin(); node_edit_popup.enhanceWithin();
node_edit_popup.popup("open"); node_edit_popup.popup("open");
...@@ -424,45 +406,38 @@ ...@@ -424,45 +406,38 @@
function waitForNodeClick(gadget, node, config_dict) { function waitForNodeClick(gadget, node, config_dict) {
gadget.props.nodes_click_monitor.monitor(loopEventListener(node, "dblclick", false, openNodeDialog.bind(null, gadget, node, config_dict))); gadget.props.nodes_click_monitor.monitor(loopEventListener(node, "dblclick", false, openNodeDialog.bind(null, gadget, node, config_dict)));
} }
function newElement(gadget, element, configuration) { function addNode(gadget, node_id, node_data) {
var element_type = element._class.replace(".", "-"), option = configuration[element_type], render_element = $(gadget.props.element).find("#main"), coordinate = element.coordinate, box, absolute_position, domElement; var render_element = $(gadget.props.element).find("#main"), class_definition = gadget.props.data.class_definition[node_data._class], coordinate = node_data.coordinate, dom_element_id, box, absolute_position, domElement;
// we don't save coordinates as properties of nodes dom_element_id = generateDomElementId(gadget.props.element);
delete element.coordinate; gadget.props.node_id_to_dom_element_id[node_id] = dom_element_id;
element.element_id = generateElementId(gadget.props.element); node_data.name = node_data.name || class_definition.name;
if (!element.id) { gadget.props.data.graph.node[node_id] = node_data;
element.id = generateNodeId(gadget, element_type, option); if (coordinate === undefined) {
} coordinate = {
element.name = element.name || option.name; top: 0,
addElementToContainer(gadget.props.node_container, element); left: 0
if (coordinate !== undefined) { };
coordinate = updateElementCoordinate(gadget, element.id, coordinate);
}
if (element.element_id === undefined) {
element.element_id = generateElementId(gadget.props.element);
} }
node_data.coordinate = updateElementCoordinate(gadget, node_id, coordinate);
// XXX make node template an option, or use CSS from class_definition
/*jslint nomen: true*/ /*jslint nomen: true*/
domElement = domParser.parseFromString(node_template({ domElement = domParser.parseFromString(node_template({
"class": element._class.replace(".", "-"), "class": node_data._class.replace(".", "-"),
element_id: element.element_id, element_id: dom_element_id,
title: element.name || element.id, title: node_data.name || node_data.id,
name: element.name || element.id name: node_data.name || node_data.id
}), "text/html").querySelector(".window"); }), "text/html").querySelector(".window");
render_element.append(domElement); render_element.append(domElement);
waitForNodeClick(gadget, domElement, configuration); waitForNodeClick(gadget, domElement, class_definition);
box = $(gadget.props.element).find("#" + element.element_id); box = $(gadget.props.element).find("#" + dom_element_id);
absolute_position = convertToAbsolutePosition(gadget, coordinate.left, coordinate.top); absolute_position = convertToAbsolutePosition(gadget, coordinate.left, coordinate.top);
box.css("top", absolute_position[1]); box.css("top", absolute_position[1]);
box.css("left", absolute_position[0]); box.css("left", absolute_position[0]);
updateNodeStyle(gadget, element.element_id); updateNodeStyle(gadget, dom_element_id);
draggable(gadget); draggable(gadget);
gadget.notifyDataChanged(); gadget.notifyDataChanged();
} }
function waitForDragover(gadget) { function waitForDrop(gadget) {
return loopEventListener(gadget.props.main, "dragover", false, function() {
return undefined;
});
}
function waitForDrop(gadget, config) {
var callback; var callback;
function canceller() { function canceller() {
if (callback !== undefined) { if (callback !== undefined) {
...@@ -470,71 +445,52 @@ ...@@ -470,71 +445,52 @@
} }
} }
/*jslint unparam: true*/ /*jslint unparam: true*/
function itsANonResolvableTrap(resolve, reject) { function resolver(resolve, reject) {
callback = function(evt) { callback = function(evt) {
try { try {
var element = domParser.parseFromString(evt.dataTransfer.getData("text/html"), "text/html").querySelector(".tool"), offset = $(gadget.props.main).offset(), box_top = evt.clientY - offset.top + "px", box_left = evt.clientX - offset.left + "px", element_class = element.id.replace("-", "."), relative_position = convertToRelativePosition(gadget, box_left, box_top); var class_name = JSON.parse(evt.dataTransfer.getData("application/json")), offset = $(gadget.props.main).offset(), relative_position = convertToRelativePosition(gadget, evt.clientX - offset.left + "px", evt.clientY - offset.top + "px");
newElement(gadget, { addNode(gadget, generateNodeId(gadget, {
_class: class_name
}), {
coordinate: { coordinate: {
left: relative_position[0], left: relative_position[0],
top: relative_position[1] top: relative_position[1]
}, },
_class: element_class _class: class_name
}, config); });
} catch (e) { } catch (e) {
reject(e); reject(e);
} }
}; };
gadget.props.main.addEventListener("drop", callback, false); gadget.props.main.addEventListener("drop", callback, false);
} }
return new RSVP.Promise(itsANonResolvableTrap, canceller); return new RSVP.all([ // loopEventListener adds an event listener that will prevent default for
// dragover
loopEventListener(gadget.props.main, "dragover", false, function() {
return undefined;
}), RSVP.Promise(resolver, canceller) ]);
} }
initGadgetMixin(gadget_klass); initGadgetMixin(gadget_klass);
gadget_klass.declareAcquiredMethod("getConfigurationDict", "getConfigurationDict").declareAcquiredMethod("notifyDataChanged", "notifyDataChanged").ready(function(g) { gadget_klass.declareAcquiredMethod("notifyDataChanged", "notifyDataChanged").ready(function(g) {
g.props.edge_container = {}; g.props.node_id_to_dom_element_id = {};
g.props.preference_container = {}; g.props.zoom_level = 1;
g.props.style_attr_list = [ "width", "height", "padding-top", "line-height" ]; g.props.style_attr_list = [ "width", "height", "padding-top", "line-height" ];
}).declareMethod("render", function(data) { }).declareMethod("render", function(data) {
this.props.data = JSON.parse(data); this.props.data = JSON.parse(data);
this.props.node_container = this.props.data.nodes;
this.props.jsplumb_instance = jsPlumb.getInstance(); this.props.jsplumb_instance = jsPlumb.getInstance();
}).declareMethod("getData", function() { }).declareMethod("getContent", function() {
return JSON.stringify({ return JSON.stringify(this.props.data);
nodes: this.props.node_container,
edges: this.props.edge_container,
preference: this.props.preference_container
});
}).declareMethod("startService", function() { }).declareMethod("startService", function() {
var g = this, preference = g.props.data.preference !== undefined ? g.props.data.preference : {}, coordinates = preference.coordinates, config; var gadget = this;
g.notifyDataChanged(); this.props.main = this.props.element.querySelector("#main");
return g.getConfigurationDict().push(function(config_dict) { initJsPlumb(this);
config = config_dict; this.props.nodes_click_monitor = RSVP.Monitor();
g.props.main = g.props.element.querySelector("#main"); $.each(this.props.data.graph.node, function(key, value) {
initJsPlumb(g); addNode(gadget, key, value);
g.props.nodes_click_monitor = RSVP.Monitor();
$.each(g.props.data.nodes, function(key, value) {
if (coordinates === undefined || coordinates[key] === undefined) {
value.coordinate = {
top: 0,
left: 0
};
} else {
value.coordinate = coordinates[key];
}
value.id = key;
newElement(g, value, config);
if (value.data) {
// backward compatibility
updateElementData(g, key, {
data: value.data
});
}
});
$.each(g.props.data.edges, function(key, value) {
addEdge(g, key, value);
}); });
}).push(function() { $.each(this.props.data.graph.edge, function(key, value) {
return RSVP.all([ waitForDragover(g), waitForDrop(g, config), waitForConnection(g), waitForConnectionDetached(g), waitForConnectionClick(g), g.props.nodes_click_monitor ]); addEdge(gadget, key, value);
}); });
return RSVP.all([ waitForDrop(gadget), waitForConnection(gadget), waitForConnectionDetached(gadget), waitForConnectionClick(gadget), gadget.props.nodes_click_monitor ]);
}); });
})(RSVP, rJS, $, jsPlumb, Handlebars, initGadgetMixin, loopEventListener, promiseEventListener, DOMParser); })(RSVP, rJS, $, jsPlumb, Handlebars, initGadgetMixin, loopEventListener, promiseEventListener, DOMParser);
\ No newline at end of file
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../lib/qunit.css">
<script src="../lib/rsvp.min.js"></script>
<script src="../lib/renderjs.min.js"></script>
<script src="../lib/qunit.js"></script>
<script src="../lib/jquery.js"></script>
<script src="../lib/jquery.simulate.js"></script>
<script src="test.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
</html>
/*global rJS, JSON, QUnit, jQuery, RSVP, console*/
(function(rJS, JSON, QUnit, RSVP, $) {
"use strict";
var start = QUnit.start, stop = QUnit.stop, test = QUnit.test, equal = QUnit.equal, ok = QUnit.ok, sample_class_definition = {
edge: {
description: "Base definition for edge",
properties: {
_class: {
type: "string"
},
destination: {
type: "string"
},
name: {
type: "string"
},
required: [ "name", "_class", "source", "destination" ],
source: {
type: "string"
}
},
type: "object"
},
"Example.Edge": {
_class: "edge",
allOf: [ {
$ref: "#edge"
}, {
properties: {
color: {
"enum": [ "red", "green", "blue" ]
}
}
} ],
description: "An example edge with a color property"
},
"Example.Node": {
_class: "node",
allOf: [ {
$ref: "#node"
}, {
properties: {
shape: {
type: "string"
}
}
} ],
description: "An example node with a shape property"
},
node: {
description: "Base definition for node",
properties: {
_class: {
type: "string"
},
coordinate: {
properties: {
left: "number",
top: "number"
},
type: "object"
},
name: {
type: "string"
},
required: [ "name", "_class" ]
},
type: "object"
}
}, sample_graph = {
edge: {
edge1: {
_class: "Example.Edge",
source: "N1",
destination: "N2",
color: "blue"
}
},
node: {
N1: {
_class: "Example.Node",
name: "Node 1",
coordinate: {
top: 0,
left: 0
},
shape: "square"
},
N2: {
_class: "Example.Node",
name: "Node 2",
shape: "circle"
}
}
}, sample_graph_not_connected = {
edge: {},
node: {
N1: {
_class: "Example.Node",
name: "Node 1",
shape: "square"
},
N2: {
_class: "Example.Node",
name: "Node 2",
shape: "circle"
}
}
}, sample_data_graph = JSON.stringify({
class_definition: sample_class_definition,
graph: sample_graph
}), sample_data_graph_not_connected = JSON.stringify({
class_definition: sample_class_definition,
graph: sample_graph_not_connected
}), sample_data_empty_graph = JSON.stringify({
class_definition: sample_class_definition,
graph: {
node: {},
edge: {}
}
});
QUnit.config.testTimeout = 5e3;
rJS(window).ready(function(g) {
test("Sample graph can be loaded and output is equal to input", function() {
var jsplumb_gadget;
stop();
g.declareGadget("./index.html", {
element: document.querySelector("#qunit-fixture")
}).then(function(new_gadget) {
jsplumb_gadget = new_gadget;
return jsplumb_gadget.render(sample_data_graph);
}).then(function() {
return jsplumb_gadget.getContent();
}).then(function(content) {
equal(content, sample_data_graph);
}).fail(console.error.bind(this)).always(start);
});
test("New node can be drag & dropped", function() {
var jsplumb_gadget;
stop();
function runTest() {
// XXX here I used getContent to have a promise, but there must be a
// more elegant way.
return jsplumb_gadget.getContent().then(function() {
// fake a drop event
var e = new Event("drop");
e.dataTransfer = {
getData: function(type) {
// make sure we are called properly
equal(type, "application/json");
return JSON.stringify("Example.Node");
}
};
jsplumb_gadget.props.main.dispatchEvent(e);
}).then(function() {
return jsplumb_gadget.getContent();
}).then(function(content) {
var node, graph = JSON.parse(content).graph;
equal(1, Object.keys(graph.node).length);
node = graph.node[Object.keys(graph.node)[0]];
equal("Example.Node", node._class);
});
}
g.declareGadget("./index.html", {
element: document.querySelector("#qunit-fixture")
}).then(function(new_gadget) {
jsplumb_gadget = new_gadget;
jsplumb_gadget.render(sample_data_empty_graph);
}).then(function() {
return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);
}).fail(console.error.bind(this)).always(start);
});
test("Node can be dragged", function() {
var jsplumb_gadget;
stop();
function runTest() {
return jsplumb_gadget.getContent().then(function() {
// 100 and 60 are about 10% of the #main div ( set by css, so this
// might change )
$("div[title='Node 1']").simulate("drag", {
dx: 100,
dy: 60
});
}).then(function() {
return jsplumb_gadget.getContent();
}).then(function(content) {
var graph = JSON.parse(content).graph, node_coordinate = graph.node.N1.coordinate;
// Since original coordinates where 0,0 we are now about 0.1,0.1
// as we moved 10%
ok(node_coordinate.top - .1 < .1, "Top is ok");
ok(node_coordinate.left - .1 < .1, "Left is ok");
});
}
g.declareGadget("./index.html", {
element: document.querySelector("#qunit-fixture")
}).then(function(new_gadget) {
jsplumb_gadget = new_gadget;
jsplumb_gadget.render(sample_data_graph);
}).then(function() {
return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);
}).fail(console.error.bind(this)).always(start);
});
test("Node properties can be edited", function() {
var jsplumb_gadget;
stop();
function runTest() {
return jsplumb_gadget.getContent().then(function() {
$("div[title='Node 1']").simulate("dblclick");
// XXX popup not displayed
$("input[name='name']").val("Modified Name");
$("input[value='Validate']").click();
}).then(function() {
return jsplumb_gadget.getContent();
}).then(function(content) {
var graph = JSON.parse(content).graph, node = graph.node.N1;
equal(node.name, "Modified Name");
});
}
g.declareGadget("./index.html", {
element: document.querySelector("#qunit-fixture")
}).then(function(new_gadget) {
jsplumb_gadget = new_gadget;
jsplumb_gadget.render(sample_data_graph);
}).then(function() {
return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);
}).fail(console.error.bind(this)).always(start);
});
test("Node can be connected", function() {
var jsplumb_gadget;
stop();
function runTest() {
return jsplumb_gadget.getContent().then(function(content) {
var node1 = jsplumb_gadget.props.main.querySelector("div[title='Node 1']"), node2 = jsplumb_gadget.props.main.querySelector("div[title='Node 2']");
// At this point we have no edge
equal(Object.keys(JSON.parse(content).graph.edge).length, 0);
jsplumb_gadget.props.jsplumb_instance.connect({
source: node1.id,
target: node2.id
});
}).then(function() {
return jsplumb_gadget.getContent();
}).then(function(content) {
var edge, graph = JSON.parse(content).graph;
equal(Object.keys(graph.node).length, 2);
equal(Object.keys(graph.edge).length, 1);
edge = graph.edge[Object.keys(graph.edge)[0]];
// XXX how edge class would be set ? the first one from schema ?
//equal(edge._class, "Example.Edge");
equal(edge.source, "N1");
equal(edge.destination, "N2");
});
}
g.declareGadget("./index.html", {
element: document.querySelector("#qunit-fixture")
}).then(function(new_gadget) {
jsplumb_gadget = new_gadget;
jsplumb_gadget.render(sample_data_graph_not_connected);
}).then(function() {
return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);
}).fail(console.error.bind(this)).always(start);
});
test("Node can be deleted", function() {
var jsplumb_gadget;
stop();
function runTest() {
return jsplumb_gadget.getContent().then(function() {
$("div[title='Node 1']").simulate("dblclick");
// XXX popup not displayed
$("input[value='Delete']").click();
}).then(function() {
return jsplumb_gadget.getContent();
}).then(function(content) {
var graph = JSON.parse(content).graph;
equal(1, Object.keys(graph.node).length);
});
}
g.declareGadget("./index.html", {
element: document.querySelector("#qunit-fixture")
}).then(function(new_gadget) {
jsplumb_gadget = new_gadget;
jsplumb_gadget.render(sample_data_graph);
}).then(function() {
return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);
}).fail(console.error.bind(this)).always(start);
});
});
})(rJS, JSON, QUnit, RSVP, jQuery);
\ No newline at end of file
...@@ -949,17 +949,17 @@ ...@@ -949,17 +949,17 @@
newFunction = newFunction || function() { }; newFunction = newFunction || function() { };
return function() { return function() {
var r = null; var r = null;
try { //try {
r = newFunction.apply(this, arguments); r = newFunction.apply(this, arguments);
} catch (e) { //} catch (e) {
jsPlumbUtil.log("jsPlumb function failed : " + e); // jsPlumbUtil.log("jsPlumb function failed : " + e);
} //}
if (returnOnThisValue == null || (r !== returnOnThisValue)) { if (returnOnThisValue == null || (r !== returnOnThisValue)) {
try { //try {
r = wrappedFunction.apply(this, arguments); r = wrappedFunction.apply(this, arguments);
} catch (e) { //} catch (e) {
jsPlumbUtil.log("wrapped function failed : " + e); // jsPlumbUtil.log("wrapped function failed : " + e);
} //}
} }
return r; return r;
}; };
......
...@@ -12,17 +12,18 @@ ...@@ -12,17 +12,18 @@
g.element = element; g.element = element;
}); });
}).declareMethod("render", function(options) { }).declareMethod("render", function(options) {
var select = this.element.getElementsByTagName("select")[0], i, template, field_json = options.field_json, tmp = ""; var select = this.element.getElementsByTagName("select")[0], i, template, tmp = "";
select.setAttribute("name", field_json.key); select.setAttribute("name", options.key);
for (i = 0; i < field_json.items.length; i += 1) { for (i = 0; i < options.property_definition.enum.length; i += 1) {
if (field_json.items[i][1] === field_json.value) { if (options.property_definition.enum[i] === options.value) {
template = selected_option_template; template = selected_option_template;
} else { } else {
template = option_template; template = option_template;
} }
// XXX value and text are always same in json schema
tmp += template({ tmp += template({
value: field_json.items[i][1], value: options.property_definition.enum[i],
text: field_json.items[i][0] text: options.property_definition.enum[i]
}); });
} }
select.innerHTML += tmp; select.innerHTML += tmp;
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
gadget.element = element; gadget.element = element;
}); });
}).declareMethod("render", function(options) { }).declareMethod("render", function(options) {
var input = this.element.querySelector("input"), field_json = options.field_json || {}; var input = this.element.querySelector("input");
input.setAttribute("value", field_json.value); input.setAttribute("value", options.value);
input.setAttribute("name", field_json.key); input.setAttribute("name", options.key);
input.setAttribute("title", field_json.title); input.setAttribute("title", options.title || options.key);
}).declareMethod("getContent", function() { }).declareMethod("getContent", function() {
var input = this.element.querySelector("input"), result = {}; var input = this.element.querySelector("input"), result = {};
if (input.value !== "") { if (input.value !== "") {
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
gadget.element = element; gadget.element = element;
}); });
}).declareMethod("render", function(options) { }).declareMethod("render", function(options) {
var input = this.element.querySelector("input"), field_json = options.field_json || {}; var input = this.element.querySelector("input");
input.setAttribute("value", field_json.value || ""); input.setAttribute("value", options.value || "");
input.setAttribute("name", field_json.key); input.setAttribute("name", options.key);
input.setAttribute("title", field_json.title); input.setAttribute("title", options.title || options.key);
}).declareMethod("getContent", function() { }).declareMethod("getContent", function() {
var input = this.element.querySelector("input"), result = {}; var input = this.element.querySelector("input"), result = {};
result[input.getAttribute("name")] = input.value; result[input.getAttribute("name")] = input.value;
......
...@@ -5,21 +5,8 @@ ...@@ -5,21 +5,8 @@
<link rel="stylesheet" href="../lib/jquery-ui.css"> <link rel="stylesheet" href="../lib/jquery-ui.css">
<link rel="stylesheet" href="toolbox.css"> <link rel="stylesheet" href="toolbox.css">
<script src="../lib/jquery.js"></script>
<script src="../lib/jquery-ui.js"></script>
<script src="../lib/rsvp.min.js"></script> <script src="../lib/rsvp.min.js"></script>
<script src="../lib/renderjs.min.js"></script> <script src="../lib/renderjs.min.js"></script>
<script src="../lib/handlebars.min.js"></script>
<script id="tool-template" type="text/x-handlebars-template">
<div id="{{key}}"
class="tool {{key}}"
draggable="true">
{{name}}
<ul/>
</div>
</script>
<script src="../dream/mixin_gadget.js"></script> <script src="../dream/mixin_gadget.js"></script>
<script src="../dream/mixin_promise.js"></script> <script src="../dream/mixin_promise.js"></script>
......
/*global window, document, RSVP, rJS, Handlebars, initGadgetMixin*/ /*global window, document, RSVP, rJS, initGadgetMixin*/
(function(window, document, RSVP, rJS, Handlebars, initGadgetMixin) { (function(window, document, RSVP, rJS, initGadgetMixin) {
"use strict"; "use strict";
/*jslint nomen: true*/ /*jslint nomen: true*/
var gadget_klass = rJS(window), tool_template_source = gadget_klass.__template_element.getElementById("tool-template").innerHTML, tool_template = Handlebars.compile(tool_template_source); var gadget_klass = rJS(window);
function waitForDragstart(tool) { function waitForDragstart(tool) {
var callback; var callback;
function canceller() { function canceller() {
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
function itsANonResolvableTrap(resolve, reject) { function itsANonResolvableTrap(resolve, reject) {
callback = function(evt) { callback = function(evt) {
try { try {
evt.dataTransfer.setData("text/html", tool.outerHTML); evt.dataTransfer.setData("application/json", tool.dataset.class_name);
} catch (e) { } catch (e) {
reject(e); reject(e);
} }
...@@ -24,22 +24,28 @@ ...@@ -24,22 +24,28 @@
return new RSVP.Promise(itsANonResolvableTrap, canceller); return new RSVP.Promise(itsANonResolvableTrap, canceller);
} }
initGadgetMixin(gadget_klass); initGadgetMixin(gadget_klass);
gadget_klass.declareAcquiredMethod("getConfigurationDict", "getConfigurationDict").declareMethod("render", function() { gadget_klass.declareMethod("render", function(json_data) {
var g = this; var data = JSON.parse(json_data), tools_container = document.createElement("div");
return g.getConfigurationDict().push(function(config_dict) { /* display all nodes in the palette.
var tools_container = document.createElement("div"); */
tools_container.className = "tools-container"; tools_container.className = "tools-container";
Object.keys(config_dict).forEach(function(key) { Object.keys(data.class_definition).forEach(function(key) {
var name = config_dict[key].name || key.split("-")[1]; var _class = data.class_definition[key], tool;
if (key !== "Dream-Configuration") { // XXX "expand" the json schema "allOF" etc
tools_container.innerHTML += tool_template({ if (_class._class === "node") {
key: key, tool = document.createElement("div");
name: name // XXX maybe allow to configure the class name ?
tool.className = "tool " + key;
tool.textContent = _class.name || key;
tool.draggable = true;
tool.dataset.class_name = JSON.stringify(key);
Object.keys(_class.css || {}).forEach(function(k) {
tool.style[k] = _class.css[k];
}); });
tools_container.appendChild(tool);
} }
}); });
g.props.element.querySelector(".tools").appendChild(tools_container); this.props.element.querySelector(".tools").appendChild(tools_container);
});
}).declareMethod("startService", function() { }).declareMethod("startService", function() {
var promiseArray = []; var promiseArray = [];
[].forEach.call(this.props.element.querySelectorAll(".tool"), function(tool) { [].forEach.call(this.props.element.querySelectorAll(".tool"), function(tool) {
...@@ -47,4 +53,4 @@ ...@@ -47,4 +53,4 @@
}); });
return RSVP.all(promiseArray); return RSVP.all(promiseArray);
}); });
})(window, document, RSVP, rJS, Handlebars, initGadgetMixin); })(window, document, RSVP, rJS, initGadgetMixin);
\ No newline at end of file \ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment