233
by mattgiuca
Added a shaky implementation of EditArea as the text editor. |
1 |
/****
|
2 |
* This page contains some general usefull functions for javascript
|
|
3 |
*
|
|
4 |
****/
|
|
5 |
||
6 |
||
7 |
// need to redefine this functiondue to IE problem
|
|
8 |
function getAttribute( elm, aname ) { |
|
9 |
try{ |
|
10 |
var avalue = elm.getAttribute( aname ); |
|
11 |
}catch(exept){ |
|
12 |
||
13 |
}
|
|
14 |
if ( ! avalue ) { |
|
15 |
for ( var i = 0; i < elm.attributes.length; i ++ ) { |
|
16 |
var taName = elm.attributes [i] .name.toLowerCase(); |
|
17 |
if ( taName == aname ) { |
|
18 |
avalue = elm.attributes [i] .value; |
|
19 |
return avalue; |
|
20 |
}
|
|
21 |
}
|
|
22 |
}
|
|
23 |
return avalue; |
|
24 |
};
|
|
25 |
||
26 |
// need to redefine this function due to IE problem
|
|
27 |
function setAttribute( elm, attr, val ) { |
|
28 |
if(attr=="class"){ |
|
29 |
elm.setAttribute("className", val); |
|
30 |
elm.setAttribute("class", val); |
|
31 |
}else{ |
|
32 |
elm.setAttribute(attr, val); |
|
33 |
}
|
|
34 |
};
|
|
35 |
||
36 |
/* return a child element
|
|
37 |
elem: element we are searching in
|
|
38 |
elem_type: type of the eleemnt we are searching (DIV, A, etc...)
|
|
39 |
elem_attribute: attribute of the searched element that must match
|
|
40 |
elem_attribute_match: value that elem_attribute must match
|
|
41 |
option: "all" if must return an array of all children, otherwise return the first match element
|
|
42 |
depth: depth of search (-1 or no set => unlimited)
|
|
43 |
*/
|
|
44 |
function getChildren(elem, elem_type, elem_attribute, elem_attribute_match, option, depth) |
|
45 |
{
|
|
46 |
if(!option) |
|
47 |
var option="single"; |
|
48 |
if(!depth) |
|
49 |
var depth=-1; |
|
50 |
if(elem){ |
|
51 |
var children= elem.childNodes; |
|
52 |
var result=null; |
|
53 |
var results= new Array(); |
|
54 |
for (var x=0;x<children.length;x++) { |
|
55 |
strTagName = new String(children[x].tagName); |
|
56 |
children_class="?"; |
|
57 |
if(strTagName!= "undefined"){ |
|
58 |
child_attribute= getAttribute(children[x],elem_attribute); |
|
59 |
if((strTagName.toLowerCase()==elem_type.toLowerCase() || elem_type=="") && (elem_attribute=="" || child_attribute==elem_attribute_match)){ |
|
60 |
if(option=="all"){ |
|
61 |
results.push(children[x]); |
|
62 |
}else{ |
|
63 |
return children[x]; |
|
64 |
}
|
|
65 |
}
|
|
66 |
if(depth!=0){ |
|
67 |
result=getChildren(children[x], elem_type, elem_attribute, elem_attribute_match, option, depth-1); |
|
68 |
if(option=="all"){ |
|
69 |
if(result.length>0){ |
|
70 |
results= results.concat(result); |
|
71 |
}
|
|
72 |
}else if(result!=null){ |
|
73 |
return result; |
|
74 |
}
|
|
75 |
}
|
|
76 |
}
|
|
77 |
}
|
|
78 |
if(option=="all") |
|
79 |
return results; |
|
80 |
}
|
|
81 |
return null; |
|
82 |
};
|
|
83 |
||
84 |
function isChildOf(elem, parent){ |
|
85 |
if(elem){ |
|
86 |
if(elem==parent) |
|
87 |
return true; |
|
88 |
while(elem.parentNode != 'undefined'){ |
|
89 |
return isChildOf(elem.parentNode, parent); |
|
90 |
}
|
|
91 |
}
|
|
92 |
return false; |
|
93 |
};
|
|
94 |
||
95 |
function getMouseX(e){ |
|
96 |
/*if(document.all)
|
|
97 |
return event.x + document.body.scrollLeft;
|
|
98 |
else
|
|
99 |
return e.pageX;*/
|
|
100 |
if(e!=null && typeof(e.pageX)!="undefined"){ |
|
101 |
return e.pageX; |
|
102 |
}else{ |
|
103 |
return (e!=null?e.x:event.x)+ document.documentElement.scrollLeft; |
|
104 |
}
|
|
105 |
//return (e!=null) ? e.pageX : event.x + document.documentElement.scrollLeft;
|
|
106 |
};
|
|
107 |
||
108 |
function getMouseY(e){ |
|
109 |
/*if(document.all)
|
|
110 |
return event.y + document.body.scrollTop;
|
|
111 |
else
|
|
112 |
return e.pageY;*/
|
|
113 |
if(e!=null && typeof(e.pageY)!="undefined"){ |
|
114 |
return e.pageY; |
|
115 |
}else{ |
|
116 |
return (e!=null?e.y:event.y)+ document.documentElement.scrollTop; |
|
117 |
}
|
|
118 |
//return (e!=null) ? e.pageY : event.y + document.documentElement.scrollTop;
|
|
119 |
};
|
|
120 |
||
121 |
function calculeOffsetLeft(r){ |
|
122 |
return calculeOffset(r,"offsetLeft") |
|
123 |
};
|
|
124 |
||
125 |
function calculeOffsetTop(r){ |
|
126 |
return calculeOffset(r,"offsetTop") |
|
127 |
};
|
|
128 |
||
129 |
function calculeOffset(element,attr){ |
|
130 |
var offset=0; |
|
131 |
while(element){ |
|
132 |
offset+=element[attr]; |
|
133 |
element=element.offsetParent |
|
134 |
}
|
|
135 |
return offset; |
|
136 |
};
|
|
137 |
||
138 |
/** return the computed style
|
|
139 |
* @param: elem: the reference to the element
|
|
140 |
* @param: prop: the name of the css property
|
|
141 |
*/
|
|
142 |
function get_css_property(elem, prop) |
|
143 |
{
|
|
144 |
if(document.defaultView) |
|
145 |
{
|
|
146 |
return document.defaultView.getComputedStyle(elem, null).getPropertyValue(prop); |
|
147 |
}
|
|
148 |
else if(elem.currentStyle) |
|
149 |
{
|
|
150 |
var prop = prop.replace(/-\D/gi, function(sMatch) |
|
151 |
{
|
|
152 |
return sMatch.charAt(sMatch.length - 1).toUpperCase(); |
|
153 |
});
|
|
154 |
return elem.currentStyle[prop]; |
|
155 |
}
|
|
156 |
else return null; |
|
157 |
}
|
|
158 |
||
159 |
/****
|
|
160 |
* Moving an element
|
|
161 |
***/
|
|
162 |
||
163 |
var move_current_element; |
|
164 |
/* allow to move an element in a window
|
|
165 |
e: the event
|
|
166 |
id: the id of the element
|
|
167 |
frame: the frame of the element
|
|
168 |
ex of use:
|
|
169 |
in html: <img id='move_area_search_replace' onmousedown='return parent.start_move_element(event,"area_search_replace", parent.frames["this_frame_id"]);' .../>
|
|
170 |
or
|
|
171 |
in javascript: document.getElementById("my_div").onmousedown= start_move_element
|
|
172 |
*/
|
|
173 |
function start_move_element(e, id, frame){ |
|
174 |
var elem_id=(e.target || e.srcElement).id; |
|
175 |
if(id) |
|
176 |
elem_id=id; |
|
177 |
if(!frame) |
|
178 |
frame=window; |
|
179 |
if(frame.event) |
|
180 |
e=frame.event; |
|
181 |
||
182 |
move_current_element= frame.document.getElementById(elem_id); |
|
183 |
move_current_element.frame=frame; |
|
184 |
frame.document.onmousemove= move_element; |
|
185 |
frame.document.onmouseup= end_move_element; |
|
186 |
/*move_current_element.onmousemove= move_element;
|
|
187 |
move_current_element.onmouseup= end_move_element;*/
|
|
188 |
||
189 |
//alert(move_current_element.frame.document.body.offsetHeight);
|
|
190 |
||
191 |
mouse_x= getMouseX(e); |
|
192 |
mouse_y= getMouseY(e); |
|
193 |
//window.status=frame+ " elem: "+elem_id+" elem: "+ move_current_element + " mouse_x: "+mouse_x;
|
|
194 |
move_current_element.start_pos_x = mouse_x - (move_current_element.style.left.replace("px","") || calculeOffsetLeft(move_current_element)); |
|
195 |
move_current_element.start_pos_y = mouse_y - (move_current_element.style.top.replace("px","") || calculeOffsetTop(move_current_element)); |
|
196 |
return false; |
|
197 |
};
|
|
198 |
||
199 |
function end_move_element(e){ |
|
200 |
move_current_element.frame.document.onmousemove= ""; |
|
201 |
move_current_element.frame.document.onmouseup= ""; |
|
202 |
move_current_element=null; |
|
203 |
};
|
|
204 |
||
205 |
function move_element(e){ |
|
206 |
/*window.status="move"+frame;
|
|
207 |
window.status="move2"+frame.event;*/
|
|
208 |
if(move_current_element.frame && move_current_element.frame.event) |
|
209 |
e=move_current_element.frame.event; |
|
210 |
var mouse_x=getMouseX(e); |
|
211 |
var mouse_y=getMouseY(e); |
|
212 |
var new_top= mouse_y - move_current_element.start_pos_y; |
|
213 |
var new_left= mouse_x - move_current_element.start_pos_x; |
|
214 |
||
215 |
var max_left= move_current_element.frame.document.body.offsetWidth- move_current_element.offsetWidth; |
|
216 |
max_top= move_current_element.frame.document.body.offsetHeight- move_current_element.offsetHeight; |
|
217 |
new_top= Math.min(Math.max(0, new_top), max_top); |
|
218 |
new_left= Math.min(Math.max(0, new_left), max_left); |
|
219 |
||
220 |
move_current_element.style.top= new_top+"px"; |
|
221 |
move_current_element.style.left= new_left+"px"; |
|
222 |
return false; |
|
223 |
};
|
|
224 |
||
225 |
/***
|
|
226 |
* Managing a textarea (this part need the navigator infos from editAreaLoader
|
|
227 |
***/
|
|
228 |
||
229 |
var nav= editAreaLoader.nav; |
|
230 |
||
231 |
// allow to get infos on the selection: array(start, end)
|
|
232 |
function getSelectionRange(textarea){ |
|
233 |
//if(nav['isIE'])
|
|
234 |
// get_IE_selection(textarea);
|
|
235 |
return {"start": textarea.selectionStart, "end": textarea.selectionEnd}; |
|
236 |
};
|
|
237 |
||
238 |
// allow to set the selection
|
|
239 |
function setSelectionRange(textarea, start, end){ |
|
240 |
textarea.focus(); |
|
241 |
||
242 |
start= Math.max(0, Math.min(textarea.value.length, start)); |
|
243 |
end= Math.max(start, Math.min(textarea.value.length, end)); |
|
244 |
||
245 |
if(nav['isOpera']){ // Opera bug when moving selection start and selection end |
|
246 |
textarea.selectionEnd = 1; |
|
247 |
textarea.selectionStart = 0; |
|
248 |
textarea.selectionEnd = 1; |
|
249 |
textarea.selectionStart = 0; |
|
250 |
}
|
|
251 |
textarea.selectionStart = start; |
|
252 |
textarea.selectionEnd = end; |
|
253 |
//textarea.setSelectionRange(start, end);
|
|
254 |
||
255 |
if(nav['isIE']) |
|
256 |
set_IE_selection(textarea); |
|
257 |
};
|
|
258 |
||
259 |
||
260 |
// set IE position in Firefox mode (textarea.selectionStart and textarea.selectionEnd). should work as a repeated task
|
|
261 |
function get_IE_selection(textarea){ |
|
262 |
||
263 |
if(textarea && textarea.focused) |
|
264 |
{
|
|
265 |
if(!textarea.ea_line_height) |
|
266 |
{ // calculate the lineHeight |
|
267 |
var div= document.createElement("div"); |
|
268 |
div.style.fontFamily= get_css_property(textarea, "font-family"); |
|
269 |
div.style.fontSize= get_css_property(textarea, "font-size"); |
|
270 |
div.style.visibility= "hidden"; |
|
271 |
div.innerHTML="0"; |
|
272 |
document.body.appendChild(div); |
|
273 |
textarea.ea_line_height= div.offsetHeight; |
|
274 |
document.body.removeChild(div); |
|
275 |
}
|
|
276 |
//textarea.focus();
|
|
277 |
var range = document.selection.createRange(); |
|
278 |
var stored_range = range.duplicate(); |
|
279 |
stored_range.moveToElementText( textarea ); |
|
280 |
stored_range.setEndPoint( 'EndToEnd', range ); |
|
281 |
if(stored_range.parentElement()==textarea){ |
|
282 |
// the range don't take care of empty lines in the end of the selection
|
|
283 |
var elem= textarea; |
|
284 |
var scrollTop= 0; |
|
285 |
while(elem.parentNode){ |
|
286 |
scrollTop+= elem.scrollTop; |
|
287 |
elem= elem.parentNode; |
|
288 |
}
|
|
289 |
||
290 |
// var scrollTop= textarea.scrollTop + document.body.scrollTop;
|
|
291 |
||
292 |
// var relative_top= range.offsetTop - calculeOffsetTop(textarea) + scrollTop;
|
|
293 |
var relative_top= range.offsetTop - calculeOffsetTop(textarea)+ scrollTop; |
|
294 |
// alert("rangeoffset: "+ range.offsetTop +"\ncalcoffsetTop: "+ calculeOffsetTop(textarea) +"\nrelativeTop: "+ relative_top);
|
|
295 |
var line_start = Math.round((relative_top / textarea.ea_line_height) +1); |
|
296 |
||
297 |
var line_nb= Math.round(range.boundingHeight / textarea.ea_line_height); |
|
298 |
||
299 |
// alert("store_range: "+ stored_range.text.length+"\nrange: "+range.text.length+"\nrange_text: "+ range.text);
|
|
300 |
var range_start= stored_range.text.length - range.text.length; |
|
301 |
var tab= textarea.value.substr(0, range_start).split("\n"); |
|
302 |
range_start+= (line_start - tab.length)*2; // add missing empty lines to the selection |
|
303 |
textarea.selectionStart = range_start; |
|
304 |
||
305 |
var range_end= textarea.selectionStart + range.text.length; |
|
306 |
tab= textarea.value.substr(0, range_start + range.text.length).split("\n"); |
|
307 |
range_end+= (line_start + line_nb - 1 - tab.length)*2; |
|
308 |
textarea.selectionEnd = range_end; |
|
309 |
}
|
|
310 |
}
|
|
311 |
setTimeout("get_IE_selection(document.getElementById('"+ textarea.id +"'));", 50); |
|
312 |
};
|
|
313 |
||
314 |
function IE_textarea_focus(){ |
|
315 |
event.srcElement.focused= true; |
|
316 |
}
|
|
317 |
||
318 |
function IE_textarea_blur(){ |
|
319 |
event.srcElement.focused= false; |
|
320 |
}
|
|
321 |
||
322 |
// select the text for IE (take into account the \r difference)
|
|
323 |
function set_IE_selection(textarea){ |
|
324 |
var nbLineStart=textarea.value.substr(0, textarea.selectionStart).split("\n").length - 1; |
|
325 |
var nbLineEnd=textarea.value.substr(0, textarea.selectionEnd).split("\n").length - 1; |
|
326 |
var range = document.selection.createRange(); |
|
327 |
range.moveToElementText( textarea ); |
|
328 |
range.setEndPoint( 'EndToStart', range ); |
|
329 |
range.moveStart('character', textarea.selectionStart - nbLineStart); |
|
330 |
range.moveEnd('character', textarea.selectionEnd - nbLineEnd - (textarea.selectionStart - nbLineStart) ); |
|
331 |
range.select(); |
|
332 |
};
|
|
333 |
||
334 |
||
335 |
editAreaLoader.waiting_loading["elements_functions.js"]= "loaded"; |