/* @private * Currently not used * Rrule info: http://www.kanzaki.com/docs/ical/rrule.html */ Ext.ensible.cal.RecurrenceField = Ext.extend(Ext.form.Field, { fieldLabel: 'Repeats', startDate: new Date().clearTime(), enableFx: true, initComponent : function(){ Ext.ensible.cal.RecurrenceField.superclass.initComponent.call(this); if(!this.height){ this.autoHeight = true; } }, onRender: function(ct, position){ if(!this.el){ this.frequencyCombo = new Ext.ensible.cal.RecurrenceCombo({ id: this.id+'-frequency', listeners: { 'recurrencechange': { fn: this.showOptions, scope: this } } }); if(this.fieldLabel){ this.frequencyCombo.fieldLabel = this.fieldLabel; } this.innerCt = new Ext.Container({ cls: 'extensible-recur-inner-ct', items: [] }); this.fieldCt = new Ext.Container({ autoEl: {id:this.id}, //make sure the container el has the field's id cls: 'extensible-recur-ct', renderTo: ct, items: [this.frequencyCombo, this.innerCt] }); this.fieldCt.ownerCt = this; this.innerCt.ownerCt = this.fieldCt; this.el = this.fieldCt.getEl(); this.items = new Ext.util.MixedCollection(); this.items.addAll(this.initSubComponents()); } Ext.ensible.cal.RecurrenceField.superclass.onRender.call(this, ct, position); }, // afterRender : function(){ // Ext.ensible.cal.RecurrenceField.superclass.afterRender.call(this); // this.setStartDate(this.startDate); // }, // private initValue : function(){ this.setStartDate(this.startDate); if(this.value !== undefined){ this.setValue(this.value); } else if(this.frequency !== undefined){ this.setValue('FREQ='+this.frequency); } else{ this.setValue('NONE'); } this.originalValue = this.getValue(); }, showOptions : function(o){ var layoutChanged = false, unit = 'day'; if(o != 'NONE'){ this.hideSubPanels(); } this.frequency = o; switch(o){ case 'DAILY': layoutChanged = this.showSubPanel(this.repeatEvery); layoutChanged |= this.showSubPanel(this.until); break; case 'WEEKLY': layoutChanged = this.showSubPanel(this.repeatEvery); layoutChanged |= this.showSubPanel(this.weekly); layoutChanged |= this.showSubPanel(this.until); unit = 'week'; break; case 'MONTHLY': layoutChanged = this.showSubPanel(this.repeatEvery); layoutChanged |= this.showSubPanel(this.monthly); layoutChanged |= this.showSubPanel(this.until); unit = 'month'; break; case 'YEARLY': layoutChanged = this.showSubPanel(this.repeatEvery); layoutChanged |= this.showSubPanel(this.yearly); layoutChanged |= this.showSubPanel(this.until); unit = 'year'; break; default: // case NONE this.hideInnerCt(); return; } if(layoutChanged){ this.innerCt.doLayout(); } this.showInnerCt(); this.repeatEvery.updateLabel(unit); }, showSubPanel : function(p){ if (p.rendered) { p.show(); return false; } else{ if(this.repeatEvery.rendered){ // make sure weekly/monthly options show in the middle p = this.innerCt.insert(1, p); } else{ p = this.innerCt.add(p); } p.show(); return true; } }, showInnerCt: function(){ if(!this.innerCt.isVisible()){ if(this.enableFx && Ext.enableFx){ this.innerCt.getPositionEl().slideIn('t', { duration: .3 }); } else{ this.innerCt.show(); } } }, hideInnerCt: function(){ if(this.innerCt.isVisible()){ if(this.enableFx && Ext.enableFx){ this.innerCt.getPositionEl().slideOut('t', { duration: .3, easing: 'easeIn', callback: this.hideSubPanels, scope: this }); } else{ this.innerCt.hide(); this.hideSubPanels(); } } }, setStartDate : function(dt){ this.items.each(function(p){ p.setStartDate(dt); }); }, getValue : function(){ if(!this.rendered) { return this.value; } if(this.frequency=='NONE'){ return ''; } var value = 'FREQ='+this.frequency; this.items.each(function(p){ if(p.isVisible()){ value += p.getValue(); } }); return value; }, setValue : function(v){ this.value = v; if(v == null || v == '' || v == 'NONE'){ this.frequencyCombo.setValue('NONE'); this.showOptions('NONE'); return this; } var parts = v.split(';'); this.items.each(function(p){ p.setValue(parts); }); Ext.each(parts, function(p){ if(p.indexOf('FREQ') > -1){ var freq = p.split('=')[1]; this.frequencyCombo.setValue(freq); this.showOptions(freq); return; } }, this); return this; }, hideSubPanels : function(){ this.items.each(function(p){ p.hide(); }); }, initSubComponents : function(){ Ext.ensible.cal.recurrenceBase = Ext.extend(Ext.Container, { fieldLabel: ' ', labelSeparator: '', hideLabel: true, layout: 'table', anchor: '100%', startDate: this.startDate, //TODO: This is not I18N-able: getSuffix : function(n){ if(!Ext.isNumber(n)){ return ''; } switch (n) { case 1: case 21: case 31: return "st"; case 2: case 22: return "nd"; case 3: case 23: return "rd"; default: return "th"; } }, //shared by monthly and yearly components: initNthCombo: function(cbo){ var cbo = Ext.getCmp(this.id+'-combo'), dt = this.startDate, store = cbo.getStore(), last = dt.getLastDateOfMonth().getDate(), dayNum = dt.getDate(), nthDate = dt.format('jS') + ' day', isYearly = this.id.indexOf('-yearly') > -1, yearlyText = ' in ' + dt.format('F'), nthDayNum, nthDay, lastDay, lastDate, idx, data, s; nthDayNum = Math.ceil(dayNum / 7); nthDay = nthDayNum + this.getSuffix(nthDayNum) + dt.format(' l'); if(isYearly){ nthDate += yearlyText; nthDay += yearlyText; } data = [[nthDate],[nthDay]]; s = isYearly ? yearlyText : ''; if(last-dayNum < 7){ data.push(['last '+dt.format('l')+s]); } if(last == dayNum){ data.push(['last day'+s]); } idx = store.find('field1', cbo.getValue()); store.removeAll(); cbo.clearValue(); store.loadData(data); if(idx > data.length-1){ idx = data.length-1; } cbo.setValue(store.getAt(idx > -1 ? idx : 0).data.field1); return this; }, setValue:Ext.emptyFn }); this.repeatEvery = new Ext.ensible.cal.recurrenceBase({ id: this.id+'-every', layoutConfig: { columns: 3 }, items: [{ xtype: 'label', text: 'Repeat every' },{ xtype: 'numberfield', id: this.id+'-every-num', value: 1, width: 35, minValue: 1, maxValue: 99, allowBlank: false, enableKeyEvents: true, listeners: { 'keyup': { fn: function(){ this.repeatEvery.updateLabel(); }, scope: this } } },{ xtype: 'label', id: this.id+'-every-label' }], setStartDate: function(dt){ this.startDate = dt; this.updateLabel(); return this; }, getValue: function(){ var v = Ext.getCmp(this.id+'-num').getValue(); return v > 1 ? ';INTERVAL='+v : ''; }, setValue : function(v){ var set = false, parts = Ext.isArray(v) ? v : v.split(';'); Ext.each(parts, function(p){ if(p.indexOf('INTERVAL') > -1){ var interval = p.split('=')[1]; Ext.getCmp(this.id+'-num').setValue(interval); } }, this); return this; }, updateLabel: function(type){ if(this.rendered){ var s = Ext.getCmp(this.id+'-num').getValue() == 1 ? '' : 's'; this.type = type ? type.toLowerCase() : this.type || 'day'; var lbl = Ext.getCmp(this.id+'-label'); if(lbl.rendered){ lbl.update(this.type + s + ' beginning ' + this.startDate.format('l, F j')); } } return this; }, afterRender: function(){ Ext.ensible.cal.recurrenceBase.superclass.afterRender.call(this); this.updateLabel(); } }); this.weekly = new Ext.ensible.cal.recurrenceBase({ id: this.id+'-weekly', layoutConfig: { columns: 2 }, items: [{ xtype: 'label', text: 'on:' },{ xtype: 'checkboxgroup', id: this.id+'-weekly-days', items: [ {boxLabel: 'Sun', name: 'SU', id: this.id+'-weekly-SU'}, {boxLabel: 'Mon', name: 'MO', id: this.id+'-weekly-MO'}, {boxLabel: 'Tue', name: 'TU', id: this.id+'-weekly-TU'}, {boxLabel: 'Wed', name: 'WE', id: this.id+'-weekly-WE'}, {boxLabel: 'Thu', name: 'TH', id: this.id+'-weekly-TH'}, {boxLabel: 'Fri', name: 'FR', id: this.id+'-weekly-FR'}, {boxLabel: 'Sat', name: 'SA', id: this.id+'-weekly-SA'} ] }], setStartDate: function(dt){ this.startDate = dt; this.selectToday(); return this; }, selectToday: function(){ this.clearValue(); var day = this.startDate.format('D').substring(0,2).toUpperCase(); Ext.getCmp(this.id + '-days').setValue(day, true); }, clearValue: function(){ Ext.getCmp(this.id + '-days').setValue([false, false, false, false, false, false, false]); }, getValue: function(){ var v = '', sel = Ext.getCmp(this.id+'-days').getValue(); Ext.each(sel, function(chk){ if(v.length > 0){ v += ','; } v += chk.name; }); var day = this.startDate.format('D').substring(0,2).toUpperCase(); return v.length > 0 && v != day ? ';BYDAY='+v : ''; }, setValue : function(v){ var set = false, parts = Ext.isArray(v) ? v : v.split(';'); this.clearValue(); Ext.each(parts, function(p){ if(p.indexOf('BYDAY') > -1){ var days = p.split('=')[1].split(','), vals = {}; Ext.each(days, function(d){ vals[d] = true; }, this); Ext.getCmp(this.id+'-days').setValue(vals); return set = true; } }, this); if(!set){ this.selectToday(); } return this; } }); this.monthly = new Ext.ensible.cal.recurrenceBase({ id: this.id+'-monthly', layoutConfig: { columns: 3 }, items: [{ xtype: 'label', text: 'on the' },{ xtype: 'combo', id: this.id+'-monthly-combo', mode: 'local', width: 150, triggerAction: 'all', forceSelection: true, store: [] },{ xtype: 'label', text: 'of each month' }], setStartDate: function(dt){ this.startDate = dt; this.initNthCombo(); return this; }, getValue: function(){ var cbo = Ext.getCmp(this.id+'-combo'), store = cbo.getStore(), idx = store.find('field1', cbo.getValue()), dt = this.startDate, day = dt.format('D').substring(0,2).toUpperCase(); if (idx > -1) { switch(idx){ case 0: return ';BYMONTHDAY='+dt.format('j'); case 1: return ';BYDAY='+cbo.getValue()[0].substring(0,1)+day; case 2: return ';BYDAY=-1'+day; default: return ';BYMONTHDAY=-1'; } } return ''; } }); this.yearly = new Ext.ensible.cal.recurrenceBase({ id: this.id+'-yearly', layoutConfig: { columns: 3 }, items: [{ xtype: 'label', text: 'on the' },{ xtype: 'combo', id: this.id+'-yearly-combo', mode: 'local', width: 170, triggerAction: 'all', forceSelection: true, store: [] },{ xtype: 'label', text: 'each year' }], setStartDate: function(dt){ this.startDate = dt; this.initNthCombo(); return this; }, getValue: function(){ var cbo = Ext.getCmp(this.id+'-combo'), store = cbo.getStore(), idx = store.find('field1', cbo.getValue()), dt = this.startDate, day = dt.format('D').substring(0,2).toUpperCase(), byMonth = ';BYMONTH='+dt.format('n'); if(idx > -1){ switch(idx){ case 0: return byMonth; case 1: return byMonth+';BYDAY='+cbo.getValue()[0].substring(0,1)+day; case 2: return byMonth+';BYDAY=-1'+day; default: return byMonth+';BYMONTHDAY=-1'; } } return ''; } }); this.until = new Ext.ensible.cal.recurrenceBase({ id: this.id+'-until', untilDateFormat: 'Ymd\\T000000\\Z', layoutConfig: { columns: 5 }, items: [{ xtype: 'label', text: 'and continuing' },{ xtype: 'combo', id: this.id+'-until-combo', mode: 'local', width: 85, triggerAction: 'all', forceSelection: true, value: 'forever', store: ['forever', 'for', 'until'], listeners: { 'select': { fn: function(cbo, rec){ var dt = Ext.getCmp(this.id+'-until-date'); if(rec.data.field1 == 'until'){ dt.show(); if (dt.getValue() == '') { dt.setValue(this.startDate.add(Date.DAY, 5)); dt.setMinValue(this.startDate.clone().add(Date.DAY, 1)); } } else{ dt.hide(); } if(rec.data.field1 == 'for'){ Ext.getCmp(this.id+'-until-num').show(); Ext.getCmp(this.id+'-until-endlabel').show(); } else{ Ext.getCmp(this.id+'-until-num').hide(); Ext.getCmp(this.id+'-until-endlabel').hide(); } }, scope: this } } },{ xtype: 'datefield', id: this.id+'-until-date', showToday: false, hidden: true },{ xtype: 'numberfield', id: this.id+'-until-num', value: 5, width: 35, minValue: 1, maxValue: 99, allowBlank: false, hidden: true },{ xtype: 'label', id: this.id+'-until-endlabel', text: 'occurrences', hidden: true }], setStartDate: function(dt){ this.startDate = dt; return this; }, getValue: function(){ var dt = Ext.getCmp(this.id+'-date'); if(dt.isVisible()){ return ';UNTIL='+dt.getValue().format(this.untilDateFormat); } var ct = Ext.getCmp(this.id+'-num'); if(ct.isVisible()){ return ';COUNT='+ct.getValue(); } return ''; }, setValue : function(v){ var set = false, parts = Ext.isArray(v) ? v : v.split(';'); Ext.each(parts, function(p){ if(p.indexOf('COUNT') > -1){ var count = p.split('=')[1]; Ext.getCmp(this.id+'-combo').setValue('for'); Ext.getCmp(this.id+'-num').setValue(count).show(); Ext.getCmp(this.id+'-endlabel').show(); } else if(p.indexOf('UNTIL') > -1){ var dt = p.split('=')[1]; Ext.getCmp(this.id+'-combo').setValue('until'); Ext.getCmp(this.id+'-date').setValue(Date.parseDate(dt, this.untilDateFormat)).show(); Ext.getCmp(this.id+'-endlabel').hide(); } }, this); return this; } }); return [this.repeatEvery, this.weekly, this.monthly, this.yearly, this.until]; } }); Ext.reg('extensible.recurrencefield', Ext.ensible.cal.RecurrenceField);