From: Michael M Slusarz Date: Wed, 28 Jul 2010 03:33:27 +0000 (-0600) Subject: Allow month/year/week to be clicked on and trigger events. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=d12cbcd05a630be6adc73b22a07b6e4a88571325;p=horde.git Allow month/year/week to be clicked on and trigger events. Also, clean up event handling so it is all done with a single observe. --- diff --git a/framework/Core/lib/Horde/Core/Ui/JsCalendar.php b/framework/Core/lib/Horde/Core/Ui/JsCalendar.php index 0212519a5..21900559b 100644 --- a/framework/Core/lib/Horde/Core/Ui/JsCalendar.php +++ b/framework/Core/lib/Horde/Core/Ui/JsCalendar.php @@ -28,6 +28,12 @@ class Horde_Core_Ui_JsCalendar * * @param array $params Configuration parameters for the widget: *
+     * 'click_month' - (boolean) If true, the month is clickable.
+     *                 DEFAULT: false
+     * 'click_week' - (boolean) If true, will display a clickable week.
+     *                DEFAULT: false
+     * 'click_year' - (boolean) If true, the year is clickable.
+     *                DEFAULT: false
      * 'full_weekdays' - (boolean) Add full weekday localized list to
      *                   javascript object.
      *                   DEFAULT: false
@@ -44,6 +50,9 @@ class Horde_Core_Ui_JsCalendar
         self::$_initRun = true;
 
         $params = array_merge(array(
+            'click_month' => false,
+            'click_week' => false,
+            'click_year' => false,
             'full_weekdays' => false,
             'short_weekdays' => false
         ), $params);
@@ -57,9 +66,12 @@ class Horde_Core_Ui_JsCalendar
 
         Horde::addScriptFile('calendar.js', 'horde');
         Horde::addInlineScript(array(
-            'Horde_Calendar.firstDayOfWeek = ' . (isset($GLOBALS['prefs']) ? intval($GLOBALS['prefs']->getValue('first_week_day')) : 1),
-            'Horde_Calendar.weekdays = ' . Horde_Serialize::serialize($weekdays, Horde_Serialize::JSON, $GLOBALS['registry']->getCharset()),
-            'Horde_Calendar.months = ' . Horde_Serialize::serialize(self::months(), Horde_Serialize::JSON, $GLOBALS['registry']->getCharset())
+            'Horde_Calendar.click_month = ' . intval($params['click_month']),
+            'Horde_Calendar.click_week = ' . intval($params['click_week']),
+            'Horde_Calendar.click_year = ' . intval($params['click_year']),
+            'Horde_Calendar.firstDayOfWeek = ' . intval($GLOBALS['prefs']->getValue('first_week_day')),
+            'Horde_Calendar.months = ' . Horde_Serialize::serialize(self::months(), Horde_Serialize::JSON, $GLOBALS['registry']->getCharset()),
+            'Horde_Calendar.weekdays = ' . Horde_Serialize::serialize($weekdays, Horde_Serialize::JSON, $GLOBALS['registry']->getCharset())
         ));
         if ($params['full_weekdays']) {
             Horde::addInlineScript(array(
diff --git a/horde/js/calendar.js b/horde/js/calendar.js
index 9de7164c0..76718fae5 100644
--- a/horde/js/calendar.js
+++ b/horde/js/calendar.js
@@ -5,11 +5,25 @@
  * --------------
  * Horde_Calendar:select
  *   params: Date object
+ *   Fired when a date is selected.
+ *
+ * Horde_Calendar:selectMonth
+ *   params: Date object
+ *   Fired when a month is selected.
+ *
+ * Horde_Calendar:selectWeek
+ *   params: Date object
+ *   Fired when a week is selected.
+ *
+ * Horde_Calendar:selectYear
+ *   params: Date object
+ *   Fired when a year is selected.
  */
 
 var Horde_Calendar =
 {
-    // Variables set externally: firstDayOfWeek, fullweekdays, months,
+    // Variables set externally: click_month, click_week, click_year,
+    //                           firstDayOfWeek, fullweekdays, months,
     //                           weekdays
     // Variables defaulting to null: date, month, openDate, trigger, year
 
@@ -63,6 +77,17 @@ var Horde_Calendar =
         return Math.ceil((this.daysInMonth(month, year) - firstWeekDays) / 7) + weeks;
     },
 
+    // http://javascript.about.com/library/blstdweek.htm
+    weekOfYear: function(d)
+    {
+        var newYear = new Date(d.getFullYear(), 0, 1),
+            day = newYear.getDay();
+        if (this.firstDayOfWeek != 0) {
+            day = ((day + (7 - this.firstDayOfWeek)) % 7);
+        }
+        return Math.ceil((((d - newYear) / 86400000) + day + 1) / 7);
+    },
+
     draw: function(timestamp, init)
     {
         this.date = new Date(timestamp);
@@ -91,16 +116,6 @@ var Horde_Calendar =
 
         if (this.firstDayOfWeek == 0) {
             startOfView = 1 - firstOfMonth;
-
-            // We may need to adjust the number of days in the view if
-            // we're starting weeks on Sunday.
-            if (firstOfMonth == 0) {
-                //daysInView -= 7;
-            }
-
-            if ((new Date(this.year, this.month, daysInMonth)).getDay() == 0) {
-                daysInView += 7;
-            }
         } else {
             // @TODO Adjust this for days other than Monday.
             startOfView = (firstOfMonth == 0)
@@ -108,44 +123,39 @@ var Horde_Calendar =
                 : 2 - firstOfMonth;
         }
 
-        div.down('THEAD').down('TR', 1).down('TD', 1).update(this.year);
-        div.down('THEAD').down('TR', 2).down('TD', 1).update(this.months[this.month]);
+        div.down('.hordeCalendarYear').update(this.year);
+        div.down('.hordeCalendarMonth').update(this.months[this.month]);
         tbody.update('');
 
         for (i = startOfView, i_max = startOfView + daysInView; i < i_max; ++i) {
             if (count == 1) {
                 row = new Element('TR');
+                if (this.click_week) {
+                    row.insert(new Element('TD').insert(new Element('A', { className: 'hordeCalendarWeek' }).insert(this.weekOfYear(new Date(this.year, this.month, (i < 1) ? 1 : i)))));
+                }
             }
 
             cell = new Element('TD');
 
             if (i < 1 || i > daysInMonth) {
                 cell.addClassName('hordeCalendarEmpty');
-                row.appendChild(cell);
-
-                if (count == 7) {
-                    tbody.insert(row);
-                    count = 0;
+                row.insert(cell);
+            } else {
+                if (today_year == this.year &&
+                    today_month == this.month &&
+                    today_day == i) {
+                    cell.writeAttribute({ className: 'hordeCalendarToday' });
                 }
 
-                ++count;
-                continue;
-            }
-
-            if (today_year == this.year &&
-                today_month == this.month &&
-                today_day == i) {
-                cell.writeAttribute({ className: 'hordeCalendarToday' });
-            }
+                if (open_year == this.year &&
+                    open_month == this.month &&
+                    open_day == i) {
+                    cell.addClassName('hordeCalendarCurrent');
+                }
 
-            if (open_year == this.year &&
-                open_month == this.month &&
-                open_day == i) {
-                cell.addClassName('hordeCalendarCurrent');
+                row.insert(cell.insert(new Element('A', { className: 'hordeCalendarDay', href: '#' }).insert(i)));
             }
 
-            row.insert(cell.insert(new Element('A', { href: '#' }).insert(i).observe('click', this.dayOnClick.bindAsEventListener(this))));
-
             if (count == 7) {
                 tbody.insert(row);
                 count = 0;
@@ -183,7 +193,7 @@ var Horde_Calendar =
             iframe = $('hordeCalendarIframe');
             if (!iframe) {
                 iframe = new Element('IFRAME', { name: 'hordeCalendarIframe', id: 'hordeCalendarIframe', src: 'javascript:false;', scrolling: 'no', frameborder: 0 }).hide();
-                document.body.appendChild(iframe);
+                $(document.body).insert(iframe);
             }
             iframe.clonePosition(div).setStyle({
                 position: 'absolute',
@@ -194,15 +204,6 @@ var Horde_Calendar =
         }
     },
 
-    dayOnClick: function(e)
-    {
-        this.hideCal();
-
-        this.trigger.fire('Horde_Calendar:select', new Date(this.year, this.month, parseInt(e.element().innerHTML, 10)));
-
-        e.stop();
-    },
-
     hideCal: function()
     {
         var iefix = $('hordeCalendarIframe');
@@ -235,50 +236,94 @@ var Horde_Calendar =
     init: function()
     {
         var i, link, row,
+            offset = this.click_week ? 1 : 0,
             thead = new Element('THEAD'),
             table = new Element('TABLE', { className: 'hordeCalendarPopup', cellSpacing: 0 }).insert(thead).insert(new Element('TBODY'));
 
         // Title bar.
-        link = new Element('A', { href: '#', className: 'hordeCalendarClose' }).insert('x');
-        link.observe('click', function(e) { this.hideCal(); e.stop(); }.bind(this));
-        thead.insert(new Element('TR').insert(new Element('TD', { colSpan: 7, className: 'rightAlign' }).insert(link)));
+        link = new Element('A', { href: '#', className: 'hordeCalendarClose rightAlign' }).insert('x');
+        thead.insert(new Element('TR').insert(new Element('TD', { colspan: 6 + offset })).insert(new Element('TD').insert(link)));
 
         // Year.
         row = new Element('TR');
-        link = new Element('A', { href: '#' }).insert('«');
-        link.observe('click', this.changeYear.bind(this, -1));
+        link = new Element('A', { className: 'hordeCalendarPrevYear', href: '#' }).insert('«');
         row.insert(new Element('TD').insert(link));
 
-        row.insert(new Element('TD', { colSpan: 5, align: 'center' }));
+        tmp = new Element('TD', { align: 'center', colspan: 5 + offset });
+        if (this.click_year) {
+            tmp.insert(new Element('A', { className: 'hordeCalendarYear' }));
+        } else {
+            tmp.addClassName('hordeCalendarYear');
+        }
+        row.insert(tmp);
 
-        link = new Element('A', { href: '#' }).insert('»');
-        link.observe('click', this.changeYear.bind(this, 1));
+        link = new Element('A', { className: 'hordeCalendarNextYear', href: '#' }).insert('»');
         row.insert(new Element('TD', { className: 'rightAlign' }).insert(link));
 
         thead.insert(row);
 
         // Month name.
         row = new Element('TR');
-        link = new Element('A', { href: '#' }).insert('«');
-        link.observe('click', this.changeMonth.bind(this, -1));
+        link = new Element('A', { className: 'hordeCalendarPrevMonth', href: '#' }).insert('«');
         row.insert(new Element('TD').insert(link));
 
-        row.insert(new Element('TD', { colSpan: 5, align: 'center' }));
+        tmp = new Element('TD', { align: 'center', colspan: 5 + offset });
+        if (this.click_year) {
+            tmp.insert(new Element('A', { className: 'hordeCalendarMonth' }));
+        } else {
+            tmp.addClassName('hordeCalendarMonth');
+        }
+        row.insert(tmp);
 
-        link = new Element('A', { href: '#' }).insert('»');
-        link.observe('click', this.changeMonth.bind(this, 1));
+        link = new Element('A', { className: 'hordeCalendarNextMonth', href: '#' }).insert('»');
         row.insert(new Element('TD', { className: 'rightAlign' }).insert(link));
 
         thead.insert(row);
 
         // Weekdays.
         row = new Element('TR');
+        if (this.click_week) {
+            row.insert(new Element('TH'));
+        }
         for (i = 0; i < 7; ++i) {
             row.insert(new Element('TH').insert(this.weekdays[(i + this.firstDayOfWeek) % 7]));
         }
         thead.insert(row);
 
         $(document.body).insert({ bottom: new Element('DIV', { id: 'hordeCalendar' }).setStyle({ position: 'absolute' }).hide().insert(table) });
+
+        $('hordeCalendar').observe('click', this.clickHandler.bindAsEventListener(this));
+    },
+
+    clickHandler: function(e)
+    {
+        var elt = e.element();
+
+        if (elt.hasClassName('hordeCalendarDay')) {
+            this.hideCal();
+            this.trigger.fire('Horde_Calendar:select', new Date(this.year, this.month, parseInt(e.element().textContent, 10)));
+        } else if (elt.hasClassName('hordeCalendarClose')) {
+            this.hideCal();
+        } else if (elt.hasClassName('hordeCalendarPrevYear')) {
+            this.changeYear(-1);
+        } else if (elt.hasClassName('hordeCalendarNextYear')) {
+            this.changeYear(1);
+        } else if (elt.hasClassName('hordeCalendarPrevMonth')) {
+            this.changeMonth(-1);
+        } else if (elt.hasClassName('hordeCalendarNextMonth')) {
+            this.changeMonth(1);
+        } else if (this.click_year && elt.hasClassName('hordeCalendarYear')) {
+            this.trigger.fire('Horde_Calendar:selectYear', new Date(this.year, this.month, 1));
+            this.hideCal();
+        } else if (this.click_month && elt.hasClassName('hordeCalendarMonth')) {
+            this.trigger.fire('Horde_Calendar:selectMonth', new Date(this.year, this.month, 1));
+            this.hideCal();
+        } else if (this.click_week && elt.hasClassName('hordeCalendarWeek')) {
+            this.trigger.fire('Horde_Calendar:selectWeek', new Date(this.year, this.month, elt.up('TR').down('A.hordeCalendarDay').textContent));
+            this.hideCal();
+        }
+
+        e.stop();
     }
 
 };
diff --git a/horde/themes/screen.css b/horde/themes/screen.css
index e16762b60..950250a9d 100644
--- a/horde/themes/screen.css
+++ b/horde/themes/screen.css
@@ -751,6 +751,11 @@ ul.sound-list {
 .hordeCalendarPopup .hordeCalendarToday {
     font-weight: bold;
 }
+.hordeCalendarPopup .hordeCalendarWeek {
+    background: #bbb;
+    font-size: 90%;
+    font-style: italic;
+}
 
 .hidden {
     display: none;