diff options
-rw-r--r-- | README | 8 | ||||
-rw-r--r-- | demo.html | 3 | ||||
-rw-r--r-- | derivation-editor.js | 8 | ||||
-rw-r--r-- | raphael.inline_text_editing.js | 193 |
4 files changed, 205 insertions, 7 deletions
@@ -1,7 +1,9 @@ Visualize and edit machine translation derivations using raphaeljs. +Took raphael.inline_text_editing.js from [1]. +Partially adapted from [3] and [2]. Resources: - * http://grokbase.com/p/gg/raphaeljs/135twn41fq/how-to-move-text-and-rect-together-using-raphaeljs - * https://github.com/marmelab/Raphael.InlineTextEditing - * http://raphaeljs.com/graffle.html + [1] https://github.com/marmelab/Raphael.InlineTextEditing + [2] http://grokbase.com/p/gg/raphaeljs/135twn41fq/how-to-move-text-and-rect-together-using-raphaeljs + [3] http://raphaeljs.com/graffle.html @@ -6,7 +6,8 @@ <title>derivation editor</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js" charset="utf-8"></script> <script src="https://raw.githubusercontent.com/DmitryBaranovskiy/raphael/v2.1.2/raphael-min.js" type="text/javascript" charset="utf-8"></script> - <script src="https://raw.githubusercontent.com/marmelab/Raphael.InlineTextEditing/fd578f0eddd4172e6d9b3fde4cb67576cf546dc1/raphael.inline_text_editing.js" charset="utf-8"></script> + <!--<script src="https://raw.githubusercontent.com/marmelab/Raphael.InlineTextEditing/fd578f0eddd4172e6d9b3fde4cb67576cf546dc1/raphael.inline_text_editing.js" charset="utf-8"></script>--> + <script src="raphael.inline_text_editing.js" charset="utf-8"></script> <script src="dummy.js" type="text/javascript" charset="utf-8"></script> <script src="derivation-editor.js" type="text/javascript" charset="utf-8"></script> </head> diff --git a/derivation-editor.js b/derivation-editor.js index 08b97fc..641a478 100644 --- a/derivation-editor.js +++ b/derivation-editor.js @@ -369,7 +369,7 @@ var DE_make_obj = function (x, text, type) } else if(e.ctrlKey) { // add var x = DE_shapes_by_id[this["id_"]].attr("x")+DE_shapes_by_id[this["id_"]].attr("width") +2*DE_ui_padding; - var new_obj = DE_make_obj(x, "test", "target"); + var new_obj = DE_make_obj(x, "", "target"); var new_grid = this["grid_"]+1; new_obj["grid_"] = new_grid; new_obj.pair["grid_"] = new_grid; @@ -391,6 +391,8 @@ var DE_make_obj = function (x, text, type) if (DE_edit_mode) return; DE_edit_mode = true; this.pair.toFront(); + this.toBack(); + //this.animate({"opacity":0}, 250); DE_cur_ed = this.pair; DE_cur_ed_shape = this; var input = DE_cur_ed.inlineTextEditing.startEditing(); @@ -505,10 +507,10 @@ var DE_add_object = function() } } if (!DE_shapes[max_idx]) { - DE_make_obj(DE_ui_xbegin+DE_ui_padding, "X", "target"); + DE_make_obj(DE_ui_xbegin+DE_ui_padding, "", "target"); } else { DE_make_obj(DE_shapes[max_idx].getBBox().x2+(DE_ui_margin-DE_ui_padding), - "X", + "", "target"); } DE_paper.setSize(DE_paper.width+DE_target_shapes[DE_target_shapes.length-1].getBBox().width+DE_ui_margin, DE_paper.height); diff --git a/raphael.inline_text_editing.js b/raphael.inline_text_editing.js new file mode 100644 index 0000000..ccc37ed --- /dev/null +++ b/raphael.inline_text_editing.js @@ -0,0 +1,193 @@ +/* + * Inline text editing tool for Raphaël 2.0 & compatible with Raphaël Free transform. + * Source: https://github.com/marmelab/Raphael.InlineTextEditing + * Licensed under the MIT license + */ +(function (root, factory) { + if (typeof define === "function" && define.amd) { + // AMD. Register as an anonymous module. + define(["raphael"], function(Raphael) { + // Use global variables if the locals are undefined. + return factory(Raphael || root.Raphael); + }); + } else { + // RequireJS isn't being used. Assume Raphael is loaded in <script> tag + factory(Raphael); + } +}(this, function(Raphael) { + + Raphael.fn.inlineTextEditing = function(subject, options, callback) { + + // Store instance of the Raphael paper + var paper = this; + + subject.inlineTextEditing = { + paper : paper, + input: null, + + /** + * Start text editing by hiding the current element and adding a text field at the same position + * @return jQuery input element + */ + startEditing: function(){ + // Store Raphael container above the svg + var container = this.paper.canvas.parentNode; + var translateX = 0; + var translateY = 0; + var transformOrder = {}; + + // Retrieve element transformation + var rotation = subject._.deg; + var scaleX = subject._.sx; + var scaleY = subject._.sy; + var matrix = subject.node.getAttribute('transform'); + + // Check if the element has translations & retrieve transformations order + for(var i = 0, length = subject._.transform.length; i < length; i++){ + var matrixComponents = subject._.transform[i]; + var transform = matrixComponents[0].toLowerCase(); + transformOrder[transform] = transform; + + if(transform == 't'){ + translateX += matrixComponents[1]; + translateY += matrixComponents[2]; + } + } + + + // Check if there is implicit matrix + for(var i = 0, length = subject._.transform.length; i < length; i++){ + if(subject._.transform[i][0].toLowerCase() == 'm'){ + var matrixComponents = subject._.transform[i].slice(1); + + // Perform transformation from matrix elements + rotation += -1 * Math.asin(matrixComponents[2]) * 180 / Math.PI; + scaleX *= matrixComponents[0] / Math.cos(rotation*Math.PI/180); + scaleY *= matrixComponents[3] / Math.cos(rotation*Math.PI/180); + + transformOrder = {r: 'r', s:'s'}; + } + } + + // Remove transformation on the current element to retrieve original dimension + subject.node.removeAttribute('transform'); + + var originalBbox = subject._getBBox(); + var width = originalBbox.width; + var height = originalBbox.height; + var x = container.offsetLeft + subject.attrs.x + translateX; + var y = container.offsetTop + subject.attrs.y - height / 2 + translateY; + var sTransform = ''; + var sOrigin = 'center center'; + var oTransform = { + // t : 'translate('+(translateX)+'px, '+(translateY)+'px)', + r : 'rotate('+rotation+'deg)', + s : 'scale('+scaleX+', '+scaleY+')' + }; + + // Build transform CSS property in the same order than the element + for(var transform in transformOrder){ + if(oTransform[transform] != undefined){ + sTransform += oTransform[transform] + ' '; + } + } + + // Re-apply stored transformation to the element and hide it + subject.node.setAttribute("transform", matrix); + subject.hide(); + + // Prepare input styles + var oStyles = { + position: 'absolute', + background: 'red', + left: x-3+'px', + top: y-3+'px', + width: width+10+'px', + "background-color": "rgba(1, f, f, 0.2)", + height: height+5+'px', + color: subject.attrs.fill, + + '-moz-transform-origin': sOrigin, + '-ms-transform-origin': sOrigin, + '-o-transform-origin': sOrigin, + '-webkit-transform-origin': sOrigin, + 'transform-origin': sOrigin, + + '-moz-transform' : sTransform, + '-ms-transform' : sTransform, + '-o-transform' : sTransform, + '-webkit-transform' : sTransform, + 'transform' : sTransform + }; + + // Retrieve font styles + var aFontAttributes = ['font', 'font-family', 'font-size', 'font-style', 'font-weight', 'font-variant'/*, 'line-height'*/]; + + for(var i = 0, length = aFontAttributes.length; i < length; i++){ + var attribute = aFontAttributes[i]; + + if(subject.attrs[attribute] != undefined){ + oStyles[attribute] = subject.attrs[attribute]; + } + + if(subject.node.style[attribute] != undefined){ + oStyles[attribute] = subject.node.style[attribute]; + } + } + + var sStyles = ''; + for(var z in oStyles){ + sStyles += z + ':' + oStyles[z] + ';'; + } + + // Create an input element with theses styles + this.input = document.createElement("textarea"); + this.input.value = subject.attrs.text ? subject.attrs.text.replace(/\'/g,"\\\'") : ''; + this.input.setAttribute("style", sStyles); + + this.input.addEventListener('keyup', this._handleKeyDown.bind(this)); + + // Add the input in the container and apply focus on it + container.appendChild(this.input); + this.input.focus(); + + return this.input; + }, + + /** + * Apply text modification and remove associated input + */ + stopEditing: function(){ + + // Set the new the value + subject.attr("text", this.input.value); + + // Show the text element + subject.show(); + + // Remove text input + this.input.parentNode.removeChild(this.input); + }, + + _handleKeyDown: function(e){ + var tmp = document.createElement("span"); + var text = this.input.value; + tmp.setAttribute('style', this.input.style.cssText); + tmp.style.height = null; + tmp.style.width = null; + tmp.style.visibility = 'hidden'; + tmp.innerHTML = text.split('\n').join('<br />'); + + this.input.parentNode.appendChild(tmp); + + this.input.style.width = tmp.offsetWidth+50 + "px"; + this.input.style.height = tmp.offsetHeight+5 + "px"; + + tmp.parentNode.removeChild(tmp); + } + }; + + return subject.inlineTextEditing; + } + +})); |