// vim: ts=4:sw=4:nu:fdc=4:nospell
/**
 * Ext.ux.plugins
 *
 * @author    Ing. Jozef Sakáloš <jsakalos@aariadne.com>
 * @copyright (c) 2007, by Ing. Jozef Sakáloš
 * @date      24. November 2007
 * @version   $Id: Ext.ux.plugins.js 596 2007-11-25 13:40:43Z jozo $
 */
 
Ext.namespace('Ext.ux', 'Ext.ux.plugins');
 
/**
 * Remote Validator
 * Makes remote (server) field validation easier
 *
 * To be used by form fields like TextField, NubmerField, TextArea, ...
 */
Ext.ux.plugins.RemoteValidator = {
    init:function(field) {
        // save original functions
        var isValid = field.isValid;
        var validate = field.validate;
 
        // apply remote validation to field
        Ext.apply(field, {
             remoteValid:false
 
            // private
            ,isValid:function(preventMark) {
                if(this.disabled) {
                    return true;
                }
                return isValid.call(this, preventMark) && this.remoteValid;
            }
 
            // private
            ,validate:function() {
                var clientValid = validate.call(this);
                if(!this.disabled && !clientValid) {
                    return false;
                }
                if(this.disabled || (clientValid && this.remoteValid)) {
                    this.clearInvalid();
                    return true;
                }
                if(!this.remoteValid) {
                    this.markInvalid(this.reason);
                    return false;
                }
                return false;
            }
 
            // private - remote validation request
            ,validateRemote:function() {
                this.rvOptions.params = this.rvOptions.params || {};
                this.rvOptions.params.field = this.name;
                this.rvOptions.params.value = this.getValue();
                Ext.Ajax.request(this.rvOptions);
            }
 
            // private - remote validation request success handler
            ,rvSuccess:function(response, options) {
                var o;
                try {
                    o = Ext.decode(response.responseText);
                }
                catch(e) {
                    throw this.cannotDecodeText;
                }
                if('object' !== typeof o) {
                    throw this.notObjectText;
                }
                if(true !== o.success) {
                    throw this.serverErrorText + ': ' + o.error;
                }
                var names = this.rvOptions.paramNames;
                this.remoteValid = true === o[names.valid];
                this.reason = o[names.reason];
                this.validate();
            }
 
            // private - remote validation request failure handler
            ,rvFailure:function(response, options) {
                throw this.requestFailText
            }
 
            // private - runs from keyup event handler
            ,filterRemoteValidation:function(e) {
                if(!e.isNavKeyPress()) {
                    this.remoteValidationTask.delay(this.remoteValidationDelay);
                }
            }
        });
 
        // remote validation defaults
        Ext.applyIf(field, {
             remoteValidationDelay:500
            ,reason:'Server has not yet validated the value'
            ,cannotDecodeText:'Cannot decode json object'
            ,notObjectText:'Server response is not an object'
            ,serverErrorText:'Server error'
            ,requestFailText:'Server request failed'
        });
 
        // install event handlers on field render
        field.on({
            render:{single:true, scope:field, fn:function() {
                this.remoteValidationTask = new Ext.util.DelayedTask(this.validateRemote, this);
                this.el.on(this.validationEvent, this.filterRemoteValidation, this);
            }}
        });
 
        // setup remote validation request options
        field.rvOptions = field.rvOptions || {};
        Ext.applyIf(field.rvOptions, {
             method:'post'
            ,scope:field
            ,success:field.rvSuccess
            ,failure:field.rvFailure
            ,paramNames: {
                 valid:'valid'
                ,reason:'reason'
            }
        });
    }
};
 
// end of file