1 /*********************************************************************************
2 * SugarCRM is a customer relationship management program developed by
3 * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Affero General Public License version 3 as published by the
7 * Free Software Foundation with the addition of the following permission added
8 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
9 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
10 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
17 * You should have received a copy of the GNU Affero General Public License along with
18 * this program; if not, see http://www.gnu.org/licenses or write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
23 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25 * The interactive user interfaces in modified source and object code versions
26 * of this program must display Appropriate Legal Notices, as required under
27 * Section 5 of the GNU Affero General Public License version 3.
29 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
30 * these Appropriate Legal Notices must retain the display of the "Powered by
31 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
32 * technical reasons, the Appropriate Legal Notices must display the words
33 * "Powered by SugarCRM".
34 ********************************************************************************/
38 * This is a javascript object that handles rendering the non-date portions
39 * of a datetime field. There are some assumptions that are made so this
40 * class serves more as a utility rather than a building block. It is used
41 * primarily to handle the datetime field shown for Call, Meetings and Tasks
46 * Datetimecombo constructor
51 * @allowEmptyHM - if this param was set true , the hour and minute select field will has an empty option.
53 function Datetimecombo (datetime, field, timeformat, tabindex, showCheckbox, checked, allowEmptyHM) {
54 this.datetime = datetime;
55 this.allowEmptyHM = allowEmptyHM;
56 if(typeof this.datetime == "undefined" || datetime == '' || trim(datetime).length < 10) {
59 var month = d.getMonth();
60 var date = d.getDate();
61 var year = d.getYear();
62 var hours = d.getHours();
63 var minutes = d.getMinutes();
66 this.fieldname = field;
67 //Get hours and minutes and adjust as necessary
68 this.hrs = parseInt(datetime.substring(11,13), 10);
69 this.mins = parseInt(datetime.substring(14,16), 10);
71 //A safety scan to make sure hrs and minutes are formatted correctly
72 if (this.mins > 0 && this.mins < 15) {
74 } else if (this.mins > 15 && this.mins < 30) {
76 } else if (this.mins > 30 && this.mins < 45) {
78 } else if (this.mins > 45) {
84 this.timeformat = timeformat; //23:00 || 11:00
85 this.tabindex = tabindex == null || isNaN(tabindex) ? 1 : tabindex;
87 // Calculate other derived values
88 this.timeseparator = this.timeformat.substring(2,3);
89 this.has12Hours = /^11/.test(this.timeformat);
90 this.hasMeridiem = /am|pm/i.test(this.timeformat);
91 if(this.hasMeridiem) {
92 this.pm = /pm/.test(this.timeformat);
94 this.meridiem = this.hasMeridiem ? trim(this.datetime.substring(16)) : '';
95 this.datetime = this.datetime.substr(0,10);
96 this.showCheckbox = showCheckbox;
97 this.checked = parseInt(checked);
98 document.getElementById(this.fieldname + '_date').value = this.datetime;
104 * This function renders the javascript portion to handle updates
105 * on the calendar widget. We have to do this because browsers like Mozilla
106 * have errors when attempting to handle events inside a class function.
107 * This is the reason why this code that is generated is not placed within
108 * the update function of the Datetimecombo class. Instead, it is run
109 * using the eval() method when the widget is loaded.
111 Datetimecombo.prototype.jsscript = function(callback) {
112 //text = '\n<script language="javascript" type="text/html">';
113 text = '\nfunction update_' + this.fieldname + '(calendar) {';
114 text += '\nif(calendar != null) {';
115 text += '\ncalendar.onUpdateTime();';
116 text += '\ncalendar.onSetTime();';
117 text += '\ncalendar.hide();';
119 text += '\nd = document.getElementById("' + this.fieldname + '_date").value;';
120 text += '\nh = document.getElementById("' + this.fieldname + '_hours").value;';
121 text += '\nm = document.getElementById("' + this.fieldname + '_minutes").value;';
122 text += '\nnewdate = d + " " + h + "' + this.timeseparator + '" + m;';
123 if(this.hasMeridiem) {
124 text += '\nif(typeof document.getElementById("' + this.fieldname + '_meridiem") != "undefined") {';
125 text += '\n newdate += document.getElementById("' + this.fieldname + '_meridiem").value;';
128 text += '\nif(trim(newdate) =="'+ this.timeseparator +'") newdate="";';
129 text += '\ndocument.getElementById("' + this.fieldname + '").value = newdate;';
130 text += '\n' + callback;
132 //text += '\n</script>';
138 * This function renders the HTML form elements for this widget
140 Datetimecombo.prototype.html = function(callback) {
142 //Now render the items
143 var text = '<select class="datetimecombo_time" size="1" id="' + this.fieldname + '_hours" tabindex="' + this.tabindex + '" onchange="combo_' + this.fieldname + '.update(); ' + callback + '">';
144 var h1 = this.has12Hours ? 1 : 0;
145 var h2 = this.has12Hours ? 12 : 23;
146 if(this.allowEmptyHM){
147 text += '<option></option>';
149 for(i=h1; i <= h2; i++) {
150 val = i < 10 ? "0" + i : i;
151 text += '<option value="' + val + '" ' + (i == this.hrs ? "SELECTED" : "") + '>' + val + '</option>';
154 text += '\n</select> ';
155 text += this.timeseparator;
156 text += '\n <select class="datetimecombo_time" size="1" id="' + this.fieldname + '_minutes" tabindex="' + this.tabindex + '" onchange="combo_' + this.fieldname + '.update(); ' + callback + '">';
157 if(this.allowEmptyHM){
158 text += '\n<option></option>';
160 text += '\n<option value="00" ' + (this.mins == 0 ? "SELECTED" : "") + '>00</option>';
161 text += '\n<option value="15" ' + (this.mins == 15 ? "SELECTED" : "") + '>15</option>';
162 text += '\n<option value="30" ' + (this.mins == 30 ? "SELECTED" : "") + '>30</option>';
163 text += '\n<option value="45" ' + (this.mins == 45 ? "SELECTED" : "") + '>45</option>';
164 text += '\n</select>';
166 if(this.hasMeridiem) {
168 text += '\n<select class="datetimecombo_time" size="1" id="' + this.fieldname + '_meridiem" tabindex="' + this.tabindex + '" onchange="combo_' + this.fieldname + '.update(); ' + callback + '">';
169 if(this.allowEmptyHM){
170 text += '\n<option></option>';
172 text += '\n<option value="' + (this.pm ? "am" : "AM") + '" ' + (/am/i.test(this.meridiem) ? "SELECTED" : "") + '>' + (this.pm ? "am" : "AM") + '</option>';
173 text += '\n<option value="' + (this.pm ? "pm" : "PM") + '" ' + (/pm/i.test(this.meridiem) ? "SELECTED" : "") + '>' + (this.pm ? "pm" : "PM") + '</option>';
174 text += '\n</select>';
177 if(this.showCheckbox) {
178 text += '\n<input style="visibility:hidden;" type="checkbox" name="' + this.fieldname + '_flag" id="' + this.fieldname + '_flag" tabindex="' + this.tabindex + '" onchange="combo_' + this.fieldname + '.update(); ' + callback + '" ' + (this.checked ? 'CHECKED' : '') + '>';
179 //text += ' ' + SUGAR.language.get("app_strings", "LBL_LINK_NONE");
188 * This method handles events on the hour, minute and meridiem elements for the widget
190 * XXX TODO 20100317 Frank Steegmans: The code in this module is violating so many best practices
191 * that it will need to get rewritten. Also note that it still stems from before the datetime unification.
193 Datetimecombo.prototype.update = function() {
194 // Bug 42025: hour/minute/second still required when start_date is non required
195 // Fixing this by just assigning default when they aren't required
196 var d = window.document.getElementById(this.fieldname + '_date');
197 var h = window.document.getElementById(this.fieldname + '_hours');
198 var m = window.document.getElementById(this.fieldname + '_minutes');
199 var mer = document.getElementById(this.fieldname + "_meridiem");
201 if(d.value == "") { // if date is not set wipe time settings
204 if(mer) mer.selectedIndex = 0;
205 } else { // if date is set and hours/minutes are not allowed empty, initialize them
206 if(this.allowEmptyHM) {
207 if(h.selectedIndex == 0) h.selectedIndex = 12;
208 if(m.selectedIndex == 0) m.selectedIndex = 1;
209 if(mer && (mer.selectedIndex == 0)) mer.selectedIndex = 1;
213 var newdate = d.value + ' ' + h.value + this.timeseparator + m.value;
215 if(this.hasMeridiem) {
216 ampm = document.getElementById(this.fieldname + "_meridiem").value;
219 if(trim(newdate) == ""+this.timeseparator+""){
222 document.getElementById(this.fieldname).value = newdate;
224 if(this.showCheckbox) {
225 flag = this.fieldname + '_flag';
226 date = this.fieldname + '_date';
227 hours = this.fieldname + '_hours';
228 mins = this.fieldname + '_minutes';
230 if(document.getElementById(flag).checked) {
231 document.getElementById(flag).value=1;
232 document.getElementById(this.fieldname).value = '';
233 document.getElementById(date).disabled=true;
234 document.getElementById(hours).disabled=true;
235 document.getElementById(mins).disabled=true;
237 document.getElementById(flag).value=0;
238 document.getElementById(date).disabled=false;
239 document.getElementById(hours).disabled=false;
240 document.getElementById(mins).disabled=false;