|
Calendar alteration; Month and Year selected by dropdown box
05-21-2010, 08:54 PM
|
Calendar alteration; Month and Year selected by dropdown box
|
Posts: 37
|
I'm using the calender as found by http://www.softcomplex.com/products/tigra_calendar/ for inputting of birthdate; However I'm trying to convert it so that a drop down box is used for the month and year rather than clicking the arrows. I'm fairly new to Javascript and learning a lot but I can't seem to find a way to do this. There are some theories used that I don't understand yet.
Anyone have the time to convert this script for a drop down box? I'm sure I would learn a lesson or two from the code you come up with because I've been trying for hours.
Here is the .js files with my modifications so far:
PHP Code:
// Tigra Calendar v4.0.3 (01/12/2009) American (mm/dd/yyyy) // http://www.softcomplex.com/products/tigra_calendar/ // Public Domain Software... You're welcome.
// default settins var A_TCALDEF = { 'months' : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 'weekdays' : ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], 'yearscroll': true, // show year scroller 'weekstart': 0, // first day of week: 0-Su or 1-Mo 'centyear' : 70, // 2 digit years less than 'centyear' are in 20xx, othewise in 19xx. 'imgpath' : '_images/cal/' // directory with calendar images } // date parsing function function f_tcalParseDate (s_date) {
var re_date = /^\s*(\d{1,2})\/(\d{1,2})\/(\d{2,4})\s*$/; if (!re_date.exec(s_date)) return alert ("Invalid date: '" + s_date + "'.\nAccepted format is mm/dd/yyyy.") var n_day = Number(RegExp.$2), n_month = Number(RegExp.$1), n_year = Number(RegExp.$3); if (n_year < 100) n_year += (n_year < this.a_tpl.centyear ? 2000 : 1900); if (n_month < 1 || n_month > 12) return alert ("Invalid month value: '" + n_month + "'.\nAllowed range is 01-12."); var d_numdays = new Date(n_year, n_month, 0); if (n_day > d_numdays.getDate()) return alert("Invalid day of month value: '" + n_day + "'.\nAllowed range for selected month is 01 - " + d_numdays.getDate() + "."); return new Date (n_year, n_month - 1, n_day); } // date generating function function f_tcalGenerDate (d_date) { //Set Birthdate field to green and good before returning value setRegisterField ("birthdate", "valid"); // Set birthdate to valid checkFormSubmittable(); // Enable submit button if all is good return ( (d_date.getMonth() < 9 ? '0' : '') + (d_date.getMonth() + 1) + "/" + (d_date.getDate() < 10 ? '0' : '') + d_date.getDate() + "/" + d_date.getFullYear() ); }
// implementation function tcal (a_cfg, a_tpl) { // apply default template if not specified if (!a_tpl) a_tpl = A_TCALDEF;
// register in global collections if (!window.A_TCALS) window.A_TCALS = []; if (!window.A_TCALSIDX) window.A_TCALSIDX = []; this.s_id = a_cfg.id ? a_cfg.id : A_TCALS.length; window.A_TCALS[this.s_id] = this; window.A_TCALSIDX[window.A_TCALSIDX.length] = this; // assign methods this.f_show = f_tcalShow; this.f_hide = f_tcalHide; this.f_toggle = f_tcalToggle; this.f_update = f_tcalUpdate; this.f_relDate = f_tcalRelDate; this.f_parseDate = f_tcalParseDate; this.f_generDate = f_tcalGenerDate; // create calendar icon this.s_iconId = 'tcalico_' + this.s_id; this.e_icon = f_getElement(this.s_iconId); if (!this.e_icon) { document.write('<img src="' + a_tpl.imgpath + 'cal.gif" id="' + this.s_iconId + '" onclick="A_TCALS[\'' + this.s_id + '\'].f_toggle()" class="tcalIcon" alt="Open Calendar" />'); this.e_icon = f_getElement(this.s_iconId); } // save received parameters this.a_cfg = a_cfg; this.a_tpl = a_tpl; }
function f_tcalShow (d_date) {
setRegisterField ("birthdate", "invalid"); // find input field if (!this.a_cfg.controlname) throw("TC: control name is not specified"); if (this.a_cfg.formname) { var e_form = document.forms[this.a_cfg.formname]; if (!e_form) throw("TC: form '" + this.a_cfg.formname + "' can not be found"); this.e_input = e_form.elements[this.a_cfg.controlname]; } else this.e_input = f_getElement(this.a_cfg.controlname);
if (!this.e_input || !this.e_input.tagName || this.e_input.tagName != 'INPUT') throw("TC: element '" + this.a_cfg.controlname + "' does not exist in " + (this.a_cfg.formname ? "form '" + this.a_cfg.controlname + "'" : 'this document'));
// Ensure color status of Birthdate field is current if (this.e_input.value) {setRegisterField ("birthdate", "valid") }; if (!this.e_input.value) {setRegisterField ("birthdate", "invalid") };
//alert (this.e_input.value);
// dynamically create HTML elements if needed this.e_div = f_getElement('tcal'); if (!this.e_div) { this.e_div = document.createElement("DIV"); this.e_div.id = 'tcal'; document.body.appendChild(this.e_div); } this.e_shade = f_getElement('tcalShade'); if (!this.e_shade) { this.e_shade = document.createElement("DIV"); this.e_shade.id = 'tcalShade'; document.body.appendChild(this.e_shade); } this.e_iframe = f_getElement('tcalIF') if (b_ieFix && !this.e_iframe) { this.e_iframe = document.createElement("IFRAME"); this.e_iframe.style.filter = 'alpha(opacity=0)'; this.e_iframe.id = 'tcalIF'; this.e_iframe.src = this.a_tpl.imgpath + 'pixel.gif'; document.body.appendChild(this.e_iframe); } // hide all calendars f_tcalHideAll();
// generate HTML and show calendar this.e_icon = f_getElement(this.s_iconId); if (!this.f_update()) return;
this.e_div.style.visibility = 'visible'; this.e_shade.style.visibility = 'visible'; if (this.e_iframe) this.e_iframe.style.visibility = 'visible';
// change icon and status this.e_icon.src = this.a_tpl.imgpath + 'no_cal.gif'; this.e_icon.title = 'Close Calendar'; this.b_visible = true; }
function f_tcalHide (n_date) { if (n_date) this.e_input.value = this.f_generDate(new Date(n_date));
// no action if not visible if (!this.b_visible) return;
// hide elements if (this.e_iframe) this.e_iframe.style.visibility = 'hidden'; if (this.e_shade) this.e_shade.style.visibility = 'hidden'; this.e_div.style.visibility = 'hidden'; // change icon and status this.e_icon = f_getElement(this.s_iconId); this.e_icon.src = this.a_tpl.imgpath + 'cal.gif'; this.e_icon.title = 'Open Calendar'; this.b_visible = false; }
function f_tcalToggle () { return this.b_visible ? this.f_hide() : this.f_show(); }
function f_tcalUpdate (d_date) { var d_today = this.a_cfg.today ? this.f_parseDate(this.a_cfg.today) : f_tcalResetTime(new Date()); var d_selected = this.e_input.value == '' ? (this.a_cfg.selected ? this.f_parseDate(this.a_cfg.selected) : d_today) : this.f_parseDate(this.e_input.value);
// figure out date to display if (!d_date) // selected by default d_date = d_selected; else if (typeof(d_date) == 'number') // get from number d_date = f_tcalResetTime(new Date(d_date)); else if (typeof(d_date) == 'string') // parse from string this.f_parseDate(d_date); if (!d_date) return false;
// first date to display var d_firstday = new Date(d_date); d_firstday.setDate(1); d_firstday.setDate(1 - (7 + d_firstday.getDay() - this.a_tpl.weekstart) % 7); var a_class, s_html = '<table class="ctrl"><tbody><tr><select name="monthPick" '; //alert ("here: " + A_TCALDEF.months[1]); for (loop = 0; loop<12; loop++) {
s_html += '<option value="' + loop + '">' + A_TCALDEF.months[loop] + '</option>' } s_html += '</select><select name = "yearPick" ' + this.f_relDate(d_date, 1, 'y')
for (loop = 1900; loop<2000; loop++) { s_html += '<option value="' + loop + '">' + loop + '</option>' } s_html += '</select>'
//+'<select><option>September</option><option>October</option>' //+ '<select><option>2009</option><option>2008</option'// + d_date.getFullYear()
+ '</tr></tbody></table><table><tbody><tr class="wd">';
/* var a_class, s_html = '<table class="ctrl"><tbody><tr>' + (this.a_tpl.yearscroll ? '<td' + this.f_relDate(d_date, -1, 'y') + ' title="Previous Year"><img src="' + this.a_tpl.imgpath + 'prev_year.gif" /></td>' : '') + '<td' + this.f_relDate(d_date, -1) + ' title="Previous Month"><img src="' + this.a_tpl.imgpath + 'prev_mon.gif" /></td><th>' + this.a_tpl.months[d_date.getMonth()] + ' ' + d_date.getFullYear() + '</th><td' + this.f_relDate(d_date, 1) + ' title="Next Month"><img src="' + this.a_tpl.imgpath + 'next_mon.gif" /></td>' + (this.a_tpl.yearscroll ? '<td' + this.f_relDate(d_date, 1, 'y') + ' title="Next Year"><img src="' + this.a_tpl.imgpath + 'next_year.gif" /></td></td>' : '') + '</tr></tbody></table><table><tbody><tr class="wd">'; */
// print weekdays titles for (var i = 0; i < 7; i++) s_html += '<th>' + this.a_tpl.weekdays[(this.a_tpl.weekstart + i) % 7] + '</th>'; s_html += '</tr>' ;
// print calendar table var n_date, n_month, d_current = new Date(d_firstday); while (d_current.getMonth() == d_date.getMonth() || d_current.getMonth() == d_firstday.getMonth()) { // print row heder s_html +='<tr>'; for (var n_wday = 0; n_wday < 7; n_wday++) {
a_class = []; n_date = d_current.getDate(); n_month = d_current.getMonth();
// other month if (d_current.getMonth() != d_date.getMonth()) a_class[a_class.length] = 'othermonth'; // weekend if (d_current.getDay() == 0 || d_current.getDay() == 6) a_class[a_class.length] = 'weekend'; // today if (d_current.valueOf() == d_today.valueOf()) a_class[a_class.length] = 'today'; // selected if (d_current.valueOf() == d_selected.valueOf()) a_class[a_class.length] = 'selected';
s_html += '<td onclick="A_TCALS[\'' + this.s_id + '\'].f_hide(' + d_current.valueOf() + ')"' + (a_class.length ? ' class="' + a_class.join(' ') + '">' : '>') + n_date + '</td>'
d_current.setDate(++n_date); while (d_current.getDate() != n_date && d_current.getMonth() == n_month) { d_current.setHours(d_current.getHours + 1); d_current = f_tcalResetTime(d_current); } } // print row footer s_html +='</tr>'; } s_html +='</tbody></table>'; // update HTML, positions and sizes this.e_div.innerHTML = s_html;
var n_width = this.e_div.offsetWidth; var n_height = this.e_div.offsetHeight; var n_top = f_getPosition (this.e_icon, 'Top') + this.e_icon.offsetHeight; var n_left = f_getPosition (this.e_icon, 'Left') - n_width + this.e_icon.offsetWidth; if (n_left < 0) n_left = 0; this.e_div.style.left = n_left + 'px'; this.e_div.style.top = n_top + 'px';
this.e_shade.style.width = (n_width + 8) + 'px'; this.e_shade.style.left = (n_left - 1) + 'px'; this.e_shade.style.top = (n_top - 1) + 'px'; this.e_shade.innerHTML = b_ieFix ? '<table><tbody><tr><td rowspan="2" colspan="2" width="6"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td width="7" height="7" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_tr.png\', sizingMethod=\'scale\');"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td></tr><tr><td height="' + (n_height - 7) + '" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_mr.png\', sizingMethod=\'scale\');"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td></tr><tr><td width="7" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_bl.png\', sizingMethod=\'scale\');"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_bm.png\', sizingMethod=\'scale\');" height="7" align="left"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_br.png\', sizingMethod=\'scale\');"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td></tr><tbody></table>' : '<table><tbody><tr><td rowspan="2" width="6"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td rowspan="2"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td width="7" height="7"><img src="' + this.a_tpl.imgpath + 'shade_tr.png"></td></tr><tr><td background="' + this.a_tpl.imgpath + 'shade_mr.png" height="' + (n_height - 7) + '"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td></tr><tr><td><img src="' + this.a_tpl.imgpath + 'shade_bl.png"></td><td background="' + this.a_tpl.imgpath + 'shade_bm.png" height="7" align="left"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td><img src="' + this.a_tpl.imgpath + 'shade_br.png"></td></tr><tbody></table>'; if (this.e_iframe) { this.e_iframe.style.left = n_left + 'px'; this.e_iframe.style.top = n_top + 'px'; this.e_iframe.style.width = (n_width + 6) + 'px'; this.e_iframe.style.height = (n_height + 6) +'px'; } return true; }
function f_getPosition (e_elemRef, s_coord) { var n_pos = 0, n_offset, e_elem = e_elemRef;
while (e_elem) { n_offset = e_elem["offset" + s_coord]; n_pos += n_offset; e_elem = e_elem.offsetParent; } // margin correction in some browsers if (b_ieMac) n_pos += parseInt(document.body[s_coord.toLowerCase() + 'Margin']); else if (b_safari) n_pos -= n_offset; e_elem = e_elemRef; while (e_elem != document.body) { n_offset = e_elem["scroll" + s_coord]; if (n_offset && e_elem.style.overflow == 'scroll') n_pos -= n_offset; e_elem = e_elem.parentNode; } return n_pos; }
function f_tcalRelDate (d_date, d_diff, s_units) { var s_units = (s_units == 'y' ? 'FullYear' : 'Month'); var d_result = new Date(d_date); d_result['set' + s_units](d_date['get' + s_units]() + d_diff); if (d_result.getDate() != d_date.getDate()) d_result.setDate(0); return ' onclick="A_TCALS[\'' + this.s_id + '\'].f_update(' + d_result.valueOf() + ')"'; }
function f_tcalHideAll () { for (var i = 0; i < window.A_TCALSIDX.length; i++) window.A_TCALSIDX[i].f_hide(); }
function f_tcalResetTime (d_date) { d_date.setHours(0); d_date.setMinutes(0); d_date.setSeconds(0); d_date.setMilliseconds(0); return d_date; }
f_getElement = document.all ? function (s_id) { return document.all[s_id] } : function (s_id) { return document.getElementById(s_id) };
if (document.addEventListener) window.addEventListener('scroll', f_tcalHideAll, false); if (window.attachEvent) window.attachEvent('onscroll', f_tcalHideAll); // global variables var s_userAgent = navigator.userAgent.toLowerCase(), re_webkit = /WebKit\/(\d+)/i; var b_mac = s_userAgent.indexOf('mac') != -1, b_ie5 = s_userAgent.indexOf('msie 5') != -1, b_ie6 = s_userAgent.indexOf('msie 6') != -1 && s_userAgent.indexOf('opera') == -1; var b_ieFix = b_ie5 || b_ie6, b_ieMac = b_mac && b_ie5, b_safari = b_mac && re_webkit.exec(s_userAgent) && Number(RegExp.$1) < 500;
The CSS file and images remain the same, although the arrows are not used anymore. My notes so far from what I've figured out:
calling "this.f_relDate(d_date, -1)" will return text of a javascript command including the ONCLICK=" " tag to set the calender back a day. the "-1" can be changed to go back more than one day, likewise the - can be removed to go forward. It affects years if you call this.f_relDate(d_date, -1, "y").
My idea was to have an ONCHANGE event handler on the SELECT list box which takes the current year displayed and subtracts the current setting on the listbox and calls the above mentioned function with the correct offset to get the calender to the date selected.
The concept thats confusing me is all the use of "this". I don't understand where "this" is coming from, I know how to use "this" and that it changes with the environment and situation that you use it in. However it's not clear to me how these functions are originally being called. I've tried replacing "this" with different objects to try and hit on the origin but it doesn't work so I know I haven't got the right object that "this" represents.
Any takers? I could learn from the solution I am sure of it!
|
|
|
|
05-21-2010, 10:52 PM
|
Re: Calendar alteration; Month and Year selected by dropdown box
|
Posts: 1,712
Name: Jeremy Miller
Location: Las Vegas, NV
|
Forgive me for ignoring your code, but I didn't want to spend the time to see what you changed and wanted to make sure that what I created would work as an extension to the base code. I downloaded the code and made a few changes which are described here.
First, if you download the code and look at sample1.html, I added a few options to the constructor to help us as can be seen here.
Code:
var current_date = new Date();
new tcal ({
// form name
'formname': 'testform',
// input name
'controlname': 'testinput',
//Change title navigation to select boxes
'titlenavigation': 'select',
//When titlenavigation==select, then allow min, max years
'titlenavigationminyear': current_date.getFullYear(),
'titlenavigationmaxyear': current_date.getFullYear() + 5
});
I decided not to remove the left/right navigation options, but to change the title to allow users to select the month and year, while displaying the current month/year. In the code above, I use the current year as the minimum year and 5 years from this year as the maximum year (giving 6 entries total for the year dropdown).
I then went under the assign method section of the constructor and created ids for the month and year dropdowns that I planned to create and assigned a function to catch when those dropdowns changed. That's this code:
Code:
this.f_titleNavChange = f_tcalTitleNavChange;
this.f_tcalMonthId = 'tcalmonth_' + this.s_id;
this.f_tcalYearId = 'tcalyear_' + this.s_id;
You'll notice that tcal is a function, but it is treated as an object. That's something javascript does. Because of the assign method section, the other functions become members of that object, so "this" refers to the instance of the tcal object, allowing us to retain the configuration values and other variables over multiple instances.
After that, I went in to find where the title was output and found it where the "this.a_tpl.months[current_month] + ' ' + current_year" code was. Because I needed to remove that code if the titlenavigation configuration value was set as "select", I turned it into a variable and then created the dropdowns with classnames so that you can style them via the stylesheet (those classnames are tcalMonth and tcalYear, respectively). Here's the code that generates the dropdowns:
Code:
var current_month = d_date.getMonth();
var current_year = d_date.getFullYear();
var title_navigation_code = this.a_tpl.months[current_month] + ' ' + current_year;
var min_year = parseInt(this.a_cfg.titlenavigationminyear);
var max_year = parseInt(this.a_cfg.titlenavigationmaxyear);
if (this.a_cfg.titlenavigation == 'select' && min_year > 1970 && max_year > 1970 && min_year < max_year) {
title_navigation_code = '<select class="tcalMonth" id="' + this.f_tcalMonthId + '" onChange="A_TCALS[\'' + this.s_id + '\'].f_titleNavChange();">';
for(var i=0;i<A_TCALDEF.months.length;i++) {
title_navigation_code += '<option value="' + i + '"' + (i == current_month?' SELECTED':'') + '>' + A_TCALDEF.months[i] + '</option>';
}
title_navigation_code += '</select>';
title_navigation_code += ' <select class="tcalYear" id="' + this.f_tcalYearId + '" onChange="A_TCALS[\'' + this.s_id + '\'].f_titleNavChange();">';
for(i=min_year;i<=max_year;i++) {
title_navigation_code += '<option value="' + i + '"' + (i == current_year?' SELECTED':'') + '>' + i + '</option>';
}
title_navigation_code += '</select>';
}
The variable "title_navigation_code" then contained either just the month/year if the user did not have the configuration value set and dropdowns if it was set, the years for min and max were greater than 1970, and the max date was greater than the min date.
NOTE: I kept the methodology of the base script, but it's more prudent to use DOM methods to create HTML entities on a page -- I'll leave that to you as an exercise, but should you choose to ignore that, the script will still work.
The last step (before testing) was to create the navigation change function. Because I had assigned id vlaues
Code:
// title navigation function
function f_tcalTitleNavChange () {
var target_date = new Date(document.getElementById(this.f_tcalYearId).options[document.getElementById(this.f_tcalYearId).options.selectedIndex].value, document.getElementById(this.f_tcalMonthId).options[document.getElementById(this.f_tcalMonthId).options.selectedIndex].value);
this.f_update(target_date);
}
All that function does is create a new date based on the selected month and year and then call the native f_update function with the new date to update the display.
And, that was all there was to it (  ).
I've attached the 2 files (I did not update the other files that use different languages).
Enjoy and hopefully the explanation helps you (and others) learn. 
__________________
Jeremy Miller
Please login or register to view this content. Registration is FREE
|
|
|
|
05-22-2010, 03:45 AM
|
Re: Calendar alteration; Month and Year selected by dropdown box
|
Posts: 37
|
Hi,
Thanks so much, I've implemented the code and see that it works.. Now I will have to take some time and go through it and try and grasp these concepts behind how and why.
|
|
|
|
|
« Reply to Calendar alteration; Month and Year selected by dropdown box
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|