diff options
| author | Alon Levy <alon@pobox.com> | 2014-12-04 13:41:04 +0200 |
|---|---|---|
| committer | Alon Levy <alon@pobox.com> | 2014-12-04 13:42:12 +0200 |
| commit | 8227fdd4239cf3393c3728350c266673749d6b44 (patch) | |
| tree | 7d132f3604e65ecfa8ce7429be6a06dfb8050598 | |
| parent | f11f4005656d5df9649b59edd1e44b21b63d89e7 (diff) | |
svgInput modularized, works mostly
missing correct width (setting it on the input instead of the FO) plus
only chrome looks ok for link, FF still misplaced.
| -rw-r--r-- | res/css/partials/graph-view.scss | 22 | ||||
| -rw-r--r-- | res/css/style.css | 18 | ||||
| -rw-r--r-- | src/rz_core.js | 231 |
3 files changed, 169 insertions, 102 deletions
diff --git a/res/css/partials/graph-view.scss b/res/css/partials/graph-view.scss index f4854998..a129d41b 100644 --- a/res/css/partials/graph-view.scss +++ b/res/css/partials/graph-view.scss @@ -22,16 +22,36 @@ } .nodetext { - fill: $dark-grey; font-size:17px; z-index:3; } +// editor for node text +.svg-input-fo-node { + fill: $dark-grey; + z-index:3; +} + +.svg-input-fo-node input { + font-size:17px; + background-color: transparent; +} + .linklabel{ stroke: $dark-grey; font-size:14px; + background-color: transparent; +} + +// editor for link text +.svg-input-fo-link { + stroke: $dark-grey; +} +.svg-input-fo-link input { + font-size: 14px; + background-color: transparent; } .link { diff --git a/res/css/style.css b/res/css/style.css index 61fa7a6a..6f8b8d54 100644 --- a/res/css/style.css +++ b/res/css/style.css @@ -166,9 +166,25 @@ table { font-size: 17px; z-index: 3; } +.svg-input-fo-node { + fill: #363636; + z-index: 3; } + +.svg-input-fo-node input { + font-size: 17px; + background-color: transparent; } + .linklabel { stroke: #363636; - font-size: 14px; } + font-size: 14px; + background-color: transparent; } + +.svg-input-fo-link { + stroke: #363636; } + +.svg-input-fo-link input { + font-size: 14px; + background-color: transparent; } .link { fill: none; diff --git a/src/rz_core.js b/src/rz_core.js index 2bf71e78..858fa15d 100644 --- a/src/rz_core.js +++ b/src/rz_core.js @@ -15,22 +15,132 @@ var addednodes = [], drag, force; -// SVG Util -function appendForeignElementInputWithID(base, elemid, width, height) -{ - var input = document.createElement('input'), - body = document.createElement('body'), - fo = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject'); +// "CSS" for SVG elements. Reused for editing elements. +var node_text_dx = 15, + node_text_dy = '.30em', + svg_input_fo_node_x = node_text_dx, + svg_input_fo_node_y = '-.70em', + svg_input_fo_height = '28px', + svg_input_fo_width = '100px'; + + +/** + * svgInput - creates an embedded input element under a given + * + * edit_node(@sibling, @node) + * edit_link(@sibling, @link) + */ +var svgInput = (function() { + function appendForeignElementInputWithID(base, elemid, width, height) + { + var input = document.createElement('input'), + body = document.createElement('body'), + fo = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject'); + + body.appendChild(input); + + fo.setAttribute('width', width || svg_input_fo_width); + fo.setAttribute('height', height || svg_input_fo_height); + fo.style.pointerEvents = 'none'; + input.style.pointerEvents = 'all'; + fo.appendChild(body); + base.appendChild(fo); + input.setAttribute('id', elemid); + return input; + } + + function editname_on_keydown(e) { + var ret = undefined, + jelement = createOrGetSvgInput(), + element = jelement[0], + newname = jelement.val(), + fo = createOrGetSvgInputFO(), + d; + + if (element != this) { + console.log('unexpected editname_on_keypress this should be the svg-input element'); + } + + if (e.which == 13 || e.which == 27) { + fo.hide(); + ret = false; + d = jelement.data().d; + if (e.which == 13 && newname != d.name) { + if (d.hasOwnProperty('__src')) { + graph.editLink(d.__src.id, d.__dst.id, newname); + } else { + graph.editName(d.id, newname); + } + update_view__graph(true); + } + } + rz_bus.ui_key.push({where: consts.KEYSTROKE_WHERE_EDIT_NODE, keys: [e.which]}); + return ret; + }; + + + // FIXME: element being deleted. Some delete is legit - removal of related element. Some isn't (a click). + // Instead of investigating (time constraint) reparenting as sibling, and introducing + // this function. Cost of creation of element is negligble, it's just ugly.. + function createOrGetSvgInput() + { + var svg_input_name = 'svg-input', + svg_input_selector = '#' + svg_input_name, + svg_input = $(svg_input_selector); + + if (svg_input.length == 0) { + console.log('creating new svg-input'); + svg_input = $(appendForeignElementInputWithID(vis[0][0], svg_input_name)); + svg_input.on('keydown', editname_on_keydown); + } + return svg_input; + } + + function createOrGetSvgInputFO() + { + return createOrGetSvgInput().parent().parent(); + } + /* + * @param e visual node element + * @param n node model object + */ + function enable(e, n) { + var oldname = n.name, + svg_input = createOrGetSvgInput(e, n), + fo = createOrGetSvgInputFO(), + is_link = n.hasOwnProperty('__src'); + + e.parentNode.appendChild(fo[0]); // This will unparent from the old parent + if (is_link) { + fo.attr('transform', e.getAttribute('transform')); + // XXX links set the text-anchor middle attribute. no idea how to do that + fo.attr('x', -$(e).width() / 2); + fo.attr('y', -$(e).height() / 2 - 3); // XXX This minus 3 is only kinda ok. + fo.attr('class', 'svg-input-fo-link'); + } else { + fo.attr('x', svg_input_fo_node_x); + fo.attr('y', svg_input_fo_node_y); + fo.attr('transform', null); + fo.attr('class', 'svg-input-fo-node'); + } + // Set width correctly + svg_input.attr('width', Math.max($(e).width() * 1.2, $(e).width() + 50)); + fo.show(); + svg_input.val(oldname); + svg_input.data().d = n; + svg_input.focus(); + // TODO: set cursor to correct location in text + } + + return { + enable: enable, + hide: function() { + createOrGetSvgInputFO().hide(); + } + }; +}()); + - body.appendChild(input); - - fo.setAttribute('width', width || '100px'); - fo.setAttribute('height', height || '100px'); - fo.appendChild(body); - base.appendChild(fo); - input.setAttribute('id', elemid); - return input; -} function recenterZoom() { vis.attr("transform", "translate(0,0)scale(1)"); @@ -163,7 +273,7 @@ function canvas_handler_dblclick(){ var n_ve = locate_visual_element(n); // locate visual element var on_slowdown_cb = function(){ - editNodeText($(n_ve).find('.nodetext'), n); + svgInput.enable($(n_ve).find('.nodetext'), n); observer.disconnect(); } var mutation_handler = rz_observer.new_Mutation_Handler__on_dxy_slowdown(on_slowdown_cb); @@ -264,7 +374,7 @@ function update_view__graph(no_relayout) { .attr("text-anchor", "middle") .on("click", function(d, i) { if (d.state !== "temp") { - editLinkText(this, d); + svgInput.enable(this, d); } }); @@ -305,15 +415,15 @@ function update_view__graph(no_relayout) { nodetext = nodeEnter.insert("text") .attr("class", "nodetext graph") - .attr("dx", 15) - .attr("dy", ".30em") + .attr("dx", node_text_dx) + .attr("dy", node_text_dy) .on("click", function(d, i) { if (d3.event.defaultPrevented) { // drag happened, ignore click https://github.com/mbostock/d3/wiki/Drag-Behavior#on return; } if (d.state !== "temp") { - editNodeText(this, d); + svgInput.enable(this, d); selection.update([d]); showNodeInfo(this.parentNode.node, i); update_view__graph(true); @@ -583,91 +693,12 @@ function showNodeInfo(d, i) { } function overlay_mousedown() { - createOrGetSvgInputFO().hide(); + svgInput.hide(); selection.clear(); view.hide(); update_view__graph(true); } -function editname_on_keypress(e) { - var ret = undefined, - element = createOrGetSvgInput(), - newname = element.val(), - fo = createOrGetSvgInputFO(), - d; - - if (element != this) { - console.log('unexpected editname_on_keypress this should be the svg-input element'); - } - - if (e.which == 13 || e.which == 27) { - fo.hide(); - ret = false; - d = element.data().d; - if (e.which == 13 && newname != d.name) { - if (d.hasOwnProperty('__src')) { - graph.editLink(d.__src.id, d.__dst.id, newname); - } else { - graph.editName(d.id, newname); - } - update_view__graph(true); - } - } - rz_bus.ui_key.push({where: consts.KEYSTROKE_WHERE_EDIT_NODE, keys: [e.which]}); - return ret; -}; - -function createOrGetSvgInput() -{ - var svg_input_name = 'svg-input', - svg_input_selector = '#' + svg_input_name, - svg_input = $(svg_input_selector); - - if (svg_input.length == 0) { - console.log('creating new svg-input'); - svg_input = $(appendForeignElementInputWithID(vis[0][0], svg_input_name)); - svg_input.on('keypress', editname_on_keypress); - } - return svg_input; -} - -function createOrGetSvgInputFO() -{ - return createOrGetSvgInput().parent().parent(); -} - -/** - * @param e visual node element - * @param n node model object - */ -function editBothText(e, n) { - var oldname = n.name, - svg_input = createOrGetSvgInput(), - fo = createOrGetSvgInputFO(), - is_link = n.hasOwnProperty('__src'); - - e.parentNode.appendChild(fo[0]); // This will unparent from the old parent - if (is_link) { - fo.attr('transform', e.getAttribute('transform')); - fo.attr('dx', null); - fo.attr('dy', null); - svg_input.attr('class', 'linklabel graph'); - } else { - fo.attr('dx', e.getAttribute('dx')); - fo.attr('dy', e.getAttribute('dy')); - fo.attr('transform', null); - svg_input.attr('class', 'nodetext graph'); - } - fo.show(); - svg_input.val(oldname); - svg_input.data().d = n; - svg_input.focus(); - // TODO: set cursor to correct location in text -} - -var editLinkText = editBothText; -var editNodeText = editBothText; - return { graph: graph, force: force, |
