/**
 * $Id: cist.js,v 1.2.6.11 2007/09/12 07:52:10 pafei Exp $
 * $Source: /cvs/cist/online/Web/cist/resource/javascript/cist.js,v $
 * 
 * Javascript-Klassen, um auf Cist-Funktionalitaet zugreifen zu koennen
 */


var Cist = {
	rpc_url: '/cist_version_4-4/rpc/',
	resource_uri: '/cist_version_4-4/resource/',
	version: '$Name: version_4-4 $'
}

var CistHtml = {
	/**
	 * aendert die Optionen eines HMTL-Selects
	 * 
	 * Beispiel:
	 * 
	 * Cist.changeSelectOptions('fk_attributwert', Cist.getSelectOptions, {content_type:'asdf', id:$F('fk_attributname')})
	 * 
	 * @param string id						die id des HTML Selects, dessen Options angepasst werden sollen
	 * @param string function_to_call 		die Funktion, welche das XML generiert, welches dann als Select-Options
	 *                                		geschrieben wird
	 * @param Object function_arguments die Argumente, welche an `function_to_call` uebergeben werden
	 */
	changeSelectOptions: function(id, function_to_call, function_arguments) {
		//CistHtml.startLoadingAnimation(id);
		internArguments = {html_select_id: id};
		function_to_call(CistHtml.changeSelectOptionsComplete, function_arguments, internArguments);
	},
	
	changeSelectOptionsComplete: function(request, internArguments, data) {
		selectId = internArguments.html_select_id;
		select = jQuery("#"+selectId);
		CistHtml.removeChildrenjQuery(select);
		for (key in data) {
			value = data[key];
			CistHtml.appendToSelectjQuery(select, key, value);
		}
		CistHtml.stopLoadingAnimation(internArguments.html_select_id);
  	},

	/**
	 * entfernt alle Kinder eines DOM-Elements
         *
         * Beispiel:
         * Cist.removeChildren($('projekt'));
         *
         * @param DomElement domElement
         */

	removeChildrenjQuery: function(select) {
		select_name = select[0].name;
		select_children = jQuery(select).children();
		select_children.remove();
	},
	
	/**
         * add item to select element the less elegant, but compatible way
         */

	appendToSelectjQuery: function(select, value, content) {
		var opt;
		opt = document.createElement("option");
		opt.value = value;
		opt.innerHtml = content;
		opt.appendChild(document.createTextNode(content));
		jQuery(opt).appendTo(select);
	}, 
	
	/**
	 * zeigt Lade-Animation 
	 * @param String id die id des Elements, bei dem die Animation angezeigt werden soll
	 * @param String position die Position relativ zum DOM-Objekt mit 'id'. Moeglich ist 'bottom', 'after',
	 *                        'before' oder 'top'. Default ist 'after'.
	 */
	startLoadingAnimation: function(id) {
		if (arguments[1]) {
			position = arguments[1];
		} else {
			position = 'after';
		}
		insertion = Insertion.After;
		switch (position) {
			case "before":
				insertion = Insertion.Before;
			case "top":
				insertion = Insertion.Top;
			case "bottom":
				insertion = Insertion.Bottom;
		}
		new insertion(id, '<img src="'+Cist.resource_uri+'images/loading_animation.gif" alt="loading..." id="cist_ajax_loading_'+id+'" />');
	},
	
	/**
	 * stoppt eine zuvor mittels CistHtml.startLoadingAnimation() gestartete Load-Animation
	 */
	stopLoadingAnimation: function(id) {
		var element = $('cist_ajax_loading_' + id);
		if (element) {
			element.parentNode.removeChild(element);
		}
	},
	
	openWindowAtMousePosition: function(event, url, width, height) {
		var windowArguments= 'width='+width+',height='+height+',resizable=1,status=0,toolbar=0,scrollbars=1,menubar=0';
		pointerX = Event.pointerX(event);
		pointerY = Event.pointerY(event);
		var w=window.open(url, 'cist', windowArguments); w.moveTo(pointerX-(width/2), pointerY);
		w.focus();
	},
	
	/**
	 * positioniert element1 relativ zu element2
	 * Groesstenteils uebernommen von tooltip.js (http://tooltip.crtx.org/)
	 * 
	 * Beispiel:
	 * <a href="#" onmouseover="CistHtml.displayElementAtMousePosition($('tooltip_3'), event.target, 20, 20)">link</a>
	 * @param string element1 die Id des zu anzeigenden Elements
	 * @param string element2 die Id des anderen Elements, zu dem element1 positioniert werden soll
	 * @param int offset_x (fakultativ) der gewuenschte horizontale Abstand zu element2
	 * @param int offset_y (fakultativ) der gewuenschte vertikale Abstand zu element2
	 */
	displayElementAtPosition: function(element1_id, element2_id, offset_x, offset_y) {
		var element1 = $(element1_id);
		var element2 = $(element2_id);
		var left_top = Position.positionedOffset(element2);
		var left = left_top[0];
		var top = left_top[1];
		
		element1Dimensions = element1.getDimensions();
		element1Width = element1Dimensions.width;

		var winWidth, winHeight, d=document;
		if (typeof window.innerWidth!='undefined') {
			winWidth = window.innerWidth;
			winHeight = window.innerHeight;
		} else {
			if (d.documentElement && typeof d.documentElement.clientWidth!='undefined' && d.documentElement.clientWidth!=0) {
				winWidth = d.documentElement.clientWidth
				winHeight = d.documentElement.clientHeight
			} else {
				if (d.body && typeof d.body.clientWidth!='undefined') {
					winWidth = d.body.clientWidth
					winHeight = d.body.clientHeight
				}
			}
		}

		if (offset_x) {
			left = left + offset_x;
		}
		if (offset_y) {
			top = top + offset_y;
		}

		// Make sure element1 doesn't go off the page. The 1.2 comes from Trial and error. 
		// We don't track the height, its possible (and much more common) that the height of an item will be more than the browser pane
		if ((left + parseInt(element1Width)) > winWidth) {
			left = winWidth - parseInt(element1Width) * 1.2;
		}
		element1.style.top = top + "px";
		element1.style.left = left + "px";
		element1.show();
	}
	
}

var CistData = {
	/**
	 * lade per XML ueber AJAX von einem bestimmten content_type
	 *
	 * Beispiel:
	 * CistData.load(CistHtml.changeSelectOptionsComplete, {content_type: 'stelle', field_id: 3})
	 * 
	 * @param Function functionOnComplete bei abgeschlossenem Ajax-Request wird functionOnComplete(request, internArguments, data) aufgerufen
	 *                                    mit request: XmlHttpRequest-Objekt, data: Array von Objects
	 * @param Object arguments argumente, welche beim Ajax-Call als Url-Paramter mitgegeben werden. Einziges Argument, 
	 *                         welches wirklich benoetigt wird, ist content_type. Um das Resultatset einzuschraenken 
	 *                         kann z.B. field_id:5 das Feld "id" eingeschraenkt werden
	 * @param Object internArguments wird danach an functionOnComplete uebergeben (dient dazu, herauszufinden was der
	 *                               urspruengliche Request fuer den Ajax-Call war
	 */
	load: function(functionOnComplete, arguments, internArguments) {
		internArguments.afterLoadComplete = functionOnComplete;
		var pars = $H(arguments).toQueryString();
		var url = Cist.rpc_url + 'load';
		var myAjax = new Cist.AjaxRequest(url, {method: 'get', parameters: pars, onComplete: CistData.loadComplete}, internArguments);
	},
	
	/**
	 * verarbeitet Ajax-Response von CistData.load
	 */
	loadComplete: function(request, internArguments) {
  		var items = request.responseXML.getElementsByTagName("row");
  		var data = [];
		for (var i=0; i<items.length; i++) {
			var item = items[i];
			data = data.concat(getElementAttributes(item));
		}
		onCompleteFunction = internArguments.afterLoadComplete;
		delete internArguments.afterLoadComplete;
		onCompleteFunction(request, internArguments, data);
	}, 
	
	/**
	 * ermittle SelectOptions via CistData.load()
	 * 
	 * Beispiel (laedt SelectOptions von ContentType 'attributwert' mit der WhereClause fk_attributname=?):
	 * CistData.getSelectOptions(myFunc, {keyColumn: 'id', valColumn: 'wert', content_type: 'attributwert', field_fk_attributname:$F('fk_attributname')}})
	 * 
	 * @param Function functionOnComplete bei abgeschlossenem Ajax-Request wird functionOnComplete(request, data) aufgerufen
	 *                                    mit request: XmlHttpRequest-Objekt, data: Array von Objects mit Keys 'key' und 'value'
	 * @param Object arguments Argumente, welche an CistData.load() uebergeben werden, keys:
	 *                         - content_type (zwingend)
	 *                         - keyColumn (zwingend): die key-Spalte des ContentTypes, woher die Daten geholt werden
	 *                         - valColumn (zwingend): die Werte-Spalte des ContentTypes, woher die Daten geholt werden
	 *                         - field_xyz: um das Resultset weiter einzuschraenken: {field_xyz: wert} benuetzen
	 */
	getSelectOptions: function(functionOnComplete, arguments, internArguments) {
		internArguments.keyColumn = arguments.keyColumn;
		internArguments.valColumn = arguments.valColumn;
		delete arguments.keyColumn;
		delete arguments.valColumn;
		internArguments.afterSelectComplete = functionOnComplete;
		CistData.load(CistData.getSelectOptionsComplete, arguments, internArguments);
	}, 
	
	/**
	 * verarbeitet Ajax-Response von CistData.getSelectOptions
	 */
	getSelectOptionsComplete: function(request, internArguments, data) {
		var keyColumn = internArguments.keyColumn;
		var valColumn = internArguments.valColumn;
		delete internArguments.keyColumn;
		delete internArguments.valColumn;
		var result = {};
		for (i=0; i<data.length; i++) {
			row = data[i];
			result[row[keyColumn]] = row[valColumn];
		}
		onCompleteFunction = internArguments.afterSelectComplete;
		delete internArguments.afterSelectComplete;
		onCompleteFunction(request, internArguments, result);
	}
}

/**
 * setzt einen Ajax-Request ab, speichert sich die dabei verwendeten Arguments
 * 
 * Beispiel:
 * var pars = ['content_type=stelle', 'id=2'].join('&');
 * var url = Cist.rpc_url + 'load';
 * var myAjax = new Cist.AjaxRequest(url, {method: 'get', parameters: pars, onComplete: CistData.loadComplete}, {parameters: pars});
 * 
 * falls der Ajax-Call erfolgreich abgesetzt werden konnte, wird in diesem Beispiel
 * Cist.loadComplete(xmlHttpRequestObject, {parameters: pars})
 * aufgerufen
 * 
 * @param String url der Url, an den der Ajax-Request geht
 * @param Object ajaxArguments Objekt, welches an Ajax.Request() uebergeben wird. Von den onXYZ-Properties bitte nur
 *                             onComplete setzen
 * @param Object internArguments
 */
Cist.AjaxRequest = function(url, ajaxArguments, internArguments) {
  this.internArguments = internArguments;
  this.callOnComplete = ajaxArguments.onComplete;
  this.onComplete = function(request) {
    this.callOnComplete(request, this.internArguments);
  }
  ajaxArguments.onComplete = this.onComplete.bind(this);
  var myAjax = new Ajax.Request(url, ajaxArguments);
}


/**
 * gibt die attribute eines DOM-Elements als Objekt zurueck
 * @param element DOM-Element
 */
function getElementAttributes(element) {
	var result = {};
	for (var i=0; i<element.attributes.length; i++) {
		attribute = element.attributes[i];
		result[attribute.name] = attribute.value;
	}
	return result;
}


function ajaxSucc(request,settings) {
		var targ = jQuery(request.target).parent();
		var ftarg = null;
		jQuery(targ).empty();
		jQuery(targ).append(settings.responseText);	
		ftarg = jQuery(targ).find("form");
		jQuery(".ajaxedit").unbind();
		jQuery(ftarg).submit( function() { 		
		  	jQuery(this).append('<input type="hidden" name="ajax" value="1" />');
		  	var sub = jQuery(this).find(":submit").attr("name");
		  	jQuery(this).append('<input type="hidden" name="' + sub + '" value="1" />');
			var options = { 
				target: jQuery(this).parent(),		
				success: function(request) {
					jQuery(".ajaxedit").unbind();
					dothefilter();
				}
			};
		  	jQuery(this).ajaxSubmit(options);
		  	return false;
		} );
	};
	
function ajaxSubmitted(ajaxeditplain, ftarg, request) {
	if (request.indexOf('"error"') > -1) {
		var fparent = ftarg.parent();
		fparent.empty();
		fparent.append(request);
		ftarg = fparent.find("form");
		if (ftarg.is("form")) {
			ftarg.submit(function() {
				ajaxDoSubmit(ftarg, ajaxeditplain);
				return false;
			});	
		}
		else {
			alert('Falsche Anwort fom Server');
		}
		
	} else {
		if (request.indexOf('"ajaxedit_plain"') > -1) {
			ajaxeditplain = ajaxeditplain.parent();
		}
		ajaxeditplain.empty();
		ajaxeditplain.append(request);
		dothefilter();
	}
};	
	
function ajaxDoSubmit(ftarg, ajaxeditplain) {
 	ftarg.append('<input type="hidden" name="ajax" value="1" />');
  	var sub = ftarg.find(":submit").attr("name");
  	ftarg.append('<input type="hidden" name="' + sub + '" value="1" />');
  	
	var options = { 
		success: function(request) {
			ajaxSubmitted(ajaxeditplain, ftarg, request);
		}
	};
  	ftarg.ajaxSubmit(options);
  	return false;
}

function ajaxSuccPlain(who, request,settings) {
//		var targ = jQuery(request.target);
		var targ = who;
		var ftarg = null;
		who.unbind();
		jQuery(targ).empty();
		jQuery(targ).append(settings.responseText);
//		jQuery(".ajaxedit_plain").unbind();
		ftarg = jQuery(targ).find("form");	
                var hastinymce= jQuery(targ).find(".cist_edit_textarea,.tinymce").is(".tinymce");
		jQuery(ftarg).submit(function() {
                   var hastinymce= jQuery(targ).find(".cist_edit_textarea,.tinymce").is(".tinymce");
                   if (hastinymce) {
     			elid= jQuery(targ).find(".tinymce").attr("id");
			var tiny= tinyMCE.getInstanceById(elid);
                        //skip_cleanup= false, skip_callback=true
			tiny.triggerSave(true, true);
//                        tinyMCE.triggerSave();
                   }
		   ajaxDoSubmit(ftarg, targ);
		   return false;
		});
                if (hastinymce) {
                  elid= jQuery(targ).find(".tinymce").attr("id");
                  tinyMCE.execCommand("mceAddControl", true, elid);
                }
	};
	
function ajaxNull(request,settings) {
console.debug(request);
}

function dothefilter() {
	jQuery(".ajaxedit").click(function() {
		
			//var ajaxmeta = jQuery(this).parent().find("div").filter(".ajaxmeta").html();
		var ajaxmeta = jQuery(this).prev().html();
		jQuery(this).ajaxSuccess(ajaxSucc);
		jQuery.ajax({
			type: "GET",
			url: "/cistern/?ajax=1&" + this.id + ajaxmeta,
			dataType: "html"
		});
	});
	
	jQuery(".ajaxedit_plain").click(function() {
		var ajPlain = jQuery(this);		
		jQuery(this).ajaxSuccess(function(request,settings) {
			ajaxSuccPlain(ajPlain, request, settings);
		});
		var ajaxmeta = jQuery(this).children(".ajaxmeta").html();
		//alert("/cistern/?go=view_edit_content&ajax=1&" + this.id + ajaxmeta);
		jQuery.ajax({
			type: "GET",
			url: this.id + ajaxmeta,
			dataType: "html"
		});		
	});
	
}

jQuery(document).ready(function() {

	dothefilter();
});
	

