summaryrefslogtreecommitdiff
path: root/raphael.inline_text_editing.js
diff options
context:
space:
mode:
authorPatrick Simianer <p@simianer.de>2015-11-06 11:59:21 +0100
committerPatrick Simianer <p@simianer.de>2015-11-06 11:59:21 +0100
commit00ab985b296b8a41f782be9766faa7e6320f4198 (patch)
tree4a948c9a77fe701edbe2502c26dc0e1cbddb9941 /raphael.inline_text_editing.js
parentd27eb43719b1d861a0aaa01a121511bc2e389b0d (diff)
fixed edit mode
Diffstat (limited to 'raphael.inline_text_editing.js')
-rw-r--r--raphael.inline_text_editing.js193
1 files changed, 193 insertions, 0 deletions
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;
+ }
+
+}));