The Flash Forms calendar controls can restrict selectable date ranges. Fixes dates can be specified using the startRange and endRange attributes, but what if you need to programmatically change the ranges at runtime? The following example does just that, it uses two calendar controls to prompt for start and end dates, and uses a couple of lines of ActionScript to ensure that the end date cannot be before the start date.
<cfsavecontent variable="setRangeStart">
var dtRangeStart=new Date(calStart.selectedDate);
calEnd.selectableRange={rangeStart: dtRangeStart};
</cfsavecontent>
<cfform format="flash" width="400" height="450">
<cfformgroup type="horizontal">
<cfformgroup type="vertical">
<cfformitem type="text">Start Date:</cfformitem>
<cfcalendar name="calStart" onChange="#setRangeStart#">
</cfformgroup>
<cfformgroup type="vertical">
<cfformitem type="text">End Date:</cfformitem>
<cfcalendar name="calEnd">
</cfformgroup>
</cfformgroup>
</cfform>
A live example can be viewed at http://www.forta.com/misc/flashforms/calendarrange.cfm.
Illegal usage of actionscript.
The following actionscript commands are not allowed: "import, new, delete, createChild, loadmovie, duplicateMovieClip, AttachMovie, registerclass, createTextField, __proto__".
It would make sense to use the same script with the datefield too, not?
<cfsavecontent variable="test">
loadMovie('http://livedocs.macromedia.com/flash/Samples/Acces...', here);
</cfsavecontent>
<cfform format="flash" width="800" height="650">
<cfformgroup type="horizontal">
<cfformgroup type="vertical">
<cfformitem type="text">End Date:</cfformitem>
<cfcalendar name="calEnd" onchange="#test#">
</cfformgroup>
</cfformgroup>
<cfinput type="button" name="here">
</cfform>
Best Regards,
Reto
For example.. Click on the March 31st for Start Date. On the End Date calendar, move ahead to April and you'll notice that the 26th is gone. Follow this through the calendar and you'll see it happens for every month.
http://cfpim.blogspot.com/2005/04/clock-timer-in-f...
Freedom for actionscript :D
//Pim;
How can i change also a previous set "endrange" (is setting from database) for the "calEnd"
in the same function with setRangeStart?
The problem is: if i decrease the "calStart" at runtime the value of "calEnd" persists restrict the range to the previous set "endrange".
And i can not select the new lower range with the "calEnd".
I hope you understand my bad english.
A little sample with a bad syntax:
var dtRangeStart=new Date(calStart.selectedDate);
calEnd.selectableRange={rangeStart: dtRangeStart};
!! calEnd.endrange ={rangeStart: dtRangeStart}; !!
thanks for a little help
Best Regards, jurli
Depends what do you like to do. To achive the result of the Sample from Ben you don't need to use the restricted keyword new. It works perfectly with only line:
<cfsavecontent variable="setRangeStart">
calEnd.selectableRange={rangeStart: calStart.selectedDate};
</cfsavecontent>
<cfinput type="datefield" name="calStart" onchange="{calEnd.selectableRange={rangeStart: calStart.selectedDate};}">
<cfinput type="datefield" name="calEnd">
<cfsavecontent variable="setRangeStart">
var dtRangeStart=new Date(calStart.selectedDate);
calEnd.selectableRange={rangeStart: dtRangeStart};
calEnd.selectedDate = null;
</cfsavecontent>
...and each control has the required attribute set to true. Does anyone know how to modify the validation error message for a cfcalendar object? The "message" attribute is not available...it just says "Error in calEnd text"?
Oh, and one more thing, someone asked asked about the illegal use of actionscript commands. I have found that if you do not have a space between the call and the "new" keyword (e.g. var dtRangeStart=new Date(calStart.selectedDate)), the compiler seems to ignore the new keyword. just food for thought. if you try the example above and put a space between (dtRangeStart = new), it will fail.
Note: Same EXACT <cfsavecontent>:
<cfsavecontent variable="setRangeStart">
var dtRangeStart=new Date();
calEnd.selectableRange={rangeStart: dtRangeStart};
</cfsavecontent>
(#1)
<cfform format="flash" width="400" height="450">
<cfformgroup type="horizontal">
<cfformgroup type="vertical">
<cfformitem type="text">End Date:</cfformitem>
<cfcalendar name="calEnd" onChange="#setRangeStart#">
</cfformgroup>
</cfformgroup>
</cfform>
(#2)
<cfsavecontent variable="setRangeStart">
var dtRangeStart=new Date();
calEnd.selectableRange={rangeStart: dtRangeStart};
</cfsavecontent>
<cfform format="flash" width="400" height="450">
<cfformgroup type="horizontal" width="100%"
label="Date:">
<cfinput type="datefield" align="middle" border="1"
name="calEnd" required="yes" readonly="no"
onChange="#setRangeStart#">
</cfformgroup>
</cfform>
---
(#2) results in error: Illegal usage of actionscript org.apache.oro.text.regex.Perl5Pattern@ (...etc)
Is there some way to limit the datefield to not allow selection before the current date using only one datefield ???
Much Appreciated.
From the help above I was able to make a calendar where start and end dates restircted each other. The NOW date was also used as a restriction:
<cfset datenow=dateformat(now(), 'dd/mm/yyyy') >
<cfsavecontent variable="setRangeStart">
calEnd.selectableRange={rangeStart: calStart.selectedDate};
</cfsavecontent>
<cfsavecontent variable="setRangeEnd">
calStart.selectableRange={rangeEnd: calEnd.selectedDate};
</cfsavecontent>
<cfform format="flash" width="400" height="450" >
<cfformgroup type="horizontal">
<cfformgroup type="vertical">
<cfformitem type="text">Start Date:</cfformitem>
<cfcalendar endrange="#datenow#" name="calStart" onChange="#setRangeStart#">
</cfformgroup>
<cfformgroup type="vertical">
<cfformitem type="text">End Date:</cfformitem>
<cfcalendar endrange="#datenow#" name="calEnd" onchange="#setRangeEnd#">
</cfformgroup>
</cfformgroup>
</cfform>
I have been able to achieve similar with datefields however as there is no endrange attribute I did not know how to restict the now date:
<cfform format="flash" width="400" height="450">
<cfformgroup type="horizontal">
<cfformgroup type="vertical">
<cfformitem type="text">Start Date:</cfformitem>
<cfinput type="datefield" name="calStart" mask="dd mmmm yyyy" onchange="{calEnd.selectableRange={rangeStart: calStart.selectedDate};}">
</cfformgroup>
<cfformgroup type="vertical">
<cfformitem type="text">End Date:</cfformitem>
<cfinput type="datefield" name="calEnd" mask="dd mmmm yyyy" onchange="{calStart.selectableRange={rangeEnd: calEnd.selectedDate};}">
</cfformgroup>
</cfformgroup>
</cfform>
Anyway thanks to those who have contributed above. If anyone knows how to restrict the NOW date in a datefield I would be greatful if you could post it.
Anybody have any ideas?
<cfset thisyear = dateFormat(Now(),'YYYY')>
<!--- Actionscript to handle the logic for the Datefields and select boxes --->
<cfformitem type="script">
function setRangeStart(Datename1:mx.controls.DateField, Datename2:mx.controls.DateField, EndSelect:mx.controls.ComboBox){
var dtRangeStart = Datename1.selectedDate;
Datename2.selectableRange = {rangeStart: dtRangeStart};
Datename1.displayedYear = Number(EndSelect.selectedItem.data);
_global.flag == 1;
}
function UpdateSelect(Datename1:mx.controls.DateField, select:mx.controls.ComboBox){
<!--- Jog the datefield to reduce the click lag on this update function --->
Datename1.selectedDate = Datename1.selectedDate;
<!--- splice the string to find the year --->
var year = Datename1.text.substr(6,4);
<!---alert('date: ' +year+ '', 'Alert');--->
for(var i = 0; i< select.getLength(); i ++){
select.selectedIndex = i;
if(year == select.selectedItem.data){
break; // this will terminate/exit the loop
}
}
}
function setStartYear(name:mx.controls.DateField, select:mx.controls.ComboBox){
var StartDate = '';
if(name.text != ''){
StartDate = name.text;
name.selectedDate = null;
StartDate = StartDate.substring(0, StartDate.length-4);
StartDate += select.selectedItem.data;
name.text = StartDate;
}
name.displayedYear = Number(select.selectedItem.data);
name.selectedDate = StartDate;
<!---alert('date: ' +Number(select.selectedItem.data)+ ' year: ' +name.displayedYear+ '', 'Alert');--->
}
function Datelogic(StartSelect:mx.controls.ComboBox, EndSelect:mx.controls.ComboBox, Datename2:mx.controls.DateField){
var Index = StartSelect.selectedIndex;
for(var i = 0; i< StartSelect.getLength(); i ++){
if(EndSelect.getLength() <= Index && i >= EndSelect.getLength()){
EndSelect.addItem(selectYear1.getItemAt(i));
}else{
EndSelect.removeItemAt(Index+1)
var year = Datename2.text.substr(6,4);
if(year < EndSelect.selectedItem.data && _global.flag != 1){
Datename2.selectedDate = null;
Datename2.displayedYear = Number(EndSelect.selectedItem.data);
<!---alert('second: ' +EndSelect.selectedItem.data+ '', 'Alert');--->
}
}
}
_global.flag == 0;
}
function setRangeEnd(Datename1:mx.controls.DateField, Datename2:mx.controls.DateField, StartSelect:mx.controls.ComboBox){
var dtRangeEnd = Datename1.selectedDate;
Datename2.selectableRange = {rangeEnd: dtRangeEnd};
Datename1.displayedYear = Number(StartSelect.selectedItem.data);
_global.flag == 1;
}
</cfformitem>
<cfformgroup type="horizontal" visible="yes" enabled="yes" style="marginLeft:-3;" >
<cfinput type="datefield" name="ActAfterDate" width="125" label="After Date:" bind="#form.ActAfterDate#" onChange="setRangeStart(ActAfterDate, ActBeforeDate); UpdateSelect(ActAfterDate, selectYear1); Datelogic(selectYear1, selectYear2, ActBeforeDate);">
<cfselect name="selectYear1" width="80" label="" onChange="setStartYear(ActAfterDate, selectYear1); Datelogic(selectYear1, selectYear2, ActBeforeDate); setRangeStart(ActAfterDate, ActBeforeDate);" onMouseDown="selectYear1.dropdownWidth = 90;">
<cfoutput>
<cfloop index="i" from="#thisyear#" to="2000" step="-1" >
<option value="#i#"<cfif i eq thisyear>selected</cfif>>#i#</option>
</cfloop>
</cfoutput>
</cfselect>
<cfformitem type="spacer" height="1" />
</cfformgroup>
<cfformgroup type="horizontal" visible="yes" enabled="yes" style="marginLeft:-15;" >
<cfinput type="datefield" name="ActBeforeDate" width="125" label="Before Date:" bind="#form.ActBeforeDate#" onChange="setRangeEnd(ActBeforeDate, ActAfterDate, selectYear1); UpdateSelect(ActBeforeDate, selectYear2);">
<cfselect name="selectYear2" width="80" label="" onchange="setStartYear(ActBeforeDate, selectYear2);" onMouseDown="selectYear2.dropdownWidth = 90;">
<cfoutput>
<option value="#thisyear#"selected>#thisyear#</option>
</cfoutput>
</cfselect>
</cfformgroup>
I am interested to see your post in action. I have tried however get a 500 error. Is there any actionscript in your code that may cause this.
Thanks Simon
If anyone knows of a solution to that disappearance issue, I'd love to hear it!
<!--- http://www.forta.com/blog/index.cfm?mode=e&ent... --->
<cfform format="flash" name="myForm" width="300" height="300">
<!--- this restricts the startDate and endDate to begin at today --->
<cfformgroup type="horizontal" visible="no" height="0">
<cfinput type="datefield" name="firstAvailableDate" value="#dateAdd('d',-1,now())#">
</cfformgroup>
<!--- this restricts the endDate to within 6 months (86400000 seconds in 180 days) of startDate --->
<cfformitem type="script">
function setRange()
{
var dtRangeStartDate = startDate.selectedDate;
var dt_num:Number = dtRangeStartDate.getTime();
dt_num += 86400000 * 180;
endDate.selectableRange = {rangeEnd: dt_num};
}
</cfformitem>
<!--- endDate.selectableRange = {rangeStart: dtRangeStartDate,rangeEnd: dt_num}; --->
<!--- when I set the endDate rangeStart to the startDate (and if startDate is after today but still in this month) it causes today's position to "disappear" from future months. To get around it, I set the endDate disabledRanges rangeEnd to today (from firstAvailableDate) --->
<cfinput type="datefield"
name="startDate"
label="Start Date"
onChange="setRange()"
onFocus="startDate.disabledRanges=[{rangeEnd:firstAvailableDate.selectedDate}];">
<cfinput type="datefield"
name="endDate"
label="End Date"
onFocus="endDate.disabledRanges=[{rangeEnd:firstAvailableDate.selectedDate}];">
</cfform>
Ben thanks again.
Is there a disabledDays attribute?
I only want users to be able to select a single day within the range
Say for example a range of today - 2 weeks until today + 4 weeks but only be able to select a Monday date.
thanks in advance.
tim
Do you know how to bind the startDate value to the endDate. For instance, if a user selects a week from now(), the user will be able to select days from now() and 6 months from the startDate. How can I disable the days before the startDate?
I think my problem is:
I need to bind the startDate value instead of the now() but I don't know how I can do it, in the secondAvailableDate
<cfformgroup type="horizontal" visible="no" height="0">
<cfinput type="datefield" name="secondAvailableDate" value="#dateAdd('d',0,now())#">
</cfformgroup>
<cfinput type="datefield"
name="endDate"
mask="dd/mm/yyyy"
width="100"
required="yes"
message="End date is missing."
onFocus="endDate.disabledRanges=[{rangeEnd:secondAvailableDate.selectedDate}];">
Any ideas?
Thanks for your comment to get this working on a datefield.
onChange="{SearchToField.selectableRange={rangeStart: SearchFromField.selectedDate};}"
It worked like a charm!