Add basic Ajax interface. No event rendering yet, not much dynamics
authorJan Schneider <jan@horde.org>
Mon, 12 Jan 2009 17:48:27 +0000 (18:48 +0100)
committerJan Schneider <jan@horde.org>
Mon, 12 Jan 2009 17:48:27 +0000 (18:48 +0100)
either. But the general interface is there and works.

22 files changed:
kronolith/config/prefs.php.dist
kronolith/docs/CHANGES
kronolith/index.php
kronolith/js/kronolith.js [new file with mode: 0644]
kronolith/js/src/kronolith.js [new file with mode: 0644]
kronolith/lib/Kronolith.php
kronolith/templates/index/day.inc [new file with mode: 0644]
kronolith/templates/index/index.inc [new file with mode: 0644]
kronolith/templates/index/month.inc [new file with mode: 0644]
kronolith/templates/index/week.inc [new file with mode: 0644]
kronolith/templates/javascript_defs.php
kronolith/themes/ajax.css [new file with mode: 0644]
kronolith/themes/graphics/agenda.png [new file with mode: 0644]
kronolith/themes/graphics/back_quick.png [new file with mode: 0644]
kronolith/themes/graphics/checkbox_off.png [new file with mode: 0644]
kronolith/themes/graphics/checkbox_on.png [new file with mode: 0644]
kronolith/themes/graphics/checkbox_over.png [new file with mode: 0644]
kronolith/themes/graphics/drag-handle.png [new file with mode: 0644]
kronolith/themes/graphics/new_small_fade.png [new file with mode: 0644]
kronolith/themes/graphics/picker.png [new file with mode: 0644]
kronolith/themes/graphics/submit.png [new file with mode: 0644]
kronolith/themes/graphics/tasks.png [new file with mode: 0644]

index 9d79b4a..b9d82a7 100644 (file)
@@ -9,7 +9,7 @@ $prefGroups['view'] = array(
     'column' => _("Display Options"),
     'label' => _("User Interface"),
     'desc' => _("Select confirmation options, how to display the different views and choose default view."),
-    'members' => array('confirm_delete', 'defaultview',
+    'members' => array('dynamic_view', 'confirm_delete', 'defaultview',
                        'time_between_days', 'week_start_monday',
                        'day_hour_start', 'day_hour_end', 'day_hour_force',
                        'slots_per_hour', 'show_icons', 'show_time', 'show_location',
@@ -78,6 +78,15 @@ if ($GLOBALS['registry']->hasMethod('contacts/sources')) {
     );
 }
 
+// show dynamic view?
+$_prefs['dynamic_view'] = array(
+    'value' => 0,
+    'locked' => false,
+    'shared' => false,
+    'type' => 'checkbox',
+    'desc' => _("Show the dynamic view by default, if the browser supports it?")
+);
+
 // confirm deletion of events which don't recur?
 $_prefs['confirm_delete'] = array(
     'value' => 1,
index 010e9cc..d74d11f 100644 (file)
@@ -2,6 +2,7 @@
 v3.0-cvs
 --------
 
+[jan] Add AJAX interface.
 [jan] Store events in UTC and convert to the user's timezone on the fly.
 [jan] Remove alarm reminder code.
 [jan] Change listEvents API method to return keys as dates instead of
index 5076fa7..ed7b9d7 100644 (file)
@@ -19,4 +19,44 @@ if (!$kronolith_configured) {
 }
 
 require_once KRONOLITH_BASE . '/lib/base.php';
-require KRONOLITH_BASE . '/' . $prefs->getValue('defaultview') . '.php';
+
+if (!$prefs->getValue('dynamic_view') || !$browser->hasFeature('xmlhttpreq')) {
+    include KRONOLITH_BASE . '/' . $prefs->getValue('defaultview') . '.php';
+    exit;
+}
+
+require_once 'Horde/Identity.php';
+$identity = Identity::factory();
+$logout_link = Horde::getServiceLink('logout', 'kronolith');
+if ($logout_link) {
+    $logout_link = Horde::widget($logout_link, _("_Logout"), 'logout');
+}
+$help_link = Horde::getServiceLink('help', 'kronolith');
+if ($help_link) {
+    $help_link = Horde::widget($help_link, _("Help"), 'helplink', 'help', 'popup(this.href); return false;');
+}
+$today = Kronolith::currentDate();
+$remote_calendars = @unserialize($prefs->getValue('remote_cals'));
+$current_user = Auth::getAuth();
+$my_calendars = array();
+$shared_calendars = array();
+foreach (Kronolith::listCalendars() as $id => $cal) {
+    if ($cal->get('owner') == $current_user) {
+        $my_calendars[$id] = $cal;
+    } else {
+        $shared_calendars[$id] = $cal;
+    }
+}
+
+$scripts = array(
+    array('ContextSensitive.js', 'kronolith', true),
+    array('dhtmlHistory.js', 'horde', true),
+    array('redbox.js', 'horde', true),
+);
+Kronolith::header('', $scripts);
+echo "<body>\n";
+require KRONOLITH_TEMPLATES . '/index/index.inc';
+Kronolith::includeScriptFiles();
+Kronolith::outputInlineScript();
+$notification->notify(array('listeners' => array('javascript')));
+echo "</body>\n</html>";
diff --git a/kronolith/js/kronolith.js b/kronolith/js/kronolith.js
new file mode 100644 (file)
index 0000000..f381f83
--- /dev/null
@@ -0,0 +1 @@
+var frames={horde_main:true},KronolithCore={view:"",remove_gc:[],debug:function(A,B){if(!this.is_logout&&Kronolith.conf.debug){alert(A+": "+(B instanceof Error?B.name+"-"+B.message:Object.inspect(B)))}},setTitle:function(A){document.title=Kronolith.conf.name+" :: "+A},showNotifications:function(A){if(!A.size()||this.is_logout){return}A.find(function(D){switch(D.type){case"kronolith.timeout":this.logout(Kronolith.conf.timeout_url);return true;case"horde.error":case"horde.message":case"horde.success":case"horde.warning":case"kronolith.request":case"kronolith.sticky":var H,I,K,E,J,F,G=$("alerts"),B=new Element("DIV",{className:D.type.replace(".","-")}),C=D.message;if(!G){G=new Element("DIV",{id:"alerts"});$(document.body).insert(G)}if($w("kronolith.request kronolith.sticky").indexOf(D.type)==-1){C=C.unescapeHTML().unescapeHTML()}G.insert(B.update(C));if(Kronolith.conf.is_ie6){K=new Element("DIV",{className:"ie6alertsfix"}).clonePosition(B,{setLeft:false,setTop:false});H=K;K.insert(B.remove());G.insert(K)}else{H=B}I=Effect.Fade.bind(this,B,{duration:1.5,afterFinish:this.removeAlert.bind(this)});H.observe("click",I);if($w("horde.error kronolith.request kronolith.sticky").indexOf(D.type)==-1){I.delay(D.type=="horde.warning"?10:3)}if(D.type=="kronolith.request"){J=function(){I();document.stopObserving("click",J)};document.observe("click",J)}if(F=$("alertslog")){switch(D.type){case"horde.error":E=Kronolith.text.alog_error;break;case"horde.message":E=Kronolith.text.alog_message;break;case"horde.success":E=Kronolith.text.alog_success;break;case"horde.warning":E=Kronolith.text.alog_warning;break}if(E){F=F.down("DIV UL");if(F.down().hasClassName("noalerts")){F.down().remove()}F.insert(new Element("LI").insert(new Element("P",{className:"label"}).insert(E)).insert(new Element("P",{className:"indent"}).insert(C).insert(new Element("SPAN",{className:"alertdate"}).insert("["+(new Date).toLocaleString()+"]"))))}}}},this)},toggleAlertsLog:function(){var A=$("alertsloglink").down("A"),C=$("alertslog").down("DIV"),B={duration:0.5};if(C.visible()){Effect.BlindUp(C,B);A.update(Kronolith.text.showalog)}else{Effect.BlindDown(C,B);A.update(Kronolith.text.hidealog)}},removeAlert:function(C){try{var A=$(C.element),B=A.up();if(B&&B.parentNode){this.addGC(A.remove());if(!B.childElements().size()&&B.hasClassName("ie6alertsfix")){this.addGC(B.remove())}}}catch(D){this.debug("removeAlert",D)}},logout:function(A){this.is_logout=true;this.redirect(A||(Kronolith.conf.URI_IMP+"/LogOut"))},redirect:function(A){A=this.addSID(A);if(parent.frames.horde_main){parent.location=A}else{window.location=A}},addMouseEvents:function(A){this.DMenu.addElement(A.id,"ctx_"+A.type,A)},removeMouseEvents:function(A){this.DMenu.removeElement($(A).readAttribute("id"));this.addGC(A)},addPopdown:function(B,A){var C=$(B);C.insert({after:$($("popdown_img").cloneNode(false)).writeAttribute("id",B+"_img").show()});this.addMouseEvents({id:B+"_img",type:A,offset:C.up(),left:true})},addGC:function(A){this.remove_gc=this.remove_gc.concat(A)},clickObserveHandler:function(A){return A.d.observe("click",KronolithCore._clickFunc.curry(A))},_clickFunc:function(B,A){B.p?B.f(A):B.f();if(!B.ns){A.stop()}},addSID:function(A){if(!Kronolith.conf.SESSION_ID){return A}return this.addURLParam(A,Kronolith.conf.SESSION_ID.toQueryParams())},addURLParam:function(A,C){var B=A.indexOf("?");if(B!=-1){C=$H(A.toQueryParams()).merge(C).toObject();A=A.substring(0,B)}return A+"?"+Object.toQueryString(C)},go:function(A,D){var G,C,E;if(A.startsWith("compose:")){return}var B=A.split(":");var F=B.shift();switch(F){case"day":case"week":case"month":case"year":case"agenda":case"tasks":if(this.view==F){break}var H=F.capitalize();this._addHistory(A);["Day","Week","Month","Year","Tasks","Agenda"].each(function(I){$("kronolithNav"+I).removeClassName("on")});if(this.view){$("kronolithView"+this.view.capitalize()).fade()}if($("kronolithView"+H)){$("kronolithView"+H).appear()}$("kronolithNav"+H).addClassName("on");switch(F){case"day":case"week":case"month":case"year":$("kronolithMinical").select("td").each(function(I){I.removeClassName("kronolithSelected");if(B.length){if(!I.hasClassName("kronolithMinicalWeek")&&(F=="month"||(F=="day"&&I.readAttribute("date")==B[0]))){I.addClassName("kronolithSelected")}}});if(F=="week"&&B.length){$("kronolithMinical").select("td").each(function(J){if(J.readAttribute("date")==B[0]){var I=J.parentNode.childNodes;for(i=0;i<I.length;i++){if(I.item(i)!=J&&I.item(i).tagName=="TD"){$(I.item(i)).addClassName("kronolithSelected")}}throw $break}})}$("kronolithBody").select("div.kronolithEvent").each(function(I){KronolithCore.clickObserveHandler({d:I,f:$("kronolithEventForm").appear.bind($("kronolithEventForm"))});I.observe("mouseover",I.addClassName.curry("kronolithSelected"));I.observe("mouseout",I.removeClassName.curry("kronolithSelected"))});break}this.view=F;break;case"options":this._addHistory(F);KronolithCore.setTitle(Kronolith.text.prefs);this.iframeContent(F,Kronolith.conf.prefs_url);break}},_addHistory:function(B,A){if(Horde.dhtmlHistory.getCurrentLocation()!=B){Horde.dhtmlHistory.add(B,A)}},iframeContent:function(B,D){if(B===null){B=D}var A=$("dimpmain_portal"),C;if(!A){KronolithCore.showNotifications([{type:"horde.error",message:"Bad portal!"}]);return}C=new Element("IFRAME",{id:"iframe"+B,className:"iframe",frameBorder:0,src:D});this._resizeIE6Iframe(C);if(B=="options"){C.observe("load",function(){$("iframeoptions").contentWindow.document.getElementById("menu").style.display="none"})}A.insert(C)},_onMenuShow:function(A){var E,C,B,D;switch(A.ctx){case"ctx_folder":E=$("ctx_folder_create","ctx_folder_rename","ctx_folder_delete");C=KronolithCore.DMenu.element();if(C.readAttribute("mbox")=="INBOX"){E.invoke("hide")}else{if(Kronolith.conf.fixed_folders.indexOf(C.readAttribute("mbox"))!=-1){E.shift();E.invoke("hide")}else{E.invoke("show")}}if(C.hasAttribute("u")){$("ctx_folder_poll").hide();$("ctx_folder_nopoll").show()}else{$("ctx_folder_poll").show();$("ctx_folder_nopoll").hide()}break;case"ctx_message":[$("ctx_message_reply_list")].invoke(this.viewport.createSelection("domid",A.id).get("dataob").first().listmsg?"show":"hide");break;case"ctx_reply":D=this.viewport.getSelected();if(D.size()==1){B=D.get("dataob").first()}[$("ctx_reply_reply_list")].invoke(B&&B.listmsg?"show":"hide");break;case"ctx_otheractions":$("oa_seen","oa_unseen","oa_flagged","oa_clear","oa_sep1","oa_blacklist","oa_whitelist","oa_sep2").compact().invoke(this.viewport.getSelected().size()?"show":"hide");break}return true},_onResize:function(B,A){if(this.viewport){this.viewport.onResize(B,A)}this._resizeIE6()},updateTitle:function(){var B,A,C;if(this.viewport.isFiltering()){A=Kronolith.text.search+" :: "+this.viewport.getMetaData("total_rows")+" "+Kronolith.text.resfound}else{B=$(this.getFolderId(this.folder));if(B){C=B.readAttribute("u");A=B.readAttribute("l");if(C>0){A+=" ("+C+")"}}else{A=this.viewport.getMetaData("label")}}KronolithCore.setTitle(A)},_keydownHandler:function(D){if(D.findElement("FORM")||RedBox.overlayVisible()){return}var G,F,B,E,C,A=D.keyCode||D.charCode;switch(A){case Event.KEY_ESC:$("kronolithEventForm").fade({duration:0.5});break;case Event.KEY_DELETE:case Event.KEY_BACKSPACE:if(sel.size()==1){B=sel.get("dataob").first();if(D.shiftKey){this.moveSelected(B.rownum+((B.rownum==this.viewport.getMetaData("total_rows"))?-1:1),true)}this.flag("deleted",B)}else{this.flag("deleted")}D.stop();break;case Event.KEY_UP:case Event.KEY_DOWN:if(D.shiftKey&&this.lastrow!=-1){E=this.viewport.createSelection("rownum",this.lastrow+((A==Event.KEY_UP)?-1:1));if(E.size()){E=E.get("dataob").first();this.viewport.scrollTo(E.rownum);this.msgSelect(E.domid,{shift:true})}}else{this.moveSelected(A==Event.KEY_UP?-1:1)}D.stop();break;case Event.KEY_PAGEUP:case Event.KEY_PAGEDOWN:if(!D.ctrlKey&&!D.shiftKey&&!D.altKey&&!D.metaKey){F=this.viewport.getPageSize()-1;move=F*(A==Event.KEY_PAGEUP?-1:1);if(sel.size()==1){G=this.viewport.currentOffset();C=sel.get("rownum").first()-1;switch(A){case Event.KEY_PAGEUP:if(G!=C){move=G-C}break;case Event.KEY_PAGEDOWN:if((G+F)!=C){move=G+F-C}break}}this.moveSelected(move);D.stop()}break;case Event.KEY_HOME:case Event.KEY_END:this.moveSelected(A==Event.KEY_HOME?1:this.viewport.getMetaData("total_rows"),true);D.stop();break;case Event.KEY_RETURN:if(!D.element().match("input")){if(sel.size()==1){this.msgWindow(sel.get("dataob").first())}}D.stop();break;case 65:case 97:if(D.ctrlKey){this.selectAll();D.stop()}break}},_closeRedBox:function(){var A=RedBox.getWindowContents();KronolithCore.addGC([A,A.descendants()].flatten());RedBox.close()},_onLoad:function(){var B,D=KronolithCore.clickObserveHandler,A=KronolithCore.DMenu;if(Horde.dhtmlHistory.initialize()){Horde.dhtmlHistory.addListener(this.go.bind(this))}if(!Horde.dhtmlHistory.getCurrentLocation()){this.go(Kronolith.conf.login_view)}B=$("kronolithLogo");if(B.visible()){D({d:B.down("a"),f:this.go.bind(this,"portal")})}D({d:$("id_fullday"),f:function(){$("kronolithEventForm").select(".edit_at").each(Element.toggle)}});D({d:$("kronolithNewEvent"),f:KronolithCore.editEvent});$("kronolithEventActions").select("input.button").each(function(C){D({d:C,f:function(){Effect.Fade("kronolithEventForm")}})});$("kronolithEventForm").select("div.kronolithTags span").each(function(C){$("id_tags").value=$F("id_tags")+C.getText()+", "});["Day","Week","Month","Year","Tasks","Agenda"].each(function(C){D({d:$("kronolithNav"+C),f:KronolithCore.go.bind(KronolithCore,C.toLowerCase())})});$("kronolithMenu").select("div.kronolithCalendars div").each(function(C){D({d:C,f:KronolithCore.toggleCalendar.bind(KronolithCore,C)});C.observe("mouseover",C.addClassName.curry("kronolithCalOver"));C.observe("mouseout",C.removeClassName.curry("kronolithCalOver"))});D({d:$("kronolithMinicalDate"),f:KronolithCore.go.bind(KronolithCore,"month:"+$("kronolithMinicalDate").readAttribute("date"))});$("kronolithMinical").select("td").each(function(C){D({d:C,f:function(){if(C.hasClassName("kronolithMinicalWeek")){KronolithCore.go("week:"+C.readAttribute("date"))}else{if(!C.hasClassName("empty")){KronolithCore.go("day:"+C.readAttribute("date"))}}}})});$("kronolithViewMonth").select(".kronolithFirstCol").each(function(C){D({d:C,f:KronolithCore.go.bind(KronolithCore,"week")})});$("kronolithViewMonth").select(".kronolithDay").each(function(C){D({d:C,f:KronolithCore.go.bind(KronolithCore,"day")})});this._resizeIE6()},_resizeIE6:function(){var C=(($("kronolithViewMonth").getWidth()-20-2-2-16)/7)-2-2;$("kronolithViewMonth").select(".kronolithCol").invoke("setStyle",{width:C+"px"});var A=(($("kronolithViewMonth").getHeight()-25)/6)-2-2;$("kronolithViewMonth").select(".kronolithViewBody .kronolithCol").invoke("setStyle",{height:A+"px"});$("kronolithViewMonth").select(".kronolithViewBody .kronolithFirstCol").invoke("setStyle",{height:A+"px"});$("kronolithViewWeek").select(".kronolithCol").invoke("setStyle",{width:(C-1)+"px"});var B=$("kronolithViewDay").getWidth()-20-2-2-16-3;var C=((B+7)/7)-1;$("kronolithViewDay").select(".kronolithViewHead .kronolithCol").invoke("setStyle",{width:B+"px"});$("kronolithViewDay").select(".kronolithViewBody .kronolithCol").invoke("setStyle",{width:C+"px"});$("kronolithViewDay").select(".kronolithViewBody .kronolithAllDay .kronolithCol").invoke("setStyle",{width:B+"px"})},_resizeIE6Iframe:function(A){if(Kronolith.conf.is_ie6){A.setStyle({width:$("kronolithmain").getStyle("width"),height:(document.viewport.getHeight()-20)+"px"})}},editEvent:function(){$("kronolithEventForm").appear({duration:0.5})},toggleCalendar:function(A){if(A.hasClassName("on")){A.removeClassName("on")}else{A.addClassName("on")}}};if(typeof ContextSensitive!="undefined"){KronolithCore.DMenu=new ContextSensitive()}document.observe("dom:loaded",function(){try{if(parent.opener&&parent.opener.location.host==window.location.host&&parent.opener.KronolithCore){Kronolith.baseWindow=parent.opener.Kronolith.baseWindow||parent.opener}}catch(A){}new PeriodicalExecuter(function(){if(KronolithCore.remove_gc.size()){try{$A(KronolithCore.remove_gc.splice(0,75)).compact().invoke("stopObserving")}catch(B){KronolithCore.debug("remove_gc[].stopObserving",B)}}},10);KronolithCore._onLoad();document.observe("keydown",KronolithCore._keydownHandler.bind(KronolithCore));Event.observe(window,"resize",KronolithCore._onResize.bind(KronolithCore));if(Kronolith.conf.is_ie6){document.observe("selectstart",Event.stop);$("foobar").compact().invoke("select","LI").flatten().compact().each(function(B){B.observe("mouseover",B.addClassName.curry("over")).observe("mouseout",B.removeClassName.curry("over"))})}});Event.observe(window,"load",function(){KronolithCore.window_load=true});Element.addMethods({setText:function(B,C){var A=0;$A(B.childNodes).each(function(D){if(D.nodeType==3){if(A++){Element.remove(D)}else{D.nodeValue=C}}});if(!A){$(B).insert(C)}},getText:function(B,A){var C="";$A(B.childNodes).each(function(D){if(D.nodeType==3){C+=D.nodeValue}else{if(A&&D.hasChildNodes()){C+=$(D).getText(true)}}});return C}});Object.extend(Array.prototype,{numericSort:function(){return this.sort(function(B,A){if(B>A){return 1}else{if(B<A){return-1}}return 0})}});Object.extend(String.prototype,{evalScripts:function(){var re=/function\s+([^\s(]+)/g;this.extractScripts().each(function(s){var func;eval(s);while(func=re.exec(s)){window[func[1]]=eval(func[1])}})}});
\ No newline at end of file
diff --git a/kronolith/js/src/kronolith.js b/kronolith/js/src/kronolith.js
new file mode 100644 (file)
index 0000000..d050939
--- /dev/null
@@ -0,0 +1,945 @@
+/**
+ * kronolith.js - Base application logic.
+ * NOTE: ContextSensitive.js must be loaded before this file.
+ *
+ * $Horde$
+ *
+ * Copyright 2008 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Jan Schneider <jan@horde.org>
+ */
+
+/* Trick some Horde js into thinking this is the parent Horde window. */
+var frames = { horde_main: true },
+
+/* Kronolith object. */
+KronolithCore = {
+
+    view: '',
+    remove_gc: [],
+
+    debug: function(label, e)
+    {
+        if (!this.is_logout && Kronolith.conf.debug) {
+            alert(label + ': ' + (e instanceof Error ? e.name + '-' + e.message : Object.inspect(e)));
+        }
+    },
+
+    setTitle: function(title)
+    {
+        document.title = Kronolith.conf.name + ' :: ' + title;
+    },
+
+    showNotifications: function(msgs)
+    {
+        if (!msgs.size() || this.is_logout) {
+            return;
+        }
+
+        msgs.find(function(m) {
+            switch (m.type) {
+            case 'kronolith.timeout':
+                this.logout(Kronolith.conf.timeout_url);
+                return true;
+
+            case 'horde.error':
+            case 'horde.message':
+            case 'horde.success':
+            case 'horde.warning':
+            case 'kronolith.request':
+            case 'kronolith.sticky':
+                var clickdiv, fadeeffect, iefix, log, requestfunc, tmp,
+                    alerts = $('alerts'),
+                    div = new Element('DIV', { className: m.type.replace('.', '-') }),
+                    msg = m.message;;
+
+                if (!alerts) {
+                    alerts = new Element('DIV', { id: 'alerts' });
+                    $(document.body).insert(alerts);
+                }
+
+                if ($w('kronolith.request kronolith.sticky').indexOf(m.type) == -1) {
+                    msg = msg.unescapeHTML().unescapeHTML();
+                }
+                alerts.insert(div.update(msg));
+
+                // IE6 has a bug that does not allow the body of a div to be
+                // clicked to trigger an onclick event for that div (it only
+                // seems to be an issue if the div is overlaying an element
+                // that itself contains an image).  However, the alert box
+                // normally displays over the message list, and we use several
+                // graphics in the default message list layout, so we see this
+                // buggy behavior 99% of the time.  The workaround is to
+                // overlay the div with a like sized div containing a clear
+                // gif, which tricks IE into the correct behavior.
+                if (Kronolith.conf.is_ie6) {
+                    iefix = new Element('DIV', { className: 'ie6alertsfix' }).clonePosition(div, { setLeft: false, setTop: false });
+                    clickdiv = iefix;
+                    iefix.insert(div.remove());
+                    alerts.insert(iefix);
+                } else {
+                    clickdiv = div;
+                }
+
+                fadeeffect = Effect.Fade.bind(this, div, { duration: 1.5, afterFinish: this.removeAlert.bind(this) });
+
+                clickdiv.observe('click', fadeeffect);
+
+                if ($w('horde.error kronolith.request kronolith.sticky').indexOf(m.type) == -1) {
+                    fadeeffect.delay(m.type == 'horde.warning' ? 10 : 3);
+                }
+
+                if (m.type == 'kronolith.request') {
+                    requestfunc = function() {
+                        fadeeffect();
+                        document.stopObserving('click', requestfunc)
+                    };
+                    document.observe('click', requestfunc);
+                }
+
+                if (tmp = $('alertslog')) {
+                    switch (m.type) {
+                    case 'horde.error':
+                        log = Kronolith.text.alog_error;
+                        break;
+
+                    case 'horde.message':
+                        log = Kronolith.text.alog_message;
+                        break;
+
+                    case 'horde.success':
+                        log = Kronolith.text.alog_success;
+                        break;
+
+                    case 'horde.warning':
+                        log = Kronolith.text.alog_warning;
+                        break;
+                    }
+
+                    if (log) {
+                        tmp = tmp.down('DIV UL');
+                        if (tmp.down().hasClassName('noalerts')) {
+                            tmp.down().remove();
+                        }
+                        tmp.insert(new Element('LI').insert(new Element('P', { className: 'label' }).insert(log)).insert(new Element('P', { className: 'indent' }).insert(msg).insert(new Element('SPAN', { className: 'alertdate'}).insert('[' + (new Date).toLocaleString() + ']'))));
+                    }
+                }
+            }
+        }, this);
+    },
+
+    toggleAlertsLog: function()
+    {
+        var alink = $('alertsloglink').down('A'),
+            div = $('alertslog').down('DIV'),
+            opts = { duration: 0.5 };
+        if (div.visible()) {
+            Effect.BlindUp(div, opts);
+            alink.update(Kronolith.text.showalog);
+        } else {
+            Effect.BlindDown(div, opts);
+            alink.update(Kronolith.text.hidealog);
+        }
+    },
+
+    removeAlert: function(effect)
+    {
+        try {
+            var elt = $(effect.element),
+                parent = elt.up();
+            // We may have already removed this element from the DOM tree
+            // (if the user clicked on the notification), so check parentNode
+            // here - will return null if node is not part of DOM tree.
+            if (parent && parent.parentNode) {
+                this.addGC(elt.remove());
+                if (!parent.childElements().size() &&
+                    parent.hasClassName('ie6alertsfix')) {
+                    this.addGC(parent.remove());
+                }
+            }
+        } catch (e) {
+            this.debug('removeAlert', e);
+        }
+    },
+
+    logout: function(url)
+    {
+        this.is_logout = true;
+        this.redirect(url || (Kronolith.conf.URI_IMP + '/LogOut'));
+    },
+
+    redirect: function(url)
+    {
+        url = this.addSID(url);
+        if (parent.frames.horde_main) {
+            parent.location = url;
+        } else {
+            window.location = url;
+        }
+    },
+
+    /* Add/remove mouse events on the fly.
+     * Parameter: object with the following names - id, type, offset
+     *   (optional), left (optional), onShow (optional)
+     * Valid types:
+     *   'message', 'draft'  --  Message list rows
+     *   'container', 'special', 'folder'  --  Folders
+     *   'reply', 'forward', 'otheractions'  --  Message list buttons
+     *   'contacts'  --  Linked e-mail addresses */
+    addMouseEvents: function(p)
+    {
+        this.DMenu.addElement(p.id, 'ctx_' + p.type, p);
+    },
+
+    /* elt = DOM element */
+    removeMouseEvents: function(elt)
+    {
+        this.DMenu.removeElement($(elt).readAttribute('id'));
+        this.addGC(elt);
+    },
+
+    /* Add a popdown menu to an actions button. */
+    addPopdown: function(bid, ctx)
+    {
+        var bidelt = $(bid);
+        bidelt.insert({ after: $($('popdown_img').cloneNode(false)).writeAttribute('id', bid + '_img').show() });
+        this.addMouseEvents({ id: bid + '_img', type: ctx, offset: bidelt.up(), left: true });
+    },
+
+    /* Utility functions. */
+    addGC: function(elt)
+    {
+        this.remove_gc = this.remove_gc.concat(elt);
+    },
+
+    // o: (object) Contains the following items:
+    //    'd'  - (required) The DOM element
+    //    'f'  - (required) The function to bind to the click event
+    //    'ns' - (optional) If set, don't stop the event's propogation
+    //    'p'  - (optional) If set, passes in the event object to the called
+    //                      function
+    clickObserveHandler: function(o)
+    {
+        return o.d.observe('click', KronolithCore._clickFunc.curry(o));
+    },
+
+    _clickFunc: function(o, e)
+    {
+        o.p ? o.f(e) : o.f();
+        if (!o.ns) {
+            e.stop();
+        }
+    },
+
+    addSID: function(url)
+    {
+        if (!Kronolith.conf.SESSION_ID) {
+            return url;
+        }
+        return this.addURLParam(url, Kronolith.conf.SESSION_ID.toQueryParams());
+    },
+
+    addURLParam: function(url, params)
+    {
+        var q = url.indexOf('?');
+
+        if (q != -1) {
+            params = $H(url.toQueryParams()).merge(params).toObject();
+            url = url.substring(0, q);
+        }
+        return url + '?' + Object.toQueryString(params);
+    },
+
+    go: function(fullloc, data)
+    {
+        var app, f, separator;
+
+        if (fullloc.startsWith('compose:')) {
+            return;
+        }
+
+        /*
+        $('dimpmain_portal').update(Kronolith.text.loading).show();
+
+        if (loc.startsWith('app:')) {
+            app = loc.substr(4);
+            if (app == 'imp' || app == 'dimp') {
+                this.go('folder:INBOX');
+                return;
+            }
+            this.highlightSidebar('app' + app);
+            this._addHistory(loc, data);
+            if (data) {
+                this.iframeContent(loc, data);
+            } else if (Kronolith.conf.app_urls[app]) {
+                this.iframeContent(loc, Kronolith.conf.app_urls[app]);
+            }
+            return;
+        }
+        */
+        var locParts = fullloc.split(':');
+        var loc = locParts.shift();
+
+        switch (loc) {
+        case 'day':
+        case 'week':
+        case 'month':
+        case 'year':
+        case 'agenda':
+        case 'tasks':
+            if (this.view == loc) {
+                break;
+            }
+
+            var locCap = loc.capitalize();
+            this._addHistory(fullloc);
+
+            [ 'Day', 'Week', 'Month', 'Year', 'Tasks', 'Agenda' ].each(function(a) {
+                $('kronolithNav' + a).removeClassName('on');
+            });
+            if (this.view) {
+                $('kronolithView' + this.view.capitalize()).fade();
+            }
+            if ($('kronolithView' + locCap)) {
+                $('kronolithView' + locCap).appear();
+            }
+            $('kronolithNav' + locCap).addClassName('on');
+
+            switch (loc) {
+            case 'day':
+            case 'week':
+            case 'month':
+            case 'year':
+                $('kronolithMinical').select('td').each(function(td) {
+                    td.removeClassName('kronolithSelected');
+                    if (locParts.length) {
+                        if (!td.hasClassName('kronolithMinicalWeek') &&
+                            (loc == 'month' ||
+                             (loc == 'day' &&
+                              td.readAttribute('date') == locParts[0]))) {
+                            td.addClassName('kronolithSelected');
+                        }
+                    }
+                });
+                if (loc == 'week' && locParts.length) {
+                    $('kronolithMinical').select('td').each(function(td) {
+                        if (td.readAttribute('date') == locParts[0]) {
+                            var tds = td.parentNode.childNodes;
+                            for (i = 0; i < tds.length; i++) {
+                                if (tds.item(i) != td &&
+                                    tds.item(i).tagName == 'TD') {
+                                    $(tds.item(i)).addClassName('kronolithSelected');
+                                }
+                            }
+                            throw $break;
+                        }
+                    });
+                }
+                $('kronolithBody').select('div.kronolithEvent').each(function(s) {
+                    KronolithCore.clickObserveHandler({ d: s, f: $('kronolithEventForm').appear.bind($('kronolithEventForm')) });
+                    s.observe('mouseover', s.addClassName.curry('kronolithSelected'));
+                    s.observe('mouseout', s.removeClassName.curry('kronolithSelected'));
+                });
+
+                break;
+            }
+
+            this.view = loc;
+            break;
+
+        case 'options':
+            //this.highlightSidebar('appoptions');
+            this._addHistory(loc);
+            KronolithCore.setTitle(Kronolith.text.prefs);
+            this.iframeContent(loc, Kronolith.conf.prefs_url);
+            break;
+        }
+    },
+
+    _addHistory: function(loc, data)
+    {
+        if (Horde.dhtmlHistory.getCurrentLocation() != loc) {
+            Horde.dhtmlHistory.add(loc, data);
+        }
+    },
+
+    iframeContent: function(name, loc)
+    {
+        if (name === null) {
+            name = loc;
+        }
+
+        var container = $('dimpmain_portal'), iframe;
+        if (!container) {
+            KronolithCore.showNotifications([ { type: 'horde.error', message: 'Bad portal!' } ]);
+            return;
+        }
+
+        iframe = new Element('IFRAME', { id: 'iframe' + name, className: 'iframe', frameBorder: 0, src: loc });
+        this._resizeIE6Iframe(iframe);
+
+        // Hide menu in prefs pages.
+        if (name == 'options') {
+            iframe.observe('load', function() { $('iframeoptions').contentWindow.document.getElementById('menu').style.display = 'none'; });
+        }
+
+        container.insert(iframe);
+    },
+    _onMenuShow: function(ctx)
+    {
+        var elts, folder, ob, sel;
+
+        switch (ctx.ctx) {
+        case 'ctx_folder':
+            elts = $('ctx_folder_create', 'ctx_folder_rename', 'ctx_folder_delete');
+            folder = KronolithCore.DMenu.element();
+            if (folder.readAttribute('mbox') == 'INBOX') {
+                elts.invoke('hide');
+            } else if (Kronolith.conf.fixed_folders.indexOf(folder.readAttribute('mbox')) != -1) {
+                elts.shift();
+                elts.invoke('hide');
+            } else {
+                elts.invoke('show');
+            }
+
+            if (folder.hasAttribute('u')) {
+                $('ctx_folder_poll').hide();
+                $('ctx_folder_nopoll').show();
+            } else {
+                $('ctx_folder_poll').show();
+                $('ctx_folder_nopoll').hide();
+            }
+            break;
+
+        case 'ctx_message':
+            [ $('ctx_message_reply_list') ].invoke(this.viewport.createSelection('domid', ctx.id).get('dataob').first().listmsg ? 'show' : 'hide');
+            break;
+
+        case 'ctx_reply':
+            sel = this.viewport.getSelected();
+            if (sel.size() == 1) {
+                ob = sel.get('dataob').first();
+            }
+            [ $('ctx_reply_reply_list') ].invoke(ob && ob.listmsg ? 'show' : 'hide');
+            break;
+
+        case 'ctx_otheractions':
+            $('oa_seen', 'oa_unseen', 'oa_flagged', 'oa_clear', 'oa_sep1', 'oa_blacklist', 'oa_whitelist', 'oa_sep2').compact().invoke(this.viewport.getSelected().size() ? 'show' : 'hide');
+            break;
+        }
+        return true;
+    },
+
+    _onResize: function(noupdate, nowait)
+    {
+        if (this.viewport) {
+            this.viewport.onResize(noupdate, nowait);
+        }
+        this._resizeIE6();
+    },
+
+    updateTitle: function()
+    {
+        var elt, label, unseen;
+        if (this.viewport.isFiltering()) {
+            label = Kronolith.text.search + ' :: ' + this.viewport.getMetaData('total_rows') + ' ' + Kronolith.text.resfound;
+        } else {
+            elt = $(this.getFolderId(this.folder));
+            if (elt) {
+                unseen = elt.readAttribute('u');
+                label = elt.readAttribute('l');
+                if (unseen > 0) {
+                    label += ' (' + unseen + ')';
+                }
+            } else {
+                label = this.viewport.getMetaData('label');
+            }
+        }
+        KronolithCore.setTitle(label);
+    },
+
+    /* Keydown event handler */
+    _keydownHandler: function(e)
+    {
+        // Only catch keyboard shortcuts in message list view. Disable catching
+        // when in form elements or the RedBox overlay is visible.
+        if (e.findElement('FORM') ||
+            RedBox.overlayVisible()) {
+            return;
+        }
+
+        var co, ps, r, row, rowoff,
+            kc = e.keyCode || e.charCode;
+
+        switch (kc) {
+        case Event.KEY_ESC:
+            $('kronolithEventForm').fade({ duration: 0.5 });
+            break;
+
+        case Event.KEY_DELETE:
+        case Event.KEY_BACKSPACE:
+            if (sel.size() == 1) {
+                r = sel.get('dataob').first();
+                if (e.shiftKey) {
+                    this.moveSelected(r.rownum + ((r.rownum == this.viewport.getMetaData('total_rows')) ? -1 : 1), true);
+                }
+                this.flag('deleted', r);
+            } else {
+                this.flag('deleted');
+            }
+            e.stop();
+            break;
+
+        case Event.KEY_UP:
+        case Event.KEY_DOWN:
+            if (e.shiftKey && this.lastrow != -1) {
+                row = this.viewport.createSelection('rownum', this.lastrow + ((kc == Event.KEY_UP) ? -1 : 1));
+                if (row.size()) {
+                    row = row.get('dataob').first();
+                    this.viewport.scrollTo(row.rownum);
+                    this.msgSelect(row.domid, { shift: true });
+                }
+            } else {
+                this.moveSelected(kc == Event.KEY_UP ? -1 : 1);
+            }
+            e.stop();
+            break;
+
+        case Event.KEY_PAGEUP:
+        case Event.KEY_PAGEDOWN:
+            if (!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) {
+                ps = this.viewport.getPageSize() - 1;
+                move = ps * (kc == Event.KEY_PAGEUP ? -1 : 1);
+                if (sel.size() == 1) {
+                    co = this.viewport.currentOffset();
+                    rowoff = sel.get('rownum').first() - 1;
+                    switch (kc) {
+                    case Event.KEY_PAGEUP:
+                        if (co != rowoff) {
+                            move = co - rowoff;
+                        }
+                        break;
+
+                    case Event.KEY_PAGEDOWN:
+                        if ((co + ps) != rowoff) {
+                            move = co + ps - rowoff;
+                        }
+                        break;
+                    }
+                }
+                this.moveSelected(move);
+                e.stop();
+            }
+            break;
+
+        case Event.KEY_HOME:
+        case Event.KEY_END:
+            this.moveSelected(kc == Event.KEY_HOME ? 1 : this.viewport.getMetaData('total_rows'), true);
+            e.stop();
+            break;
+
+        case Event.KEY_RETURN:
+            if (!e.element().match('input')) {
+                // Popup message window if single message is selected.
+                if (sel.size() == 1) {
+                    this.msgWindow(sel.get('dataob').first());
+                }
+            }
+            e.stop();
+            break;
+
+        case 65: // A
+        case 97: // a
+            if (e.ctrlKey) {
+                this.selectAll();
+                e.stop();
+            }
+            break;
+        }
+    },
+
+    _closeRedBox: function()
+    {
+        var c = RedBox.getWindowContents();
+        KronolithCore.addGC([ c, c.descendants() ].flatten());
+        RedBox.close();
+    },
+
+    /* Onload function. */
+    _onLoad: function() {
+        var tmp,
+             C = KronolithCore.clickObserveHandler,
+             dmenu = KronolithCore.DMenu;
+
+        if (Horde.dhtmlHistory.initialize()) {
+            Horde.dhtmlHistory.addListener(this.go.bind(this));
+        }
+
+        /* Initialize the starting page if necessary. addListener() will have
+         * already fired if there is a current location so only do a go()
+         * call if there is no current location. */
+        if (!Horde.dhtmlHistory.getCurrentLocation()) {
+            this.go(Kronolith.conf.login_view);
+        }
+
+        /* Add popdown menus. */
+        /*
+        KronolithCore.addPopdown('button_reply', 'reply');
+        dmenu.disable('button_reply_img', true, true);
+        KronolithCore.addPopdown('button_forward', 'forward');
+        dmenu.disable('button_forward_img', true, true);
+        KronolithCore.addPopdown('button_other', 'otheractions');
+        */
+
+        /* Set up click event observers for elements on main page. */
+        tmp = $('kronolithLogo');
+        if (tmp.visible()) {
+            C({ d: tmp.down('a'), f: this.go.bind(this, 'portal') });
+        }
+
+        C({ d: $('id_fullday'), f: function() { $('kronolithEventForm').select('.edit_at').each(Element.toggle); } });
+
+        C({ d: $('kronolithNewEvent'), f: KronolithCore.editEvent });
+
+        $('kronolithEventActions').select('input.button').each(function(s) {
+           C({ d: s, f: function() { Effect.Fade('kronolithEventForm');} });
+        });
+
+        $('kronolithEventForm').select('div.kronolithTags span').each(function(s) {
+           $('id_tags').value = $F('id_tags') + s.getText() + ', ';
+        });
+
+        [ 'Day', 'Week', 'Month', 'Year', 'Tasks', 'Agenda' ].each(function(a) {
+            C({ d: $('kronolithNav' + a), f: KronolithCore.go.bind(KronolithCore, a.toLowerCase()) });
+        });
+
+        $('kronolithMenu').select('div.kronolithCalendars div').each(function(s) {
+            C({ d: s, f: KronolithCore.toggleCalendar.bind(KronolithCore, s) });
+            s.observe('mouseover', s.addClassName.curry('kronolithCalOver'));
+            s.observe('mouseout', s.removeClassName.curry('kronolithCalOver'));
+        });
+
+        C({ d: $('kronolithMinicalDate'), f: KronolithCore.go.bind(KronolithCore, 'month:' + $('kronolithMinicalDate').readAttribute('date')) });
+        $('kronolithMinical').select('td').each(function(td) {
+            C({ d: td, f: function() {
+                if (td.hasClassName('kronolithMinicalWeek')) {
+                   KronolithCore.go('week:' + td.readAttribute('date'));
+               } else if (!td.hasClassName('empty')) {
+                   KronolithCore.go('day:' + td.readAttribute('date'));
+               }
+            }});
+        });
+
+        /* Set up click event observers for elements on month view. */
+        $('kronolithViewMonth').select('.kronolithFirstCol').each(function(l) {
+            C({ d: l, f: KronolithCore.go.bind(KronolithCore, 'week') });
+        });
+        $('kronolithViewMonth').select('.kronolithDay').each(function(l) {
+            C({ d: l, f: KronolithCore.go.bind(KronolithCore, 'day') });
+        });
+
+        /*
+        C({ d: $('composelink'), f: KronolithCore.compose.bind(KronolithCore, 'new') });
+        C({ d: $('checkmaillink'), f: this.pollFolders.bind(this) });
+
+        [ 'portal', 'options' ].each(function(a) {
+            var d = $('app' + a);
+            if (d) {
+                C({ d: d, f: this.go.bind(this, a) });
+            }
+        }, this);
+        tmp = $('applogout');
+        if (tmp) {
+            C({ d: tmp, f: function() { $('applogout').down('A').update('[' + KronolithText.onlogout + ']'); KronolithCore.logout(); } });
+        }
+
+        tmp = $('applicationfolders');
+        if (tmp) {
+            tmp.select('li.custom a').each(function(s) {
+                C({ d: s, f: this.go.bind(this, 'app:' + s.readAttribute('app')) });
+            }, this);
+        }
+
+        C({ d: $('newfolder'), f: this.createBaseFolder.bind(this) });
+        new Drop('dropbase', this._folderDropConfig);
+        tmp = $('hometab');
+        if (tmp) {
+            C({ d: tmp, f: this.go.bind(this, 'portal') });
+        }
+        $('tabbar').select('a.applicationtab').each(function(a) {
+            C({ d: a, f: this.go.bind(this, 'app:' + a.readAttribute('app')) });
+        }, this);
+        C({ d: $('button_reply'), f: this.composeMailbox.bind(this, 'reply'), ns: true });
+        C({ d: $('button_forward'), f: this.composeMailbox.bind(this, Kronolith.conf.forward_default), ns: true });
+        [ 'spam', 'ham', 'deleted' ].each(function(a) {
+            var d = $('button_' + a);
+            if (d) {
+                C({ d: d, f: this.flag.bind(this, a) });
+            }
+        }, this);
+        C({ d: $('button_compose').down('A'), f: KronolithCore.compose.bind(KronolithCore, 'new') });
+        C({ d: $('button_other'), f: function(e) { dmenu.trigger(e.findElement('A').next(), true); }, p: true });
+        C({ d: $('qoptions').down('.qclose a'), f: this.searchfilterClear.bind(this, false) });
+        [ 'all', 'current' ].each(function(a) {
+            var d = $('sf_' + a);
+            if (d) {
+                C({ d: d, f: this.updateSearchfilter.bind(this, a, 'folder') });
+            }
+        }, this);
+        [ 'msgall', 'from', 'to', 'subject' ].each(function(a) {
+            C({ d: $('sf_' + a), f: this.updateSearchfilter.bind(this, a, 'msg') });
+        }, this);
+        C({ d: $('msglistHeader'), f: this.sort.bind(this), p: true });
+        C({ d: $('ctx_folder_create'), f: function() { this.createSubFolder(dmenu.element()); }.bind(this), ns: true });
+        C({ d: $('ctx_folder_rename'), f: function() { this.renameFolder(dmenu.element()); }.bind(this), ns: true });
+        C({ d: $('ctx_folder_empty'), f: function() { var mbox = dmenu.element().readAttribute('mbox'); dmenu.close(true); if (window.confirm(Kronolith.text.empty_folder)) { KronolithCore.doAction('EmptyFolder', { folder: mbox }, null, this._emptyFolderCallback.bind(this)); } }.bind(this), ns: true });
+        C({ d: $('ctx_folder_delete'), f: function() { var mbox = dmenu.element().readAttribute('mbox'); dmenu.close(true); if (window.confirm(Kronolith.text.delete_folder)) { KronolithCore.doAction('DeleteFolder', { folder: mbox }, null, this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this))); } }.bind(this), ns: true });
+        [ 'ctx_folder_seen', 'ctx_folder_unseen' ].each(function(a) {
+            C({ d: $(a), f: function(type) { this.flag(type, null, dmenu.element().readAttribute('mbox')); }.bind(this, a == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen'), ns: true });
+        }, this);
+        [ 'ctx_folder_poll', 'ctx_folder_nopoll' ].each(function(a) {
+            C({ d: $(a), f: function(modify) { this.modifyPollFolder(dmenu.element().readAttribute('mbox'), modify); }.bind(this, a == 'ctx_folder_poll'), ns: true });
+        }, this);
+        C({ d: $('ctx_container_create'), f: function() { this.createSubFolder(dmenu.element()); }.bind(this), ns: true });
+        C({ d: $('ctx_container_rename'), f: function() { this.renameFolder(dmenu.element()); }.bind(this), ns: true });
+        [ 'reply', 'reply_all', 'reply_list', 'forward_all', 'forward_body', 'forward_attachments' ].each(function(a) {
+            C({ d: $('ctx_message_' + a), f: this.composeMailbox.bind(this, a), ns: true });
+        }, this);
+        [ 'seen', 'unseen', 'flagged', 'clear', 'spam', 'ham', 'blacklist', 'whitelist', 'deleted', 'undeleted' ].each(function(a) {
+            var d = $('ctx_message_' + a);
+            if (d) {
+                C({ d: d, f: this.flag.bind(this, a), ns: true });
+            }
+        }, this);
+        C({ d: $('ctx_draft_resume'), f: this.composeMailbox.bind(this, 'resume') });
+        [ 'flagged', 'clear', 'deleted', 'undeleted' ].each(function(a) {
+            var d = $('ctx_draft_' + a);
+            if (d) {
+                C({ d: d, f: this.flag.bind(this, a), ns: true });
+            }
+        }, this);
+        [ 'reply', 'reply_all', 'reply_list' ].each(function(a) {
+            C({ d: $('ctx_reply_' + a), f: this.composeMailbox.bind(this, a), ns: true });
+        }, this);
+        [ 'forward_all', 'forward_body', 'forward_attachments' ].each(function(a) {
+            C({ d: $('ctx_forward_' + a), f: this.composeMailbox.bind(this, a), ns: true });
+        }, this);
+        C({ d: $('previewtoggle'), f: this.togglePreviewPane.bind(this), ns: true });
+        [ 'seen', 'unseen', 'flagged', 'clear', 'blacklist', 'whitelist' ].each(function(a) {
+            var d = $('oa_' + a);
+            if (d) {
+                C({ d: d, f: this.flag.bind(this, a), ns: true });
+            }
+        }, this);
+        C({ d: $('oa_selectall'), f: this.selectAll.bind(this), ns: true });
+
+        tmp = $('oa_purge_deleted');
+        if (tmp) {
+            C({ d: tmp, f: this.purgeDeleted.bind(this), ns: true });
+        }
+
+        $('toggleHeaders').select('A').each(function(a) {
+            C({ d: a, f: function() { [ a.up().select('A'), $('msgHeadersColl', 'msgHeaders') ].flatten().invoke('toggle'); }, ns: true });
+        });
+        $('msg_newwin', 'msg_newwin_options').compact().each(function(a) {
+            C({ d: a, f: function() { this.msgWindow(this.viewport.getViewportSelection().search({ imapuid: { equal: [ Kronolith.conf.msg_index ] } , view: { equal: [ Kronolith.conf.msg_folder ] } }).get('dataob').first()); }.bind(this) });
+        }, this);
+        */
+
+        this._resizeIE6();
+    },
+
+    // IE 6 width fixes (See Bug #6793)
+    _resizeIE6: function()
+    {
+        // One width to rule them all:
+        // 20 label, 2 label border, 2 label margin, 16 scrollbar,
+        // 7 cols, 2 col border, 2 col margin
+        var col_width = (($('kronolithViewMonth').getWidth()-20-2-2-16)/7)-2-2;
+        $('kronolithViewMonth').select('.kronolithCol').invoke('setStyle', { width: col_width + 'px' });
+
+        // Set month dimensions.
+        // 6 rows, 2 row border, 2 row margin
+        var col_height = (($('kronolithViewMonth').getHeight()-25)/6)-2-2;
+        $('kronolithViewMonth').select('.kronolithViewBody .kronolithCol').invoke('setStyle', { height: col_height + 'px' });
+        $('kronolithViewMonth').select('.kronolithViewBody .kronolithFirstCol').invoke('setStyle', { height: col_height + 'px' });
+
+        // Set week dimensions.
+        $('kronolithViewWeek').select('.kronolithCol').invoke('setStyle', { width: (col_width - 1) + 'px' });
+
+        // Set day dimensions.
+        // 20 label, 2 label border, 2 label margin, 16 scrollbar, 2 col border
+        var head_col_width = $('kronolithViewDay').getWidth()-20-2-2-16-3;
+        // 20 label, 2 label border, 2 label margin, 16 scrollbar, 2 col border
+        // 7 cols
+        var col_width = ((head_col_width+7)/7)-1;
+        $('kronolithViewDay').select('.kronolithViewHead .kronolithCol').invoke('setStyle', { width: head_col_width + 'px' });
+        $('kronolithViewDay').select('.kronolithViewBody .kronolithCol').invoke('setStyle', { width: col_width + 'px' });
+        $('kronolithViewDay').select('.kronolithViewBody .kronolithAllDay .kronolithCol').invoke('setStyle', { width: head_col_width + 'px' });
+
+        /*
+        if (Kronolith.conf.is_ie6) {
+            var tmp = parseInt($('sidebarPanel').getStyle('width'), 10),
+                tmp1 = document.viewport.getWidth() - tmp - 30;
+            $('normalfolders').setStyle({ width: tmp + 'px' });
+            $('kronlithmain').setStyle({ width: tmp1 + 'px' });
+            $('msglist').setStyle({ width: (tmp1 - 5) + 'px' });
+            $('msgBody').setStyle({ width: (tmp1 - 25) + 'px' });
+            tmp = $('dimpmain_portal').down('IFRAME');
+            if (tmp) {
+                this._resizeIE6Iframe(tmp);
+            }
+        }
+        */
+    },
+
+    _resizeIE6Iframe: function(iframe)
+    {
+        if (Kronolith.conf.is_ie6) {
+            iframe.setStyle({ width: $('kronolithmain').getStyle('width'), height: (document.viewport.getHeight() - 20) + 'px' });
+        }
+    },
+
+    editEvent: function()
+    {
+        $('kronolithEventForm').appear({ duration: 0.5 });
+    },
+
+    toggleCalendar: function(elm)
+    {
+        if (elm.hasClassName('on')) {
+            elm.removeClassName('on');
+        } else {
+            elm.addClassName('on');
+        }
+    }
+
+};
+
+// Initialize DMenu now.  Need to init here because IE doesn't load dom:loaded
+// in a predictable order.
+if (typeof ContextSensitive != 'undefined') {
+    KronolithCore.DMenu = new ContextSensitive();
+}
+
+document.observe('dom:loaded', function() {
+    /* Don't do additional onload stuff if we are in a popup. We need a
+     * try/catch block here since, if the page was loaded by an opener
+     * out of this current domain, this will throw an exception. */
+    try {
+        if (parent.opener &&
+            parent.opener.location.host == window.location.host &&
+            parent.opener.KronolithCore) {
+            Kronolith.baseWindow = parent.opener.Kronolith.baseWindow || parent.opener;
+        }
+    } catch (e) {}
+
+    /* Init garbage collection function - runs every 10 seconds. */
+    new PeriodicalExecuter(function() {
+        if (KronolithCore.remove_gc.size()) {
+            try {
+                $A(KronolithCore.remove_gc.splice(0, 75)).compact().invoke('stopObserving');
+            } catch (e) {
+                KronolithCore.debug('remove_gc[].stopObserving', e);
+            }
+        }
+    }, 10);
+
+    //$('kronolithLoading').hide();
+    //$('kronolithPage').show();
+
+    /* Start message list loading as soon as possible. */
+    KronolithCore._onLoad();
+
+    /* Bind key shortcuts. */
+    document.observe('keydown', KronolithCore._keydownHandler.bind(KronolithCore));
+
+    /* Resize elements on window size change. */
+    Event.observe(window, 'resize', KronolithCore._onResize.bind(KronolithCore));
+
+    if (Kronolith.conf.is_ie6) {
+        /* Disable text selection in preview pane for IE 6. */
+        document.observe('selectstart', Event.stop);
+
+        /* Since IE 6 doesn't support hover over non-links, use javascript
+         * events to replicate mouseover CSS behavior. */
+        $('foobar').compact().invoke('select', 'LI').flatten().compact().each(function(e) {
+            e.observe('mouseover', e.addClassName.curry('over')).observe('mouseout', e.removeClassName.curry('over'));
+        });
+    }
+});
+
+Event.observe(window, 'load', function() {
+    KronolithCore.window_load = true;
+});
+
+/* Helper methods for setting/getting element text without mucking
+ * around with multiple TextNodes. */
+Element.addMethods({
+    setText: function(element, text)
+    {
+        var t = 0;
+        $A(element.childNodes).each(function(node) {
+            if (node.nodeType == 3) {
+                if (t++) {
+                    Element.remove(node);
+                } else {
+                    node.nodeValue = text;
+                }
+            }
+        });
+
+        if (!t) {
+            $(element).insert(text);
+        }
+    },
+
+    getText: function(element, recursive)
+    {
+        var text = '';
+        $A(element.childNodes).each(function(node) {
+            if (node.nodeType == 3) {
+                text += node.nodeValue;
+            } else if (recursive && node.hasChildNodes()) {
+                text += $(node).getText(true);
+            }
+        });
+        return text;
+    }
+});
+
+/* Create some utility functions. */
+Object.extend(Array.prototype, {
+    numericSort: function()
+    {
+        return this.sort(function(a, b) {
+            if (a > b) {
+                return 1;
+            } else if (a < b) {
+                return -1;
+            }
+            return 0;
+        });
+    }
+});
+
+Object.extend(String.prototype, {
+    // We define our own version of evalScripts() to make sure that all
+    // scripts are running in the same scope and that all functions are
+    // defined in the global scope. This is not the case when using
+    // prototype's evalScripts().
+    evalScripts: function()
+    {
+        var re = /function\s+([^\s(]+)/g;
+        this.extractScripts().each(function(s) {
+            var func;
+            eval(s);
+            while (func = re.exec(s)) {
+                window[func[1]] = eval(func[1]);
+            }
+        });
+    }
+});
index 1510b50..79f0b7c 100644 (file)
@@ -44,6 +44,120 @@ define('PERMS_DELEGATE', 1024);
 class Kronolith {
 
     /**
+     * Output everything up to but not including the <body> tag.
+     *
+     * @since Kronolith 3.0
+     *
+     * @param string $title   The title of the page.
+     * @param array $scripts  Any additional scripts that need to be loaded.
+     *                        Each entry contains the three elements necessary
+     *                        for a Horde::addScriptFile() call.
+     */
+    function header($title, $scripts = array())
+    {
+        // Don't autoload any javascript files.
+        Horde::disableAutoloadHordeJS();
+
+        // Need to include script files before we start output
+        Horde::addScriptFile('prototype.js', 'horde', true);
+        Horde::addScriptFile('effects.js', 'horde', true);
+
+        // ContextSensitive must be loaded first.
+        while (list($key, $val) = each($scripts)) {
+            if (($val[0] == 'ContextSensitive.js') &&
+                ($val[1] == 'kronolith')) {
+                Horde::addScriptFile($val[0], $val[1], $val[2]);
+                unset($scripts[$key]);
+                break;
+            }
+        }
+        Horde::addScriptFile('kronolith.js', 'kronolith', true);
+
+        // Add other scripts now
+        foreach ($scripts as $val) {
+            call_user_func_array(array('Horde', 'addScriptFile'), $val);
+        }
+
+        $page_title = $GLOBALS['registry']->get('name');
+        if (!empty($title)) {
+            $page_title .= ' :: ' . $title;
+        }
+
+        if (isset($GLOBALS['language'])) {
+            header('Content-type: text/html; charset=' . NLS::getCharset());
+            header('Vary: Accept-Language');
+        }
+
+        echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">' . "\n" .
+             (!empty($GLOBALS['language']) ? '<html lang="' . strtr($GLOBALS['language'], '_', '-') . '"' : '<html') . ">\n".
+             "<head>\n" .
+             '<title>' . htmlspecialchars($page_title) . "</title>\n" .
+             '<link href="' . $GLOBALS['registry']->getImageDir() . "/favicon.ico\" rel=\"SHORTCUT ICON\" />\n".
+             Kronolith::wrapInlineScript(Kronolith::includeJSVars());
+
+        Kronolith::includeStylesheetFiles(true);
+
+        echo "</head>\n";
+
+        // Send what we have currently output so the browser can start
+        // loading CSS/JS. See:
+        // http://developer.yahoo.com/performance/rules.html#flush
+        flush();
+    }
+
+    /**
+     * Outputs the javascript code which defines all javascript variables
+     * that are dependent on the local user's account.
+     *
+     * @since Kronolith 3.0
+     *
+     * @private
+     *
+     * @return string
+     */
+    function includeJSVars()
+    {
+        global $browser, $conf, $prefs, $registry;
+
+        require_once 'Horde/Serialize.php';
+
+        $kronolith_webroot = $registry->get('webroot');
+        $horde_webroot = $registry->get('webroot', 'horde');
+
+        /* Variables used in core javascript files. */
+        $code['conf'] = array(
+            'URI_AJAX' => Horde::url($kronolith_webroot . '/ajax.php', true, -1),
+            'URI_PREFS' => Horde::url($horde_webroot . '/services/prefs/', true, -1),
+            //'URI_VIEW' => Util::addParameter(Horde::url($imp_webroot . '/view.php', true, -1), array('actionID' => 'view_source', 'id' => 0), null, false),
+
+            'SESSION_ID' => defined('SID') ? SID : '',
+
+            'prefs_url' => str_replace('&amp;', '&', Horde::getServiceLink('options', 'kronolith')),
+
+            'name' => $registry->get('name'),
+
+            'is_ie6' => ($browser->isBrowser('msie') && ($browser->getMajor() < 7)),
+
+            'login_view' => $prefs->getValue('defaultview'),
+
+            // Turn debugging on?
+            'debug' => !empty($conf['js']['debug']),
+        );
+
+        /* Gettext strings used in core javascript files. */
+        $code['text'] = array_map('addslashes', array(
+        ));
+        for ($i = 1; $i <= 12; ++$i) {
+            $code['text']['month'][$i - 1] = NLS::getLangInfo(constant('MON_' . $i));
+        }
+        for ($i = 1; $i <= 7; ++$i) {
+            $code['text']['weekday'][$i] = NLS::getLangInfo(constant('DAY_' . $i));
+        }
+
+        return array('var Kronolith = ' . Horde_Serialize::serialize($code, SERIALIZE_JSON, NLS::getCharset()) . ';');
+    }
+
+    /**
      * Add inline javascript to the output buffer.
      *
      * @since Kronolith 2.2
@@ -70,8 +184,8 @@ class Kronolith {
         }
         $GLOBALS['__kronolith_inline_script'][] = $script;
 
-        // If headers have already been sent, we need to output a
-        // <script> tag directly.
+        // If headers have already been sent, we need to output a <script> tag
+        // directly.
         if (ob_get_length() || headers_sent()) {
             Kronolith::outputInlineScript();
         }
@@ -98,6 +212,274 @@ class Kronolith {
     }
 
     /**
+     * Print inline javascript to output buffer after wrapping with necessary
+     * javascript tags.
+     *
+     * @since Kronolith 3.0
+     *
+     * @param array $script  The script to output.
+     *
+     * @return string  The script with the necessary HTML javascript tags
+     *                 appended.
+     */
+    function wrapInlineScript($script)
+    {
+        return '<script type="text/javascript">//<![CDATA[' . "\n" . implode("\n", $script) . "\n//]]></script>\n";
+    }
+
+    /**
+     * Outputs the necessary script tags, honoring local configuration choices
+     * as to script caching.
+     *
+     * @since Kronolith 3.0
+     */
+    function includeScriptFiles()
+    {
+        global $conf;
+
+        $cache_type = @$conf['server']['cachejs'];
+
+        if (empty($cache_type) ||
+            $cache_type == 'none' ||
+            ($cache_type == 'horde_cache' &&
+             $conf['cache']['driver'] == 'none')) {
+            Horde::includeScriptFiles();
+            return;
+        }
+
+        $js_tocache = $js_force = array();
+        $mtime = array(0);
+
+        $s_list = Horde::listScriptFiles();
+        foreach ($s_list as $app => $files) {
+            foreach ($files as $file) {
+                if ($file['d'] && ($file['f'][0] != '/')) {
+                    $js_tocache[$file['p'] . $file['f']] = false;
+                    $mtime[] = filemtime($file['p'] . $file['f']);
+                } else {
+                    $js_force[] = $file['u'];
+                }
+            }
+        }
+
+        require_once KRONOLITH_BASE . '/lib/version.php';
+        $sig = md5(serialize($s_list) . max($mtime) . KRONOLITH_VERSION);
+
+        switch ($cache_type) {
+        case 'filesystem':
+            $js_filename = '/' . $sig . '.js';
+            $js_path = $conf['server']['cachejsparams']['file_location'] . $js_filename;
+            $js_url = $conf['server']['cachejsparams']['file_url'] . $js_filename;
+            $exists = file_exists($js_path);
+            break;
+
+        case 'horde_cache':
+            require_once 'Horde/Cache.php';
+            $cache = &Horde_Cache::singleton($conf['cache']['driver'], Horde::getDriverConfig('cache', $conf['cache']['driver']));
+            $exists = $cache->exists($sig, empty($conf['server']['cachejsparams']['lifetime']) ? 0 : $conf['server']['cachejsparams']['lifetime']);
+            $js_url = Kronolith::getCacheURL('js', $sig);
+            break;
+        }
+
+        if (!$exists) {
+            $out = '';
+            foreach ($js_tocache as $key => $val) {
+                // Separate JS files with a newline since some compressors may
+                // strip trailing terminators.
+                if ($val) {
+                    // Minify these files a bit by removing newlines and
+                    // comments.
+                    $out .= preg_replace(array('/\n+/', '/\/\*.*?\*\//'), array('', ''), file_get_contents($key)) . "\n";
+                } else {
+                    $out .= file_get_contents($key) . "\n";
+                }
+            }
+
+            switch ($cache_type) {
+            case 'filesystem':
+                register_shutdown_function(array('Kronolith', '_filesystemGC'), 'js');
+                file_put_contents($js_path, $out);
+                break;
+
+            case 'horde_cache':
+                $cache->set($sig, $out);
+                break;
+            }
+        }
+
+        foreach (array_merge(array($js_url), $js_force) as $val) {
+            echo '<script type="text/javascript" src="' . $val . '"></script>' . "\n";
+        }
+    }
+
+    /**
+     * Outputs the necessary style tags, honoring local configuration choices
+     * as to stylesheet caching.
+     *
+     * @since Kronolith 3.0
+     *
+     * @param boolean $print  Include print CSS?
+     */
+    function includeStylesheetFiles($print = false)
+    {
+        global $conf, $prefs, $registry;
+
+        $theme = $prefs->getValue('theme');
+        $themesfs = $registry->get('themesfs');
+        $themesuri = $registry->get('themesuri');
+        $css = Horde::getStylesheets('kronolith', $theme);
+        $css_out = array();
+
+        // Add print specific stylesheets.
+        if ($print) {
+            // Add Horde print stylesheet
+            $css_out[] = array('u' => $registry->get('themesuri', 'horde') . '/print/screen.css',
+                               'f' => $registry->get('themesfs', 'horde') . '/print/screen.css',
+                               'm' => 'print');
+            $css_out[] = array('u' => $themesuri . '/print/screen.css',
+                               'f' => $themesfs . '/print/screen.css',
+                               'm' => 'print');
+            if (file_exists($themesfs . '/' . $theme . '/print.css')) {
+                $css_out[] = array('u' => $themesuri . '/' . $theme . '/print.css',
+                                   'f' => $themesfs . '/' . $theme . '/print.css',
+                                   'm' => 'print');
+            }
+        }
+
+        $css[] = array('u' => $themesuri . '/ajax.css',
+                       'f' => $themesfs .  '/ajax.css');
+
+        // Load custom stylesheets.
+        if (!empty($conf['css_files'])) {
+            foreach ($conf['css_files'] as $css_file) {
+                $css[] = array('u' => $themesuri . '/' . $css_file,
+                               'f' => $themesfs .  '/' . $css_file);
+            }
+        }
+
+        $cache_type = @$conf['server']['cachecss'];
+
+        if (empty($cache_type) ||
+            $cache_type == 'none' ||
+            ($cache_type == 'horde_cache' &&
+             $conf['cache']['driver'] == 'none')) {
+            $css_out = array_merge($css, $css_out);
+        } else {
+            $mtime = array(0);
+            $out = '';
+
+            foreach ($css as $file) {
+                $mtime[] = filemtime($file['f']);
+            }
+
+            require_once KRONOLITH_BASE . '/lib/version.php';
+            $sig = md5(serialize($css) . max($mtime) . KRONOLITH_VERSION);
+
+            switch ($cache_type) {
+            case 'filesystem':
+                $css_filename = '/' . $sig . '.css';
+                $css_path = $conf['server']['cachecssparams']['file_location'] . $css_filename;
+                $css_url = $conf['server']['cachecssparams']['file_url'] . $css_filename;
+                $exists = file_exists($css_path);
+                break;
+
+            case 'horde_cache':
+                require_once 'Horde/Cache.php';
+                $cache = &Horde_Cache::singleton($GLOBALS['conf']['cache']['driver'], Horde::getDriverConfig('cache', $GLOBALS['conf']['cache']['driver']));
+                $exists = $cache->exists($sig, empty($GLOBALS['conf']['server']['cachecssparams']['lifetime']) ? 0 : $GLOBALS['conf']['server']['cachecssparams']['lifetime']);
+                $css_url = Kronolith::getCacheURL('css', $sig);
+                break;
+            }
+
+            if (!$exists) {
+                $flags = defined('FILE_IGNORE_NEW_LINES') ? (FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) : 0;
+                foreach ($css as $file) {
+                    $path = substr($file['u'], 0, strrpos($file['u'], '/') + 1);
+                    // Fix relative URLs, remove multiple whitespaces, and
+                    // strip comments.
+                    $out .= preg_replace(array('/(url\(["\']?)([^\/])/i', '/\s+/', '/\/\*.*?\*\//'), array('$1' . $path . '$2', ' ', ''), implode('', file($file['f'], $flags)));
+                }
+
+                switch ($cache_type) {
+                case 'filesystem':
+                    register_shutdown_function(array('Kronolith', '_filesystemGC'), 'css');
+                    file_put_contents($css_path, $out);
+                    break;
+
+                case 'horde_cache':
+                    $cache->set($sig, $out);
+                    break;
+                }
+            }
+
+            $css_out = array_merge(array(array('u' => $css_url)), $css_out);
+        }
+
+        foreach ($css_out as $file) {
+            echo '<link href="' . $file['u'] . '" rel="stylesheet" type="text/css"' . (isset($file['m']) ? ' media="' . $file['m'] . '"' : '') . ' />' . "\n";
+        }
+    }
+
+    /**
+     * Creates a URL for cached Kronolith data.
+     *
+     * @since Kronolith 3.0
+     *
+     * @param string $type  The cache type.
+     * @param string $cid   The cache id.
+     *
+     * @return string  The URL to the cache page.
+     */
+    function getCacheURL($type, $cid)
+    {
+        $parts = array(
+            $GLOBALS['registry']->get('webroot'),
+            'cache.php',
+            $type,
+            $cid
+        );
+        return Horde::url(implode('/', $parts));
+    }
+
+    /**
+     * Do garbage collection in the statically served file directory.
+     *
+     * @since Kronolith 3.0
+     *
+     * @access private
+     *
+     * @param string $type  Either 'css' or 'js'.
+     */
+    function _filesystemGC($type)
+    {
+        static $dir_list = array();
+
+        $ptr = $GLOBALS['conf']['server'][(($type == 'css') ? 'cachecssparams' : 'cachejsparams')];
+        $dir = $ptr['file_location'];
+        if (in_array($dir, $dir_list)) {
+            return;
+        }
+
+        $c_time = time() - $ptr['lifetime'];
+        $d = dir($dir);
+        $dir_list[] = $dir;
+
+        while (($entry = $d->read()) !== false) {
+            $path = $dir . '/' . $entry;
+            if (in_array($entry, array('.', '..'))) {
+                continue;
+            }
+
+            if ($c_time > filemtime($path)) {
+                $old_error = error_reporting(0);
+                unlink($path);
+                error_reporting($old_error);
+            }
+        }
+        $d->close();
+    }
+
+    /**
      * Returns all the events that happen each day within a time period.
      *
      * @param object $startDate    The start of the time range.
@@ -2031,6 +2413,35 @@ class Kronolith {
     }
 
     /**
+     * Returns the background color for a calendar.
+     *
+     * @param array|Horde_Share_Object $calendar  A calendar share or a hash
+     *                                            from a remote calender
+     *                                            definition.
+     *
+     * @return string  A HTML color code.
+     */
+    function backgroundColor($calendar)
+    {
+        $color = is_array($calendar) ? @$calendar['color'] : $calendar->get('color');
+        return empty($color) ? '#dddddd' : $color;
+    }
+
+    /**
+     * Returns the foreground color for a calendar.
+     *
+     * @param array|Horde_Share_Object $calendar  A calendar share or a hash
+     *                                            from a remote calender
+     *                                            definition.
+     * @return string  A HTML color code.
+     */
+    function foregroundColor($calendar)
+    {
+        require_once 'Horde/Image.php';
+        return Horde_Image::brightness(Kronolith::backgroundColor($calendar)) < 128 ? '#f6f6f6' : '#000';
+    }
+
+    /**
      * Builds Kronolith's list of menu items.
      */
     function getMenu($returnType = 'object')
diff --git a/kronolith/templates/index/day.inc b/kronolith/templates/index/day.inc
new file mode 100644 (file)
index 0000000..0cd9dcf
--- /dev/null
@@ -0,0 +1,75 @@
+<div id="kronolithViewDay" class="kronolithView kronolithViewDay" style="display:none">
+
+<div class="kronolithViewHead">
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol">&nbsp;</div>
+    <div class="kronolithCol"><span>Monday, October 1, 2008</span></div>
+  </div>
+</div>
+<div class="kronolithViewBody">
+  <div class="kronolithRow kronolithAllDay">
+     <div class="kronolithFirstCol"><?php echo _("All day") ?></div>
+    <div class="kronolithCol">
+      <div class="kronolithEvent c3">Restauração da Independência</div>
+      <div class="kronolithEvent c2">Dia Mundial da Usabilidade</div>
+    </div>
+  </div>
+<?php for ($i = 0; $i < 24; $i++): ?>
+  <div class="kronolithRow<?php if ($i < 9 || $i > 19) echo ' kronolithNight' ?>">
+    <div class="kronolithFirstCol"><?php printf('%02d', $i) ?></div>
+    <div class="kronolithCol kronolithFirstField"></div>
+    <div class="kronolithCol"></div>
+    <div class="kronolithCol"></div>
+    <div class="kronolithCol"></div>
+    <div class="kronolithCol"></div>
+    <div class="kronolithCol"></div>
+    <div class="kronolithCol kronolithLastField"></div>
+  </div>
+<?php endfor; ?>
+
+  <div class="kronolithEvents">
+    <div class="kronolithEvent c1 kronolithEventFull col1 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c2 kronolithEventFull col2 hour1 length6">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col3 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col4 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col5 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col6 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col7 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+  </div>
+</div>
+
+</div>
diff --git a/kronolith/templates/index/index.inc b/kronolith/templates/index/index.inc
new file mode 100644 (file)
index 0000000..36c9834
--- /dev/null
@@ -0,0 +1,244 @@
+<!-- ini header -->
+<div id="kronolithHeader">
+  <div id="kronolithLogo"><h1><a href="#"><?php echo $registry->get('name') ?></a></h1></div>
+
+  <!-- ini user zone -->
+  <div id="kronolithUser">
+   <?php echo $identity->getName(); if ($logout_link) echo ' <span class="kronolithSeparator">&middot;</span> ' . $logout_link ?><br />
+   <a href="#" id="kronolithToday"><?php echo _("Today") ?></a> <span class="kronolithSeparator">&middot;</span> <a href="#"><?php echo _("Options") ?></a><?php if ($help_link) echo ' <span class="kronolithSeparator">&middot;</span> ' . $help_link ?><br />
+  </div>
+  <!-- end user zone -->
+</div>
+<!-- end header -->
+
+<!-- ini bar -->
+<div id="kronolithBar">
+  <form>
+    <div class="kronolithDateChoice">
+      <div id="kronolithDateChoiceDay"><?php echo $today->format('l, j') ?></div>
+    </div>
+    <div class="kronolithDateChoice">
+      <div id="kronolithDateChoiceMonth"><?php echo $today->format('F') ?></div>
+    </div>
+    <div class="kronolithDateChoice">
+      <div id="kronolithDateChoiceYear"><?php echo $today->format('Y') ?></div>
+    </div>
+  </form>
+
+  <div id="kronolithNav">
+    <a id="kronolithNavDay"><?php echo _("Day") ?></a>
+    <a id="kronolithNavWeek"><?php echo _("Week") ?></a>
+    <a id="kronolithNavMonth"><?php echo _("Month") ?></a>
+    <a id="kronolithNavYear"><?php echo _("Year") ?></a>
+    <a id="kronolithNavTasks"><?php echo _("Tasks") ?></a>
+    <a id="kronolithNavAgenda"><?php echo _("Agenda") ?></a>
+  </div>
+</div>
+<!-- end bar -->
+
+<!-- ini main area -->
+<div id="kronolithMain">
+
+<!-- ini menu -->
+<div id="kronolithMenu">
+  <div id="kronolithAddEvents">
+    <span id="kronolithNewEvent"><?php echo _("New event") ?></span>
+    <span id="kronolithQuickEvent" onclick="$('kronolithQuickinsert').appear()">+</span>
+  </div>
+
+  <h3>
+    <a href="#" class="kronolithAdd">+</a>
+    <?php echo _("My Calendars") ?>
+  </h3>
+
+  <?php if (count($my_calendars)): ?>
+  <div class="kronolithCalendars">
+    <?php foreach ($my_calendars as $id => $cal): ?>
+    <div class="<?php echo (in_array($id, $display_calendars)) ? 'kronolithCalOn' : 'kronolithCalOff' ?> full" style="background-color:<?php echo Kronolith::backgroundColor($cal) ?>;color:<?php echo Kronolith::foregroundColor($cal) ?>"><?php echo htmlspecialchars($cal->get('name')) ?></div>
+    <?php endforeach; ?>
+  </div>
+  <?php endif; ?>
+
+  <h3>
+    <a href="#" class="kronolithAdd">+</a>
+    <?php echo _("Shared Calendars") ?>
+  </h3>
+
+  <?php if (count($shared_calendars)): ?>
+  <div class="kronolithCalendars">
+    <?php foreach ($shared_calendars as $id => $cal): ?>
+    <div class="<?php echo (in_array($id, $display_calendars)) ? 'kronolithCalOn' : 'kronolithCalOff' ?> full" style="background-color:<?php echo Kronolith::backgroundColor($cal) ?>;color:<?php echo Kronolith::foregroundColor($cal) ?>"><?php echo htmlspecialchars($cal->get('name')) ?></div>
+    <?php endforeach; ?>
+  </div>
+  <?php endif; ?>
+
+  <h3>
+    <a href="#" class="kronolithAdd">+</a>
+    <?php echo _("Remote Calendars") ?>
+  </h3>
+
+  <?php if (count($remote_calendars)): ?>
+  <div class="kronolithCalendars">
+    <?php foreach ($remote_calendars as $id => $cal): ?>
+    <div class="<?php echo (in_array($id, $display_calendars)) ? 'kronolithCalOn' : 'kronolithCalOff' ?> full" style="background-color:<?php echo Kronolith::backgroundColor($cal) ?>;color:<?php echo Kronolith::foregroundColor($cal) ?>"><?php echo htmlspecialchars($cal['name']) ?></div>
+    <?php endforeach; ?>
+  </div>
+  <?php endif; ?>
+
+  <div id="kronolithMinical">
+    <table cellspacing="1" cellpadding="0" border="0">
+    <caption>
+      <a id="kronolithMinicalPrev" title="<?php echo _("Previous month") ?>">&lt;</a>
+      <a id="kronolithMinicalNext" title="<?php echo _("Next month") ?>">&gt;</a>
+      <span id="kronolithMinicalDate"><?php echo $today->format('F Y') ?></span>
+    </caption>
+
+    <thead>
+      <tr><th class="kronolithMinicalEmpty">&nbsp;</th><th title="<?php echo _("Monday") ?>"><?php echo substr(_("Monday"), 0, 1) ?></th><th title="<?php echo _("Tuesday") ?>"><?php echo substr(_("Tuesday"), 0, 1) ?></th><th title="<?php echo _("Wednesday") ?>"><?php echo substr(_("Wednesday"), 0, 1) ?></th><th title="<?php echo _("Thursday") ?>"><?php echo substr(_("Thursday"), 0, 1) ?></th><th title="<?php echo _("Friday") ?>"><?php echo substr(_("Friday"), 0, 1) ?></th><th title="<?php echo _("Saturday") ?>"><?php echo substr(_("Saturday"), 0, 1) ?></th><th title="<?php echo _("Sunday") ?>"><?php echo substr(_("Sunday"), 0, 1) ?></th></tr>
+    </thead>
+
+    <tbody>
+    <?php
+    $currentDay = null;
+    $firstDay = clone $today;
+    $firstDay->mday = 1;
+    $week = $firstDay->weekOfYear();
+    while (!$currentDay || $currentDay->month == $today->month):
+        $currentDay = Horde_Date::firstDayOfWeek($week, $today->year);
+    ?>
+      <tr>
+        <td class="kronolithMinicalWeek" date="<?php echo $currentDay->dateString() ?>"><?php echo $week ?></td>
+        <?php for ($i = 0; $i < 7; $i++): ?>
+        <td class="<?php if ($currentDay->month != $today->month) echo 'kronolithMinicalEmpty'; elseif ($currentDay->mday == $today->mday) echo 'on' ?>" date="<?php echo $currentDay->dateString() ?>"><?php echo $currentDay->mday ?></td>
+        <?php $currentDay->mday++; endfor; ?>
+      </tr>
+      <?php $week++; endwhile; ?>
+    </tbody>
+    </table>
+  </div>
+
+  <h3>
+    <a href="#" class="kronolithAdd"><?php echo _("Advanced") ?></a>
+    <?php echo _("Search") ?>
+  </h3>
+
+  <form action="#" method="post">
+    <input type="text" id="kronolithSearch" class="kronolithLongField" /><br />
+    <select name="q_what">
+      <option value="1"><?php echo _("Calendars") ?></option>
+      <option value="2"><?php echo _("Events") ?></option>
+    </select>
+    <input type="submit" value="OK" class="button ok" /><br />
+  </form>
+</div>
+<!-- end menu -->
+
+<!-- ini edit -->
+<div id="kronolithEventForm" style="display:none"><form action="#" method="post">
+<div>
+  <label for="id_ttl"><?php echo _("Title") ?></label><br />
+  <input type="text" name="ttl" id="id_ttl" class="kronolithLongField" />
+</div>
+
+<table cellspacing="2" cellpadding="0" border="0"><tbody>
+  <tr>
+    <td class="rightAlign">
+      <label for="id_local"><?php echo _("Location") ?></label><br />
+      <small><a href="#"><?php echo _("Geolocation") ?></a></small>
+    </td>
+    <td><input type="text" name="local" id="id_local" value="Porto, Portugal" class="kronolithLongField" /></td>
+  </tr>
+
+  <tr>
+    <td class="rightAlign"><label for="id_fullday"><?php echo _("All-day") ?></label></td>
+    <td><input type="checkbox" name="fullday" id="id_fullday" /></td>
+  </tr>
+
+  <tr>
+    <td class="rightAlign"><label for="id_from"><?php echo _("From") ?></label></td>
+    <td>
+      <input type="text" name="from_ymd" id="id_from" value="2006-10-30" size="9" class="kronolithDatePicker" />
+      <?php echo _("at") ?>
+      <input type="text" name="from_Hi" value="10:30" size="4" />
+    </td>
+  </tr>
+
+  <tr>
+    <td class="rightAlign">
+      <label for="id_to"><?php echo _("To") ?></label></td>
+    <td>
+      <input type="text" name="to_ymd" id="id_to" value="2006-10-30" size="9" class="kronolithDatePicker" />
+      <?php echo _("at") ?>
+      <input type="text" name="to_Hi" value="10:30" size="4" />
+    </td>
+  </tr>
+
+  <tr>
+    <td class="rightAlign"><label for="id_recur"><?php echo _("Repeat") ?></label></td>
+    <td><select name="recur" id="id_recur" class="kronolithLongField">
+      <option value="0"><?php echo _("no repeat") ?></option>
+      <option value="1"><?php echo _("Every day") ?></option>
+      <option value="2"><?php echo _("Every week") ?></option>
+      <option value="3"><?php echo _("Every 15 days") ?></option>
+      <option value="4" selected><?php echo _("Every year") ?></option>
+      <option value="5"><?php echo _("Custom...") ?></option>
+    </select></td>
+  </tr>
+</tbody></table>
+
+<div>
+  <label for="id_url"><?php echo _("URL") ?></label><br />
+  <input type="text" name="url" id="id_url" class="kronolithLongField" />
+</div>
+
+<div>
+  <label for="id_tags"><?php echo _("Tags") ?></label><br />
+  <textarea name="tags" id="id_tags" rows="2" class="kronolithLongField"></textarea>
+</div>
+
+<div class="kronolithTags">
+  <span>portugal</span>
+  <span>política</span>
+  <span>religião</span>
+  <span>outra</span>
+  <span>informática</span>
+  <span>lálá</span>
+</div>
+
+<div id="kronolithEventActions">
+  <input type="button" value="<?php echo _("Save") ?>" class="button ok" />
+  <input type="button" value="<?php echo _("Delete") ?>" class="button ko" />
+  <input type="button" value="<?php echo _("Cancel") ?>" class="button cancel" />
+  <span id="kronolithEventAdvancedLink">| <a href="#"><?php echo _("Advanced") ?></a></span><br />
+</div>
+
+</form></div>
+<!-- end edit -->
+
+<!-- ini body -->
+<div id="kronolithBody">
+<?php
+$img_blank = Horde::img('blank.gif', '', 'height="8" width="8"', $registry->getImageDir('horde'));
+require dirname(__FILE__) . '/month.inc';
+require dirname(__FILE__) . '/week.inc';
+require dirname(__FILE__) . '/day.inc';
+?>
+</div>
+<!-- end body -->
+
+</div>
+<!-- end main area -->
+
+<div id="kronolithQuickinsert" style="display:none">
+  <form action="#" method="post">
+    <input type="text" name="q" value="" /> <input type="button" value="ok" class="button ok" onclick="$('kronolithQuickinsert').fade()" /><br />
+    <?php echo _("I.e. Dinner with John tomorrow 10am") ?><br />
+  </form>
+</div>
+
+<div class="kronlithContextMenu" style="display:none">
+  <a href="#">teste</a>
+  <div class="kronolithSeparator"></div>
+  <a href="#">teste</a>
+  <a href="#">teste</a>
+</div>
diff --git a/kronolith/templates/index/month.inc b/kronolith/templates/index/month.inc
new file mode 100644 (file)
index 0000000..d66540b
--- /dev/null
@@ -0,0 +1,170 @@
+<div id="kronolithViewMonth" class="kronolithView kronolithViewMonth" style="display:none">
+
+<div class="kronolithViewHead">
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol">&nbsp;</div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_2) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_3) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_4) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_5) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_6) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_7) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_1) ?></span></div>
+  </div>
+</div>
+
+<div class="kronolithViewBody">
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol">44</div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">25</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">26</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">27</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">28</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">29</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">30</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">1</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+  </div>
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol">45</div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">2</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+      <div class="kronolithEvent c1 kronolithEventFull">Restauração da Independência</div>
+      <div class="kronolithEvent c2">10h Dia Mundial da Usabilidade</div>
+      <div class="kronolithEvent c3">10h Dia Mundial da Usabilidade</div>
+      <div class="kronolithEvent c4">10h Dia Mundial da Usabilidade</div>
+      <div class="kronolithEvent c2">10h Dia Mundial da Usabilidade</div>
+      <div class="kronolithMore"><a href="javascript:show('day');">...</a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">3</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">4</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">5</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">6</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">7</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">8</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+  </div>
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol">46</div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">9</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">10</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">11</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">12</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">13</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">14</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">15</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+  </div>
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol">47</div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">16</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">17</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">18</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">19</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">20</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">21</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">22</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+  </div>
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol">48</div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">23</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">24</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">25</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">26</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">27</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">28</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">29</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+  </div>
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol">49</div>
+    <div class="kronolithCol kronolithToday">
+      <div class="kronolithCorner"><div class="kronolithDay">30</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+      <div class="kronolithEvent c1">10h00 &#149; Dia Mundial da Usabilidade</div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><div class="kronolithDay">31</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">1</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">2</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">3</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">4</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol kronolithOtherMonth">
+      <div class="kronolithCorner"><div class="kronolithDay">5</div><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+  </div>
+</div>
+
+</div>
diff --git a/kronolith/templates/index/week.inc b/kronolith/templates/index/week.inc
new file mode 100644 (file)
index 0000000..5040eb8
--- /dev/null
@@ -0,0 +1,115 @@
+<div id="kronolithViewWeek" class="kronolithView kronolithViewWeek" style="display:none">
+
+<div class="kronolithViewHead">
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol">&nbsp;</div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_2) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_3) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_4) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_5) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_6) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_7) ?></span></div>
+    <div class="kronolithCol"><span><?php echo NLS::getLangInfo(DAY_1) ?></span></div>
+  </div>
+</div>
+<div class="kronolithViewBody">
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol"><?php echo _("All day") ?></div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+      <div class="kronolithEvent c3">Restauração da Independência</div>
+      <div class="kronolithEvent c2">Dia Mundial da Usabilidade</div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+  </div>
+
+<?php for ($i = 0; $i < 24; $i++): ?>
+  <div class="kronolithRow">
+    <div class="kronolithFirstCol"><?php printf('%02d', $i) ?></div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+    <div class="kronolithCol">
+      <div class="kronolithCorner"><a href="javascript:edit();" class="kronolithAdd"><?php echo $img_blank ?></a></div>
+    </div>
+  </div>
+<?php endfor; ?>
+
+  <div class="kronolithEvents">
+    <div class="kronolithEvent c1 kronolithEventFull col1 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c2 kronolithEventFull col2 hour1 length6">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col3 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col4 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col5 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col6 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+
+    <div class="kronolithEvent c1 kronolithEventFull col7 hour0 length2">
+      <div class="kronolithDragger kronolithDraggerTop"></div>
+      <div class="kronolithEventInfo">10h diiaiaiai jkh gjhg fjkgh fkjgh kfjhg jkfhg kjfh g</div>
+      <div class="kronolithDragger kronolithDraggerBottom"></div>
+    </div>
+  </div>
+</div>
+
+</div>
index 075b7e9..120bb78 100644 (file)
@@ -1,4 +1,7 @@
 <?php
+/**
+ * JavaScript variables for the traditional interface.
+ */
 
 require_once 'Horde/Serialize.php';
 $charset = NLS::getCharset();
diff --git a/kronolith/themes/ajax.css b/kronolith/themes/ajax.css
new file mode 100644 (file)
index 0000000..3973a5c
--- /dev/null
@@ -0,0 +1,639 @@
+body {
+    overflow: hidden;
+}
+
+#kronolithToday {
+    font-weight: bold;
+}
+
+.kronolithSeparator {
+    padding-left: 2px;
+    padding-right: 2px;
+    color: #808080;
+}
+
+/* Logo */
+#kronolithLogo {
+    display: none;
+}
+
+/* User data and options */
+#kronolithUser {
+    float: right;
+    margin-top: 8px;
+    margin-right: 10px;
+    font-size: 70%;
+}
+
+/* Main area */
+#kronolithMain {
+    clear: both;
+    padding-top: 15px;
+}
+
+/* Left menu column */
+#kronolithMenu {
+    position: absolute;
+    left: 10px;
+    width: 150px;
+    top: 10px;
+}
+#kronolithMenu h3 {
+    position: relative;
+    margin-top: 15px;
+    margin-bottom: 10px;
+    height: 20px;
+    line-height: 20px;
+    font-size: 100%;
+    font-weight: bold;
+    border-bottom: 1px #000 dotted;
+}
+#kronolithMenu a.kronolithAdd {
+    position: absolute;
+    right: 0;
+    padding-right: 8px;
+    background: transparent url("graphics/plus.png") no-repeat;
+    color: transparent;
+    cursor: pointer;
+}
+#kronolithMenu div.kronolithCalendars {
+    margin-bottom: 15px;
+}
+#kronolithMenu div.kronolithCalendars div {
+    margin-bottom: 5px;
+    padding: 2px 2px 2px 20px;
+    background: url("graphics/checkbox_off.png") 2px center no-repeat;
+    cursor: pointer;
+}
+#kronolithMenu div.kronolithCalendars div.kronolithCalOn {
+    background-image: url("graphics/checkbox_on.png");
+}
+#kronolithMenu div.kronolithCalendars div.kronolithCalOver {
+    background-image: url("graphics/checkbox_over.png");
+}
+
+/* to be removed */
+div.c1 {
+       color: #336600;
+}
+div.c2 {
+       color: #1a5587;
+}
+div.c3 {
+       color: #d38a23;
+}
+div.c4 {
+       color: #4b2a16;
+}
+div.c1.kronolithEventFull {
+       background-color: #336600 !important;
+}
+div.c2.kronolithEventFull {
+       background-color: #1a5587 !important;
+}
+div.c3.kronolithEventFull {
+       background-color: #d38a23 !important;
+}
+div.c4.kronolithEventFull {
+       background-color: #4b2a16 !important;
+}
+
+#kronolithAddEvents span {
+    /* We need some style here. */
+    margin-bottom: 5px;
+    padding-right: 10px;
+    font-weight: bold;
+    cursor: pointer;
+}
+span#kronolithQuickEvent {
+    background: transparent url("graphics/new.png") no-repeat;
+    color: transparent;
+}
+
+#kronolithMenu form {
+    padding: 0;
+    margin: 0 0 5px 0;
+    line-height: 35px;
+}
+#kronolithSearch {
+    width: 80px;
+}
+
+/* Quick edit */
+#kronolithQuickinsert {
+    position: absolute;
+    z-index: 110;
+    left: 105px;
+    top: 10px;
+    width: 250px;
+    height: 75px;
+    margin: 0;
+    padding: 0;
+    background: transparent url("graphics/back_quick.png") top left no-repeat;
+}
+#kronolithQuickinsert form {
+    padding:  5px;
+    margin: 5px 5px 5px 15px;
+}
+
+/* Navigation bar */
+#kronolithBar {
+    position: absolute;
+    left: 175px;
+    top: 10px;
+}
+#kronolithBar form {
+    float: left;
+    margin: 0;
+}
+#kronolithBar .kronolithDateChoice {
+    float: left;
+    margin: 0 2px 0 0;
+    background: #d6d6d6;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    font-weight: bold;
+}
+#kronolithBar .kronolithDateChoice div {
+    padding: 0 10px;
+    height: 25px;
+    line-height: 25px;
+}
+
+#kronolithNav {
+    float: left;
+    margin-left: 5px;
+    height: 25px;
+    line-height: 25px;
+}
+#kronolithNav a {
+    display: block;
+    float: left;
+    margin: 0 1px 0 0;
+    padding: 0 5px 0 25px;
+    background-color: #f0f0f0;
+    background-position: 5px center;
+    background-repeat: no-repeat;
+    font-weight: bold;
+    text-decoration: none;
+    color: #202020;
+    cursor: pointer;
+}
+#kronolithNav a:first-child {
+    -moz-border-radius-topleft: 5px;
+    -moz-border-radius-bottomleft: 5px;
+    -webkit-border-top-left-radius: 5px;
+    -webkit-border-bottom-left-radius: 5px;
+}
+#kronolithNav a:last-child {
+    -moz-border-radius-topright: 5px;
+    -moz-border-radius-bottomright: 5px;
+    -webkit-border-top-right-radius: 5px;
+    -webkit-border-bottom-right-radius: 5px;
+}
+#kronolithNav a:first-child:last-child {
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+}
+#kronolithNav a:hover, #kronolithNav a.on {
+    background-color: #d9d9d9;
+}
+#kronolithNavTasks {
+    background-image: url("graphics/tasks.png");
+}
+#kronolithNavAgenda {
+    background-image: url("graphics/agenda.png");
+}
+#kronolithNavDay {
+    background-image: url("graphics/dayview.png");
+}
+#kronolithNavWeek {
+    background-image: url("graphics/weekview.png");
+}
+#kronolithNavMonth {
+    background-image: url("graphics/monthview.png");
+}
+#kronolithNavYear {
+    background-image: url("graphics/yearview.png");
+}
+
+/* Event form dialog */
+#kronolithEventForm {
+    position: absolute;
+    z-index: 1000;
+    left: 50%;
+    margin-left: -210px;
+    top: 50px;
+    width: 400px;
+    padding: 10px 20px;
+    background: #efefef;
+    border: 1px #c0c0c0 solid;
+}
+#kronolithEventForm div {
+    margin-bottom: 5px;
+}
+#kronolithEventForm label {
+    font-weight: bold;
+}
+#kronolithEventForm input.kronolithDatePicker {
+    padding-right: 20px;
+    background-image: url("graphics/picker.png");
+    background-position: right center;
+    background-repeat: no-repeat;
+}
+.kronolithLongField {
+    width: 100%;
+}
+div#kronolithEventActions {
+    margin: 5px 0;
+}
+div#kronolithEventActions #kronolithEventAdvancedLink {
+    padding-left: 2px;
+}
+div#kronolithEventActions #kronolithEventAdvancedLink a {
+    color: inherit;
+}
+
+div.kronolithTags {
+    max-height: 75px;
+    overflow: auto;
+    line-height: 20px;
+}
+div.kronolithTags span {
+    padding: 2px 4px;
+    background-color: #fff;
+    border: 1px #c0c0c0 solid;
+    -moz-border-radius: 4px;
+    -webkit-border-radius: 4px;
+    font-size: 90%;
+}
+div.kronolithTags span:hover {
+    background-color: #ffc;
+    cursor: pointer;
+}
+
+/* Context menu */
+.kronolithContextMenu {
+    width: auto;
+    min-width: 150px;
+    padding: 2px;
+    position: absolute;
+    top: 0;
+    z-index: 1000;
+    background: #f4f4f4;
+    border: 1px #c0c0c0 solid;
+    color: #202020;
+}
+.kronolithContextMenu a {
+    display: block;
+    height: 18px;
+    line-height: 18px;
+    padding: 2px 4px;
+    border: 1px #f4f4f4 solid;
+    color: #202020;
+    text-decoration: none;
+    white-space: nowrap;
+
+}
+.kronolithContextMenu a:hover {
+    color: black;
+    text-decoration: none;
+}
+.kronolithContextMenu div.kronolithSeparator {
+    height: 1px;
+    line-height: 1px;
+    background: #d4d4d4;
+    margin-bottom: 1px;
+}
+
+/* Mini calendar */
+#kronolithMinical {
+    position: relative;
+}
+#kronolithMinical table {
+    width: 100%;
+}
+#kronolithMinical caption {
+    position: relative;
+    margin-bottom: 10px;
+    height: 20px;
+    line-height: 20px;
+    font-weight: bold;
+    font-size: 100%;
+    border-bottom: 1px #000 dotted;
+    text-align: left;
+}
+#kronolithMinicalPrev, #kronolithMinicalNext {
+    position: absolute;
+    top: 0;
+    right: 0;
+    font-weight: bold;
+    cursor: pointer;
+    text-decoration: none;
+}
+#kronolithMinicalPrev {
+    right: 15px;
+}
+
+#kronolithMinical th, #kronolithMinical td {
+    font-size: 90%;
+}
+#kronolithMinical thead th, #kronolithMinical tbody td.kronolithMinicalWeek {
+    width: 16px;
+    height: 16px;
+    line-height: 16px;
+    text-align: center;
+    background-color: #d6d6d6;
+    color: #202020;
+    border: 1px #c0c0c0 solid !important;
+}
+#kronolithMinical thead th.kronolithMinicalEmpty {
+    background: none;
+    border: none !important;
+}
+#kronolithMinical tbody td.kronolithMinicalWeek {
+    cursor: pointer;
+}
+#kronolithMinical tbody td {
+    width: 16px;
+    height: 16px;
+    line-height: 16px;
+    border: 1px #e2e2e2 solid;
+    text-align: center;
+    color: #808080;
+    empty-cells: show;
+    cursor: pointer;
+}
+
+#kronolithMinical tbody.kronolithSelected tr td, #kronolithMinical tbody tr.kronolithSelected td, #kronolithMinical tbody td.kronolithSelected {
+    background-color: #ebf3fc;
+    border-color: #808080;
+}
+#kronolithMinical tbody td.on, #kronolithMinical tbody.kronolithSelected tr td.on, #kronolithMinical tbody tr.kronolithSelected td.on {
+    background-color: #808080;
+    border-color: #808080;
+    color: white;
+}
+#kronolithMinical tbody td.kronolithMinicalEmpty, #kronolithMinical tbody.kronolithSelected tr td.kronolithMinicalEmpty, #kronolithMinical tbody tr.kronolithSelected td.kronolithMinicalEmpty {
+    background: none;
+    border: none;
+    color: silver;
+    cursor: default;
+}
+
+/* Main views */
+div.kronolithView {
+    position: absolute;
+    top: 50px;
+    left: 175px;
+    right: 10px;
+    bottom: 10px;
+    display: block;
+    margin: 5px 0;
+    overflow: hidden;
+}
+div.kronolithView div.kronolithRow div {
+    width: 13%;
+}
+
+div.kronolithRow div {
+    float: left;
+    position: relative;
+    margin-right: 2px;
+    margin-bottom: 2px;
+    padding: 0;
+    border: 1px #c0c0c0 solid;
+    overflow: hidden;
+}
+div.kronolithRow div.kronolithFirstCol {
+    width: 20px !important;
+}
+
+/* Main view header row */
+div.kronolithView div.kronolithViewHead div.kronolithRow {
+    height: 20px;
+}
+div.kronolithView div.kronolithViewHead div.kronolithRow div {
+    height: 21px;
+    line-height: 21px;
+    font-weight: bold;
+}
+div.kronolithView div.kronolithViewHead div.kronolithRow div span {
+    padding: 0 5px;
+}
+div.kronolithView div.kronolithViewHead div.kronolithRow div.kronolithFirstCol {
+    border-color: transparent;
+}
+
+/* Main view body */
+div.kronolithView div.kronolithViewBody {
+    position: absolute;
+    top: 25px;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    overflow: auto;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow {
+    clear: both;
+    vertical-align: top;
+    height: auto;
+}
+
+/* Main view month */
+.kronolithViewMonth div.kronolithViewBody div.kronolithRow div {
+    height: 86px;
+}
+
+/* Main view week */
+#kronolithViewWeek div.kronolithViewBody div.kronolithRow div {
+    height: 41px;
+}
+
+/* Main view day */
+.kronolithViewDay div.kronolithViewBody div.kronolithRow div.kronolithFirstCol {
+    margin-right: 2px;
+    border-right-width: 1px;
+}
+.kronolithViewDay div.kronolithViewBody div.kronolithRow div {
+    height: 41px;
+}
+.kronolithViewDay div.kronolithViewBody div.kronolithRow div.kronolithCol {
+    border-width: 1px 0;
+    margin-right: 0;
+}
+.kronolithViewDay div.kronolithViewBody div.kronolithRow div.kronolithCol.kronolithFirstField {
+    border-left-width: 1px;
+}
+.kronolithViewDay div.kronolithViewBody div.kronolithRow div.kronolithCol.kronolithLastField {
+    border-right-width: 1px;
+}
+.kronolithViewDay div.kronolithViewBody div.kronolithRow.kronolithAllDay div.kronolithCol {
+    border-width: 1px;
+}
+
+/* More main view */
+div.kronolithView div.kronolithViewBody div.kronolithRow div {
+    font-size: 95%;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div.kronolithFirstCol {
+    font-weight: bold;
+    text-align: center;
+}
+.kronolithViewDay div.kronolithViewBody div.kronolithRow.kronolithNight div {
+    background-color: #f4f4f4;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div.kronolithFirstCol:hover {
+    cursor: pointer;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div .kronolithCorner {
+    float: left;
+    margin: 0 2px 2px 0;
+    padding: 0;
+    width: auto;
+    height: auto;
+    border: none;
+}
+div.kronolithViewMonth div.kronolithViewBody div.kronolithRow div.kronolithDay {
+    display: inline;
+    width: 15px;
+    height: 15px;
+    line-height: 15px;
+    margin: 0 2px 2px 0;
+    padding: 0;
+    border-width: 0 1px 1px 0;
+    text-align: center;
+    vertical-align: middle;
+    font-weight: bold;
+    cursor: pointer;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div a.kronolithAdd {
+    display: inline;
+    width: 15px;
+    height: 15px;
+    line-height: 15px;
+    padding: 2px;
+    text-align: center;
+    background: transparent url("graphics/new_small_fade.png") 3px 5px no-repeat;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div a.kronolithAdd:hover {
+    background-image: url("graphics/new_small.png");
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div.kronolithOtherMonth {
+    background: #f7f7f7;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div.kronolithOtherMonth .kronolithDay {
+    border-color: transparent;
+    color: silver;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div.kronolithToday {
+    background-color: #ebf3fc;
+    border-color: #808080;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div div.kronolithMore {
+    position: absolute;
+    z-index: 10;
+    right: 0;
+    bottom: 0;
+    width: 15px;
+    height: 15px;
+    background: white;
+    border-right: none;
+    border-bottom: none;
+    text-align: center;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div div.kronolithMore a {
+    text-decoration: none;
+}
+
+/* Events */
+div.kronolithView div.kronolithViewBody div.kronolithRow div .kronolithEvent {
+    float: none;
+    width: auto;
+    height: 15px;
+    line-height: 15px;
+    margin: 0 2px 2px 0;
+    padding: 2px 5px;
+    background: none;
+    border: none;
+    cursor: pointer;
+    overflow: hidden;
+    -moz-border-radius: 4px;
+    -webkit-border-radius: 4px;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div .kronolithEvent.kronolithSelected {
+    height: auto;
+}
+div.kronolithView div.kronolithViewBody div.kronolithRow div .kronolithEvent.kronolithEventFull {
+    color: white !important;
+}
+div.kronolithView .kronolithEvents .kronolithEvent {
+    position: absolute;
+    z-index: 100;
+    width: 12%;
+    margin: 5px;
+    opacity: .8;
+    filter: alpha(opacity=80);
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    color: white;
+}
+div.kronolithViewWeek .kronolithEvents .kronolithEvent {
+    width: 11%;
+}
+div.kronolithView .kronolithEvents .kronolithEvent .kronolithDragger {
+    position: absolute;
+    width: 100%;
+    height: 12px;
+    background: transparent url("graphics/drag-handle.png") center center no-repeat;
+}
+div.kronolithView .kronolithEvents .kronolithEvent.kronolithSelected .kronolithDragger {
+    background-color: #202020;
+}
+div.kronolithView .kronolithEvents .kronolithEvent .kronolithDragger.kronolithDraggerTop {
+    top: 0;
+    -moz-border-radius: 5px 5px 0 0;
+    -webkit-border-top-left-radius: 5px;
+    -webkit-border-top-right-radius: 5px;
+    cursor: n-resize;
+}
+div.kronolithView .kronolithEvents .kronolithEvent .kronolithDragger.kronolithDraggerBottom {
+    bottom: 0;
+    -moz-border-radius: 0 0 5px 5px;
+    -webkit-border-bottom-left-radius: 5px;
+    -webkit-border-bottom-right-radius: 5px;
+    cursor: s-resize;
+}
+div.kronolithView .kronolithEvents .kronolithEvent .kronolithEventInfo {
+    margin: 10px 0;
+    padding: 5px;
+}
+
+/* To be removed */
+.kronolithEvents .kronolithEvent.width50 { width: 5% !important; }
+
+.kronolithEvents .kronolithEvent.col1 { left: 30px; }
+.kronolithEvents .kronolithEvent.col2 { left: 15.5%; }
+.kronolithEvents .kronolithEvent.col3 { left: 28.5%; }
+.kronolithEvents .kronolithEvent.col4 { left: 41.5%; }
+.kronolithEvents .kronolithEvent.col5 { left: 54.5%; }
+.kronolithEvents .kronolithEvent.col6 { left: 67.5%; }
+.kronolithEvents .kronolithEvent.col7 { left: 80.5%; }
+/* done */
+
+.kronolithEvents .kronolithEvent.hour0 { top: 50px; }
+.kronolithEvents .kronolithEvent.hour1 { top: 95px; }
+.kronolithEvents .kronolithEvent.hour2 { top: 140px; }
+.kronolithEvents .kronolithEvent.hour3 { top: 185px; }
+.kronolithEvents .kronolithEvent.hour4 { top: 230px; }
+/* till 23 */
+
+.kronolithEvents .kronolithEvent.length1 { height: 35px; }
+.kronolithEvents .kronolithEvent.length2 { height: 75px; }
+.kronolithEvents .kronolithEvent.length3 { height: 120px; }
+.kronolithEvents .kronolithEvent.length4 { height: 165px; }
+.kronolithEvents .kronolithEvent.length5 { height: 210px; }
+.kronolithEvents .kronolithEvent.length6 { height: 255px; }
+/* till 23 */
+
+/* end tables */
diff --git a/kronolith/themes/graphics/agenda.png b/kronolith/themes/graphics/agenda.png
new file mode 100644 (file)
index 0000000..5132943
Binary files /dev/null and b/kronolith/themes/graphics/agenda.png differ
diff --git a/kronolith/themes/graphics/back_quick.png b/kronolith/themes/graphics/back_quick.png
new file mode 100644 (file)
index 0000000..c99339a
Binary files /dev/null and b/kronolith/themes/graphics/back_quick.png differ
diff --git a/kronolith/themes/graphics/checkbox_off.png b/kronolith/themes/graphics/checkbox_off.png
new file mode 100644 (file)
index 0000000..1a78b26
Binary files /dev/null and b/kronolith/themes/graphics/checkbox_off.png differ
diff --git a/kronolith/themes/graphics/checkbox_on.png b/kronolith/themes/graphics/checkbox_on.png
new file mode 100644 (file)
index 0000000..564a0de
Binary files /dev/null and b/kronolith/themes/graphics/checkbox_on.png differ
diff --git a/kronolith/themes/graphics/checkbox_over.png b/kronolith/themes/graphics/checkbox_over.png
new file mode 100644 (file)
index 0000000..86c0894
Binary files /dev/null and b/kronolith/themes/graphics/checkbox_over.png differ
diff --git a/kronolith/themes/graphics/drag-handle.png b/kronolith/themes/graphics/drag-handle.png
new file mode 100644 (file)
index 0000000..d55eb52
Binary files /dev/null and b/kronolith/themes/graphics/drag-handle.png differ
diff --git a/kronolith/themes/graphics/new_small_fade.png b/kronolith/themes/graphics/new_small_fade.png
new file mode 100644 (file)
index 0000000..87405b4
Binary files /dev/null and b/kronolith/themes/graphics/new_small_fade.png differ
diff --git a/kronolith/themes/graphics/picker.png b/kronolith/themes/graphics/picker.png
new file mode 100644 (file)
index 0000000..2712746
Binary files /dev/null and b/kronolith/themes/graphics/picker.png differ
diff --git a/kronolith/themes/graphics/submit.png b/kronolith/themes/graphics/submit.png
new file mode 100644 (file)
index 0000000..56b32a7
Binary files /dev/null and b/kronolith/themes/graphics/submit.png differ
diff --git a/kronolith/themes/graphics/tasks.png b/kronolith/themes/graphics/tasks.png
new file mode 100644 (file)
index 0000000..b39605d
Binary files /dev/null and b/kronolith/themes/graphics/tasks.png differ