Ext.QuickTips.init();
// turn on validation errors beside the field globally
Ext.form.Field.prototype.msgTarget = 'side';
/*Ext.MessageBox.buttonText.cancel = 'Anuluj';
Ext.MessageBox.buttonText.no = 'Nie';
Ext.MessageBox.buttonText.yes = 'Tak';
Ext.MessageBox.buttonText.ok = 'OK';
Date.monthNames = ['Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Paźdźiernik', 'Listopad', 'Grudzień'];
*/
Ext.BLANK_IMAGE_URL = '_img/s.gif';
Ext.ns('Calc');
Ext.ns('Calc.calc');
Ext.ns('Calc.elem');

Calc.inputValues = {};
Calc.inputsValid = true;
Calc.expandedGrids = {};

Calc.sliderData = {
    kwota: [10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000, 120000, 140000, 160000, 180000, 200000, 220000, 240000, 260000, 280000, 300000, 320000, 340000, 360000, 380000, 400000, 420000, 440000, 460000, 480000, 500000, 550000, 600000, 650000, 700000, 750000, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, 2000000 ],
    rata: [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500, 3000, 3500, 4000, 4500, 5000],
    okres: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
    rata15: [100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, 320, 340, 360, 380, 400, 420, 440, 460, 480, 500]
};

Calc.calc = {
    init: function(config) {

		if( ! Calc.Path.Root ) {
			Calc.Path.Root = '../kalkulatory/site/';
		}


		Ext.BLANK_IMAGE_URL = Calc.Path.Root + '_img/s.gif';



        //element który będzie maskowany podczas pobierania wyników
        Calc.maskedBody = new Ext.Element(Ext.query('div.col-3')[1]);

		//uruchomienie odpowiedniego formularza
        Calc.calcNo = config.calcId;
        this.calcNo = 'calc_' + config.calcId;
		//alert(calc);
        this.inputPanel = new Calc[this.calcNo].input();

    },
    //////////////////////////////////////////////////////////////////////////////////////////////
    // collectData
    //////////////////////////////////////////////////////////////////////////////////////////////
    // funkcja wołana dla każdego komponentu w sekcji input po kliku na klawisz oblicz
    // jako argument przyjmuje podany komponent - jesli ten ma ustawiony atrybut inputPanel na true
    // wydobywa z niego nazwy/wartości inputów i wrzuca je do tablicy Calc.inputValues
    //////////////////////////////////////////////////////////////////////////////////////////////
    collectData: function(component) {
        var valid;
        if (component.xtype == 'inputPanel') {
            component.getInputs();
            valid = component.validateInputs();
            Calc.inputsValid = Calc.inputsValid && valid;
            var subsection;
            if (component.title != '') subsection = component.title;
            else subsection = 'dane';
            Calc.inputValues[subsection] = ( component.getInputValues() );
        }

    },

    submitInputs: function(evt) {
        evt.stopEvent();
        Calc.inputsValid = true;
        Calc.calc.inputPanel.cascade(Calc.calc.collectData);
        if (Calc.inputsValid) {
            Calc.calc.makeRequest();
        }
    },

    clearInputs: function(evt) {
        evt.stopEvent();
        Ext.Msg.confirm('Potwierdzenie', 'Czy na pewno chcesz wyczyścić wszystkie pola?', function(clicked){
        	if (clicked=='yes')	Calc.calc.inputPanel.cascade(Calc.calc.clearData);
		});

    },

    clearData: function(panel) {
        if (panel.xtype == 'inputPanel') {
            panel.getInputs();
            panel.clearInputs();
        }else if(panel.xtype == 'elem.custSlider'){
			panel.adjustLabels(panel.initValue);
            panel.ownerCt.renderLabels();
            panel.setRealValue(panel.initValue);
		}
    },

    comma2dot: function(value) {
        return value.replace(',', '.');
    },


    scrollToSection: function(id) {
    	//var resultPanel = Ext.getCmp('result');
    	//resultPanel.focus();

  		var el = Ext.getDom(id);
		if(el){
            var body =  Ext.get(document.documentElement || document.body);
            var body2 = Ext.getBody();
            var top = ( Ext.fly(el).getOffsetsTo( body2 )[1] ) + body2.dom.scrollTop;
            body.scrollTo( 'top', top - 5, {duration:2 });
        }
    },

    //////////////////////////////////////////////////////////////////////////////////
    // successFn
    //////////////////////////////////////////////////////////////////////////////////
    // funkcja uruchamiana po poprawnym odbiorze danych z serwera
    // dekoduje odebrane dane, przygotowuje je dla grida oraz tworzy grid
    //////////////////////////////////////////////////////////////////////////////////
    successFn: function(response, options) {
        Calc.maskedBody.unmask();

    //kasujemy ewentualne wyniki z poprzednich obliczeń
        Calc.resultsEx = false;
        Calc.expandedGrids = {};

		//dekodowanie wiadomości z json'a
        var resultText = Ext.util.JSON.decode(response.responseText);
        Calc.results = resultText;

        if (Calc.results.validator){
        	Calc.calc.markInvalid();
            Calc.calc.showErrors('Niektóre z wprowadzonych przez Ciebie danych są błędne. <br /> Popraw je i naciślij "Oblicz" ponownie.');

        }else if ( ! Calc.results || Calc.results.errors ) Calc.calc.showErrors( Calc.results.errors || 'Wystąpił nieoczekiwany błąd');
        else Calc.calc.showResult();

        Calc.calc.scrollToSection( 'calcResult' );
        //Calc.maskedBody.unmask();
    },
    makeRequest: function() {
    	//console.log(Calc.inputValues);
        //wysyłamy ajax'em wprowadzone dane, otrzymane wyniki wrzucamy do gridów
        Ext.Ajax.request({
            url: Calc.Path.Json + '/wykres' + Calc.calcNo,
            method: 'POST',
            waitMsg: 'Waiting...',
            success: this.successFn,
            failure: function(response, options) {
                Calc.calc.showErrors();
                Calc.maskedBody.unmask();
            },
            params: {
                dane: Ext.util.JSON.encode(Calc.inputValues)
            }

        });

        Calc.maskedBody.mask('Proszę czekać, trwa analizowanie wprowadzonych danych...');
        var msgDiv = Ext.query('.ext-el-mask-msg')[0];
        msgDiv = new Ext.Element(msgDiv);
        msgDiv.insertHtml('beforeEnd', '<img src="'+ Calc.Path.Root +'_img/pasek_loader.gif" />');
    },
    markInvalid: function(){
    	var tempInput;
    	for(obj in Calc.results.validator){
    		for(inObj in Calc.results.validator[obj]){

				for(panelEl in Calc.results.validator[obj][inObj]){
					if(panelEl == 'kwotaPozostala') {
						tempInput = Calc.calc.inputPanel.find('baseCls', 'calc-04-loan-wrapper')[0].items.items[inObj].kwotaPozostala;
						tempInput.markInvalid(Calc.results.validator[obj][inObj].kwotaPozostala);
					}else if(panelEl == 'oprocentowanie'){
						tempInput = Calc.calc.inputPanel.find('baseCls', 'calc-04-loan-wrapper')[0].items.items[inObj].oprocentowanie;
						tempInput.markInvalid(Calc.results.validator[obj][inObj].oprocentowanie);
					}else if(panelEl == 'ilMiesiecy'){
						tempInput = Calc.calc.inputPanel.find('baseCls', 'calc-04-loan-wrapper')[0].items.items[inObj].miesiace;
						tempInput.markInvalid(Calc.results.validator[obj][inObj].ilMiesiecy);
					}else if(panelEl == 'miesiecznaSplata'){
						tempInput = Calc.calc.inputPanel.find('baseCls', 'calc-04-loan-wrapper')[0].items.items[inObj].rata;
						tempInput.markInvalid(Calc.results.validator[obj][inObj].miesiecznaSplata);
					}
				}
    			tempInput = Calc.calc.inputPanel.find('name', inObj)[0];
				if(tempInput) tempInput.markInvalid(Calc.results.validator[obj][inObj]);

			}
		}

	},
    showResult: function() {
    	//reset widocznych gridów
		Calc.visibleGrid = null;
		Calc.resultsTog = null;
		Calc.gridState = null;

        var resultPanel = Ext.getCmp('result');
        if (resultPanel) resultPanel.destroy();
        resultPanel = new Calc[ this.calcNo ].result();
    },
    showErrors: function(komunikat) {
        var resultPanel = Ext.getCmp('result');
        if (resultPanel) resultPanel.destroy();
        resultPanel = new Calc.error({ komunikat: komunikat });
    }
};


////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calc.inputPanel
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Klasa abstrakcyjna - reprezentuje podsekcję bloku input. Posiada tytuł podsekcji, panele podrzędne
// oraz mechanizmy walidacji i zbierania danych z podległych inputów
////////////////////////////////////////////////////////////////////////////////////////////////////////////

Ext.ns('Calc.inputPanel');

Calc.inputPanel = Ext.extend(Ext.Panel, {
    border:true,
	collapsible: false,
    //header: true,
    baseCls: 'calc-input-subsection',
    inputGroup: 'grupa',
    title: 'input subsection',
    html: 'input subsection body',
	initComponent: function() {

		Calc.inputPanel.superclass.initComponent.apply(this, arguments);
		this.addEvents ( 'myafterrender' );

	},
	aferRender: function(){
    Calc.inputPanel.superclass.afterRender.call(this);

    this.fireEvent('myafterrender', this);
  },

	getInputs: function(){
		this.numberFields = Ext.query('input[type=text]', this.el.dom);
		this.radios = Ext.query('input[type=radio]', this.el.dom);
		this.hidden = Ext.query('input[type=hidden]', this.el.dom);
		this.checkboxes = Ext.query('input[type=checkbox]', this.el.dom);

		this.validated = Ext.query('input[class*=validated]', this.el.dom);

		var subPanels = this.find('cls', 'multiInput');
		this.repeatingFields = [];
		var tempInputs;
		var hidden;
		if(subPanels[0]){
			for(var i=0; i<subPanels.length; i++){
				tempInputs = Ext.query('input[type=text]', subPanels[i].el.dom);
				hidden = Ext.query('input[type=hidden]', subPanels[i].el.dom);
				if(subPanels[i].xtype == 'calc_04.loanPanel'){
          this.repeatingFields.push({
  					typKredytu: Calc.calc.comma2dot(hidden[0].value),
  					kwotaPozostala: Calc.calc.comma2dot(tempInputs[1].value),
  					oprocentowanie: Calc.calc.comma2dot(tempInputs[2].value),
  					ilMiesiecy:  Calc.calc.comma2dot(tempInputs[3].value),
  					miesiecznaSplata: Calc.calc.comma2dot(tempInputs[4].value)
  				});
        }else if(subPanels[i].xtype == 'calc_06.changePanel'){
          this.repeatingFields.push({
  					miesiac: Calc.calc.comma2dot(tempInputs[0].value),
  					kurs: Calc.calc.comma2dot(tempInputs[1].value)
  				});
        }

			}
		}

	},
	clearInputs: function(){
		var extField;
		for(var i=0; i<this.validated.length; i++){
			extField = Ext.getCmp(this.validated[i].id);
			extField.setRawValue('');
		}
	},
	validateInputs: function(){
		var extField;
		var valid = true;
		var validTemp;
		for(var i=0; i<this.validated.length; i++){
			extField = Ext.getCmp(this.validated[i].id);
			validTemp = extField.validate();
			valid = valid && validTemp;
		}
		return valid;

	},
	getInputValues: function(){
		var record = {};

		if(this.find('xtype', 'calc_06.changePanel')[0]){
			if(this.repeatingFields[0]){
				record = [];
				for(var i=0; i<this.repeatingFields.length; i++){
					record.push(this.repeatingFields[i]);
				}
			}
		}
		else if(this.find('xtype', 'calc_04.loanPanel')[0]){
			if(this.repeatingFields[0]){
				record['kredyty'] = [];
				for(var i=0; i<this.repeatingFields.length; i++){
					record['kredyty'].push(this.repeatingFields[i]);
				}
			}
		}
		else{

			if(this.numberFields[0]){
				for(var i=0; i<this.numberFields.length; i++){
					//nie pobieram pól z 'hidden' w nazwie i takich którym nie przypisano nazwy
					if(this.numberFields[i].name.indexOf('hidden')==-1 && this.numberFields[i].name) {
            record[this.numberFields[i].name] = Calc.calc.comma2dot(this.numberFields[i].value);
          }
				}
			}
			if(this.radios[0]){
				for(var i=0; i<this.radios.length; i++){
					//alert(this.radios[i].getAttribute('checked'));
					if(Ext.isIE){
						if(this.radios[i].getAttribute('checked') ) record[this.radios[i].name] = this.radios[i].value;
					}else {
						if(this.radios[i].getAttribute('checked')!=null ) record[this.radios[i].name] = this.radios[i].value;
					}

				}
			}
			if(this.hidden[0]){
				for(var i=0; i<this.hidden.length; i++){
					record[this.hidden[i].name] = Calc.calc.comma2dot(this.hidden[i].value);
				}
			}
			if(this.checkboxes[0]){
				for(var i=0; i<this.checkboxes.length; i++){
					if (this.checkboxes[i].checked) record[this.checkboxes[i].name] = 'on';
					else record[this.checkboxes[i].name] = 'off';
					//alert(record[this.checkboxes[i].name]);
				}
			}

		}
		return record;
	}

});

Ext.reg('inputPanel', Calc.inputPanel);

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calc.input
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Klasa abstrakcyjna - reprezentuje sekcję wprowadzania danych użytkownika
////////////////////////////////////////////////////////////////////////////////////////////////////////

Ext.ns('Calc.input');

Calc.input = Ext.extend(Ext.form.FormPanel, {
    border:true,
    //url: 'receive.php',
    //header: true,
    waitMsgTarget: true,
	  id: 'calc-form',
    title: 'input section',
    baseCls: 'calc-input',
    renderTo: 'calcInput',

    //html: '<button>wyczyść</button><button>Oblicz</button>',
	initComponent: function() {
		Ext.apply(this, {
			width: 710,
			footer: true,
			plugins: [{
				//Reakcja na click przycisku "Oblicz"
				init: function(component){
					component.on('myafterrender', function(){
					   var obliczButton = Ext.query('input[value=oblicz]', this.footer.dom)[0];
					   obliczButton = new Ext.Element(obliczButton);
					   obliczButton.on('click', Calc.calc.submitInputs);
          });
          component.on('myafterrender', function(){
					   var wyczyscButton = Ext.query('a[class*=wyczysc]', this.footer.dom)[0];
					   wyczyscButton = new Ext.Element(wyczyscButton);
					   wyczyscButton.on('click', Calc.calc.clearInputs);
          });

				}
			},{
			  //dołączenie przycisków wyczysć oblicz
        init: function(component){
          component.on('render', function(){
            var buttonsHtml = ['<ul class="horizontal"><li><a class="tr wyczysc" href="#">Wyczyść</a></li>',
              '<li><input class="submit" type="image" value="oblicz" src="'+ Calc.Path.Root +'_img/btn.calc.oblicz.png" id="inputOblicz"/></li></ul>'].join(' ');
            Ext.DomHelper.append(this.footer.dom, buttonsHtml);
          });
        }
      }]
		});
		Calc.input.superclass.initComponent.apply(this, arguments);

		this.addEvents ( 'myafterrender' );
	},
	afterRender: function(){
		Calc.input.superclass.afterRender.call(this);
		this.fireEvent('myafterrender', this);
	}

});

Ext.reg('input', Calc.input);

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calc.result
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Klasa abstrakcyjna - reprezentuje sekcję wyników obliczeniowych kalkulatora,
////////////////////////////////////////////////////////////////////////////////////////////////////////

Calc.result = Ext.extend(Ext.Panel, {
    border:true,
    title: 'Result section',
    id: 'result',
    renderTo: 'calcResult',
    baseCls: 'calc-result',
    html: '<br />',
	initComponent: function() {
		this.on('expandgrid', function(params){
			this.gridToExpand = params.grid;
			Calc.gridState = 'expand';

			//jeśli nie ma wyników z poprzedniego rozwijania pobierz je, jesli są pomiń pobieranie i użyj ich
			if(!Calc.resultsEx)	{
				//zmiana napisu wyzwalacza na "proszę czekać"
				params.trigger.changeText('Proszę czekać...');
				this.ajxRequest(this.expandGrid);
			}else {
				this.gridToExpand.store.loadData(Calc.resultsEx.grid1);
				Ext.getCmp('expand').changeText('Zwiń tabelę');
			}

		});

		this.on('collapsegrid', function(params){
			Calc.gridState = 'collapse';
			this.gridToExpand.store.loadData(Calc.results.grid1 || []);
			Ext.getCmp('expand').changeText('Pokaż pełne zestawienie');
		});

		this.on('togglegrids', function(params){

		  this.toHide = params.gridToHide;
		  this.toShow = params.gridToShow;
		  //zmiana napisu wyzwalacza na "proszę czekać"
		  params.trigger.changeText('Proszę czekać...');

		  if(!Calc.resultsTog){
			this.ajxRequest(this.loadToggleResult);
		  }else{
		  	this.toHide.hide();
		  	this.toShow.show();
		  }

		});

		Calc.result.superclass.initComponent.apply(this, arguments);
		this.addEvents ( 'afterrender' );
		this.addEvents ( 'expandgrid' );
		this.addEvents ( 'collapsegrid' );
		this.addEvents ( 'togglegrids' );
	},

	//////////////////////////////////////////////////////////////////////////////////////////////
	afterRender: function(){
		Calc.result.superclass.afterRender.call(this);

		this.fireEvent('afterrender', this);
	},

	expandGrid: function(response, options){
		var resultText = Ext.util.JSON.decode(response.responseText);
  		Calc.resultsEx = resultText;
  		this.gridToExpand.store.loadData(Calc.resultsEx.grid1);
  		Ext.getCmp('expand').changeText('Zwiń tabelę');
	},

  loadToggleResult: function(response, options){
    var resultText = Ext.util.JSON.decode(response.responseText);
    Calc.resultsTog = resultText;

    this.toShow.store.loadData(Calc.resultsTog.grid1);
    this.toHide.hide();
	this.toShow.show();

  },

	ajxRequest: function(success){
    Ext.Ajax.request({
			url: Calc.Path.Json+'/tabela'+Calc.calcNo,
			method: 'POST',
			waitMsg: 'Waiting...',
			success: success,
			failure: function(response, options){
				Calc.calc.showErrors();
			},
			params: {
				dane: Ext.util.JSON.encode(Calc.inputValues)
			},
			scope: this

		}); //end Ext.Ajax.request()
  }

});

Ext.reg('result', Calc.result);

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calc.error
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Klasa wyswietla komunikat o błędzie w sekcji wyników kalkulatora
////////////////////////////////////////////////////////////////////////////////////////////////////////
Ext.ns('Calc.error');

Calc.error = Ext.extend(Calc.result, {
	title: 'Błąd',

    komunikat: 'Niestety wystąpił błąd poczas pobierania wyników z serwera.',

    initComponent: function( ) {

        if( ! this.komunikat ){
            this.komunikat = ['Niestety wystąpił błąd poczas pobierania wyników z serwera. Administrator systemu został już o tym powiadomiony. <br />',
	              'Spróbuj ponownie za jakis czas.' ].join(' ');
        }

        Ext.apply(this, {
		  items: [{
	        xtype: 'panel',
	        cls: 'resultPanel',
	        border: false,
	        html: this.komunikat
	      }]
		});
		Calc.error.superclass.initComponent.apply(this, arguments);
		this.addEvents ( 'afterrender' );
	},
	afterRender: function(){
		Calc.error.superclass.afterRender.call(this);
		this.fireEvent('afterrender', this);
	}
});

Ext.reg('calc.error', Calc.error);

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calc.elem.slider
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Panel zawierający suwak i input typu text
////////////////////////////////////////////////////////////////////////////////////////////////////////
Calc.elem.slider = Ext.extend(Ext.Panel, {
	border: true,
	collapsible: false,
	title: 'Suwak',
	//yearsToMonths: true,
	headerAsText: true,
	initComponent: function() {
		Ext.apply(this, {
			//header: true,
			html: this.insertInput(),
			baseCls: 'calc-slider',
			items: [{
				labels: this.labels,
				initValue: this.initValue,

				width: 500,
				//increment: 10,
				xtype: 'elem.custSlider'
			}],
			plugins: [{
          init: function(component){
            //wyświetlenie labeli
            component.on('myafterrender', function(){

              //input typu text
              this.sliderInput = Ext.query('input[class=slider-numberfield]', this.el.dom)[0];
              this.sliderInputEl = new Ext.Element(this.sliderInput);

              this.sliderInputEl.on('keyup', function(evt, input){
                var value = parseInt(input.value);
                if( !isNaN(value) ) input.value = value;

              });

              //akcja odpalana po wyjsciu z inputa
              this.sliderInputEl.on('blur', function(evt, input){
                var value = parseInt(input.value);
                var valueForSlider;
                var slider = component.find('xtype', 'elem.custSlider')[0];

                if( isNaN(value) ){
                  if(component.yearsToMonths) input.value = slider.getRealValue()*12;
                  else input.value = slider.getRealValue();
                  return;
                }
                if(component.yearsToMonths) value = value/12;
                
                //szukanie najblizszej wartości wśród labeli
                var index = slider.labels.indexOf(value);
                if(index==-1) {
                	var lastDiff;
                	var diff;
                	var ind;
                	for(var i=0; i<slider.labels.length; i++){
						diff = Math.abs( value - slider.labels[i] );
						if(i==0) lastDiff = diff + 1;
						else if(i==slider.labels.length-1 && !ind)ind=i+1;
						if(diff > lastDiff && !ind) ind=i;
						else lastDiff = diff;
					}
					valueForSlider = slider.labels[ind-1];
				}else valueForSlider = value;
				
                if(component.yearsToMonths) value = Math.round(value);
                var min = component.labels[0];
                var max = component.labels[component.labels.length-1];
                var mmin = slider.labelArray[0];
                var mmax = slider.labelArray[slider.labelArray.length-1];

				slider.inputChanged = true;
                if(value>=mmin && value<+mmax){
                  slider.setRealValue(valueForSlider);
                }
                else if(value>=min && value<=max) {
                  slider.adjustLabels(valueForSlider);
                  component.renderLabels();
                  slider.setRealValue(valueForSlider);
                }
                else if(value<min) {
                  slider.adjustLabels(min);
                  component.renderLabels();
                  slider.setRealValue(min);
                  slider.setInputValue();
                }
                else if(value>max){
                  slider.adjustLabels(max);
                  component.renderLabels();
                  slider.setRealValue(max);
                  slider.setInputValue();
                }else{
				  slider.inputChanged = false
				}

                
              });

              //dodanie labeli
              Ext.DomHelper.insertAfter(this.sliderInput, '<div class="slider-labels">'+this.getComponent(0).getLabels().join(' ')+'</div>');

            });
          }
		    }]
		});
        Calc.elem.slider.superclass.initComponent.apply(this, arguments);
        //definicja nowego zdarzenia - myafterrender
        this.addEvents ( 'myafterrender' );
    }, // eo function initComponent

 	onRender:function() {
        Calc.elem.slider.superclass.onRender.apply(this, arguments);
    }, // eo function onRender

	afterRender: function(){
		Calc.elem.slider.superclass.afterRender.call(this);
		this.fireEvent('myafterrender', this);
	},
	renderLabels: function(){
	    var labels = Ext.query('div[class=slider-labels]', this.el.dom)[0];
	    Ext.DomHelper.overwrite(labels, ' '+this.getComponent(0).getLabels().join(' ')+' ');
	},
	insertInput: function(){
  	var html = '<input type="text" class="slider-numberfield" name="'+this.valueName+'"/>';
  	var label = 'zł';
  	if(this.yearsToMonths) label = 'm-cy';
  	return html+label ;
	}

});

Ext.reg('elem.slider', Calc.elem.slider);


////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calc.elem.custSlider
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Suwak z przyciskami less i more
////////////////////////////////////////////////////////////////////////////////////////////////////////
Calc.elem.custSlider = Ext.extend(Ext.Slider, {

  clickRange: [10,30],
	border: true,
	collapsible: false,
	title: 'Suwak',
	headerAsText: true,
	initComponent: function() {
		Ext.apply(this, {
			increment: 10,
			//baseCls: 'cust-slider',
			plugins: [{
				init: function(component){
					component.on('myafterrender', function(){

						//szukanie najblizszej wartości wśród labeli
		                var index = component.labels.indexOf(this.initValue);
		                var value = this.initValue;
		                if(index==-1) {
		                	var value;
		                	var lastDiff;
		                	var diff;
		                	var ind;
		                	for(var i=0; i<component.labels.length; i++){
								diff = Math.abs( value - component.labels[i] );
								if(i==0) lastDiff = diff + 1;
								else if(i==component.labels.length-1 && !ind)ind=i+1;
								if(diff > lastDiff && !ind) ind=i;
								else lastDiff = diff;
							}
							value = component.labels[ind-1];
							
						}
						
						//wartosc suwaka
						var valIndex = this.labels.indexOf(value);
						if(valIndex+5 > this.labels.length) {
			                this.setValue(100, false);
			            }else if(valIndex-5 < 0){
			                this.setValue(0, false);
			            }else{
			                this.setValue(50, false);
			            }
			            this.adjustLabels(value);
			            this.ownerCt.renderLabels();

					  //wartosc inputa
					  this.setInputValue();

					//przyciski do zmiany zakresu labeli
					var lessButton = Ext.DomHelper.insertBefore(this.el.dom, '<div class="slide-less"></div>', true);
					var moreButton = Ext.DomHelper.insertAfter(this.el.dom, '<div class="slide-more"></div>', true);

		            component.lessRepeater = new Ext.util.ClickRepeater(lessButton, {
		                  interval : 70,
		                  delay: 400,
		                  handler: function(){
							if(component.startLabel != 0){
				                component.startLabel = component.startLabel-1;
				                component.labelArray = component.labels.slice(component.startLabel, component.startLabel+11);
				                component.ownerCt.renderLabels();
				                component.fireEvent('rangechanged');
						    }else{
						    	var val = component.getValue();
						    	if(val>0) component.setValue(val-10, false);
							}
						  }
		            });

	              component.moreRepeater = new Ext.util.ClickRepeater(moreButton, {
	                  interval : 70,
	                  delay: 400,
	                  handler: function(){
						if(component.startLabel + 11 != component.labels.length){
			                component.startLabel = component.startLabel+1;
			                component.labelArray = component.labels.slice(component.startLabel, component.startLabel+11);
			                component.ownerCt.renderLabels();
			                component.fireEvent('rangechanged');
					    }else{
						    	var val = component.getValue();
						    	if(val<100) component.setValue(val+10, false);
						}
					  }
	              });
	              
	              

		}); // end component.on('myafterrender'

		component.on('change', function(evt){
		  // ustawia wartość inputa gdy zmiana wartości slidera pochodzi z klawiatury, myszy lub kliku
		  // strzałek do zmiany zakresu. this.inputChanged jest ustawiane gdy zmiana pochodzi z inputa bocznego
		  if (!this.inputChanged || evt.dragging) this.setInputValue();
		  this.inputChanged = false;
		});
		component.on('rangechanged', function(){
			this.setInputValue();
		});
		component.on('dragstart', function(){
			this.dragging = true;
			//console.log('start');
		});
		component.on('dragend', function(){
			this.dragging = false;
			this.once = false;
		});
		component.on('drag', function(slider,evt){
			//kierunek przewijania skali suwaka
			component.scrollDirection = 'no';
			if(evt.getPageX()>component.getBox().x+component.getBox().width) component.scrollDirection = 'more';
			else if(component.getBox().x>evt.getPageX()) component.scrollDirection = 'less';
			
			if(component.scrollDirection!='no' && !component.once){
				component.once = true; 
				component.dragScroll();
			}
			
		});
		}
	}]//end plugins

		}); // end Ext.apply(this
        Calc.elem.custSlider.superclass.initComponent.apply(this, arguments);

    		// inicjacja labeli suwaka
        this.adjustLabels(this.initValue);

        //definicja nowego zdarzenia - myafterrender
        this.addEvents ( 'myafterrender' );
        this.addEvents ( 'rangechanged' );

    }, // eo function initComponent

 	onRender:function() {
        Calc.elem.custSlider.superclass.onRender.apply(this, arguments);
    }, // eo function onRender

	afterRender: function(){
		Calc.elem.custSlider.superclass.afterRender.call(this);
		this.fireEvent('myafterrender', this);
	},
	getLabels: function(){
		var labels = [];
		for(var i=0; i<11; i++){
			if(i==10) labels.push('<div class="slider-label last">');
			else labels.push('<div class="slider-label">');
			//this.formatLabel(this.labelArray[i].toString());
			labels.push( this.formatLabel(this.labelArray[i].toString()) );
			labels.push('</div>');
    	}
    	if(this.ownerCt.yearsToMonths) labels.push('<div>lata</div>');
    	else labels.push('<div>zł</div>');
	    labels.join(' ');
	    return labels;
	},
	getNormalValue: function(){
		var value = this.getValue()/10;
		return this.labels[this.startLabel+value];

	},
	setInputValue: function(){
    	var value = this.getNormalValue();
	    if(this.ownerCt.yearsToMonths) value = value*12;
		   this.ownerCt.sliderInput.value = value;
    },
  adjustLabels: function(sliderValue){
    var valIndex = this.labels.indexOf(sliderValue);
    if(valIndex == -1) this.startLabel = 0;
    else if(valIndex+5 > this.labels.length) this.startLabel = valIndex - 10;
    else if(valIndex-5 < 0) this.startLabel = valIndex;
    else this.startLabel = valIndex-5;

    this.labelArray = this.labels.slice(this.startLabel, this.startLabel+11);
  },
  setRealValue: function(value){
    var index = this.labelArray.indexOf(value);
    this.setValue(index*10);
  },
  getRealValue: function(){
    var value = this.getValue();
    value = this.labelArray[value/10];
    return value;
  },
  formatLabel: function(label){
  	var formatLabel;
  	var newString = label;
  	var endIndex = (label.lastIndexOf(' ')==-1) ? label.length-1 : label.indexOf(' ');
  	var spaceIndex = endIndex - 2;

  	while(spaceIndex>0){
	  	newString = label.substring(0,spaceIndex)+' '+newString.substring(spaceIndex);
	  	spaceIndex = spaceIndex -3;
	}
	
  	formatLabel = newString;
	return formatLabel;
  },
  //przewijanie zakresu suwaka myszą
  dragScroll: function(){
  	var maxVal = this.labels[this.labels.length-1];
  	var minVal = this.labels[0];
  	
	if(this.dragging){
		if(this.scrollDirection=='more'){
	  	  	this.moreRepeater.fireEvent('click');
		} else if(this.scrollDirection=='less'){
		  	this.lessRepeater.fireEvent('click');
		}
		var that = this;
	    setTimeout(function(){
	  		that.dragScroll();
	  	}, 70);
	}
  }

});

Ext.reg('elem.custSlider', Calc.elem.custSlider);


////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calc.elem.numberfield
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pole input numeryczne
////////////////////////////////////////////////////////////////////////////////////////////////////////
Calc.elem.numberfield = Ext.extend(Ext.form.NumberField, {
	width: 43,
    cls: 'calc-numberfield validated',
    labelSeparator: '',
    decimalSeparator: ',',
    invalidText: 'niepoprawny',
    blankText: 'Pole wymagane',
    minValue: 0,
    minText: 'Wartość musi być większa od zera' ,
    allowBlank: false,

	getErrorCt : 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
      	  this.el.findParent('.input-wrapper', 5, true);
  	}
});



Ext.reg('elem.numberfield', Calc.elem.numberfield);

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calc.elem.combo
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pole input numeryczne
////////////////////////////////////////////////////////////////////////////////////////////////////////
Calc.elem.combo = Ext.extend(Ext.form.ComboBox, {
	width: 100,
	initComponent: function() {
		Ext.apply(this, {
			allowBlank: false,
        	cls: 'validated',
        	invalidClass: 'calc-invalid',
        	//fieldLabel: 'Wybierz walutę',
        	labelSeparator: '',
    		//hiddenName: 'waluta',
    		blankText: 'Pole wymagane',
    		msgTarget: 'side',
    		triggerAction: 'all',
    		mode: 'local',
    		editable: false,
    		forceSelection: true
		});
        Calc.elem.combo.superclass.initComponent.apply(this, arguments);
        //definicja nowego zdarzenia - myafterrender
        this.addEvents ( 'myafterrender' );
    }, // eo function initComponent

 	onRender:function() {
        Calc.elem.combo.superclass.onRender.apply(this, arguments);
    }, // eo function onRender

	afterRender: function(){
		Calc.elem.combo.superclass.afterRender.call(this);
		this.fireEvent('myafterrender', this);
	}

});

Ext.reg('elem.combo', Calc.elem.combo);

Calc.expand = Ext.extend( Ext.form.Label, {
    id: 'expand',
    border: false,
    title: '',
    html: '<div class="txt-more"><a href="#" class="expandTable">Pokaż pełne zestawienie</a></div><br/>',
    plugins: [{
      init: function(component){
        var cmp = component;

        cmp.on('afterrender', function(){
          var expander = Ext.query('a.expandTable')[0];
          this.expander = new Ext.Element(expander);

          this.expander.on('click', function(evt){
            evt.stopEvent();
            //jeli nie ustawiono paramertu expandCmp ani toggleCmp wyjdź
            if(!cmp.expandCmp && !cmp.toggleCmp) return;

            //ustawiono parametr expandCmp - zmień dane tabeli
            else if(cmp.expandCmp){
              //jesli podana tabela nie jest rozwinięta rozwiń ją, jak nie zwiń ją
              if (!Calc.expandedGrids[component.expandCmp]){
              	Calc.expandedGrids[component.expandCmp] = true;
              	component.ownerCt.fireEvent('expandgrid', {grid: Ext.getCmp(component.expandCmp), trigger: component});
        			}else {
        				Calc.expandedGrids[component.expandCmp] = false;
        				component.ownerCt.fireEvent('collapsegrid', {grid: Ext.getCmp(component.expandCmp), trigger: component});

        			}
        		//ustawiono parametr toggleCmp - zamień widoczność dwóch tabel
            }else if(cmp.toggleCmp){
              var hidden;
			  var bExpand = true;
              if( !Calc.visibleGrid || Calc.visibleGrid==cmp.toggleCmp.grid1 ) {
                Calc.visibleGrid = cmp.toggleCmp.grid2;
                hidden = cmp.toggleCmp.grid1;
				bExpand = false;
              }
              else{
                Calc.visibleGrid = cmp.toggleCmp.grid1;
                hidden = cmp.toggleCmp.grid2;
              }
              var params = {gridToShow: Ext.getCmp(Calc.visibleGrid), gridToHide: Ext.getCmp(hidden), trigger: cmp, bExp: bExpand};
              component.ownerCt.fireEvent('togglegrids', params);
            }




          });// end this.expander.on('click', function(evt){
        });// end cmp.on('afterrender', function(){
      }
    }],
	initComponent: function() {
		Calc.expand.superclass.initComponent.apply(this, arguments);
		this.addEvents ( 'afterrender' );
	},
	afterRender: function(){
		Calc.expand.superclass.afterRender.call(this);

		this.fireEvent('afterrender', this);
	},
	changeText: function(text){
		Ext.DomHelper.overwrite( this.expander, text);
	}

});

Ext.reg('elem.expand', Calc.expand);


// KOrekcja błędu Ext2.2 - błędne wstawianie forHtml to html source.
// @see http://extjs.com/forum/showthread.php?p=206557
// do usunięcia wraz z aktualizacją ext'a
Ext.override(Ext.form.Label, {
    onRender : function(ct, position){
        if(!this.el){
            this.el = document.createElement('label');
            this.el.id = this.getId();
            this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
            if(this.forId){
                this.el.setAttribute(Ext.isIE? 'htmlFor' : 'for', this.forId);
            }
        }
        Ext.form.Label.superclass.onRender.call(this, ct, position);
    }
});
////fix 2
//http://extjs.com/forum/showthread.php?t=44603
Ext.override(Ext.form.Checkbox, {
	onRender: function(ct, position){
		Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
		if(this.inputValue !== undefined){
			this.el.dom.value = this.inputValue;
		}
		//this.el.addClass('x-hidden');
		this.innerWrap = this.el.wrap({
			//tabIndex: this.tabIndex,
			cls: this.baseCls+'-wrap-inner'
		});
		this.wrap = this.innerWrap.wrap({cls: this.baseCls+'-wrap'});
		if(this.boxLabel){
			this.labelEl = this.innerWrap.createChild({
				tag: 'label',
				htmlFor: this.el.id,
				cls: 'x-form-cb-label',
				html: this.boxLabel
			});
		}
		this.imageEl = this.innerWrap.createChild({
			tag: 'img',
			src: Ext.BLANK_IMAGE_URL,
			cls: this.baseCls
		}, this.el);
		if(this.checked){
			this.setValue(true);
		}else{
			this.checked = this.el.dom.checked;
		}
		this.originalValue = this.checked;
	},
	afterRender: function(){
		Ext.form.Checkbox.superclass.afterRender.call(this);
		//this.wrap[this.checked ? 'addClass' : 'removeClass'](this.checkedCls);
		this.imageEl[this.checked ? 'addClass' : 'removeClass'](this.checkedCls);
	},
	initCheckEvents: function(){
		//this.innerWrap.removeAllListeners();
		this.innerWrap.addClassOnOver(this.overCls);
		this.innerWrap.addClassOnClick(this.mouseDownCls);
		//this.innerWrap.on('click', this.onClick, this);
		this.el.on('click', this.onClick, this);
		this.imageEl.on('click', this.onClick, this);
		//this.innerWrap.on('keyup', this.onKeyUp, this);
	},
	onFocus: function(e) {
		Ext.form.Checkbox.superclass.onFocus.call(this, e);
		//this.el.addClass(this.focusCls);
		this.innerWrap.addClass(this.focusCls);
	},
	onBlur: function(e) {
		Ext.form.Checkbox.superclass.onBlur.call(this, e);
		//this.el.removeClass(this.focusCls);
		this.innerWrap.removeClass(this.focusCls);
	},
	onClick: function(e){
		if (Ext.isSafari) {
			this.el.focus();
		}
		if (!this.disabled && !this.readOnly) {
			this.toggleValue();
		}
		//e.stopEvent();
	},
	onEnable: Ext.form.Checkbox.superclass.onEnable,
	onDisable: Ext.form.Checkbox.superclass.onDisable,
	onKeyUp: undefined,
	setValue: function(v) {
		var checked = this.checked;
		this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
		if(this.rendered){
			this.el.dom.checked = this.checked;
			this.el.dom.defaultChecked = this.checked;
			//this.wrap[this.checked ? 'addClass' : 'removeClass'](this.checkedCls);
			this.imageEl[this.checked ? 'addClass' : 'removeClass'](this.checkedCls);
		}
		if(checked != this.checked){
			this.fireEvent("check", this, this.checked);
			if(this.handler){
				this.handler.call(this.scope || this, this, this.checked);
			}
		}
	}
});
Ext.override(Ext.form.Radio, {
	checkedCls: 'x-form-radio-checked'
});


Ext.ns('Calc.Labels');

Calc.Labels.newLabel  = function( text, decimalPrecision, maxValue ) {
 //   var text = '%';

    this.text = text;
    this.decimalPrecision = decimalPrecision;
    this.maxValue = maxValue;

    this.init = function ( C ){
        if( this.decimalPrecision ){
             C.decimalPrecision = this.decimalPrecision;
        }
        if( this.maxValue ){
             C.maxValue = this.maxValue;
             C.maxText = 'Wartość tego pola nie może przekroczyć {0}' ;
        }
        C.on( 'render', function ( Input ){
             var pos = Input.el.findParent('.x-form-element', 5, true) || // use form element wrap if available
               Input.el.findParent('.x-form-field-wrap', 5, true);   // else direct field wrap

             pos.createChild({cls:'x-form-label-right', tag:'span', html: this.text, style: 'padding-left: 3px;' });
        }, this );
    }
};

Calc.Labels.proc = new Calc.Labels.newLabel( '%', 2, 100 );
Calc.Labels.zl   = new Calc.Labels.newLabel( 'zł' );
Calc.Labels.msc  = new Calc.Labels.newLabel( 'm-cy' );


Ext.apply(Ext.form.VTypes, {
    /**
     * @param val text
     * @param Ext.form.Field
     */
    xorTest : function(val, field) {

        if ( ! field.xorField ) {
            field.allowBlank=false;
            return ( val != '' );
        }

        var xor = Ext.getCmp( field.xorField );

        xor.vtype = 'xorTest';
        xor.xorField = field.getId();

            field.on('blur', function(){

                if( field.getValue() || field.getValue()=='0' )  {
                    xor.setValue( '' );
                }

                if( ! field.getValue() && ! xor.getValue() && field.getValue()!='0' && xor.getValue()!='0' ){
                    xor.markInvalid( Ext.form.VTypes.xorTestText );
                    xor.allowBlank = false;
                }else{
                    xor.allowBlank = true;
                    xor.clearInvalid();
                }
            });

        return true;
    },
    xorTestText : 'Wypełnij poprawnie przynajmniej jedno z tych pól'
});


/**
 * Copyright (c) 2008, Steven Chim
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
  * Ext.ux.form.Spinner Class
	*
	* @author  Steven Chim
	* @version Spinner.js 2008-05-08 v0.3
  *
  * @class Ext.ux.form.Spinner
  * @extends Ext.form.TriggerField
  */

Ext.namespace("Ext.ux.form");

Ext.ux.form.Spinner = function(config){
	Ext.ux.form.Spinner.superclass.constructor.call(this, config);
	this.addEvents({
		'spin' : true,
		'spinup' : true,
		'spindown' : true
	});
}

Ext.extend(Ext.ux.form.Spinner, Ext.form.TriggerField, {
	triggerClass : 'x-form-spinner-trigger',
	splitterClass : 'x-form-spinner-splitter',

	//////

	alternateKey : Ext.EventObject.shiftKey,
	strategy : undefined,

	//private
	onRender : function(ct, position){
		Ext.ux.form.Spinner.superclass.onRender.call(this, ct, position);

		this.splitter = this.wrap.createChild({tag:'div', cls:this.splitterClass, style:'width:13px; height:2px;'});
		this.splitter.show().setRight( (Ext.isIE) ? 1 : 2 );
		this.splitter.show().setTop(10);

		this.proxy = this.trigger.createProxy('', this.splitter, true);
		this.proxy.addClass("x-form-spinner-proxy");
		this.proxy.setStyle('left','0px');
		this.proxy.setSize(14, 1);
		this.proxy.hide();
		this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", {dragElId: this.proxy.id});


		this.initSpinner();
	},

	//private
	initTrigger : function(){
		this.trigger.addClassOnOver('x-form-trigger-over');
		this.trigger.addClassOnClick('x-form-trigger-click');
	},

	//private
	initSpinner : function(){
		this.keyNav = new Ext.KeyNav(this.el, {
			"up" : function(e){
				e.preventDefault();
				this.onSpinUp();
			},

			"down" : function(e){
				e.preventDefault();
				this.onSpinDown();
			},

			"pageUp" : function(e){
				e.preventDefault();
				this.onSpinUpAlternate();
			},

			"pageDown" : function(e){
				e.preventDefault();
				this.onSpinDownAlternate();
			},

			scope : this
		});

		//this.trigger.un("click", this.onTriggerClick);
		this.repeater = new Ext.util.ClickRepeater(this.trigger);
		this.repeater.on("click", this.onTriggerClick, this, {preventDefault:true});
		this.trigger.on("mouseover", this.onMouseOver, this, {preventDefault:true});
		this.trigger.on("mouseout",  this.onMouseOut,  this, {preventDefault:true});
		this.trigger.on("mousemove", this.onMouseMove, this, {preventDefault:true});
		this.trigger.on("mousedown", this.onMouseDown, this, {preventDefault:true});
		this.trigger.on("mouseup",   this.onMouseUp,   this, {preventDefault:true});
		this.wrap.on("mousewheel",   this.handleMouseWheel, this);

		this.dd.setXConstraint(0, 0, 10)
		this.dd.setYConstraint(1500, 1500, 10);
		this.dd.endDrag = this.endDrag.createDelegate(this);
		this.dd.startDrag = this.startDrag.createDelegate(this);
		this.dd.onDrag = this.onDrag.createDelegate(this);

        /*
        jsakalos suggestion
        http://extjs.com/forum/showthread.php?p=121850#post121850 */
        if('object' == typeof this.strategy && this.strategy.xtype) {
            switch(this.strategy.xtype) {
                case 'number':
                    this.strategy = new Ext.ux.form.Spinner.NumberStrategy(this.strategy);
	                break;

                case 'date':
                    this.strategy = new Ext.ux.form.Spinner.DateStrategy(this.strategy);
	                break;

                case 'time':
                    this.strategy = new Ext.ux.form.Spinner.TimeStrategy(this.strategy);
                	break;

                default:
                    delete(this.strategy);
                	break;
            }
            delete(this.strategy.xtype);
        }

		if(this.strategy == undefined){
			this.strategy = new Ext.ux.form.Spinner.NumberStrategy();
		}
	},

	//private
	onMouseOver : function(){
		if(this.disabled){
			return;
		}
		var middle = this.getMiddle();
		this.__tmphcls = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown';
		this.trigger.addClass(this.__tmphcls);
	},

	//private
	onMouseOut : function(){
		this.trigger.removeClass(this.__tmphcls);
	},

	//private
	onMouseMove : function(){
		if(this.disabled){
			return;
		}
		var middle = this.getMiddle();
		if( ((Ext.EventObject.getPageY() > middle) && this.__tmphcls == "x-form-spinner-overup") ||
			((Ext.EventObject.getPageY() < middle) && this.__tmphcls == "x-form-spinner-overdown")){
		}
	},

	//private
	onMouseDown : function(){
		if(this.disabled){
			return;
		}
		var middle = this.getMiddle();
		this.__tmpccls = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown';
		this.trigger.addClass(this.__tmpccls);
	},

	//private
	onMouseUp : function(){
		this.trigger.removeClass(this.__tmpccls);
	},

	//private
	onTriggerClick : function(){
		if(this.disabled || this.getEl().dom.readOnly){
			return;
		}
		var middle = this.getMiddle();
		var ud = (Ext.EventObject.getPageY() < middle) ? 'Up' : 'Down';
		this['onSpin'+ud]();
	},

	//private
	getMiddle : function(){
		var t = this.trigger.getTop();
		var h = this.trigger.getHeight();
		var middle = t + (h/2);
		return middle;
	},

	handleMouseWheel : function(e){
		if(this.disabled || this.getEl().dom.readOnly){
			Ext.EventObject.preventDefault();	//prevent scrolling when disabled/readonly
			return;
		}
		var delta = e.getWheelDelta();
		if(delta > 0){
			this.onSpinUp();
			e.stopEvent();
		} else if(delta < 0){
			this.onSpinDown();
			e.stopEvent();
		}
	},

	//private
	startDrag : function(){
		this.proxy.show();
		this._previousY = Ext.fly(this.dd.getDragEl()).getTop();
	},

	//private
	endDrag : function(){
		this.proxy.hide();
	},

	//private
	onDrag : function(){
		if(this.disabled){
			return;
		}
		var y = Ext.fly(this.dd.getDragEl()).getTop();
		var ud = '';

		if(this._previousY > y){ud = 'Up';}         //up
		if(this._previousY < y){ud = 'Down';}       //down

		if(ud != ''){
			this['onSpin'+ud]();
		}

		this._previousY = y;
	},

	//private
	onSpinUp : function(){
		if(Ext.EventObject.shiftKey == true){
			this.onSpinUpAlternate();
			return;
		}else{
			this.strategy.onSpinUp(this);
		}
		this.fireEvent("spin", this);
		this.fireEvent("spinup", this);
	},

	//private
	onSpinDown : function(){
		if(Ext.EventObject.shiftKey == true){
			this.onSpinDownAlternate();
			return;
		}else{
			this.strategy.onSpinDown(this);
		}
		this.fireEvent("spin", this);
		this.fireEvent("spindown", this);
	},

	//private
	onSpinUpAlternate : function(){
		this.strategy.onSpinUpAlternate(this);
		this.fireEvent("spin", this);
		this.fireEvent("spinup", this);
	},

	//private
	onSpinDownAlternate : function(){
		this.strategy.onSpinDownAlternate(this);
		this.fireEvent("spin", this);
		this.fireEvent("spindown", this);
	}

});

Ext.reg('uxspinner', Ext.ux.form.Spinner);

/**
 * Copyright (c) 2008, Steven Chim
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/***
 * Abstract Strategy
 */
Ext.ux.form.Spinner.Strategy = function(config){
	Ext.apply(this, config);
};

Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
	defaultValue : 0,
	minValue : undefined,
	minValue : undefined,
	maxValue : undefined,
	incrementValue : 1,
	alternateIncrementValue : 5,

	onSpinUp : function(field){
		this.spin(field, false, false);
	},

	onSpinDown : function(field){
		this.spin(field, true, false);
	},

	onSpinUpAlternate : function(field){
		this.spin(field, false, true);
	},

	onSpinDownAlternate : function(field){
		this.spin(field, true, true);
	},

	spin : function(field, down, alternate){
		//extend
	},

	fixBoundries : function(value){
		return value;
		//overwrite
	}

});

/***
 * Concrete Strategy: Numbers
 */
Ext.ux.form.Spinner.NumberStrategy = function(config){
	Ext.ux.form.Spinner.NumberStrategy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.ux.form.Spinner.NumberStrategy, Ext.ux.form.Spinner.Strategy, {

    allowDecimals : true,
    decimalPrecision : 2,

	spin : function(field, down, alternate){
		Ext.ux.form.Spinner.NumberStrategy.superclass.spin.call(this, field, down, alternate);

		var v = parseFloat(field.getValue());
		var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;

		(down == true) ? v -= incr : v += incr ;
		v = (isNaN(v)) ? this.defaultValue : v;
		v = this.fixBoundries(v);
		field.setRawValue(v);
	},

	fixBoundries : function(value){
		var v = value;

		if(this.minValue != undefined && v < this.minValue){
			v = this.minValue;
		}
		if(this.maxValue != undefined && v > this.maxValue){
			v = this.maxValue;
		}

		return this.fixPrecision(v);
	},

    // private
    fixPrecision : function(value){
        var nan = isNaN(value);
        if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
            return nan ? '' : value;
        }
        return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
    }
});


/***
 * Concrete Strategy: Date
 */
Ext.ux.form.Spinner.DateStrategy = function(config){
	Ext.ux.form.Spinner.DateStrategy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.ux.form.Spinner.DateStrategy, Ext.ux.form.Spinner.Strategy, {
	defaultValue : new Date(),
	format : "Y-m-d",
	incrementValue : 1,
	incrementConstant : Date.DAY,
	alternateIncrementValue : 1,
	alternateIncrementConstant : Date.MONTH,

	spin : function(field, down, alternate){
		Ext.ux.form.Spinner.DateStrategy.superclass.spin.call(this);

		var v = field.getRawValue();

		v = Date.parseDate(v, this.format);
		var dir = (down == true) ? -1 : 1 ;
		var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
		var dtconst = (alternate == true) ? this.alternateIncrementConstant : this.incrementConstant;

		if(typeof this.defaultValue == 'string'){
			this.defaultValue = Date.parseDate(this.defaultValue, this.format);
		}

		v = (v) ? v.add(dtconst, dir*incr) : this.defaultValue;

		v = this.fixBoundries(v);
		field.setRawValue(Ext.util.Format.date(v,this.format));
	},

	//private
	fixBoundries : function(date){
		var dt = date;
		var min = (typeof this.minValue == 'string') ? Date.parseDate(this.minValue, this.format) : this.minValue ;
		var max = (typeof this.maxValue == 'string') ? Date.parseDate(this.maxValue, this.format) : this.maxValue ;

		if(this.minValue != undefined && dt < min){
			dt = min;
		}
		if(this.maxValue != undefined && dt > max){
			dt = max;
		}

		return dt;
	}

});


/***
 * Concrete Strategy: Time
 */
Ext.ux.form.Spinner.TimeStrategy = function(config){
	Ext.ux.form.Spinner.TimeStrategy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.ux.form.Spinner.TimeStrategy, Ext.ux.form.Spinner.DateStrategy, {
	format : "H:i",
	incrementValue : 1,
	incrementConstant : Date.MINUTE,
	alternateIncrementValue : 1,
	alternateIncrementConstant : Date.HOUR
});


////////////////////////////////////////////////////////////////////////////////////////////////////////
// Calc.flashContent
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Klasa tworzy panel dla flashowego wykresu
////////////////////////////////////////////////////////////////////////////////////////////////////////

Calc.flashContent = Ext.extend(Ext.Panel, {
    border:false,
    title: 'flashPanel',
    header: false,
    id: 'flashPanel',
    html: ['<div id="wrapperFlash"></div>'
      ].join(' '),
    plugins: [{
          init: function(panel){
            panel.on('afterrender', function(){

			 //console.log();
             var charts ='';
             if( Ext.isArray( Calc.results.xml ) ){
                 for( var iChart=0 ; iChart <  Calc.results.xml.length -1; iChart ++ ){
                     charts +=  Calc.Path.Xml + Calc.results.xml[ iChart ] +';';
                 }
                 charts += Calc.Path.Xml +Calc.results.xml[ iChart ];    // ostatni dodawany jest w ten sposób. tak by nie pojawiał się nadmiarowy średnik
             }else{
                 charts = Calc.Path.Xml +Calc.results.xml ;
             }

              var so = new SWFObject( Calc.Path.Root + "_swf/opencalcmultichart_flash.swf", "video", "690", "290", "9", "#ffffff", false);
			  var calcId = $("#calcInput").attr("title");
			  so.addVariable("calcId", calcId);
              if(this.floats){
	          	so.addVariable("floats" , "true");
				so.addVariable("charts" , charts);
			  }else{
			  	so.addVariable( 'firstDate', Calc.results.range[0] );
	          	so.addVariable( 'secondDate', Calc.results.range[1] );
	          	so.addVariable( 'charts', charts );
	            so.addVariable( 'type', '' );
	            so.addVariable( 'precision', 2 );
			  }

			  so.addParam("wmode","transparent");
              so.write("wrapperFlash");
            });
          }
    }],
	initComponent: function() {
		Calc.flashContent.superclass.initComponent.apply(this, arguments);
		this.addEvents ( 'afterrender' );
	},
	afterRender: function(){
		Calc.flashContent.superclass.afterRender.call(this);
		this.fireEvent('afterrender', this);
	}

});

Ext.reg('elem.flashContent', Calc.flashContent);

Ext.MessageBox2 = function(){
    var dlg, opt, mask, waitTimer;
    var bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl;
    var buttons, activeTextEl, bwidth, iconCls = '';

    // private
    var handleButton = function(button){
        if(dlg.isVisible()){
            dlg.hide();
            Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value], 1);
        }
    };

    // private
    var handleHide = function(){
        if(opt && opt.cls){
            dlg.el.removeClass(opt.cls);
        }
        progressBar.reset();
    };

    // private
    var handleEsc = function(d, k, e){
        if(opt && opt.closable !== false){
            dlg.hide();
        }
        if(e){
            e.stopEvent();
        }
    };

    // private
    var updateButtons = function(b){
        var width = 0;
        if(!b){
            buttons["ok"].hide();
            buttons["cancel"].hide();
            buttons["yes"].hide();
            buttons["no"].hide();
            return width;
        }
        dlg.footer.dom.style.display = '';
        for(var k in buttons){
            if(typeof buttons[k] != "function"){
                if(b[k]){
                    buttons[k].show();
                    buttons[k].setText(typeof b[k] == "string" ? b[k] : Ext.MessageBox2.buttonText[k]);
                    width += buttons[k].el.getWidth()+15;
                }else{
                    buttons[k].hide();
                }
            }
        }
        return width;
    };

    return {

        getDialog : function(titleText){
           if(!dlg){
                dlg = new Ext.Window({
                	draggable: false,
                    autoCreate : true,
                    title:titleText,
                    resizable:false,
                    constrain:true,
                    constrainHeader:true,
                    minimizable : false,
                    maximizable : false,
                    stateful: false,
                    modal: true,
                    shim:true,
                    buttonAlign:"center",
                    width:400,
                    height:100,
                    minHeight: 80,
                    plain:true,
                    footer:true,
                    closable:true,
                    close : function(){
                        if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
                            handleButton("no");
                        }else{
                            handleButton("cancel");
                        }
                    }
                });
                buttons = {};
                var bt = this.buttonText;
                //TODO: refactor this block into a buttons config to pass into the Window constructor
                buttons["ok"] = dlg.addButton(bt["ok"], handleButton.createCallback("ok"));
                buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));
                buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));
                buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));
                buttons["ok"].hideMode = buttons["yes"].hideMode = buttons["no"].hideMode = buttons["cancel"].hideMode = 'offsets';
                dlg.render(document.body);
                dlg.getEl().addClass('x-window-dlg');
                mask = dlg.mask;
                bodyEl = dlg.body.createChild({
                    html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'
                });
                iconEl = Ext.get(bodyEl.dom.firstChild);
                var contentEl = bodyEl.dom.childNodes[1];
                msgEl = Ext.get(contentEl.firstChild);
                textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
                textboxEl.enableDisplayMode();
                textboxEl.addKeyListener([10,13], function(){
                    if(dlg.isVisible() && opt && opt.buttons){
                        if(opt.buttons.ok){
                            handleButton("ok");
                        }else if(opt.buttons.yes){
                            handleButton("yes");
                        }
                    }
                });
                textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
                textareaEl.enableDisplayMode();
                progressBar = new Ext.ProgressBar({
                    renderTo:bodyEl
                });
               bodyEl.createChild({cls:'x-clear'});
            }
            return dlg;
        },

        updateText : function(text){
            if(!dlg.isVisible() && !opt.width){
                dlg.setSize(this.maxWidth, 100); // resize first so content is never clipped from previous shows
            }
            msgEl.update(text || '&#160;');

            var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0;
            var mw = msgEl.getWidth() + msgEl.getMargins('lr');
            var fw = dlg.getFrameWidth('lr');
            var bw = dlg.body.getFrameWidth('lr');
            if (Ext.isIE && iw > 0){
                //3 pixels get subtracted in the icon CSS for an IE margin issue,
                //so we have to add it back here for the overall width to be consistent
                iw += 3;
            }
            var w = Math.max(Math.min(opt.width || iw+mw+fw+bw, this.maxWidth),
                        Math.max(opt.minWidth || this.minWidth, bwidth || 0));

            if(opt.prompt === true){
                activeTextEl.setWidth(w-iw-fw-bw);
            }
            if(opt.progress === true || opt.wait === true){
                progressBar.setSize(w-iw-fw-bw);
            }
            dlg.setSize(w, 'auto').center();
            return this;
        },

        updateProgress : function(value, progressText, msg){
            progressBar.updateProgress(value, progressText);
            if(msg){
                this.updateText(msg);
            }
            return this;
        },

        /**
         * Returns true if the message box is currently displayed
         * @return {Boolean} True if the message box is visible, else false
         */
        isVisible : function(){
            return dlg && dlg.isVisible();
        },

        hide : function(){
            if(this.isVisible()){
                dlg.hide();
                handleHide();
            }
            return this;
        },

        show : function(options){
            if(this.isVisible()){
                this.hide();
            }
            opt = options;
            var d = this.getDialog(opt.title || "&#160;");

            d.setTitle(opt.title || "&#160;");
            var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
            d.tools.close.setDisplayed(allowClose);
            activeTextEl = textboxEl;
            opt.prompt = opt.prompt || (opt.multiline ? true : false);
            if(opt.prompt){
                if(opt.multiline){
                    textboxEl.hide();
                    textareaEl.show();
                    textareaEl.setHeight(typeof opt.multiline == "number" ?
                        opt.multiline : this.defaultTextHeight);
                    activeTextEl = textareaEl;
                }else{
                    textboxEl.show();
                    textareaEl.hide();
                }
            }else{
                textboxEl.hide();
                textareaEl.hide();
            }
            activeTextEl.dom.value = opt.value || "";
            if(opt.prompt){
                d.focusEl = activeTextEl;
            }else{
                var bs = opt.buttons;
                var db = null;
                if(bs && bs.ok){
                    db = buttons["ok"];
                }else if(bs && bs.yes){
                    db = buttons["yes"];
                }
                if (db){
                    d.focusEl = db;
                }
            }
            if(opt.iconCls){
              d.setIconClass(opt.iconCls);
            }
            this.setIcon(opt.icon);
            bwidth = updateButtons(opt.buttons);
            progressBar.setVisible(opt.progress === true || opt.wait === true);
            this.updateProgress(0, opt.progressText);
            this.updateText(opt.msg);
            if(opt.cls){
                d.el.addClass(opt.cls);
            }
            d.proxyDrag = opt.proxyDrag === true;
            d.modal = opt.modal !== false;
            d.mask = opt.modal !== false ? mask : false;
            if(!d.isVisible()){
                // force it to the end of the z-index stack so it gets a cursor in FF
                document.body.appendChild(dlg.el.dom);
                d.setAnimateTarget(opt.animEl);
                d.show(opt.animEl);
            }

            //workaround for window internally enabling keymap in afterShow
            d.on('show', function(){
                if(allowClose === true){
                    d.keyMap.enable();
                }else{
                    d.keyMap.disable();
                }
            }, this, {single:true});

            if(opt.wait === true){
                progressBar.wait(opt.waitConfig);
            }
            return this;
        },

        setIcon : function(icon){
            if(icon && icon != ''){
                iconEl.removeClass('x-hidden');
                iconEl.replaceClass(iconCls, icon);
                iconCls = icon;
            }else{
                iconEl.replaceClass(iconCls, 'x-hidden');
                iconCls = '';
            }
            return this;
        },

        progress : function(title, msg, progressText){
            this.show({
                title : title,
                msg : msg,
                buttons: false,
                progress:true,
                closable:false,
                minWidth: this.minProgressWidth,
                progressText: progressText
            });
            return this;
        },

        wait : function(msg, title, config){
            this.show({
                title : title,
                msg : msg,
                buttons: false,
                closable:false,
                wait:true,
                modal:true,
                minWidth: this.minProgressWidth,
                waitConfig: config
            });
            return this;
        },

        alert : function(title, msg, fn, scope){
            this.show({
                title : title,
                msg : msg,
                buttons: this.OK,
                fn: fn,
                scope : scope
            });
            return this;
        },

        confirm : function(title, msg, fn, scope){
            this.show({
                title : title,
                msg : msg,
                buttons: this.YESNO,
                fn: fn,
                scope : scope,
                icon: this.QUESTION
            });
            return this;
        },

        prompt : function(title, msg, fn, scope, multiline, value){
            this.show({
                title : title,
                msg : msg,
                buttons: this.OKCANCEL,
                fn: fn,
                minWidth:250,
                scope : scope,
                prompt:true,
                multiline: multiline,
                value: value
            });
            return this;
        },

        OK : {ok:true},

        CANCEL : {cancel:true},

        OKCANCEL : {ok:true, cancel:true},

        YESNO : {yes:true, no:true},

        YESNOCANCEL : {yes:true, no:true, cancel:true},

        INFO : 'ext-mb-info',

        WARNING : 'ext-mb-warning',

        QUESTION : 'ext-mb-question',

        ERROR : 'ext-mb-error',

        defaultTextHeight : 75,

        maxWidth : 600,

        minWidth : 100,

        minProgressWidth : 250,

        buttonText : {
            ok : "OK",
            cancel : "Cancel",
            yes : "Yes",
            no : "No"
        }
    };
}();


Ext.Msg = Ext.MessageBox2;
