客户的要求(查看图片),点击Range,可以选择一个日期范围,点击Calc可以选择日期的计算,计算完后,结果会同时显示在后面的input里,可以看下图片。因为考虑到很多地方要用到,所以写到help方法里了。感觉这个东西以后还会用,估计其他的同学也有可能会用到类似的功能,所以发出来,大家看看。计算日期用ruby代码来写很方便,用js代码来写,就很麻烦。
_time_period.html.erb
<% prefix << '_' unless prefix.blank? %>
<a onclick="$('<%= prefix %>unequal').style.display=($('<%= prefix %>unequal').style.display=='none' ? '' : 'none');$('<%= prefix %>widget').style.display='none';$('<%= prefix %>change_type').value = '';$('<%= prefix %>_num').value='';$('<%= prefix %>time_type').value='';$('#<%= prefix %>big').value = '';$('<%= prefix %>less').value='';" >Range</a>
<a onclick="$('<%= prefix %>widget').style.display=($('<%= prefix %>widget').style.display=='none' ? '' : 'none');$('<%= prefix %>unequal').style.display='none';$('<%= prefix %>big').value = '';$('<%= prefix %>less').value='';$('<%= prefix %>change_type').value = '';$('<%= prefix %>time_num').value='';$('<%= prefix %>time_type').value='';" >Calc</a><span> =
<%= calendar_date_select_tag("#{prefix}equal",nil,:style => "width: 80px;",:embedded => false,:year_range => 30.years.ago..-30.years.ago) %>
</span><span id='<%= prefix %>unequal' style='display: none;'>>
<%= calendar_date_select_tag("#{prefix}big",nil,:style => "width: 80px;",:embedded => false,:year_range => 30.years.ago..-30.years.ago) %>
<
<%= calendar_date_select_tag("#{prefix}less",nil,:style => "width: 80px;",:embedded => false,:year_range => 30.years.ago..-30.years.ago ) %>
</span>
<span id='<%= prefix %>widget' style='display:none;'>
<script type="text/javascript">
var equal = $('<%= prefix %>equal');
var change_type = $('<%= prefix %>change_type');
var time_num = $('<%= prefix %>time_num');
var time_type = $('<%= prefix %>time_type');
equal.observe('change', function(event){
count_date();
});
change_type.observe('change', function(event){
count_date();
enter_equal();
});
time_num.observe('change', function(event){
count_date();
enter_equal();
});
time_type.observe('change', function(event){
count_date();
enter_equal();
});
function enter_equal(){
if($F('<%= prefix %>equal')==''){alert('Please enter a date first!');}
}
function count_date(){
if((!equal.value.blank()) && (!change_type.value.blank()) && (!time_num.value.blank()) && (!time_type.value.blank())){
var time_num_number = Number(time_num.value);
if (/^\d+$/.test(String(time_num.value)) && IsDate(equal.value)) {
var r = equal.value.match(/^(\d{1,4})([-|\/])(\d{1,2})\2(\d{1,2})$/);
var year = Number(r[1]);
var month = Number(r[3]);
var day = Number(r[4]);
if(time_type.value == 0){
$('<%= prefix %>result').value = equal.value;
} else {
if(change_type.value == 'plus' && time_type.value == 'days'){
day = day + time_num_number;
} else if (change_type.value == 'plus' && time_type.value == 'months') {
month = month + time_num_number;
} else if (change_type.value == 'plus' && time_type.value == 'years'){
year = year + time_num_number;
} else if (change_type.value == 'minus' && time_type.value == 'days'){
day = day - time_num_number;
} else if (change_type.value == 'minus' && time_type.value == 'months'){
month = month - time_num_number;
} else if (change_type.value == 'minus' && time_type.value == 'years'){
year = year - time_num_number;
}
var result = correct_date(Number(year),Number(month),Number(day));
$('<%= prefix %>result').value = result;
}
} else {
$('<%= prefix %>result').value = '';
}
} else {
$('<%= prefix %>result').value = '';
}
}
</script>
<select id='<%= prefix %>change_type' style='width: 80px;'>
<option value=''>(+/-)</option>
<option value='plus'>+</option>
<option value='minus'>-</option>
</select>
<%= text_field_tag("#{prefix}time_num",nil,:style => 'width: 80px;' ) %>
<select id='<%= prefix %>time_type' style='width: 80px;' >
<option value=''>(d/m/y)</option>
<option value='days'>Days</option>
<option value='months'>Months</option>
<option value='years'>Years</option>
</select>
<input type='text' readonly='readonly' id='<%= prefix %>result' value='' size=10 />
</span>
<%= render :partial => 'time_period',:locals => { :prefix => ''} %>
//匹配//yyyy-mm-dd || yyyy/mm/dd
function IsDate(str)
{
var r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);
if(r==null)return false; var d = new Date(r[1], r[3]-1, r[4]);
return (d.getFullYear()==r[1]&&(d.getMonth()+1)==r[3]&&d.getDate()==r[4]);
}
//修正日期
//这里一直想不到很好的实现方法
function correct_date(year,month,day){
var stand_day = day_max(year,month);
if(day > stand_day){
day = day - stand_day;
month = month + 1;
}
if(month > 12){
month = month - 12;
year = year + 1;
}
if(day <= 0){
var last_stand_day = day_max(year, month - 1);
month = month - 1;
day = day + last_stand_day;
}
if(month <= 0){
month = month + 12;
year = year - 1;
}
if(year <= 0){
alert('invalid year!');
return false;
}
var str_month = (month >= 10) ? String(month) : '0'+ String(month);
var str_day = (day >= 10) ? String(day) : '0'+ String(day);
var str = String(year)+'-'+str_month+'-'+str_day;
if(IsDate(str)){
return str;
} else {
return correct_date(year,month,day);
}
}
//当月的最大日期
function day_max(year,month){
if(month==4 || month==6 || month==9 || month==11){
return 30;
} else if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){
return 31;
} else {
if(isleap(year)){
return 29;
} else {
return 28;
}
}
}
//是否是闰年
function isleap(year){
return (year % 4 == 0 || (year % 100 == 0 && year % 400 == 0))
}
关于这段js代码,其实一直在后台有ruby实现的,相对而言,简单很多
if params[:change_type] == "plus"
date = params[:equal].to_date + params[:time_num].to_i
elsif params[:change_type] == "minus"
date = params[:equal].to_date - params[:time_num].to_i
end
if params[:change_type] == "plus"
date = date.months_since(params[:time_num].to_i)
elsif params[:change_type] == "minus"
date = date.months_ago(params[:time_num].to_i)
end
但是考虑到,如果用js的话,可以避免多余的和后台通信,而且以后复用的话,不用在加很多代码。
关于这段js日期计算,冥冥之中感觉应该还有比较更好的写法,对js日期这块不熟悉,希望有经验的能提出意见。
就是他了,year,month,day在这里其实每次只有一个值在变,但是变化的范围不确定。
//修正日期
function correct_date(year,month,day){
var stand_day = day_max(year,month);
if(day > stand_day){
day = day - stand_day;
month = month + 1;
}
if(month > 12){
month = month - 12;
year = year + 1;
}
if(day <= 0){
var last_stand_day = day_max(year, month - 1);
month = month - 1;
day = day + last_stand_day;
}
if(month <= 0){
month = month + 12;
year = year - 1;
}
if(year <= 0){
alert('invalid year!');
return false;
}
var str_month = (month >= 10) ? String(month) : '0'+ String(month);
var str_day = (day >= 10) ? String(day) : '0'+ String(day);
var str = String(year)+'-'+str_month+'-'+str_day;
if(IsDate(str)){
return str;
} else {
return correct_date(year,month,day);
}
}