PDA

View Full Version : Ext.ux.picker.Time [timepickerfield]



renato01
23 Mar 2012, 7:44 AM
Timepicker for hours and minutes. The TimePickerField is derived from the Ext.field.DatePicker. So it inherits al default behavior. The value returned by timepicker is a full date object, with time portion.
Here is a touch version of time picker:


The picker:


/**
* The picker with hours and minutes slots
*/
Ext.define('Ext.ux.picker.Time', {
extend:'Ext.picker.Picker',
xtype:'timepicker',


config:{
/**
* @cfg {Number} increment The number of minutes between each minute value in the list.
* Defaults to: 5
*/
increment:5,


/**
* @cfg {Number} start value of hours
*/
minHours:0,


/**
* @cfg {Number} end value of hours.
*/
maxHours:23,


/**
* @cfg {String} title to show above hour slot
* Note: for titles to show set the {useTitle} config to true.
*/
hoursTitle:'Hours',


/**
* @cfg {String} title to show above hour slot
* Note: for this to show set the {useTitle} config to true.
*/
minutesTitle:'Minutes',


/**
* @cfg {boolean} show/hide title headers.
* Note: defaults to false (framework default 'Ext.picker.Picker')
*/


slots: []
},


/**
*
* @param value
* @param animated
*/
setValue:function (value, animated) {
var increment = this.getInitialConfig().increment,
modulo;


if (Ext.isDate(value)) {
value = {
hours:value.getHours(),
minutes:value.getMinutes()
};
}


//Round minutes
modulo = value.minutes % increment;
if (modulo > 0) {
value.minutes = Math.round(value.minutes / increment) * increment;
}
this.callParent([value, animated]);
},


/**
* @override
* @returns {Date} A date object containing the selected hours and minutes. Year, month, day default to the current date..
*/
getValue:function () {
var value = this.callParent(arguments),
date = new Date();
value = new Date(date.getFullYear(), date.getMonth(), date.getDate(), value.hours, value.minutes);
return value;
},


applySlots:function (slots) {
var me = this,
hours = me.createHoursSlot(),
minutes = me.createMinutesSlot();


return [hours, minutes];
},


createHoursSlot:function () {
var me = this,
initialConfig = me.getInitialConfig(),
title = initialConfig.hoursTitle ,
minHours = initialConfig.minHours,
maxHours = initialConfig.maxHours,
hours = [],
slot;


for (var i = minHours; i <= maxHours; i++) {
var text = (i < 10) ? ('0' + i) : i; //Add leading zero
hours.push({text:text, value:i});
}


slot = {
name:'hours',
align:'center',
title:title,
data:hours,
flex:1
};


return slot;
},


createMinutesSlot:function () {
var me = this,
initialConfig = me.getInitialConfig(),
title = initialConfig.minutesTitle ,
increment = initialConfig.increment,
minutes = [],
slot;


for (var j = 0; j < 60; j += increment) {
var text;
text = (j < 10) ? ('0' + j) : j; //Add leading zero
minutes.push({text:text, value:j});
}


slot = {
name:'minutes',
align:'center',
title:title,
data:minutes,
flex:1
};
return slot;
}
});


The picker text field (extends from the datepickerfield)


/**
* TimePickerfield. Extends from datepickerfield
*/
Ext.define('Ext.ux.field.TimePicker', {
extend:'Ext.field.DatePicker',
xtype:'timepickerfield',


requires:['Ext.ux.picker.Time'],


config:{
dateFormat:'H:i', //Default format show time only
picker:true
},


/**
* @override
* @param value
* Source copied, small modification
*/
applyValue:function (value) {
if (!Ext.isDate(value) && !Ext.isObject(value)) {
value = null;
}


// Begin modified section
if (Ext.isObject(value)) {
var date = new Date(),
year = value.year || date.getFullYear(), // Defaults to current year if year was not supplied etc..
month = value.month || date.getMonth(),
day = value.day || date.getDate();


value = new Date(year, month, day, value.hours, value.minutes); //Added hour and minutes
}
// End modfied section!
return value;
},


applyPicker:function (picker) {
picker = Ext.factory(picker, 'Ext.ux.picker.Time');
picker.setHidden(true); // Do not show picker on creeation
Ext.Viewport.add(picker);
return picker;
},


updatePicker:function (picker) {
picker.on({
scope:this,
change:'onPickerChange',
hide:'onPickerHide'
});
picker.setValue(this.getValue());
return picker;
}
});



Usage:

{
xtype: 'timepickerfield',
label: 'time',
value: new Date(), // object also possible {hours:12, minutes:25},
name: 'time',
picker:{
height:300
minHours:9, //(optional)Selectable hours will be between 9-18
maxHours:18 // (optional) These values default to 0-24
}
}





//* Notes:
getValue() // will return a {Date} object
getFormattedValue() //will return H:i (example16:40)

That's all. Any thoughts?


[EDIT]
- Refactored picker code.
- Implemented mithcell's comments

mitchellsimoens
23 Mar 2012, 9:13 AM
You should make picker a proper config of Ext.ux.picker.Time and use applyPicker method to do the Ext.factory to create the slot instead of doing it in getPicker and in updatePicker add the listener and set value.

renato01
26 Mar 2012, 7:54 AM
Took @mitchellsimoens comments and modified code.
Although, one question to @mitchell:
How would you do this part? The setHidden and then add to Viewport part?
Otherwise the picker won't show or immediately show after you add to Viewport..



applyPicker:function (picker) {
picker = Ext.factory(picker, 'Ext.ux.picker.Time');
picker.setHidden(true); // Do not show picker on creeation
Ext.Viewport.add(picker);
return picker;
}



I think that's why the Ext.field.DatePicker does the creation of the picker inside the getPicker(), when its first called..

supersaiyen
2 Apr 2012, 10:29 AM
Here's my attempt at the same notion, not sure i'm loving the input/output value format, but it works.


/**
* @author RWeneck
*
* Adapted from https://github.com/ghuntley/Ext.ux.touch.DateTimePicker
*
*/
Ext.define('Application.view.TimePicker', {
extend : 'Ext.Picker',
xtype : 'timepicker',


config : {
/**
* @cfg {String/Number} value The value to initialize the picker with
* @accessor
*/
value: "11:00 AM",
/**
* @cfg {String} hourText
* The label to show for the hour column. Defaults to 'Hour'.
*/
hourText : 'Hour',
/**
* @cfg {String} minuteText
* The label to show for the minute column. Defaults to 'Minute'.
*/
minuteText : 'Minute',
/**
* @cfg {String} daynightText
* The label to show for the daynight column. Defaults to 'AM/PM'.
*/
daynightText : 'AM/PM',
/**
* @cfg {Array} slotOrder
* An array of strings that specifies the order of the slots. Defaults to <tt>['hour', 'minute', 'daynight']</tt>.
*/
slotOrder : ['hour', 'minute', 'daynight']


},
// @private
initialize: function() {
var me = this;

var hours = [],
minutes = [],
daynight = [],
i;

for( i = 1; i <= 12; i++) {
hours.push({
text : i,
value : i
});
}


for( i = 0; i < 60; i += 5) {
minutes.push({
text : i < 10 ? '0' + i : i,
value : i
});
}


daynight.push({
text : 'AM',
value : 'AM'
}, {
text : 'PM',
value : 'PM'
});



var newSlots = [];
Ext.each(this.getSlotOrder(), function(item) {
newSlots.push(this.createSlot(item, hours, minutes, daynight));
}, this);

this.setSlots(newSlots);
this.callParent(arguments);
},
createSlot : function(name, hours, minutes, daynight) {
switch (name) {
case 'hour':
return {
name : 'hour',
align : 'center',
data : hours,
title : this.getUseTitles() ? this.getHourText() : false,
flex : 2
};
case 'minute':
return {
name : 'minute',
align : 'center',
data : minutes,
title : this.getUseTitles() ? this.getMinuteText() : false,
flex : 2
};
case 'daynight':
return {
name : 'daynight',
align : 'center',
data : daynight,
title : this.getUseTitles() ? this.getDaynightText() : false,
flex : 2
};
}
},


/**
* Takes a String or an object that represents time,
* The object should contain the keys; hour, minute, daynight
* or the string should be in the format of "11:00 AM"
*/
setValue : function(value, animated) {
if(!value){
value = {
hour : 11,
minute : 00,
daynight : "AM"
}
}
if(typeof value == "string"){
var hour, minute, daynight;
value = value.trim();
hour = value.substring(0, value.indexOf(":"));
minute = value.substring(value.indexOf(":")+1, value.indexOf(" "));
daynight = value.substring(value.indexOf(" ")+1);

value = {
hour : hour,
minute : minute,
daynight : daynight
}
}
this.callParent(arguments);

for(key in value) {
slot = this.child('[name=' + key + ']');
if(slot) {
if(key === 'hour' && value[key] > 12) {
daynightVal = 'PM';
value[key] -= 12;
}
slot.setValue(value[key], animated);
}
}
return this;
}
});


Can be used like so:


var picker = Ext.create('Application.view.TimePicker', {
useTitles : true,
value : "11:30 AM"
});
Ext.Viewport.add(picker);
picker.show();


33474

hjeDK
7 May 2012, 6:20 AM
This looks great, but how do you add it to an app and use it?
I'm using Sencha Touch 2 with the MVC-file structure and have read a bit about the Ext.Loader, but I still get
Uncaught Error: [Ext.createByAlias] Cannot create an instance of unrecognized alias: widget.timepickerfield

supersaiyen
7 May 2012, 6:40 AM
Create a TimePicker.js in your app/view folder. Change the Ext.define line to your applications name:

Ext.define('YOURAPPLICATON.view.TimePicker', {...
Then instantiate it like:


var picker = Ext.create('YOURAPPLICATION.view.TimePicker', {
useTitles : true,
value : "11:30 AM"
});
Ext.Viewport.add(picker);
picker.show();
This extends from datepicker, not datepickerfield, so you'll need to add it to the viewport and call show, though it wouldnt take much to assign it to a pickerfield's picker value.

hjeDK
7 May 2012, 6:46 AM
I was trying to implement @renato01 version as I need a 24-hour clock. and that makes use of Ext.ux-folders.

renato01
7 May 2012, 6:51 AM
This looks great, but how do you add it to an app and use it?
I'm using Sencha Touch 2 with the MVC-file structure and have read a bit about the Ext.Loader, but I still get
Uncaught Error: [Ext.createByAlias] Cannot create an instance of unrecognized alias: widget.timepickerfield

It looks like the files didn't load correctly.
Make sure the two files are in the correct folder:
- ext/ux/picker/Time.js
- ext/ux/field/TimePicker.js

Add the requires to your code and make sure they load correctly:

requires:['Ext.ux.field.TimePicker']

You may also need to configure the loader correctly.
Add this before you init your application


Ext.Loader.setConfig({
enabled: true,
paths:{
'Ext': '../../Scripts/ext' //This should be the url to your script folder..
}
});

That should do it!

Once you get that working, you can try this (better solution/more advanced):
Rename all occurrences of 'Ext' to 'YourAppName' and put the files in a 'ux' folder. The 'ux' should be on the same level as 'controller' & 'view'.
Example:

'Ext.ux.field.TimePicker' to > 'YOUAPPNAME.ux.field.TimePicker'
'Ext.ux.picker.Picker' to > 'YOUAPPNAME.ux.picker.Time'


- /ux/picker/Time.js
- /ux/field/TimePicker.js

hjeDK
7 May 2012, 7:08 AM
Thanks :) now I made it to show up on the view, but the sheet won't show up when I click the field.
I put the example code in as an item in a fieldset along with a datepicker and a selectfield

EDIT: the sheet turned up behind my panel that I have made as a modal popup. Any idea how to solve that?

renato01
7 May 2012, 7:22 AM
That might be a problem.. Because the picker is itself modal..
Maybe look into zIndex...

hjeDK
7 May 2012, 7:24 AM
That might be a problem.. Because the picker is itself modal..
Maybe look into zIndex...

Sencha's own datepicker shows up on top as expected. Maybe it can be compared to track down the issue.

renato01
8 May 2012, 6:37 AM
Sencha's own datepicker shows up on top as expected. Maybe it can be compared to track down the issue.

Could you post a small example code, where it doesn't work?

hjeDK
8 May 2012, 10:29 PM
Here's and excerpt of what I've got:



Ext.define('myApp.view.NewEvent',
{
extend: 'Ext.form.Panel',
requires: [ 'Ext.form.FieldSet',
'Ext.ux.picker.Time',
'Ext.ux.field.TimePicker',


],
xtype: 'neweventplan',
config:
{
itemId: 'newevent',
centered: true,
height: '100%',
width: '100%',
modal: true,
showAnimation: { type: 'slideIn', direction: 'left' },
styleHtmlContent: true,
scrollable: true,
items: [
{
<other components
},
{
xtype: 'fieldset',
items: [
{
<other components>
},
{
xtype: 'timepickerfield',
label: 'Tid',
itemId: 'timefield',
value: new Date(),
name: 'time',
picker:{
height: 300,
}
}

renato01
8 May 2012, 11:07 PM
Setting the zIndex to 10 or larger seems to fix the picker above modal panel issue..
Messageboxes also have a zIndex of 10 by default.

Try this:

picker:{
height:300,
zIndex:10
}

hjeDK
8 May 2012, 11:23 PM
The zIndex thing did the trick. Thanks :)

... I really need to get my UPPER/lower case thing straight :)

Carlos_hb
30 May 2012, 6:57 AM
Hi I was trying to use your code but i need a pickerfield where you can choose month, day, hours and minutes, is there a posibility to do this in a same picker using your code ?

arunjoy
6 Jun 2012, 4:13 AM
how to bind data to slot from database....

moin4u
30 Jul 2012, 7:12 AM
hi renato01,

Unable to achieve that I am getting the following error,

Uncaught Error: [Ext.createByAlias] Cannot create an instance of unrecognized alias: widget.timepickerfield

I put the timepickerfield class in the main view of my app and Time.js in sdk/src/ux/picker folder, while I am using Sencha touch 2, pleae guid eme on that.

Thank

Moin

renato01
30 Jul 2012, 7:20 AM
@moin4u
Please read post #8 in this thread. Sounds like the same problem..
Put the 'ux' folder in the root of sdk.

http://www.sencha.com/forum/showthread.php?190297-Ext.ux.picker.Time-timepickerfield&p=797526&viewfull=1#post797526

Veer_Muchandi
14 Jan 2013, 1:09 PM
Is there a way to extend this to accept both date and time as a single field (Timestamp)? I have a need to send Timestamp to my backend as "01/14/2013 3:30 EST".

icebergdelphi
3 Sep 2013, 7:14 AM
Hi, reopen this thread, how to add the timepickerfield to use it in sencha architech 2.2?

Thanks.:-?

renato01
3 Sep 2013, 7:22 AM
Hi, reopen this thread, how to add the timepickerfield to use it in sencha architech 2.2?

Thanks.:-?

Sorry. I have no Idea. I never worked with architecht.. Can't you add custom components?

icebergdelphi
3 Sep 2013, 8:12 AM
Thanks but i have not idea too, i currently working with sencha architec, and i need to add custom components.

rey880512
16 Mar 2017, 11:51 AM
Good, sorry for my English, I write because I'm working with sencha and I just saw a post of yours in the forum about timepicker. I have the following problem:


I'm trying to create a timepickerfield, but when I select the field the picker comes out empty which can be that. Here I leave a catch. Greeting and thank you beforehand.

56039