Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #4574 -- Added CSS classes to the admin calendar widget for bet…

…ter control over styling.
  • Loading branch information...
commit af67ce5e18525ba52ee4533229468ed07f912536 1 parent 2bc5143
Roberto Aguilar authored September 07, 2013 jphalip committed September 10, 2013
3  django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js
@@ -293,8 +293,9 @@ var DateTimeShortcuts = {
293 293
             var date_parts = inp.value.split('-');
294 294
             var year = date_parts[0];
295 295
             var month = parseFloat(date_parts[1]);
  296
+            var selected = new Date(inp.value);
296 297
             if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) {
297  
-                DateTimeShortcuts.calendars[num].drawDate(month, year);
  298
+                DateTimeShortcuts.calendars[num].drawDate(month, year, selected);
298 299
             }
299 300
         }
300 301
 
43  django/contrib/admin/static/admin/js/calendar.js
@@ -27,13 +27,29 @@ var CalendarNamespace = {
27 27
         }
28 28
         return days;
29 29
     },
30  
-    draw: function(month, year, div_id, callback) { // month = 1-12, year = 1-9999
  30
+    draw: function(month, year, div_id, callback, selected) { // month = 1-12, year = 1-9999
31 31
         var today = new Date();
32 32
         var todayDay = today.getDate();
33 33
         var todayMonth = today.getMonth()+1;
34 34
         var todayYear = today.getFullYear();
35 35
         var todayClass = '';
36 36
 
  37
+        // Use UTC functions here because the date field does not contain time
  38
+        // and using the UTC function variants prevent the local time offset
  39
+        // from altering the date, specifically the day field.  For example:
  40
+        //
  41
+        // ```
  42
+        // var x = new Date('2013-10-02');
  43
+        // var day = x.getDate();
  44
+        // ```
  45
+        //
  46
+        // The day variable above will be 1 instead of 2 in, say, US Pacific time
  47
+        // zone.
  48
+        var isSelectedMonth = false;
  49
+        if (typeof selected != 'undefined') {
  50
+            isSelectedMonth = (selected.getUTCFullYear() == year && (selected.getUTCMonth()+1) == month);
  51
+        }
  52
+
37 53
         month = parseInt(month);
38 54
         year = parseInt(year);
39 55
         var calDiv = document.getElementById(div_id);
@@ -55,7 +71,7 @@ var CalendarNamespace = {
55 71
         tableRow = quickElement('tr', tableBody);
56 72
         for (var i = 0; i < startingPos; i++) {
57 73
             var _cell = quickElement('td', tableRow, ' ');
58  
-            _cell.style.backgroundColor = '#f3f3f3';
  74
+            _cell.className = "nonday";
59 75
         }
60 76
 
61 77
         // Draw days of month
@@ -69,6 +85,13 @@ var CalendarNamespace = {
69 85
             } else {
70 86
                 todayClass='';
71 87
             }
  88
+
  89
+            // use UTC function; see above for explanation.
  90
+            if (isSelectedMonth && currentDay == selected.getUTCDate()) {
  91
+                if (todayClass != '') todayClass += " ";
  92
+                todayClass += "selected";
  93
+            }
  94
+
72 95
             var cell = quickElement('td', tableRow, '', 'class', todayClass);
73 96
 
74 97
             quickElement('a', cell, currentDay, 'href', 'javascript:void(' + callback + '('+year+','+month+','+currentDay+'));');
@@ -78,7 +101,7 @@ var CalendarNamespace = {
78 101
         // Draw blanks after end of month (optional, but makes for valid code)
79 102
         while (tableRow.childNodes.length < 7) {
80 103
             var _cell = quickElement('td', tableRow, ' ');
81  
-            _cell.style.backgroundColor = '#f3f3f3';
  104
+            _cell.className = "nonday";
82 105
         }
83 106
 
84 107
         calDiv.appendChild(calTable);
@@ -86,7 +109,7 @@ var CalendarNamespace = {
86 109
 }
87 110
 
88 111
 // Calendar -- A calendar instance
89  
-function Calendar(div_id, callback) {
  112
+function Calendar(div_id, callback, selected) {
90 113
     // div_id (string) is the ID of the element in which the calendar will
91 114
     //     be displayed
92 115
     // callback (string) is the name of a JavaScript function that will be
@@ -97,14 +120,22 @@ function Calendar(div_id, callback) {
97 120
     this.today = new Date();
98 121
     this.currentMonth = this.today.getMonth() + 1;
99 122
     this.currentYear = this.today.getFullYear();
  123
+    if (typeof selected != 'undefined') {
  124
+        this.selected = selected;
  125
+    }
100 126
 }
101 127
 Calendar.prototype = {
102 128
     drawCurrent: function() {
103  
-        CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback);
  129
+        CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback, this.selected);
104 130
     },
105  
-    drawDate: function(month, year) {
  131
+    drawDate: function(month, year, selected) {
106 132
         this.currentMonth = month;
107 133
         this.currentYear = year;
  134
+
  135
+        if(selected) {
  136
+            this.selected = selected;
  137
+        }
  138
+
108 139
         this.drawCurrent();
109 140
     },
110 141
     drawPreviousMonth: function() {
73  tests/admin_widgets/tests.py
@@ -549,6 +549,79 @@ def test_show_hide_date_time_picker_widgets(self):
549 549
         self.assertEqual(
550 550
             self.get_css_value('#clockbox0', 'display'), 'none')
551 551
 
  552
+    def test_calendar_nonday_class(self):
  553
+        """
  554
+        Ensure cells that are not days of the month have the `nonday` CSS class.
  555
+        Refs #4574.
  556
+        """
  557
+        self.admin_login(username='super', password='secret', login_url='/')
  558
+        # Open a page that has a date and time picker widgets
  559
+        self.selenium.get('%s%s' % (self.live_server_url,
  560
+            '/admin_widgets/member/add/'))
  561
+
  562
+        # fill in the birth date.
  563
+        self.selenium.find_element_by_id('id_birthdate_0').send_keys('2013-06-01')
  564
+
  565
+        # Click the calendar icon
  566
+        self.selenium.find_element_by_id('calendarlink0').click()
  567
+
  568
+        # get all the tds within the calendar
  569
+        calendar0 = self.selenium.find_element_by_id('calendarin0')
  570
+        tds = calendar0.find_elements_by_tag_name('td')
  571
+
  572
+        # make sure the first and last 6 cells have class nonday
  573
+        for td in tds[:6] + tds[-6:]:
  574
+            self.assertEqual(td.get_attribute('class'), 'nonday')
  575
+
  576
+    def test_calendar_selected_class(self):
  577
+        """
  578
+        Ensure cell for the day in the input has the `selected` CSS class.
  579
+        Refs #4574.
  580
+        """
  581
+        self.admin_login(username='super', password='secret', login_url='/')
  582
+        # Open a page that has a date and time picker widgets
  583
+        self.selenium.get('%s%s' % (self.live_server_url,
  584
+            '/admin_widgets/member/add/'))
  585
+
  586
+        # fill in the birth date.
  587
+        self.selenium.find_element_by_id('id_birthdate_0').send_keys('2013-06-01')
  588
+
  589
+        # Click the calendar icon
  590
+        self.selenium.find_element_by_id('calendarlink0').click()
  591
+
  592
+        # get all the tds within the calendar
  593
+        calendar0 = self.selenium.find_element_by_id('calendarin0')
  594
+        tds = calendar0.find_elements_by_tag_name('td')
  595
+
  596
+        # verify the selected cell
  597
+        selected = tds[6]
  598
+        self.assertEqual(selected.get_attribute('class'), 'selected')
  599
+
  600
+        self.assertEqual(selected.text, '1')
  601
+
  602
+    def test_calendar_no_selected_class(self):
  603
+        """
  604
+        Ensure no cells are given the selected class when the field is empty.
  605
+        Refs #4574.
  606
+        """
  607
+        self.admin_login(username='super', password='secret', login_url='/')
  608
+        # Open a page that has a date and time picker widgets
  609
+        self.selenium.get('%s%s' % (self.live_server_url,
  610
+            '/admin_widgets/member/add/'))
  611
+
  612
+        # Click the calendar icon
  613
+        self.selenium.find_element_by_id('calendarlink0').click()
  614
+
  615
+        # get all the tds within the calendar
  616
+        calendar0 = self.selenium.find_element_by_id('calendarin0')
  617
+        tds = calendar0.find_elements_by_tag_name('td')
  618
+
  619
+        # verify there are no cells with the selected class
  620
+        selected = [td for td in tds if td.get_attribute('class') == 'selected']
  621
+
  622
+        self.assertEqual(len(selected), 0)
  623
+
  624
+
552 625
 class DateTimePickerSeleniumChromeTests(DateTimePickerSeleniumFirefoxTests):
553 626
     webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'
554 627
 

0 notes on commit af67ce5

Please sign in to comment.
Something went wrong with that request. Please try again.