//
// This file contains the Ext 'fixes' that are required to get around
// known bugs.  We keep it separate from the Ext lib installation to
// make it easier to upgrade in the future.  At upgrade time we can go
// through the list of fixes and pull them out if the new version has
// addressed the issue.
//

//
// Issue: If a form field has a vtype assigned to it then it will ignore
//        the allowBlank=true setting and always perform validation.
// Soln:  Over-ride the TextField class so that when allowBlank=true, 
//        validation only occurs when the field contains a non-empty
//        value.
// Reference: 
//        http://www.extjs.com/forum/showthread.php?p=454606#post454606
//
Ext.override(Ext.form.TextField, {
	validateValue : function(value) {
		if(value.length < 1 || value === this.emptyText) { // if it's blank
			if(this.allowBlank) {

				// Check custom validation on empty value
				// Don't use 'value' variable cause it may contain 'this.emptyText'
				if(Ext.isFunction(this.validator)) {
					var msg = this.validator('');
					if(msg !== true) {
						this.markInvalid(msg);
						return false;
					}
				}

				// Don't check other (length, vtype, regex) validators cause it dosen't make sense.
				// On empty value they are always false.
				this.clearInvalid();
				return true;
			} else {
				this.markInvalid(this.blankText);
				return false;
			}
		}

		if(value.length < this.minLength){
			this.markInvalid(String.format(this.minLengthText, this.minLength));
			return false;
		}
		if(value.length > this.maxLength){
			this.markInvalid(String.format(this.maxLengthText, this.maxLength));
			return false;
		}

		if(this.vtype){
			var vt = Ext.form.VTypes;
			if(!vt[this.vtype](value, this)){
				this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
				return false;
			}
		}

		if(this.regex && !this.regex.test(value)){
			this.markInvalid(this.regexText);
			return false;
		}

		if(Ext.isFunction(this.validator)){
			var msg = this.validator(value);
			if(msg !== true){
				this.markInvalid(msg);
				return false;
			}
		}

		return true;
	}
});


// Altered the native DatePicker to include a 'Clear' button.
Ext.override(Ext.DatePicker, {
	
	showClear : true,
	
	onRender : function(container, position){
		var m = [
			'<table cellspacing="0">',
			'<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
			'<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
			dn = this.dayNames,
			i;
		for(i = 0; i < 7; i++){
			var d = this.startDay+i;
			if(d > 6){
				d = d-7;
			}
			m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
		}
		m[m.length] = '</tr></thead><tbody><tr>';
		for(i = 0; i < 42; i++) {
			if(i % 7 === 0 && i !== 0){
				m[m.length] = '</tr><tr>';
			}
			m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
		}
		
		//--Removed
		//m.push('</tr></tbody></table></td></tr>',
		//	this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
		//	'</table><div class="x-date-mp"></div>');
		//--End Removed
		
		//--Added
		var btns = '</tr></tbody></table></td></tr>';
		if (this.showToday && this.showClear) {
			btns += '<tr>';
			btns += '<td class="x-date-bottom x-date-today" align="left"></td>';
			btns += '<td class="x-date-bottom">&nbsp;</td>';
			btns += '<td class="x-date-bottom x-date-clear" align="right"></td>';
			btns += '</tr>';
		} else if (this.showToday) {
			btns += '<tr>';
			btns += '<td colspan="3" class="x-date-bottom x-date-today" align="center"></td>';
			btns += '</tr>';
		} else if (this.showClear) {
			btns += '<tr>';
			btns += '<td colspan="3" class="x-date-bottom x-date-clear" align="center"></td>';
			btns += '</tr>';
		} 
		btns += '</table><div class="x-date-mp"></div>';
		m.push(btns);
		//--End Added
	
		var el = document.createElement('div');
		el.className = 'x-date-picker';
		el.innerHTML = m.join('');
	
		container.dom.insertBefore(el, position);
	
		this.el = Ext.get(el);
		this.eventEl = Ext.get(el.firstChild);
	
		this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
			handler: this.showPrevMonth,
			scope: this,
			preventDefault:true,
			stopDefault:true
		});
	
		this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
			handler: this.showNextMonth,
			scope: this,
			preventDefault:true,
			stopDefault:true
		});
	
		this.monthPicker = this.el.down('div.x-date-mp');
		this.monthPicker.enableDisplayMode('block');
	
		this.keyNav = new Ext.KeyNav(this.eventEl, {
			'left' : function(e){
				if(e.ctrlKey){
					this.showPrevMonth();
				}else{
					this.update(this.activeDate.add('d', -1));
				}
			},
	
			'right' : function(e){
				if(e.ctrlKey){
					this.showNextMonth();
				}else{
					this.update(this.activeDate.add('d', 1));
				}
			},
	
			'up' : function(e){
				if(e.ctrlKey){
					this.showNextYear();
				}else{
					this.update(this.activeDate.add('d', -7));
				}
			},
	
			'down' : function(e){
				if(e.ctrlKey){
					this.showPrevYear();
				}else{
					this.update(this.activeDate.add('d', 7));
				}
			},
	
			'pageUp' : function(e){
				this.showNextMonth();
			},
	
			'pageDown' : function(e){
				this.showPrevMonth();
			},
	
			'enter' : function(e){
				e.stopPropagation();
				return true;
			},
	
			scope : this
		});
	
		this.el.unselectable();
	
		this.cells = this.el.select('table.x-date-inner tbody td');
		this.textNodes = this.el.query('table.x-date-inner tbody span');
	
		this.mbtn = new Ext.Button({
			text: '&#160;',
			tooltip: this.monthYearText,
			renderTo: this.el.child('td.x-date-middle', true)
		});
		this.mbtn.el.child('em').addClass('x-btn-arrow');
	
		if(this.showToday){
			this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
			var today = (new Date()).dateFormat(this.format);
			this.todayBtn = new Ext.Button({
				renderTo: this.el.child('td.x-date-today', true),
				text: String.format(this.todayText, today),
				tooltip: String.format(this.todayTip, today),
				handler: this.selectToday,
				scope: this
			});
		}
		
		//--Added
		if(this.showClear){
			this.clearBtn = new Ext.Button({
				renderTo: this.el.child('td.x-date-clear', true),
				text: "Clear",
				tooltip: "Clear",
				handler: this.clearDate,
				scope: this
			});
		}
		//--End Added
		
		this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
		this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
		this.mon(this.mbtn, 'click', this.showMonthPicker, this);
		this.onEnable(true);
	},

	clearDate : function(){
		this.fireEvent("select", this, '');
	}
	
});


//
// FORM FIELD INFO ICONS
//
// This is an extension.  It give us the ability to show an information icon to
// the right of all form elements.  Use the following set of attributes on any
// Ext.form.Field element to take advantage of this extension:
//
// tooltipText: text to show in a tooltip when hovering over the info icon
// tooltipTitle: title to show in a tooltip when hovering over the info icon
// labelTipEnabled: true to show a tip when hovering over the field's label (default==false)
//
Ext.override(Ext.form.Field, {
	labelTipEnabled: false,
	afterRender: function() {
        var findLabel = function(field) {
            var wrapDiv = null;
            var label = null
            wrapDiv = field.getEl().up("div.x-form-item");
            if (wrapDiv) label = wrapDiv.child("label");
            if (label) return label;
        };
	
		var field = this;
		if (field.tooltipText) {
			if (field.labelTipEnabled) {
				// Add a tooltip to the label
				var label = findLabel(this);
	            if (label) {                       
	                label.addClass(this.tooltipClass || "x-textfield-tooltip");
	                Ext.QuickTips.register({
	                    target:  label,        
	                    title: this.tooltipTitle,           
	                    text: this.tooltipText,
	                    enabled: true,
	                    dismissDelay: 60000 * 30
	                });
	            }
			}

			// Add an info icon with a tooltip
			if (!field.infoIcon) {
				var elp = field.getInfoCt();
	            if(!elp){
	                field.el.dom.title = msg;
	                return;
	            }
	            field.infoIcon = elp.createChild({cls:'x-form-info-icon'});
	            if (field.ownerCt) {
	                field.ownerCt.on('afterlayout', field.alignInfoIcon, field);
	                field.ownerCt.on('expand', field.alignInfoIcon, field);
	            }
	            field.on('resize', field.alignInfoIcon, field);
	            field.on('destroy', function(){ Ext.destroy(this.infoIcon); }, field);
			}
			field.alignInfoIcon();				
            field.infoIcon.dom.qtip = field.tooltipText;
            if (field.tooltipTitle) {
            	field.infoIcon.dom.qtitle = field.tooltipTitle;
            }
            field.infoIcon.show();
		}

        Ext.form.Field.superclass.afterRender.call(this);    
        this.initEvents();  
        this.initValue();
    },

    getInfoCt : function(){
        return this.el.findParent('.x-form-element', 5, true) || // use form element wrap if available
            this.el.findParent('.x-form-field-wrap', 5, true);   // else direct field wrap
    },
    
    alignInfoIcon : function() {
	    if (this.el.dom.type=='checkbox' || this.el.dom.type=='radio') {
	    	this.infoIcon.alignTo(this.el, 'tl-tr', [2, -4]);
	    } else {
	    	this.infoIcon.alignTo(this.el, 'tl-tr', [2, 0]);
	    }
        
    }
});


//
//Issue: When spawning dialogs, something was preventing us from being
//       able to specify a form control within that dialog that should
//       receive default focus.
//Soln:  Found a fix in the FAQ that helps with this.
//Reference: http://www.sencha.com/learn/Ext_FAQ_Window
//
Ext.override(Ext.Window, {
	toFront : function(e) {
		if (this.manager.bringToFront(this)) {
			if (e && !e.getTarget().focus) {
				this.focus();
			}
		}
		return this;
	}
});


//
//Issue: SliderField has a bug where it is not firing events
//Soln:  Found a fix in the forums.
//Reference: http://www.sencha.com/forum/showthread.php?96628-sliderField
//
Ext.override(Ext.form.SliderField, {
	initEvents : function(){
		Ext.form.SliderField.superclass.initEvents.call(this);
		this.slider.on('change', this.onChange, this); 
		this.slider.on('changecomplete', this.onChangeComplete, this);
	},
	onChange : function(slider, v){
		this.setValue(v, undefined, true);
		this.fireEvent('change',this);
	},
	onChangeComplete : function(slider, v){
		this.fireEvent('changecomplete',this);
	},
	refresh : function() {
		this.slider.syncThumb();
	}
});

//Issue: DateField has the ability to accept and display dates using the current locale, but then dates
//       are always submitted to the server using a normalized date format.  The TimeField does not
//       do this.
//Soln:  I've overridden the TimeField so that we can specify the submit format and to provide a 
//       method that will return the time using the specified format.
Ext.override(Ext.form.TimeField, {
	submitFormat : 'G:i',
	getSubmitValue : function() {	
		return Ext.util.Format.date(Date.parseDate(this.getValue(),this.format), this.submitFormat);
	}
});

