// swad.js: javascript functions /* SWAD (Shared Workspace At a Distance), is a web platform developed at the University of Granada (Spain), and used to support university teaching. Copyright (C) 1999-2015 Antonio Caņas-Vargas University of Granada (SPAIN) (acanas@ugr.es) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ // Global variable used in refreshConnected() var ActionAJAX; // Global variables used in writeLocalClock() var secondsSince1970UTC; // Global variables used in writeClockConnected() var NumUsrsCon; var ListSeconds = []; var countClockConnected = 0; // Write a date in client local time function writeLocalDateFromUTC(id,TimeUTC) { var d = new Date; var Yea; var Mon; var Day; var StrMon; var StrDay; d.setTime(TimeUTC * 1000); Yea = d.getFullYear(); Mon = d.getMonth() + 1; Day = d.getDate(); StrMon = ((Mon < 10) ? '0' : '') + Mon; StrDay = ((Day < 10) ? '0' : '') + Day; document.getElementById(id).innerHTML = Yea + '/' + StrMon + '/' + StrDay; } /*************** Write a date-time in client local time **********************/ // - id is the id of the HTML element in which date-time will be written // - TimeUTC is the date-time to write in UTC UNIX time format // - separator is HTML code to write between date and time function writeLocalDateTimeFromUTC(id,TimeUTC,separator) { var d = new Date; var Yea; var Mon; var Day; var Hou; var Min; var Sec; var StrMon; var StrDay; var StrHou; var StrMin; var StrSec; d.setTime(TimeUTC * 1000); Yea = d.getFullYear(); Mon = d.getMonth() + 1; Day = d.getDate(); Hou = d.getHours(); Min = d.getMinutes(); Sec = d.getSeconds(); StrMon = ((Mon < 10) ? '0' : '') + Mon; StrDay = ((Day < 10) ? '0' : '') + Day; StrHou = ((Hou < 10) ? '0' : '') + Hou; StrMin = ((Min < 10) ? '0' : '') + Min; StrSec = ((Sec < 10) ? '0' : '') + Sec; document.getElementById(id).innerHTML = Yea + '/' + StrMon + '/' + StrDay + separator + StrHou + ':' + StrMin + ':' + StrSec; } // Set local date-time form fields from UTC time function setLocalDateTimeFormFromUTC(id,TimeUTC) { var FormYea = document.getElementById(id+'Year'); var FormMon = document.getElementById(id+'Month'); var FormDay = document.getElementById(id+'Day'); var FormHou = document.getElementById(id+'Hour'); var FormMin = document.getElementById(id+'Minute'); var FormSec = document.getElementById(id+'Second'); var d; var Year; var YearIsValid = false; if (TimeUTC) { d = new Date; d.setTime(TimeUTC * 1000); Year = d.getFullYear(); for (var i=0; i 0) { if (FormMon.options[0].selected) { // No month selected, set to january FormMon.options[1].selected = true; Days = 31; } else if (FormMon.options[2].selected) // Adjust days of february Days = ((((Yea % 4) == 0) && ((Yea % 100) != 0)) || ((Yea % 400) == 0)) ? 29 : 28; else if (FormMon.options[ 4].selected || FormMon.options[ 6].selected || FormMon.options[ 9].selected || FormMon.options[11].selected) Days = 30; else Days = 31; if (FormDay.options[0].selected) // No day selected, set to 1 FormDay.options[1].selected = true; else if (FormDay.selectedIndex > Days) FormDay.options[Days].selected = true; for (var i=FormDay.options.length; i<=Days ; i++) { // Create new days var x = String (i); FormDay.options[i] = new Option(x,x); } for (var i=FormDay.options.length-1; i>Days; i--) // Remove days FormDay.options[i] = null; } } // Set a date range form to yesterday function setDateToYesterday() { var d = new (Date); d.setTime(d.getTime() - 24*60*60*1000); // Today - 1 day setDateRange(d); } // Set a date range form to today function setDateToToday() { var d = new (Date); setDateRange(d); } // Set a date range form to a specific day function setDateRange(d) { var FormYea; var Yea = d.getFullYear(); var Mon = d.getMonth()+1; var Day = d.getDate(); FormYea = document.getElementById('StartYear'); for (var i=0; i= 60) { H = Math.floor(M / 60); M %= 60; } else H = 0; S = ListSeconds[i] % 60; if (H != 0) { StrM = ((M < 10) ? '0' : '') + M; StrS = ((S < 10) ? '0' : '') + S; PrintableClock = H + ':' + StrM + ''' + StrS + '"'; } else if (M != 0) { StrS = ((S < 10) ? '0' : '') + S; PrintableClock = M + ''' + StrS + '"'; } else PrintableClock = S + '"'; BoxClock.innerHTML = PrintableClock; } } } setTimeout('writeClockConnected()',1000); // refresh after 1 second } // Automatic refresh of connected users using AJAX. This function must be called from time to time var objXMLHttpReqCon = false; function refreshConnected() { objXMLHttpReqCon = AJAXCreateObject(); if (objXMLHttpReqCon) { var RefreshParams = RefreshParamNxtActCon + '&' + RefreshParamIdSes + '&' + RefreshParamCrsCod; objXMLHttpReqCon.onreadystatechange = readConnUsrsData; // onreadystatechange must be lowercase objXMLHttpReqCon.open('POST',ActionAJAX,true); objXMLHttpReqCon.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); objXMLHttpReqCon.send(RefreshParams); } } // Automatic refresh of last clicks using AJAX. This function must be called from time to time var objXMLHttpReqLog = false; function refreshLastClicks() { objXMLHttpReqLog = AJAXCreateObject(); if (objXMLHttpReqLog) { var RefreshParams = RefreshParamNxtActLog + '&' + RefreshParamIdSes + '&' + RefreshParamCrsCod; objXMLHttpReqLog.onreadystatechange = readLastClicksData; // onreadystatechange must be lowercase objXMLHttpReqLog.open('POST',ActionAJAX,true); objXMLHttpReqLog.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); objXMLHttpReqLog.send(RefreshParams); } } // Create AJAX object (try is unknown in earlier versions of Netscape, but works in IE5) function AJAXCreateObject() { var obj = false; if (window.XMLHttpRequest) { // Mozilla, Safari,... obj = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { obj = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { obj = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } return obj; } // Receives and show connected users data function readConnUsrsData() { if (objXMLHttpReqCon.readyState == 4) { // Check if data have been received if (objXMLHttpReqCon.status == 200) { var endOfDelay = objXMLHttpReqCon.responseText.indexOf('|',0); // Get separator position var endOfNotif = objXMLHttpReqCon.responseText.indexOf('|',endOfDelay+1); // Get separator position var endOfGblCon = objXMLHttpReqCon.responseText.indexOf('|',endOfNotif+1); // Get separator position var endOfCrsCon = objXMLHttpReqCon.responseText.indexOf('|',endOfGblCon+1); // Get separator position var endOfNumUsrs = objXMLHttpReqCon.responseText.indexOf('|',endOfCrsCon+1); // Get separator position var delay = parseInt(objXMLHttpReqCon.responseText.substring(0,endOfDelay)); // Get refresh delay var htmlNotif = objXMLHttpReqCon.responseText.substring(endOfDelay +1,endOfNotif); // Get HTML code for new notifications var htmlGblCon = objXMLHttpReqCon.responseText.substring(endOfNotif +1,endOfGblCon); // Get HTML code for connected var htmlCrsCon = objXMLHttpReqCon.responseText.substring(endOfGblCon+1,endOfCrsCon); // Get HTML code for course connected var NumUsrsStr = objXMLHttpReqCon.responseText.substring(endOfCrsCon+1,endOfNumUsrs); // Get number of users var startOfUsr; var endOfUsr; NumUsrsCon = (NumUsrsStr.length ? parseInt(NumUsrsStr) : 0); var divNewNotif = document.getElementById('msg'); // Access to new notifications DIV if (divNewNotif) divNewNotif.innerHTML = (htmlNotif.length) ? htmlNotif : ''; // Update new notifications DIV var divGblConnected = document.getElementById('globalconnected'); // Access to global connected DIV if (divGblConnected) divGblConnected.innerHTML = htmlGblCon; // Update global connected DIV if (htmlCrsCon.length) { var divCrsConnected = document.getElementById('courseconnected'); // Access to course connected DIV if (divCrsConnected) { divCrsConnected.innerHTML = htmlCrsCon; // Update course connected DIV countClockConnected = 0; // Don't refresh again using writeClockConnected until past 10 seconds startOfUsr = endOfNumUsrs + 1; for (var NumUsr=0; NumUsr= 60000) // If refresh slower than 1 time each 60 seconds, do refresh; else abort setTimeout('refreshConnected()',delay); } } } // Receives and show last clicks data function readLastClicksData() { if (objXMLHttpReqLog.readyState == 4) { // Check if data have been received if (objXMLHttpReqLog.status == 200) { var endOfDelay = objXMLHttpReqLog.responseText.indexOf('|',0); // Get separator position var endOfLastClicks = objXMLHttpReqLog.responseText.indexOf('|',endOfDelay+1); // Get separator position var delay = parseInt(objXMLHttpReqLog.responseText.substring(0,endOfDelay)); // Get refresh delay var htmlLastClicks = objXMLHttpReqLog.responseText.substring(endOfDelay+1); // Get HTML code for last clicks var divLastClicks = document.getElementById('lastclicks'); // Access to last click DIV if (divLastClicks) divLastClicks.innerHTML = htmlLastClicks; // Update global connected DIV if (delay > 200) // If refresh slower than 1 time each 0.2 seconds, do refresh; else abort setTimeout('refreshLastClicks()',delay); } } } // Zoom a user's photograph function zoom(imagen,urlPhoto,shortName) { var xPos = imagen.offsetLeft; var yPos = imagen.offsetTop; var tempEl = imagen.offsetParent; while (tempEl != null) { xPos += tempEl.offsetLeft; yPos += tempEl.offsetTop; tempEl = tempEl.offsetParent; } xPos -= (187+15); yPos -= ((250+15)/2); if (yPos < 0) yPos = 0; document.getElementById('zoomLyr').style.left = xPos + 'px'; document.getElementById('zoomLyr').style.top = yPos + 'px'; document.getElementById('zoomImg').src = urlPhoto; document.getElementById('zoomTxt').innerHTML = '' + shortName + ''; } // Exit from zooming a user's photograph function noZoom(imagen) { var xPos = -(187+15); var yPos = -(250+15+110); document.getElementById('zoomTxt').innerHTML = ''; document.getElementById('zoomImg').src='/icon/_.gif'; document.getElementById('zoomLyr').style.left = xPos + 'px'; document.getElementById('zoomLyr').style.top = yPos + 'px'; } // Select or unselect a radio element in a form function selectUnselectRadio (radio,groupRadios,numRadiosInGroup){ if (radio.IsChecked) radio.checked = false; radio.IsChecked = !radio.IsChecked; for (var i=0; i'; /***** Month head: first letter for each day of week *****/ HTMLContent += '' HTMLContent += ''; for (DayOfWeek = 0; DayOfWeek < 7; DayOfWeek++) HTMLContent += ''; HTMLContent += ''; /***** Draw every week of the month *****/ for (Week = 0; Week < 6; Week++) { HTMLContent += ''; /***** Draw every day of the week *****/ for (DayOfWeek = 0; DayOfWeek < 7; DayOfWeek++) { /***** Set class for day being drawn *****/ ClassForDay = (Mon == Month) ? 'DAY_WRK' : 'DAY_WRK_LIGHT'; /* Day being drawn is sunday? */ if (DayOfWeek == 6) // All the sundays are holidays ClassForDay = (Mon == Month) ? 'DAY_HLD' : 'DAY_HLD_LIGHT'; /* Date being drawn is today? */ /* IsToday = (Gbl.CurrentAct != ActPrnCal && Mon == Month && Yea == Gbl.Now.Date.Yea && Mon == Gbl.Now.Date.Month && Day == Gbl.Now.Date.Day); */ IsToday = (Yea == Year && Mon == Month && Day == Today); /* Check if day has an exam announcement */ /* ThisDayHasEvent = false; if (!DrawingCalendar || Mon == Month) // If drawing calendar and the month is not the real one, don't draw exam announcements for (NumExamAnnouncement = 0; NumExamAnnouncement < Gbl.LstExamAnnouncements.NumExamAnnounc; NumExamAnnouncement++) if (Yea == Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Year && Mon == Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Month && Day == Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Day) { ThisDayHasEvent = true; if (PutLinkToEvents) { sprintf (StrExamOfX,Txt_Exam_of_X,Gbl.CurrentCrs.Crs.FullName); sprintf (Gbl.Title,"%s: %02u/%02u/%04u", StrExamOfX, Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Day, Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Month, Gbl.LstExamAnnouncements.Lst[NumExamAnnouncement].Yea); } break; } */ /***** Write the box with the day *****/ HTMLContent += ''; /***** Set the next day *****/ NumDaysInMonth = (Mon == 2) ? GetNumDaysFebruary (Yea) : NumDaysMonth[Mon]; if (++Day > NumDaysInMonth) { if (++Mon > 12) { Yea++; Mon = 1; } Day = 1; } } HTMLContent += ''; } /***** End of month *****/ HTMLContent += '
' + DAYS_CAPS[DayOfWeek] + '
'; /* If day has an exam announcement */ /* if (PutLinkToEvents && ThisDayHasEvent) { Act_FormStart (ActSeeExaAnn); fprintf (Gbl.F.Out,"" "" "" "" "
", ClassForDay); Act_LinkFormSubmit (Gbl.Title,ClassForDay); } else { */ HTMLContent += '
" "
"); Act_FormEnd (); } else */ HTMLContent += ''; HTMLContent += '
'; document.getElementById(id).innerHTML = HTMLContent; } /*****************************************************************************/ /***************** Compute day of the week from a given date *****************/ /*****************************************************************************/ // Return 0 for monday, 1 for tuesday,... 6 for sunday function GetDayOfWeek (Year,Month,Day) { if (Month <= 2) { Month += 12; Year--; } return ( ( ( Day+ (Month*2)+ Math.floor(((Month+1)*3)/5)+ Year+ ( Math.floor(Year/4)- Math.floor(Year/100)+ Math.floor(Year/400) ) +2 ) % 7 ) + 5 ) % 7; } /*****************************************************************************/ /****************** Return the number of days of february ********************/ /*****************************************************************************/ function GetNumDaysFebruary (Year) { return (GetIfLeapYear (Year) ? 29 : 28); } /*****************************************************************************/ /************************* Return true if year is leap ***********************/ /*****************************************************************************/ function GetIfLeapYear (Year) { return (Year % 4 == 0) && ((Year % 100 != 0) || (Year % 400 == 0)); }