elements_functions.js 9.78 KB
/****
 * This page contains some general usefull functions for javascript
 *
 ****/  
	
	
	// need to redefine this functiondue to IE problem
	function getAttribute( elm, aName ) {
		var aValue,taName,i;
		try{
			aValue = elm.getAttribute( aName );
		}catch(exept){}
		
		if( ! aValue ){
			for( i = 0; i < elm.attributes.length; i ++ ) {
				taName = elm.attributes[i] .name.toLowerCase();
				if( taName == aName ) {
					aValue = elm.attributes[i] .value;
					return aValue;
				}
			}
		}
		return aValue;
	};
	
	// need to redefine this function due to IE problem
	function setAttribute( elm, attr, val ) {
		if(attr=="class"){
			elm.setAttribute("className", val);
			elm.setAttribute("class", val);
		}else{
			elm.setAttribute(attr, val);
		}
	};
	
	/* return a child element
		elem: element we are searching in
		elem_type: type of the eleemnt we are searching (DIV, A, etc...)
		elem_attribute: attribute of the searched element that must match
		elem_attribute_match: value that elem_attribute must match
		option: "all" if must return an array of all children, otherwise return the first match element
		depth: depth of search (-1 or no set => unlimited)
	*/
	function getChildren(elem, elem_type, elem_attribute, elem_attribute_match, option, depth)
	{           
		if(!option)
			var option="single";
		if(!depth)
			var depth=-1;
		if(elem){
			var children= elem.childNodes;
			var result=null;
			var results= [];
			for (var x=0;x<children.length;x++) {
				strTagName = new String(children[x].tagName);
				children_class="?";
				if(strTagName!= "undefined"){
					child_attribute= getAttribute(children[x],elem_attribute);
					if((strTagName.toLowerCase()==elem_type.toLowerCase() || elem_type=="") && (elem_attribute=="" || child_attribute==elem_attribute_match)){
						if(option=="all"){
							results.push(children[x]);
						}else{
							return children[x];
						}
					}
					if(depth!=0){
						result=getChildren(children[x], elem_type, elem_attribute, elem_attribute_match, option, depth-1);
						if(option=="all"){
							if(result.length>0){
								results= results.concat(result);
							}
						}else if(result!=null){                                                                          
							return result;
						}
					}
				}
			}
			if(option=="all")
			   return results;
		}
		return null;
	};       
	
	function isChildOf(elem, parent){
		if(elem){
			if(elem==parent)
				return true;
			while(elem.parentNode != 'undefined'){
				return isChildOf(elem.parentNode, parent);
			}
		}
		return false;
	};
	
	function getMouseX(e){

		if(e!=null && typeof(e.pageX)!="undefined"){
			return e.pageX;
		}else{
			return (e!=null?e.x:event.x)+ document.documentElement.scrollLeft;
		}
	};
	
	function getMouseY(e){
		if(e!=null && typeof(e.pageY)!="undefined"){
			return e.pageY;
		}else{
			return (e!=null?e.y:event.y)+ document.documentElement.scrollTop;
		}
	};
	
	function calculeOffsetLeft(r){
		return calculeOffset(r,"offsetLeft")
	};
	
	function calculeOffsetTop(r){
		return calculeOffset(r,"offsetTop")
	};
	
	function calculeOffset(element,attr){
		var offset=0;
		while(element){
			offset+=element[attr];
			element=element.offsetParent
		}
		return offset;
	};
	
	/** return the computed style
	 *	@param: elem: the reference to the element
	 *	@param: prop: the name of the css property	 
	 */
	function get_css_property(elem, prop)
	{
		if(document.defaultView)
		{
			return document.defaultView.getComputedStyle(elem, null).getPropertyValue(prop);
		}
		else if(elem.currentStyle)
		{
			var prop = prop.replace(/-\D/gi, function(sMatch)
			{
				return sMatch.charAt(sMatch.length - 1).toUpperCase();
			});
			return elem.currentStyle[prop];
		}
		else return null;
	}
	
/****
 * Moving an element 
 ***/  
	
	var _mCE;	// currently moving element
	
	/* allow to move an element in a window
		e: the event
		id: the id of the element
		frame: the frame of the element 
		ex of use:
			in html:	<img id='move_area_search_replace' onmousedown='return parent.start_move_element(event,"area_search_replace", parent.frames["this_frame_id"]);' .../>  
		or
			in javascript: document.getElementById("my_div").onmousedown= start_move_element
	*/
	function start_move_element(e, id, frame){
		var elem_id=(e.target || e.srcElement).id;
		if(id)
			elem_id=id;		
		if(!frame)
			frame=window;
		if(frame.event)
			e=frame.event;
			
		_mCE= frame.document.getElementById(elem_id);
		_mCE.frame=frame;
		frame.document.onmousemove= move_element;
		frame.document.onmouseup= end_move_element;
		/*_mCE.onmousemove= move_element;
		_mCE.onmouseup= end_move_element;*/
		
		//alert(_mCE.frame.document.body.offsetHeight);
		
		mouse_x= getMouseX(e);
		mouse_y= getMouseY(e);
		//window.status=frame+ " elem: "+elem_id+" elem: "+ _mCE + " mouse_x: "+mouse_x;
		_mCE.start_pos_x = mouse_x - (_mCE.style.left.replace("px","") || calculeOffsetLeft(_mCE));
		_mCE.start_pos_y = mouse_y - (_mCE.style.top.replace("px","") || calculeOffsetTop(_mCE));
		return false;
	};
	
	function end_move_element(e){
		_mCE.frame.document.onmousemove= "";
		_mCE.frame.document.onmouseup= "";		
		_mCE=null;
	};
	
	function move_element(e){
		var newTop,newLeft,maxLeft;

		if( _mCE.frame && _mCE.frame.event )
			e=_mCE.frame.event;
		newTop	= getMouseY(e) - _mCE.start_pos_y;
		newLeft	= getMouseX(e) - _mCE.start_pos_x;
		
		maxLeft	= _mCE.frame.document.body.offsetWidth- _mCE.offsetWidth;
		max_top	= _mCE.frame.document.body.offsetHeight- _mCE.offsetHeight;
		newTop	= Math.min(Math.max(0, newTop), max_top);
		newLeft	= Math.min(Math.max(0, newLeft), maxLeft);
		
		_mCE.style.top	= newTop+"px";
		_mCE.style.left	= newLeft+"px";		
		return false;
	};
	
/***
 * Managing a textarea (this part need the navigator infos from editAreaLoader
 ***/ 
	
	var nav= editAreaLoader.nav;
	
	// allow to get infos on the selection: array(start, end)
	function getSelectionRange(textarea){
		return {"start": textarea.selectionStart, "end": textarea.selectionEnd};
	};
	
	// allow to set the selection
	function setSelectionRange(t, start, end){
		t.focus();
		
		start	= Math.max(0, Math.min(t.value.length, start));
		end		= Math.max(start, Math.min(t.value.length, end));
	
		if( nav.isOpera && nav.isOpera < 9.6 ){	// Opera bug when moving selection start and selection end
			t.selectionEnd = 1;	
			t.selectionStart = 0;			
			t.selectionEnd = 1;	
			t.selectionStart = 0;		
		}
		t.selectionStart	= start;
		t.selectionEnd		= end;		
		//textarea.setSelectionRange(start, end);
		
		if(nav.isIE)
			set_IE_selection(t);
	};

	
	// set IE position in Firefox mode (textarea.selectionStart and textarea.selectionEnd). should work as a repeated task
	function get_IE_selection(t){
		var d=document,div,range,stored_range,elem,scrollTop,relative_top,line_start,line_nb,range_start,range_end,tab;
		if(t && t.focused)
		{	
			if(!t.ea_line_height)
			{	// calculate the lineHeight
				div= d.createElement("div");
				div.style.fontFamily= get_css_property(t, "font-family");
				div.style.fontSize= get_css_property(t, "font-size");
				div.style.visibility= "hidden";			
				div.innerHTML="0";
				d.body.appendChild(div);
				t.ea_line_height= div.offsetHeight;
				d.body.removeChild(div);
			}
			//t.focus();
			range = d.selection.createRange();
			try
			{
				stored_range = range.duplicate();
				stored_range.moveToElementText( t );
				stored_range.setEndPoint( 'EndToEnd', range );
				if(stored_range.parentElement() == t){
					// the range don't take care of empty lines in the end of the selection
					elem		= t;
					scrollTop	= 0;
					while(elem.parentNode){
						scrollTop+= elem.scrollTop;
						elem	= elem.parentNode;
					}
				
				//	var scrollTop= t.scrollTop + document.body.scrollTop;
					
				//	var relative_top= range.offsetTop - calculeOffsetTop(t) + scrollTop;
					relative_top= range.offsetTop - calculeOffsetTop(t)+ scrollTop;
				//	alert("rangeoffset: "+ range.offsetTop +"\ncalcoffsetTop: "+ calculeOffsetTop(t) +"\nrelativeTop: "+ relative_top);
					line_start	= Math.round((relative_top / t.ea_line_height) +1);
					
					line_nb		= Math.round(range.boundingHeight / t.ea_line_height);
					
					range_start	= stored_range.text.length - range.text.length;
					tab	= t.value.substr(0, range_start).split("\n");			
					range_start	+= (line_start - tab.length)*2;		// add missing empty lines to the selection
					t.selectionStart = range_start;
					
					range_end	= t.selectionStart + range.text.length;
					tab	= t.value.substr(0, range_start + range.text.length).split("\n");			
					range_end	+= (line_start + line_nb - 1 - tab.length)*2;
					t.selectionEnd = range_end;
				}
			}
			catch(e){}
		}
		if( t && t.id )
		{
			setTimeout("get_IE_selection(document.getElementById('"+ t.id +"'));", 50);
		}
	};
	
	function IE_textarea_focus(){
		event.srcElement.focused= true;
	}
	
	function IE_textarea_blur(){
		event.srcElement.focused= false;
	}
	
	// select the text for IE (take into account the \r difference)
	function set_IE_selection( t ){
		var nbLineStart,nbLineStart,nbLineEnd,range;
		if(!window.closed){ 
			nbLineStart=t.value.substr(0, t.selectionStart).split("\n").length - 1;
			nbLineEnd=t.value.substr(0, t.selectionEnd).split("\n").length - 1;
			try
			{
				range = document.selection.createRange();
				range.moveToElementText( t );
				range.setEndPoint( 'EndToStart', range );
				range.moveStart('character', t.selectionStart - nbLineStart);
				range.moveEnd('character', t.selectionEnd - nbLineEnd - (t.selectionStart - nbLineStart)  );
				range.select();
			}
			catch(e){}
		}
	};
	
	
	editAreaLoader.waiting_loading["elements_functions.js"]= "loaded";