/////////////////////////////////////////////////////// // // localendar.com - Common.js // /////////////////////////////////////////////////////// var ppcIE =((navigator.appName == "Microsoft Internet Explorer") || ((navigator.appName == "Netscape") && (parseInt(navigator.appVersion)==5))); var ppcNN6 =((navigator.appName == "Netscape") && (parseInt(navigator.appVersion)==5)); var ppcNN =((navigator.appName == "Netscape")&&(document.layers)) ; var posX = 4; var posY = 4; var now = new Date(); //"<= startDate >"); var eventWindow; function today() { var result = "" var d = new Date(); var curr_date = d.getDate(); var curr_month = d.getMonth(); curr_month++; var curr_year = (d.getFullYear()+"").substring(2,4); if (curr_month<10) result+="0"; result += curr_month + "-"; if (curr_date<10) result+="0"; result+=curr_date + "-" + curr_year; return result } function getPos(atImg) { // MO: Using jQuery to get position 2/1/10 var position=$('#'+atImg).offset(); posX=position.left; posY=position.top; /* if ( ppcIE ) { posX = getOffsetLeft(document.images[atImg]); posY = getOffsetTop(document.images[atImg]) + document.images[atImg].height; } else if (ppcNN) { posX = document.images[atImg].x; posY = document.images[atImg].y + document.images[atImg].height; } */ } function fn_chg_color(lcfield,pcolor){ fn_chk_color(lcfield,pcolor); } function fn_chk_color(lcfield,pcolor){ var numStr = "0123456789ABCDEFabcdef"; if (pcolor.length==0) return true; for (i = 0; i < pcolor.length; i++) { thisChar = pcolor.charAt(i); if (numStr.indexOf(thisChar) == -1){ $.Zebra_Dialog("Please enter a valid six character hexidecimal color value.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcfield.value = ''; return false; } } if (pcolor.length!=6){ $.Zebra_Dialog("Please enter a valid six character hexidecimal color value.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcfield.value = ''; return false; } lcfield.value = pcolor; return true; } function validateNewUser(lcform){ var retval = true; if (( !isEmail(lcform)) /*|| (!isLocation(lcform))*/ || (! isName(lcform)) || (! checkPassword(lcform)) || (! checkAgree(lcform)) || (!checkTimezone(lcform)) ){ retval=false; } else { if (lcform.country.value=="USA") retval = checkZip(lcform); else retval = checkCountry(lcform) } return retval; } function checkSelect(lcform){ var w = eval("document." + lcform.name + ".event_category"); var count = 0; for (var x = 0; x < w.length; x++) { if (lcform.event_category[x].checked) { count++ } } if (count == 0 ) { $.Zebra_Dialog("Please select at least one category", { 'type': 'error', 'overlay_opacity': .5, 'title': 'No Categories Selected' }); lcform.event_category[0].focus(); return false; } return true; } function category_check(lcform,pvalue){ var w = eval("document." + lcform.name + ".event_category"); for (var x = 0; x < w.length; x++) { if (pvalue == 'all'){ w[x].checked = true; }else { w[x].checked = false; } } } function popup(info){ var view_window; var lcf; info=info.toUpperCase(); if (info=="HELP") lcf="FAQ"; if (info=="LEGAL") lcf="Legal"; if (info=="A1CLEGAL") lcf="A1CLEGAL"; if (info=="PRIVACY") lcf="Privacy"; if (info=="A1CPRIVACY") lcf="A1CPRIVACY"; // if (info=="PRINTCAL") lcf="PrintableCalendar"; view_window = window.open("/elsie?JSP="+lcf+"&context=None", "localendar", "width=500,height=500,scrollbars=yes,resizable=yes"); view_window.focus(); } function popupEventAdd() { view_window = window.open("/elsie?JSP=EventEditorAnon", "localendar", "width=545,height=550,menubar=yes,scrollbars=yes,resizable=yes"); } function popupPrintableCalendar() { var view_window = window.open("/elsie?JSP=PrintableCalendar&context=None", "printablelocalendar", "toolbar=yes,menubar=yes,width=700,height=600,scrollbars=yes,resizable=yes"); view_window.focus(); } function lc_navjump(p_direction,p_menutype,p_startdate){ window.location.href="/elsie?JSP=Calendar&mode=MONTH_"+p_direction+"&menu_type="+p_menutype+"&start_date="+p_startdate; } function lc_dayjump(p_menutype,p_date){ window.location.href="/elsie?JSP=Calendar&menu_type="+p_menutype+"&start_date="+p_date; } function lc_weekjump(p_menutype,p_date){ window.location.href="/elsie?JSP=Calendar&menu_type="+p_menutype+"&start_date="+p_date; } function lc_monthjump(p_menutype,p_date){ window.location.href="/elsie?JSP=Calendar&menu_type="+p_menutype+"&start_date="+p_date; } function lc_yearjump(p_menutype,p_date){ window.location.href="/elsie?JSP=Calendar&menu_type="+p_menutype+"&start_date="+p_date; } /* function lc_publishjump(p_menutype,p_date,p_calendarid,p_rsslink){ window.location.href="/elsie?JSP=PublishedCalendar&mode=PUBLISH_PUBLIC&search_type="+p_menutype+"&start_date="+p_date+"&calendar_id="+p_calendarid+"&rss_link="+p_rsslink; } */ function lc_searchjump(p_lat,p_lon,p_radius,p_date,p_type){ window.location.href="/elsie?JSP=SearchResults&mode=ADVSEARCH&member_lat="+p_lat+"&member_long="+p_lon+"&radius="+p_radius+"&start_date="+p_date+"&search_type="+p_type; } function lc_pubsearchjump(p_lat,p_lon,p_radius,p_date,p_type){ window.location.href="/elsie?JSP=PublishedSearch&mode=PUBSEARCH&membar_lat="+p_lat+"&member_long="+p_lon+"&radius="+p_radius+"&start_date="+p_date+"&search_type="+p_type; } function HelpWindow(vers){ var view_window; view_window = window.open(('https:' == document.location.protocol ? 'https://' : 'http://')+"www.localendar.com/docs/display/lc"); view_window.title = "FAQ"; view_window.focus(); } function AddEvent(eventDate){ var target = "/elsie?DAM=EventEditor"; if (eventDate!=null){ target+="&eventDate="+eventDate; } window.location.href= target; } function Preferences(){ window.location.href="/elsie?JSP=PreferencesGeneral" } function Search(){ window.location.href="/elsie?JSP=Search" } function PublicEventDetail(m, calendar_id,event_id,more_info,exportDate,category) { if (eventWindow){ eventWindow.close(); } var dualScreenLeft = window.screenLeft != undefined ? window.screenLeft : screen.left; var dualScreenTop = window.screenTop != undefined ? window.screenTop : screen.top; var left = ((screen.width / 2) - (400 / 2)) + dualScreenLeft; var top = ((screen.height / 2) - (510 / 2)) + dualScreenTop; eventWindow = window.open(('https:' == document.location.protocol ? 'https://' : 'http://')+"localendar.com/event?DAM=PublishedEvent&m="+m+"&event_id="+event_id+"&calendar_id="+calendar_id+"&more_info="+more_info+"&export_date="+exportDate+"&category="+category, "previewevent", "scrollbars=yes,resizable=yes,width=400, height=510, top=" + top + ", left=" + left); if (window.focus) { eventWindow.focus(); } } function zipSearchSubmit(lcform) { var c = lcform.city.value; if (c.length < 3) { $.Zebra_Dialog("Please enter at least the first 3 characters of the city", { 'type': 'warning', 'overlay_opacity': .5, 'title': 'Insufficient Information' }); return false; } return true; } function checkAdvSearch(lcform) { var addressOK = ""; addressOK = $('#member_lat').val(); if (addressOK==null || addressOK=="" || addressOK=="null"){ $.Zebra_Dialog("Please provide a valid geographic location for searching", { 'type': 'warning', 'overlay_opacity': .5, 'title': 'Insufficient Information' }); return false; } else { return true; } } function prefsGeneralSubmit(lcform) { if (checkDayViewRange(lcform)) return true; else return false; } function isNumber(data) { var numStr = "0123456789"; for (i = 0; i < data.length; i++) { thisChar = data.charAt(i); if (numStr.indexOf(thisChar) == -1) return false; } return true; } function checkCountry(lcform) { if (lcform.country.value=="---"){ $.Zebra_Dialog("Please select your country", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); return false; } else return true; } function checkTimezone(lcform) { if (lcform.timezone.value=="---"){ $.Zebra_Dialog("Please select your timezone", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); return false; } else return true; } function checkZip(lcform) { var zipcode = lcform.zip.value; if (zipcode!="00000"&& ((!isNumber(zipcode)) || zipcode == "" || zipcode.length != 5) ) { $.Zebra_Dialog("Please enter a valid 5 digit zipcode", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.zip.focus(); return false; } return true; } function checkDayViewRange(lcform) { var dayStart = lcform.dayStart.selectedIndex+1; var dayEnd = lcform.dayEnd.selectedIndex+1; if (dayEnd<=dayStart) { $.Zebra_Dialog("Please make sure the day-view 'To:' hour is later than the 'From:' hour.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.dayStart.focus(); return false; } return true; } // if you put one space in then it passes function checkSubject(lcform) { var subject = lcform.event_title.value; if (subject == "") { $.Zebra_Dialog("You must supply a title for this event", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.event_title.select(); return false; } return true; } function checkChangeMemberLogon(lcform) { var str = lcform.username.value; // Return false if characters are not a-z, A-Z, or 1-9. for (var i = 0; i < str.length; i++) { var ch = str.substring(i, i + 1); if (((ch < "a" || "z" < ch) && (ch < "A" || "Z" < ch) && (ch < "0" || "9" < ch)) || ch ==' ' && ch != '.') { if (ch!='_' && ch!='-') { $.Zebra_Dialog("The Account name may only consist of letters & numbers (spaces are not allowed).

Please change your Account name.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.username.select(); lcform.username.focus(); return false; } } } return true; } function isName(lcform) { var str = lcform.username.value; // Return false if name field is blank. if (str == "") { $.Zebra_Dialog("The Account Name is blank.

Please enter your Account name.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.username.focus(); return false; } return checkChangeMemberLogon(lcform); } function isEmail(lcform) { // Return false if e-mail field is blank. var str = lcform.email.value; if (str == "") { $.Zebra_Dialog("The Email Address is blank.

Please enter your email address.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.email.focus(); return false; } // Return false if e-mail field does not contain a '@' and '.' . if (str.indexOf ('@',0) == -1 || str.indexOf ('.',0) == -1){ $.Zebra_Dialog("Please enter a valid email address.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.email.select(); lcform.email.focus(); return false; } return true; } function isLocation(lcform) { // Return false if e-mail field is blank. var str = lcform.member_location_desc.value; if (str == "") { $.Zebra_Dialog("Please enter a valid location.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.member_phys_address.focus(); return false; } return true; } function checkPassword(lcform) { var pw1 = lcform.password.value; var pw2 = lcform.confirmpw.value; // Return false if pw don't match. if (lcform.password.value == "") { $.Zebra_Dialog("The Password field is blank.

Please enter your password.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.password.focus(); return false; } if (lcform.confirmpw.value == "") { $.Zebra_Dialog("The Re-Enter Password field is blank.

Please enter your password again in the Re-Enter Password field.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.confirmpw.focus(); return false; } if (pw1 != pw2) { $.Zebra_Dialog("The Passwords you entered do not match.

Please check your entries.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.password.select(); lcform.password.focus(); return false; } if (pw1.length<6) { $.Zebra_Dialog("Please enter a password that is at least 6 characters long.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.password.select(); lcform.password.focus(); return false; } // Return false if characters are not '0-9' or '.' . for (var i = 0; i < pw1.length; i++) { var ch = pw1.substring(i, i + 1); if (((ch < "a" || "z" < ch) && (ch < "A" || "Z" < ch) && (ch < "0" || "9" < ch)) || ch ==' ' && ch != '.') { if (ch!='_' && ch!='-') { $.Zebra_Dialog("The Password field only accepts letters & numbers (spaces are not allowed).

Please change your password.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.password.select(); lcform.password.focus(); return false; } } } return true; } function checkChangePassword(lcform) { var old_pw = lcform.password.value; var new_pw1 = lcform.newpassword.value; var new_pw2 = lcform.confirmpw.value; if (old_pw == "") { $.Zebra_Dialog("The Password field is blank.

Please enter your password.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.password.focus(); return false; } if (new_pw2 == "") { $.Zebra_Dialog("The Confirm Password field is blank.

Please enter your password again in the Confirm Password field.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.confirmpw.focus(); return false; } if (new_pw1 != new_pw2) { $.Zebra_Dialog("The Passwords you entered do not match.

Please check your entries.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.newpassword.select(); lcform.newpassword.focus(); return false; } if (new_pw1.length<6) { $.Zebra_Dialog("Please enter a password that is at least 6 characters long.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.password.select(); lcform.password.focus(); return false; } // Return false if characters are not '0-9' or '.' . for (var i = 0; i < new_pw1.length; i++) { var ch = new_pw1.substring(i, i + 1); if (((ch < "a" || "z" < ch) && (ch < "A" || "Z" < ch) && (ch < "0" || "9" < ch)) || ch ==' ' && ch != '.') { if (ch!='_' && ch!='-') { $.Zebra_Dialog("The Password field only accepts letters & numbers (spaces are not allowed).

Please change your password.", { 'type': 'error', 'overlay_opacity': .5, 'title': 'Validation Error' }); lcform.newpassword.select(); lcform.newpassword.focus(); return false; } } } return true; } function checkAgree(lcform) { if (!lcform.agree.checked) { $.Zebra_Dialog("Please indicate that you accept the Terms of Service", { 'type': 'warning', 'overlay_opacity': .5, 'title': 'Message' }); lcform.agree.focus(); return false; } return true; } function EditEvent(event_id,event_public,repeatsCode,eventDate) { if (repeatsCode!=null && repeatsCode!="N") { $.Zebra_Dialog('This is a repeating event. Do you want to edit the series, or just this occurrence?', { 'type': 'question', 'overlay_opacity': .5, 'title': 'Edit Repeating Event', 'buttons': ['Edit the Series','Edit this Occurrence'], 'onClose': function(caption) { if (caption=="Edit the Series") window.location.href="/elsie?DAM=EventEditor&event_id="+event_id+"&public_event="+event_public; else if (caption=="Edit this Occurrence") window.location.href="/elsie?DAM=EventEditor&event_id="+event_id+"&public_event="+event_public+"&occur=Y&odate="+eventDate; } }); } else window.location.href="/elsie?DAM=EventEditor&event_id="+event_id+"&public_event="+event_public; } function getRestaurants(zipcode) { var view_window; view_window = window.open("http://www.usrg.com/script/nearzip.asp?ZIP="+zipcode,"localendar","width=800,height=500,scrollbars=yes,resizable=yes"); view_window.focus(); } function trim(strValue) { var intLoop=0; for(intLoop=0; intLoop=0; intLoop=strValue.length-1) { if(strValue.charAt(intLoop)==" ") strValue=strValue.substring(0,intLoop); else break; } return strValue; } function AnonAddInfo() { var view_window; view_window = window.open("/elsie?JSP=AnonAddInfo", "localendar", "width=475,height=565,scrollbars=no,resizable=yes"); view_window.focus(); } // Geo-Encoding functions function hideGeoAlerts(panel){ var prefix = ""; if (panel==0){ // Event Location prefix="event"; } else if (panel==1){ // Weather Location prefix="weather"; } else if (panel==2){ // Member Location prefix="member" } $("#"+prefix+"_location_chooser").hide(); $("#"+prefix+"_location_valid").hide(); $("#"+prefix+"_location_invalid").hide(); $("#"+prefix+"_location_none").hide(); $("#"+prefix+"_lat").val(""); $("#"+prefix+"_long").val(""); $("#"+prefix+"_location_desc").val(""); } function geocodeAddress(panel){ var prefix = ""; if (panel==0){ // Event Location prefix="event"; } else if (panel==1){ // Weather Location prefix="weather"; } else if (panel==2){ // Member Location prefix="member" } hideGeoAlerts(panel); $("#"+prefix+"_geoList").empty(); var address = $("#"+prefix+"_phys_address").val(); jQuery.support.cors = true; $.getJSON("https://maps.googleapis.com/maps/api/geocode/json",{address:address,sensor:"false"}, function(data) { if (data.results.length>0) { geoData = data; if (geoData.results.length>1){ $("#"+prefix+"_geoList").append($("") .attr("value",-1) .text("-- Please select --") ); } for (i=0;i") .attr("value",i) .text(data.results[i].formatted_address) ); } } else { geoData=null; } if (geoData==null){ $("#"+prefix+"_location_none").show(); } else if (geoData.results.length==1){ storeLatLong({value:"0"},panel) $("#"+prefix+"_location_valid").show(); } else if (geoData.results.length>1) { $("#"+prefix+"_location_chooser").show(); } }); } function storeLatLong(obj,panel){ var prefix = ""; if (panel==0){ // Event Location prefix="event"; } else if (panel==1){ // Weather Location prefix="weather"; } else if (panel==2){ // Member Location prefix="member" } if (obj.value==-1){ $("#"+prefix+"_location_valid").hide(); $("#"+prefix+"_lat").val(""); $("#"+prefix+"_long").val(""); $("#"+prefix+"_location_desc").val(""); } else { $("#"+prefix+"_lat").val(geoData.results[obj.value].geometry.location.lat); $("#"+prefix+"_long").val(geoData.results[obj.value].geometry.location.lng); var desc = $("#"+prefix+"_geoList option:selected").text(); if (""==desc){ desc = $("#"+prefix+"_phys_address").val(); } $("#"+prefix+"_location_desc").val(desc); $("#"+prefix+"_location_valid").html("Location valid
("+$("#"+prefix+"_location_desc").val()+")"); $("#"+prefix+"_location_valid").show(); } } // // Task-related functions // function addTask() { window.location.href="/elsie?DAM=EventEditor" } function deleteTask(index) { $.Zebra_Dialog("Are you sure you want to delete entry\n\""+taskList[index].title+"\" ?", { 'type': 'question', 'overlay_opacity': .5, 'title': 'Delete Task?', 'buttons': ['Delete','Cancel'], 'onClose': function(caption) { if (caption=="Delete"){ window.location.href="/elsie?DAM=TaskEditor&task_id="+taskList[index].tId+"&action=D"; } } }); } function editTask(task_id) { window.location.href="/elsie?DAM=TaskEditor&task_id="+task_id; } function checkDate(objName) { var strDatestyle = "US"; //United States style //var strDatestyle = "EU"; //European style var strDate; var strDateArray; var strDay; var strMonth; var strYear; var intDay; var intMonth; var intYear; var booFound = false; var datefield = objName; var strSeparatorArray = new Array("-"," ","/","."); var intElementNr; var err = 0; var strMonthArray = new Array(12); strMonthArray[0] = "Jan"; strMonthArray[1] = "Feb"; strMonthArray[2] = "Mar"; strMonthArray[3] = "Apr"; strMonthArray[4] = "May"; strMonthArray[5] = "Jun"; strMonthArray[6] = "Jul"; strMonthArray[7] = "Aug"; strMonthArray[8] = "Sep"; strMonthArray[9] = "Oct"; strMonthArray[10] = "Nov"; strMonthArray[11] = "Dec"; strDate = datefield.value; if (strDate.length < 1) { return false; } for (intElementNr = 0; intElementNr < strSeparatorArray.length; intElementNr++) { if (strDate.indexOf(strSeparatorArray[intElementNr]) != -1) { strDateArray = strDate.split(strSeparatorArray[intElementNr]); if (strDateArray.length != 3) { err = 1; return false; } else { strDay = strDateArray[0]; strMonth = strDateArray[1]; strYear = strDateArray[2]; } booFound = true; } } if (booFound == false) { if (strDate.length>5) { strDay = strDate.substr(0, 2); strMonth = strDate.substr(2, 2); strYear = strDate.substr(4); } } if (strYear.length == 2) { strYear = '20' + strYear; } // US style if (strDatestyle == "US") { strTemp = strDay; strDay = strMonth; strMonth = strTemp; } intDay = parseInt(strDay, 10); if (isNaN(intDay)) { err = 2; return false; } intMonth = parseInt(strMonth, 10); if (isNaN(intMonth)) { for (i = 0;i<12;i++) { if (strMonth.toUpperCase() == strMonthArray[i].toUpperCase()) { intMonth = i+1; strMonth = strMonthArray[i]; i = 12; } } if (isNaN(intMonth)) { err = 3; return false; } } intYear = parseInt(strYear, 10); if (isNaN(intYear)||strYear.length<2) { err = 4; return false; } if (intMonth>12 || intMonth<1) { err = 5; return false; } if ((intMonth == 1 || intMonth == 3 || intMonth == 5 || intMonth == 7 || intMonth == 8 || intMonth == 10 || intMonth == 12) && (intDay > 31 || intDay < 1)) { err = 6; return false; } if ((intMonth == 4 || intMonth == 6 || intMonth == 9 || intMonth == 11) && (intDay > 30 || intDay < 1)) { err = 7; return false; } if (intMonth == 2) { if (intDay < 1) { err = 8; return false; } if (LeapYear(intYear) == true) { if (intDay > 29) { err = 9; return false; } } else { if (intDay > 28) { err = 10; return false; } } } // if (strDatestyle == "US") // datefield.value = strMonthArray[intMonth-1] + " " + intDay+" " + strYear; // else // datefield.value = intDay + " " + strMonthArray[intMonth-1] + " " + strYear; if(objName.name.toLowerCase()=="duedate") { $("#todo [name=month]").val(intMonth); $("#todo [name=day]").val(intDay); $("#todo [name=year]").val(intYear); } else if(objName.name.toLowerCase()=="duedate") { document.addform.skipdate.value=intMonth+"/"+intDay+"/"+strYear } return true; } function LeapYear(intYear) { if (intYear % 100 == 0) { if (intYear % 400 == 0) { return true; } } else { if ((intYear % 4) == 0) { return true; } } return false; } /*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("'); f = window.self.document.getElementById(id); } return f; }; /** * Configure a given WCH object to be displayed on top of the given element. * Optionally, a second element can be passed, and in this case it will setup * the WCH object to cover both elements. * * @param f [HTMLIFrame] the WCH object * @param el [HTMLElement] the element to cover. * @param el2 [HTMLElement, optional] another element to cover. */ Zapatec.Utils.setupWCH_el = function(f, el, el2) { if (f) { var pos = Zapatec.Utils.getAbsolutePos(el), X1 = pos.x, Y1 = pos.y, X2 = X1 + el.offsetWidth, Y2 = Y1 + el.offsetHeight; if (el2) { var p2 = Zapatec.Utils.getAbsolutePos(el2), XX1 = p2.x, YY1 = p2.y, XX2 = XX1 + el2.offsetWidth, YY2 = YY1 + el2.offsetHeight; if (X1 > XX1) X1 = XX1; if (Y1 > YY1) Y1 = YY1; if (X2 < XX2) X2 = XX2; if (Y2 < YY2) Y2 = YY2; } Zapatec.Utils.setupWCH(f, X1, Y1, X2-X1, Y2-Y1); } }; /** * Configure a WCH object to cover a certain part of the screen. * * @param f [HTMLIFrame] the WCH object. * @param x [number] the X coordinate. * @param y [number] the Y coordinate. * @param w [number] the width of the area. * @param h [number] the height of the area. */ Zapatec.Utils.setupWCH = function(f, x, y, w, h) { if (f) { var s = f.style; (typeof x != "undefined") && (s.left = x + "px"); (typeof y != "undefined") && (s.top = y + "px"); (typeof w != "undefined") && (s.width = w + "px"); (typeof h != "undefined") && (s.height = h + "px"); s.visibility = "inherit"; } }; /** * Hide a WCH object. * * @param f [HTMLIFrame] object to hide. */ Zapatec.Utils.hideWCH = function(f) { if (f) f.style.visibility = "hidden"; }; //@} /// \defgroup Scroll-with-window functions //@{ /** * A generic Utils function that returns the current scroll position. * */ Zapatec.Utils.getPageScrollY = function() { return window.pageYOffset || document.documentElement.scrollTop || (document.body ? document.body.scrollTop : 0) || 0; }; // Object setup. Zapatec.ScrollWithWindow = {}; Zapatec.ScrollWithWindow.list = []; // Set to a number between 0 and 1, lower means longer scrolling. Zapatec.ScrollWithWindow.stickiness = 0.25; /** * Registers a given object to have its style.top set equal to the window * scroll position as the browser scrolls. * * @param node [HTMLElement] -- a reference to the node to scroll. */ Zapatec.ScrollWithWindow.register = function(node) { var top = parseInt(node.style.top) || 0; var scrollY = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop || 0; top -= scrollY; if (top < 0) top = 0; Zapatec.ScrollWithWindow.list[Zapatec.ScrollWithWindow.list.length] = { node: node, origTop: top }; }; /** * Unregisters a given object. * * @param node [HTMLElement] -- a reference to the node to scroll. */ Zapatec.ScrollWithWindow.unregister = function(node) { for (var count = 0; count < Zapatec.ScrollWithWindow.list.length; count++) { var elm = Zapatec.ScrollWithWindow.list[count]; if (node == elm.node) { Zapatec.ScrollWithWindow.list.splice(count, 1); return; } } }; /** * \internal Called each time the window is scrolled to set objects' positions. * * @param newScrollY [number] -- the new window scroll position. */ Zapatec.ScrollWithWindow.handler = function(newScrollY) { // Move oldScrollY towards newScrollY, evening up if the difference is small. oldScrollY += ((newScrollY - oldScrollY) * this.stickiness); if (Math.abs(oldScrollY - newScrollY) <= 1) oldScrollY = newScrollY; for (var count = 0; count < Zapatec.ScrollWithWindow.list.length; count++) { var elm = Zapatec.ScrollWithWindow.list[count]; var node = elm.node; if (!elm.origTop) { elm.origTop = Zapatec.Utils.getAbsolutePos(node).y; node.style.position = 'absolute'; } node.style.top = elm.origTop + parseInt(oldScrollY) + 'px'; } }; // Processed scroll position & Event hook. var oldScrollY = Zapatec.Utils.getPageScrollY(); setInterval( 'var newScrollY = Zapatec.Utils.getPageScrollY(); ' + 'if (newScrollY != oldScrollY) { ' + 'Zapatec.ScrollWithWindow.handler(newScrollY); ' + '}', 50); //@} /** * Destroys the given element (remove it from the DOM tree) if it's not null * and it's parent is not null. * * @param el [HTMLElement] the element to destroy. */ Zapatec.Utils.destroy = function(el) { if (el && el.parentNode) el.parentNode.removeChild(el); }; /** * Opens a new window at a certain URL and having some properties. * * @param url [string] the URL to open a new window to. * @param windowName [string] the name of the new window (as for target attribute). * @param width [number] the width of the new window in pixels. * @param height [number] the height of the new window in pixels. * @param scrollbars [string] "yes" or "no" for scrollbars. * * @return [object] the new window */ Zapatec.Utils.newCenteredWindow = function(url, windowName, width, height, scrollbars){ var leftPosition = 0; var topPosition = 0; if (screen.width) leftPosition = (screen.width - width)/2; if (screen.height) topPosition = (screen.height - height)/2; var winArgs = 'height=' + height + ',width=' + width + ',top=' + topPosition + ',left=' + leftPosition + ',scrollbars=' + scrollbars + ',resizable'; var win = window.open(url,windowName,winArgs); return win; }; /** * Finds the size of the current web page. This is the usable size * and does not include the browser's menu and buttons. * * @return [object] dimension with the height and width of the window */ Zapatec.Utils.getWindowSize = function() { var winH = document.body.clientHeight || document.documentElement.clientHeight || window.innerHeight || 0; var winW = document.body.clientWidth || document.documentElement.clientWidth || window.innerWidth || 0; var dimension = {}; dimension.height = winH; dimension.width = winW; return dimension; } /** * Given a reference to a select element, this function will select the option * having the given value and optionally will call the default handler for * "onchange". * * @param sel [HTMLSelectElement] reference to the SELECT element. * @param val [string] the value that we should select. * @param call_default [boolean] true if the default onchange should be called. */ Zapatec.Utils.selectOption = function(sel, val, call_default) { var a = sel.options, i, o; for (i = a.length; --i >= 0;) { o = a[i]; o.selected = (o.val == val); } sel.value = val; if (call_default) { if (typeof sel.onchange == "function") sel.onchange(); else if (typeof sel.onchange == "string") eval(sel.onchange); } }; /** * A more flexible way to get the "nextSibling" of a given element. If the * "tag" argument is passed, then this function will return the next sibling * that has a certain tag. Otherwise it will simply return el.nextSibling. * * @param el [HTMLElement] reference to the anchor element. * @param tag [string] the tag name of the returned node. * @param alternateTag [string] the alternate tag name of the returned node. * * @return [HTMLElement or null] el.nextSibling if tag is not passed, or the * first element after el having the specified tag. Null is returned if no * element could be found. */ Zapatec.Utils.getNextSibling = function(el, tag, alternateTag) { el = el.nextSibling; if (!tag) { return el; } tag = tag.toLowerCase(); if (alternateTag) alternateTag = alternateTag.toLowerCase(); while (el) { if (el.nodeType == 1 && (el.tagName.toLowerCase() == tag || (alternateTag && el.tagName.toLowerCase() == alternateTag))) { return el; } el = el.nextSibling; } return el; }; /** * Similar to Zapatec.Utils.getNextSibling(), this function will return the * first child of the given element that has a specified tag. * * @param el [HTMLElement] reference to the anchor element. * @param tag [string] the tag name of the returned node. * @param alternateTag [string] the alternate tag name of the returned node. * * @return [HTMLElement] reference to the found node, or null if none could be * found. */ Zapatec.Utils.getFirstChild = function(el, tag, alternateTag) { el = el.firstChild; if (!tag) { return el; } tag = tag.toLowerCase(); if (el.nodeType == 1) { if (el.tagName.toLowerCase() == tag) { return el; } else if (alternateTag) { alternateTag = alternateTag.toLowerCase(); if (el.tagName.toLowerCase() == alternateTag) { return el; } } } return Zapatec.Utils.getNextSibling(el, tag, alternateTag); }; /** * Similar to the DOM's built in insertBefore. * Insert a node after an existing node. * * @param el [oldNode] The existing element * @param el [newNode] the new element to insert after the old one. * */ Zapatec.Utils.insertAfter = function(oldNode, newNode) { if(oldNode.nextSibling) { oldNode.parentNode.insertBefore(newNode, oldNode.nextSibling); } else { oldNode.parentNode.appendChild(newNode); } } Zapatec.Utils._ids = {}; /**< [number, static] maintains a list of generated IDs */ /** * Generates an unique ID, for a certain code (let's say "class"). If the * optional "id" argument is passed, then it just returns the id for that code * (no generation). This function is sometimes useful when we need to create * elements and be able to access them later by ID. * * @param code [string] the class of ids. User defined, can be anything. * @param id [string, optional] specify if the ID is already known. * * @return [string] the unique ID */ Zapatec.Utils.generateID = function(code, id) { if (typeof id == "undefined") { if (typeof this._ids[code] == "undefined") this._ids[code] = 0; id = ++this._ids[code]; } return "zapatec-" + code + "-" + id; }; /** * Add a tooltip to the specified element. * * Function that adds a custom tooltip for an element. The "target" is the * element to where the tooltip should be added to, and the "tooltip" is a DIV * that contains the tooltip text. Optionally, the tooltip DIV can have the * "title" attribute set; if so, its value will be displayed highlighted as * the title of the tooltip. * * @param target reference to or ID of the target element * @param tooltip reference to or ID of the tooltip content element */ Zapatec.Utils.addTooltip = function(target, tooltip) { return new Zapatec.Tooltip(target, tooltip); }; Zapatec.isLite=true; Zapatec.Utils.checkActivation = function() { return true; /* if (!Zapatec.isLite) return true; var bWizard=false; var arrProducts=[]; var ii; var scripts = document.getElementsByTagName('script'); for(ii = 0; ii < scripts.length; ii++) { if (/src\/calendar.js/i.test(scripts[ii].src)) arrProducts["calendar"]=true else if (/src\/menu.js/i.test(scripts[ii].src)) arrProducts["menu"]=true else if (/src\/tree.js/i.test(scripts[ii].src)) arrProducts["tree"]=true if (/wizard.js/i.test(scripts[ii].src)) bWizard=true } var bProduct=false; for (ii in arrProducts) if (arrProducts[ii]) { bProduct=true break } // Is a product even being used? if (!bProduct) return true; if (bWizard) return true; var anchors = document.getElementsByTagName('A'); for(ii = 0; ii < anchors.length; ii++) if (/(dev|www)\.zapatec\.com/i.test(anchors[ii].href)) return true; var strMsg=""; strMsg='You are using the Free version of the Zapatec Software.\n'+ 'While using the Free version, a link to www.zapatec.com in this page is required.' if (arrProducts["calendar"]) strMsg+='\nTo purchase the Zapatec Calendar visit www.zapatec.com/website/main/products/prod1/.' if (arrProducts["menu"]) strMsg+='\nTo purchase the Zapatec Menu visit www.zapatec.com/website/main/products/prod2/.' if (arrProducts["tree"]) strMsg+='\nTo purchase the Zapatec Tree visit www.zapatec.com/website/main/products/prod3/.' alert(strMsg) return false; */ } // Browser sniffing /// detect Opera browser Zapatec.is_opera = /opera/i.test(navigator.userAgent); /// detect a special case of "web browser" Zapatec.is_ie = ( /msie/i.test(navigator.userAgent) && !Zapatec.is_opera ); /// detect IE5.0/Win Zapatec.is_ie5 = ( Zapatec.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); /// detect IE for Macintosh Zapatec.is_mac_ie = ( /msie.*mac/i.test(navigator.userAgent) && !Zapatec.is_opera ); /// detect KHTML-based browsers Zapatec.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); /// detect Konqueror Zapatec.is_konqueror = /Konqueror/i.test(navigator.userAgent); /// detect Gecko Zapatec.is_gecko = /Gecko/i.test(navigator.userAgent); /** * Simulation of call() function that is missing in IE 5.0 */ if (!Function.prototype.call) { Function.prototype.call = function () { var self = arguments[0]; self._this_func = this; var args = new Array(); for (var i=1; i < arguments.length; i++) { args[args.length] = 'arguments[' + i + ']'; } var ret = eval('self._this_func(' + args.join(',') + ')'); self._this_func = null; return ret; }; } /** * Simulation of array functions that are missing in IE 5.0 */ if (!Array.prototype.pop) { Array.prototype.pop = function() { var last; if (this.length) { last = this[this.length - 1]; this.length -= 1; } return last; }; } if (!Array.prototype.push) { Array.prototype.push = function() { for (var i = 0; i < arguments.length; ++i) { this[this.length] = arguments[i]; } return this.length; }; } if (!Array.prototype.shift) { Array.prototype.shift = function() { var first; if (this.length) { first = this[0]; for (var i = 0; i < this.length - 1; ++i) { this[i] = this[i + 1]; } this.length -= 1; } return first; }; } if (!Array.prototype.unshift) { Array.prototype.unshift = function() { if (arguments.length) { var i, len = arguments.length; for (i = this.length + len - 1; i >= len; --i) { this[i] = this[i - len]; } for (i = 0; i < len; ++i) { this[i] = arguments[i]; } } return this.length; }; } if (!Array.prototype.splice) { Array.prototype.splice = function(index, howMany) { var elements = [], removed = [], i; for (i = 2; i < arguments.length; ++i) { elements.push(arguments[i]); } for (i = index; (i < index + howMany) && (i < this.length); ++i) { removed.push(this[i]); } for (i = index + howMany; i < this.length; ++i) { this[i - howMany] = this[i]; } this.length -= removed.length; for (i = this.length + elements.length - 1; i >= index + elements.length; --i) { this[i] = this[i - elements.length]; } for (i = 0; i < elements.length; ++i) { this[index + i] = elements[i]; } return removed; }; } /* * The Zapatec DHTML Calendar * * Copyright (c) 2004 by Zapatec, Inc. * http://www.zapatec.com * 1700 MLK Way, Berkeley, California, * 94709, U.S.A. * All rights reserved. * * Main Calendar file. Creates a popup or flat calendar with various options. * * Original version written by Mihai Bazon, * http://www.bazon.net/mishoo/calendar.epl */ // $Id: calendar.js 1040 2005-11-08 00:31:11Z ken $ /** * The Calendar object constructor. Call it, for example, like this: * * \code * // the following function is called when a date is clicked * function selFunc(cal) { * alert(cal.date); * } * // the following function is called when the calendar should be closed * function closeFunc(cal) { * cal.destroy(); * } * var cal = new Zapatec.Calendar(1, new Date(), selFunc, closeFunc); * \endcode * * The above creates a new Calendar object. The Calendar isn't displayed * instantly; using the "cal" variable, the programmer can now set certain * configuration variables, hook his own event handlers and then display the * calendar using Zapatec.Calendar.create(). * * @param firstDayOfWeek [int] the first day of week (0 for Sun, 1 for Mon, ...) * @param dateStr [string or Date] a string to be the default date, or a reference to a Date object * @param onSelected [function] this function will be called when a date is selected * @param onClose [function] this is called when the calendar should be closed */ Zapatec.Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) { // member variables this.bShowHistoryEvent=false; // did the History event on Today fire? this.activeDiv = null; this.currentDateEl = null; this.getDateStatus = null; this.getDateToolTip = null; this.getDateText = null; this.timeout = null; this.onSelected = onSelected || null; this.onClose = onClose || null; this.onFDOW = null; this.dragging = false; this.hidden = false; this.minYear = 1970; this.maxYear = 2050; this.minMonth = 0; this.maxMonth = 11; this.dateFormat = Zapatec.Calendar.i18n("DEF_DATE_FORMAT"); this.ttDateFormat = Zapatec.Calendar.i18n("TT_DATE_FORMAT"); this.historyDateFormat = "%B %d, %Y"; this.isPopup = true; this.weekNumbers = true; this.noGrab = false; if (Zapatec.Calendar.prefs.fdow || (Zapatec.Calendar.prefs.fdow == 0)) { this.firstDayOfWeek = parseInt(Zapatec.Calendar.prefs.fdow, 10); } else { var fd = 0; if (typeof firstDayOfWeek == "number") { fd = firstDayOfWeek; } else if (typeof Zapatec.Calendar._FD == 'number') { fd = Zapatec.Calendar._FD; } this.firstDayOfWeek = fd; } this.showsOtherMonths = false; this.dateStr = dateStr; this.showsTime = false; this.sortOrder = "asc"; //Sort for multiple dates in ascending order this.time24 = true; this.timeInterval = null; //step for changing time this.yearStep = 2; this.hiliteToday = true; this.multiple = null; // HTML elements this.table = null; this.element = null; this.tbody = new Array(); //array of rows of months this.firstdayname = null; // Combo boxes this.monthsCombo = null; // months this.hilitedMonth = null; this.activeMonth = null; this.yearsCombo = null; // years this.hilitedYear = null; this.activeYear = null; this.histCombo = null; // history this.hilitedHist = null; // Information this.dateClicked = false; this.numberMonths = 1; //number of months displayed this.controlMonth = 1; //the number of month with all the combos to control the date this.vertical = false; //vertical or horizontal positioning of months this.monthsInRow = 1; //number of months in one row this.titles = new Array(); //array of titles for the months this.rowsOfDayNames = new Array(); //array of rows of day names // one-time initializations Zapatec.Calendar._initSDN(); }; /** * \internal This function is called from the constructor, only once, to * initialize some internal arrays containing translation strings. It is also * called from the calendar wizard in order to reconfigure the calendar with a * language different than the initially selected one. */ Zapatec.Calendar._initSDN = function() { if (typeof Zapatec.Calendar._TT._SDN == "undefined") { // table of short day names if (typeof Zapatec.Calendar._TT._SDN_len == "undefined") Zapatec.Calendar._TT._SDN_len = 3; var ar = []; for (var i = 8; i > 0;) { ar[--i] = Zapatec.Calendar._TT._DN[i].substr(0, Zapatec.Calendar._TT._SDN_len); } Zapatec.Calendar._TT._SDN = ar; // table of short month names if (typeof Zapatec.Calendar._TT._SMN_len == "undefined") Zapatec.Calendar._TT._SMN_len = 3; ar = []; for (var i = 12; i > 0;) { ar[--i] = Zapatec.Calendar._TT._MN[i].substr(0, Zapatec.Calendar._TT._SMN_len); } Zapatec.Calendar._TT._SMN = ar; } }; /** * Translate a string according to the currently loaded language table. The * \em type variable can be null or missing, or can have one of the following * values: "dn", "sdn", "mn", "smn". * * -# if \em type is null or missing, the given \em str will be looked up in * the translation table. If a value is found, it is returned. Otherwise, * the string is looked up in the English table (if present). If still not * found, the value of \em str itself is returned. * -# if \em type is passed, then the value of \em str is looked up in one of * the following internal arrays, depending on the value of \em type: * - DN (day name) * - SDN (short day name) * - MN (month name) * - SMN (short month name) * * @param str [string] ID of translation text (can be the English text) * @param type [string, optional] domain to search through * * @return the translation according to the current language. */ Zapatec.Calendar.i18n = function(str, type) { var tr = ''; if (!type) { // normal _TT request if (Zapatec.Calendar._TT) tr = Zapatec.Calendar._TT[str]; if (!tr && Zapatec.Calendar._TT_en) tr = Zapatec.Calendar._TT_en[str]; } else switch(type) { case "dn" : tr = Zapatec.Calendar._TT._DN[str]; break; case "sdn" : tr = Zapatec.Calendar._TT._SDN[str]; break; case "mn" : tr = Zapatec.Calendar._TT._MN[str]; break; case "smn" : tr = Zapatec.Calendar._TT._SMN[str]; break; } if (!tr) tr = "" + str; return tr; }; // ** constants /// "static", needed for event handlers. Zapatec.Calendar._C = null; /// preferences Zapatec.Calendar.prefs = { fdow : null, /**< when NULL we will use the options passed at Zapatec.Calendar.setup */ history : "", /**< keeps the history as one big string */ sortOrder : "asc", /**< Sort order for multiple dates. Ascending by default */ hsize : 9 /**< maximum history size (number of stored items) */ }; // BEGIN: CALENDAR STATIC FUNCTIONS /** * Writes the preferences cookie. */ Zapatec.Calendar.savePrefs = function() { // FIXME: should we make the domain, path and expiration time configurable? // I guess these defaults are right though.. Zapatec.Utils.writeCookie("ZP_CAL", Zapatec.Utils.makePref(this.prefs), null, '/', 30); }; /** * Loads the preference cookie and merges saved prefs to Zapatec.Calendar.prefs. */ Zapatec.Calendar.loadPrefs = function() { var txt = Zapatec.Utils.getCookie("ZP_CAL"), tmp; if (txt) { tmp = Zapatec.Utils.loadPref(txt); if (tmp) Zapatec.Utils.mergeObjects(this.prefs, tmp); } // FIXME: DEBUG! //this.prefs.history = "1979/03/08,1976/12/28,1978/08/31,1998/09/21"; //this.prefs.history = null; }; /** * \internal Adds a set of events to make some element behave like a button. * * @param el [HTMLElement] reference to your element. */ Zapatec.Calendar._add_evs = function(el) { var C = Zapatec.Calendar; Zapatec.Utils.addEvent(el, "mouseover", C.dayMouseOver); Zapatec.Utils.addEvent(el, "mousedown", C.dayMouseDown); Zapatec.Utils.addEvent(el, "mouseout", C.dayMouseOut); if (Zapatec.is_ie) Zapatec.Utils.addEvent(el, "dblclick", C.dayMouseDblClick); }; /** * \internal This function undoes what Zapatec.Calendar._add_evs did, therefore * unregisters the event handlers. * * @param el [HTMLElement] reference to your element. */ Zapatec.Calendar._del_evs = function(el) { var C = this; Zapatec.Utils.removeEvent(el, "mouseover", C.dayMouseOver); Zapatec.Utils.removeEvent(el, "mousedown", C.dayMouseDown); Zapatec.Utils.removeEvent(el, "mouseout", C.dayMouseOut); if (Zapatec.is_ie) Zapatec.Utils.removeEvent(el, "dblclick", C.dayMouseDblClick); }; /** * Given an HTML element, this function determines if it's part of the "months" * combo box and if so it returns the element containing the month name. * * @param el [HTMLElement] some element (usually that triggered onclick) * @return [HTMLElement] element with the month */ Zapatec.Calendar.findMonth = function(el) { if (typeof el.month != "undefined") { return el; } else if (el.parentNode && typeof el.parentNode.month != "undefined") { return el.parentNode; } return null; }; /** Similar to findMonth() but for the history combo. */ Zapatec.Calendar.findHist = function(el) { if (typeof el.histDate != "undefined") { return el; } else if (el.parentNode && typeof el.parentNode.histDate != "undefined") { return el.parentNode; } return null; }; /** Similar to the above functions, but for the years combo. */ Zapatec.Calendar.findYear = function(el) { if (typeof el.year != "undefined") { return el; } else if (el.parentNode && typeof el.parentNode.year != "undefined") { return el.parentNode; } return null; }; /** * This function displays the months combo box. It doesn't need any parameters * because it uses the static _C variable which maintains a reference to the * last calendar that was clicked in the page. */ Zapatec.Calendar.showMonthsCombo = function () { var cal = Zapatec.Calendar._C; if (!cal) { return false; } var cd = cal.activeDiv; var mc = cal.monthsCombo; var date = cal.date, MM = cal.date.getMonth(), YY = cal.date.getFullYear(), min = (YY == cal.minYear), max = (YY == cal.maxYear); for (var i = mc.firstChild; i; i = i.nextSibling) { var m = i.month; Zapatec.Utils.removeClass(i, "hilite"); Zapatec.Utils.removeClass(i, "active"); Zapatec.Utils.removeClass(i, "disabled"); i.disabled = false; if ((min && m < cal.minMonth) || (max && m > cal.maxMonth)) { Zapatec.Utils.addClass(i, "disabled"); i.disabled = true; } if (m == MM) Zapatec.Utils.addClass(cal.activeMonth = i, "active"); } var s = mc.style; s.display = "block"; if (cd.navtype < 0) s.left = cd.offsetLeft + "px"; else { var mcw = mc.offsetWidth; if (typeof mcw == "undefined") // Konqueror brain-dead techniques mcw = 50; s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px"; } s.top = (cd.offsetTop + cd.offsetHeight) + "px"; cal.updateWCH(mc); }; /** * Same as the above, this function displays the history combo box for the * active calendar. */ Zapatec.Calendar.showHistoryCombo = function() { var cal = Zapatec.Calendar._C, a, h, i, cd, hc, s, tmp, div; if (!cal) return false; hc = cal.histCombo; while (hc.firstChild) hc.removeChild(hc.lastChild); if (Zapatec.Calendar.prefs.history) { a = Zapatec.Calendar.prefs.history.split(/,/); i = 0; while (tmp = a[i++]) { tmp = tmp.split(/\//); h = Zapatec.Utils.createElement("div"); h.className = Zapatec.is_ie ? "label-IEfix" : "label"; h.histDate = new Date(parseInt(tmp[0], 10), parseInt(tmp[1], 10)-1, parseInt(tmp[2], 10), tmp[3] ? parseInt(tmp[3], 10) : 0, tmp[4] ? parseInt(tmp[4], 10) : 0); h.appendChild(window.document.createTextNode(h.histDate.print(cal.historyDateFormat))); hc.appendChild(h); if (h.histDate.dateEqualsTo(cal.date)) Zapatec.Utils.addClass(h, "active"); } } cd = cal.activeDiv; s = hc.style; s.display = "block"; s.left = Math.floor(cd.offsetLeft + (cd.offsetWidth-hc.offsetWidth)/2) + "px"; s.top = (cd.offsetTop + cd.offsetHeight) + "px"; cal.updateWCH(hc); cal.bEventShowHistory=true; // Set state the we DID enter History event }; /** * Displays the years combo box for the active calendar. The "fwd" parameter * tells it if it should display future (right) or past (left) years. * * @param fwd [boolean] true if it's for the right combo (future), false * otherwise. */ Zapatec.Calendar.showYearsCombo = function (fwd) { var cal = Zapatec.Calendar._C; if (!cal) { return false; } var cd = cal.activeDiv; var yc = cal.yearsCombo; if (cal.hilitedYear) { Zapatec.Utils.removeClass(cal.hilitedYear, "hilite"); } if (cal.activeYear) { Zapatec.Utils.removeClass(cal.activeYear, "active"); } cal.activeYear = null; var Y = cal.date.getFullYear() + (fwd ? 1 : -1); var yr = yc.firstChild; var show = false; for (var i = 12; i > 0; --i) { if (Y >= cal.minYear && Y <= cal.maxYear) { yr.firstChild.data = Y; yr.year = Y; yr.style.display = "block"; show = true; } else { yr.style.display = "none"; } yr = yr.nextSibling; Y += fwd ? cal.yearStep : -cal.yearStep; } if (show) { var s = yc.style; s.display = "block"; if (cd.navtype < 0) s.left = cd.offsetLeft + "px"; else { var ycw = yc.offsetWidth; if (typeof ycw == "undefined") // Konqueror brain-dead techniques ycw = 50; s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px"; } s.top = (cd.offsetTop + cd.offsetHeight) + "px"; } cal.updateWCH(yc); }; // event handlers /** * This is an event handler that gets called when the mouse button is released * upon the document. The name (tableMouseUp) is because of historic reasons * (in the initial calendar versions this event was triggered by the calendar * table, but now it's the document who does it). * * This function does a number of things. It determines which is the element * that was actually clicked. Note that the "mouseup" event usually means * "something was clicked"; it's "mouseup" who fires the "onclick" event, not * "mousedown" ;-). So, if the clicked element is a member of one of the combo * boxes such as month, year or history, then the appropriate action is taken * (switch month, year or go to history date). * * Also, the Zapatec.Calendar.cellClick() function is called, which further * examines the target element and might do other things. * * Finally, this handler deregisters itself (it's automatically enabled at * "mousedown" on document), stops the event propagation, sets the static _C * variable to \em null (meaning "no calendar is currently in use"). * * @param ev [Event] the event object * @return false */ Zapatec.Calendar.tableMouseUp = function(ev) { var cal = Zapatec.Calendar._C; if (!cal) { return false; } if (cal.timeout) { clearTimeout(cal.timeout); } var el = cal.activeDiv; if (!el) { return false; } var target = Zapatec.Utils.getTargetElement(ev); if (typeof(el.navtype) == "undefined") { while(!target.calendar) { if (!target.tagName) return false; target = target.parentNode; } } ev || (ev = window.event); Zapatec.Utils.removeClass(el, "active"); if (target == el || target.parentNode == el) { Zapatec.Calendar.cellClick(el, ev); } var mon = Zapatec.Calendar.findMonth(target); var date = null; if (mon) { if (!mon.disabled) { date = new Date(cal.date); if (mon.month != date.getMonth()) { date.setMonth(mon.month); cal.setDate(date, true); cal.dateClicked = false; cal.callHandler(); } } } else { var year = Zapatec.Calendar.findYear(target); if (year) { date = new Date(cal.date); if (year.year != date.getFullYear()) { date.setFullYear(year.year); cal.setDate(date, true); cal.dateClicked = false; cal.callHandler(); } } else { var hist = Zapatec.Calendar.findHist(target); if (hist && !hist.histDate.dateEqualsTo(cal.date)) { //(date = new Date(cal.date)).setDateOnly(hist.histDate); date = new Date(hist.histDate); cal._init(cal.firstDayOfWeek, cal.date = date); cal.dateClicked = false; cal.callHandler(); cal.updateHistory(); } } } Zapatec.Utils.removeEvent(window.document, "mouseup", Zapatec.Calendar.tableMouseUp); Zapatec.Utils.removeEvent(window.document, "mouseover", Zapatec.Calendar.tableMouseOver); Zapatec.Utils.removeEvent(window.document, "mousemove", Zapatec.Calendar.tableMouseOver); cal._hideCombos(); Zapatec.Calendar._C = null; return Zapatec.Utils.stopEvent(ev); }; /** * Event handler that gets called when the end-user moves the mouse over the * document. * * This function is pretty complicated too. It adds hover/active state class * to elements that are highlighted and/or clicked. It determines whether one * is trying to modify the time by "drag'n'drop" (the original interface * implemented by the calendar). Finally, it determines if the * mouse is over combo box items, also adding/removing hover states and setting * some calendar variables with reference to the element involved. * * @param ev * * @return */ Zapatec.Calendar.tableMouseOver = function (ev) { var cal = Zapatec.Calendar._C; if (!cal) { return; } var el = cal.activeDiv; var target = Zapatec.Utils.getTargetElement(ev); if (target == el || target.parentNode == el) { Zapatec.Utils.addClass(el, "hilite active"); Zapatec.Utils.addClass(el.parentNode, "rowhilite"); } else { if (typeof el.navtype == "undefined" || (el.navtype != 50 && ((el.navtype == 0 && !cal.histCombo) || Math.abs(el.navtype) > 2))) Zapatec.Utils.removeClass(el, "active"); Zapatec.Utils.removeClass(el, "hilite"); Zapatec.Utils.removeClass(el.parentNode, "rowhilite"); } ev || (ev = window.event); if (el.navtype == 50 && target != el) { var pos = Zapatec.Utils.getAbsolutePos(el); var w = el.offsetWidth; var x = ev.clientX; var dx; var decrease = true; if (x > pos.x + w) { dx = x - pos.x - w; decrease = false; } else dx = pos.x - x; if (dx < 0) dx = 0; var range = el._range; var current = el._current; var date = cal.date; var pm = (date.getHours() >= 12); var old = el.firstChild.data; // old value of the element var count = Math.floor(dx / 10) % range.length; for (var i = range.length; --i >= 0;) if (range[i] == current) break; while (count-- > 0) if (decrease) { if (--i < 0) { i = range.length - 1; } } else if ( ++i >= range.length ) { i = 0; } //ALLOWED TIME CHECK if (cal.getDateStatus) { //Current time is changing, check with the callback to see if it's in range of allowed times // Fills the "minute" and "hour" variables with the time that user wants to set, to pass them to the dateStatusHandler for verification. // As the script passes hours in 24 format, we need to convert input values if they are not in the needed format. var minute = null; // minutes to be passed var hour = null; // hours to be passed var new_date = new Date(date); // as we pass date element to the handler, we need to create new one and fill it with new minutes or hours (depending on what had changed) // if "ampm" was clicked if (el.className.indexOf("ampm", 0) != -1) { minute = date.getMinutes(); // minutes didn't change // if the "ampm" value has changed we need to correct hours (add 12 or exclude 12 or set it to zero) if (old != range[i]) { hour = (range[i] == "pm") ? ((date.getHours() == 0) ? (12) : (date.getHours() + 12)) : (date.getHours() - 12); } else { hour = date.getHours(); } // updates our new Date object that will be passed to the handler new_date.setHours(hour); } // if hours were clicked if (el.className.indexOf("hour", 0) != -1) { minute = date.getMinutes(); // minutes didn't change hour = (!cal.time24) ? ((pm) ? ((range[i] != 12) ? (parseInt(range[i], 10) + 12) : (12)) : ((range[i] != 12) ? (range[i]) : (0))) : (range[i]); // new value of hours new_date.setHours(hour); } // if minutes were clicked if (el.className.indexOf("minute", 0) != -1) { hour = date.getHours(); // hours didn't change minute = range[i]; // new value of minutes new_date.setMinutes(minute); } } var status = false; // if the handler is set, we pass new values and retrieve result in "status" variable if (cal.getDateStatus) { status = cal.getDateStatus(new_date, date.getFullYear(), date.getMonth(), date.getDate(), parseInt(hour, 10), parseInt(minute, 10)); } // if time is enabled, we set new value if (status == false) { if ( !((!cal.time24) && (range[i] == "pm") && (hour > 23)) ) { el.firstChild.data = range[i]; } } cal.onUpdateTime(); //END OF ALLOWED TIME CHECK } var mon = Zapatec.Calendar.findMonth(target); if (mon) { if (!mon.disabled) { if (mon.month != cal.date.getMonth()) { if (cal.hilitedMonth) { Zapatec.Utils.removeClass(cal.hilitedMonth, "hilite"); } Zapatec.Utils.addClass(mon, "hilite"); cal.hilitedMonth = mon; } else if (cal.hilitedMonth) { Zapatec.Utils.removeClass(cal.hilitedMonth, "hilite"); } } } else { if (cal.hilitedMonth) { Zapatec.Utils.removeClass(cal.hilitedMonth, "hilite"); } var year = Zapatec.Calendar.findYear(target); if (year) { if (year.year != cal.date.getFullYear()) { if (cal.hilitedYear) { Zapatec.Utils.removeClass(cal.hilitedYear, "hilite"); } Zapatec.Utils.addClass(year, "hilite"); cal.hilitedYear = year; } else if (cal.hilitedYear) { Zapatec.Utils.removeClass(cal.hilitedYear, "hilite"); } } else { if (cal.hilitedYear) { Zapatec.Utils.removeClass(cal.hilitedYear, "hilite"); } var hist = Zapatec.Calendar.findHist(target); if (hist) { if (!hist.histDate.dateEqualsTo(cal.date)) { if (cal.hilitedHist) { Zapatec.Utils.removeClass(cal.hilitedHist, "hilite"); } Zapatec.Utils.addClass(hist, "hilite"); cal.hilitedHist = hist; } else if (cal.hilitedHist) { Zapatec.Utils.removeClass(cal.hilitedHist, "hilite"); } } else if (cal.hilitedHist) { Zapatec.Utils.removeClass(cal.hilitedHist, "hilite"); } } } return Zapatec.Utils.stopEvent(ev); }; /** * This is a simple function that stops a "mousedown" related to the calendar's * table element. This helps avoiding text selection in certain browsers (most * notably, Safari, since Mozilla already has a better way). * * @param ev [Event] the Event object * @return false */ Zapatec.Calendar.tableMouseDown = function (ev) { if (Zapatec.Utils.getTargetElement(ev) == Zapatec.Utils.getElement(ev)) { return Zapatec.Utils.stopEvent(ev); } }; /** * \defgroup dndmove Drag'n'drop (move calendar) functions * * Contains some functions that implement calendar "drag'n'drop" facility which * allows one to move the calendar around the browser's view. */ //@{ /** * Called at mouseover and/or mousemove on document, this function repositions * the calendar according to the current mouse position. * * @param ev [Event] The Event object * @return false */ Zapatec.Calendar.calDragIt = function (ev) { ev || (ev = window.event); var cal = Zapatec.Calendar._C; if (!(cal && cal.dragging)) { return false; } var posX = ev.clientX + window.document.body.scrollLeft; var posY = ev.clientY + window.document.body.scrollTop; cal.hideShowCovered(); var st = cal.element.style, L = posX - cal.xOffs, T = posY - cal.yOffs; st.left = L + "px"; st.top = T + "px"; Zapatec.Utils.setupWCH(cal.WCH, L, T); return Zapatec.Utils.stopEvent(ev); }; /** * Gets called when the drag and drop operation is finished; thus, at * "onmouseup". This function unregisters D'n'D event handlers and calls * Zapatec.Calendar.hideShowCovered() which repaints as appropriate any * "windowed controls" that might have been hidden by the end user moving the * calendar. (note, this is only for IE5; for IE5.5 there are better--albeit * uglier--workarounds). * * @param ev [Event] the event object * @return false */ Zapatec.Calendar.calDragEnd = function (ev) { var cal = Zapatec.Calendar._C; if (!cal) { return false; } cal.dragging = false; Zapatec.Utils.removeEvent(window.document, "mousemove", Zapatec.Calendar.calDragIt); Zapatec.Utils.removeEvent(window.document, "mouseover", Zapatec.Calendar.calDragIt); Zapatec.Utils.removeEvent(window.document, "mouseup", Zapatec.Calendar.calDragEnd); Zapatec.Calendar.tableMouseUp(ev); cal.hideShowCovered(); }; //@} /** * Called when the mouse button is pressed upon a button. The name of this * function is so for historical reasons; currently, this function is used for * \em any type of buttons used in the calendar, not only "days". * * This function does quite some things. It checks if the clicked cell is the * title bar or the status bar, in which case it starts the calendar dragging * mechanism (cal._dragStart()). If the cell is a time part, then it registers * Zapatec.Calendar.tableMouseOver() event handler on the document. If the * cell is a "navigation" button (next/prev year or month, or today) then a * timeout is created that will show the appropriate combo box if the button is * not quickly depressed. * * @param ev [Event] the event object * @return false */ Zapatec.Calendar.dayMouseDown = function(ev) { var canDrag = true; var el = Zapatec.Utils.getElement(ev); if (el.disabled) { return false; } var cal = el.calendar; //BEGIN: fix for the extra information bug in IE while(!cal) { el = el.parentNode; cal = el.calendar; } //END cal.bEventShowHistory=false; // Set state the we DID NOT enter History event cal.activeDiv = el; Zapatec.Calendar._C = cal; if (el.navtype != 300) { if (el.navtype == 50) { //turns off changing the time by dragging if timeInterval is set if (!((cal.timeInterval == null) || ((cal.timeInterval < 60) && (el.className.indexOf("hour", 0) != -1)))) {canDrag = false;} el._current = el.firstChild.data; if (canDrag) {Zapatec.Utils.addEvent(window.document, "mousemove", Zapatec.Calendar.tableMouseOver);} } else { if (((el.navtype == 201) || (el.navtype == 202)) && (cal.timeInterval > 30) && (el.timePart.className.indexOf("minute", 0) != -1)) {canDrag = false;} if (canDrag) {Zapatec.Utils.addEvent(window.document, Zapatec.is_ie5 ? "mousemove" : "mouseover", Zapatec.Calendar.tableMouseOver);} } if (canDrag) {Zapatec.Utils.addClass(el, "hilite active");} Zapatec.Utils.addEvent(window.document, "mouseup", Zapatec.Calendar.tableMouseUp); } else if (cal.isPopup) { cal._dragStart(ev); } else { Zapatec.Calendar._C = null; } if (el.navtype == -1 || el.navtype == 1) { if (cal.timeout) clearTimeout(cal.timeout); cal.timeout = setTimeout("Zapatec.Calendar.showMonthsCombo()", 250); } else if (el.navtype == -2 || el.navtype == 2) { if (cal.timeout) clearTimeout(cal.timeout); cal.timeout = setTimeout((el.navtype > 0) ? "Zapatec.Calendar.showYearsCombo(true)" : "Zapatec.Calendar.showYearsCombo(false)", 250); } else if (el.navtype == 0 && Zapatec.Calendar.prefs.history) { if (cal.timeout) clearTimeout(cal.timeout); cal.timeout = setTimeout("Zapatec.Calendar.showHistoryCombo()", 250); } else { cal.timeout = null; } return Zapatec.Utils.stopEvent(ev); }; /** * For IE5 we can't make unselectable elements, but we can void the selection * immediately after the double click event :D. This function is a double * click handler which does exactly that. Uses IE-specific functions. */ Zapatec.Calendar.dayMouseDblClick = function(ev) { Zapatec.Calendar.cellClick(Zapatec.Utils.getElement(ev), ev || window.event); if (Zapatec.is_ie) window.document.selection.empty(); }; /** * This function gets called at "onmouseover" events that trigger on any kind * of button, like dates, navigation buttons, etc. Basically, the function * computes and caches the tooltip (if it's a date cell for instance) and * displays it in the status bar. If the cell is not a navigation button, it * will also add "rowhilite" class to the containing TR element. * * @param ev [Event] the event object. * @return false */ Zapatec.Calendar.dayMouseOver = function(ev) { var el = Zapatec.Utils.getElement(ev), caldate = el.caldate; //BEGIN: fix for the extra information bug in IE while (!el.calendar) { el = el.parentNode; caldate = el.caldate; } //END var cal = el.calendar; var cel = el.timePart; if (caldate) { caldate = new Date(caldate[0], caldate[1], caldate[2]); if (caldate.getDate() != el.caldate[2]) caldate.setDate(el.caldate[2]); } if (Zapatec.Utils.isRelated(el, ev) || Zapatec.Calendar._C || el.disabled) { return false; } if (el.ttip) { if (el.ttip.substr(0, 1) == "_") { el.ttip = caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1); } el.calendar.showHint(el.ttip); } if (el.navtype != 300) { //turns off highliting of the time part which can not be changed by dragging if (!((cal.timeInterval == null) || (el.className.indexOf("ampm", 0) != -1) || ((cal.timeInterval < 60) && (el.className.indexOf("hour", 0) != -1))) && (el.navtype == 50)) {return Zapatec.Utils.stopEvent(ev);} if (((el.navtype == 201) || (el.navtype == 202)) && (cal.timeInterval > 30) && (cel.className.indexOf("minute", 0) != -1)) {return Zapatec.Utils.stopEvent(ev);} Zapatec.Utils.addClass(el, "hilite"); if (caldate) { Zapatec.Utils.addClass(el.parentNode, "rowhilite"); } } return Zapatec.Utils.stopEvent(ev); }; /** * Gets called when the mouse leaves a button. This function "undoes" what * dayMouseOver did, that is, it removes the "rowhilite" class from the * containing TR and restores the status bar display to read "Select date". * * @param ev [Event] the event object. * @return false */ Zapatec.Calendar.dayMouseOut = function(ev) { var el = Zapatec.Utils.getElement(ev); //BEGIN: fix for the extra information bug in IE while (!el.calendar) { el = el.parentNode; caldate = el.caldate; } //END if (Zapatec.Utils.isRelated(el, ev) || Zapatec.Calendar._C || el.disabled) return false; Zapatec.Utils.removeClass(el, "hilite"); if (el.caldate) Zapatec.Utils.removeClass(el.parentNode, "rowhilite"); if (el.calendar) el.calendar.showHint(Zapatec.Calendar.i18n("SEL_DATE")); return Zapatec.Utils.stopEvent(ev); }; /** * The generic "click" handler. This function handles actions on any kind of * buttons that appear inside our calendar. It determines the button type by * querying \em el.navtype. The following types of objects are supported: * * - Date cells (navtype is undefined). The function will select that date, * add appropriate class names and remove them from the previously selected * date. If the date in the calendar \em has \em changed, it calls the * calendar's onSelect handler (see the constructor). If multiple dates is * enabled, it will not unselect previously selected date but rather maintain * an array of dates which will be avaliable to the onSelect or onClose * handler. * - The Close button (navtype == 200). If this is clicked, then the * calendar's onClose handler is called immediately. * - The Today button (navtype == 0). The calendar will jump to the "today" * date and time, unless it's already there. * - The About button (navtype == 400). It will display an alert with the * "about message", as defined in the translation file. * - Previous year (navtype == -2) * - Previous month (navtype == -1) * - Next month (navtype == 1) * - Next year (navtype == 2) * - Day names (navtype == 100). If any of them is clicked, the calendar will * display that day as the first day of week. It calls the "onFDOW" event * handler if defined. * - Time parts (navtype == 50). If any of them is clicked, this function will * determine if it's a click or shift-click, and will take the appropriate * action (simple click means add 1, shift-click means substract 1 from that * time part). Then it calls onUpdateTime() to refresh the display. * - Time scroll buttons (navtype == 201 or navtype == 202). If such buttons * are clicked, the time part involved is determined and it is incremented or * decremented with the current step (default: 5). 201 is for "add", 202 for * "substract". * * @param el [HTMLElement] the object being clicked on * @param ev [Event] the event object */ Zapatec.Calendar.cellClick = function(el, ev) { var cal = el.calendar; var closing = false; var newdate = false; var date = null; //BEGIN: fix for the extra information bug in IE while(!cal) { el = el.parentNode; cal = el.calendar; } //END if (typeof el.navtype == "undefined") { if (cal.currentDateEl) { Zapatec.Utils.removeClass(cal.currentDateEl, "selected"); Zapatec.Utils.addClass(el, "selected"); closing = (cal.currentDateEl == el); if (!closing) { cal.currentDateEl = el; } } var tmpDate = new Date(el.caldate[0], el.caldate[1], el.caldate[2]); if (tmpDate.getDate() != el.caldate[2]) { tmpDate.setDate(el.caldate[2]); } cal.date.setDateOnly(tmpDate); cal.currentDate.setDateOnly(tmpDate); date = cal.date; var other_month = !(cal.dateClicked = !el.otherMonth); if (!other_month && cal.multiple) cal._toggleMultipleDate(new Date(date)); newdate = true; // a date was clicked if (other_month) cal._init(cal.firstDayOfWeek, date); cal.onSetTime(); } else { if (el.navtype == 200) { Zapatec.Utils.removeClass(el, "hilite"); cal.callCloseHandler(); return; } date = new Date(cal.date); if (el.navtype == 0 && !cal.bEventShowHistory) // Set date to Today if Today clicked AND History NOT shown date.setDateOnly(new Date()); // TODAY // unless "today" was clicked, we assume no date was clicked so // the selected handler will know not to close the calenar when // in single-click mode. // cal.dateClicked = (el.navtype == 0); cal.dateClicked = false; var year = date.getFullYear(); var mon = date.getMonth(); function setMonth(m) { var day = date.getDate(); var max = date.getMonthDays(m); if (day > max) { date.setDate(max); } date.setMonth(m); }; switch (el.navtype) { case 400: Zapatec.Utils.removeClass(el, "hilite"); var text = Zapatec.Calendar.i18n("ABOUT"); if (typeof text != "undefined") { text += cal.showsTime ? Zapatec.Calendar.i18n("ABOUT_TIME") : ""; } else { // FIXME: this should be removed as soon as lang files get updated! text = "Help and about box text is not translated into this language.\n" + "If you know this language and you feel generous please update\n" + "the corresponding file in \"lang\" subdir to match calendar-en.js\n" + "and send it back to to get it into the distribution ;-)\n\n" + "Thank you!\n" + "http://www.zapatec.com\n"; } alert(text); return; case -2: if (year > cal.minYear) { date.setFullYear(year - 1); } break; case -1: if (mon > 0) { setMonth(mon - 1); } else if (year-- > cal.minYear) { date.setFullYear(year); setMonth(11); } break; case 1: if (mon < 11) { setMonth(mon + 1); } else if (year < cal.maxYear) { date.setFullYear(year + 1); setMonth(0); } break; case 2: if (year < cal.maxYear) { date.setFullYear(year + 1); } break; case 100: cal.setFirstDayOfWeek(el.fdow); Zapatec.Calendar.prefs.fdow = cal.firstDayOfWeek; Zapatec.Calendar.savePrefs(); if (cal.onFDOW) cal.onFDOW(cal.firstDayOfWeek); return; case 50: //turns off time changing if timeInterval is set with special value if (el.className.indexOf("ampm", 0) >= 0) // always check ampm changes ; else if (!((cal.timeInterval == null) || ((cal.timeInterval < 60) && (el.className.indexOf("hour", 0) != -1)))) {break;} var range = el._range; var current = el.firstChild.data; var pm = (date.getHours() >= 12); for (var i = range.length; --i >= 0;) if (range[i] == current) break; if (ev && ev.shiftKey) { if (--i < 0) { i = range.length - 1; } } else if ( ++i >= range.length ) { i = 0; } //ALLOWED TIME CHECK if (cal.getDateStatus) { //Current time is changing, check with the callback to see if it's in range // Fills "minute" and "hour" variables with the time that user wants to set, to pass them to the dateStatusHandler. // As the script passes hours in 24 format, we need to convert inputed values if they are not in the needed format var minute = null; // minutes to be passed var hour = null; // hours to be passed // as we pass date element to the handler, we need to create new one and fill it with new minutes or hours (depending on what had changed) var new_date = new Date(date); // if "ampm" was clicked if (el.className.indexOf("ampm", 0) != -1) { minute = date.getMinutes(); // minutes didn't change // if the "ampm" value has changed we need to correct hours (add 12 or exclude 12 or set it to zero) hour = (range[i] == "pm") ? ((date.getHours() == 12) ? (date.getHours()) : (date.getHours() + 12)) : (date.getHours() - 12); // if the time is disabled we seek the first one disabled. // It fixes the bug when you can not change from 'am' to 'pm' or vice versa for the dates that have restrictions for time. // This part of code is very easy to understand, so it don't need much comments if ( cal.getDateStatus && cal.getDateStatus(new_date, date.getFullYear(), date.getMonth(), date.getDate(), parseInt(hour, 10), parseInt(minute, 10)) ) { var dirrect; if (range[i] == "pm") { dirrect = -5; } else { dirrect = 5; } hours = hour; minutes = minute; do { minutes += dirrect; if (minutes >=60) { minutes -= 60; ++hours; if (hours >= 24) hours -= 24; new_date.setHours(hours); } if (minutes < 0) { minutes += 60; --hours; if (hours < 0) hours += 24; new_date.setHours(hours); } new_date.setMinutes(minutes); if (!cal.getDateStatus(new_date, date.getFullYear(), date.getMonth(), date.getDate(), parseInt(hours, 10), parseInt(minutes, 10))) { hour = hours; minute = minutes; if (hour > 12) i = 1; else i = 0; cal.date.setHours(hour); cal.date.setMinutes(minute); cal.onSetTime(); } } while ((hour != hours) || (minute != minutes)); } // updates our new Date object that will be passed to the handler new_date.setHours(hour); } // if hours were clicked if (el.className.indexOf("hour", 0) != -1) { minute = date.getMinutes(); // minutes didn't change hour = (!cal.time24) ? ((pm) ? ((range[i] != 12) ? (parseInt(range[i], 10) + 12) : (12)) : ((range[i] != 12) ? (range[i]) : (0))) : (range[i]); // new value of hours new_date.setHours(hour); } // if minutes were clicked if (el.className.indexOf("minute", 0) != -1) { hour = date.getHours(); // hours didn't change minute = range[i]; // new value of minutes new_date.setMinutes(minute); } } var status = false; // if the handler is set, we pass new values and retreive result in "status" variable if (cal.getDateStatus) { status = cal.getDateStatus(new_date, date.getFullYear(), date.getMonth(), date.getDate(), parseInt(hour, 10), parseInt(minute, 10)); } if (!status) { el.firstChild.data = range[i]; } //END OF ALLOWED TIME CHECK cal.onUpdateTime(); return; case 201: // timepart, UP case 202: // timepart, DOWN var cel = el.timePart; //turns off time changing if timeInterval is set with special value if ((cel.className.indexOf("minute", 0) != -1) && (cal.timeInterval > 30)) {break;} var val = parseInt(cel.firstChild.data, 10); var pm = (date.getHours() >= 12); var range = cel._range; for (var i = range.length; --i >= 0;) if (val == range[i]) { val = i; break; } var step = cel._step; if (el.navtype == 201) { val = step*Math.floor(val/step); val += step; if (val >= range.length) val = 0; } else { val = step*Math.ceil(val/step); val -= step; if (val < 0) val = range.length-step; } //ALLOWED TIME CHECK if (cal.getDateStatus) { //Current time is changing, check with the callback to see if it's in range of allowed times // Fills "minute" and "hour" variables with the time that user wants to set, to pass them to the dateStatusHandler. // As the script passes hours in 24 format, we need to convert inputed values if they are not in the needed format var minute = null; // minutes to be passed var hour = null; // hours to be passed // as we pass date element to the handler, we need to create new one and fill it with new minutes or hours (depending on what had changed) var new_date = new Date(date); // if hours were changed if (cel.className == "hour") { minute = date.getMinutes(); hour = (!cal.time24) ? ((pm) ? ((range[val] != 12) ? (parseInt(range[val], 10) + 12) : (12)) : ((range[val] != 12) ? (range[val]) : (0))) : (range[val]); new_date.setHours(hour); } // if minutes were changed if (cel.className == "minute") { hour = date.getHours(); minute = val; new_date.setMinutes(range[val]); } } var status = false; // if the handler is set, we pass new values and retreive result in "status" variable if (cal.getDateStatus) { status = cal.getDateStatus(new_date, date.getFullYear(), date.getMonth(), date.getDate(), parseInt(hour, 10), parseInt(minute, 10)); } if (!status) { cel.firstChild.data = range[val]; } cal.onUpdateTime(); //END OF ALLOWED TIME CHECK return; case 0: // TODAY will bring us here //fix for the today bug for the special dates if (cal.getDateStatus && ((cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate()) == true) || (cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate()) == "disabled"))) { // remember, "date" was previously set to new // Date() if TODAY was clicked; thus, it // contains today date. return false; } break; } if (!date.equalsTo(cal.date)) { if ((el.navtype >= -2 && el.navtype <=2) && (el.navtype != 0)) { cal._init(cal.firstDayOfWeek, date, true); return; } cal.setDate(date); newdate = !(el.navtype && (el.navtype >= -2 && el.navtype <=2)); } } if (newdate) { cal.callHandler(); } if (closing) { Zapatec.Utils.removeClass(el, "hilite"); cal.callCloseHandler(); } }; // END: CALENDAR STATIC FUNCTIONS // BEGIN: CALENDAR OBJECT FUNCTIONS /** * This function creates the calendar HTML elements inside the given parent. * If _par is null than it creates a popup calendar inside the BODY element. * If _par is an element, be it BODY, then it creates a non-popup calendar * (still hidden). * * The function looks rather complicated, but what it does is quite simple. * The basic calendar elements will be created, that is, a containing DIV, a * TABLE that contains a headers (titles, navigation bar and day names bars), a * body containing up to 12 months, each has 6 rows with 7 or 8 cells (this depends on whether week * numbers are on or off) and a footer containing the status bar. Appropriate * event handlers are assigned to all buttons or to the titles and status bar * (for drag'n'drop). * * This function also builds the time selector if the calendar is configured * so, and it also creates the elements required for combo boxes (years, * months, history). * * This function does not display day names or dates. This is done in * Zapatec.Calendar.prototype._init(). Therefore, by separating these 2 * actions we can make date switching happen much faster because the _init * function will already have the elements in place (so we don't need to create * them again and again). This was a major improvement which got in * the calendar v0.9.1. * * @param _par */ Zapatec.Calendar.prototype.create = function (_par) { var parent = null; if (! _par) { // default parent is the document body, in which case we create // a popup calendar. parent = window.document.getElementsByTagName("body")[0]; this.isPopup = true; this.WCH = Zapatec.Utils.createWCH(); } else { parent = _par; this.isPopup = false; } this.currentDate = this.date = this.dateStr ? new Date(this.dateStr) : new Date(); var table = Zapatec.Utils.createElement("table"); this.table = table; table.cellSpacing = 0; table.cellPadding = 0; table.calendar = this; Zapatec.Utils.addEvent(table, "mousedown", Zapatec.Calendar.tableMouseDown); var div = Zapatec.Utils.createElement("div"); this.element = div; div.className = "calendar"; //FIX for Opera's bug with row highlighting if (Zapatec.is_opera) { table.style.width = (this.monthsInRow * ((this.weekNumbers) ? (8) : (7)) * 2 + 4.4 * this.monthsInRow) + "em"; } if (this.isPopup) { div.style.position = "absolute"; div.style.display = "none"; } div.appendChild(table); var cell = null; var row = null; var cal = this; var hh = function (text, cs, navtype) { cell = Zapatec.Utils.createElement("td", row); cell.colSpan = cs; cell.className = "button"; if (Math.abs(navtype) <= 2) cell.className += " nav"; Zapatec.Calendar._add_evs(cell); cell.calendar = cal; cell.navtype = navtype; if (text.substr(0, 1) != "&") { cell.appendChild(document.createTextNode(text)); } else { // FIXME: dirty hack for entities cell.innerHTML = text; } return cell; }; //Creating all the controls on the top var title_length = ((this.weekNumbers) ? (8) : (7)) * this.monthsInRow - 2; var thead = Zapatec.Utils.createElement("thead", table); if (this.numberMonths == 1) { this.title = thead; } row = Zapatec.Utils.createElement("tr", thead); // begin: [MEO] this.about = hh("", 1, 400); this.about.ttip = null;//Zapatec.Calendar.i18n("INFO"); this.about.className = "about"; // end this.title = hh("", title_length, 300); this.title.className = "title"; this.title.ttip = Zapatec.Calendar.i18n("DRAG_TO_MOVE"); this.title.style.cursor = "move"; // begin: [MEO] var p = cal.params; if (p.flat==null) { this.close = hh("×", 1, 200); this.close.ttip = Zapatec.Calendar.i18n("CLOSE"); this.close.className = "close"; } // end if (this.params && this.params.titleHtml) this.title.innerHTML=this.params.titleHtml row = Zapatec.Utils.createElement("tr", thead); this._nav_py = hh("«", 1, -2); this._nav_py.ttip = Zapatec.Calendar.i18n("PREV_YEAR"); this._nav_pm = hh("‹", 1, -1); this._nav_pm.ttip = Zapatec.Calendar.i18n("PREV_MONTH"); this._nav_now = hh(Zapatec.Calendar.i18n("TODAY"), title_length - 2, 0); this._nav_now.ttip = Zapatec.Calendar.i18n("GO_TODAY"); this._nav_nm = hh("›", 1, 1); this._nav_nm.ttip = Zapatec.Calendar.i18n("NEXT_MONTH"); this._nav_ny = hh("»", 1, 2); this._nav_ny.ttip = Zapatec.Calendar.i18n("NEXT_YEAR"); //Here we calculate the number of rows for multimonth calendar var rowsOfMonths = Math.floor(this.numberMonths / this.monthsInRow); if (this.numberMonths % this.monthsInRow > 0) { ++rowsOfMonths; } //Every iteration of this cycle creates a row of months in the calendar for (var l = 1; l <= rowsOfMonths; ++l) { var thead = Zapatec.Utils.createElement("thead", table); //Fix for the Operas bug, this is a workaround which makes Opera display THEAD elements as TBODY el. //The problem is that Opera displays all the THEAD elements in the table first, and only then TBODY elements (an ugly look!). if (Zapatec.is_opera) {thead.style.display = "table-row-group";} if (this.numberMonths != 1) { row = Zapatec.Utils.createElement("tr", thead); var title_length = 5; this.weekNumbers && ++title_length; //creating the titles for the months this.titles[l] = new Array(); for (var k = 1; (k <= this.monthsInRow) && ((l - 1) * this.monthsInRow + k <= this.numberMonths); ++k) { cell = Zapatec.Utils.createElement("td", row); cell.colSpan = 1; cell.className = "button"; cell.innerHTML = "

 

"; this.titles[l][k] = hh("", title_length, 300); this.titles[l][k].className = "title"; cell = Zapatec.Utils.createElement("td", row); cell.colSpan = 1; cell.className = "button"; cell.innerHTML = "

 

"; } } // day names row = Zapatec.Utils.createElement("tr", thead); row.className = "daynames"; for (k = 1; (k <= this.monthsInRow) && ((l - 1) * this.monthsInRow + k <= this.numberMonths); ++k) { if (this.weekNumbers) { cell = Zapatec.Utils.createElement("td", row); cell.className = "name wn"; cell.appendChild(window.document.createTextNode(Zapatec.Calendar.i18n("WK"))); if (k > 1) { Zapatec.Utils.addClass(cell, "month-left-border"); } var cal_wk = Zapatec.Calendar.i18n("WK") if (cal_wk == null) { //if it's not defined in the language file, leave it blank cal_wk = ""; } } for (var i = 7; i > 0; --i) { cell = Zapatec.Utils.createElement("td", row); cell.appendChild(window.document.createTextNode("")); if (!i) { cell.navtype = 100; cell.calendar = this; Zapatec.Calendar._add_evs(cell); } } } this.firstdayname = row.childNodes[this.weekNumbers?1:0]; this.rowsOfDayNames[l] = this.firstdayname; this._displayWeekdays(); var tbody = Zapatec.Utils.createElement("tbody", table); this.tbody[l] = tbody; for (i = 6; i > 0; --i) { //creating a row of days for all the months in the row row = Zapatec.Utils.createElement("tr", tbody); for (k = 1; (k <= this.monthsInRow) && ((l - 1) * this.monthsInRow + k <= this.numberMonths); ++k) { if (this.weekNumbers) { cell = Zapatec.Utils.createElement("td", row); cell.appendChild(document.createTextNode("")); } for (var j = 7; j > 0; --j) { cell = Zapatec.Utils.createElement("td", row); cell.appendChild(document.createTextNode("")); cell.calendar = this; Zapatec.Calendar._add_evs(cell); } } } } var tfoot = Zapatec.Utils.createElement("tfoot", table); ///MEO if (this.showsTime) { row = Zapatec.Utils.createElement("tr", tfoot); row.className = "time"; //empty area for positioning the time controls under the control month var emptyColspan; if (this.monthsInRow != 1) { cell = Zapatec.Utils.createElement("td", row); emptyColspan = cell.colSpan = Math.ceil((((this.weekNumbers) ? 8 : 7) * (this.monthsInRow - 1)) / 2); cell.className = "timetext"; cell.innerHTML = " "; } cell = Zapatec.Utils.createElement("td", row); cell.className = "timetext"; cell.colSpan = this.weekNumbers ? 2 : 1; cell.innerHTML = Zapatec.Calendar.i18n("TIME") || " "; (function() { function makeTimePart(className, init, range_start, range_end) { var table, tbody, tr, tr2, part; if (range_end) { cell = Zapatec.Utils.createElement("td", row); cell.colSpan = 2; cell.className = "parent-" + className; table = Zapatec.Utils.createElement("table", cell); table.cellSpacing = table.cellPadding = 0; if (className == "hour") table.align = "right"; table.className = "calendar-time-scroller"; tbody = Zapatec.Utils.createElement("tbody", table); tr = Zapatec.Utils.createElement("tr", tbody); tr2 = Zapatec.Utils.createElement("tr", tbody); } else tr = row; part = Zapatec.Utils.createElement("td", tr); part.className = className; part.appendChild(window.document.createTextNode(init)); part.calendar = cal; part.ttip = Zapatec.Calendar.i18n("TIME_PART"); part.navtype = 50; part._range = []; if (!range_end) part._range = range_start; else { part.rowSpan = 2; for (var i = range_start; i <= range_end; ++i) { var txt; if (i < 10 && range_end >= 10) txt = '0' + i; else txt = '' + i; part._range[part._range.length] = txt; } var up = Zapatec.Utils.createElement("td", tr); up.className = "up"; up.navtype = 201; up.calendar = cal; up.timePart = part; if (Zapatec.is_khtml) up.innerHTML = " "; Zapatec.Calendar._add_evs(up); var down = Zapatec.Utils.createElement("td", tr2); down.className = "down"; down.navtype = 202; down.calendar = cal; down.timePart = part; if (Zapatec.is_khtml) down.innerHTML = " "; Zapatec.Calendar._add_evs(down); } Zapatec.Calendar._add_evs(part); return part; }; var hrs = cal.currentDate.getHours(); var mins = cal.currentDate.getMinutes(); var t12 = !cal.time24; var pm = (hrs > 12); if (t12 && pm) hrs -= 12; var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23); //calculating of the step for hours H._step = (cal.timeInterval > 30) ? (cal.timeInterval / 60) : 1; cell = Zapatec.Utils.createElement("td", row); cell.innerHTML = ":"; cell.className = "colon"; var M = makeTimePart("minute", mins, 0, 59); //calculating of the step for minutes M._step = ((cal.timeInterval) && (cal.timeInterval < 60)) ? (cal.timeInterval) : 5; // FIXME: make this part configurable var AP = null; if (t12) { AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]); AP.className += " button"; } else Zapatec.Utils.createElement("td", row).innerHTML = " "; cal.onSetTime = function() { var hrs = this.currentDate.getHours(); var mins = this.currentDate.getMinutes(); if (this.timeInterval) { mins += this.timeInterval - ((mins - 1 + this.timeInterval) % this.timeInterval) - 1; } while (mins >= 60) { mins -= 60; ++hrs; } if (this.timeInterval > 60) { var interval = this.timeInterval / 60; if (hrs % interval != 0) { hrs += interval - ((hrs - 1 + interval) % interval) - 1; } if (hrs >= 24) {hrs -= 24;} } //ALLOWED TIME CHECK // This part of code seeks for the first enabled time value for this date. // It is written for the cases when you change day, month or year and the time value is disabled for the new date. // So if you only allow 8:00 - 17:00 on Mondays and you change the date to a Monday but the time is 7:00 it will // automatically move forward to 8:00. var new_date = new Date(this.currentDate); if (this.getDateStatus && this.getDateStatus(this.currentDate, this.currentDate.getFullYear(), this.currentDate.getMonth(), this.currentDate.getDate(), hrs, mins)) { hours = hrs; minutes = mins; do { if (this.timeInterval) { if (this.timeInterval < 60) { minutes += this.timeInterval; } else { hrs += this.timeInterval / 60; } } else { minutes += 5; } if (minutes >=60) { minutes -= 60; hours += 1; } if (hours >= 24) {hours -= 24;} new_date.setMinutes(minutes); new_date.setHours(hours); if (!this.getDateStatus(new_date, this.currentDate.getFullYear(), this.currentDate.getMonth(), this.currentDate.getDate(), hours, minutes)) { hrs = hours; mins = minutes; } } while ((hrs != hours) || (mins != minutes)); } //END OF ALLOWED TIME CHECK var pm = (hrs > 12); if (pm && t12) hrs -= 12; H.firstChild.data = (hrs < 10) ? ("0" + hrs) : hrs; M.firstChild.data = (mins < 10) ? ("0" + mins) : mins; if (t12) AP.firstChild.data = pm ? "pm" : "am"; this.currentDate.setMinutes(mins); this.currentDate.setHours(hrs); }; cal.onUpdateTime = function() { var date = this.currentDate; var h = parseInt(H.firstChild.data, 10); if (t12) { if (/pm/i.test(AP.firstChild.data) && h < 12) h += 12; else if (/am/i.test(AP.firstChild.data) && h == 12) h = 0; } var d = date.getDate(); var m = date.getMonth(); var y = date.getFullYear(); date.setHours(h); date.setMinutes(parseInt(M.firstChild.data, 10)); date.setFullYear(y); date.setMonth(m); date.setDate(d); this.dateClicked = false; this.callHandler(); }; })(); //empty area after the time controls if (this.monthsInRow != 1) { cell = Zapatec.Utils.createElement("td", row); cell.colSpan = ((this.weekNumbers) ? 8 : 7) * (this.monthsInRow - 1) - Math.ceil(emptyColspan); cell.className = "timetext"; cell.innerHTML = " "; } } else { this.onSetTime = this.onUpdateTime = function() {}; } row = Zapatec.Utils.createElement("tr", tfoot); row.className = "footrow"; cell = hh(Zapatec.Calendar.i18n("SEL_DATE"), this.weekNumbers ? (8 * this.numberMonths) : (7 * this.numberMonths), 300); cell.className = "ttip"; if (this.isPopup) { cell.ttip = Zapatec.Calendar.i18n("DRAG_TO_MOVE"); cell.style.cursor = "move"; } this.tooltips = cell; div = this.monthsCombo = Zapatec.Utils.createElement("div", this.element); div.className = "combo"; for (i = 0; i < 12; ++i) { var mn = Zapatec.Utils.createElement("div"); mn.className = Zapatec.is_ie ? "label-IEfix" : "label"; mn.month = i; mn.appendChild(window.document.createTextNode(Zapatec.Calendar.i18n(i, "smn"))); div.appendChild(mn); } div = this.yearsCombo = Zapatec.Utils.createElement("div", this.element); div.className = "combo"; for (i = 12; i > 0; --i) { var yr = Zapatec.Utils.createElement("div"); yr.className = Zapatec.is_ie ? "label-IEfix" : "label"; yr.appendChild(window.document.createTextNode("")); div.appendChild(yr); } div = this.histCombo = Zapatec.Utils.createElement("div", this.element); div.className = "combo history"; this._init(this.firstDayOfWeek, this.date); parent.appendChild(this.element); }; /** * This function handles keypress events that occur while a popup calendar is * displayed. The implementation is quite complicated; this function calls * cellClick in order to set the new date as if it was clicked. * * @param ev [Event] the event object * @return false */ Zapatec.Calendar._keyEvent = function(ev) { if (!window.calendar) { return false; } (Zapatec.is_ie) && (ev = window.event); var cal = window.calendar; var act = (Zapatec.is_ie || ev.type == "keypress"); var K = ev.keyCode; var date = new Date(cal.date); if (ev.ctrlKey) { switch (K) { case 37: // KEY left act && Zapatec.Calendar.cellClick(cal._nav_pm); break; case 38: // KEY up act && Zapatec.Calendar.cellClick(cal._nav_py); break; case 39: // KEY right act && Zapatec.Calendar.cellClick(cal._nav_nm); break; case 40: // KEY down act && Zapatec.Calendar.cellClick(cal._nav_ny); break; default: return false; } } else switch (K) { case 32: // KEY space (now) Zapatec.Calendar.cellClick(cal._nav_now); break; case 27: // KEY esc act && cal.callCloseHandler(); break; //Fix for the key navigation case 37: // KEY left if (act && !cal.multiple) { date.setTime(date.getTime() - 86400000); cal.setDate(date); } break; case 38: // KEY up if (act && !cal.multiple) { date.setTime(date.getTime() - 7 * 86400000); cal.setDate(date); } break; case 39: // KEY right if (act && !cal.multiple) { date.setTime(date.getTime() + 86400000); cal.setDate(date); } break; case 40: // KEY down if (act && !cal.multiple) { date.setTime(date.getTime() + 7 * 86400000); cal.setDate(date); } break; case 13: // KEY enter if (act) { //FIX for Enter key! Zapatec.Calendar.cellClick(cal.currentDateEl); } break; default: return false; } return Zapatec.Utils.stopEvent(ev); }; /** * (RE)Initializes the calendar to the given date and firstDayOfWeek. * * This function perform the action of actually displaying the day names and * dates in the calendar. But first, it checks if the passed date fits in the * allowed range, configured by the "minYear", "maxYear", "minMonth" and * "maxMonth" properties of the Calendar object. * * It takes care to highlight special days (calling the * calendar.getDateStatus() function which can be overridden by external * scripts) or to highlight any dates that might be selected (for instance when * multiple dates is on, this function will call _initMultipleDates() to * highlight selected dates accordingly). * * This function is highly optimized for speed, therefore the code in it is not * trivial and what it does might not seem obvious. :-) So, WARNING, this is * voodoo. If you want to properly understand the code you should analyze it * line by line and try to execute it step by step; use the Venkman JS * debugger. * * @param firstDayOfWeek [int] the first day of week, 0 for Sunday, 1 for Monday, etc. * @param date [Date] the date to initialize the calendar to * * @return */ Zapatec.Calendar.prototype._init = function (firstDayOfWeek, date, last) { var today = new Date(), TD = today.getDate(), TY = today.getFullYear(), TM = today.getMonth(); //this.table.style.visibility = "hidden"; if (this.getDateStatus && !last) { var status = this.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate()); var backupDate = new Date(date); while (((status == true) || (status == "disabled")) && (backupDate.getMonth() == date.getMonth())) { date.setTime(date.getTime() + 86400000); var status = this.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate()); } if (backupDate.getMonth() != date.getMonth()) { date = new Date(backupDate); while (((status == true) || (status == "disabled")) && (backupDate.getMonth() == date.getMonth())) { date.setTime(date.getTime() - 86400000); var status = this.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate()); } } if (backupDate.getMonth() != date.getMonth()) { last = true; date = new Date(backupDate); } } var year = date.getFullYear(); var month = date.getMonth(); var rowsOfMonths = Math.floor(this.numberMonths / this.monthsInRow); var minMonth; var diffMonth, last_row, before_control; if (!this.vertical) { diffMonth = (this.controlMonth - 1); minMonth = month - diffMonth; } else { last_row = ((this.numberMonths - 1) % this.monthsInRow) + 1; before_control = (this.controlMonth - 1) % this.monthsInRow; bottom = (before_control >= (last_row) ? (last_row) : (before_control)); diffMonth = (before_control) * (rowsOfMonths - 1) + Math.floor((this.controlMonth - 1) / this.monthsInRow) + bottom; minMonth = month - diffMonth; } var minYear = year; if (minMonth < 0) { minMonth += 12; --minYear; } var maxMonth = minMonth + this.numberMonths - 1; var maxYear = minYear; if (maxMonth > 11) { maxMonth -= 12; ++maxYear; } function disableControl(ctrl) { Zapatec.Calendar._del_evs(ctrl); ctrl.disabled = true; ctrl.className = "button"; ctrl.innerHTML = "

 

"; } function enableControl(ctrl, sign) { Zapatec.Calendar._add_evs(ctrl); ctrl.disabled = false; ctrl.className = "button nav"; ctrl.innerHTML = sign; } if (minYear <= this.minYear) { if (!this._nav_py.disabled) { disableControl(this._nav_py); } } else { if (this._nav_py.disabled) { enableControl(this._nav_py, "«"); } } if (maxYear >= this.maxYear) { if (!this._nav_ny.disabled) { disableControl(this._nav_ny); } } else { if (this._nav_ny.disabled) { enableControl(this._nav_ny, "»"); } } if (((minYear == this.minYear) && (minMonth <= this.minMonth)) || (minYear < this.minYear)) { if (!this._nav_pm.disabled) { disableControl(this._nav_pm); } } else { if (this._nav_pm.disabled) { enableControl(this._nav_pm, "‹"); } } if (((maxYear == this.maxYear) && (maxMonth >= this.maxMonth)) || (maxYear > this.maxYear)) { if (!this._nav_nm.disabled) { disableControl(this._nav_nm); } } else { if (this._nav_nm.disabled) { enableControl(this._nav_nm, "›"); } } //FIX for range checking : spreading of the range on 1 month on the both sides; upperMonth = this.maxMonth + 1; upperYear = this.maxYear; if (upperMonth > 11) { upperMonth -= 12; ++upperYear; } bottomMonth = this.minMonth - 1; bottomYear = this.minYear; if (bottomMonth < 0) { bottomMonth += 12; --bottomYear; } maxDate1 = new Date(maxYear, maxMonth, date.getMonthDays(maxMonth), 23, 59, 59, 999); maxDate2 = new Date(upperYear, upperMonth, 1, 0, 0, 0, 0); minDate1 = new Date(minYear, minMonth, 1, 0, 0, 0, 0); minDate2 = new Date(bottomYear, bottomMonth, date.getMonthDays(bottomMonth), 23, 59, 59, 999); if (maxDate1.getTime() > maxDate2.getTime()) { date.setTime(date.getTime() - (maxDate1.getTime() - maxDate2.getTime())); } if (minDate1.getTime() < minDate2.getTime()) { date.setTime(date.getTime() + (minDate2.getTime() - minDate1.getTime())); } delete maxDate1; delete maxDate2; delete minDate1; delete minDate2; this.firstDayOfWeek = firstDayOfWeek; if (!last) { this.currentDate = date; } this.date = date; (this.date = new Date(this.date)).setDateOnly(date); year = this.date.getFullYear(); month = this.date.getMonth(); var initMonth = date.getMonth(); var mday = this.date.getDate(); var no_days = date.getMonthDays(); // calendar voodoo for computing the first day that would actually be // displayed in the calendar, even if it's from the previous month. // WARNING: this is magic. ;-) var months = new Array(); if (this.numberMonths % this.monthsInRow > 0) { ++rowsOfMonths; } //creating of the array of date objects for every month for (var l = 1; l <= rowsOfMonths; ++l) { months[l] = new Array(); for (var k = 1; (k <= this.monthsInRow) && ((l - 1) * this.monthsInRow + k <= this.numberMonths); ++k) { var tmpDate = new Date(date); if (this.vertical) { var validMonth = date.getMonth() - diffMonth + ((k - 1) * (rowsOfMonths - 1) + (l - 1) + ((last_row < k) ? (last_row) : (k - 1))); } else { var validMonth = date.getMonth() - diffMonth + (l - 1) * this.monthsInRow + k - 1; } if (validMonth < 0) { tmpDate.setFullYear(tmpDate.getFullYear() - 1); validMonth = 12 + validMonth; } if (validMonth > 11) { tmpDate.setFullYear(tmpDate.getFullYear() + 1); validMonth = validMonth - 12; } tmpDate.setDate(1); tmpDate.setMonth(validMonth); var day1 = (tmpDate.getDay() - this.firstDayOfWeek) % 7; if (day1 < 0) day1 += 7; tmpDate.setDate(-day1); tmpDate.setDate(tmpDate.getDate() + 1); months[l][k] = tmpDate; } } var MN = Zapatec.Calendar.i18n(month, "smn"); var weekend = Zapatec.Calendar.i18n("WEEKEND"); var dates = this.multiple ? (this.datesCells = {}) : null; var DATETXT = this.getDateText; //every iteration of the cycle fills one row of months with values; for (var l = 1; l <= rowsOfMonths; ++l) { var row = this.tbody[l].firstChild; for (var i = 7; --i > 0; row = row.nextSibling) { var cell = row.firstChild; var hasdays = false; //this fills one row of days for all the months in the row for (var k = 1; (k <= this.monthsInRow) && ((l - 1) * this.monthsInRow + k <= this.numberMonths); ++k) { date = months[l][k]; if (this.weekNumbers) { cell.className = " day wn"; cell.innerHTML = date.getWeekNumber(); if (k > 1) { Zapatec.Utils.addClass(cell, "month-left-border"); } cell = cell.nextSibling; } row.className = "daysrow"; var iday; for (j = 7; cell && (iday = date.getDate()) && (j > 0); date.setDate(iday+1), ((date.getDate() == iday) ? (date.setHours(1) && date.setDate(iday + 1)) : (false)), cell = cell.nextSibling, --j) { var wday = date.getDay(), dmonth = date.getMonth(), dyear = date.getFullYear(); cell.className = " day"; if ((!this.weekNumbers) && (j == 7) && (k != 1)) { Zapatec.Utils.addClass(cell, "month-left-border"); } if ((j == 1) && (k != this.monthsInRow)) { Zapatec.Utils.addClass(cell, "month-right-border"); } if (this.vertical) { validMonth = initMonth - diffMonth + ((k - 1) * (rowsOfMonths - 1) + (l - 1) + ((last_row < k) ? (last_row) : (k - 1))); } else { validMonth = initMonth - diffMonth + ((l - 1) * this.monthsInRow + k - 1); } if (validMonth < 0) { validMonth = 12 + validMonth; } if (validMonth > 11) { validMonth = validMonth - 12; } var current_month = !(cell.otherMonth = !(dmonth == validMonth)); if (!current_month) { if (this.showsOtherMonths) cell.className += " othermonth"; else { //cell.className = "emptycell"; cell.innerHTML = "

 

"; cell.disabled = true; continue; } } else hasdays = true; cell.disabled = false; cell.innerHTML = DATETXT ? DATETXT(date, dyear, dmonth, iday) : iday; dates && (dates[date.print("%Y%m%d")] = cell); if (this.getDateStatus) { var status = this.getDateStatus(date, dyear, dmonth, iday); if (this.getDateToolTip) { var toolTip = this.getDateToolTip(date, dyear, dmonth, iday); if (toolTip) cell.title = toolTip; } if (status == true) { cell.className += " disabled"; cell.disabled = true; } else { if (/disabled/i.test(status)) cell.disabled = true; cell.className += " " + status; } } if (!cell.disabled) { cell.caldate = [dyear, dmonth, iday]; cell.ttip = "_"; if (!this.multiple && current_month && iday == this.currentDate.getDate() && this.hiliteToday && (dmonth == this.currentDate.getMonth()) && (dyear == this.currentDate.getFullYear())) { cell.className += " selected"; this.currentDateEl = cell; } if (dyear == TY && dmonth == TM && iday == TD) { cell.className += " today"; cell.ttip += Zapatec.Calendar.i18n("PART_TODAY"); } if ((weekend != null) && (weekend.indexOf(wday.toString()) != -1)) { cell.className += cell.otherMonth ? " oweekend" : " weekend"; } } } if (!(hasdays || this.showsOtherMonths)) row.className = "emptyrow"; } if ((i == 1) && (l < rowsOfMonths)) { if (row.className == "emptyrow") { row = row.previousSibling; } cell = row.firstChild; while (cell != null) { Zapatec.Utils.addClass(cell, "month-bottom-border"); cell = cell.nextSibling; } } } } //this.title.firstChild.data = Zapatec.Calendar.i18n(month, "mn") + ", " + year; //filling of all titles for the months if (this.numberMonths == 1) { this.title.innerHTML = Zapatec.Calendar.i18n(month, "mn") + ", " + year; } else { for (var l = 1; l <= rowsOfMonths; ++l) { for (var k = 1; (k <= this.monthsInRow) && ((l - 1) * this.monthsInRow + k <= this.numberMonths); ++k) { if (this.vertical) { validMonth = month - diffMonth + ((k - 1) * (rowsOfMonths - 1) + (l - 1) + ((last_row < k) ? (last_row) : (k - 1))); } else { validMonth = month - diffMonth + (l - 1) * this.monthsInRow + k - 1; } validYear = year; if (validMonth < 0) { --validYear; validMonth = 12 + validMonth; } if (validMonth > 11) { ++validYear; validMonth = validMonth - 12; } this.titles[l][k].innerHTML = Zapatec.Calendar.i18n(validMonth, "mn") + ", " + validYear; } } } this.onSetTime(); //this.table.style.visibility = "visible"; this._initMultipleDates(); this.updateWCH(); // PROFILE // this.showHint("Generated in " + ((new Date()) - today) + " ms"); }; /** * If "multiple dates" is selected (the calendar.multiple property) this * function will highlight cells that display dates that are selected. It is * only called from the _init() function. */ Zapatec.Calendar.prototype._initMultipleDates = function() { if (this.multiple) { for (var i in this.multiple) { var cell = this.datesCells[i]; var d = this.multiple[i]; if (!d) continue; if (cell) cell.className += " selected"; } } }; /** * Given a Date object, this function will "toggle" it in the calendar; that * is, it will select it if not already selected, or unselect it if was already * selected. The array of dates is updated accordingly and the cell object * will be added or removed the appropriate class name ("selected"). Of * course, this only takes place if "multiple dates" is selected. * * @param date [Date] the date to (un)select. */ Zapatec.Calendar.prototype._toggleMultipleDate = function(date) { if (this.multiple) { // MEO var i = 0; for (var ii in this.multiple) {i++;} // var ds = date.print("%Y%m%d"); var cell = this.datesCells[ds]; if (cell) { var d = this.multiple[ds]; if (!d) { //MEO if (i==20) { alert("Your 'Skip List' is full (20). You need to remove a date before you add a new one."); return; } // Zapatec.Utils.addClass(cell, "selected"); this.multiple[ds] = date; } else { Zapatec.Utils.removeClass(cell, "selected"); delete this.multiple[ds]; } } } }; /** * Call this in order to install a function handler that returns a tooltip for * the given date. For example: * * \code * function myHandler(date) { * var str = date.print("%Y/%m/%d"); * if (str == "1979/08/03") { * return "Happy birthday Mishoo! :D"; * } * return str; * } * calendar.setDateToolTipHandler(myHandler); * \endcode * * The tooltip handler is a "unary" function (receives one argument). The * argument passed is a date object and the function should return the tooltip * for that date. * * @param unaryFunction [function] your tooltip handler, as described above */ Zapatec.Calendar.prototype.setDateToolTipHandler = function (unaryFunction) { this.getDateToolTip = unaryFunction; }; /** * Moves the calendar to the specified date. If \em date is not passed, then * the "today" date is assumed. This function does range checking and displays * an error in the status bar if the new date is not allowed by the configured * calendar range. Otherwise, it simply calls _init() with the new date. * * @param date [Date, optional] the date object. */ Zapatec.Calendar.prototype.setDate = function (date, justInit) { // workaround for some bugs in our parseDate code if (!date) date = new Date(); if (!date.equalsTo(this.date)) { var year = date.getFullYear(), m = date.getMonth(); if (year == this.minYear && m < this.minMonth) this.showHint("
" + Zapatec.Calendar.i18n("E_RANGE") + " »»»
"); else if (year == this.maxYear && m > this.maxMonth) this.showHint("
««« " + Zapatec.Calendar.i18n("E_RANGE") + "
"); this._init(this.firstDayOfWeek, date, justInit); } }; /** * Displays a hint in the status bar * * @param text [string] what to display */ Zapatec.Calendar.prototype.showHint = function(text) { this.tooltips.innerHTML = text; }; /** * Refreshes the calendar. Useful if the "disabledHandler" function is * dynamic, meaning that the list of disabled date can change at runtime. Just * call this function if you think that the list of disabled dates should * change. * * This function simply calls _init() using the current firstDayOfWeek and the * current calendar date. */ Zapatec.Calendar.prototype.reinit = function() { this._init(this.firstDayOfWeek, this.date); }; /** * "refresh()" isn't a good name for it: this function _destroys_ the calendar * object and creates another one with the same parameters. This comes in * handy for the calendar wizard where we need to reconstruct the calendar for * virtually any property change. */ Zapatec.Calendar.prototype.refresh = function() { var p = this.isPopup ? null : this.element.parentNode; var x = parseInt(this.element.style.left); var y = parseInt(this.element.style.top); this.destroy(); this.dateStr = this.date; this.create(p); if (this.isPopup) this.showAt(x, y); else this.show(); }; /** * Configures the "firstDayOfWeek" parameter of the calendar. * * @param firstDayOfWeek [int] the new first day of week, 0 for Sunday, 1 for Monday, etc. */ Zapatec.Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) { if (this.firstDayOfWeek != firstDayOfWeek) { this._init(firstDayOfWeek, this.date); //displaying the day names for all the rows of the months var rowsOfMonths = Math.floor(this.numberMonths / this.monthsInRow); if (this.numberMonths % this.monthsInRow > 0) { ++rowsOfMonths; } for (var l = 1; l <= rowsOfMonths; ++l) { this.firstdayname = this.rowsOfDayNames[l]; this._displayWeekdays(); } } }; /** * These functions allow one to install a handler that gets called for each * date when a month is displayed in the calendar. Based on this handler's * return value, that date can be disabled or highlighted using a class name * returned by the handler. * * The handler has the following prototype: * * \code * function dateStatus(date, year, month, day); * \endcode * * While all 4 parameters are passed, the handler can for instance use only the * first one. The year, month and day can all be determined from the first * parameter which is a Date object, but because many people will explicitely * need the year, month or day, we pass them too to speed things up (since we * already know them at the time the handler is called). * * Here is an example of a not-so-complex handler: * * \code * function my_DateStatus(date, year, month, day) { * var str = date.print("%Y/%m/%d"); * if (str >= '2000/01/01' && str <= '2000/12/31') { * return true; // disable all dates in 2000 * } * if (str == "1979/08/03") { * return "birthday"; * } * return false; * } * calendar.setDateStatusHandler(my_DateStatus); * \endcode * * The above handler will disable all dates in 2000 (returns true) and * highlight "1979/08/03" using the class "birthday". From this example we can * notice that the handler can return a boolean value or a string value. The * "boolean" return type is supported for backwards compatibility (function * setDisabledHandler, which is deprecated by setDateStatusHandler). Here's * what the return value means: * * - \b true: the date will be disabled. * - \b false: no action taken (date stays enabled). * - "disabled": the date will be disabled. * - "other_string": the "other_string" will be added to the cell's class name. * - "disabled other_string": the date will be disabled and "disabled other_string" * will be added to cell's class name; this helps one make a date disabled while * still highlighting it in a special way. * * Note that user defined class names should have an associated CSS part * somewhere in the document that specifies how the days will look like; * otherwise, no difference will be visible. For instance, for highlighting * "birthday" dates, one should also add: * * \code * .birthday { color: #f00; } * \endcode * * somewhere in the CSS of the calling document. (the above will make them * red). * * Disabled dates are not clickable; however, if one overrides the "disable" * CSS class, or if the cell also gets an "other_string" class that contains * settings that override the "disabled" class, those cells might not look * "disabled" but still behave so. * * \b WARNING: this function gets called 28 to 31 times each time a month is * displayed. This means that if you are doing crazy computations in order to * determine the status of a day, things \em will slow down dramatically. You * have been warned. * * @param unaryFunction [function] handler that decides the status of the passed date */ Zapatec.Calendar.prototype.setDateStatusHandler = Zapatec.Calendar.prototype.setDisabledHandler = function (unaryFunction) { this.getDateStatus = unaryFunction; }; /** * Configures a range of allowed dates for the calendar. Currently, this * function supports setting a range on a "month granularity". This means, * using it you can't disable part of a month. Both parameters are numeric and * can be float. The range is "inclusive". * * This function might seem somehow complicated, but it's designed in a way * that keeps backwards compatibility with the calendar v0.9.6. * * -# when the end points are integers, the full years will be included. That * is, if you call calendar.setRange(1999, 2005) then only dates between and * including 1999/01/01 and 2005/12/31 will be allowed. * -# when the end points are floats, the decimal part specifies the month. * Therefore, calendar.setRange(1999.03, 2005.05) will allow dates between * and including 1999/03/01 (March 1) and 2005/05/31 (May 31). * * The above statements mean that the following two lines are equivalent: * * \code * calendar.setDate(1999, 2005); // or * calendar.setDate(1999.01, 2005.12); * \endcode * * @param A [number] the range start point * @param Z [number] the range end point */ Zapatec.Calendar.prototype.setRange = function (A, Z) { var m, a = Math.min(A, Z), z = Math.max(A, Z); this.minYear = m = Math.floor(a); this.minMonth = (m == a) ? 0 : Math.ceil((a-m)*100-1); this.maxYear = m = Math.floor(z); this.maxMonth = (m == z) ? 11 : Math.ceil((z-m)*100-1); }; /** * This function sets up the cal.multiple property initially when the flat or popup calendar is created. * If there are dates to be displayed or added to the first time, this property will be filled with those * dates at the beginning. * * multiple -- [Array] - stores the current dates for future use and appending of additional dates */ Zapatec.Calendar.prototype.setMultipleDates = function(multiple) { if (!multiple || typeof multiple == "undefined") return; this.multiple = {}; for (var i = multiple.length; --i >= 0;) { var d = multiple[i]; var ds = d.print("%Y%m%d"); this.multiple[ds] = d; } }; /** * Call the calendar's callback function, if defined. The passed argument * is the date object. This is a public function meant to be invoked by the user so that s/he can * have more controls on what to do with the dates selected. */ Zapatec.Calendar.prototype.submitFlatDates = function() { if (typeof this.params.flatCallback == "function") { //Specify the pre-set sorting so that Zapatec.Utils will sort the multiple dates accordingly. //Default to "asc" if it does not equal to "asc" or "desc". Zapatec.Utils.sortOrder = (this.sortOrder!="asc" && this.sortOrder!="desc" && this.sortOrder!="none") ? "none" : this.sortOrder; if ( this.multiple && (Zapatec.Utils.sortOrder != "none") ) { var dateArray = new Array(); for (var i in this.multiple) { var currentDate = this.multiple[i]; // sometimes the date is not actually selected, that's why we need to check. if (currentDate) { // and push it in the "dateArray", in case one triggers the calendar again. dateArray[dateArray.length] = currentDate; } //Now let's sort the dateArray array dateArray.sort(Zapatec.Utils.compareDates); } this.multiple = {}; for (var i = 0; i < dateArray.length; i++) { var d = dateArray[i]; var ds = d.print("%Y%m%d"); this.multiple[ds] = d; } } //Else no need to sort the multiple dates. this.params.flatCallback(this); } } /** * Call the calendar's "onSelected" handler, if defined. The passed arguments * are the date object and a string with the date formatted by the specifier in * calendar.dateFormat. */ Zapatec.Calendar.prototype.callHandler = function () { if (this.onSelected) { this.onSelected(this, this.date.print(this.dateFormat)); } }; /** * This function updates the calendar history and saves the cookie. The * history is a string containing date and time formatted as "%Y/%m/%d/%H/%M" * (that is, all time parts separated by slashes, in a "most significant to * least significant order"). Further, such formats are separated by commas, * and the current calendar date is added the first, then the cookie saved. */ Zapatec.Calendar.prototype.updateHistory = function () { var a, i, d, tmp, s, str = "", len = Zapatec.Calendar.prefs.hsize - 1; if (Zapatec.Calendar.prefs.history) { a = Zapatec.Calendar.prefs.history.split(/,/); i = 0; while (i < len && (tmp = a[i++])) { s = tmp.split(/\//); d = new Date(parseInt(s[0], 10), parseInt(s[1], 10)-1, parseInt(s[2], 10), parseInt(s[3], 10), parseInt(s[4], 10)); if (!d.dateEqualsTo(this.date)) str += "," + tmp; } } Zapatec.Calendar.prefs.history = this.date.print("%Y/%m/%d/%H/%M") + str; Zapatec.Calendar.savePrefs(); }; /** * Calls the calendar's onClose handler, if present. Either way, this function * calls updateHistory() in order to update the history cookie. */ Zapatec.Calendar.prototype.callCloseHandler = function () { if (this.dateClicked) { this.updateHistory(); } if (this.onClose) { this.onClose(this); } this.hideShowCovered(); }; /** Removes the calendar object from the DOM tree and destroys it. */ Zapatec.Calendar.prototype.destroy = function () { this.hide(); // this also removes keyboard events :-\ Zapatec.Utils.destroy(this.element); Zapatec.Utils.destroy(this.WCH); Zapatec.Calendar._C = null; window.calendar = null; }; /** * Moves the calendar element to a different section in the DOM tree (changes * its parent). This might be useful for flat calendars. * * @param new_parent [HTMLElement] the new parent for the calendar. */ Zapatec.Calendar.prototype.reparent = function (new_parent) { var el = this.element; el.parentNode.removeChild(el); new_parent.appendChild(el); }; /** * This gets called when the user presses a mouse button anywhere in the * document, if the calendar is shown. If the click was outside the open * calendar this function closes it and stops the event from propagating. * * @param ev [Event] the event object. * @return false if the event is stopped. */ Zapatec.Calendar._checkCalendar = function(ev) { if (!window.calendar) { return false; } var el = Zapatec.is_ie ? Zapatec.Utils.getElement(ev) : Zapatec.Utils.getTargetElement(ev); for (; el != null && el != calendar.element; el = el.parentNode); if (el == null) { // calls closeHandler which should hide the calendar. window.calendar.callCloseHandler(); return Zapatec.Utils.stopEvent(ev); } }; /** * Updates the calendar "WCH" (windowed controls hider). A WCH is an * "invention" (read: "miserable hack") that works around one of the most * common and old bug in Internet Explorer: the SELECT boxes or IFRAMES show on * top of any other HTML element. This function makes sure that the WCH covers * correctly the calendar element and another element if passed. * * @param other_el [HTMLElement, optional] a second element that the WCH should cover. */ Zapatec.Calendar.prototype.updateWCH = function(other_el) { Zapatec.Utils.setupWCH_el(this.WCH, this.element, other_el); }; /** * Displays a hidden calendar. It walks quickly through the HTML elements and * makes sure that they don't have "hover" or "active" class names that might * be there from a previous time the same calendar was displayed. This * function also calls updateWCH() and hideShowCovered() to workaround * miserable IE bugs. * * If the calendar is a popup calendar and doesn't have the "noGrab" property * set, this function also adds document event handlers to intercept key events * or to close the calendar when one clicks outside it. */ Zapatec.Calendar.prototype.show = function () { var rows = this.table.getElementsByTagName("tr"); for (var i = rows.length; i > 0;) { var row = rows[--i]; Zapatec.Utils.removeClass(row, "rowhilite"); var cells = row.getElementsByTagName("td"); for (var j = cells.length; j > 0;) { var cell = cells[--j]; Zapatec.Utils.removeClass(cell, "hilite"); Zapatec.Utils.removeClass(cell, "active"); } } this.element.style.display = "block"; this.hidden = false; if (this.isPopup) { this.updateWCH(); window.calendar = this; if (!this.noGrab) { Zapatec.Utils.addEvent(window.document, "keydown", Zapatec.Calendar._keyEvent); Zapatec.Utils.addEvent(window.document, "keypress", Zapatec.Calendar._keyEvent); Zapatec.Utils.addEvent(window.document, "mousedown", Zapatec.Calendar._checkCalendar); } } this.hideShowCovered(); }; /** * Hides the calendar. Also removes any "hilite" from the class of any TD * element. Unregisters the document event handlers for key presses and * mousedown. */ Zapatec.Calendar.prototype.hide = function () { if (this.isPopup) { Zapatec.Utils.removeEvent(window.document, "keydown", Zapatec.Calendar._keyEvent); Zapatec.Utils.removeEvent(window.document, "keypress", Zapatec.Calendar._keyEvent); Zapatec.Utils.removeEvent(window.document, "mousedown", Zapatec.Calendar._checkCalendar); } this.element.style.display = "none"; Zapatec.Utils.hideWCH(this.WCH); this.hidden = true; this.hideShowCovered(); }; /** * Shows the calendar at a given absolute position (beware that, depending on * the calendar element style -- position property -- this might be relative to * the parent's containing rectangle). * * @param x [int] the X position * @param y [int] the Y position */ Zapatec.Calendar.prototype.showAt = function (x, y) { var s = this.element.style; s.left = x + "px"; s.top = y + "px"; this.show(); }; /** * This function displays the calendar near a given "anchor" element, according * to some rules passed in \em opts. The \em opts argument is a string * containing one or 2 letters. The first letter decides the vertical * alignment, and the second letter decides the horizontal alignment relative * to the anchor element. Following we will describe these options; in parens * we will use simple descriptions like "top to bottom" which means that the * top margin of the calendar is aligned with the bottom margin of the object. * * \b Vertical align: * * - T -- the calendar is completely above the element (bottom to top) * - t -- the calendar is above the element but might overlap it (bottom to bottom) * - C -- the calendar is vertically centered to the element * - b -- the calendar is below the element but might overlap it (top to top) * - B -- the calendar is completely below the element (top to bottom) * * \b Horizontal align (defaults to 'l' if no letter passed): * * - L -- the calendar is completely to the left of the element (right to left) * - l -- the calendar is to the left of the element but might overlap it (right to right) * - C -- the calendar is horizontally centered to the element * - r -- the calendar is to the right of the element but might overlap it (left to left) * - R -- the calendar is completely to the right of the element (left to right) * * @param el [HTMLElement] the anchor element * @param opts [string, optional] the align options, as described above. Defaults to "Bl" if nothing passed. */ Zapatec.Calendar.prototype.showAtElement = function (el, opts) { var self = this; var p = Zapatec.Utils.getAbsolutePos(el); if (!opts || typeof opts != "string") { this.showAt(p.x, p.y + el.offsetHeight); return true; } // MO: Using jQuery to get position 2/1/10 var position=$('#'+el.id).offset(); p.x=position.left; p.y=position.top; this.element.style.display = "block"; var w = self.element.offsetWidth; var h = self.element.offsetHeight; self.element.style.display = "none"; var valign = opts.substr(0, 1); var halign = "l"; if (opts.length > 1) { halign = opts.substr(1, 1); } // vertical alignment switch (valign) { case "T": p.y -= h; break; case "B": p.y += el.offsetHeight; break; case "C": p.y += (el.offsetHeight - h) / 2; break; case "t": p.y += el.offsetHeight - h; break; case "b": break; // already there } // horizontal alignment switch (halign) { case "L": p.x -= w; break; case "R": p.x += el.offsetWidth; break; case "C": p.x += (el.offsetWidth - w) / 2; break; case "l": p.x += el.offsetWidth - w; break; case "r": break; // already there } p.width = w; p.height = h + 40; self.monthsCombo.style.display = "none"; //MO 2/5/2009 (for IE) Zapatec.Utils.fixBoxPosition(p); self.showAt(p.x, p.y); }; /** * Customizes the date format that will be reported to the onSelect handler. * The format string is described in Date.prototype.print(). * * @param str [string] the date format. */ Zapatec.Calendar.prototype.setDateFormat = function (str) { this.dateFormat = str; }; /** Customizes the tooltip date format. See * Zapatec.Calendar.prototype.setDateFormat() for a description of the \em str * format. * * @param str [string] the "tooltip" date format */ Zapatec.Calendar.prototype.setTtDateFormat = function (str) { this.ttDateFormat = str; }; /** * Tries to identify the date represented in a string. If successful it also * calls this.setDate which moves the calendar to the given date. * * @param str [string] a date * @param fmt [string] the format to try to parse \em str in */ Zapatec.Calendar.prototype.parseDate = function (str, fmt) { // Konqueror if (!str) return this.setDate(this.date); if (!fmt) fmt = this.dateFormat; var date = Date.parseDate(str, fmt); return this.setDate(date); }; /** * This function hides or shows "windowed controls" accordingly so that the * calendar isn't obtured by any such control. Historically, this function was * used for any browser. It simply walks through all SELECT, IFRAME and APPLET * elements present in the DOM, checks if they intersect the calendar and hides * them if so or makes them visible otherwise. This approacy has a number of * problems, the most important being that if the end-user's code contains a * SELECT which is already hidden and it must stay hidden, it will still be * made visible when the calendar closes. The other obvious problem is that * there's an ugly effect generated by elements that suddenly (dis)appear when * you drag the calendar around the screen. * * Currently this function is only used on IE5.0/Windows, browser that leaves * no room for a better workaround to this problem. For IE5.5+/Windows an * workaround is possible, albeit amazingly ugly (WCH). For other browsers * such crazy techniques are not anymore useful because the bugs related to * windowed controls were fixed. */ Zapatec.Calendar.prototype.hideShowCovered = function () { if (!Zapatec.is_ie5) return; var self = this; function getVisib(obj){ var value = obj.style.visibility; if (!value) { if (window.document.defaultView && typeof (window.document.defaultView.getComputedStyle) == "function") { // Gecko, W3C if (!Zapatec.is_khtml) value = window.document.defaultView. getComputedStyle(obj, "").getPropertyValue("visibility"); else value = ''; } else if (obj.currentStyle) { // IE value = obj.currentStyle.visibility; } else value = ''; } return value; }; var tags = ["applet", "iframe", "select"]; var el = self.element; var p = Zapatec.Utils.getAbsolutePos(el); var EX1 = p.x; var EX2 = el.offsetWidth + EX1; var EY1 = p.y; var EY2 = el.offsetHeight + EY1; for (var k = tags.length; k > 0; ) { var ar = window.document.getElementsByTagName(tags[--k]); var cc = null; for (var i = ar.length; i > 0;) { cc = ar[--i]; p = Zapatec.Utils.getAbsolutePos(cc); var CX1 = p.x; var CX2 = cc.offsetWidth + CX1; var CY1 = p.y; var CY2 = cc.offsetHeight + CY1; if (self.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { if (!cc.__msh_save_visibility) { cc.__msh_save_visibility = getVisib(cc); } cc.style.visibility = cc.__msh_save_visibility; } else { if (!cc.__msh_save_visibility) { cc.__msh_save_visibility = getVisib(cc); } cc.style.visibility = "hidden"; } } } }; /** * This function displays the week day names in the calendar header, according * to the current "firstDayOfWeek". */ Zapatec.Calendar.prototype._displayWeekdays = function () { var fdow = this.firstDayOfWeek; var cell = this.firstdayname; var weekend = Zapatec.Calendar.i18n("WEEKEND"); //displaying one row of day names for every month in the row for (k = 1; (k <= this.monthsInRow) && (cell); ++k) { for (var i = 0; i < 7; ++i) { cell.className = " day name"; if ((!this.weekNumbers) && (i == 0) && (k != 1)) { Zapatec.Utils.addClass(cell, "month-left-border"); } if ((i == 6) && (k != this.monthsInRow)) { Zapatec.Utils.addClass(cell, "month-right-border"); } var realday = (i + fdow) % 7; if ((this.params && this.params.fdowClick) || i) { if (Zapatec.Calendar.i18n("DAY_FIRST") != null) { cell.ttip = Zapatec.Calendar.i18n("DAY_FIRST").replace("%s", Zapatec.Calendar.i18n(realday, "dn")); } cell.navtype = 100; cell.calendar = this; cell.fdow = realday; Zapatec.Calendar._add_evs(cell); } if ((weekend != null) && (weekend.indexOf(realday.toString()) != -1)) { Zapatec.Utils.addClass(cell, "weekend"); } cell.innerHTML = Zapatec.Calendar.i18n((i + fdow) % 7, "sdn"); cell = cell.nextSibling; } if (this.weekNumbers && cell) { cell = cell.nextSibling; } } }; /** * Compare two dates in either ascending or descending order. To be used for * the multiple dates feature. This function is passed as an argument to the * sort routine which calls it to compare dates. * * @param date1 [date] first date * @param date2 [date] second date */ Zapatec.Utils.compareDates = function(date1, date2) { if (Zapatec.Calendar.prefs.sortOrder == "asc") return date1 - date2; else //"desc"ending order return date2 - date1; } /** \internal Hides all combo boxes that might be displayed. */ Zapatec.Calendar.prototype._hideCombos = function () { this.monthsCombo.style.display = "none"; this.yearsCombo.style.display = "none"; this.histCombo.style.display = "none"; this.updateWCH(); }; /** \internal Starts dragging the element. */ Zapatec.Calendar.prototype._dragStart = function (ev) { ev || (ev = window.event); if (this.dragging) { return; } this.dragging = true; var posX = ev.clientX + window.document.body.scrollLeft; var posY = ev.clientY + window.document.body.scrollTop; var st = this.element.style; this.xOffs = posX - parseInt(st.left); this.yOffs = posY - parseInt(st.top); Zapatec.Utils.addEvent(window.document, "mousemove", Zapatec.Calendar.calDragIt); Zapatec.Utils.addEvent(window.document, "mouseover", Zapatec.Calendar.calDragIt); Zapatec.Utils.addEvent(window.document, "mouseup", Zapatec.Calendar.calDragEnd); }; // BEGIN: DATE OBJECT PATCHES /** \defgroup DateExtras Augmenting the Date object with some utility functions * and variables. */ //@{ Date._MD = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; /**< Number of days in each month */ Date.SECOND = 1000; /**< One second has 1000 milliseconds. */ Date.MINUTE = 60 * Date.SECOND; /**< One minute has 60 seconds. */ Date.HOUR = 60 * Date.MINUTE; /**< One hour has 60 minutes. */ Date.DAY = 24 * Date.HOUR; /**< One day has 24 hours. */ Date.WEEK = 7 * Date.DAY; /**< One week has 7 days. */ /** Returns the number of days in the month. The \em month parameter is * optional; if not passed, the current month of \b this Date object is * assumed. * * @param month [int, optional] the month number, 0 for January. */ Date.prototype.getMonthDays = function(month) { var year = this.getFullYear(); if (typeof month == "undefined") { month = this.getMonth(); } if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) { return 29; } else { return Date._MD[month]; } }; /** Returns the number of the current day in the current year. */ Date.prototype.getDayOfYear = function() { var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0); var time = now - then; return Math.floor(time / Date.DAY); }; /** Returns the number of the week in year, as defined in ISO 8601. */ Date.prototype.getWeekNumber = function() { var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); var DoW = d.getDay(); d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu var ms = d.valueOf(); // GMT d.setMonth(0); d.setDate(4); // Thu in Week 1 return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1; }; /** Checks dates equality. Checks time too. */ Date.prototype.equalsTo = function(date) { return ((this.getFullYear() == date.getFullYear()) && (this.getMonth() == date.getMonth()) && (this.getDate() == date.getDate()) && (this.getHours() == date.getHours()) && (this.getMinutes() == date.getMinutes())); }; /** Checks dates equality. Ignores time. */ Date.prototype.dateEqualsTo = function(date) { return ((this.getFullYear() == date.getFullYear()) && (this.getMonth() == date.getMonth()) && (this.getDate() == date.getDate())); }; /** Set only the year, month, date parts (keep existing time) */ Date.prototype.setDateOnly = function(date) { var tmp = new Date(date); this.setDate(1); this.setFullYear(tmp.getFullYear()); this.setMonth(tmp.getMonth()); this.setDate(tmp.getDate()); }; /** Prints the date in a string according to the given format. * * The format (\b str) may contain the following specialties: * * - %%a - Abbreviated weekday name * - %%A - Full weekday name * - %%b - Abbreviated month name * - %%B - Full month name * - %%C - Century number * - %%d - The day of the month (00 .. 31) * - %%e - The day of the month (0 .. 31) * - %%H - Hour (00 .. 23) * - %%I - Hour (01 .. 12) * - %%j - The day of the year (000 .. 366) * - %%k - Hour (0 .. 23) * - %%l - Hour (1 .. 12) * - %%m - Month (01 .. 12) * - %%M - Minute (00 .. 59) * - %%n - A newline character * - %%p - "PM" or "AM" * - %%P - "pm" or "am" * - %%S - Second (00 .. 59) * - %%s - Number of seconds since Epoch * - %%t - A tab character * - %%W - The week number (as per ISO 8601) * - %%u - The day of week (1 .. 7, 1 = Monday) * - %%w - The day of week (0 .. 6, 0 = Sunday) * - %%y - Year without the century (00 .. 99) * - %%Y - Year including the century (ex. 1979) * - %%% - A literal %% character * * They are almost the same as for the POSIX strftime function. * * @param str [string] the format to print date in. */ Date.prototype.print = function (str) { var m = this.getMonth(); var d = this.getDate(); var y = this.getFullYear(); var wn = this.getWeekNumber(); var w = this.getDay(); var s = {}; var hr = this.getHours(); var pm = (hr >= 12); var ir = (pm) ? (hr - 12) : hr; var dy = this.getDayOfYear(); if (ir == 0) ir = 12; var min = this.getMinutes(); var sec = this.getSeconds(); s["%a"] = Zapatec.Calendar.i18n(w, "sdn"); // abbreviated weekday name [FIXME: I18N] s["%A"] = Zapatec.Calendar.i18n(w, "dn"); // full weekday name s["%b"] = Zapatec.Calendar.i18n(m, "smn"); // abbreviated month name [FIXME: I18N] s["%B"] = Zapatec.Calendar.i18n(m, "mn"); // full month name // FIXME: %c : preferred date and time representation for the current locale s["%C"] = 1 + Math.floor(y / 100); // the century number s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31) s["%e"] = d; // the day of the month (range 1 to 31) // FIXME: %D : american date style: %m/%d/%y // FIXME: %E, %F, %G, %g, %h (man strftime) s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format) s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format) s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366) s["%k"] = hr ? hr : "0"; // hour, range 0 to 23 (24h format) s["%l"] = ir; // hour, range 1 to 12 (12h format) s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12 s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59 s["%n"] = "\n"; // a newline character s["%p"] = pm ? "PM" : "AM"; s["%P"] = pm ? "pm" : "am"; // FIXME: %r : the time in am/pm notation %I:%M:%S %p // FIXME: %R : the time in 24-hour notation %H:%M s["%s"] = Math.floor(this.getTime() / 1000); s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59 s["%t"] = "\t"; // a tab character // FIXME: %T : the time in 24-hour notation (%H:%M:%S) s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn; s["%u"] = (w == 0) ? 7 : w; // the day of the week (range 1 to 7, 1 = MON) s["%w"] = w ? w : "0"; // the day of the week (range 0 to 6, 0 = SUN) // FIXME: %x : preferred date representation for the current locale without the time // FIXME: %X : preferred time representation for the current locale without the date s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99) s["%Y"] = y; // year with the century s["%%"] = "%"; // a literal '%' character var re = /%./g; if (!Zapatec.is_ie5 && !Zapatec.is_khtml && !Zapatec.is_mac_ie) return str.replace(re, function (par) { return s[par] || par; }); var a = str.match(re); for (var i = 0; i < a.length; i++) { var tmp = s[a[i]]; if (tmp) { re = new RegExp(a[i], 'g'); str = str.replace(re, tmp); } } return str; }; /** * Parses a date from a string in the specified format. * * @param str [string] the date as a string * @param fmt [string] the format to try to parse the date in * * @return [Date] a date object containing the parsed date or \b null if for * some reason the date couldn't be parsed. */ Date.parseDate = function (str, fmt) { // Konqueror if (!str) return new Date(); var y = 0; var m = -1; var d = 0; var a = str.split(/\W+/); var b = fmt.match(/%./g); var i = 0, j = 0; var hr = 0; var min = 0; for (i = 0; i < a.length; ++i) { if (!a[i]) continue; switch (b[i]) { case "%d": case "%e": d = parseInt(a[i], 10); break; case "%m": m = parseInt(a[i], 10) - 1; break; case "%Y": case "%y": y = parseInt(a[i], 10); (y < 100) && (y += (y > 29) ? 1900 : 2000); break; case "%b": case "%B": for (j = 0; j < 12; ++j) if (Zapatec.Calendar.i18n(j, "mn").substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; } break; case "%H": case "%I": case "%k": case "%l": hr = parseInt(a[i], 10); break; case "%P": case "%p": if (/pm/i.test(a[i]) && hr < 12) hr += 12; break; case "%M": min = parseInt(a[i], 10); break; } } //Fix for the mm/dd/yy bug var validDate = !isNaN(y) && !isNaN(m) && !isNaN(d) && !isNaN(hr) && !isNaN(min); if (!validDate) {return null;} if (y != 0 && m != -1 && d != 0) return new Date(y, m, d, hr, min, 0); y = 0; m = -1; d = 0; for (i = 0; i < a.length; ++i) { if (a[i].search(/[a-zA-Z]+/) != -1) { var t = -1; for (j = 0; j < 12; ++j) if (Zapatec.Calendar.i18n(j, "mn").substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; } if (t != -1) { if (m != -1) d = m+1; m = t; } } else if (parseInt(a[i], 10) <= 12 && m == -1) { m = a[i]-1; } else if (parseInt(a[i], 10) > 31 && y == 0) { y = parseInt(a[i], 10); (y < 100) && (y += (y > 29) ? 1900 : 2000); } else if (d == 0) { d = a[i]; } } if (y == 0) { var today = new Date(); y = today.getFullYear(); } if (m != -1 && d != 0) return new Date(y, m, d, hr, min, 0); return null; }; Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; /**< save a reference to the original setFullYear function */ /** * This function replaces the original Date.setFullYear() with a "safer" * function which makes sure that the month or date aren't modified (unless in * the exceptional case where the date is February 29 but the new year doesn't * contain it). * * @param y [int] the new year to move this date to */ Date.prototype.setFullYear = function(y) { var d = new Date(this); d.__msh_oldSetFullYear(y); if (d.getMonth() != this.getMonth()) this.setDate(28); this.__msh_oldSetFullYear(y); }; /** * This function compares only years, months and days of two date objects. * * @return [int] -1 if date1>date2, 1 if date2>date1 or 0 if they are equal * * @param date1 [Date] first date to compare * @param date1 [Date] second date to compare */ Date.prototype.compareDatesOnly = function (date1,date2) { var year1 = date1.getYear(); var year2 = date2.getYear(); var month1 = date1.getMonth(); var month2 = date2.getMonth(); var day1 = date1.getDate(); var day2 = date2.getDate(); if (year1 > year2) { return -1; } if (year2 > year1) { return 1; } //years are equal if (month1 > month2) { return -1; } if (month2 > month1) { return 1; } //years and months are equal if (day1 > day2) { return -1; } if (day2 > day1) { return 1; } //days are equal return 0; } //@} // END: DATE OBJECT PATCHES window.calendar = null; /**< global object that remembers the calendar */ // initialize the preferences object; // embed it in a try/catch so we don't have any surprises try { Zapatec.Calendar.loadPrefs(); } catch(e) {}; Zapatec.Utils.addEvent(window, "load", Zapatec.Utils.checkActivation); /* * The Zapatec DHTML Calendar * * Copyright (c) 2004 by Zapatec, Inc. * http://www.zapatec.com * 1700 MLK Way, Berkeley, California, * 94709, U.S.A. * All rights reserved. * * Original version written by Mihai Bazon, * http://www.bazon.net/mishoo/calendar.epl * * This file defines helper functions for setting up the calendar. They are * intended to help non-programmers get a working calendar on their site * quickly. This script should not be seen as part of the calendar. It just * shows you what one can do with the calendar, while in the same time * providing a quick and simple method for setting it up. If you need * exhaustive customization of the calendar creation process feel free to * modify this code to suit your needs (this is recommended and much better * than modifying calendar.js itself). */ // $Id: calendar-setup.js 1031 2005-11-05 19:26:46Z ken $ //test for the right path Zapatec.Setup = function () {}; Zapatec.Setup.test = true; /** * This function "patches" an input field (or other element) to use a calendar * widget for date selection. * * Note that you can use the Zapatec DHTML Calendar Wizard and generate the code * and modify the results. * The "params" is a single object that can have the following properties: * * \code * prop. name | description * ------------------------------------------------------------------------------------------------- * inputField | the ID of an input field to store the date * displayArea | the ID of a DIV or other element to show the date * button | ID of a button or other element that will trigger the calendar * eventName | event that will trigger the calendar, without the "on" prefix (default: "click") * closeEventName| event that will close the calendar (i.e. one can use "focus" for eventName and "blur" for closeEventName) * ifFormat | date format that will be stored in the input field * daFormat | the date format that will be used to display the date in displayArea * singleClick | (true/false) wether the calendar is in single click mode or not (default: true) * firstDay | numeric: 0 to 6. "0" means display Sunday first, "1" means display Monday first, etc. * align | alignment (default: "Br"); if you don't know what's this see the calendar documentation * range | array with 2 elements. Default: [1900.0, 2999.12] -- the range of years available * weekNumbers | (true/false) if it's true (default) the calendar will display week numbers * flat | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID * flatCallback | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar) * disableFunc | function that receives a JS Date object and should return true if that date has to be disabled in the calendar * onSelect | function that gets called when a date is selected. You don't _have_ to supply this (the default is generally okay) * onClose | function that gets called when the calendar is closed. [default] * onUpdate | function that gets called after the date is updated in the input field. Receives a reference to the calendar. * date | the date that the calendar will be initially displayed to * showsTime | default: false; if true the calendar will include a time selector * timeFormat | the time format; can be "12" or "24", default is "12" * electric | if true (default) then given fields/date areas are updated for each move; otherwise they're updated only on close * sortOrder | ("asc"(ending)/"desc"(ending)/"none"). If "asc" (default), order of the multiple dates (when multiple dates is on) will be sorted in ascending order. Otherwise, it will be sorted in descending order. "none" means no sorting is needed. * step | configures the step of the years in drop-down boxes; default: 2 * position | configures the calendar absolute position; default: null * cache | if "true" (but default: "false") it will reuse the same calendar object, where possible * showOthers | if "true" (but default: "false") it will show days from other months too * saveDate | if set (default unset) will save a cookie for this duration. * numberMonths | Have the calendar display multiple months * controlMonth | When displaying multiple months, this will be the control month. Default 1. * vertical | When displaying multiple months, months can progress in a vertical or horizontal way. Horizontal is the default. * monthsInRow | When displaying multiple months how many months in a horizontal row. Works both in vertical and horizontal mode. Default numberMonths * fdowClick | Allow click on Days of Week 1st day * titleHtml | Html you can put in title of calendar * * \endcode * * None of them is required, they all have default values. However, if you * pass none of "inputField", "displayArea" or "button" you'll get a warning * saying "nothing to setup". */ Zapatec.Calendar.setup = function (params) { function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } }; param_default("inputField", null); param_default("displayArea", null); param_default("button", null); param_default("eventName", "click"); param_default("ifFormat", "%Y/%m/%d"); param_default("daFormat", "%Y/%m/%d"); param_default("singleClick", true); param_default("disableFunc", null); param_default("dateStatusFunc", params["disableFunc"]); // takes precedence if both are defined param_default("dateText", null); param_default("firstDay", null); param_default("align", "Br"); param_default("range", [1900, 2999]); param_default("weekNumbers", true); param_default("flat", null); param_default("flatCallback", null); param_default("onSelect", null); param_default("onClose", null); param_default("onUpdate", null); param_default("date", null); param_default("showsTime", false); param_default("sortOrder", "asc"); param_default("timeFormat", "24"); param_default("timeInterval", null); param_default("electric", true); param_default("step", 2); param_default("position", null); param_default("cache", false); param_default("showOthers", false); param_default("multiple", null); param_default("saveDate", null); param_default("fdowClick", false); param_default("titleHtml", null); if ((params.numberMonths > 12) || (params.numberMonths < 1)) { params.numberMonths = 1; } else { param_default("numberMonths", 1); } if (params.numberMonths > 1) { params.showOthers = false; } params.numberMonths = parseInt(params.numberMonths, 10); if ((params.controlMonth > params.numberMonths) || (params.controlMonth < 1)) { params.controlMonth = 1; } else { param_default("controlMonth", 1); } params.controlMonth = parseInt(params.controlMonth, 10); param_default("vertical", false); if (params.monthsInRow > params.numberMonths) { params.monthsInRow = params.numberMonths; } param_default("monthsInRow", params.numberMonths); params.monthsInRow = parseInt(params.monthsInRow, 10); if (params.multiple) { params.singleClick = false; } var tmp = ["inputField", "displayArea", "button"]; for (var i in tmp) { if (typeof params[tmp[i]] == "string") { params[tmp[i]] = document.getElementById(params[tmp[i]]); } } if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) { alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code"); return false; } if (((params.timeInterval) && ((params.timeInterval !== Math.floor(params.timeInterval)) || ((60 % params.timeInterval !== 0) && (params.timeInterval % 60 !== 0)))) || (params.timeInterval > 360)) { alert("timeInterval option can only have the following number of minutes:\n1, 2, 3, 4, 5, 6, 10, 15, 30, 60, 120, 180, 240, 300, 360 "); params.timeInterval = null; } if (params.date && !Date.parse(params.date)) { //alert("Start Date Invalid: " + params.date + ".\nSee date option.\nDefaulting to today."); params.date = null; } if (params.saveDate) { //If saveDate is on We're saving the date in a cookie param_default("cookiePrefix", window.location.href + "--" + params.button.id); //fetch the cookie var cookieName = params.cookiePrefix; var newdate = Zapatec.Utils.getCookie(cookieName); if (newdate != null) { //if there's a cookie //set the value of the text field document.getElementById(params.inputField.id).value = newdate; } } function onSelect(cal) { var p = cal.params; var update = (cal.dateClicked || p.electric); if (update && p.flat) { if (typeof p.flatCallback == "function") { if (!p.multiple) //User can call function submitFlatDates directly in Calendar object to handle the submission of multiple dates. p.flatCallback(cal); } else alert("No flatCallback given -- doing nothing."); return false; } if (update && p.inputField) { p.inputField.value = cal.currentDate.print(p.ifFormat); if (typeof p.inputField.onchange == "function") p.inputField.onchange(); } if (update && p.displayArea) p.displayArea.innerHTML = cal.currentDate.print(p.daFormat); if (update && p.singleClick && cal.dateClicked) cal.callCloseHandler(); if (update && typeof p.onUpdate == "function") p.onUpdate(cal); if (p.saveDate) { //save date in cookie //unique name of the cookie is the name of the button + href var cookieName = p.cookiePrefix; Zapatec.Utils.writeCookie(cookieName, p.inputField.value, null, '/', p.saveDate); } }; if (params.flat != null) { if (typeof params.flat == "string") params.flat = document.getElementById(params.flat); if (!params.flat) { alert("Calendar.setup:\n Flat specified but can't find parent."); return false; } var cal = new Zapatec.Calendar(params.firstDay, params.date, params.onSelect || onSelect); cal.showsOtherMonths = params.showOthers; cal.showsTime = params.showsTime; cal.time24 = (params.timeFormat == "24"); cal.timeInterval = params.timeInterval; cal.params = params; cal.weekNumbers = params.weekNumbers; cal.sortOrder = params.sortOrder.toLowerCase(); cal.setRange(params.range[0], params.range[1]); cal.setDateStatusHandler(params.dateStatusFunc); cal.getDateText = params.dateText; cal.numberMonths = params.numberMonths; cal.controlMonth = params.controlMonth; cal.vertical = params.vertical; cal.yearStep = params.step; cal.monthsInRow = params.monthsInRow; if (params.ifFormat) { cal.setDateFormat(params.ifFormat); } if (params.inputField && params.inputField.type == "text" && typeof params.inputField.value == "string") { cal.parseDate(params.inputField.value); } if (params.multiple) { cal.setMultipleDates(params.multiple); } cal.create(params.flat); cal.show(); return cal; } var triggerEl = params.button || params.displayArea || params.inputField; triggerEl["on" + params.eventName] = function() { var dateEl = params.inputField || params.displayArea; //FIX for Enter key! if (triggerEl.blur) {triggerEl.blur();} var dateFmt = params.inputField ? params.ifFormat : params.daFormat; var mustCreate = false; var cal = window.calendar; // Exit if calendar is NOT hidden and user tries to create another calendar (Click or SpaceBar) // Rev 1.9 - this needs to be integrated, it broke the multiple month feature //if (cal && !cal.hidden) return false; if (!(cal && params.cache)) { window.calendar = cal = new Zapatec.Calendar(params.firstDay, params.date, params.onSelect || onSelect, params.onClose || function(cal) { if (params.cache) cal.hide(); else cal.destroy(); }); cal.showsTime = params.showsTime; cal.time24 = (params.timeFormat == "24"); cal.timeInterval = params.timeInterval; cal.weekNumbers = params.weekNumbers; cal.numberMonths = params.numberMonths; cal.controlMonth = params.controlMonth; cal.vertical = params.vertical; cal.monthsInRow = params.monthsInRow; cal.historyDateFormat = params.ifFormat || params.daFormat; mustCreate = true; } else { if (params.date) cal.setDate(params.date); cal.hide(); } if (params.multiple) { cal.setMultipleDates(params.multiple); } cal.showsOtherMonths = params.showOthers; cal.yearStep = params.step; cal.setRange(params.range[0], params.range[1]); cal.params = params; cal.setDateStatusHandler(params.dateStatusFunc); cal.getDateText = params.dateText; cal.setDateFormat(dateFmt); if (mustCreate) cal.create(); if (dateEl) { var dateValue; //figure out if the it's in value or innerHTML if (dateEl.value) { dateValue = dateEl.value; } else { dateValue = dateEl.innerHTML; } if (dateValue != "") { //if there is a date to initialize from var parsedDate = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt); //This check for when webmaster initializes the box with something like //"check in" if (parsedDate != null) { //if it's parsable cal.setDate(parsedDate); } } } if (!params.position) cal.showAtElement(params.button || params.displayArea || params.inputField, params.align); else cal.showAt(params.position[0], params.position[1]); return false; }; if (params.closeEventName) { triggerEl["on" + params.closeEventName] = function() { if (window.calendar) window.calendar.callCloseHandler(); }; } return cal; }; // ** I18N // Calendar EN language // Author: Mihai Bazon, // Encoding: any // Distributed under the same terms as the calendar itself. // For translators: please use UTF-8 if possible. We strongly believe that // Unicode is the answer to a real internationalized world. Also please // include your contact information in the header, as can be seen above. // full day names Zapatec.Calendar._DN = new Array ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"); // Please note that the following array of short day names (and the same goes // for short month names, _SMN) isn't absolutely necessary. We give it here // for exemplification on how one can customize the short day names, but if // they are simply the first N letters of the full name you can simply say: // // Zapatec.Calendar._SDN_len = N; // short day name length // Zapatec.Calendar._SMN_len = N; // short month name length // // If N = 3 then this is not needed either since we assume a value of 3 if not // present, to be compatible with translation files that were written before // this feature. // short day names Zapatec.Calendar._SDN = new Array ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"); // First day of the week. "0" means display Sunday first, "1" means display // Monday first, etc. Zapatec.Calendar._FD = 0; // full month names Zapatec.Calendar._MN = new Array ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); // short month names Zapatec.Calendar._SMN = new Array ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); // tooltips Zapatec.Calendar._TT_en = Zapatec.Calendar._TT = {}; Zapatec.Calendar._TT["INFO"] = "About the calendar"; Zapatec.Calendar._TT["ABOUT"] = //"DHTML Date/Time Selector\n" + //"(c) zapatec.com 2002-2004\n" + // don't translate this this ;-) //"For latest version visit: http://www.zapatec.com/\n" + //"\n\n" + "Date selection:\n" + "- Use the \xab, \xbb buttons to select year\n" + "- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + "- Hold mouse button on any of the above buttons for faster selection."; Zapatec.Calendar._TT["ABOUT_TIME"] = "\n\n" + "Time selection:\n" + "- Click on any of the time parts to increase it\n" + "- or Shift-click to decrease it\n" + "- or click and drag for faster selection."; Zapatec.Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)"; Zapatec.Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)"; Zapatec.Calendar._TT["GO_TODAY"] = "Go Today (hold for history)"; Zapatec.Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)"; Zapatec.Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)"; Zapatec.Calendar._TT["SEL_DATE"] = "Select date"; Zapatec.Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; Zapatec.Calendar._TT["PART_TODAY"] = " (today)"; // the following is to inform that "%s" is to be the first day of week // %s will be replaced with the day name. Zapatec.Calendar._TT["DAY_FIRST"] = "Display %s first"; // This may be locale-dependent. It specifies the week-end days, as an array // of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 // means Monday, etc. Zapatec.Calendar._TT["WEEKEND"] = "0,6"; Zapatec.Calendar._TT["CLOSE"] = "Close"; Zapatec.Calendar._TT["TODAY"] = "Today"; Zapatec.Calendar._TT["TIME_PART"] = "(Shift-)Click to change value"; // date formats Zapatec.Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; Zapatec.Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; Zapatec.Calendar._TT["WK"] = "wk"; Zapatec.Calendar._TT["TIME"] = "Time:"; Zapatec.Calendar._TT["E_RANGE"] = "Outside the range"; /* Preserve data */ if(Zapatec.Calendar._DN) Zapatec.Calendar._TT._DN = Zapatec.Calendar._DN; if(Zapatec.Calendar._SDN) Zapatec.Calendar._TT._SDN = Zapatec.Calendar._SDN; if(Zapatec.Calendar._SDN_len) Zapatec.Calendar._TT._SDN_len = Zapatec.Calendar._SDN_len; if(Zapatec.Calendar._MN) Zapatec.Calendar._TT._MN = Zapatec.Calendar._MN; if(Zapatec.Calendar._SMN) Zapatec.Calendar._TT._SMN = Zapatec.Calendar._SMN; if(Zapatec.Calendar._SMN_len) Zapatec.Calendar._TT._SMN_len = Zapatec.Calendar._SMN_len; Zapatec.Calendar._DN = Zapatec.Calendar._SDN = Zapatec.Calendar._SDN_len = Zapatec.Calendar._MN = Zapatec.Calendar._SMN = Zapatec.Calendar._SMN_len = null $(document).ready(function() { $(".defaultText").focus(function(srcc) { if ($(this).val() == $(this)[0].title) { $(this).removeClass("defaultTextActive"); $(this).val(""); } }); $(".defaultText").blur(function() { if ($(this).val() == "") { $(this).addClass("defaultTextActive"); $(this).val($(this)[0].title); } }); $(".defaultText").blur(); });