Ticket #15231: patch_admin_datetimeshortcuts.diff

File patch_admin_datetimeshortcuts.diff, 60.2 KB (added by Fabian Büchler, 13 years ago)

patch for current trunk (>= r16402)

  • django/contrib/admin/media/css/widgets.css

     
    333333    right: 0;
    334334}
    335335
    336 .calendar-cancel {
     336.calendar-cancel,
     337.clock-cancel {
    337338    margin: 0 !important;
    338339    padding: 0;
    339340    font-size: 10px;
  • django/contrib/admin/media/js/calendar.js

     
    1 /*
    2 calendar.js - Calendar functions by Adrian Holovaty
    3 */
    4 
    5 function removeChildren(a) { // "a" is reference to an object
    6     while (a.hasChildNodes()) a.removeChild(a.lastChild);
    7 }
    8 
    9 // quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]);
    10 function quickElement() {
    11     var obj = document.createElement(arguments[0]);
    12     if (arguments[2] != '' && arguments[2] != null) {
    13         var textNode = document.createTextNode(arguments[2]);
    14         obj.appendChild(textNode);
    15     }
    16     var len = arguments.length;
    17     for (var i = 3; i < len; i += 2) {
    18         obj.setAttribute(arguments[i], arguments[i+1]);
    19     }
    20     arguments[1].appendChild(obj);
    21     return obj;
    22 }
    23 
    24 // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
    25 var CalendarNamespace = {
    26     monthsOfYear: gettext('January February March April May June July August September October November December').split(' '),
    27     daysOfWeek: gettext('S M T W T F S').split(' '),
    28     firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')),
    29     isLeapYear: function(year) {
    30         return (((year % 4)==0) && ((year % 100)!=0) || ((year % 400)==0));
    31     },
    32     getDaysInMonth: function(month,year) {
    33         var days;
    34         if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12) {
    35             days = 31;
    36         }
    37         else if (month==4 || month==6 || month==9 || month==11) {
    38             days = 30;
    39         }
    40         else if (month==2 && CalendarNamespace.isLeapYear(year)) {
    41             days = 29;
    42         }
    43         else {
    44             days = 28;
    45         }
    46         return days;
    47     },
    48     draw: function(month, year, div_id, callback) { // month = 1-12, year = 1-9999
    49         var today = new Date();
    50         var todayDay = today.getDate();
    51         var todayMonth = today.getMonth()+1;
    52         var todayYear = today.getFullYear();
    53         var todayClass = '';
    54 
    55         month = parseInt(month);
    56         year = parseInt(year);
    57         var calDiv = document.getElementById(div_id);
    58         removeChildren(calDiv);
    59         var calTable = document.createElement('table');
    60         quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month-1] + ' ' + year);
    61         var tableBody = quickElement('tbody', calTable);
    62 
    63         // Draw days-of-week header
    64         var tableRow = quickElement('tr', tableBody);
    65         for (var i = 0; i < 7; i++) {
    66             quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]);
    67         }
    68 
    69         var startingPos = new Date(year, month-1, 1 - CalendarNamespace.firstDayOfWeek).getDay();
    70         var days = CalendarNamespace.getDaysInMonth(month, year);
    71 
    72         // Draw blanks before first of month
    73         tableRow = quickElement('tr', tableBody);
    74         for (var i = 0; i < startingPos; i++) {
    75             var _cell = quickElement('td', tableRow, ' ');
    76             _cell.style.backgroundColor = '#f3f3f3';
    77         }
    78 
    79         // Draw days of month
    80         var currentDay = 1;
    81         for (var i = startingPos; currentDay <= days; i++) {
    82             if (i%7 == 0 && currentDay != 1) {
    83                 tableRow = quickElement('tr', tableBody);
    84             }
    85             if ((currentDay==todayDay) && (month==todayMonth) && (year==todayYear)) {
    86                 todayClass='today';
    87             } else {
    88                 todayClass='';
    89             }
    90             var cell = quickElement('td', tableRow, '', 'class', todayClass);
    91 
    92             quickElement('a', cell, currentDay, 'href', 'javascript:void(' + callback + '('+year+','+month+','+currentDay+'));');
    93             currentDay++;
    94         }
    95 
    96         // Draw blanks after end of month (optional, but makes for valid code)
    97         while (tableRow.childNodes.length < 7) {
    98             var _cell = quickElement('td', tableRow, ' ');
    99             _cell.style.backgroundColor = '#f3f3f3';
    100         }
    101 
    102         calDiv.appendChild(calTable);
    103     }
    104 }
    105 
    106 // Calendar -- A calendar instance
    107 function Calendar(div_id, callback) {
    108     // div_id (string) is the ID of the element in which the calendar will
    109     //     be displayed
    110     // callback (string) is the name of a JavaScript function that will be
    111     //     called with the parameters (year, month, day) when a day in the
    112     //     calendar is clicked
    113     this.div_id = div_id;
    114     this.callback = callback;
    115     this.today = new Date();
    116     this.currentMonth = this.today.getMonth() + 1;
    117     this.currentYear = this.today.getFullYear();
    118 }
    119 Calendar.prototype = {
    120     drawCurrent: function() {
    121         CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback);
    122     },
    123     drawDate: function(month, year) {
    124         this.currentMonth = month;
    125         this.currentYear = year;
    126         this.drawCurrent();
    127     },
    128     drawPreviousMonth: function() {
    129         if (this.currentMonth == 1) {
    130             this.currentMonth = 12;
    131             this.currentYear--;
    132         }
    133         else {
    134             this.currentMonth--;
    135         }
    136         this.drawCurrent();
    137     },
    138     drawNextMonth: function() {
    139         if (this.currentMonth == 12) {
    140             this.currentMonth = 1;
    141             this.currentYear++;
    142         }
    143         else {
    144             this.currentMonth++;
    145         }
    146         this.drawCurrent();
    147     },
    148     drawPreviousYear: function() {
    149         this.currentYear--;
    150         this.drawCurrent();
    151     },
    152     drawNextYear: function() {
    153         this.currentYear++;
    154         this.drawCurrent();
    155     }
    156 }
  • django/contrib/admin/media/js/datetimeshortcuts.js

     
     1/**
     2 * Django admin DateTime shortcuts
     3 *
     4 * @requires jQuery 1.4.2 or later
     5 *
     6 * DateTimeShortcuts
     7 * -----------------
     8 *
     9 * Inserts shortcut buttons (clock and calendar) after all input:text fields
     10 * having the classes .vDateField and .vTimeField.
     11 *
     12 * The $("selector").datetimeshortcuts() plugin is intended to be applied on
     13 * fieldsets or whole forms which contain, or may later contain (inline
     14 * fieldsets) date or time fields.
     15 *
     16 * All options as defined in datetimeshortcuts.defaults can be overwritten by
     17 * passing them as array to the datetimeshortcuts() method.
     18 *
     19 */
     20
     21(function($) {
     22   
     23    $.fn.datetimeshortcuts = function(options) {
     24        // variables set in base.html
     25        var datetimeshortcuts_defaults = $('body').data('datetimeshortcuts_defaults');
     26       
     27        // extend default settings with user options
     28        var o = $.extend({
     29                admin_media_prefix: $('body').data('admin_media_prefix')
     30            },
     31            $.fn.datetimeshortcuts.defaults,
     32            datetimeshortcuts_defaults,
     33            options);
     34       
     35        // Check admin_media_prefix setting:
     36        // usually set in admin/base.html template, but if that was overridden,
     37        // it might be missing. Set it to something clearly invalid so that
     38        // somebody might notice it.
     39        if (o.admin_media_prefix == undefined) {
     40            o.admin_media_prefix = '/missing-admin-media-prefix/';
     41        }
     42       
     43       
     44        /* --- utitity functions ------------------------------------------- */
     45       
     46        // month names
     47        var month_names = gettext('January February March April May June July August September October November December').split(' ');
     48       
     49        // weekday names
     50        var weekdays = gettext('S M T W T F S').split(' ');
     51       
     52        // first day of week
     53        var first_day_of_week = parseInt(get_format('FIRST_DAY_OF_WEEK'));
     54       
     55        // find leap years
     56        var is_leap_year = function(year) {
     57            return new Date(year, 1, 29).getDate() == 29;
     58        };
     59       
     60        // number of days in month
     61        var get_days_in_month = function(month, year) {
     62            return 32 - new Date(year, month-1, 32).getDate();
     63        };
     64       
     65       
     66        /* --- initialization functions ------------------------------------ */
     67       
     68        // add shortcuts for date fields
     69        var add_calendar = function(element) {
     70            // insert span.datetimeshortcuts
     71            var shortcuts = $('<span class="'+o.class_shortcuts+'">').insertAfter(element);
     72           
     73            // insert today link
     74            if (o.enable_today) {
     75                shortcuts.append(' <a href="#" class="'+o.class_today+'">'+gettext('Today')+'</a>');
     76                if (o.enable_calendar) {
     77                    shortcuts.append(" | ");
     78                }
     79            }
     80           
     81            // insert calendar link
     82            if (o.enable_calendar) {
     83                $('<a href="#" class="'+o.class_calendar+'"></a>')
     84                    .appendTo(shortcuts)
     85                    .append('<img src="'+o.admin_media_prefix + 'img/admin/icon_calendar.gif" alt="'+gettext('Calendar')+'" />');
     86            }
     87        };
     88       
     89        // add shortcuts for time fields
     90        var add_clock = function(element) {
     91            // insert span.datetimeshortcuts
     92            var shortcuts = $('<span class="'+o.class_shortcuts+'">').insertAfter(element);
     93           
     94            // insert now link
     95            if (o.enable_now) {
     96                shortcuts.append(' <a href="#" class="'+o.class_now+'">'+gettext('Now')+'</a>');
     97                if (o.enable_clock) {
     98                    shortcuts.append(" | ");
     99                }
     100            }
     101           
     102            // insert clock link
     103            if (o.enable_clock) {
     104                $('<a href="#" class="'+o.class_clock+'"></a>')
     105                    .appendTo(shortcuts)
     106                    .append('<img src="'+o.admin_media_prefix + 'img/admin/icon_clock.gif" alt="'+gettext('Clock')+'" />');
     107            }
     108        };
     109       
     110        // draw a month calendar table
     111        var draw_calendar_table = function(selected, show) {
     112            var y_sel, m_sel, d_sel;
     113            // selected date (optional)
     114            if (selected != null) {
     115                y_sel = selected.getFullYear();
     116                m_sel = selected.getMonth() + 1;
     117                d_sel = selected.getDate();
     118            }
     119            // month to show
     120            var y_show = show.getFullYear();
     121            var m_show = show.getMonth() + 1;
     122            // today
     123            var today = new Date();
     124            var y_tod = today.getFullYear();
     125            var m_tod = today.getMonth() + 1;
     126            var d_tod = today.getDate();
     127           
     128            // create table
     129            var cal = $('<table><caption>'+month_names[m_show-1]+' '+y_show+'</caption></table>')
     130           
     131            // add day-of-week headers
     132            var row = $('<tr>').appendTo(cal);
     133            for (var i = 0; i < 7; i++) {
     134                row.append('<th>'+weekdays[(i + first_day_of_week) % 7]+'</th>');
     135            }
     136           
     137            var start = new Date(y_show, m_show-1, 1 - first_day_of_week).getDay();
     138            var days = get_days_in_month(m_show, y_show);
     139           
     140            // draw blanks before 1st of month
     141            var row = $('<tr>').appendTo(cal);
     142            for (var i = 0; i < start; i++) {
     143                $('<td> </td>').appendTo(row).addClass('nonday');
     144            }
     145           
     146            // draw month days
     147            var current = 1;
     148            for (var i = start; current <= days; i++) {
     149                if (i % 7 == 0 && current != 1) {
     150                    row = $('<tr>').appendTo(cal);
     151                }
     152                var today_class = '';
     153                // mark today
     154                if ((current == d_tod) && (m_show == m_tod) && (y_show == y_tod)) {
     155                    today_class = 'today';
     156                }
     157                // mark selected day
     158                if ((current == d_sel) && (m_show == m_sel) && (y_show == y_sel)) {
     159                    today_class = 'selected';
     160                }
     161                $('<td>').appendTo(row)
     162                    .addClass(today_class)
     163                    .append('<a href="#">'+current+'</a>')
     164                    .find('a')
     165                    .data('date', new Date(y_show, m_show-1, current++));
     166            }
     167           
     168            // draw blanks after last of month
     169            while(row.children('td').length < 7) {
     170                $('<td> </td>').appendTo(row).addClass('nonday');
     171            }
     172           
     173            return cal;
     174        };
     175       
     176        // init one calendar per fieldset
     177        var init_calendar_box = function(fieldset) {
     178            // insert calendar box if not there
     179            if (fieldset.find('.'+o.class_calendarbox).length == 0) {
     180               
     181                $('<div class="'+o.class_calendarbox+' module">'  +
     182                    '  <div>'+
     183                    '    <a href="#" class="calendarnav-previous"><</a>' +
     184                    '    <a href="#" class="calendarnav-next">></a>' +
     185                    '  </div>' +
     186                    '  <div class="calendar_table calendar"></div>' +
     187                    '  <div class="calendar-shortcuts">'+
     188                    '    <a href="#" class="'+o.class_today+' yesterday">'+gettext('Yesterday')+'</a> | <a href="#" class="'+o.class_today+'">'+gettext('Today')+'</a> | <a href="#" class="'+o.class_today+' tomorrow">'+gettext('Tomorrow')+'</a>' +
     189                    '  </div>' +
     190                    '  <p class="calendar-cancel"><a href="#">'+gettext('Cancel')+'</p>' +
     191                    '</div>')
     192                    .appendTo(fieldset).css('position', 'absolute').hide();
     193               
     194                // prev/next event handlers
     195                fieldset.find('.'+o.class_calendarbox)
     196                    .delegate('.calendarnav-previous, .calendarnav-next',
     197                              'click', function(event) {
     198                        var func = $(this).is('.calendarnav-next') ? 'calendar_next' : 'calendar_previous';
     199                        $(this).parents('.'+o.class_calendarbox).trigger(func);
     200                        event.preventDefault();
     201                        event.stopPropagation();
     202                    })
     203                    // days event handlers
     204                    .delegate('td a', 'click', function(event) {
     205                        fieldset.trigger('callback_calendar',
     206                                         $(event.target).data('date'));
     207                        event.preventDefault();
     208                        event.stopPropagation();
     209                    })
     210                    // cancel link
     211                    .find('.calendar-cancel').click(function(event) {
     212                        fieldset.trigger('hide_calendar');
     213                        event.preventDefault();
     214                        event.stopPropagation();
     215                    });
     216            }
     217        };
     218       
     219        // init one clock box per fieldset
     220        var init_clock_box = function(fieldset) {
     221            // insert clock box if not there
     222            if (fieldset.find('.'+o.class_clockbox).length == 0) {
     223               
     224                var timelist = $('<div class="'+o.class_clockbox+' module">'  +
     225                    '  <h2>'+gettext('Choose a time')+'</h2>' +
     226                    '  <ul class="timelist"></ul>' +
     227                    '  <p class="clock-cancel"><a href="#">'+gettext('Cancel')+'</p>' +
     228                    '</div>')
     229                    .appendTo(fieldset).css('position', 'absolute').hide()
     230                    .find('.timelist');
     231               
     232                timelist.append('<li><a href="#">'+gettext('Now')+'</a></li>').find('a:last').data('time', new Date());
     233                timelist.append('<li><a href="#">'+gettext('Midnight')+'</a></li>').find('a:last').data('time', new Date(1970,1,1,0,0));
     234                timelist.append('<li><a href="#">'+gettext('6 a.m.')+'</a></li>').find('a:last').data('time', new Date(1970,1,1,6,0));
     235                timelist.append('<li><a href="#">'+gettext('Noon')+'</a></li>').find('a:last').data('time', new Date(1970,1,1,12,0));
     236               
     237                // time links event handlers
     238                fieldset.find('.'+o.class_clockbox)
     239                    .delegate('li a', 'click', function(event) {
     240                        fieldset.trigger('callback_clock',
     241                                         $(event.target).data('time'));
     242                        event.preventDefault();
     243                        event.stopPropagation();
     244                    })
     245                    // cancel link
     246                    .find('.clock-cancel').click(function(event) {
     247                        fieldset.trigger('hide_clock');
     248                        event.preventDefault();
     249                        event.stopPropagation();
     250                    });
     251            }
     252        };
     253       
     254        return this.each(function() {
     255            var fieldset = $(this);
     256           
     257            /* --- setup datetimeshortcuts specific event handlers --------- */
     258            fieldset
     259           
     260            // show calendar
     261            .bind('show_calendar', function(event) {
     262                fieldset.trigger('hide_clock');
     263                fieldset.trigger('hide_calendar');
     264               
     265                var target = $(event.target);
     266                var calendar = fieldset.children('.'+o.class_calendarbox);
     267                var field = target
     268                    .parents('.'+o.class_shortcuts)
     269                    .prev(o.date_fields);
     270               
     271                // Check current field value for valid date
     272                // and open calendar with that date selected
     273                var date_sel = null;
     274                var date_show = new Date();
     275                if (field.val().length > 0) {
     276                    // only support specific date formats here for simplicity
     277                    // (jQueryUI.datepicker.dateParse could help here)
     278                    var regex = null, y, m, d;
     279                    if (o.date_input_format == '%Y-%m-%d') {
     280                        regex = /^(\d{4})-(\d{2})-(\d{2})$/;
     281                        y=1; m=2; d=3;
     282                    }
     283                    else if (o.date_input_format == '%m/%d/%Y') {
     284                        regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
     285                        y=3; m=1; d=2;
     286                    }
     287                    else if (o.date_input_format == '%m/%d/%y') {
     288                        regex = /^(\d{2})\/(\d{2})\/(\d{2})$/;
     289                        y=3; m=1; d=2;
     290                    }
     291                    else if (o.date_input_format == '%d.%m.%Y') {
     292                        regex = /^(\d{2})\.(\d{2})\.(\d{4})$/;
     293                        y=3; m=2; d=1;
     294                    }
     295                    else if (o.date_input_format == '%d.%m.%y') {
     296                        regex = /^(\d{2})\.(\d{2})\.(\d{2})$/;
     297                        y=3; m=2; d=1;
     298                    }
     299                   
     300                    if (regex != null) {
     301                        var match = regex.exec(field.val());
     302                        if (match != null) {
     303                            year = match[y];
     304                            month = match[m];
     305                            day = match[d];
     306                            if (y.length == 2) {
     307                                year = '20'+year;
     308                            }
     309                            date_sel = new Date(year, month-1, day);
     310                            date_show = new Date(year, month-1, day);
     311                        }
     312                    }
     313                }
     314               
     315                // open calendar
     316                calendar
     317                    // remember field and date
     318                    .data('calendar_date_field', field)
     319                    .data('calendar_date_show', date_show)
     320                    .data('calendar_date_sel', date_sel)
     321                    // draw correct month
     322                    .find('.calendar_table').empty()
     323                    .append(draw_calendar_table(date_sel, date_show))
     324                    .end().show();
     325               
     326                // position based on LTR or RTL direction
     327                var target_pos = target.position();
     328                var dir = $('body').attr('direction');
     329                if (dir != 'rtl') {
     330                    calendar.css('left', target_pos.left + target.width() + 'px');
     331                }
     332                if (dir == 'rtl' ||
     333                    ((calendar.offset().left + calendar.width()) > $(window).width())) {
     334                    calendar.css('left',
     335                        target_pos.left - calendar.width() + 'px');
     336                }
     337                calendar.css('top',
     338                    Math.max(0, target_pos.top - calendar.height()/2) + 'px');
     339               
     340                // bind close handler to document
     341                $('body').bind('click.datetimeshortcuts', function() {
     342                    fieldset.trigger('hide_calendar');
     343                });
     344            })
     345           
     346            // show next month in calendar
     347            .bind('calendar_next', function(event) {
     348                var cal = $(event.target);
     349                var tbl = cal.find('.calendar_table').empty();
     350                var selected = cal.data('calendar_date_sel');
     351                var show = cal.data('calendar_date_show');
     352                var month = show.getMonth();
     353                var year = show.getFullYear();
     354                if (month == 11) {
     355                    month = 0;
     356                    year++;
     357                }
     358                else {
     359                    month++;
     360                }
     361                show.setFullYear(year, month);
     362                cal.data('calendar_date_show', show);
     363                tbl.append(draw_calendar_table(selected, show))
     364            })
     365           
     366            // show previous month in calendar
     367            .bind('calendar_previous', function(event) {
     368                var cal = $(event.target);
     369                var tbl = cal.find('.calendar_table').empty();
     370                var selected = cal.data('calendar_date_sel');
     371                var show = cal.data('calendar_date_show');
     372                var month = show.getMonth();
     373                var year = show.getFullYear();
     374                if (month == 0) {
     375                    month = 11;
     376                    year--;
     377                }
     378                else {
     379                    month--;
     380                }
     381                show.setFullYear(year, month);
     382                cal.data('calendar_date_show', show);
     383                tbl.append(draw_calendar_table(selected, show))
     384            })
     385           
     386            // hide calendar
     387            .bind('hide_calendar', function(event) {
     388                $(event.target)
     389                    .children('.'+o.class_calendarbox)
     390                    .removeData('calendar_date_field')
     391                    .removeData('calendar_date_sel')
     392                    .removeData('calendar_date_show')
     393                    .hide();
     394                $('document').unbind('.datetimeshortcuts');
     395            })
     396           
     397            // show clock
     398            .bind('show_clock', function(event) {
     399                fieldset.trigger('hide_clock');
     400                fieldset.trigger('hide_calendar');
     401               
     402                var target = $(event.target);
     403                var clock = fieldset.children('.'+o.class_clockbox);
     404                var field = target
     405                    .parents('.'+o.class_shortcuts)
     406                    .prev(o.time_fields);
     407               
     408                // open clock
     409                clock
     410                    .data('clock_time_field', field)
     411                    .show();
     412               
     413                // position based on LTR or RTL direction
     414                var target_pos = target.position();
     415                var dir = $('body').attr('direction');
     416                if (dir != 'rtl') {
     417                    clock.css('left', target_pos.left + target.width() + 'px');
     418                }
     419                if (dir == 'rtl' ||
     420                    ((clock.offset().left + clock.width()) > $(window).width())) {
     421                    clock.css('left', target_pos.left - clock.width() + 'px');
     422                }
     423                clock.css('top',
     424                    Math.max(0, target_pos.top - clock.height()/2) + 'px');
     425               
     426                // bind close handler to document
     427                $('body').bind('click.datetimeshortcuts', function() {
     428                    fieldset.trigger('hide_clock');
     429                });
     430            })
     431           
     432            // hide clock
     433            .bind('hide_clock', function(event) {
     434                $(event.target)
     435                    .children('.'+o.class_clockbox)
     436                    .removeData('clock_time_field')
     437                    .hide();
     438                $('document').unbind('.datetimeshortcuts');
     439            })
     440           
     441            // calendar callback
     442            .bind('callback_calendar', function(event, date) {
     443                $(event.target)
     444                    .find('.'+o.class_calendarbox)
     445                    .data('calendar_date_field')
     446                    .val(date.strftime(o.date_input_format))
     447                    .focus();
     448                fieldset.trigger('hide_calendar');
     449            })
     450           
     451            // today link callback
     452            .bind('callback_today', function(event, days_offset) {
     453                var d = new Date();
     454                d.setDate(d.getDate() + days_offset);
     455                $(event.target)
     456                   .val(d.strftime(o.date_input_format))
     457                   .focus();
     458            })
     459           
     460            // clock callback
     461            .bind('callback_clock', function(event, time) {
     462                $(event.target)
     463                    .find('.'+o.class_clockbox)
     464                    .data('clock_time_field')
     465                    .val(time.strftime(o.time_input_format))
     466                    .focus();
     467                fieldset.trigger('hide_clock');
     468            })
     469           
     470            // now link callback
     471            .bind('callback_now', function(event) {
     472                var d = new Date();
     473                $(event.target)
     474                    .val(d.strftime(o.time_input_format))
     475                    .focus();
     476            })
     477           
     478           
     479            /* --- add datetime shortcut widgets --------------------------- */
     480           
     481            // add shortcuts to date fields
     482            fieldset.find(o.date_fields).each(function() {
     483                add_calendar($(this));
     484            });
     485            // add shortcuts to time fields
     486            fieldset.find(o.time_fields).each(function() {
     487                add_clock($(this));
     488            });
     489            // create calendar and clock widgets
     490            init_calendar_box(fieldset);
     491            init_clock_box(fieldset);
     492           
     493           
     494            /* --- setup $(this)-wide event delegation --------------------- */
     495            fieldset
     496           
     497            // click on calendar
     498            .delegate("."+o.class_shortcuts+" ."+o.class_calendar,
     499                      "click", function(event) {
     500                $(event.target).trigger('show_calendar')
     501                // prevent following link
     502                event.preventDefault();
     503                event.stopPropagation();
     504            })
     505           
     506            // click on today link
     507            .delegate("."+o.class_shortcuts+" ."+o.class_today,
     508                      "click", function(event) {
     509                $(event.target)
     510                    // find .datetimeshortcuts span
     511                    .parents('.'+o.class_shortcuts)
     512                    .prev(o.date_fields)
     513                    // update field
     514                    .trigger('callback_today', 0);
     515                fieldset.trigger('hide_calendar');
     516                // prevent following link
     517                event.preventDefault();
     518                event.stopPropagation();
     519            })
     520           
     521            // click on yesterday/today/tomorrow links in calendar
     522            .delegate("."+o.class_calendarbox+" ."+o.class_today,
     523                      "click", function(event) {
     524                var target = $(event.target);
     525                var offset = 0;
     526                if (target.is('.yesterday')) {
     527                    offset = -1;
     528                }
     529                else if (target.is('.tomorrow')) {
     530                    offset = 1;
     531                }
     532                // find calendarbox
     533                target.parents('.'+o.class_calendarbox)
     534                    // target field is stored on calendar's data attribute
     535                    .data('calendar_date_field')
     536                    // update field
     537                    .trigger('callback_today', offset)
     538                    .focus();
     539                fieldset.trigger('hide_calendar');
     540                // prevent following link
     541                event.preventDefault();
     542                event.stopPropagation();
     543            })
     544           
     545            // click on clock
     546            .delegate("."+o.class_shortcuts+" ."+o.class_clock,
     547                      "click", function(event) {
     548                $(event.target).trigger('show_clock');
     549                // prevent following link
     550                event.preventDefault();
     551                event.stopPropagation();
     552            })
     553           
     554            // click on now link
     555            .delegate("."+o.class_shortcuts+" ."+o.class_now,
     556                      "click", function(event) {
     557                $(event.target)
     558                    // find .datetimeshortcuts span
     559                    .parents('.'+o.class_shortcuts)
     560                    .prev(o.time_fields)
     561                    // update field
     562                    .trigger('callback_now');
     563                fieldset.trigger('hide_clock');
     564                // prevent following link
     565                event.preventDefault();
     566                event.stopPropagation();
     567            })
     568        });
     569    };
     570   
     571    $.fn.datetimeshortcuts.defaults = {
     572        // classes (do not change - css depends on these)
     573        class_shortcuts: "datetimeshortcuts",
     574        class_today: "today",
     575        class_calendar: "calendar",
     576        class_now: "now",
     577        class_clock: "clock",
     578        class_calendarbox: "calendarbox",
     579        class_clockbox: "clockbox",
     580        // date and time format
     581        date_input_format: get_format('DATE_INPUT_FORMATS')[0],
     582        time_input_format: get_format('TIME_INPUT_FORMATS')[0],
     583        // selectors for date and time fields
     584        date_fields: "input:text.vDateField",
     585        time_fields: "input:text.vTimeField",
     586        // enable clock or calendar widgets
     587        enable_calendar: true,
     588        enable_today: true,
     589        enable_clock: true,
     590        enable_now: true
     591    }
     592   
     593    // by default, initialize on all fieldset.module elements
     594    // which hold any date or time fields
     595    $(document).ready(function() {
     596       $("fieldset.module").datetimeshortcuts();
     597    });
     598   
     599})(django.jQuery);
  • django/contrib/admin/media/js/admin/DateTimeShortcuts.js

     
    1 // Inserts shortcut buttons after all of the following:
    2 //     <input type="text" class="vDateField">
    3 //     <input type="text" class="vTimeField">
    4 
    5 var DateTimeShortcuts = {
    6     calendars: [],
    7     calendarInputs: [],
    8     clockInputs: [],
    9     calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
    10     calendarDivName2: 'calendarin',  // name of <div> that contains calendar
    11     calendarLinkName: 'calendarlink',// name of the link that is used to toggle
    12     clockDivName: 'clockbox',        // name of clock <div> that gets toggled
    13     clockLinkName: 'clocklink',      // name of the link that is used to toggle
    14     shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts
    15     admin_media_prefix: '',
    16     init: function() {
    17         // Get admin_media_prefix by grabbing it off the window object. It's
    18         // set in the admin/base.html template, so if it's not there, someone's
    19         // overridden the template. In that case, we'll set a clearly-invalid
    20         // value in the hopes that someone will examine HTTP requests and see it.
    21         if (window.__admin_media_prefix__ != undefined) {
    22             DateTimeShortcuts.admin_media_prefix = window.__admin_media_prefix__;
    23         } else {
    24             DateTimeShortcuts.admin_media_prefix = '/missing-admin-media-prefix/';
    25         }
    26 
    27         var inputs = document.getElementsByTagName('input');
    28         for (i=0; i<inputs.length; i++) {
    29             var inp = inputs[i];
    30             if (inp.getAttribute('type') == 'text' && inp.className.match(/vTimeField/)) {
    31                 DateTimeShortcuts.addClock(inp);
    32             }
    33             else if (inp.getAttribute('type') == 'text' && inp.className.match(/vDateField/)) {
    34                 DateTimeShortcuts.addCalendar(inp);
    35             }
    36         }
    37     },
    38     // Add clock widget to a given field
    39     addClock: function(inp) {
    40         var num = DateTimeShortcuts.clockInputs.length;
    41         DateTimeShortcuts.clockInputs[num] = inp;
    42 
    43         // Shortcut links (clock icon and "Now" link)
    44         var shortcuts_span = document.createElement('span');
    45         shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
    46         inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
    47         var now_link = document.createElement('a');
    48         now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().strftime('" + get_format('TIME_INPUT_FORMATS')[0] + "'));");
    49         now_link.appendChild(document.createTextNode(gettext('Now')));
    50         var clock_link = document.createElement('a');
    51         clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
    52         clock_link.id = DateTimeShortcuts.clockLinkName + num;
    53         quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_clock.gif', 'alt', gettext('Clock'));
    54         shortcuts_span.appendChild(document.createTextNode('\240'));
    55         shortcuts_span.appendChild(now_link);
    56         shortcuts_span.appendChild(document.createTextNode('\240|\240'));
    57         shortcuts_span.appendChild(clock_link);
    58 
    59         // Create clock link div
    60         //
    61         // Markup looks like:
    62         // <div id="clockbox1" class="clockbox module">
    63         //     <h2>Choose a time</h2>
    64         //     <ul class="timelist">
    65         //         <li><a href="#">Now</a></li>
    66         //         <li><a href="#">Midnight</a></li>
    67         //         <li><a href="#">6 a.m.</a></li>
    68         //         <li><a href="#">Noon</a></li>
    69         //     </ul>
    70         //     <p class="calendar-cancel"><a href="#">Cancel</a></p>
    71         // </div>
    72 
    73         var clock_box = document.createElement('div');
    74         clock_box.style.display = 'none';
    75         clock_box.style.position = 'absolute';
    76         clock_box.className = 'clockbox module';
    77         clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
    78         document.body.appendChild(clock_box);
    79         addEvent(clock_box, 'click', DateTimeShortcuts.cancelEventPropagation);
    80 
    81         quickElement('h2', clock_box, gettext('Choose a time'));
    82         time_list = quickElement('ul', clock_box, '');
    83         time_list.className = 'timelist';
    84         time_format = get_format('TIME_INPUT_FORMATS')[0];
    85         quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().strftime('" + time_format + "'));");
    86         quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,0,0,0,0).strftime('" + time_format + "'));");
    87         quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,6,0,0,0).strftime('" + time_format + "'));");
    88         quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,12,0,0,0).strftime('" + time_format + "'));");
    89 
    90         cancel_p = quickElement('p', clock_box, '');
    91         cancel_p.className = 'calendar-cancel';
    92         quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
    93     },
    94     openClock: function(num) {
    95         var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
    96         var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
    97 
    98         // Recalculate the clockbox position
    99         // is it left-to-right or right-to-left layout ?
    100         if (getStyle(document.body,'direction')!='rtl') {
    101             clock_box.style.left = findPosX(clock_link) + 17 + 'px';
    102         }
    103         else {
    104             // since style's width is in em, it'd be tough to calculate
    105             // px value of it. let's use an estimated px for now
    106             // TODO: IE returns wrong value for findPosX when in rtl mode
    107             //       (it returns as it was left aligned), needs to be fixed.
    108             clock_box.style.left = findPosX(clock_link) - 110 + 'px';
    109         }
    110         clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + 'px';
    111 
    112         // Show the clock box
    113         clock_box.style.display = 'block';
    114         addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
    115     },
    116     dismissClock: function(num) {
    117        document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none';
    118        window.document.onclick = null;
    119     },
    120     handleClockQuicklink: function(num, val) {
    121        DateTimeShortcuts.clockInputs[num].value = val;
    122        DateTimeShortcuts.clockInputs[num].focus();
    123        DateTimeShortcuts.dismissClock(num);
    124     },
    125     // Add calendar widget to a given field.
    126     addCalendar: function(inp) {
    127         var num = DateTimeShortcuts.calendars.length;
    128 
    129         DateTimeShortcuts.calendarInputs[num] = inp;
    130 
    131         // Shortcut links (calendar icon and "Today" link)
    132         var shortcuts_span = document.createElement('span');
    133         shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
    134         inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
    135         var today_link = document.createElement('a');
    136         today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
    137         today_link.appendChild(document.createTextNode(gettext('Today')));
    138         var cal_link = document.createElement('a');
    139         cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
    140         cal_link.id = DateTimeShortcuts.calendarLinkName + num;
    141         quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar'));
    142         shortcuts_span.appendChild(document.createTextNode('\240'));
    143         shortcuts_span.appendChild(today_link);
    144         shortcuts_span.appendChild(document.createTextNode('\240|\240'));
    145         shortcuts_span.appendChild(cal_link);
    146 
    147         // Create calendarbox div.
    148         //
    149         // Markup looks like:
    150         //
    151         // <div id="calendarbox3" class="calendarbox module">
    152         //     <h2>
    153         //           <a href="#" class="link-previous">&lsaquo;</a>
    154         //           <a href="#" class="link-next">&rsaquo;</a> February 2003
    155         //     </h2>
    156         //     <div class="calendar" id="calendarin3">
    157         //         <!-- (cal) -->
    158         //     </div>
    159         //     <div class="calendar-shortcuts">
    160         //          <a href="#">Yesterday</a> | <a href="#">Today</a> | <a href="#">Tomorrow</a>
    161         //     </div>
    162         //     <p class="calendar-cancel"><a href="#">Cancel</a></p>
    163         // </div>
    164         var cal_box = document.createElement('div');
    165         cal_box.style.display = 'none';
    166         cal_box.style.position = 'absolute';
    167         cal_box.className = 'calendarbox module';
    168         cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
    169         document.body.appendChild(cal_box);
    170         addEvent(cal_box, 'click', DateTimeShortcuts.cancelEventPropagation);
    171 
    172         // next-prev links
    173         var cal_nav = quickElement('div', cal_box, '');
    174         var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev('+num+');');
    175         cal_nav_prev.className = 'calendarnav-previous';
    176         var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
    177         cal_nav_next.className = 'calendarnav-next';
    178 
    179         // main box
    180         var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
    181         cal_main.className = 'calendar';
    182         DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
    183         DateTimeShortcuts.calendars[num].drawCurrent();
    184 
    185         // calendar shortcuts
    186         var shortcuts = quickElement('div', cal_box, '');
    187         shortcuts.className = 'calendar-shortcuts';
    188         quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);');
    189         shortcuts.appendChild(document.createTextNode('\240|\240'));
    190         quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
    191         shortcuts.appendChild(document.createTextNode('\240|\240'));
    192         quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);');
    193 
    194         // cancel bar
    195         var cancel_p = quickElement('p', cal_box, '');
    196         cancel_p.className = 'calendar-cancel';
    197         quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
    198     },
    199     openCalendar: function(num) {
    200         var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
    201         var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
    202         var inp = DateTimeShortcuts.calendarInputs[num];
    203 
    204         // Determine if the current value in the input has a valid date.
    205         // If so, draw the calendar with that date's year and month.
    206         if (inp.value) {
    207             var date_parts = inp.value.split('-');
    208             var year = date_parts[0];
    209             var month = parseFloat(date_parts[1]);
    210             if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) {
    211                 DateTimeShortcuts.calendars[num].drawDate(month, year);
    212             }
    213         }
    214 
    215         // Recalculate the clockbox position
    216         // is it left-to-right or right-to-left layout ?
    217         if (getStyle(document.body,'direction')!='rtl') {
    218             cal_box.style.left = findPosX(cal_link) + 17 + 'px';
    219         }
    220         else {
    221             // since style's width is in em, it'd be tough to calculate
    222             // px value of it. let's use an estimated px for now
    223             // TODO: IE returns wrong value for findPosX when in rtl mode
    224             //       (it returns as it was left aligned), needs to be fixed.
    225             cal_box.style.left = findPosX(cal_link) - 180 + 'px';
    226         }
    227         cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + 'px';
    228 
    229         cal_box.style.display = 'block';
    230         addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
    231     },
    232     dismissCalendar: function(num) {
    233         document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'none';
    234         window.document.onclick = null;
    235     },
    236     drawPrev: function(num) {
    237         DateTimeShortcuts.calendars[num].drawPreviousMonth();
    238     },
    239     drawNext: function(num) {
    240         DateTimeShortcuts.calendars[num].drawNextMonth();
    241     },
    242     handleCalendarCallback: function(num) {
    243         format = get_format('DATE_INPUT_FORMATS')[0];
    244         // the format needs to be escaped a little
    245         format = format.replace('\\', '\\\\');
    246         format = format.replace('\r', '\\r');
    247         format = format.replace('\n', '\\n');
    248         format = format.replace('\t', '\\t');
    249         format = format.replace("'", "\\'");
    250         return ["function(y, m, d) { DateTimeShortcuts.calendarInputs[",
    251                num,
    252                "].value = new Date(y, m-1, d).strftime('",
    253                format,
    254                "');DateTimeShortcuts.calendarInputs[",
    255                num,
    256                "].focus();document.getElementById(DateTimeShortcuts.calendarDivName1+",
    257                num,
    258                ").style.display='none';}"].join('');
    259     },
    260     handleCalendarQuickLink: function(num, offset) {
    261        var d = new Date();
    262        d.setDate(d.getDate() + offset)
    263        DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]);
    264        DateTimeShortcuts.calendarInputs[num].focus();
    265        DateTimeShortcuts.dismissCalendar(num);
    266     },
    267     cancelEventPropagation: function(e) {
    268         if (!e) e = window.event;
    269         e.cancelBubble = true;
    270         if (e.stopPropagation) e.stopPropagation();
    271     }
    272 }
    273 
    274 addEvent(window, 'load', DateTimeShortcuts.init);
  • django/contrib/admin/media/js/datetimeshortcuts.min.js

     
     1(function(c){c.fn.datetimeshortcuts=function(t){var u=c("body").data("datetimeshortcuts_defaults"),b=c.extend({admin_media_prefix:c("body").data("admin_media_prefix")},c.fn.datetimeshortcuts.defaults,u,t);if(b.admin_media_prefix==void 0)b.admin_media_prefix="/missing-admin-media-prefix/";var v=gettext("January February March April May June July August September October November December").split(" "),w=gettext("S M T W T F S").split(" "),s=parseInt(get_format("FIRST_DAY_OF_WEEK")),q=function(b,a){var e,
     2h,g;b!=null&&(e=b.getFullYear(),h=b.getMonth()+1,g=b.getDate());for(var i=a.getFullYear(),f=a.getMonth()+1,j=new Date,k=j.getFullYear(),m=j.getMonth()+1,j=j.getDate(),r=c("<table><caption>"+v[f-1]+" "+i+"</caption></table>"),n=c("<tr>").appendTo(r),l=0;l<7;l++)n.append("<th>"+w[(l+s)%7]+"</th>");for(var o=(new Date(i,f-1,1-s)).getDay(),q=32-(new Date(i,f-1,32)).getDate(),n=c("<tr>").appendTo(r),l=0;l<o;l++)c("<td> </td>").appendTo(n).addClass("nonday");for(var p=1,l=o;p<=q;l++)l%7==0&&p!=1&&(n=c("<tr>").appendTo(r)),
     3o="",p==j&&f==m&&i==k&&(o="today"),p==g&&f==h&&i==e&&(o="selected"),c("<td>").appendTo(n).addClass(o).append('<a href="#">'+p+"</a>").find("a").data("date",new Date(i,f-1,p++));for(;n.children("td").length<7;)c("<td> </td>").appendTo(n).addClass("nonday");return r},x=function(d){d.find("."+b.class_calendarbox).length==0&&(c('<div class="'+b.class_calendarbox+' module">  <div>    <a href="#" class="calendarnav-previous"><</a>    <a href="#" class="calendarnav-next">></a>  </div>  <div class="calendar_table calendar"></div>  <div class="calendar-shortcuts">    <a href="#" class="'+
     4b.class_today+' yesterday">'+gettext("Yesterday")+'</a> |\u00a0<a href="#" class="'+b.class_today+'">'+gettext("Today")+'</a> |\u00a0<a href="#" class="'+b.class_today+' tomorrow">'+gettext("Tomorrow")+'</a>  </div>  <p class="calendar-cancel"><a href="#">'+gettext("Cancel")+"</p></div>").appendTo(d).css("position","absolute").hide(),d.find("."+b.class_calendarbox).delegate(".calendarnav-previous, .calendarnav-next","click",function(a){var e=c(this).is(".calendarnav-next")?"calendar_next":"calendar_previous";
     5c(this).parents("."+b.class_calendarbox).trigger(e);a.preventDefault();a.stopPropagation()}).delegate("td a","click",function(a){d.trigger("callback_calendar",c(a.target).data("date"));a.preventDefault();a.stopPropagation()}).find(".calendar-cancel").click(function(a){d.trigger("hide_calendar");a.preventDefault();a.stopPropagation()}))},y=function(d){if(d.find("."+b.class_clockbox).length==0){var a=c('<div class="'+b.class_clockbox+' module">  <h2>'+gettext("Choose a time")+'</h2>  <ul class="timelist"></ul>  <p class="clock-cancel"><a href="#">'+
     6gettext("Cancel")+"</p></div>").appendTo(d).css("position","absolute").hide().find(".timelist");a.append('<li><a href="#">'+gettext("Now")+"</a></li>").find("a:last").data("time",new Date);a.append('<li><a href="#">'+gettext("Midnight")+"</a></li>").find("a:last").data("time",new Date(1970,1,1,0,0));a.append('<li><a href="#">'+gettext("6 a.m.")+"</a></li>").find("a:last").data("time",new Date(1970,1,1,6,0));a.append('<li><a href="#">'+gettext("Noon")+"</a></li>").find("a:last").data("time",new Date(1970,
     71,1,12,0));d.find("."+b.class_clockbox).delegate("li a","click",function(a){d.trigger("callback_clock",c(a.target).data("time"));a.preventDefault();a.stopPropagation()}).find(".clock-cancel").click(function(a){d.trigger("hide_clock");a.preventDefault();a.stopPropagation()})}};return this.each(function(){var d=c(this);d.bind("show_calendar",function(a){d.trigger("hide_clock");d.trigger("hide_calendar");var a=c(a.target),e=d.children("."+b.class_calendarbox),h=a.parents("."+b.class_shortcuts).prev(b.date_fields),
     8g=null,i=new Date;if(h.val().length>0){var f=null,j,k,m;b.date_input_format=="%Y-%m-%d"?(f=/^(\d{4})-(\d{2})-(\d{2})$/,j=1,k=2,m=3):b.date_input_format=="%m/%d/%Y"?(f=/^(\d{2})\/(\d{2})\/(\d{4})$/,j=3,k=1,m=2):b.date_input_format=="%m/%d/%y"?(f=/^(\d{2})\/(\d{2})\/(\d{2})$/,j=3,k=1,m=2):b.date_input_format=="%d.%m.%Y"?(f=/^(\d{2})\.(\d{2})\.(\d{4})$/,j=3,k=2,m=1):b.date_input_format=="%d.%m.%y"&&(f=/^(\d{2})\.(\d{2})\.(\d{2})$/,j=3,k=2,m=1);f!=null&&(f=f.exec(h.val()),f!=null&&(year=f[j],month=f[k],
     9day=f[m],j.length==2&&(year="20"+year),g=new Date(year,month-1,day),i=new Date(year,month-1,day)))}e.data("calendar_date_field",h).data("calendar_date_show",i).data("calendar_date_sel",g).find(".calendar_table").empty().append(q(g,i)).end().show();j=a.position();k=c("body").attr("direction");k!="rtl"&&e.css("left",j.left+a.width()+"px");(k=="rtl"||e.offset().left+e.width()>c(window).width())&&e.css("left",j.left-e.width()+"px");e.css("top",Math.max(0,j.top-e.height()/2)+"px");c("body").bind("click.datetimeshortcuts",
     10function(){d.trigger("hide_calendar")})}).bind("calendar_next",function(a){var a=c(a.target),b=a.find(".calendar_table").empty(),d=a.data("calendar_date_sel"),g=a.data("calendar_date_show"),i=g.getMonth(),f=g.getFullYear();i==11?(i=0,f++):i++;g.setFullYear(f,i);a.data("calendar_date_show",g);b.append(q(d,g))}).bind("calendar_previous",function(a){var a=c(a.target),b=a.find(".calendar_table").empty(),d=a.data("calendar_date_sel"),g=a.data("calendar_date_show"),i=g.getMonth(),f=g.getFullYear();i==0?
     11(i=11,f--):i--;g.setFullYear(f,i);a.data("calendar_date_show",g);b.append(q(d,g))}).bind("hide_calendar",function(a){c(a.target).children("."+b.class_calendarbox).removeData("calendar_date_field").removeData("calendar_date_sel").removeData("calendar_date_show").hide();c("document").unbind(".datetimeshortcuts")}).bind("show_clock",function(a){d.trigger("hide_clock");d.trigger("hide_calendar");var a=c(a.target),e=d.children("."+b.class_clockbox),h=a.parents("."+b.class_shortcuts).prev(b.time_fields);
     12e.data("clock_time_field",h).show();var h=a.position(),g=c("body").attr("direction");g!="rtl"&&e.css("left",h.left+a.width()+"px");(g=="rtl"||e.offset().left+e.width()>c(window).width())&&e.css("left",h.left-e.width()+"px");e.css("top",Math.max(0,h.top-e.height()/2)+"px");c("body").bind("click.datetimeshortcuts",function(){d.trigger("hide_clock")})}).bind("hide_clock",function(a){c(a.target).children("."+b.class_clockbox).removeData("clock_time_field").hide();c("document").unbind(".datetimeshortcuts")}).bind("callback_calendar",
     13function(a,e){c(a.target).find("."+b.class_calendarbox).data("calendar_date_field").val(e.strftime(b.date_input_format)).focus();d.trigger("hide_calendar")}).bind("callback_today",function(a,d){var h=new Date;h.setDate(h.getDate()+d);c(a.target).val(h.strftime(b.date_input_format)).focus()}).bind("callback_clock",function(a,e){c(a.target).find("."+b.class_clockbox).data("clock_time_field").val(e.strftime(b.time_input_format)).focus();d.trigger("hide_clock")}).bind("callback_now",function(a){var d=
     14new Date;c(a.target).val(d.strftime(b.time_input_format)).focus()});d.find(b.date_fields).each(function(){var a=c(this),a=c('<span class="'+b.class_shortcuts+'">').insertAfter(a);b.enable_today&&(a.append(' <a href="#" class="'+b.class_today+'">'+gettext("Today")+"</a>"),b.enable_calendar&&a.append(" | "));b.enable_calendar&&c('<a href="#" class="'+b.class_calendar+'"></a>').appendTo(a).append('<img src="'+b.admin_media_prefix+'img/admin/icon_calendar.gif" alt="'+gettext("Calendar")+'" />')});d.find(b.time_fields).each(function(){var a=
     15c(this),a=c('<span class="'+b.class_shortcuts+'">').insertAfter(a);b.enable_now&&(a.append(' <a href="#" class="'+b.class_now+'">'+gettext("Now")+"</a>"),b.enable_clock&&a.append(" | "));b.enable_clock&&c('<a href="#" class="'+b.class_clock+'"></a>').appendTo(a).append('<img src="'+b.admin_media_prefix+'img/admin/icon_clock.gif" alt="'+gettext("Clock")+'" />')});x(d);y(d);d.delegate("."+b.class_shortcuts+" ."+b.class_calendar,"click",function(a){c(a.target).trigger("show_calendar");a.preventDefault();
     16a.stopPropagation()}).delegate("."+b.class_shortcuts+" ."+b.class_today,"click",function(a){c(a.target).parents("."+b.class_shortcuts).prev(b.date_fields).trigger("callback_today",0);d.trigger("hide_calendar");a.preventDefault();a.stopPropagation()}).delegate("."+b.class_calendarbox+" ."+b.class_today,"click",function(a){var e=c(a.target),h=0;e.is(".yesterday")?h=-1:e.is(".tomorrow")&&(h=1);e.parents("."+b.class_calendarbox).data("calendar_date_field").trigger("callback_today",h).focus();d.trigger("hide_calendar");
     17a.preventDefault();a.stopPropagation()}).delegate("."+b.class_shortcuts+" ."+b.class_clock,"click",function(a){c(a.target).trigger("show_clock");a.preventDefault();a.stopPropagation()}).delegate("."+b.class_shortcuts+" ."+b.class_now,"click",function(a){c(a.target).parents("."+b.class_shortcuts).prev(b.time_fields).trigger("callback_now");d.trigger("hide_clock");a.preventDefault();a.stopPropagation()})})};c.fn.datetimeshortcuts.defaults={class_shortcuts:"datetimeshortcuts",class_today:"today",class_calendar:"calendar",
     18class_now:"now",class_clock:"clock",class_calendarbox:"calendarbox",class_clockbox:"clockbox",date_input_format:get_format("DATE_INPUT_FORMATS")[0],time_input_format:get_format("TIME_INPUT_FORMATS")[0],date_fields:"input:text.vDateField",time_fields:"input:text.vTimeField",enable_calendar:!0,enable_today:!0,enable_clock:!0,enable_now:!0};c(document).ready(function(){c("fieldset.module").datetimeshortcuts()})})(django.jQuery);
  • django/contrib/admin/widgets.py

     
    4545
    4646class AdminDateWidget(forms.DateInput):
    4747    class Media:
    48         js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
    49               settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js")
     48        js = (settings.ADMIN_MEDIA_PREFIX + "js/datetimeshortcuts.min.js",)
    5049
    5150    def __init__(self, attrs={}, format=None):
    5251        super(AdminDateWidget, self).__init__(attrs={'class': 'vDateField', 'size': '10'}, format=format)
    5352
    5453class AdminTimeWidget(forms.TimeInput):
    5554    class Media:
    56         js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
    57               settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js")
     55        js = (settings.ADMIN_MEDIA_PREFIX + "js/datetimeshortcuts.min.js",)
    5856
    5957    def __init__(self, attrs={}, format=None):
    6058        super(AdminTimeWidget, self).__init__(attrs={'class': 'vTimeField', 'size': '8'}, format=format)
  • django/contrib/admin/templates/admin/edit_inline/stacked.html

     
    2828                $(this).html($(this).html().replace(/(#\d+)/g, "#" + count));
    2929            });
    3030        }
    31         var reinitDateTimeShortCuts = function() {
    32             // Reinitialize the calendar and clock widgets by force, yuck.
    33             if (typeof DateTimeShortcuts != "undefined") {
    34                 $(".datetimeshortcuts").remove();
    35                 DateTimeShortcuts.init();
    36             }
    37         }
    3831        var updateSelectFilter = function() {
    3932            // If any SelectFilter widgets were added, instantiate a new instance.
    4033            if (typeof SelectFilter != "undefined"){
     
    7265            removed: updateInlineLabel,
    7366            added: (function(row) {
    7467                initPrepopulatedFields(row);
    75                 reinitDateTimeShortCuts();
    7668                updateSelectFilter();
    7769                updateInlineLabel(row);
    7870            })
  • django/contrib/admin/templates/admin/edit_inline/tabular.html

     
    7373                .filter(":even").addClass("row1").end()
    7474                .filter(rows + ":odd").addClass("row2");
    7575        }
    76         var reinitDateTimeShortCuts = function() {
    77             // Reinitialize the calendar and clock widgets by force
    78             if (typeof DateTimeShortcuts != "undefined") {
    79                 $(".datetimeshortcuts").remove();
    80                 DateTimeShortcuts.init();
    81             }
    82         }
    8376        var updateSelectFilter = function() {
    8477            // If any SelectFilter widgets are a part of the new form,
    8578            // instantiate a new SelectFilter instance for it.
     
    118111            removed: alternatingRows,
    119112            added: (function(row) {
    120113                initPrepopulatedFields(row);
    121                 reinitDateTimeShortCuts();
    122114                updateSelectFilter();
    123115                alternatingRows(row);
    124116            })
  • django/contrib/admin/templates/admin/base.html

     
    66{% block extrastyle %}{% endblock %}
    77<!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="{% block stylesheet_ie %}{% load adminmedia %}{% admin_media_prefix %}css/ie.css{% endblock %}" /><![endif]-->
    88{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %}
    9 <script type="text/javascript">window.__admin_media_prefix__ = "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}";</script>
    109{% block extrahead %}{% endblock %}
    1110{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
    1211</head>
     
    1413
    1514<body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}">
    1615
     16<script type="text/javascript">
     17    if (typeof(django) != "undefined" && typeof(django.jQuery) != "undefined") {
     18        (function($) {
     19            $('body').data('admin_media_prefix', "{% filter escapejs %}{% admin_media_prefix %}{% endfilter %}");
     20            {# TODO: templatetag admin_datetimeshortcuts (?) to render the following from django.conf.settings #}
     21            $('body').data('datetimeshortcuts_defaults', {
     22                enable_calendar: true,
     23                enable_today: true,
     24                enable_clock: true,
     25                enable_now: true
     26            });
     27        })(django.jQuery);
     28    }
     29</script>
     30
    1731<!-- Container -->
    1832<div id="container">
    1933
Back to Top