summaryrefslogtreecommitdiff
path: root/raphael.inline_text_editing.js
blob: 155594b07c63abd1b2ffaf3208b607dfa1a33634 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
 * 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 + originalBbox.x + translateX;
				var x             = container.offsetLeft + subject.attrs.x + translateX;
        x -= $("#holder").scrollLeft();
				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: 'white',
					left: x-3+'px',
					top: y-3+'px',
					width: (width+25)+'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('keypress', function () {
          DE_count_kbd += 1;
        });

				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(' ');

				this.input.parentNode.appendChild(tmp);

				this.input.style.width = tmp.offsetWidth+25 + "px";
				this.input.style.height = tmp.offsetHeight+5 + "px";

				tmp.parentNode.removeChild(tmp);
			}
		};

		return subject.inlineTextEditing;
	}

}));