(function(){
  var requiredExtVersion = "3.2.1";
  var currentExtVersion = Ext.version;
  if (requiredExtVersion !== currentExtVersion) {
    alert("Netzke needs Ext " + requiredExtVersion + ". You have " + currentExtVersion + ".");
  }
})();
Ext.BLANK_IMAGE_URL = "/extjs/resources/images/default/s.gif";
Ext.ns('Ext.netzke'); 
Ext.ns('Netzke'); 
Ext.ns('Netzke.page'); 
Ext.QuickTips.init();
Ext.state.Provider.prototype.set = function(){};
Netzke.isObject = function(o) {
  return (o != null && typeof o == "object" && o.constructor.toString() == Object.toString());
}
String.prototype.camelize=function(lowFirstLetter)
{
  var str=this; 
  var str_path=str.split('/');
  for(var i=0;i<str_path.length;i++)
  {
    var str_arr=str_path[i].split('_');
    var initX=((lowFirstLetter&&i+1==str_path.length)?(1):(0));
    for(var x=initX;x<str_arr.length;x++)
      str_arr[x]=str_arr[x].charAt(0).toUpperCase()+str_arr[x].substring(1);
    str_path[i]=str_arr.join('');
  }
  str=str_path.join('::');
  return str;
};
String.prototype.capitalize=function()
{
  var str=this.toLowerCase();
  str=str.substring(0,1).toUpperCase()+str.substring(1);
  return str;
};
String.prototype.humanize=function(lowFirstLetter)
{
  var str=this.toLowerCase();
  str=str.replace(new RegExp('_id','g'),'');
  str=str.replace(new RegExp('_','g'),' ');
  if(!lowFirstLetter)str=str.capitalize();
  return str;
};
Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
  readRecords : function(o){
    var sid = this.meta ? this.meta.id : null;
    var recordType = this.recordType, fields = recordType.prototype.fields;
    var records = [];
    var root = o[this.meta.root] || o, totalRecords = o[this.meta.totalProperty], success = o[this.meta.successProperty];
    for(var i = 0; i < root.length; i++){
      var n = root[i];
      var values = {};
      var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
      for(var j = 0, jlen = fields.length; j < jlen; j++){
        var f = fields.items[j];
        var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
        var v = n[k] !== undefined ? n[k] : f.defaultValue;
        v = f.convert(v, n);
        values[f.name] = v;
      }
      var record = new recordType(values, id);
      record.json = n;
      records[records.length] = record;
    }
    return {
      records : records,
      totalRecords : totalRecords,
      success : success
    };
  }
});
Ext.widgetMixIn = {
  height: 400,
  border: false,
  isNetzke: true, 
  latestResult: {}, 
  loadAggregatee: function(params){
    var apiParams = Ext.apply({id: params.id, container: params.container}, params.params); 
    var cachedWidgetNames = "";
    var classesList = function(pref){
      var res = [];
      for (name in this) {
        if (this[name].xtype) {
          res.push(pref + name);
          this[name].classesList = classesList; 
          res = res.concat(this[name].classesList(pref + name + ".")); 
        }
      }
      return res;
    };
    Netzke.classes.classesList = classesList;
    var cl = Netzke.classes.classesList("");
    var cache = "";
    Ext.each(cl, function(c){cache += c + ",";});
    apiParams.cache = cache;
    if (params.callback) {
      this.callbackHash[params.id] = params.callback; 
    }
    if (params.container) Ext.getCmp(params.container).removeChild(); 
    this.loadAggregateeWithCache(apiParams);
  },
  widgetLoaded : function(params){
    if (this.fireEvent('widgetload')) {
      var callbackFn = this.callbackHash[params.id.camelize(true)];
      if (callbackFn) {
        callbackFn.call(params.scope || this, this.getChildWidget(params.id));
        delete this.callbackHash[params.id.camelize(true)];
      }
    }
  },
  getParent: function(){
    var idSplit = this.id.split("__");
    idSplit.pop();
    var parentId = idSplit.join("__");
    return parentId === "" ? null : Ext.getCmp(parentId);
  },
  reload : function(){
    var parent = this.getParent();
    if (parent) {
      parent.loadAggregatee({id:this.localId(parent), container:this.ownerCt.id});
    } else {
      window.location.reload();
    }
  },
  localId : function(parent){
    return this.id.replace(parent.id + "__", "");
  },
  renderWidgetInContainer : function(params){
    var cont = Ext.getCmp(params.container);
    if (cont) {
      cont.instantiateChild(params.config);
    } else {
      this.instantiateChild(params.config);
    }
  },
  reconfigure: function(config){
    this.ownerCt.instantiateChild(config)
  },
  css : function(code){
    var linkTag = document.createElement('style');
    linkTag.type = 'text/css';
    linkTag.innerHTML = code;
    document.body.appendChild(linkTag);
  },
  js : function(code){
    eval(code);
  },
  bulkExecute : function(instructions){
    if (Ext.isArray(instructions)) {
      Ext.each(instructions, function(instruction){ this.bulkExecute(instruction)}, this);
    } else {
      for (var instr in instructions) {
        if (this[instr]) {
          this[instr].apply(this, [instructions[instr]]);
        } else {
          var childWidget = this.getChildWidget(instr);
          if (childWidget) {
            childWidget.bulkExecute(instructions[instr]);
          } else {
            throw "Netzke: Unknown method or child widget '" + instr +"' in widget '" + this.id + "'"
          }
        }
      }
    }
  },
  getChildWidget : function(id){
    if (id === "") {return this};
    var split = id.split("__");
    if (split[0] === 'parent') {
      split.shift();
      var childInParentScope = split.join("__");
      return this.getParent().getChildWidget(childInParentScope);
    } else {
      return Ext.getCmp(this.id+"__"+id);
    }
  },
  actionHandler : function(comp){
    var actionName = comp.name;
    if (this.fireEvent(actionName+'click', comp)) {
      var action = this.actions[actionName];
      var customHandler = action.initialConfig.customHandler;
      var methodName = (customHandler && customHandler.camelize(true)) || "on" + actionName.camelize();
      if (!this[methodName]) {throw "Netzke: action handler '" + methodName + "' is undefined"}
      this[methodName](comp);
    }
  },
  toolActionHandler : function(tool){
    if (this.fireEvent(tool.id+'click')) {
      var methodName = "on"+tool.camelize();
      if (!this[methodName]) {throw "Netzke: handler for tool '"+tool+"' is undefined"}
      this[methodName]();
    }
  },
  buildApiUrl: function(apip){
    return "/netzke/" + this.id + "__" + apip;
  },
  callServer : function(intp, params, callback, scope){
    if (!params) params = {};
      Ext.Ajax.request({
      params: params,
      url: this.buildApiUrl(intp),
      callback: function(options, success, response){
        if (success) {
          this.bulkExecute(Ext.decode(response.responseText));
          if (typeof callback == 'function') { 
            if (!scope) scope = this;
            callback.apply(scope, [this.latestResult]);
          }
        }
      },
      scope : this
    });
  },
  setResult: function(result) {
    this.latestResult = result;
  },
  normalizeMenuItems: function(arry, scope){
    var res = []; 
    Ext.each(arry, function(o){
      if (typeof o === "string") {
        var camelized = o.camelize(true);
        if (scope.actions[camelized]){
          res.push(scope.actions[camelized]);
        } else {
          res.push(o);
        }
      } else if (Netzke.isObject(o)) {
        if (o.menu) {
          o.menu = this.normalizeMenuItems(o.menu, scope);
        } else if (o.handler && Ext.isFunction(scope[o.handler.camelize(true)])) {
          o.handler = scope[o.handler.camelize(true)];
        }
        res.push(o);
      }
    }, this);
    delete arry;
    return res;
  },
  commonBeforeConstructor : function(config){
    var apiPoints = config.netzkeApi || [];
    apiPoints.push('load_aggregatee_with_cache'); 
    Ext.each(apiPoints, function(intp){
      this[intp.camelize(true)] = function(args, callback, scope){ this.callServer(intp, args, callback, scope); }
    }, this);
    this.actions = {};
    if (config.actions) {
      for (var name in config.actions) {
        this.addEvents(name+'click');
        var actionConfig = config.actions[name];
        actionConfig.customHandler = actionConfig.handler || actionConfig.fn; 
        actionConfig.handler = this.actionHandler.createDelegate(this); 
        actionConfig.name = name;
        this.actions[name] = new Ext.Action(actionConfig);
      }
      config.actions = this.actions;
    }
    config.bbar = config.bbar && this.normalizeMenuItems(config.bbar, this);
    config.tbar = config.tbar && this.normalizeMenuItems(config.tbar, this);
    config.fbar = config.fbar && this.normalizeMenuItems(config.fbar, this);
    config.contextMenu = config.contextMenu && this.normalizeMenuItems(config.contextMenu, this);
    config.menu = config.menu && this.normalizeMenuItems(config.menu, this);
    if (config.tools) {
      var normTools = [];
      Ext.each(config.tools, function(tool){
        this.addEvents(tool.id+'click');
        var handler = this.toolActionHandler.createDelegate(this, [tool]);
        normTools.push({id : tool, handler : handler, scope : this});
      }, this);
      config.tools = normTools;
    }
    if (config.mode === "config"){
      if (!config.title) {
        config.title = '[' + config.id + ']';
      } else {
        config.title = config.title + ' [' + config.id + ']';
      }
    } else {
      if (!config.title) {
        config.title = config.id.humanize();
      }
    }
  },
  commonAfterConstructor : function(config){
    this.feedbackGhost = new Netzke.FeedbackGhost();
    if (this.initialConfig.menu) {this.addMenu(this.initialConfig.menu, this);}
    this.addEvents(
      'widgetload' 
    );
    this.on('beforedestroy', function(){
      this.cleanUpMenu();
    }, this);
    this.callbackHash = {};
    if (this.afterConstructor) this.afterConstructor(config);
  },
  feedback:function(msg){
    if (this.initialConfig && this.initialConfig.quiet) {
      return false;
    }
    if (this.feedbackGhost) {
      this.feedbackGhost.showFeedback(msg);
    } else {
      if (typeof msg == 'string'){
        alert(msg);
      } else {
        var compoundResponse = "";
        Ext.each(msg, function(m){
          compoundResponse += m.msg + "\n"
        });
        if (compoundResponse != "") {
          alert(compoundResponse);
        }
      }
    }
  },
  addMenu : function(menu, owner){
    if (!owner) {
      owner = this;
    }
    if (!!this.hostMenu) { 
      this.hostMenu(menu, owner); 
    } else {
      if (this.ownerWidget) {
        this.ownerWidget.addMenu(menu, owner);
      }
    }
  },
  cleanUpMenu : function(owner){
    if (!owner) {
      owner = this;
    }
    if (!!this.unhostMenu) { 
      this.unhostMenu(owner); 
    } else {
      if (this.ownerWidget) {
        this.ownerWidget.cleanUpMenu(owner);
      }
    }
  },
  onWidgetLoad:Ext.emptyFn 
};
Ext.override(Ext.Container, {
  getOwnerWidget : function(){
    if (this.initialConfig.isNetzke) {
      return this;
    } else {
      if (this.ownerCt){
        return this.ownerCt.getOwnerWidget()
      } else {
        return null
      }
    }
  },
  getWidget: function(){
    return this.items ? this.items.get(0) : null; 
  },
  removeChild : function(){
    this.remove(this.getWidget());
  },
  classifyScopedName : function(n){
    var klass = Netzke.classes;
    Ext.each(n.split("."), function(s){
      klass = klass[s];
    });
    return klass;
  },
  instantiateChild : function(config){
    var klass = this.classifyScopedName(config.scopedClassName);
    var instance = new klass(config);
    if (instance.isXType("netzkewindow")) {
      instance.show();
    } else {
      this.remove(this.getWidget()); 
      this.add(instance);
      this.doLayout();
    }
  }
});
Netzke.FeedbackGhost = function(){};
Ext.apply(Netzke.FeedbackGhost.prototype, {
  showFeedback: function(msg){
    var createBox = function(s, l){
        return ['<div class="msg">',
                '<div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>',
                '<div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">', s, '</div></div></div>',
                '<div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>',
                '</div>'].join('');
    }
    var showBox = function(msg, lvl){
      if (!lvl) {lvl = 'notice'};
      var msgCt = Ext.DomHelper.insertFirst(document.body, {'class':'netzke-feedback'}, true);
      var m = Ext.DomHelper.append(msgCt, {html:createBox(msg,lvl)}, true);
      m.slideIn('t').pause(2).ghost("b", {remove:true});
    }
    if (typeof msg != 'string') {
      var compoundMsg = "";
      Ext.each(msg, function(m){
        compoundMsg += m.msg + '<br>';
      });
      if (compoundMsg != "") showBox(compoundMsg, null); 
    } else {
      showBox(msg);
    }
	}
});
Ext.apply(Ext.History, new Ext.util.Observable());
Ext.netzke.PassField = Ext.extend(Ext.form.TextField, {
  inputType: 'password'
});
Ext.reg('passfield', Ext.netzke.PassField);
Ext.netzke.ComboBox = Ext.extend(Ext.form.ComboBox, {
  displayField  : 'id',
  valueField    : 'id',
  triggerAction : 'all',
  typeAhead     : true,
  initComponent : function(){
    var row = Ext.data.Record.create([{name:'id'}]);
    var store = new Ext.data.Store({
      proxy         : new Ext.data.HttpProxy({url: Ext.getCmp(this.parentId).buildApiUrl("get_combobox_options"), jsonData:{column:this.name}}),
      reader        : new Ext.data.ArrayReader({root:'data', id:0}, row)
    });
    Ext.apply(this, {
      store : store
    });
    Ext.netzke.ComboBox.superclass.initComponent.apply(this, arguments);
    this.on('blur', function(cb){
      cb.setValue(cb.getRawValue());
    });
    this.on('specialkey', function(cb, event){
      if (event.getKey() == 9 || event.getKey() == 13) {cb.setValue(cb.getRawValue());}
    });
  }
});
Ext.reg('combobox', Ext.netzke.ComboBox);
Ext.util.Format.mask = function(v){
  return "********";
};
Ext.data.RecordArrayReader = Ext.extend(Ext.data.JsonReader, {
  readRecord : function(o){
    var sid = this.meta ? this.meta.id : null;
    var recordType = this.recordType, fields = recordType.prototype.fields;
    var records = [];
    var root = o;
    var n = root;
    var values = {};
    var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
    for(var j = 0, jlen = fields.length; j < jlen; j++){
      var f = fields.items[j];
      var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
      var v = n[k] !== undefined ? n[k] : f.defaultValue;
      v = f.convert(v, n);
      values[f.name] = v;
    }
    var record = new recordType(values, id);
    record.json = n;
    return record;
  }
});
Ext.netzke.JsonField = Ext.extend(Ext.form.TextField, {
  validator: function(value) {
    try{
      var d = Ext.decode(value);
      return true;
    } catch(e) {
      return "Invalid JSON"
    }
  }
  ,setValue: function(value) {
    this.setRawValue(Ext.encode(value));
  }
});
Ext.reg('jsonfield', Ext.netzke.JsonField);
Ext.ns('Ext.ux.form');
Ext.ux.form.DateTime = Ext.extend(Ext.form.Field, {
     defaultAutoCreate:{tag:'input', type:'hidden'}
    ,timeWidth:80
    ,dtSeparator:' '
    ,hiddenFormat:'Y-m-d H:i:s'
    ,otherToNow:true
    ,timePosition:'right' 
    ,dateFormat:'m/d/y'
    ,timeFormat:'g:i A'
    ,initComponent:function() {
        Ext.ux.form.DateTime.superclass.initComponent.call(this);
        var dateConfig = Ext.apply({}, {
             id:this.id + '-date'
            ,format:this.dateFormat || Ext.form.DateField.prototype.format
            ,width:this.timeWidth
            ,selectOnFocus:this.selectOnFocus
            ,listeners:{
                  blur:{scope:this, fn:this.onBlur}
                 ,focus:{scope:this, fn:this.onFocus}
            }
        }, this.dateConfig);
        this.df = new Ext.form.DateField(dateConfig);
        this.df.ownerCt = this;
        delete(this.dateFormat);
        var timeConfig = Ext.apply({}, {
             id:this.id + '-time'
            ,format:this.timeFormat || Ext.form.TimeField.prototype.format
            ,width:this.timeWidth
            ,selectOnFocus:this.selectOnFocus
            ,listeners:{
                  blur:{scope:this, fn:this.onBlur}
                 ,focus:{scope:this, fn:this.onFocus}
            }
        }, this.timeConfig);
        this.tf = new Ext.form.TimeField(timeConfig);
        this.tf.ownerCt = this;
        delete(this.timeFormat);
        this.relayEvents(this.df, ['focus', 'specialkey', 'invalid', 'valid']);
        this.relayEvents(this.tf, ['focus', 'specialkey', 'invalid', 'valid']);
    } 
    ,onRender:function(ct, position) {
        if(this.isRendered) {
            return;
        }
        Ext.ux.form.DateTime.superclass.onRender.call(this, ct, position);
        var t;
        if('below' === this.timePosition || 'bellow' === this.timePosition) {
            t = Ext.DomHelper.append(ct, {tag:'table',style:'border-collapse:collapse',children:[
                 {tag:'tr',children:[{tag:'td', style:'padding-bottom:1px', cls:'ux-datetime-date'}]}
                ,{tag:'tr',children:[{tag:'td', cls:'ux-datetime-time'}]}
            ]}, true);
        }
        else {
            t = Ext.DomHelper.append(ct, {tag:'table',style:'border-collapse:collapse',children:[
                {tag:'tr',children:[
                    {tag:'td',style:'padding-right:4px', cls:'ux-datetime-date'},{tag:'td', cls:'ux-datetime-time'}
                ]}
            ]}, true);
        }
        this.tableEl = t;
        this.wrap = t.wrap();
        this.wrap.on("mousedown", this.onMouseDown, this, {delay:10});
        this.df.render(t.child('td.ux-datetime-date'));
        this.tf.render(t.child('td.ux-datetime-time'));
        if(Ext.isIE && Ext.isStrict) {
            t.select('input').applyStyles({top:0});
        }
        this.on('specialkey', this.onSpecialKey, this);
        this.df.el.swallowEvent(['keydown', 'keypress']);
        this.tf.el.swallowEvent(['keydown', 'keypress']);
        if('side' === this.msgTarget) {
            var elp = this.el.findParent('.x-form-element', 10, true);
            this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
            this.df.errorIcon = this.errorIcon;
            this.tf.errorIcon = this.errorIcon;
        }
        this.el.dom.name = this.hiddenName || this.name || this.id;
        this.df.el.dom.removeAttribute("name");
        this.tf.el.dom.removeAttribute("name");
        this.isRendered = true;
        this.updateHidden();
    } 
    ,adjustSize:Ext.BoxComponent.prototype.adjustSize
    ,alignErrorIcon:function() {
        this.errorIcon.alignTo(this.tableEl, 'tl-tr', [2, 0]);
    }
    ,initDateValue:function() {
        this.dateValue = this.otherToNow ? new Date() : new Date(1970, 0, 1, 0, 0, 0);
    }
    ,clearInvalid:function(){
        this.df.clearInvalid();
        this.tf.clearInvalid();
    } 
    ,beforeDestroy:function() {
        if(this.isRendered) {
            this.wrap.removeAllListeners();
            this.wrap.remove();
            this.tableEl.remove();
            this.df.destroy();
            this.tf.destroy();
        }
    } 
    ,disable:function() {
        if(this.isRendered) {
            this.df.disabled = this.disabled;
            this.df.onDisable();
            this.tf.onDisable();
        }
        this.disabled = true;
        this.df.disabled = true;
        this.tf.disabled = true;
        this.fireEvent("disable", this);
        return this;
    } 
    ,enable:function() {
        if(this.rendered){
            this.df.onEnable();
            this.tf.onEnable();
        }
        this.disabled = false;
        this.df.disabled = false;
        this.tf.disabled = false;
        this.fireEvent("enable", this);
        return this;
    } 
    ,focus:function() {
        this.df.focus();
    } 
    ,getPositionEl:function() {
        return this.wrap;
    }
    ,getResizeEl:function() {
        return this.wrap;
    }
    ,getValue:function() {
        return this.dateValue ? new Date(this.dateValue) : '';
    } 
    ,isValid:function() {
        return this.df.isValid() && this.tf.isValid();
    } 
    ,isVisible : function(){
        return this.df.rendered && this.df.getActionEl().isVisible();
    } 
    ,onBlur:function(f) {
        if(this.wrapClick) {
            f.focus();
            this.wrapClick = false;
        }
        if(f === this.df) {
            this.updateDate();
        }
        else {
            this.updateTime();
        }
        this.updateHidden();
        (function() {
            if(!this.df.hasFocus && !this.tf.hasFocus) {
                var v = this.getValue();
                if(String(v) !== String(this.startValue)) {
                    this.fireEvent("change", this, v, this.startValue);
                }
                this.hasFocus = false;
                this.fireEvent('blur', this);
            }
        }).defer(100, this);
    } 
    ,onFocus:function() {
        if(!this.hasFocus){
            this.hasFocus = true;
            this.startValue = this.getValue();
            this.fireEvent("focus", this);
        }
    }
    ,onMouseDown:function(e) {
        if(!this.disabled) {
            this.wrapClick = 'td' === e.target.nodeName.toLowerCase();
        }
    }
    ,onSpecialKey:function(t, e) {
        var key = e.getKey();
        if(key === e.TAB) {
            if(t === this.df && !e.shiftKey) {
                e.stopEvent();
                this.tf.focus();
            }
            if(t === this.tf && e.shiftKey) {
                e.stopEvent();
                this.df.focus();
            }
        }
        if(key === e.ENTER) {
            this.updateValue();
        }
    } 
    ,setDate:function(date) {
        this.df.setValue(date);
    } 
    ,setTime:function(date) {
        this.tf.setValue(date);
    } 
    ,setSize:function(w, h) {
        if(!w) {
            return;
        }
        if('below' === this.timePosition) {
            this.df.setSize(w, h);
            this.tf.setSize(w, h);
            if(Ext.isIE) {
                this.df.el.up('td').setWidth(w);
                this.tf.el.up('td').setWidth(w);
            }
        }
        else {
            this.df.setSize(w - this.timeWidth - 4, h);
            this.tf.setSize(this.timeWidth, h);
            if(Ext.isIE) {
                this.df.el.up('td').setWidth(w - this.timeWidth - 4);
                this.tf.el.up('td').setWidth(this.timeWidth);
            }
        }
    } 
    ,setValue:function(val) {
        if(!val && true === this.emptyToNow) {
            this.setValue(new Date());
            return;
        }
        else if(!val) {
            this.setDate('');
            this.setTime('');
            this.updateValue();
            return;
        }
        if ('number' === typeof val) {
          val = new Date(val);
        }
        else if('string' === typeof val && this.hiddenFormat) {
            val = Date.parseDate(val, this.hiddenFormat)
        }
        val = val ? val : new Date(1970, 0 ,1, 0, 0, 0);
        var da, time;
        if(val instanceof Date) {
            this.setDate(val);
            this.setTime(val);
            this.dateValue = new Date(val);
        }
        else {
            da = val.split(this.dtSeparator);
            this.setDate(da[0]);
            if(da[1]) {
                if(da[2]) {
                    da[1] += da[2];
                }
                this.setTime(da[1]);
            }
        }
        this.updateValue();
    } 
    ,setVisible: function(visible){
        if(visible) {
            this.df.show();
            this.tf.show();
        }else{
            this.df.hide();
            this.tf.hide();
        }
        return this;
    } 
    ,show:function() {
        return this.setVisible(true);
    } 
    ,hide:function() {
        return this.setVisible(false);
    } 
    ,updateDate:function() {
        var d = this.df.getValue();
        if(d) {
            if(!(this.dateValue instanceof Date)) {
                this.initDateValue();
                if(!this.tf.getValue()) {
                    this.setTime(this.dateValue);
                }
            }
            this.dateValue.setMonth(0); 
            this.dateValue.setFullYear(d.getFullYear());
            this.dateValue.setMonth(d.getMonth(), d.getDate());
        }
        else {
            this.dateValue = '';
            this.setTime('');
        }
    } 
    ,updateTime:function() {
        var t = this.tf.getValue();
        if(t && !(t instanceof Date)) {
            t = Date.parseDate(t, this.tf.format);
        }
        if(t && !this.df.getValue()) {
            this.initDateValue();
            this.setDate(this.dateValue);
        }
        if(this.dateValue instanceof Date) {
            if(t) {
                this.dateValue.setHours(t.getHours());
                this.dateValue.setMinutes(t.getMinutes());
                this.dateValue.setSeconds(t.getSeconds());
            }
            else {
                this.dateValue.setHours(0);
                this.dateValue.setMinutes(0);
                this.dateValue.setSeconds(0);
            }
        }
    } 
    ,updateHidden:function() {
        if(this.isRendered) {
            var value = this.dateValue instanceof Date ? this.dateValue.format(this.hiddenFormat) : '';
            this.el.dom.value = value;
        }
    }
    ,updateValue:function() {
        this.updateDate();
        this.updateTime();
        this.updateHidden();
        return;
    } 
    ,validate:function() {
        return this.df.validate() && this.tf.validate();
    } 
    ,renderer: function(field) {
        var format = field.editor.dateFormat || Ext.ux.form.DateTime.prototype.dateFormat;
        format += ' ' + (field.editor.timeFormat || Ext.ux.form.DateTime.prototype.timeFormat);
        var renderer = function(val) {
            var retval = Ext.util.Format.date(val, format);
            return retval;
        };
        return renderer;
    } 
}); 
Ext.reg('xdatetime', Ext.ux.form.DateTime);
Ext.grid.HeaderDropZone.prototype.onNodeDrop = function(n, dd, e, data){
    var h = data.header;
    if(h != n){
        var cm = this.grid.colModel;
        var x = Ext.lib.Event.getPageX(e);
        var r = Ext.lib.Dom.getRegion(n.firstChild);
        var pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before";
        var oldIndex = this.view.getCellIndex(h);
        var newIndex = this.view.getCellIndex(n);
        if(pt == "after"){
            newIndex++;
        }
        if(oldIndex < newIndex){
            newIndex--;
        }
        cm.moveColumn(oldIndex, newIndex);
        return true;
    }
    return false;
};
Ext.override(Ext.Panel, {
    onResize : function(w, h, rw, rh){
        if(Ext.isDefined(w) || Ext.isDefined(h)){
            if(!this.collapsed){
                if(Ext.isNumber(w)){
                    this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
                } else if (w == 'auto') {
                    w = this.body.setWidth('auto').dom.offsetWidth;
                } else {
                    w = this.body.dom.offsetWidth;
                }
                if(this.tbar){
                    this.tbar.setWidth(w);
                    if(this.topToolbar){
                        this.topToolbar.setSize(w);
                    }
                }
                if(this.bbar){
                    this.bbar.setWidth(w);
                    if(this.bottomToolbar){
                        this.bottomToolbar.setSize(w);
                        if (Ext.isIE) {
                            this.bbar.setStyle('position', 'static');
                            this.bbar.setStyle('position', '');
                        }
                    }
                }
                if(this.footer){
                    this.footer.setWidth(w);
                    if(this.fbar){
                        this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
                    }
                }
                if(Ext.isNumber(h)){
                    h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
                    this.body.setHeight(h);
                }else if(h == 'auto'){
                    this.body.setHeight(h);
                }
                if(this.disabled && this.el._mask){
                    this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
                }
            }else{
                this.queuedBodySize = {width: w, height: h};
                if(!this.queuedExpand && this.allowQueuedExpand !== false){
                    this.queuedExpand = true;
                    this.on('expand', function(){
                        delete this.queuedExpand;
                        this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
                    }, this, {single:true});
                }
            }
            this.onBodyResize(w, h);
        }
        this.syncShadow();
        Ext.Panel.superclass.onResize.call(this, w, h, rw, rh);
    }
});
Ext.ns('Ext.ux.form');
Ext.ux.form.TriCheckbox = Ext.extend(Ext.form.Checkbox, {
	checked: null,
	valueList: [null, false, true],	
	stateClassList: ['x-checkbox-undef', null, 'x-checkbox-checked'],
	overClass: 'x-form-check-over',
	clickClass: 'x-form-check-down',
	triState: true,
	defaultAutoCreate: {tag: 'input', type: 'hidden', autocomplete: 'off'},
	initComponent: function() {
		this.value = this.checked;
		Ext.ux.form.TriCheckbox.superclass.initComponent.apply(this, arguments);
		this.vList = this.valueList.slice(0);
		this.cList = this.stateClassList.slice(0);
		if(this.triState !== true) {
			this.vList.shift();
			this.cList.shift();
		}
		if(this.overCls !== undefined) {
			this.overClass = this.overCls;
			delete this.overCls;
		}
		this.value = this.normalizeValue(this.value);
	},
	onRender : function(ct, position){
		Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
		this.innerWrap = this.el.wrap({tag: 'span', cls: 'x-form-check-innerwrap'});
		this.wrap = this.innerWrap.wrap({cls: 'x-form-check-wrap'});
		this.currCls = this.getCls(this.value);
		this.wrap.addClass(this.currCls);
		if(this.clickClass && !this.disabled && !this.readOnly)
			this.innerWrap.addClassOnClick(this.clickClass);
		if(this.overClass && !this.disabled && !this.readOnly)
			this.innerWrap.addClassOnOver(this.overClass);
		this.imageEl = this.innerWrap.createChild({
			tag: 'img',
			src: Ext.BLANK_IMAGE_URL,
			cls: 'x-form-tscheckbox'
		}, this.el);
		if(this.fieldClass) this.imageEl.addClass(this.fieldClass);
		if(this.boxLabel){
			this.innerWrap.createChild({
				tag: 'label', 
				htmlFor: this.el.id, 
				cls: 'x-form-cb-label', 
				html: this.boxLabel
			});
		}
		if(Ext.isIE){
			this.wrap.repaint();
		}
		this.resizeEl = this.positionEl = this.wrap;
	},
	onResize : function(){
		Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
		if(!this.boxLabel && !this.fieldLabel && this.imageEl){
			this.imageEl.alignTo(this.wrap, 'c-c');
		}
	},
	initEvents : function(){
		Ext.form.Checkbox.superclass.initEvents.call(this);
		this.mon(this.innerWrap, {
			scope: this,
			click: this.onClick
		});
	},
	onClick : function(){
		if (!this.disabled && !this.readOnly) {
			this.setValue(this.vList[(this.vList.indexOf(this.value) + 1) % this.vList.length]);
		}
	},
	getValue : function(){
		return this.value;
	},
	setValue : function(v){
		var value = this.value;
		this.value = this.normalizeValue(v);
		if(this.rendered) this.el.dom.value = this.value;
		if(value !== this.value){
			this.updateView();
			this.fireEvent('check', this, this.value);
			if(this.handler) this.handler.call(this.scope || this, this, this.value);
		}
		return this;
	},
	normalizeValue: function(v) {
		return (v === null || v === undefined) && this.triState ? null : 
			(v === true || (['true', 'yes', 'on', '1']).indexOf(String(v).toLowerCase()) != -1);
	},
	getCls: function(v) {
		var idx = this.vList.indexOf(this.value);
		return idx > -1 ? this.cList[idx] : undefined;
	},
	updateView: function() {
		var cls = this.getCls(this.value);
		if (!this.wrap || cls === undefined) return;
		this.wrap.replaceClass(this.currCls, cls);
		this.currCls = cls;
	}
});
Ext.reg('tricheckbox', Ext.ux.form.TriCheckbox);  