Daniel Schroeder Copyright © 2007-2009 Daniel Schroeder deemes79[ at ]googlemail[ dot ]com http://www.schroeder-daniel.de gCal - Enhanced Google Calendar gcal_091079 1.1.4 2009.01.09:1944 Access to all your Google Calendar's or a single Google Calendar feed. Displays start date/time, end date/time, title, description, location and all attendees with their status. Date and time format is configurable. google calendar gcal event events kalender http://www.google.com/calendar/render http://img106.imageshack.us/img106/2551/gcalzg5.png http://www.klipfolio.com/download/kid-6706/gcal.klip http://img213.imageshack.us/img213/4980/googlebannercx2.gif 30 -- true extended D\r\n\r\nTo output a backslash escape it with another backslash: \\\\"; ta2.onChange = function() { ta2.value=time_format_description; }; ta2.value=time_format_description; tab1 = Setup.addTab("Setup"); tab1.addText("Mode:"); t_comboBox_mode = tab1.addComboBox(); t_comboBox_mode.addItem("Import from Google Account"); t_comboBox_mode.addItem("Use single Calendar Feed"); t_comboBox_mode.onChange = function(index) { setup_updated = true; if(index==0) switchMode("account"); else switchMode("single"); } tab1.addSpacer(); tab1.addText("Email:"); t_username = tab1.addTextField(); t_username.onChange = function() { setup_updated = true; } tab1.addText("Password:"); t_password = tab1.addTextField(); t_password.onChange = function() { setup_updated = true; } t_password.obscured = true; var login_button = tab1.addButton("Sign in and update calendar list"); login_button.onClick = function() { load_calendar_list = true; Klip.requestRefresh(); } tab1.addText("Chose calendars to display:"); t_feedControl = tab1.addListControl(true, true); t_feedControl.onStateChange = function(index) { setup_updated = true; } tab1.addSpacer(); tab1.addText("\"Magic Cookie\" feed URL:"); t_cookie = tab1.addTextField(); t_cookie.onChange = function() { setup_updated = true; } var help1 = tab1.addButton("Find out about your \"Magic Cookie\" feed URL!"); help1.url = "http://code.google.com/intl/de/apis/calendar/docs/2.0/developers_guide_protocol.html#AuthMagicCookie"; tab1.addSpacer(); t_onlyToday = tab1.addCheckbox( "Only display todays events." ); t_onlyToday.onClick = function() { setup_updated = true; } tab1.addSpacer(); tab1.addText("Time/Date format:"); t_dateformat = tab1.addTextField(); t_dateformat.onChange = function() { setup_updated = true; } var help2 = tab1.addButton("Time/Date format description"); help2.onClick = function() { Setup.open(1); } var donate = tab1.addButton("Make a donation"); donate.url="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=deemes79%40googlemail%2ecom&no_shipping=0&no_note=1&tax=0¤cy_code=EUR&lc=DE&bn=PP%2dDonationsBF&charset=UTF%2d8"; Setup.onClose = function() { Klip.requestRefresh(); } t_comboBox_mode.selected = Prefs.getPref("t_comboBox_mode")*1; t_username.value = ungarble(Prefs.getPref("t_username")); t_password.value = ungarble(Prefs.getPref("t_password")); var t_feedControl_string = ungarble(Prefs.getPref("t_feedControl")); var t_feedControl_parts = t_feedControl_string.split("$!&"); t_feedControl_colors = new Array(); t_feedControl_urls = new Array(); for(var i=0;inowPlus1year.getTime()*1) return false; obj.canvisit=false; obj.candelete=false; var start=obj.getData("Start"); obj.setData("Start",dateFormat(start,t_dateformat.value)); obj.setData("End",dateFormat(obj.getData("End"),t_dateformat.value)); return true; } var timer = createTimer(10*1000); timer.onTick = function() { var now = new Date().getTime(); for(var i=0;i[^]*?(.*?)<\/title>[^]*?<link rel='alternate'.*?href='(.*?)'[^]*?>[^]*?<gCal:color value='#(.*?)'[^]*?>/g; var calendarList=listRequest.response.data.match(calendarListExp); t_feedControl_colors = new Array(); t_feedControl_urls = new Array(); for(var i=0;i<calendarList.length;i++) { calendarList[i].match(calendarListExp); t_feedControl.addItem(RegExp.$1,true); t_feedControl_urls[t_feedControl_urls.length] = RegExp.$2; t_feedControl_colors[t_feedControl_colors.length] = RegExp.$3; } } else { Engines.HTTP.clear304cache(); Items.clear(true); displayMessage("Can't connect to Google.",true); return false; } } else { Engines.HTTP.clear304cache(); Items.clear(true); displayMessage("Authorisation failed. Check your preferences",true); return false; } return true; } var urls_to_get = new Array(); if(t_comboBox_mode.selected==0) { if(!t_username.value.length) { Engines.HTTP.clear304cache(); Items.clear(true); displayMessage("Click here to enter your login details or a \"Magic Cookie\" feed URL.",true); return false; } myMail = t_username.value; for(var i=0;i<t_feedControl.length;i++) { if(t_feedControl.getState(i)) urls_to_get[urls_to_get.length] = t_feedControl_urls[i]; } } else { if(!t_cookie.value.length) { Engines.HTTP.clear304cache(); Items.clear(true); displayMessage("Click here to enter your \"Magic Cookie\" feed URL.",true); return false; } else if(!t_cookie.value.match(/http:\/\/(www\.){0,1}google\.com.*?basic$/)) { Engines.HTTP.clear304cache(); Items.clear(true); displayMessage("The \"Magic Cookie\" feed URL you entered seems to be not correct.",true); displayMessage("Click here to enter your \"Magic Cookie\" feed URL.",true); return false; } if(t_cookie.value.match("/feeds/(.*?)/")) myMail = RegExp.$1.replace(/%40/,"@"); urls_to_get[urls_to_get.length] = t_cookie.value; } var not_changed = true; var buffer = ""; var gotAllPreviousFeeds=false; var skip=-1; for(var i=0;i<urls_to_get.length;i++) { if(i==skip) continue; var now=new Date(); if(t_onlyToday.checked) var query_string="?orderby=starttime&sortorder=a&singleevents=true&start-min="+addLeadingZero(now.getFullYear())+"-"+addLeadingZero(now.getMonth()+1)+"-"+addLeadingZero(now.getDate())+"T00:00:00&start-max="+addLeadingZero(now.getFullYear())+"-"+addLeadingZero(now.getMonth()+1)+"-"+addLeadingZero(now.getDate())+"T23:59:59"; else var query_string="?futureevents=true&orderby=starttime&sortorder=a&singleevents=true"; var request=Engines.HTTP.newRequest(urls_to_get[i].replace(/basic/,"full")+query_string); request.headers = "Authorization: GoogleLogin auth="+ungarble(Prefs.getPref("auth_token")); request.maxsize=100000000; request.counter=0; while(!request.send() && request.response.status==500) { //this is a hook because google randomly returns a 500 internal server error...it's still beta... Engines.HTTP.clear304cache(); if(++request.counter>=100) return false; } if(request.response.status == 304) continue; not_changed = false; if(t_comboBox_mode.selected==0) { var tmp_data = request.response.data; for(var j=0;j<t_feedControl_colors.length;j++) { if(t_feedControl_urls[j]==urls_to_get[i]) var color = t_feedControl_colors[j]; } if(tmp_data.match(/<title type='text'>(.*?)<\/title>/)) { tmp_data = tmp_data.replace(/<entry>/g,"<entry><calendar_name>"+RegExp.$1+"</calendar_name>"); } buffer+=tmp_data.replace(/<entry>/g,"<entry><icon>"+color+"</icon>"); } else buffer+=request.response.data; //since we came here at least one feed has changed so we need to get all previous feeds again if(!gotAllPreviousFeeds) { gotAllPreviousFeeds=true; Engines.HTTP.clear304cache(); skip=i; i=-1; } } if(not_changed) return true; Items.statusvisible = true; var items=buffer.split("</entry>"); if(items.length==1) return true; var invitedExp=/<gd:who rel='[^']*' valueString='([^']*)' email='([^']*)'><gd:attendeeStatus value='http:\/\/schemas\.google\.com\/g\/2005#event\.invited'><\/gd:attendeeStatus><\/gd:who>/; var acceptedExp=/<gd:who rel='[^']*' valueString='([^']*)' email='([^']*)'><gd:attendeeStatus value='http:\/\/schemas\.google\.com\/g\/2005#event\.accepted'><\/gd:attendeeStatus><\/gd:who>/; var tentativeExp=/<gd:who rel='[^']*' valueString='([^']*)' email='([^']*)'><gd:attendeeStatus value='http:\/\/schemas\.google\.com\/g\/2005#event\.tentative'><\/gd:attendeeStatus><\/gd:who>/; var declinedExp=/<gd:who rel='[^']*' valueString='([^']*)' email='([^']*)'><gd:attendeeStatus value='http:\/\/schemas\.google\.com\/g\/2005#event\.declined'><\/gd:attendeeStatus><\/gd:who>/; var invitedArr, acceptedArr, tentativeArr, declinedArr; var fullDayExp=/(<gd:when startTime=')([0-9]{4}-[0-9]{2}-[0-9]{2})(' endTime=')([0-9]{4})-([0-9]{2})-([0-9]{2})('[^]*?>)/; var repeatingExp=/<gd:when startTime='[^']*' endTime='[^']*'>.*?<\/gd:when>/g; var originalEventExp=/<gd:originalEvent.*?<\/gd:originalEvent>/g; var repeatingMatches; for(var i=0;i<items.length;i++) { //modifying code for full day events while(items[i].match(fullDayExp)) { var tmpDate = new Date(RegExp.$4,RegExp.$5*1-1,RegExp.$6); tmpDate.setSeconds(-1); var tmpMonth = String(tmpDate.getMonth()*1+1).replace(/^(\d)$/,"0$1"); var tmpDay = String(tmpDate.getDate()).replace(/^(\d)$/,"0$1"); var tmpHours = String(tmpDate.getHours()).replace(/^(\d)$/,"0$1"); var tmpMinutes = String(tmpDate.getMinutes()).replace(/^(\d)$/,"0$1"); items[i]=items[i].replace(fullDayExp,"$1$2T00:00:$3"+tmpDate.getFullYear()+"-"+tmpMonth+"-"+tmpDay+"T"+tmpHours+":"+tmpMinutes+":'>"); items[i]=items[i].replace(originalEventExp,""); } //modifying code for internal comparision if(items[i].match(/<gd:when startTime='([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):[^']*' endTime='[^']*'/)) { var tmpStart = new Date(RegExp.$1,RegExp.$2*1-1,RegExp.$3,RegExp.$4,RegExp.$5,0); items[i]+="<internalStart>"+tmpStart.getTime()+"</internalStart>"; } if(items[i].match(/<gd:when startTime='[^']*' endTime='([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):[^']*'/)) var tmpEnd = new Date(RegExp.$1,RegExp.$2*1-1,RegExp.$3,RegExp.$4,RegExp.$5,0); items[i]+="<internalEnd>"+tmpEnd.getTime()+"</internalEnd>"; if(items[i].match(/<gd:reminder minutes='([0-9]*)'><\/gd:reminder>/)) items[i]+="<notify>"+(tmpStart.getTime()-RegExp.$1*60*1000)+"</notify>"; //add custom columns var custom_columns_content=t_dateformat.value.split("|"); for(var j=0;j<custom_columns_content.length;j++) { items[i]+="<custom_column_"+(j+1)+">"+dateFormat(tmpStart.getFullYear()+"-"+((tmpStart.getMonth()+1)<10?"0":"")+(tmpStart.getMonth()+1)+"-"+(tmpStart.getDate()<10?"0":"")+tmpStart.getDate()+"T"+(tmpStart.getHours()<10?"0":"")+tmpStart.getHours()+":"+(tmpStart.getMinutes()<10?"0":"")+tmpStart.getMinutes()+":",custom_columns_content[j])+"</custom_column_"+(j+1)+">" } //attendees will be set invitedArr = new Array(); acceptedArr = new Array(); tentativeArr = new Array(); declinedArr = new Array(); if(items[i].match(/<gd:who/)) { while(items[i].match(invitedExp)) { invitedArr[invitedArr.length]=RegExp.$1; items[i]=items[i].replace(invitedExp,""); } while(items[i].match(acceptedExp)) { if(RegExp.$2!=myMail) acceptedArr[acceptedArr.length]=RegExp.$1; items[i]=items[i].replace(acceptedExp,""); } while(items[i].match(tentativeExp)) { tentativeArr[tentativeArr.length]=RegExp.$1; items[i]=items[i].replace(tentativeExp,""); } while(items[i].match(declinedExp)) { declinedArr[declinedArr.length]=RegExp.$1; items[i]=items[i].replace(declinedExp,""); } if(invitedArr.length) items[i]+="<invited>"+invitedArr.join(", ")+"</invited>"; if(acceptedArr.length) items[i]+="<accepted>"+acceptedArr.join(", ")+"</accepted>"; if(tentativeArr.length) items[i]+="<tentative>"+tentativeArr.join(", ")+"</tentative>"; if(declinedArr.length) items[i]+="<declined>"+declinedArr.join(", ")+"</declined>"; if(invitedArr.length || acceptedArr.length || tentativeArr.length || declinedArr.length) items[i]+="<attendees>Attendees</attendees>"; } //removing empty location tags. items[i]=items[i].replace(/<gd:where valueString='[\sĀ]*'><\/gd:where>/g,""); //removing empty description tags items[i]=items[i].replace(/<content type='text'>[\sĀ]*<\/content>/g,""); } var food=items.join("</entry>"); if(t_comboBox_mode.selected==1 && food.match(/<title type='text'>(.*?)<\/title><subtitle type='text'>(.*?)<\/subtitle>/)) { Prefs.title=RegExp.$1; Items.iconAlt=RegExp.$2; } Items.purge(true); Engines.KlipFood.process(food); Items.sort(compareByDate); return true; } function displayMessage(message,clickable) { Engines.KlipFood.process("<entry>\ <title>"+message+"\ "); Items.statusvisible = false; for(var i=0;i12?hour*1-12:hour*1); if(hour_12 == 0) hour_12 = 12; else addLeadingZero(hour_12); var am_pm = (hour>=12?"pm":"am"); return format.replace(/([^\\]|^)yyyy/g,"$1"+year).replace(/([^\\]|^)yy/g,"$1"+year.substr(2,2)).replace(/([^\\]|^)mm/g,"$1"+month).replace(/([^\\]|^)m/g,"$1"+month*1).replace(/([^\\]|^)dd/g,"$1"+day).replace(/([^\\]|^)d/g,"$1"+day*1).replace(/([^\\]|^)hh/g,"$1"+hour).replace(/([^\\]|^)h/g,"$1"+hour*1).replace(/([^\\]|^)ii/g,"$1"+minute).replace(/([^\\]|^)i/g,"$1"+minute*1).replace(/([^\\]|^)a/g,"$1"+am_pm).replace(/([^\\]|^)HH/g,"$1"+hour_12).replace(/([^\\]|^)H/g,"$1"+hour_12*1).replace(/([^\\]|^)MM/g,"$1"+months_long[month*1]).replace(/([^\\]|^)M/g,"$1"+months_short[month*1]).replace(/([^\\]|^)DD/g,"$1"+days[dayOfWeek]).replace(/([^\\]|^)D/g,"$1"+days_short[dayOfWeek]).replace(/\|/g," ").replace(/\\([^\\]|$)/g,"$1"); } function compareByDate(item1,item2) { startDate1=item1.getData("internalStart")*1; startDate2=item2.getData("internalStart")*1; if(startDate1startDate2) return 1 else return 0; } function switchMode(mode) { if(mode=="account") { tab1[4].disabled=false; tab1[6].disabled=false; tab1[7].disabled=false; tab1[9].disabled=false; tab1[12].disabled=true; tab1[13].disabled=true; } else { tab1[4].disabled=true; tab1[6].disabled=true; tab1[7].disabled=true; tab1[9].disabled=true; tab1[12].disabled=false; tab1[13].disabled=false; } } function addLeadingZero(number) { if(number<10) number = "0"+number; return number; } ]]>