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;
}
}));
|