/*
 * 
 * Copyright 2009 by Wochenanzeiger Muenchen GmbH Marketing und Publishing
 * http://www.mp-muenchen.de
 * 
 */

Ext.namespace('Qcat');

Qcat.CancelButton = Ext.extend(Ext.Button, {
	constructor:function(config) {
		if(config.pnlgc && config.renderTo == null) {
			config.renderTo = Ext.getCmp(config.pnlgc).getEl().child(".form-field-cancel");
		}
		Ext.applyIf(config,{
			text:'Abbrechen',
			icon: Qcat.BASE_URL + '/images/qcat/tbbtn/remove.png',
			cls: 'x-btn-text-icon', 
			iconAlign: 'left',
			scale: 'medium',
			handler: function(btn, e) {
				Ext.getCmp('main-tabs').remove(Ext.getCmp('main-tabs').getActiveTab(), true);
			}
		});
		Qcat.CancelButton.superclass.constructor.apply(this, [config]);
	}
});
		
Qcat.SubmitButton = Ext.extend(Ext.Button, {
	constructor:function(config) {
		if(config.pnlgc && config.renderTo == null) {
			config.renderTo = Ext.getCmp(config.pnlgc).getEl().child(".form-field-submit");
		}
		Ext.applyIf(config,{
			text:'Speichern',
			icon: Qcat.BASE_URL + '/images/qcat/tbbtn/save.png',
			cls: 'x-btn-text-icon', 
			iconAlign: 'left',
			scale: 'medium',
			handler: function(btn, e) {
				if(gridactions) {
					gridactions.executeAction('save');
				}
			}
		});
		Qcat.CancelButton.superclass.constructor.apply(this, [config]);
	}
});

Qcat.ImgGridPanel = Ext.extend(Ext.grid.EditorGridPanel, {
	constructor:function(config) {
		
		// TODO check if el or dom config.applyToRowId == null && 
		if(typeof config.applyToRowId == 'undefined' && config.renderTo.dom.innerHTML != '') {
			config.applyToRowId = config.renderTo.dom.innerHTML;
			config.renderTo.dom.innerHTML  = '';
		}
		var myconf = Ext.apply({
			ds: new Ext.data.Store({
				proxy: new Ext.data.HttpProxy({
					url: config.url
				}),
				sortInfo: {field: "img_rank", direction: "ASC"},
				reader: new Ext.data.JsonReader({id: 'img_id'}, Ext.data.Record.create([                         
					{name: 'img_id', type: 'int'},
					{name: 'img_text'},
					{name: 'img_author'},
					{name: 'img_url'},
					{name: 'img_width', type: 'int'},
					{name: 'img_height', type: 'int'},
					{name: 'img_gallery', type: 'int'},
					{name: 'img_rank', type: 'int'}
				]))
			}),
			cm: new Ext.grid.ColumnModel([
				{header: '#', dataIndex: 'img_id', width: 30, hidden:true},
				{header: 'Text', dataIndex: 'img_text', width: 260, editor: new Ext.grid.GridEditor(new Ext.form.TextArea({allowBlank: true}))},
				{header: 'Autor', dataIndex: 'img_author', width: 100, editor: new Ext.grid.GridEditor(new Ext.form.TextArea({allowBlank: true}))},
				{header: 'Bild', dataIndex: 'img_url', renderer: function(src) {return (src) ? '<img src="'+src+'" height="45" />' : '';}, width: 180, align:'center'},
				{header: 'Breite', dataIndex: 'img_width', width: 60},
				{header: 'H&ouml;he', dataIndex: 'img_height', width: 60},
				{header: 'Galerie', dataIndex: 'img_gallery', width: 60, renderer: Qcat.Rnd.formatActive},
				{header: 'Rang', dataIndex: 'img_rank', width: 30, hidden:true}
			]),
			sm: new Ext.grid.RowSelectionModel(),
			cls:'imgs-grid-pnl',
			autoScroll: true,           
			height:250,
			width:760,
			viewConfig: {
				forceFit: true
			},
			bbar:[
				{text:'Medien hinzuf&uuml;gen', icon:Qcat.BASE_URL + '/images/qcat/menu/drop-add.gif', cls:'x-btn-text-icon' ,xType:'tbbutton', scope:this, handler: function(btn, e) {
					var gridid = this.id;
					Qcat.MediaDialog.show(Ext.apply({multiple:true, url:Qcat.BASE_URL + '/Media/index/getnodes', treeBaseParams:{loc:'sMedia'}, handler: function(vnode, obj) {
							var store = Ext.getCmp(gridid).getStore();
							var rec = store.recordType;
							for(var i=0; i < vnode.length; i++) {
								var rank = store.getCount() + 1;
								var rec2 = new rec({img_text:vnode[i].text, img_author:vnode[i].author, img_url:vnode[i].url, img_width:vnode[i].width, img_height:vnode[i].height, img_rank:rank});   
									store.add([rec2]);
							}
							var index = store.indexOf(rec2) - vnode.length + 1;
							Ext.getCmp(gridid).startEditing(index, 1);
							Qcat.MediaDialog.hide();
						}
					}, config.mediaDlg));
				}},
				{xtype:'tbseparator'},
				{text: 'Medien entfernen', icon:Qcat.BASE_URL + '/images/qcat/menu/delete.gif', cls:'x-btn-text-icon', scope:this, handler: function(btn, e){
						this.getStore().remove(this.getSelectionModel().getSelected());
					}
				},
				{xtype:'tbseparator'},
				{text: 'Medien Vorschau', icon:Qcat.BASE_URL + '/images/qcat/menu/preview.png', cls:'x-btn-text-icon', scope:this, handler: function(btn, e){
				  Qcat.Media.showImg(this.getSelectionModel().getSelected().data.img_url);
				}},
				{xtype:'tbseparator'},
				{text: 'Medien nach oben', icon:Qcat.BASE_URL + '/images/qcat/menu/arrow_up_sm.gif', cls:'x-btn-text-icon', scope:this, handler: function(btn, e){
				//var grid = Ext.getCmp(btn.gridid);
					Qcat.FormHelper.moveGridRows(this, 'up', 'img_rank');
				}},
				{xtype:'tbseparator'},
				{text: 'Medien nach unten', icon:Qcat.BASE_URL + '/images/qcat/menu/arrow_down_sm.gif', cls:'x-btn-text-icon', scope:this, handler: function(btn, e){
					Qcat.FormHelper.moveGridRows(this, 'down', 'img_rank');
				}},
				{xtype:'tbseparator'},
				{text: 'Galerie an / aus ', scope:this, handler: function(btn, e){
					var selected = this.getSelectionModel().getSelected();
					selected.set('img_gallery', (selected.get('img_gallery')==1)?0:1);
				}}
			]
		}, config);
		Qcat.ImgGridPanel.superclass.constructor.apply(this, [myconf]);
	},
	/*
	initComponent:function() {
		Qcat.ImgGridPanel.superclass.initComponent.apply(this, arguments);
	},	
	*/    
	onRender:function() {
		Qcat.ImgGridPanel.superclass.onRender.apply(this, arguments);
		if(this.applyToRowId) {
			this.store.load({params:{id:this.applyToRowId}})
		}
	}
});
 
// register xtype
Ext.reg('imggridpanel', Qcat.ImgGridPanel);


/*
 * config see Ext.form.ComboBox
 * config.controller = url for store
 * config.modeParam = value for request param mode 
 */
Qcat.StreetCombo = Ext.extend(Ext.form.ComboBox, {
	constructor:function(config) {
		var controller = config.controller || '/Places/index/getaddressdata';
		var modeParam = config.modeParam || 'street';
		Ext.applyIf(config,{
			store: new Ext.data.Store({
				baseParams:{mode:modeParam},
				proxy: new Ext.data.HttpProxy({
			  		url: Qcat.BASE_URL + controller
		 		}),
		 		reader: new Ext.data.JsonReader({id: 'streets_id'}, [{name: 'streets_id'},{name: 'street'},{name: 'quarters_plz'},{name: 'quarter'}])
			}), 
			displayField:'street', 
			typeAhead: false, 
			hideTrigger:true, 
			minChars:2, 
			triggerAction: 'all', 
			width:500, 
			listWidth:500,
			tpl: '<tpl for="."><div class="x-combo-list-item" style="width:400px">{street} <span style="color:gray">{quarters_plz} {quarter}</span> </div></tpl>',
			listeners:{
				select: function(combo, record, index) {
					var form = combo.getEl().up("form");
					form.child("input[@name*='places_quarter']", true).value = record.data.quarter;
					form.child("input[@name*='quarters_plz']", true).value = record.data.quarters_plz;
				}
			}
		});
		Qcat.StreetCombo.superclass.constructor.apply(this, [config]);
	}
});


Qcat.ZipCombo = Ext.extend(Qcat.StreetCombo, {
	constructor:function(config) {
		Ext.applyIf(config,{
			modeParam:'plz',
			width:50, 
			displayField:'quarters_plz',
			tpl: '<tpl for="."><div class="x-combo-list-item" style="width:400px">{quarters_plz} {quarter} {quarters_plz} {quarter}</div></tpl>'
		});
		Qcat.ZipCombo.superclass.constructor.apply(this, [config]);
	}
});
Qcat.PlacesCombo = Ext.extend(Ext.form.ComboBox, {
	constructor:function(config) {
		var controller = config.controller || '/Places/index/getlocationsforcombo/';
		Ext.applyIf(config,{
			store: new Ext.data.Store({
				baseParams:{},
					proxy: new Ext.data.HttpProxy({
						url: Qcat.BASE_URL + controller,
				  	disableCaching:true
			 	}),
			 	reader: new Ext.data.JsonReader({id: 'places_id'}, [{name: 'places_id'}, {name: 'places_title'},{name: 'quarters_plz'},{name: 'street'}])
			}),
			displayField:'places_title', 
			forceSelection:true,
			typeAhead: false, 
			hideTrigger:false, 
			minChars:3, 
			triggerAction: 'all', 
			width:700, 
			listWidth:700,
			tpl: '<tpl for="."><div class="x-combo-list-item" style="width:700px"><b>{places_title}</b> <small>{quarters_plz} {street}</small></div></tpl>',
			listeners:{
				select: function(combo, record, index) {
					var form = combo.getEl().up("form");
					form.child("input[@name='places_combo_id']", true).value = record.id;
					this.fireEvent('afterselect', combo, record, index);
				}
			}
		});
		Qcat.PlacesCombo.superclass.constructor.apply(this, [config]);
	}
});


String.prototype.ellipse = function(maxLength){
	if(this.length > maxLength){
		return this.substr(0, maxLength-3) + '...';
	}
	return this;
};

String.prototype.lpisec = function( str ) {  
	var si = 0;
	for ( var i = 0; i < this.length; i++ ) {
		if(this[i] == '/') {
			si = i;
		}
		if(this[i] !== str[i]) {
			return this.substr(0, si);
		}
	}  
	return String(this);  
};
Ext.data.Node.prototype.getPath = function(attr){
	attr = attr || this.getOwnerTree().pathAttr || "id";
	var p = this.parentNode;
	var b = [this.attributes[attr]];
	while(p){
		if(p.attributes[attr]) {
			b.unshift(p.attributes[attr]);
		}
		p = p.parentNode;
	}
	var sep = this.getOwnerTree().pathSeparator;
	return sep + b.join(sep);
}






Qcat.Rnd = {
	
	formatActive: function(val) {
		//var val = (!val) 0 : 1;
		var img = (!val || val == 0) ? 'inactive_7x7.gif' : 'active_7x7.gif';
	   	return '<img src="' + Qcat.BASE_URL + '/images/qcat/misc/' + img + '" height="7" width="7" vspace="3" alt="" />';
	},
	expireDate: function (date) {
		if(date=='') return '';
		var fDate = date.format('d.m.Y');
		if(fDate == '31.12.2020' || fDate == '01.01.2020') return '';
		var now = new Date();
		if(now.format('Ymd') > date.format('Ymd')){
			return '<span style="color:red">' + fDate + '</span>';
		} else {
			return fDate;
		}
	},
	startDate: function(date) {
		if(date=='') return '';
		var fDate = date.format('d.m.Y');
		if(fDate == '01.01.2000') return '';
		var now = new Date();
		if(now.format('Ymd') >= date.format('Ymd')){
			return '<span style="color:green">' + fDate + '</span>';
		} else {
			return fDate;
		}
	},
   	datenrm: function (date) {
		if(date && typeof date.format == "function"){
			return date.format('d.m.Y');
		}
		return '';
   	},
   	datetime: function (datetime) {
		if(datetime=='') return '';
		var fDate = datetime.format('d.m.Y H:i');
		if(fDate == '01.01.1970 00:00') {
			return '';
		} else {
			return fDate;
		}
   	},
	euro: function(v){
		v = (Math.round((v-0)*100))/100;
		v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
		v = String(v);
//	    v = v.toString(2);
		var ps = v.split('.');
		var whole = ps[0];
		var sub = ps[1] ? ','+ ps[1] : ',00';
		var r = /(\d+)(\d{3})/;
		while (r.test(whole)) {
			whole = whole.replace(r, '$1' + '.' + '$2');
		}
		v = whole + sub;
		if(v.charAt(0) == '-'){
			return '-' + v.substr(1) + ' &euro;';
		}
		return v + ' &euro;';
	},
	discount: function(value) {
		return (value) ? value + ' %' : value;
	},
	imgpreview: function(src, height) {
		var height = height || 50;
		return (src) ? '<img src="'+src+'" height="' + height + '" />' : '';
	}
}

Qcat.Status = {
	timeout: 2000,
	handleto:null,
	statemsg:null,
	setConfirm: function(msg) {
		this.statemsg = msg;
	},
	unsetConfirm: function() {
		this.statemsg = null;
	},
	confirmExit: function() {
		if (Qcat.Status.statemsg) {
			return Qcat.Status.statemsg;
		}
	}
	
}
window.onbeforeunload = Qcat.Status.confirmExit;

Qcat.FileWindow = Ext.extend(Ext.Window, {
	constructor:function(config, treeConfig) {
		var controller = config.controller || '/Places/index/getaddressdata';
		var modeParam = config.modeParam || 'street';
		
		this.putNode = function () {
			var node = this.items[0].getSelectionModel().getSelectedNode();
			this.fireEvent('confirmdlg',this, node);
		}
		var tc = Ext.apply({
			pathAttr:'dir', 
			region: 'center', 
			id:'file-dlg-tree', 
			split:true, 
			width:150, 
			animate:true, 
			enableDD:false, 
			autoScroll: true, 
			rootVisible:false
		}, treeConfig);
		var tree = new Ext.tree.TreePanel(tc);
		var root = new Ext.tree.AsyncTreeNode({
			text: 'Gesamt',
			draggable:false,
			id:'n0',
			dir:'n0'
		});
		tree.setRootNode(root);	 
		new Ext.tree.TreeSorter(tree, {folderSort: true});
		Ext.applyIf(config,{
			title:'Auswahl',
			width:400,
			height:350,
			closable: false,
			border:false,
			plain: true,
			layout: 'border',
			buttons: [ 
			{text: 'Ok', handler: putNodeId, scope:this},
			{text: 'Abbrechen', handler: function() {this.hide();}, scope:this}],
			items: [tree]
		});
		Qcat.FileWindow.superclass.constructor.apply(this, [config]);
	}
});


Qcat.FileDialog = {
	show: function (treeConfig, fn, fnparams) {
		function putNodeId() {
			var node = this.tree.getSelectionModel().getSelectedNode();
			if(node!=null) {
				if(typeof this.fn=='string') this.fn = eval(this.fn);
				this.fn.call(this,node,this.fnparams);
			}

		}
		if(this.dialog) {
			this.dialog.destroy();
		}
		var tc = Ext.apply({
			useArrows: true,
			pathAttr:'dir', 
			region: 'center', 
			id:'file-dlg-tree', 
			split:true, 
			width:150, 
			animate:true, 
			enableDD:false, 
			autoScroll: true, 
			rootVisible:false
		}, treeConfig);
		this.tree = new Ext.tree.TreePanel(tc);
		var root = new Ext.tree.AsyncTreeNode({
			text: 'Gesamt',
			draggable:false,
			id:'n0',
			dir:'n0'
		});
		this.tree.setRootNode(root);	 
		new Ext.tree.TreeSorter(this.tree, {folderSort: true});
		this.tree.getLoader().on("beforeload", function(treeLoader, node) {
			treeLoader.baseParams.path = node.getPath();
		}, this);
		if(treeConfig.preSelPath && treeConfig.preSelPath != '') {
			try {
				this.tree.expandPath(treeConfig.preSelPath, 'id', function(bSuccess, oLastNode) {
					if(bSuccess == true) {
						oLastNode.select();
					}
				})
			} catch (e) {
				root.expand();
			}
		} else {
			root.expand();
		}

		
		this.dialog = new Ext.Window({
			title:'Auswahl',
			width:400,
			height:350,
			closable: false,
			border:false,
			plain: true,
			layout: 'border',
			buttons: [ 
			{text: 'Ok', handler: putNodeId, scope:Qcat.FileDialog},
			{text: 'Abbrechen', handler: function() {this.dialog.hide(fnparams.id || '');}, scope:Qcat.FileDialog}],
			items: [this.tree]
		});
		this.dialog.render(document.body);
		this.fn = fn;
		this.fnparams = fnparams;
		this.dialog.toFront();
		this.dialog.show(fnparams.id || '');
	},
	hide: function()
	{	 	
		this.dialog.hide();
		this.dialog.toBack();
	}
}

Qcat.ItemsDialog = {
	show: function (treeConfig, storeConfig, fn, fnparams) {
		function putNodeId() {
			var node = this.tree.getSelectionModel().getSelectedNode();
			var vnodes = this.view.getSelectedRecords();

			if(node!=null && vnodes!=null) {
				if(this.multiple) {
					var vnode = [];
					for(var i=0; i < vnodes.length; i++) {
						vnode.push(vnodes[i].data);
					}
				} else {
					var vnode = vnodes[0].data;
				}
				if(typeof this.fn=='string') this.fn = eval(this.fn);
				this.fn.call(this,node,vnode,this.fnparams);
			}

		}
		if(this.dialog) {
			this.dialog.destroy();
		}
		var tc = Ext.apply({
			region:'west',
			cls:'no-leaf-img',
			split:true, 
			width:150, 
			animate:true, 
			enableDD:false, 
			autoScroll: true, 
			rootVisible:false
		}, treeConfig);
		this.tree = new Ext.tree.TreePanel(tc);
		var root = new Ext.tree.AsyncTreeNode({
			text: 'Gesamt',
			draggable:false,
			id:'n0',
			dir:'n0'
		});
		this.tree.setRootNode(root);	 
		new Ext.tree.TreeSorter(this.tree);
		this.tree.getLoader().on("beforeload", function(treeLoader, node) {
			treeLoader.baseParams.path = node.getPath();
		}, this);
		if(treeConfig.preSelPath && treeConfig.preSelPath != '') {
			try {
				this.tree.expandPath(treeConfig.preSelPath, 'id', function(bSuccess, oLastNode) {
					if(bSuccess == true) {
						oLastNode.select();
					}
				})
			} catch (e) {
				root.expand();
			}
		} else {
			root.expand();
		}
		var sc = Ext.apply({
			autoLoad: false,
			sortInfo:{field: storeConfig.fields[1], direction: "ASC"}
		}, storeConfig);
		this.view = new Ext.DataView({
			itemSelector: 'div.dlg-view-row',
			cls:'item-dlg',
			style:'overflow:auto',
			multiSelect: true,
			store: new Ext.data.JsonStore(sc),
			tpl: new Ext.XTemplate(
				'<tpl for=".">',
				'<div class="dlg-view-row">',
				'<div class="thumb">{' + sc.fields[1] + '}</div>',
				'</div>',
				'</tpl>'
			)
		});
		this.tree.on('click', function(node){
			var store = Qcat.ItemsDialog.view.store;
			store.baseParams = {node:node.id, path:node.getPath()};
			store.load();
		});
		var panel = new Ext.Panel({region:'center', layout:'fit', items: this.view});
		this.dialog = new Ext.Window({
			title:'Auswahl',
			width:600,
			height:350,
			closable: false,
			border: false,
			plain: true,
			layout: 'border',
			buttons: [ 
			{text: 'Ok', handler: putNodeId, scope:this},
			{text: 'Abbrechen', handler: function() {this.dialog.hide();}, scope:Qcat.ItemsDialog}],
			items: [this.tree, panel]
		});
		this.dialog.render(document.body);
		this.fn = fn;
		this.fnparams = fnparams;
		this.dialog.toFront();
		this.dialog.show();
	},
	hide: function()
	{	 	
		this.dialog.hide();
		this.dialog.toBack();
	}
}




//show config-params = treeBaseParams, url, animId, targetId, handler, handlerParams

Qcat.ImgDataView = function(config){
	Qcat.ImgDataView.superclass.constructor.call(this, config);
};

Ext.extend(Qcat.ImgDataView, Ext.DataView, {
	loadingText:'Bilder werden geladen...',
	prepareData: function(data){
		switch(data.type) {
			case 0: case 1: case 2: case 3:
			data.rurl = data.url;
			break;
			case 4:
			var suffix = data.url.substr(data.url.length - 3, data.url.length);
			if(suffix.toLowerCase() == 'flv') {
				data.rurl = Qcat.BASE_URL + "/images/qcat/misc/video.png";
				data.rwidth = 40;
			} else {
				data.rurl = Qcat.BASE_URL + "/images/qcat/misc/flash.gif";
				data.rwidth = 35;
			}
			data.rheight = 40;
			data.vspace = 20;
			break;
			default:
			var suffix = data.url.substr(data.url.length - 3, data.url.length);
			if(suffix.toLowerCase() == 'pdf') {
				data.rurl = Qcat.BASE_URL + "/images/qcat/misc/pdficon_large.gif";
				data.rheight = 32;
				data.rwidth = 32;
				data.vspace = 22;
			} else {
				data.rurl = Qcat.BASE_URL + "/images/qcat/misc/media.gif";
				data.rheight = 27;
				data.rwidth = 30;
				data.vspace = 26;
			}
		}
		var info = (data.name) ? data.name : data.file;
		data.shortName = (info) ? info.ellipse(15) : '';
		return data;
	}
});


Qcat.MediaHelper = function(config){

	Qcat.MediaHelper.superclass.constructor.call(this);
	this.addEvents(
			/**
			 * @event validate
			 * Fires when validating actions
			 */
			"ajaxResponse"
	);
	if(config.listeners) {
		this.addListener(config.listeners);
	}
	delete config.listeners;
	// apply config
	Ext.apply(this, config, {
		attrToSelect:null
	});
};

Ext.extend(Qcat.MediaHelper, Ext.util.Observable, {
	_ajaxCb: function (options, success, response) {
		var response = eval('(' + response.responseText + ')');
		if(response['alert']&&response['alert']!='') {
			Ext.Msg.alert('Fehler', response['alert']);
		} else {
			this.getView().store.reload();
		}
		this.fireEvent("ajaxResponse", this.lastAction);
		this.lastAction = null;
	},
	getUrl: function(action, node) {
		var modulePath = (this.module) ? '/' + this.module : '';
		var ctrlPath = (this.controller) ? '/' + this.controller : '';
		var url = Qcat.BASE_URL + modulePath + ctrlPath + '/' + action + 'row';
		if(node) {
			url += '?node=' +encodeURIComponent(node.id)+'&path=' +encodeURIComponent(node.getPath());
		}
		return url;
	},
	getView: function() {
		return Ext.getCmp(this.applyTo);
	},
	getSelectedImages: function (){
		var files = [];
		var imgs = this.getView().getSelectedNodes();
		for(var i=0; i < imgs.length; i++) {
			files.push(imgs[i].id); //encodeURIComponent()
		}
	   	return files;
	},
	move: function(oldNode, newNode, mode) {
		if(!mode) var mode = 'cut';
		Ext.Ajax.request({
			url: this.getUrl(mode), 
			method:'POST', 
			params:{
				node:oldNode.id, 
				path:oldNode.getPath(), 
				newNode:newNode.id, 
				newPath:newNode.getPath(), 
				'ids[]': this.getSelectedImages()
			},
			scope: this,
			callback: this._ajaxCb
		});
	},
	remove: function(node, row) {
		
		Ext.MessageBox.confirm('Hinweis', 'Wollen Sie die markierten Dateien wirklich entfernen?', function (btn) {
			if(btn=='no') return false;
			var params = {'ids[]':this.getSelectedImages()};
			if(typeof node.getPath == 'function') {
				Ext.apply(params, {node:node.id, path:node.getPath()});
			}
			Ext.Ajax.request({
				url: this.getUrl('remove'), 
				method:'POST', 
				params:params, 
				scope: this,
				callback: this._ajaxCb
			});
			//return true;
		}, this);
	},
	upload: function(node) {
		// start swfupload
		var plugin = (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]) ? navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin : 0;
		if(typeof SWFUpload == 'function' && Qcat.SID && plugin) {
			return this.uploadswf(node);
		}
		
		// end swfupload
		this.uploadNode = node; 
		function uploadFile() {
			if(typeof this.uploadNode !== 'object') {
				Ext.Msg.alert("Fehler", "Bitte einen Ordner ausw&auml;hlen.");
				return false;
			}
			//var options = document.forms['q-upload-form'].elements['profile'].options;
			var select = Ext.get('q-upload-form').child("select");
			if(select && select.dom.options && select.dom.options.selectedIndex < 1) {
				Ext.Msg.alert("Fehler", "Bitte Profil w&auml;hlen!");
				return false;
			}
			Ext.Ajax.request({
				url: this.getUrl('upload', this.uploadNode), 
				method: 'POST', 
				form:'q-upload-form', 
				scope:this, 
				callback: function(options, success, r){
					statusdlg.hide();						
					if(r.responseText == '') {
						Ext.Msg.alert("Hinweis", "Das Bild konnte vom Server nicht bearbeitet werden.");
					} else {
						this._ajaxCb(options, success, r);
						var keywordsEl = document.getElementById('upl-img-keywords');
						if(keywordsEl) {
							keywordsEl.value = '';
						}
					}
				}
			});
			var statusdlg = Ext.Msg.wait('Datei wird hochgeladen. Bitte warten...');
			//return true;
		}
		if(!this.uploadDialog) {
			this.uploadDialog = new Ext.Window({
				renderTo:document.body, 
				title:'Medien hochladen',
				closable:true, 
				closeAction:'hide',
				autoScroll: true,
				autoHeight:true,
				layout:'fit', 
				height:210, 
				width:550, 
				autoLoad: {url:this.getUrl('getuploaddlg',this.uploadNode)}, 
				buttons:[
					{text:'OK', handler:uploadFile, scope:this},
					{text:'Abbrechen', handler:function() {this.uploadDialog.hide();}, scope:this}
				]
			});
		}
		this.uploadDialog.show();
	},
	uploadswf: function(node) { 
		var treeid = node.getOwnerTree()['id'];
		if(!this.uploadswfDialog) {
			this.uploadswfDialog = new Ext.Window({
				id:'swf-upl-dlg',
				renderTo:document.body, 
				title:'Medien hochladen',
				closable:true, 
				closeAction:'hide',
				autoScroll: true,
				autoHeight:true,
				layout:'fit', 
				height:90, 
				width:470, 
				autoLoad:{url:this.getUrl('getswfuploaddlg')}, 
				fbar:new Ext.Toolbar({items:[{xtype:'progress', id:'upl-prgr', hidden:true, width:450}]})
			});
			this.uploadswfDialog.getUpdater().on("update", function(){
				
				new SWFUpload({
					// Backend Settings
					upload_url:this.getUrl('uploadswf'),  //Qcat.BASE_URL + "/Media/index/uploadswfrow",
					post_params: {PHPSESSID : Qcat.SID},

					// File Upload Settings
					file_size_limit : "50400",	// 50MB
					file_types : "*.jpg;*.gif;*.png;*.swf;*.m4v;*.flv;*.pdf",
					file_types_description : "Medien",
					file_upload_limit : "200",
					file_queue_limit : "0",
					custom_settings : {
						treeid : treeid,
						viewid: this.applyTo
					},

					
					file_dialog_start_handler : function(){return true;},
					file_queued_handler : function(file){
						return true;
					},
					file_queue_error_handler : function(file, errorCode, message){
						Ext.Msg.alert("Fehler", file.name + 'konnte nicht eingelesen werden. Fehlercode: ' + message);
					},
					file_dialog_complete_handler : function (numFilesSelected, numFilesQueued) {
						//this.getStats().files_queued
						var extForm = new Ext.form.BasicForm('q-swfupload-form');
						var extFormVals = extForm.getValues();
						if(typeof extFormVals == 'object') {
							for(var i in extFormVals){
								this.addPostParam(i,extFormVals[i]);
							}
						}
						var node = Ext.getCmp(this.customSettings.treeid).getSelectionModel().getSelectedNode();
						this.addPostParam('node', node.id);
						this.addPostParam('path', node.getPath());
						//this.addPostParam('profile',profile);
						if(numFilesQueued > 0 && Ext.getCmp('upl-prgr').isVisible() == false) {
							this.startUpload();
							Ext.getCmp('upl-prgr').setVisible(true);
							// Ext.getCmp('upl-prgr').updateText("Starte
							// Upload...");
						}
						return true;
					},
					upload_start_handler : function(file) {
						
						Ext.getCmp('upl-prgr').updateText(this.getStats().files_queued + " Dateien ausstehend");
						return true;
					},
					upload_progress_handler : function (file, bytesLoaded, bytesTotal) {
						// this.getStats().successful_uploads   files_queued
						var prnum = (bytesLoaded / bytesTotal);
						Ext.getCmp('upl-prgr').updateProgress(prnum); // updateText
					},
					upload_error_handler : function (file, errorCode, message) {
						Ext.Msg.alert("Fehler", file.name + ' konnte nicht hochgeladen werden. Fehlercode: ' + message);
					},
					upload_complete_handler : function(file) {
						if (this.getStats().files_queued === 0) {
							Ext.getCmp('upl-prgr').setVisible(false);
							// Ext.getCmp('upl-prgr').setVisible(false);
							// Ext.getCmp('upl-status').clearStatus();
							Ext.getCmp('swf-upl-dlg').hide();
							// Qcat.Media.uploadswfDialog.hide();
							Ext.getCmp(this.customSettings.viewid).store.reload();
							// Qcat.Media.view.store.reload();
						} else {	
							this.startUpload();
						}
					},
					upload_success_handler : function(file, serverData){
						try {
							var response = Ext.decode(serverData);
							if(response.alert) {
								Ext.Msg.alert("Hinweis", response.alert);
							}
						} catch (e){}
						//Ext.getCmp('upl-prgr').wait({text:"bearbeite " + file.name});
					},
					
					
					// Button Settings
					button_image_url : Qcat.BASE_URL + "/images/qcat/misc/XPButtonUploadText_61x22.png",
					button_placeholder_id : "spanButtonPlaceholder",
					button_width: 61,
					button_height: 22,
					
					// Flash Settings
					flash_url : Qcat.BASE_URL + "/js/swfupload.swf",
					
					
					// Debug Settings
					debug: false
				});	
			}, this);
		}
		this.uploadswfDialog.show();
		//return true;
	},
	preview: function() {
		var vnodes = this.getView().getSelectedRecords();
		for (var i=0; i < vnodes.length; i++){
			var vnode = vnodes[i].data;
			
			if(vnode.url.search(/(\.swf|\.flv|\.pdf)/i)>-1) {
				this.showMedia(vnode.url);
			} else {
				this.showImg(vnode.url, vnode.file);
			}
			/*
			if(vnode.type==-1) {
				window.open(vnode.url,vnode.file,'');
				continue;
			} else {
				this.showImg(vnode.url, vnode.file);
			}
			*/
		}
	},
	search: function(skey) {
		this.getView().store.load({
			url: Qcat.BASE_URL + '/' + this.module + '/index/getimages', 
			params:{skey:skey}
		});
	},
	showImg: function(url, title, alignToEl) {
		var title = title || 'Vorschau';
		var alignToEl = alignToEl || document.body;
		if(!this.imgDialog) {
			this.imgDialog = new Ext.Window({
				renderTo:document.body, 
				closable:true, 
				layout:'fit', 
				title: title, 
				height:200, 
				width:200, 
				autoCreate:true, 
				autoScroll:true,
				autoHeight:true
			});
			this.imgDialog.getUpdater().on("update", function(){
				var width = this.getEl().select("img", true).first().dom.getAttribute('width');
				if(width > 100) {
					var clWidth = document.documentElement.clientWidth || 1000;
					var width = Math.min((clWidth - 120), width);
					width = Math.max(width,60);
					this.setWidth(width + 14);
				}
				var height = this.getEl().select("img", true).first().dom.getAttribute('height');
				var clHeight = document.documentElement.clientHeight || 900;
				if(height > (clHeight - 120)) {
					this.autoHeight = false;
					height = Math.min((clHeight - 50), height);
					height = Math.max(height,60);
					this.setHeight(height);
					this.setWidth(width + 35);
				}
			}, this.imgDialog);
			this.imgDialog.alignTo(alignToEl, 'tl');
			this.imgDialog.on('hide', function(){this.imgDialog.destroy(); this.imgDialog = null}, this);
			this.imgDialog.getUpdater().showLoadIndicator = true;
		}
		this.imgDialog.show();
		this.imgDialog.getUpdater().update({
			url:this.getUrl('getpreviewimg') + '?url=' + url
		});

	},
	showMedia: function(url) {
		if(url.search(/\.pdf/i)>-1) {
			window.open(url, 'PDF-Ansicht', '');
			return;
		}
		var html;
		if(url.search(/\.swf/i)>-1) {
			html = '<object type="application/x-shockwave-flash" data="' + url + '">\n<param name="movie" value="'+row.data.url+'" />\n<param name="wmode" value="transparent" />\n</object>';
			//width="'+row.data.width+'" height="'+row.data.height+'"
		}
		if(url.search(/\.flv/i)>-1) {
			if(typeof flowplayer != 'undefined') {
				var flowid = 'n' + Ext.id();
				html = '<div id="' + flowid + '" style="width:640px; height:480px"></div>';
			} else {
				window.open(url, 'Video-Ansicht', '');
				return;				
			}

		} 
		var dialog = new Ext.Window({
			renderTo:document.body, 
			layout:'fit', 
			title: 'Vorschau', 
			autoCreate:true, 
			autoScroll:true,
			autoHeight:true,
			html:html
		});
		dialog.show(null, function() {
			if(url.search(/\.flv/i)>-1) {
				flowplayer(flowid, Qcat.BASE_URL + '/js/flowplayer-3.2.5.swf', {
					clip: {
						url: url,
						autoPlay: true
					}
				});
			} 	
		});
	
	}
});

// backward compatibility
Qcat.Media = {
	showImg: function(url, title, alignToEl) {
		if(!this.imgprv){
			this.imgprv = new Qcat.MediaHelper({
				module: 'Media', 
				controller: 'index'
			});
		}
		if(url.search(/(\.swf|\.flv|\.pdf)/i)>-1) {
			this.imgprv.showMedia(url);
		} else {
			this.imgprv.showImg(url, title, alignToEl);
		}
		
	}
};
Qcat.MediaDialog = {
	dialog:'',
	tree:'',
	view:'',
	animId:null,
	controller:'index',
	module:'Media',
	show: function (config) {
		Ext.apply(this, config);
		function putNodeId() {
			var vnodes = this.view.getSelectedRecords();
			if(vnodes!=null) {
				if(this.multiple) {
					var vnode = [];
					for(var i=0; i < vnodes.length; i++) {
						vnode.push(vnodes[i].data);
					}
					
				} else {
					var vnode = vnodes[0].data;
				}
				if(this.handler){
					if(typeof this.handler=='string') this.handler = eval(this.handler);
					this.handler.call(this,vnode,this.handlerParams);
					return;
				}
				if(this.targetId){
					document.getElementById(this.targetId).value = vnode.url;
					this.hide();
				}
			}
		}

		if(!this.dialog) {
			//Ext.apply(Qcat.MediaDialog, {preview:Qcat.Media.preview, upload:Qcat.Media.upload, getUrl:Qcat.Media.getUrl});
			var nav = new Ext.tree.TreePanel({
				useArrows:true,
				region: 'west', 
				cls:'no-leaf-img',
				split:true,
				width:150,
				animate:true, 
				loader: new Ext.tree.TreeLoader({dataUrl:this.url, baseParams: this.treeBaseParams}),
				enableDD:false,
				autoScroll: true,
				rootVisible:false,
				pathAttr:'dir'
			});
			var root = new Ext.tree.AsyncTreeNode({
				text: 'Root',
				draggable:false,
				id:'n0',
				dir:'n0'
			});
			nav.setRootNode(root);	 
			nav.getLoader().on("beforeload", function(treeLoader, node) {
				treeLoader.baseParams.path = node.getPath();
			}, this);
			// root.expand();
			root.expand(false, true, function(node) {
				node.firstChild.expand(false, true, function(node2) {
					var year = new Date().format('Y');
					if(node2.firstChild && node2.firstChild.text == year) { // 2008, 2009, etc
						node2.firstChild.expand();
					}
				});
			});	
			var dvid = Ext.id();
			this.view = new Qcat.ImgDataView({
				id:dvid,
				itemSelector: 'div.thumb-wrap',
				style:'overflow:auto',
				multiSelect: true,
				//plugins: new Ext.DataView.DragSelector({dragSafe:true}),
				store: new Ext.data.JsonStore({
					url: Qcat.BASE_URL  + '/' + Qcat.MediaDialog.module + '/' + Qcat.MediaDialog.controller + '/getimages', 
					autoLoad: false,
					root: 'images',
					id:'name',
					fields:[
						'id', 'name', 'url', 'file', 'type', 'rurl', 'rheight', 'rwidth', 'vspace', 'shortName', 'height', 'width', 'text', 'author', 'keywords'
					],
					listeners: {
			   		   'beforeload': function(store, options) {
		  	        		if(Qcat.MediaDialog.useDb && Ext.get('bbar-search-dlg')) {
		  	         	   		Ext.apply(options.params, {
		  	         	   			query:Ext.get('bbar-search-dlg').dom.value
		  	         	   		});
		  	         	   	}
		  	        		return true;
				  		}
					  }
				}),
				tpl: new Ext.XTemplate(
					'<tpl for=".">',
					'<div class="thumb-wrap" id="{file}" title="{file}">',
					'<div class="thumb"><img src="{rurl}" alt="" ext:qtip="<p>{text}</p><p>{author}</p><p>{keywords}</p>" height="{rheight}" width="{rwidth}" vspace="{vspace}"></div>',
					'<span>{shortName}<br />{height} x {width}</span></div>',
					'</tpl>'
				)
			});
			
			this.ctrl = new Qcat.MediaHelper({
				module: this.module, 
				controller: this.controller, 
				applyTo: dvid
			});
			
			var images = new Ext.Panel({id:'images', region:'center', layout:'fit', items: Qcat.MediaDialog.view, cls:'ychooser-view'});
			this.view.on('dblclick', function(view, index, vnode, e){
				this.ctrl.preview.call(this.ctrl); 
			});	 
			nav.on('click', function(node){
				Qcat.MediaDialog.view.store.load({url: Qcat.BASE_URL + '/' + Qcat.MediaDialog.module + '/' + Qcat.MediaDialog.controller + '/getimages', params:{node:node.id,path:node.getPath()}});
			});
			var fbar = [
						{text: 'Vorschau', handler: this.ctrl.preview, scope:this.ctrl}, 
						{text: 'Ok', handler: putNodeId, scope:this},
						{text: 'Abbrechen', handler: function() {this.dialog.hide(this.animId);}, scope:Qcat.MediaDialog}
						];
			if(Qcat.MediaDialog.useDb) {
				fbar.unshift(
		 			   {id:'bbar-search-dlg', xtype:'textfield', width:150},
					   ' ', 
					   {text:'Suche', handler: function(){Qcat.MediaDialog.view.store.reload()}},
					   ' ', 
					   {text:'Suche zur&uuml;cksetzen', handler: function(){
						   Ext.get('bbar-search-dlg').dom.value = '';
						   Qcat.MediaDialog.view.store.reload();
						}},
						' '		
				);
			}
			this.dialog = new Ext.Window({
				title:'Medien',
				width:720,
				height:450,
				closable:false,
				minimizable: true,
				border:false,
				plain: true,
				layout: 'border',
				defaults: {bodyStyle: 'padding:0;'},
				fbar: fbar,
				items: [nav, images]
			});
			// if markup for upload dialog exists -> provide upload button
			// if(Ext.get('q-upload-dlg')) {
				this.dialog.addButton({text: 'Hochladen', handler: function() {
					var node = nav.getSelectionModel().getSelectedNode();
					if(node == null) {
						Ext.Msg.alert("Hinweis", "Bitte Baum ausw&aumlen!");
						return false;
					}
					this.ctrl.upload.call(this.ctrl, node);
					//return true; // TODO is that return value ok?
				}, scope:this});
			// }
			this.dialog.render(document.body);
			// var dragZone = new ImageDragZone(this.view,
			// {containerScroll:true, ddGroup: 'imagesDD'});
		}
		if(config.preSelPath && config.preSelPath != '') {
			try {
				this.dialog.items.get(0).expandPath(config.preSelPath, 'dir', function(bSuccess, oLastNode) {
					if(bSuccess == true) {
						oLastNode.select();
					}
				});
			} catch (e) {}
		} 
		this.dialog.toFront();
		this.dialog.show(this.animId);
	},
	hide: function()
	{	 	
		this.dialog.hide(this.animId);
		this.dialog.toBack();
	}
};



Qcat.Forms = {
	controller:'index',
	ajaxFail: function(o)
	{
		return false;
	},
	prepare: function(action, fn)
	{
		var panel = Qcat.Layout.inst.getComponent(2).getActiveTab();
	   	var node = Qcat.Tree.tree.getSelectionModel().getSelectedNode();
	   	if(node==null) {
	   		Ext.MessageBox.alert('Fehler', 'Kein Menüpunkt ausgewählt!', function(btn) {return;});
			return false;
		}	
		var save = eval('Qcat.Forms.' + action);
		if(!fn) {
			var fn = function(o) {
			 try {
			 	Qcat.Grid.grid.getStore().reload();
			 } catch(e){}}
		} 
		
		save.call(this, panel, {node:node.id,path:node.getPath(),id:panel.rowId}, fn); 
		
	},
	insertValues: function(el, obj) // panel.getEl().dom for el
	{
		var form = Ext.DomQuery.selectNode("form", el);
		form.reset();
		var els = Ext.DomQuery.select("input", form);
		for(var i=0; i<els.length; i++) {
			var val = obj[els[i].name] || '';
			   switch(els[i].type) {
			   case "checkbox":
				   els[i].checked = (val!=1&&val!='') ? 'checked' : '';
				   break;
			   case "radio":
				   els[i].checked = (els[i].value == val) ? 'checked' : '';
				   break;
			   default:
				   els[i].value = val;
				   break;
			   }
			
			
		}
	},
	cleanIframes: function(el) {
		if(typeof el == 'string') {
			var iframes = new Array(document.getElementById(el));
		} else {
			var iframes = el.document.getElementsByTagName("iframe");
		}
		for(var i=0; i<iframes.length; i++) {
			Qcat.Forms.cleanIframes(iframes[i].contentWindow);
			iframes[i].src = "javascript:false";
		}


	},
	fixIeBug: function() {
		var fns = Ext.Element.select("input[@class*='x-form-text']");
		fns.each(function(el,scope,index) {
			if(el.hasClass('done') == false) {
				var newel = el.wrap({tag:'div'});
				newel.wrap({tag:'fieldset',cls:'iebug'});
				el.addClass('done');
			}
		});
		fns = Ext.Element.select("textarea");
		fns.each(function(el,scope,index) {
			if(el.hasClass('done') == false) {
				var newel = el.wrap({tag:'div'});
				newel.wrap({tag:'fieldset',cls:'iebug'});
				el.addClass('done');
			}
		});
	},
	save: function(panel, params, fn) // TODO (panel, url, fn)
	{
		function cb (o, fn) {
			if(!fn) return;
			if(typeof fn=='string') fn = eval(fn);
			fn.call(this,o);
		}
		var modulePath = (this.module) ? '/' + this.module : '';
		var url =  Qcat.BASE_URL + modulePath + '/' + this.controller + '/saveForm' + '?cType=' + panel.cType + '&' + Ext.urlEncode(params);
		if(panel.cType=='tinymce') {
			var id = panel.tmplIndex ? 'tinymce'+panel.rowId+'-'+panel.tmplIndex : 'tinymce'+panel.rowId;
			var code = document.getElementById(id).contentWindow.tinyMCE.getContent('elm1');
			YAHOO.util.Connect.asyncRequest('POST', url, {success: function(o) {cb(o,fn);}, failure: Qcat.Forms.ajaxFail},'&code='+encodeURIComponent(code));
			
		} else {
			var form = Ext.DomQuery.selectNode("form", panel.getEl().dom);
			var formId = form.getAttribute('id');
			
			if(typeof formId == "object") {formId = form.getAttribute('name');}  // IE takes input with name="id" if exists
			if(typeof formId == "object") {formId = form.className;}  // IE if name="name" exists, lastChance className
			// var url = '?action=save&ctrl=Forms&node='+node.id+'&id=' +
			// panel.rowId+'&formId=' + formId+'&cType=' + panel.cType;
			
			url += '&formId=' + formId;
			var fn = fn;
			if(panel.cType=='fck') { //fck -> fckbu 
				var code = FCKeditorAPI.GetInstance('fck'+ formId).GetXHTML(true);
				YAHOO.util.Connect.setForm(formId, false);
				YAHOO.util.Connect.asyncRequest('POST', url, {success: function(o) {cb(o,fn);}, failure: Qcat.Forms.ajaxFail},'&code='+encodeURIComponent(code));
			} else {
				YAHOO.util.Connect.setForm(formId, false);
		   		YAHOO.util.Connect.asyncRequest('POST', url, {success: function(o) {cb(o,fn);}, failure: Qcat.Forms.ajaxFail});
			}
		}
		
	}
}

Qcat.checkSession = {
	timeout:450000,
	controller:'index',
	inst:null,
	stopTimeout: function() {
		window.clearTimeout(Qcat.checkSession.inst);
	},
	initTimeout: function() {
		Qcat.checkSession.inst = window.setTimeout("Qcat.checkSession.exec()", Qcat.checkSession.timeout);
	},
	exec: function() {
	   	Ext.Ajax.request({
	   		url: Qcat.BASE_URL + '/' + Qcat.checkSession.controller + '/refreshSession',
	   		method:'GET',
	   		scope: this,
	   		callback:function(options, success, o) {
				try {
					var obj = eval('(' + o.responseText + ')');
					if(obj.session == false) {
						return false;
					}
					if(obj.timeout && obj.timeout > 1000) {
						Qcat.checkSession.timeout = obj.timeout;
					}
					Qcat.checkSession.initTimeout();
				} catch (e) {}
	   		}
	   	}); 
	}
}
Qcat.checkSession.initTimeout();





Qcat.Actions = function(config){
	if(Ext.isArray(config)){
		config = {actions:config};
	}

	// call parent class and set 'get key' function to 'action'
	Qcat.Actions.superclass.constructor.call(this, false, function(el){
		   return el.action;
	});
	this.addEvents(
			/**
			 * @event validate
			 * Fires when validating actions
			 */
			"validate",
			/**
			 * @event beforeaction
			 * Fires before action is executed
			 */
			"beforeaction"
	);
	if(config.listeners) {
		this.addListener(config.listeners);
	}
	if(config.actions) {
		this.addActions(config.actions);
	}
	if(config.validator) {
		this.validator = config.validator;
	}
	if(config.mapper) {
		this.mapper = config.mapper;
	}
	// TODO better with Ext.getCmp();
	// Qcat.ActionsMgr.add(this);
};
Ext.extend(Qcat.Actions, Ext.util.MixedCollection, {
	addActions: function(actions) {
		for(var i = 0; i < actions.length; i++){
			// apply default action if not set
			var actionDefaults = {
				handler: this.execute, scope: this
			}
			Ext.applyIf(actions[i], actionDefaults);
			this.add(actions[i].action, new Ext.Action(actions[i]));
		}
	},
	applyTo: function(obj, defaults) {
		var defaults = defaults || {scale: 'medium'};
		var cls, imgSuffix, buttonDefaults, uicon;
		this.each(function(action){
			cls = (action.initialConfig.text) ? 'x-btn-text-icon' : 'x-btn-icon';
			imgSuffix = (defaults.scale == 'small') ? '_sm' : '';
			uicon = (action.initialConfig.uicon) ? action.initialConfig.uicon : action.initialConfig.action;
			buttonDefaults = {
				icon: Qcat.BASE_URL + '/images/qcat/tbbtn/'+uicon + imgSuffix + '.png',
				cls: cls, 
				iconAlign: 'left'
			};
			Ext.apply(action.initialConfig, defaults);
			Ext.applyIf(action.initialConfig, buttonDefaults);
			if(obj instanceof Ext.Toolbar) {
				// add default action to Toolbar's buttons if not existent
				obj.addButton(action);
				if(defaults.usesep) {
					obj.addSpacer();
				}
			}
			if(obj instanceof Ext.menu.Menu) {
				obj.addItem(action);
			}
		});
	},
	checkAction: function(cType, actionConfig) {
		var selections = [];
		
		for(var i = 0; i < actionConfig.assign.length; i++) {
			
			if(actionConfig.assign[i].cType == cType) {
				if(typeof actionConfig.assign[i].requires != 'object' || actionConfig.assign[i].requires.length === 0) { // || this.hasListener('validate') == false
					return true;
				}
				
				for(var a = 0; a < actionConfig.assign[i].requires.length; a++) {
					if(this.fireEvent('validate', this, actionConfig.assign[i].requires[a], actionConfig) === false) {
						return false;
					}
					var selection = this.validator.call(this, actionConfig.assign[i].requires[a], actionConfig, cType);
					if(selection === false || selection === null || typeof selection == 'undefined' || ( typeof selection == 'object' && selection.length == 0)) {
						return false;
					} else {
						selections.push(selection);
					}
				}
				return selections;
			} 
			
		}
		return false;
	},
	checkStatus: function(cType, checked) {
		this.each(function(action){
			if(this.checkAction(cType, action.initialConfig) !== false) {
				if(checked === true) {
					action.disable();
				} else {
					action.enable();
				}
			} else {
				action.disable();
			}
	
	   }, this);
	},
	execute: function(extaction){
		var panel = Ext.getCmp(extaction.initialConfig.parentPanel);
		// if tabpanel, take active tab
		if(panel instanceof Ext.TabPanel) {
			panel = panel.getActiveTab();
		}
		if(panel.cType) {
			var selections = this.checkAction(panel.cType, extaction.initialConfig);
			if(selections === false) {
		   		Ext.MessageBox.alert('Fehler', 'Ihre Auswahl ist unvollständig!', function(btn) {return;});
				return false;
			}
			if(this.fireEvent('beforeaction', selections, panel, extaction.initialConfig) === false) {
				return false;
			}
			var cls = this.mapper[panel.cType];
			if(selections === true) {
				selections = [];
			}
			if(typeof cls == 'string') cls = eval(cls);
			cls[extaction.initialConfig.action].apply(cls, selections);

		} else {
			if((console && typeof console.log == 'function')) {
				console.log("panel has no cType defined");
			}
		}
	},
	executeAction: function(action) {
		var extAction = this.get(action);
		return this.execute(extAction);
	}
});


Qcat.FormHelper = {
	cleanup: function(panelid) {
		Ext.ComponentMgr.all.each(function(item, index, length) {
			if(item.pnlgc && item.pnlgc == panelid) {
				item.destroy();
			} 
		});
	},
	cleanupTinymce: function(panelid) {
		Ext.select("textarea[@class*='tinymce']", true, Ext.getCmp(panelid).getEl().dom).each(function(el, compEl, index) {
			var t = tinymce.EditorManager.get(el.id);
			if(t) {
				tinymce.EditorManager.remove(t);
			}

		});
	},
	/* wraps fieldset around text fields to restrict ie outbreak bug */
	fixIeBug: function() {
		if(Ext.isIE) {
			var fns = Ext.Element.select("input[@class*='x-form-text']");
			fns.each(function(el,scope,index) {
				if(el.hasClass('done') == false) {
					var newel = el.wrap({tag:'div'});
					newel.wrap({tag:'fieldset',cls:'iebug'});
					el.addClass('done');
				}
			});
			fns = Ext.Element.select("textarea");
			fns.each(function(el,scope,index) {
				if(el.hasClass('done') == false) {
					var newel = el.wrap({tag:'div'});
					newel.wrap({tag:'fieldset',cls:'iebug'});
					el.addClass('done');
				}
			});		
		}		
	},
	getInputSelection: function(id) {
		var input = document.getElementById(id);
		if(typeof document.selection != 'undefined') { // IE
			return document.selection.createRange().text;	
		} else if(typeof input.selectionStart != 'undefined') {// gecko
			return input.value.substring(input.selectionStart, input.selectionEnd);
		} 
		return '';
	},
	insertValues: function(el, obj) {
		var form = Ext.DomQuery.selectNode("form", el);
		form.reset();
		var els = Ext.DomQuery.select("input", form);
		for(var i=0; i<els.length; i++) {
			var val = obj[els[i].name] || '';
			switch(els[i].type) {
				case "checkbox":
				els[i].checked = (val!=1&&val!='') ? 'checked' : '';
				break;
				case "radio":
				els[i].checked = (els[i].value == val) ? 'checked' : '';
				break;
				default:
				els[i].value = val;
				break;
			}
		}
	},
	moveGridRows: function (grid, mode, col) {
		var col = col || 'img_rank';
		var direction = (mode && mode=='up') ? -1 : 1;
		var selected = grid.getSelectionModel().getSelected();
		var rank = selected.get(col);
		var index = grid.getStore().indexOf(selected);
		var sibling = grid.getStore().getAt(index + direction);
		if(sibling) {
			sibling.set(col, rank);
			selected.set(col, rank + direction);
			grid.getStore().sort(col, 'ASC');
		}
	},
	render: function(pnl_id) {
		var pnl_id = pnl_id || null;
		// pnlgc = panel cleanup
		Ext.Element.select("input[@class='fd-datum']", true).each(function(el,scope,index) {
			if(el.hasClass('x-form-text') == false) {
				new Ext.form.DateField({
					pnlgc: pnl_id,
					allowBlank: true,
					format:'d.m.Y',
					altFormats:'Y-m-d',
					applyTo:el
				});
				el.addClass('done'); // stop ie fix
			}
		});
		Ext.Element.select("select[@class='fn-combo']").each(function(el,scope,index) {
			if(el.hasClass('x-form-text') == false) {
				new Ext.form.ComboBox({
					pnlgc: pnl_id,
					applyTo:el.dom.id,
					triggerAction: 'all',
					transform:el
				});
				el.addClass('done'); // stop ie fix
			}
		});
		Ext.Element.select("span[@class*='q-toggle']", true).each(function(el,scope,index) {
			el.on('click', Qcat.FormHelper.toggleFieldSet.createDelegate(el.dom));
		});
	},
	renderAddressCombo: function(startEl, pnl_id) {
		var pnl_id = pnl_id || null;
		Ext.select("input[@class='street-combo']", true, startEl).each(function(el,scope,index) {
			if(el.hasClass('x-form-text') == false) {
				new Qcat.StreetCombo({ 
					pnlgc:pnl_id,
					applyTo:el
				});	
				el.addClass('done'); // stop ie fix
			}
		});
		Ext.select("input[@class='plz-combo']", true, startEl).each(function(el,scope,index) {
			if(el.hasClass('x-form-text') == false) {
				new Qcat.ZipCombo({
					applyTo:el, 
					pnlgc:pnl_id
				});	
				el.addClass('done'); // stop ie fix
			}
		});
		Ext.select("input[@class*='places-combo']", true, startEl).each(function(el,scope,index) {
			if(el.hasClass('done') == false) {
				new Qcat.PlacesCombo({
					applyTo:el, 
					pnlgc:pnl_id
				});
				el.addClass('done'); // stop ie fix
			}
		});
	},
	renderButtons: function(startEl) {
		Ext.select("div[@class*='xml-dlg-btn']", true, startEl).each(function(el,scope,index) {
			if(el.hasClass('done') == false) {
				var conf = Ext.decode(el.dom.firstChild.data);
				if(conf.sm && conf.sm == 'multiple') {
					conf.selModel = new Ext.tree.MultiSelectionModel();
				}
				el.dom.firstChild.data = '';
				var config = Ext.apply({
					renderTo:el, 
					text:'Auswahl',  
					handler: Qcat.FormHelper.showXmlDlg
				}, conf);
				new Ext.Button(config);
				el.addClass('done'); // stop ie fix
			}
		});
		Ext.select("div[@class*='dir-dlg-btn']", true, startEl).each(function(el,scope,index) {
			if(el.hasClass('done') == false) {
				var conf = Ext.decode(el.dom.firstChild.data);
				if(conf.sm && conf.sm == 'multiple') {
					conf.selModel = new Ext.tree.MultiSelectionModel();
				}
				el.dom.firstChild.data = '';
				var config = Ext.apply({
					renderTo:el, 
					text:'Auswahl',  
					handler: function(btn) {
						var input = btn.el.up("div.dlg-form-outer").child("input", true);
						Qcat.FileDialog.show({loader: new Ext.tree.TreeLoader({dataUrl:Qcat.BASE_URL + btn.url, baseParams: {loc:btn.loc}}), rootVisible:false, pathAttr:'dir', preSelPath: input.value}, function(node, obj) {
							//var input = obj.el.up("div.dlg-form-outer").child("input", true);
							input.value = node.getPath().replace(/\/n0\//,'/');
							Qcat.FileDialog.hide();
						}, {el:btn.initialConfig.renderTo});
					}
				}, conf);
				new Ext.Button(config);
				el.addClass('done'); // stop ie fix
			}
		});
	},
	renderImgGrid: function(config) {
		if(config.parentEl && typeof config.parentEl == 'string') {
			config.parentEl = Ext.get(config.parentEl).dom;
		}
		if(typeof config.parentEl.dom != 'undefined') {
			config.parentEl = config.parentEl.dom;
		}
		var panelid = Ext.getCmp('main-tabs').getActiveTab().id;
		if(!config.url) {
			return false;
		}
		Ext.select("div[@class*='qcat-imgs-grid']", true, config.parentEl).each(function(el,scope,index) {
			if(el.hasClass('done') == false) {
				var id = null;
				if(el.dom.innerHTML != '') {
					id = el.dom.innerHTML;
					el.dom.innerHTML = '';
				}
				var gridid = Ext.id();
	  			new Ext.grid.EditorGridPanel({
	  				pnlgc: panelid,
	  				id: gridid,
	  		        ds: new Ext.data.Store({
		  				proxy: new Ext.data.HttpProxy({
		  					url: config.url
		  				}),
		  				sortInfo: {field: "img_rank", direction: "ASC"},
		  				reader: new Ext.data.JsonReader({id: 'img_id'}, Ext.data.Record.create([                          
		  		  			{name: 'img_id', type: 'int'},
	  		  				{name: 'img_text'},
	  		  				{name: 'img_author'},
	  		  				{name: 'img_url'},
	  						{name: 'img_width', type: 'int'},
	  						{name: 'img_height', type: 'int'},
	  						{name: 'img_gallery', type: 'int'},
	  		  				{name: 'img_rank', type: 'int'}
	  		  			]))
		  			}),
	  		        cm: new Ext.grid.ColumnModel([
		  			    {header: '#', dataIndex: 'img_id', width: 30, hidden:true},
					 	{header: 'Text', dataIndex: 'img_text', width: 260, editor: new Ext.grid.GridEditor(new Ext.form.TextArea({allowBlank: true}))},
					 	{header: 'Autor', dataIndex: 'img_author', width: 100, editor: new Ext.grid.GridEditor(new Ext.form.TextArea({allowBlank: true}))},
					 	{header: 'Bild', dataIndex: 'img_url', renderer: function(src) {return (src) ? '<img src="'+src+'" height="45" />' : '';}, width: 180, align:'center'},
					 	{header: 'Breite', dataIndex: 'img_width', width: 60},
					 	{header: 'H&ouml;he', dataIndex: 'img_height', width: 60},
					 	{header: 'Galerie', dataIndex: 'img_gallery', width: 60, renderer: Qcat.Rnd.formatActive},
					 	{header: 'Rang', dataIndex: 'img_rank', width: 30, hidden:true}
					]),
					sm: new Ext.grid.RowSelectionModel(),
					cls:'imgs-grid-pnl',
	  		        autoScroll: true,	        
	  		        renderTo: el,
	  			    height:250,
	  			    width:760,
	  			    viewConfig: {
	  			        forceFit: true
	  			    },
	  			    bbar:[
	  				    {text:'Bild hinzuf&uuml;gen', gridid:gridid, icon:Qcat.BASE_URL + '/images/qcat/menu/drop-add.gif', cls:'x-btn-text-icon' ,xType:'tbbutton', scope:this, handler: function(btn, e) {
	  						Qcat.MediaDialog.show(Ext.apply({multiple:true, url:Qcat.BASE_URL + '/Media/index/getnodes', treeBaseParams:{loc:'sMedia'}, handler: function(vnode, obj) {
	  								var store = Ext.getCmp(btn.gridid).getStore();
	  								var rec = store.recordType;
									for(var i=0; i < vnode.length; i++) {
										var rank = store.getCount() + 1;
										var rec2 = new rec({img_text:'', img_author:'', img_url:vnode[i].url, img_width:vnode[i].width, img_height:vnode[i].height, img_rank:rank});	
		  						    	store.add([rec2]);
									}
	  						    	var index = store.indexOf(rec2) - vnode.length + 1;
	  						    	Ext.getCmp(btn.gridid).startEditing(index, 1);
	  						    	Qcat.MediaDialog.hide();
	  							}
	  						}, config.mediaDlg));
	  					}},
	  					{xtype:'tbseparator'},
	  			        {text: 'Bild entfernen', gridid:gridid, icon:Qcat.BASE_URL + '/images/qcat/menu/delete.gif', cls:'x-btn-text-icon', handler: function(btn, e){
	  							Ext.getCmp(btn.gridid).getStore().remove(Ext.getCmp(btn.gridid).getSelectionModel().getSelected());
	  				        }
	  			        },
	  			        {xtype:'tbseparator'},
	  			        {text: 'Bild Vorschau', gridid:gridid, icon:Qcat.BASE_URL + '/images/qcat/menu/preview.png', cls:'x-btn-text-icon', handler: function(btn, e){
	  		    			Qcat.Media.showImg(Ext.getCmp(btn.gridid).getSelectionModel().getSelected().data.img_url);
	  			        }},
	  			        {xtype:'tbseparator'},
	  			        {text: 'Bild nach oben', gridid:gridid, icon:Qcat.BASE_URL + '/images/qcat/menu/arrow_up_sm.gif', cls:'x-btn-text-icon', handler: function(btn, e){
							var grid = Ext.getCmp(btn.gridid);
							Qcat.FormHelper.moveGridRows(grid, 'up', 'img_rank');
	  			        }},
						{xtype:'tbseparator'},
						{text: 'Bild nach unten', gridid:gridid, icon:Qcat.BASE_URL + '/images/qcat/menu/arrow_down_sm.gif', cls:'x-btn-text-icon', handler: function(btn, e){
							var grid = Ext.getCmp(btn.gridid);
							Qcat.FormHelper.moveGridRows(grid, 'down', 'img_rank');
						}},
						{xtype:'tbseparator'},
						{text: 'Galerie an / aus ', gridid:gridid, handler: function(btn, e){
							var selected = Ext.getCmp(btn.gridid).getSelectionModel().getSelected();
							selected.set('img_gallery', (selected.get('img_gallery')==1)?0:1);
						}}
	  			    ]
	  			});
				el.addClass('done'); // stop ie fix
				// load imgs if ID is set
				
				if(id) {
					Ext.getCmp(gridid).getStore().load({params:{id:id}});
				}
			}
		});
	},
	showXmlDlg: function (btn) {
		var input = btn.el.up("div.dlg-form-outer").child("input", true);
		Qcat.FileDialog.show({loader: new Ext.tree.TreeLoader({dataUrl:Qcat.BASE_URL + btn.url, baseParams: {loc:btn.loc}}), rootVisible:false, pathAttr:'id', cls:'no-leaf-img', preSelPath: input.value}, function(node, obj) {
			//var input = obj.el.up("div.dlg-form-outer").child("input", true);
			input.value = node.getPath();
			Qcat.FileDialog.hide();
		}, {el:btn.initialConfig.renderTo});
	},
	showMediaDlg: function (btn) {
		var input = btn.el.up("div.dlg-form-outer").child("input", true);
		btn.initialConfig.handler = function(vnode, obj) {
			for(var i=0; i < vnode.length; i++) {
				if(input.value != '') input.value += ', ';
				input.value += vnode[i].url;
			}
			Qcat.MediaDialog.hide();
		}
		Qcat.MediaDialog.show(Ext.apply({multiple:true, url:Qcat.BASE_URL + '/Media/index/getnodes', treeBaseParams:{loc:'sMedia'}}, btn.initialConfig));
	},
	toggleFieldSet: function(){
		var el = Ext.fly(this);
		var div = el.next();
		div.enableDisplayMode();
		div.toggle(true);
		Ext.fly(this).toggleClass('q-toggle-up');
		if(this.attributes['ext:cb']) {
			var fn = eval(this.getAttribute('ext:cb'));
			this.removeAttribute('ext:cb');
			fn.call(Ext.get(this).parent("fieldset"));
		}
		if(this.attributes['ext:url']) {
			Ext.get(this).parent("fieldset").down("div").load({
				url: Qcat.BASE_URL + this.getAttribute('ext:url'),
				scripts:true
			});
			this.removeAttribute('ext:url');
		}
	},
	toggleInit: function() {
		Ext.Element.select("*[@class*='q-toggle']", true).each(function(el,scope,index) {
			if(el.hasClass('done') == false) {
				el.on('click', Qcat.FormHelper.toggleFieldSet.createDelegate(el.dom));
				if(el.next()) {
					el.next().setDisplayed(el.hasClass('q-toggle-up'));
				}
				el.addClass('done');
			}
		});
	}
}

Qcat.TreeHelper = function(config){

	Qcat.TreeHelper.superclass.constructor.call(this);
	this.addEvents(
			/**
			 * @event validate
			 * Fires when validating actions
			 */
			"ajaxResponse"
	);
	if(config.listeners) {
		this.addListener(config.listeners);
	}
	delete config.listeners;
	// apply config
	Ext.apply(this, config, {
		rootLevel:0,
		fetchMode:'id'
	});
	
	// add path as BaseParam
	if(!config.skipPathParam && typeof this.getTree().getLoader == 'function') {
		this.getTree().getLoader().on("beforeload", function(treeLoader, node) {
			treeLoader.baseParams.path = node.getPath();
		}, this);
	}
};

Ext.extend(Qcat.TreeHelper, Ext.util.Observable, {
	_ajaxCb: function (options, success, response) {
		// ajax request failed
		if(success === false) {
			Ext.MessageBox.alert('Fehler', 'Ajax Request failed', function(btn) {return;});
			return;
		}
		// ajax request succeeded
		var responseObj = eval('(' + response.responseText + ')');
		if(responseObj['alert'] && responseObj['alert']!='') {
			Ext.Msg.alert('Fehler', responseObj['alert'], function(btn) {return;});
		} else {
			if(this instanceof Qcat.TreeHelper == false) {
				return false;
			}
			if(typeof this.actParent == 'object' && typeof this.actParent.reload == 'function'){
				var getSelf = (function(){return this}).createDelegate(this);
				
				this.actParent.reload(function(){
					var self = getSelf();
					self.actParent.expand();
					self.actParent.select();
					self.fireEvent("ajaxResponse", self.actParent);
				});
			} else {
				this.fireEvent("ajaxResponse");
			}
		}
	},
	_getUrl: function(action, node) {
		var modulePath = (this.module) ? '/' + this.module : '';
		var ctrlPath = (this.controller) ? '/' + this.controller : '';
		var url = Qcat.BASE_URL + modulePath + ctrlPath + '/' + action + 'node';
		if(node) {
			url += '?node=' +encodeURIComponent(node.id)+'&path=' +encodeURIComponent(node.getPath());
		}
		return url;
	},
	getTree: function() {
		return Ext.getCmp(this.applyTo);
	},
	initDD:function(callback, scope)  {
		var scope = scope || callback;
		this.getTree().on('beforenodedrop', function(e) {
			// no drag from tree
			if(typeof e.data.node == 'undefined') {
				var mode = (e.rawEvent.ctrlKey) ? 'copy' : 'cut';
				var newNode = e.tree.getSelectionModel().getSelectedNode();
				if(!newNode) {return false;}
				callback.call(scope, newNode, e.target, mode);
			} else {
				if(this.strictLevelDD && (e.dropNode.parentNode != e.target.parentNode || e.point == 'append')) {
					return false;
				}
				// TODO drag nodes 
			   	var oldParent = e.dropNode.parentNode;
			   	if(e.point=='append') {     
			   		this.actParent = e.target;
			   	} else {
			   		this.actParent = e.target.parentNode;
			   	}
			   	// find common parent
			   	var secPath = oldParent.getPath().lpisec(this.actParent.getPath());
			   	e.tree.selectPath(secPath);
			   	this.actParent = e.tree.getSelectionModel().getSelectedNode();
			   	Ext.Ajax.request({
			   		url: this._getUrl('move',e.dropNode),
			   		params: {
			   			point: e.point,
			   			newNode: e.target.id,
			   			newPath: e.target.getPath(),
			   			newText: e.dropNode.text
			   		},
			   		method:'GET',
			   		scope: this,
			   		callback:this._ajaxCb

			   	});    
	   			/*
				 * works well, except numbers dont refresh function(options,
				 * success, response){ if(success == true) { if(oldParent &&
				 * typeof oldParent.reload == 'function') { var getSelf =
				 * (function(){return this}).createDelegate(this);
				 * oldParent.reload(function(){ var self = getSelf();
				 * self._ajaxCb.call(self, {}, true, response); }); } else {
				 * this._ajaxCb({}, true, response); } } }
				 */
			}
		}, this);
		
		this.getTree().on('nodedragover', function(e) {
			// no grid drag insert 
			if(e.point != 'append' && e.data.grid) {
				return false;
			}
		}, this);
	},
	initInlineEditor: function(config) {
		var tfconf = Ext.apply({
		   	allowBlank:false,
			blankText:'Bitte Namen angeben',
		   	width:100
		}, config);
		this.inlineEditor = new Ext.Editor(new Ext.form.TextField(tfconf), {
		   	parentEl: this.getTree().getEl(),
		   	alignment:'tl-tl',
		   	completeOnEnter:true
		});
		this.inlineEditor.on('complete', function(e, text){
			if(text == this.inlineEditor.node.text.replace(/\s<[\s\S]*>$/g, "") || text=='') return false;
		   	Ext.Ajax.request({
		   		url: this._getUrl('edit'),
		   		params: {
		   			node: this.inlineEditor.node.id,
		   			path: this.inlineEditor.node.getPath(),
		   			newText: text
		   		},
		   		method:'POST',
		   		scope: this,
		   		callback:this._ajaxCb
		   	}); 
		}, this);
	},
	getNewId: function(counter) {
		var dt = new Date();
		var newid = 'n' + (dt.format('U') - 1200000000);
		return newid;
	},
	getSelected: function() {
		return this.getTree().getSelectionModel().getSelectedNode();
	},

	appendChild: function(node) {
		var id = this.getNewId();
		var node = this.getSelected();
	   	Ext.Ajax.request({
	   		url: this._getUrl('append', node),
	   		params: {
	   			newId: id
	   		},
	   		method:'GET',
	   		scope: this,
	   		callback:function(options, success, response){
	   			if(success == true) {
	   				var response = eval('(' + response.responseText + ')');
	   				if(response['alert']&&response['alert']!='') {
	   					Ext.Msg.alert('Fehler', response['alert']);
	   					return;
	   				} 
	   				// regain scope via getSelf
	   				var getSelf = (function(){return this}).createDelegate(this);
					// if new id comes with ajax response take this, otherwise
					// try with id above
   					var newId = (response['newid']) ? response['newid'] : (response['newdir']) ? response['newdir'] : id;
   					var attr = this.getTree().pathAttr || "id";
	   				if(node.leaf == 'true') {
	   					var parent = node.parentNode;
	   					parent.reload(function() {
	   						var self = getSelf();
	   						var newnode = parent.findChild(attr, node.attributes[attr]);
	   						newnode.expand(false, true, function(newnode) {
	   							newnode.firstChild.select();
	   							self.actParent = newnode;
	   							self.editFolder(newnode.firstChild, true);
	   						});
	   					});
	   				} else {
	   					node.reload(function() {
	   						var self = getSelf();
	   						var newnode = node.findChild(attr, newId);
	   						if(newnode) {		
	   							newnode.select();
	   							self.actParent = node;
	   							self.editFolder(newnode, true);
	   						}			
	   					});
	   				}
	   			}
	   		}
	   	});  
	},
	editFolder: function(node) {
		this.actParent = node.parentNode;
		if(this.inlineEditor) {
			this.inlineEditor.node = node;
			this.inlineEditor.startEdit(node.ui.getAnchor(), node.text.replace(/\s<[\s\S]*>$/g, ""));
			this.inlineEditor.field.selectText();
		} else {
			if((console && typeof console.log == 'function')) {
				console.log("no inline editor defined")
			}
		}
	},
	insertBefore: function(node) {
		//var id = Ext.id(null,"n");
		if(node.id == 'n0') {
			Ext.Msg.alert("Hinweis", "Aktion ist auf dieser Ebene nicht m&ouml;glich");
			return false;
		}
		var id = this.getNewId();
	   	Ext.Ajax.request({
	   		url: this._getUrl('insert', node),
	   		params: {
	   			newId: id
	   		},
	   		method:'GET',
	   		scope: this,
	   		callback:function(options, success, response){
   				var response = eval('(' + response.responseText + ')');
   				if(response['alert']&&response['alert']!='') {
   					Ext.Msg.alert('Fehler', response['alert']);
   					return;
   				} 
				var newId = (response['newid']) ? response['newid'] : (response['newdir']) ? response['newdir'] : id;
				var attr = this.getTree().pathAttr || "id";
	   			
	   			var getSelf = (function(){return this}).createDelegate(this);
				var parent = node.parentNode;
				parent.reload(function() {
					var self = getSelf();
					var newnode = parent.findChild(attr, newId);
					if(newnode) {		
						newnode.select();
						self.actParent = node;
						self.editFolder(newnode, true);
					}	
				});
		   	}  
		});
	},
	refresh: function(clickEvent) {
		var clickEvent = clickEvent || false;
		var node = this.getTree().getSelectionModel().getSelectedNode();
		if(node.getDepth() > 0 && typeof node.parentNode == 'object'){
			var pnode = node.parentNode;
		} else {
			var pnode = node;
		}
		if(typeof pnode == 'object' && typeof pnode.reload == 'function') {
			var getSelf = (function(){return this}).createDelegate(this);
			setTimeout(function() {
				pnode.reload(function() {
					var self = getSelf();
					var newNode = self.getTree().getNodeById(node.id);
					if(typeof newNode == 'object'){
						newNode.select();
						if(clickEvent == true) {
							newNode.fireEvent('click', newNode);
						}
					}
				})
			},400);
		}
	},
	refreshFolder: function(node) {
		if(typeof node.reload == 'function') {
			node.reload(function(){});
		}
	},
	removeFolder: function(node) {
		Ext.Msg.confirm('Hinweis', 'Ordner ' + node.text.replace(/\s<[\s\S]*>$/g, "") + ' entfernen?', function (btn) {
			if(btn == 'no') return false;
			this.actParent = node.parentNode;
		   	Ext.Ajax.request({
		   		url: this._getUrl('remove', node),
		   		method:'GET',
		   		scope: this,
		   		callback:this._ajaxCb
		   	}); 
		}, this);
	},
	sortCustom: function(node) {
		return node.attributes['sort'] || node.attributes['text'];
	},
	toggleActive: function(node) {
		this.actParent = node.parentNode;
		Ext.Ajax.request({
			url: this._getUrl('edit', node), 
			method:'POST', 
			scope: this,
			params:{'nodeAttr[cls]':(node.attributes.cls && node.attributes.cls == 'active') ? 'inactive' : 'active'}, 
			callback:this._ajaxCb
		});
	}
});

Qcat.GridHelper = function(config){

	Qcat.GridHelper.superclass.constructor.call(this);
	this.addEvents(
			/**
			 * @event validate
			 * Fires when validating actions
			 */
			"ajaxResponse"
	);
	if(config.listeners) {
		this.addListener(config.listeners);
	}
	delete config.listeners;
	// apply config
	Ext.apply(this, config, {
		attrToSelect:null,
		lastAction:null
	});
};

Ext.extend(Qcat.GridHelper, Ext.util.Observable, {
	_ajaxCb: function (options, success, response) {
		var response = eval('(' + response.responseText + ')');
		if(response['alert']&&response['alert']!='') {
			Ext.Msg.alert('Fehler', response['alert']);
		} else {
			this.getGrid().getStore().reload();
		}
		this.fireEvent("ajaxResponse", this.lastAction);
		this.lastAction = null;
	},
	_getUrl: function(action, node) {
		var modulePath = (this.module) ? '/' + this.module : '';
		var ctrlPath = (this.controller) ? '/' + this.controller : '';
		var url = Qcat.BASE_URL + modulePath + ctrlPath + '/' + action + 'row';
		if(node) {
			url += '?node=' +encodeURIComponent(node.id)+'&path=' +encodeURIComponent(node.getPath());
		}
		return url;
	},
	code: function(node, row) {
		if(this.applyToPanel) {
			var url = this._getUrl('code', node) + '&id=' + row.id;
		  	var panel = new Ext.Panel({
		  		id:'code-pnl-' + row.id, 
		  		title: 'Code ' + row.id, 
		  		header:false, 
		  		cType:'code', 
		  		rowId:row.id,
		  		autoScroll:false, 
		  		closable: true, 
		  		renderTo:document.body, 
		  		autoLoad:url
		  	});
		   	Ext.getCmp(this.applyToPanel).add(panel);
		   	panel.show();
		}
	},	
	copy: function(node) {
		this.clipboard = {mode:'copy', cType:'list', id:node.id, path:node.getPath(), ids:this.getSelectedIds()};
	},
	create: function(node) {
		Ext.Ajax.request({
			url: this._getUrl('create', node), 
			method:'GET', 
			callback: this._ajaxCb,
			scope:this
		});
	},
	cut: function(node) {
		this.clipboard = {mode:'cut', cType:'list', id:node.id, path:node.getPath(), ids:this.getSelectedIds()};
	},
	edit: function() {
		this.getGrid().startEditing(0,0);
	},
	getGrid: function() {
		return Ext.getCmp(this.applyTo);
	},
	getSelectedIds: function() {
		var ids = [];
		var rows = this.getGrid().getSelectionModel().getSelections();
		for(var i=0; i < rows.length; i++) {
			if(this.attrToSelect){
				ids.push(rows[i].data[this.attrToSelect]);
			} else {
				ids.push(rows[i].id);
			}
		}
	   	return ids;
	},
	move: function(oldNode, newNode, mode)  {
		this.lastAction = 'move';
		if(!mode) var mode = 'cut';
		var oldPath = oldNode.getPath();
		var newPath = newNode.getPath();
		var intersec = newPath.lpisec(oldPath);
		var treeId = newNode.getOwnerTree()['id'];
		Ext.Msg.wait("bitte warten...");
		Ext.Ajax.request({
			url: this._getUrl(mode), 
			params:{
				node:oldNode.id, 
				path:oldPath, 
				newNode:newNode.id, 
				newPath:newPath, 
				'ids[]': this.getSelectedIds()
			},
			scope: this,
			method:'POST', 
			callback: function(options, success, r) {
				var response = eval('(' + r.responseText + ')');
				// && oldPath !== intersec
				if(response['total'] && response['total'] != 0) {
					oldNode.bubble(function() {
						var num = 0 - response['total'];
						Qcat.Filter.setNodeInnerParenthesis(this, num);
					});
					
					newNode.bubble(function() {
						Qcat.Filter.setNodeInnerParenthesis(this, response['total']);
					});
					
				} else {
					// if nodes got same parent node then reload parent node if parenthesis are available
					var regexp = /\((\d*)\)/;
					if(oldNode && regexp.test(oldNode.text) && oldNode.parentNode && (oldNode.parentNode === newNode.parentNode || oldPath === intersec) && typeof oldNode.parentNode.reload == 'function') {
						oldNode.parentNode.reload(function() {
							var scopeToNode = Ext.getCmp(treeId).getNodeById(oldNode.id);
							scopeToNode.select();
						});
					}
					
				}
				Ext.Msg.hide();
				this._ajaxCb(options, success, r);
			}
		});
	},
	moveRows: function(mode, col, grid) {
		var col = col || 'img_rank';
		var direction = (mode && mode=='up') ? -1 : 1;
		var grid = grid || this.getGrid();
		var selected = grid.getSelectionModel().getSelected();
		var rank = selected.get(col);
		var index = grid.getStore().indexOf(selected);
		var sibling = grid.getStore().getAt(index + direction);
		if(sibling) {
			sibling.set(col, rank);
			selected.set(col, rank + direction);
			grid.getStore().sort(col, 'ASC');
		}
	},
	paste: function(node) {
		//if(this.clipboard.cType!='list') return false;
		this.lastAction = 'paste';
		Ext.Ajax.request({
			url: this._getUrl(this.clipboard.mode), 
			params:{
				node: this.clipboard.id, 
				path: this.clipboard.path, 
				newNode: node.id, 
				newPath: node.getPath(), 
				'ids[]': this.clipboard.ids
			},
			scope: this,
			method:'POST', 
			callback: function(options, success, r) {
				var response = eval('(' + r.responseText + ')');
				if(response['total'] && response['total'] != 0) {
					if(this.clipboard.mode == 'cut') {
						var oldNode = node.getOwnerTree().getNodeById(this.clipboard.id);
						oldNode.bubble(function() {
							var num = 0 - response['total'];
							Qcat.Filter.setNodeInnerParenthesis(this, num);
						});
					}
					node.bubble(function() {
						Qcat.Filter.setNodeInnerParenthesis(this, response['total']);
					});
					
				} 
				this._ajaxCb(options, success, r);
			}
		});
	},
	preview: function() {
		Ext.Ajax.request({
			url: this._getUrl('preview'), 
			method:'POST', 
			params:{'ids[]':this.getSelectedIds()}, 
			scope: this,
			callback:this._ajaxCb
		});
	},
	remove: function(node, row) {
		Ext.Msg.confirm('Hinweis', 'Sollen die markierten Zeilen wirklich entfernt werden?', function (btn) {
			if(btn == 'no') return false;
			var params = {'ids[]':this.getSelectedIds()};
			if(typeof node.getPath == 'function') {
				Ext.apply(params, {node:node.id, path:node.getPath()});
			}
			var oldNode = node;
			Ext.Ajax.request({
				url: this._getUrl('remove'), 
				method:'POST', 
				params:params, 
				scope: this,
				callback: function(options, success, r) {
					var response = eval('(' + r.responseText + ')');
					if(response['total'] && response['total'] != 0 && typeof oldNode.bubble == 'function') {
						oldNode.bubble(function() {
							var num = 0 - response['total'];
							Qcat.Filter.setNodeInnerParenthesis(this, num);
						});
					}
					callback:this._ajaxCb(options, success, r);
				}
			});
		}, this);
	},
	save: function(node) {
		this.lastAction = 'save';
		var path = (typeof node == 'object' && typeof node.getPath == 'function') ? node.getPath() : '';
		var rows = [];
		// this.getGrid().stopEditing();
		this.getGrid().getStore().each(function(r) {
			rows.push(Ext.util.JSON.encode(r.data));
		});
		Ext.Ajax.request({
			url: this._getUrl('save'), 
			method:'POST', 
			scope: this,
			params:{'rows[]':rows, path:path}, 
			callback:this._ajaxCb
		});
	},
	sortCustom: function(node) {
		return node.attributes['sort'] || node.attributes['text'];
	},
	toggleActive: function() {
		Ext.Ajax.request({
			url: this._getUrl('toggleactive'), 
			method:'POST', 
			scope: this,
			params:{'ids[]':this.getSelectedIds()}, 
			callback:this._ajaxCb
		});
	},
	write: function() {
		Ext.Ajax.request({
			url: this._getUrl('write'), 
			method:'POST', 
			params:{'ids[]':this.getSelectedIds()}, 
			scope: this,
			callback:this._ajaxCb
		});
	}
});

Qcat.Filter = {
	lastFolder: function(path) {
		if(path !== null) {
			var splitPath = path.split("/");
			return splitPath[splitPath.length - 1];
		}
	},
	setNodeInnerParenthesis: function(node, val) {
		if(typeof node != 'object') return false;
		var regexp = /\((\d*)\)/;
		var regres = regexp.exec(node.text);
		if(regres !== null) {
			var num = Number(regres[1]) + val;
			node.setText(node.text.replace(/\(\d*\)/, "(" + num + ")"));
		} 
	}
}

Qcat.Panel = {
	show: function(config) {
	   	var options = Ext.apply({header:false, border:false, closable: true, renderTo:document.body}, config);
	   	var apply = (config.parentPanel) ? config.parentPanel : 'main-tabs';
	   	if(config.id && Ext.getCmp(config.id)) {
	   		Ext.Msg.alert("Es ist bereits ein Panel ge&ouml;ffnet. Bitte benutzen Sie dieses.");
	   	}
	  	var panel = new Ext.Panel(options);
	  	Ext.getCmp(apply).add(panel);
	   	panel.show();
	   	return panel;
	}
}

Qcat.print = function(id){    
	var printdlg = window.open('', "PrintDialog", "width=740,height=325,toolbars=yes,scrollbars=yes,status=no");
	printdlg.document.writeln(document.getElementById(id).innerHTML);
	printdlg.document.close();
	printdlg.focus();
	printdlg.print();
	// printdlg.close();
}

