Forums / Developer / Date picker (pop-up)?

Date picker (pop-up)?

Author Message

Fraser Hore

Sunday 18 December 2005 3:00:06 am

Has anyone implemented a date picker pop up to make it easier for users to enter dates? I'm thinking of the standard date picker you have when booking flights online for example.

Any ideas on how to implement this would be much appreciated.

Cheers,

Fraser

Xavier Dutoit

Monday 19 December 2005 1:36:09 am

Hi,

You've got several js interface for the calendar. The one I've choosen to add to sugarcrm was : http://www.dynarch.com/projects/calendar/ but I did it long ago and you might find some more adapted.

As for the template to modify:
design/standard/templates/content/datatype/edit/ezdate.tpl

(don't modify it directly, but create a
design/[yourdesign]/templates/content/datatype/edit/ezdate.tpl ) and clear the cache.

X+

P.S. Tell us if you decide to share the result, I thing that's a good idea.

http://www.sydesy.com

Fraser Hore

Monday 19 December 2005 3:33:47 pm

Thanks Xavier for the tip!!

I tried out the DHTML calendar you recommended and I've almost got it working. Here's what i did:

1) I copied the stylesheet to design/standard/stylsheets/popupcalendar/skins/aqua/theme.css

2) Copied the javascript files to /design/standard/javascript/popupcalendar/

3) In /settings/override/design.ini.append.php I added:

[StylesheetSettings]
SiteCSS=packages/styles/t01/files/default/file/design/base/stylesheets/t1/site-colors.css
ClassesCSS=packages/styles/t01/files/default/file/design/base/stylesheets/t1/classes-colors.css
CSSFileList[]=popupcalendar/skins/aqua/theme.css

[JavaScriptSettings]
# List of JavaScript files to include in pagelayout
JavaScriptList[]
JavaScriptList[]=popupcalendar/calendar.js
JavaScriptList[]=popupcalendar/lang/calendar-en.js
JavaScriptList[]=popupcalendar/calendar-setup.js

4) I created an override template for the ezdate attribute. In the ezdate template override i added the following ids to each input, id="year", id="month", id="day". Then i pasted the following javascript for the calendar at the very end of the template file. I also wrapped the javascript in <literal></literal> tags:

{literal}
<script type="text/javascript">
Calendar.setup(
{
inputField : "year",
ifFormat : "%Y"
}
);
Calendar.setup(
{
inputField : "month",
ifFormat : "%m"
}
);Calendar.setup(
{
inputField : "day",
ifFormat : "%d"
}
);
</script>
{/literal}

RESULTS

The good news is that clicking in each of the year, month and day input fields brings up the popup calendar. More good news is that it actually puts the appropriate year, month or day in the appropriate field.

There are two problems i could use some help with (did I forget to mention that i don't know any javascript :-) :

1) you have to click in each field and select a date to fill all three fields. If anyone can help with the javascript to enable clicking in one of the fields and updating all three, that would be awesome. As a tip, the documentation for the jscalendar describes how to keep two fields one week apart depending on whether the first or second is updated. The code is:

function catcalc(cal) {
var date = cal.date;
var time = date.getTime()
// use the _other_ field
var field = document.getElementById("f_calcdate");
if (field == cal.params.inputField) {
field = document.getElementById("f_date_a");
time -= Date.WEEK; // substract one week
} else {
time += Date.WEEK; // add one week
}
var date2 = new Date(time);
field.value = date2.print("%Y-%m-%d %H:%M");
}

Perhaps there's a hint in there!

2) The second problem is that the calendar comes up across the whole page instead of just a little calendar. must be something wrong in the css, or a css rule in the site css file is overriding the calendar css file. Any suggestions?

So, all and all it's very close and a very cool little solution. The popup calendar is essential in my opinion. Any help finishing this off would be MUCH appreciated.

Cheers,

Fraser

Fraser Hore

Tuesday 20 December 2005 1:51:14 am

Ok I got it to work, sort of.

I tried the following code in my ezdate override template and it seems to work, but only for the last of several date fields in my content class. I can still pick the year, month and day individually in the other date fields but in the last one, it will properly update all fields no matter which one i happen to select to bring up the calendar. Anyone have any ideas to get this to work for all the date attributes in my class?

The Code:

{literal}
<script type="text/javascript">
function catcalc(cal) {
var date = cal.date;
var input_field_year = document.getElementById("year");
input_field_year.value = date.print("%Y");
var input_field_month= document.getElementById("month");
input_field_month.value = date.print("%m");
var input_field_day= document.getElementById("day");
input_field_day.value = date.print("%d");
};
Calendar.setup(
{
inputField : "year",
ifFormat : "%Y",
onUpdate: catcalc
}
);
Calendar.setup(
{
inputField : "month",
ifFormat : "%m",
onUpdate: catcalc
}
);Calendar.setup(
{
inputField : "day",
ifFormat : "%d",
onUpdate: catcalc
}
);
</script>
{/literal}

Paul Forsyth

Tuesday 20 December 2005 2:01:50 am

Could this be wrapped up into its own extension? The dynarch calendar plus the override template?

Kristian Hole

Tuesday 20 December 2005 4:39:13 am

Yes, this would be cool as a separate extension.

As far as i can see the solution so far does not work if you have 2 datefields in the same class. I think it should work no matter how many fields you add.

Kristian

http://ez.no/ez_publish/documenta...tricks/show_which_templates_are_used
http://ez.no/doc/ez_publish/techn...te_operators/miscellaneous/attribute

Fraser Hore

Tuesday 20 December 2005 6:38:18 am

I was thinking about making this an extension and i think it would be quite easy to do. But, we have to get it working first! I'm a bit stumped as to why it only works on the last of the date attributes so any ideas would be appreciated. I aslo have to figure out what's going wrong with the css as the calendar spreads across the page rather than popup in a just a little box. So, the callenge is there if anyone want's to help out!

Cheers,

Fraser

Fraser Hore

Tuesday 20 December 2005 7:16:21 am

Perhaps only the last attribute works properly because the variables set in the javascript for each attribute and maybe they're not properly destroyed after each instance. Could that be it? I could use perhaps the ez template code to put the attribute identifier in the variable name.

Kristian Hole

Tuesday 20 December 2005 7:29:00 am

Yes, the problem is that there is more fields with the same identifier. You need to generate unique ids for each datefield. If you look in /design/standard/templates/content/datatype/edit/ezdate.tpl you will see that there is a unique identifier used {$attribute.id}, which you can use to generate a unique datefield. ( Like for example year_{$attribute.id} ).

I think you also need some javascriptcode in the ezdate.tpl to connect the calendar to each datefield.

Kristian

http://ez.no/ez_publish/documenta...tricks/show_which_templates_are_used
http://ez.no/doc/ez_publish/techn...te_operators/miscellaneous/attribute

Kristian Hole

Tuesday 20 December 2005 7:31:47 am

Offcourse you should put a copy of the standard template in your exension so you dont have to modify the original one. Something like extension/MYEXENSION/design/standard/templates/content/datatype/edit/ezdate.tpl.

You enable designs in an exension with
[ExtensionSettings]
DesignExtensions[]=MYEXENSION

in extension/settings/design.ini.append.php

Kristian

http://ez.no/ez_publish/documenta...tricks/show_which_templates_are_used
http://ez.no/doc/ez_publish/techn...te_operators/miscellaneous/attribute

Paul Forsyth

Tuesday 20 December 2005 8:33:16 am

Ok, i have it working now.

Once you have it all setup try this code:

<button type="reset" id="{concat('trigger',$attribute.id)}">...</button>

{literal}
<script type="text/javascript">
  Calendar.setup(
    {
      onSelect    : onSelectDateTime{/literal}{$attribute.id}{literal},
      button      : "trigger{/literal}{$attribute.id}{literal}"      
    }
  );

function onSelectDateTime{/literal}{$attribute.id}{literal}(calendar, date)
{
  var year= document.getElementById("{/literal}{$attribute_base}_datetime_year_{$attribute.id}{literal}");
  var month= document.getElementById("{/literal}{$attribute_base}_datetime_month_{$attribute.id}{literal}");
  var day= document.getElementById("{/literal}{$attribute_base}_datetime_day_{$attribute.id}{literal}");

  var date_array=date.split("/");

  year.value=date_array[0];
  month.value=date_array[1];
  day.value=date_array[2];

  if (calendar.dateClicked)
  {
    calendar.callCloseHandler(); // this calls "onClose" (see above)
  }
};
</script>
{/literal}

In this case im using datetime template though the code works for both.

One thing you have to adjust is the id tag for each input tag. You *must* copy the name param to an id param or the system wont be able to retreive the field and getElementByID will fail. Kristian, i dont suppose these id tags could be added to the template(s)?

I have this working in an extension but the design.ini file is doint what it should. I've added
[StylesheetSettings] and [JavaScriptSettings] but when ezdesign operator is applied it simply doesnt find it. 'ezdesign' does look inside the extensions so im puzzled about this. I resorted to putting hardcoded script lines in pagelayout. You *cannot* put script lines to include the js files into the attribute tpl file. If you have more than one attribute the script will be included more than once and cause problems.

Hope this helps!

Paul

Fraser Hore

Tuesday 20 December 2005 12:51:34 pm

Thanks for your work Paul. Unfortunately the code's not working for me. I'm using the ezdate attribute for now so i had to change the code slightly from datetime to date but it still isn't working.

Are you also having the problem where the calendar is streteched across the screen?

Fraser Hore

Tuesday 20 December 2005 1:21:26 pm

Ok, got it working. Went back to my old code and just replaced the variables with the ones from the name tag. One thing about the way mine is working now that i like is that i don't need a button. The calendar pops up no matter which field the user clicks in and and the updates all fields based on the selected date. Here's the code:

{literal}
<script type="text/javascript">
function catcalc(cal) {
var date = cal.date;
var year = document.getElementById("{/literal}{$attribute_base}_date_year_{$attribute.id}{literal}");
year.value = date.print("%Y");
var month= document.getElementById("{/literal}{$attribute_base}_date_month_{$attribute.id}{literal}");
month.value = date.print("%m");
var day= document.getElementById("{/literal}{$attribute_base}_date_day_{$attribute.id}{literal}");
day.value = date.print("%d");
};
Calendar.setup(
{
inputField : "{/literal}{$attribute_base}_date_year_{$attribute.id}{literal}",
ifFormat : "%Y",
onUpdate: catcalc
}
);
Calendar.setup(
{
inputField : "{/literal}{$attribute_base}_date_month_{$attribute.id}{literal}",
ifFormat : "%m",
onUpdate: catcalc
}
);Calendar.setup(
{
inputField : "{/literal}{$attribute_base}_date_day_{$attribute.id}{literal}",
ifFormat : "%d",
onUpdate: catcalc
}
);
</script>
{/literal}

Paul Forsyth

Wednesday 21 December 2005 1:00:34 am

Glad it works now!

Btw, are you using three calendars for the date field to fill three boxes? You should be able to use just one calendar as described with my code.

Paul

Fraser Hore

Wednesday 21 December 2005 3:14:54 am

I got your code working now Paul, thanks! I had a typo in one of my tags.

Here's the code for a ezDate attribute override:

<button type="reset" id="{concat('trigger',$attribute.id)}">...</button>

{literal}
<script type="text/javascript">
function OnSelectDate{/literal}{$attribute.id}{literal}(calendar, date)
{
var year = document.getElementById("{/literal}{$attribute_base}_date_year_{$attribute.id}{literal}");
var month= document.getElementById("{/literal}{$attribute_base}_date_month_{$attribute.id}{literal}");
var day= document.getElementById("{/literal}{$attribute_base}_date_day_{$attribute.id}{literal}");
var date_array=date.split("/"); 

year.value=date_array[0]; 
month.value=date_array[1]; 
day.value=date_array[2]; 

if (calendar.dateClicked) 
{
 calendar.callCloseHandler(); 
} 
};
Calendar.setup(
{
onSelect: OnSelectDate{/literal}{$attribute.id}{literal},
button : "trigger{/literal}{$attribute.id}{literal}"
}
);
</script>
{/literal}

Fraser Hore

Wednesday 21 December 2005 5:02:13 am

I realized that it's important to setup the calendar before the function as you did Paul. Otherwise you have to click on on the calendar date twice to get the calendar to close. So here is the right code for an ezdate attribute. I added an image instead of a button to call up the calendar. Have you had any luck in fixing the display of the calendar?

<img src={'popupcalendar_img.gif'|ezimage()} id="{concat('trigger',$attribute.id)}"
style="cursor: pointer; border: 1px solid blue;"
title="Date selector"
alt="Select Date"/>

{literal}
<script type="text/javascript">
Calendar.setup(
{
onSelect: OnSelectDate{/literal}{$attribute.id}{literal},
button : "trigger{/literal}{$attribute.id}{literal}"
}
);
function OnSelectDate{/literal}{$attribute.id}{literal}(calendar, date)
{
var year = document.getElementById("{/literal}{$attribute_base}_date_year_{$attribute.id}{literal}");
var month= document.getElementById("{/literal}{$attribute_base}_date_month_{$attribute.id}{literal}");
var day= document.getElementById("{/literal}{$attribute_base}_date_day_{$attribute.id}{literal}");
var date_array=date.split("/"); 

year.value=date_array[0]; 
month.value=date_array[1]; 
day.value=date_array[2]; 

if (calendar.dateClicked) 
{
 calendar.callCloseHandler(); 
} 
};
</script>
{/literal}

Paul Forsyth

Wednesday 21 December 2005 5:20:21 am

I dont have that problem at all. The calendar looks as it should to me. Im using firefox 1.5. Which browser are you using?

Fraser Hore

Wednesday 21 December 2005 5:15:30 pm

I'm also using Firefox 1.5. I also tried it in IE and i tried changing the sitestyle. No luck.

I've also been trying to get the time select to work for ezdatetime. So far the best i could get was by adding:

var hour= document.getElementById("{/literal}{$attribute_base}_datetime_hour_{$attribute.id}{literal}");
var minute= document.getElementById("{/literal}{$attribute_base}_datetime_minute_{$attribute.id}{literal}");

hour.value=calendar.date.getHours();
minute.value=calendar.date.getMinutes();

This will put the right time in, but it is in single digits (e.g. 1 hour 5 minutes). So 01:05 is 1 and 5.

Any ideas on how to get the time right?

Cheers,

Fraser

Fraser Hore

Wednesday 21 December 2005 11:50:04 pm

Paul Forsyth

Thursday 22 December 2005 12:29:27 am

The iformat line should give you the correct formatting.

I didnt bother with the hours and minutes because the calendar isnt able to change it - all you can do is set the current hour and minute. If i choose a calendar date of next month then only a manual hour and time change makes sense. So i left it.

What about changing the css file used for your calendar? I tested using calendar-brown.css.