function call( url, parameters, method, scope, use_loader ){
    
    use_loader = (use_loader == true)?true:false;
    method = (method)?method:'POST';
    
    try {
	    if( connect != undefined && connect.statusbar ){
	        connect.statusbar.showBusy();
	    }
	} catch( e ){
		connect = {};
	}
    
    if(use_loader)
        Ext.MessageBox.show({
            msg: 'Loading data, please wait...',
            progressText: 'Loading',
            width:300,
            wait:true,
            waitConfig: {interval:200},
            icon:'ext-mb-download'
        });
        
    this.handler = function( options, success, response ){
        if( success && response.responseText.length > 0) {
            try {
                eval(response.responseText);
                if(use_loader) Ext.MessageBox.hide();   
            } catch (e) {
                if( connect != undefined && connect.statusbar ){
                    connect.statusbar.clearStatus({useDefaults:true});
                }
                if(use_loader) Ext.MessageBox.hide();  
                //if(opera) opera.postError(response.responseText);
                Ext.MessageBox.show({
                   title: 'Error',
                   width:400,
                   msg: 'Unable to perform operation.<br /><br><br><br /><b>Reason:</b><br /><br />'+e.name+'<br />'+e.message,
                   buttons: Ext.MessageBox.OK,
                   icon: 'ext-mb-error'
               });
               if(typeof(console) != 'undefined') console.error( 'Exception:\n' + e + '\nResponse:\n' + response.responseText );
            }
                if( connect != undefined && connect.statusbar ){
                    connect.statusbar.clearStatus({useDefaults:true});
                }
        } else {
                if(use_loader) Ext.MessageBox.hide();   
                Ext.MessageBox.show({
                   title: 'Error',
                   msg: 'Unable to perform operation.<br /><br><br><br /><b>Reason:</b><br /><br />Server-side operation unsuccessful.',
                   buttons: Ext.MessageBox.OK,
                   icon: 'ext-mb-error'
               });
               if(typeof(console) != 'undefined') console.error('Response: ' + response.responseText);
               
                if( connect != undefined && connect.statusbar ){
                    connect.statusbar.clearStatus({useDefaults:true});
                }
        }            
    };

    var original_call = {
        url: url
        ,parameters: parameters
        ,method: method 
        ,scope: ((scope && scope.getId())?scope.getId():null)
        ,use_loader: use_loader
    };
    
    var options = {
        url: url
        ,method: method
        ,scope: scope
        ,callback:this.handler
        ,params:parameters
        ,headers: {
            'original-call-params': Ext.util.JSON.encode(original_call)
        }
    };
    
    Ext.Ajax.request(options);
}


function request (url, parameters, callback, container, method, use_loader, scope) {
    
    try {
        if( connect != undefined && connect.statusbar ){
            connect.statusbar.showBusy();
        }
    } catch( e ){
        connect = {};
    }
    
    this.request_result = { success: false };
    
    use_loader = (use_loader == true)?true:false;
    scope = scope || this;
    method = (method)?method:'POST';
    
    if (container) {
        parent = connect.elements[container.unique_name];
        callback = parent.fn[callback];
    }
    
    try {
        if( connect != undefined && connect.statusbar ){
            connect.statusbar.showBusy();
        }
    } catch( e ){
        connect = {};
    }
    
    
    
    if(use_loader)
        Ext.MessageBox.show({
            msg: 'Loading data, please wait...',
            progressText: 'Loading',
            width:300,
            wait:true,
            waitConfig: {interval:200},
            icon:'ext-mb-download'
        });
        
	   // Basic request
	Ext.Ajax.request({
	   url: url,
       method: method,
	   success: function ( result, request ) { 
           if(use_loader) Ext.MessageBox.hide(); 
           try {
                var json_data = Ext.util.JSON.decode(result.responseText);
                callback(json_data);
	        }
	        catch (err) { // if not a json object run it
                eval(result.responseText);
	        }
       },
       failure: function ( result, request) {
            if(use_loader) Ext.MessageBox.hide(); 
            Ext.MessageBox.show({
                   title: 'Error',
                   width:400,
                   msg: 'Unable to perform operation.',
                   buttons: Ext.MessageBox.OK,
                   icon: 'ext-mb-error'
               });
       },
       params: parameters,
       scope: scope
	});
    
    if( connect != undefined && connect.statusbar ){
                    connect.statusbar.clearStatus({useDefaults:true});
                }
}

function downloadCall( url, parameters ){
    document.location = url + '?' + Ext.urlEncode( parameters );
}


function redirect(url){
    Ext.getDoc().dom.location = url;
}

function copyToClipboard(s){
    if( window.clipboardData && clipboardData.setData )
    {
        clipboardData.setData("Text", s);
    }
}


function getSelectedIdsFromSelectionModelContainer( container_id ){
    var records = Ext.ComponentMgr.get( container_id ).getSelectionModel().getSelections();
    var record_ids = [];
    for ( var i in records ){
        if( records[i].get ){
            record_ids[i] =  records[i].get('id');
        }
    }
    return record_ids;
}

function stringSanitize (string){
	return string.replace('/[^a-zA-Z-0-9]+/g','');
}

function trim(str) {
	return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}

Array.prototype.contains = function(p_val) {
	for(var i = 0, l = this.length; i < l; i++) {
		if(this[i] == p_val) {
			return true;
		}
	}
	return false;
}

if (!Array.prototype.map) {
	Array.prototype.map = function(fn, scope) {
		var len = this.length;
		if (typeof fn != "function") throw new TypeError();
		
		var res = new Array(len);
		
		for (var i = 0; i < len; i++) {
			if (i in this) {
				var temp = this[i]; // in case of fn mutates value
				res[i] = fn.call(scope || this, temp, i, this);
			}
		}
		
		return res;
	};
}
