Вход Регистрация
Файл: contao-3.5.8/assets/mootools/datepicker/2.2.0/src/Picker.Date.js
Строк: 985
<?php
/*
---
name: Picker.Date
description: Creates a DatePicker, can be used for picking years/months/days and time, or all of them
authors: Arian Stolwijk
requires: [Picker, Picker.Attach, Locale.en-US.DatePicker, More/Locale, More/Date]
provides: Picker.Date
...
*/


(function(){

this.DatePicker = Picker.Date = new Class({

    Extends: 
Picker.Attach,

    
options: {/*
        onSelect: function(date){},

        minDate: new Date('3/4/2010'), // Date object or a string
        maxDate: new Date('3/4/2011'), // same as minDate
        availableDates: {}, //
        invertAvailable: false,

        format: null,*/

        
timePicker: false,
        
timePickerOnly: false, // deprecated, use onlyView = 'time'
        
timeWheelStep: 1, // 10,15,20,30

        
yearPicker: true,
        
yearsPerPage: 20,

        
startDay: 1, // Sunday (0) through Saturday (6) - be aware that this may affect your layout, since the days on the right might have a different margin
        
rtl: false,

        
startView: 'days', // allowed values: {time, days, months, years}
        
openLastView: false,
        
pickOnly: false, // 'years', 'months', 'days', 'time'
        
canAlwaysGoUp: ['months', 'days'],
        
updateAll : false, //whether or not to update all inputs when selecting a date

        
weeknumbers: false,
        
titleFormat: '%d %B, %Y', // PATCH

        // if you like to use your own translations
        
months_abbr: null,
        
days_abbr: null,
        
years_title: function(date, options){
            var 
year = date.get('year');
            return 
year + '-' + (year + options.yearsPerPage - 1);
        },
        
months_title: function(date, options){
            return 
date.get('year');
        },
        
days_title: function(date, options){
            return 
date.format('%b %Y');
        },
        
time_title: function(date, options){
            return (
options.pickOnly == 'time') ? Locale.get('DatePicker.select_a_time') : date.format(options.titleFormat); /* PATCH */
        
}
    },

    
initialize: function(attachTo, options){
        
this.parent(attachTo, options);

        
this.setOptions(options);
        
options = this.options;

        
// If we only want to use one picker / backwards compatibility
        
['year', 'month', 'day', 'time'].some(function(what){
            if (
options[what + 'PickerOnly']){
                
options.pickOnly = what;
                return 
true;
            }
            return 
false;
        });
        if (
options.pickOnly){
            
options[options.pickOnly + 'Picker'] = true;
            
options.startView = options.pickOnly;
        }

        
// backward compatibility for startView
        
var newViews = ['days', 'months', 'years'];
        [
'month', 'year', 'decades'].some(function(what, i){
            return (
options.startView == what) && (options.startView = newViews[i]);
        });

        
options.canAlwaysGoUp = options.canAlwaysGoUp ? Array.from(options.canAlwaysGoUp) : [];

        
// Set the min and max dates as Date objects
        
if (options.minDate){
            if (!(
options.minDate instanceof Date)) options.minDate = Date.parse(options.minDate);
            
options.minDate.clearTime();
        }
        if (
options.maxDate){
            if (!(
options.maxDate instanceof Date)) options.maxDate = Date.parse(options.maxDate);
            
options.maxDate.clearTime();
        }

        if (!
options.format){
            
options.format = (options.pickOnly != 'time') ? Locale.get('Date.shortDate') : '';
            if (
options.timePicker) options.format = (options.format) + (options.format ? ' ' : '') + Locale.get('Date.shortTime');
        }

        
// Some link or input has fired an event!
        
this.addEvent('attached', function(event, element){

            
// This is where we store the selected date
            
if (!this.currentView || !options.openLastView) this.currentView = options.startView;

            
this.date = limitDate(new Date(), options.minDate, options.maxDate);
            var 
tag = element.get('tag'), input;
            if (
tag == 'input') input = element;
            else {
                var 
index = this.toggles.indexOf(element);
                if (
this.inputs[index]) input = this.inputs[index];
            }
            
this.getInputDate(input);
            
this.input = input;
            
this.setColumns(this.originalColumns);
        }.
bind(this), true);

    },

    
getInputDate: function(input){
        
this.date = new Date();
        if (!
input) return;
        var 
date = Date.parse(input.get('value'));
        if (
date == null || !date.isValid()){
            var 
storeDate = input.retrieve('datepicker:value');
            if (
storeDate) date = Date.parse(storeDate);
        }
        if (
date != null && date.isValid()) this.date = date;
    },

    
// Control the previous and next elements

    
constructPicker: function(){
        
this.parent();

        if (!
this.options.rtl){
            
this.previous = new Element('div.previous[html=&#171;]').inject(this.header);
            
this.next = new Element('div.next[html=&#187;]').inject(this.header);
        } else {
            
this.next = new Element('div.previous[html=&#171;]').inject(this.header);
            
this.previous = new Element('div.next[html=&#187;]').inject(this.header);
        }
    },

    
hidePrevious: function(_next, _show){
        
this[_next ? 'next' : 'previous'].setStyle('display', _show ? 'block' : 'none');
        return 
this;
    },

    
showPrevious: function(_next){
        return 
this.hidePrevious(_next, true);
    },

    
setPreviousEvent: function(fn, _next){
        
this[_next ? 'next' : 'previous'].removeEvents('click');
        if (
fn) this[_next ? 'next' : 'previous'].addEvent('click', fn);
        return 
this;
    },

    
hideNext: function(){
        return 
this.hidePrevious(true);
    },

    
showNext: function(){
        return 
this.showPrevious(true);
    },

    
setNextEvent: function(fn){
        return 
this.setPreviousEvent(fn, true);
    },

    
setColumns: function(columns, view, date, viewFx){
        var 
ret = this.parent(columns), method;

        if ((
view || this.currentView)
            && (
method = 'render' + (view || this.currentView).capitalize())
            && 
this[method]
        ) 
this[method](date || this.date.clone(), viewFx);

        return 
ret;
    },

    
// Render the Pickers

    
renderYears: function(date, fx){
        var 
options = this.options, pages = options.columns, perPage = options.yearsPerPage,
            
_columns = [], _dates = [];
        
this.dateElements = [];

        
// start neatly at interval (eg. 1980 instead of 1987)
        
date = date.clone().decrement('year', date.get('year') % perPage);

        var 
iterateDate = date.clone().decrement('year', Math.floor((pages - 1) / 2) * perPage);

        for (var 
i = pages; i--;){
            var 
_date = iterateDate.clone();
            
_dates.push(_date);
            
_columns.push(renderers.years(
                
timesSelectors.years(options, _date.clone()),
                
options,
                
this.date.clone(),
                
this.dateElements,
                function(
date){
                    if (
options.pickOnly == 'years') this.select(date);
                    else 
this.renderMonths(date, 'fade');
                    
this.date = date;
                }.
bind(this)
            ));
            
iterateDate.increment('year', perPage);
        }

        
this.setColumnsContent(_columns, fx);
        
this.setTitle(_dates, options.years_title);

        
// Set limits
        
var limitLeft = (options.minDate && date.get('year') <= options.minDate.get('year')),
            
limitRight = (options.maxDate && (date.get('year') + options.yearsPerPage) >= options.maxDate.get('year'));
        
this[(limitLeft ? 'hide' : 'show') + 'Previous']();
        
this[(limitRight ? 'hide' : 'show') + 'Next']();

        
this.setPreviousEvent(function(){
            
this.renderYears(date.decrement('year', perPage), 'left');
        }.
bind(this));

        
this.setNextEvent(function(){
            
this.renderYears(date.increment('year', perPage), 'right');
        }.
bind(this));

        
// We can't go up!
        
this.setTitleEvent(null);

        
this.currentView = 'years';
    },

    
renderMonths: function(date, fx){
        var 
options = this.options, years = options.columns, _columns = [], _dates = [],
            
iterateDate = date.clone().decrement('year', Math.floor((years - 1) / 2));
        
this.dateElements = [];

        for (var 
i = years; i--;){
            var 
_date = iterateDate.clone();
            
_dates.push(_date);
            
_columns.push(renderers.months(
                
timesSelectors.months(options, _date.clone()),
                
options,
                
this.date.clone(),
                
this.dateElements,
                function(
date){
                    if (
options.pickOnly == 'months') this.select(date);
                    else 
this.renderDays(date, 'fade');
                    
this.date = date;
                }.
bind(this)
            ));
            
iterateDate.increment('year', 1);
        }

        
this.setColumnsContent(_columns, fx);
        
this.setTitle(_dates, options.months_title);

        
// Set limits
        
var year = date.get('year'),
            
limitLeft = (options.minDate && year <= options.minDate.get('year')),
            
limitRight = (options.maxDate && year >= options.maxDate.get('year'));
        
this[(limitLeft ? 'hide' : 'show') + 'Previous']();
        
this[(limitRight ? 'hide' : 'show') + 'Next']();

        
this.setPreviousEvent(function(){
            
this.renderMonths(date.decrement('year', years), 'left');
        }.
bind(this));

        
this.setNextEvent(function(){
            
this.renderMonths(date.increment('year', years), 'right');
        }.
bind(this));

        var 
canGoUp = options.yearPicker && (options.pickOnly != 'months' || options.canAlwaysGoUp.contains('months'));
        var 
titleEvent = (canGoUp) ? function(){
            
this.renderYears(date, 'fade');
        }.
bind(this) : null;
        
this.setTitleEvent(titleEvent);

        
this.currentView = 'months';
    },

    
renderDays: function(date, fx){
        var 
options = this.options, months = options.columns, _columns = [], _dates = [],
            
iterateDate = date.clone().decrement('month', Math.floor((months - 1) / 2));
        
this.dateElements = [];

        for (var 
i = months; i--;){
            
_date = iterateDate.clone();
            
_dates.push(_date);
            
_columns.push(renderers.days(
                
timesSelectors.days(options, _date.clone()),
                
options,
                
this.date.clone(),
                
this.dateElements,
                function(
date){
                    if (
options.pickOnly == 'days' || !options.timePicker) this.select(date)
                    else 
this.renderTime(date, 'fade');
                    
this.date = date;
                }.
bind(this)
            ));
            
iterateDate.increment('month', 1);
        }

        
this.setColumnsContent(_columns, fx);
        
this.setTitle(_dates, options.days_title);

        var 
yearmonth = date.format('%Y%m').toInt(),
            
limitLeft = (options.minDate && yearmonth <= options.minDate.format('%Y%m')),
            
limitRight = (options.maxDate && yearmonth >= options.maxDate.format('%Y%m'));
        
this[(limitLeft ? 'hide' : 'show') + 'Previous']();
        
this[(limitRight ? 'hide' : 'show') + 'Next']();

        
this.setPreviousEvent(function(){
            
this.renderDays(date.decrement('month', months), 'left');
        }.
bind(this));

        
this.setNextEvent(function(){
            
this.renderDays(date.increment('month', months), 'right');
        }.
bind(this));

        var 
canGoUp = options.pickOnly != 'days' || options.canAlwaysGoUp.contains('days');
        var 
titleEvent = (canGoUp) ? function(){
            
this.renderMonths(date, 'fade');
        }.
bind(this) : null;
        
this.setTitleEvent(titleEvent);

        
this.currentView = 'days';
    },

    
renderTime: function(date, fx){
        var 
options = this.options;
        
this.setTitle(date, options.time_title);

        var 
originalColumns = this.originalColumns = options.columns;
        
this.currentView = null; // otherwise you'd get crazy recursion
        
if (originalColumns != 1) this.setColumns(1);

        
this.setContent(renderers.time(
            
options,
            
date.clone(),
            function(
date){
                
this.select(date);
            }.
bind(this)
        ), 
fx);

        
// Hide « and » buttons
        
this.hidePrevious()
            .
hideNext()
            .
setPreviousEvent(null)
            .
setNextEvent(null);

        var 
canGoUp = options.pickOnly != 'time' || options.canAlwaysGoUp.contains('time');
        var 
titleEvent = (canGoUp) ? function(){
            
this.setColumns(originalColumns, 'days', date, 'fade');
        }.
bind(this) : null;
        
this.setTitleEvent(titleEvent);

        
this.currentView = 'time';
    },

    
select: function(date, all){
        
this.date = date;
        var 
formatted = date.format(this.options.format),
            
time = date.strftime(),
            
inputs = (!this.options.updateAll && !all && this.input) ? [this.input] : this.inputs;

        
inputs.each(function(input){
            
input.set('value', formatted).store('datepicker:value', time).fireEvent('change');
        }, 
this);

        
this.fireEvent('select', [date].concat(inputs));
        
this.close();
        return 
this;
    }

});


// Renderers only output elements and calculate the limits!

var timesSelectors = {

    
years: function(options, date){
        var 
times = [];
        for (var 
i = 0; i < options.yearsPerPage; i++){
            
times.push(+date);
            
date.increment('year', 1);
        }
        return 
times;
    },

    
months: function(options, date){
        var 
times = [];
        
date.set('month', 0);
        for (var 
i = 0; i <= 11; i++){
            
times.push(+date);
            
date.increment('month', 1);
        }
        return 
times;
    },

    
days: function(options, date){
        var 
times = [];
        
date.set('date', 1);
        while (
date.get('day') != options.startDay) date.set('date', date.get('date') - 1);
        for (var 
i = 0; i < 42; i++){
            
times.push(+date);
            
date.increment('day',  1);
        }
        return 
times;
    }

};

var 
renderers = {

    
years: function(years, options, currentDate, dateElements, fn){
        var 
container = new Element('table.years'),
            
today     = new Date(),
            
rows      = [],
            
element, classes;

        
years.each(function(_year, i){
            var 
date = new Date(_year), year = date.get('year');
            if (
i % 4 === 0) {
                
rows.push(new Element('tr'));
                
rows[rows.length - 1].inject(container)
            }
            
classes = '.year.year' + i;
            if (
year == today.get('year')) classes += '.today';
            if (
year == currentDate.get('year')) classes += '.selected';
            
element = new Element('td' + classes, {text: year}).inject(rows[rows.length - 1]);

            
dateElements.push({element: element, time: _year});

            if (
isUnavailable('year', date, options)) element.addClass('unavailable');
            else 
element.addEvent('click', fn.pass(date));
        });

        return 
container;
    },

    
months: function(months, options, currentDate, dateElements, fn){
        var 
today        = new Date(),
            
month        = today.get('month'),
            
thisyear     = today.get('year'),
            
selectedyear = currentDate.get('year'),
            
container    = new Element('table.months'),
            
monthsAbbr   = options.months_abbr || Locale.get('Date.months_abbr'),
            
rows         = [],
            
element, classes;

        
months.each(function(_month, i){
            var 
date = new Date(_month), year = date.get('year');
            if (
i % 3 === 0) {
                
rows.push(new Element('tr'));
                
rows[rows.length - 1].inject(container)
            }

            
classes = '.month.month' + (i + 1);
            if (
i == month && year == thisyear) classes += '.today';
            if (
i == currentDate.get('month') && year == selectedyear) classes += '.selected';
            
element = new Element('td' + classes, {text: monthsAbbr[i]}).inject(rows[rows.length - 1]);
            
dateElements.push({element: element, time: _month});

            if (
isUnavailable('month', date, options)) element.addClass('unavailable');
            else 
element.addEvent('click', fn.pass(date));
        });

        return 
container;
    },

    
days: function(days, options, currentDate, dateElements, fn){
        var 
month = new Date(days[14]).get('month'),
            
todayString = new Date().toDateString(),
            
currentString = currentDate.toDateString(),
            
weeknumbers = options.weeknumbers,
            
container = new Element('table.days' + (weeknumbers ? '.weeknumbers' : ''), {
                
role: 'grid', 'aria-labelledby': this.titleID
            
}),
            
header = new Element('thead').inject(container),
            
body = new Element('tbody').inject(container),
            
titles = new Element('tr.titles').inject(header),
            
localeDaysShort = options.days_abbr || Locale.get('Date.days_abbr'),
            
day, classes, element, weekcontainer, dateString,
            
where = options.rtl ? 'top' : 'bottom';

        if (
weeknumbers) new Element('th.title.day.weeknumber', {
            
text: Locale.get('DatePicker.week')
        }).
inject(titles);

        for (
day = options.startDay; day < (options.startDay + 7); day++){
            new 
Element('th.title.day.day' + (day % 7), {
                
text: localeDaysShort[(day % 7)],
                
role: 'columnheader'
            
}).inject(titles, where);
        }

        
days.each(function(_date, i){
            var 
date = new Date(_date);

            if (
i % 7 == 0){
                
weekcontainer = new Element('tr.week.week' + (Math.floor(i / 7))).set('role', 'row').inject(body);
                if (
weeknumbers) new Element('th.day.weeknumber', {text: date.get('week'), scope: 'row', role: 'rowheader'}).inject(weekcontainer);
            }

            
dateString = date.toDateString();
            
classes = '.day.day' + date.get('day');
            if (
dateString == todayString) classes += '.today';
            if (
date.get('month') != month) classes += '.otherMonth';
            
element = new Element('td' + classes, {text: date.getDate(), role: 'gridcell'}).inject(weekcontainer, where);

            if (
dateString == currentString) element.addClass('selected').set('aria-selected', 'true');
            else 
element.set('aria-selected', 'false');

            
dateElements.push({element: element, time: _date});

            if (
isUnavailable('date', date, options)) element.addClass('unavailable');
            else 
element.addEvent('click', fn.pass(date.clone()));
        });

        return 
container;
    },

    
time: function(options, date, fn){
        var 
container = new Element('div.time'),
            
// make sure that the minutes are timeWheelStep * k
            
initMinutes = (date.get('minutes') / options.timeWheelStep).round() * options.timeWheelStep

        
if (initMinutes >= 60) initMinutes = 0;
        
date.set('minutes', initMinutes);

        var 
hoursInput = new Element('input.hour[type=text]', {
            
title: Locale.get('DatePicker.use_mouse_wheel'),
            
value: date.format('%H'),
            
events: {
                
click: function(event){
                    
event.target.focus();
                    
event.stop();
                },
                
mousewheel: function(event){
                    
event.stop();
                    
hoursInput.focus();
                    var 
value = hoursInput.get('value').toInt();
                    
value = (event.wheel > 0) ? ((value < 23) ? value + 1 : 0)
                        : ((
value > 0) ? value - 1 : 23)
                    
date.set('hours', value);
                    
hoursInput.set('value', date.format('%H'));
                }.
bind(this)
            },
            
maxlength: 2
        
}).inject(container);

        new 
Element('div.separator[text=:]').inject(container);

        var 
minutesInput = new Element('input.minutes[type=text]', {
            
title: Locale.get('DatePicker.use_mouse_wheel'),
            
value: date.format('%M'),
            
events: {
                
click: function(event){
                    
event.target.focus();
                    
event.stop();
                },
                
mousewheel: function(event){
                    
event.stop();
                    
minutesInput.focus();
                    var 
value = minutesInput.get('value').toInt();
                    
value = (event.wheel > 0) ? ((value < 59) ? (value + options.timeWheelStep) : 0)
                        : ((
value > 0) ? (value - options.timeWheelStep) : (60 - options.timeWheelStep));
                    if (
value >= 60) value = 0;
                    
date.set('minutes', value);
                    
minutesInput.set('value', date.format('%M'));
                }.
bind(this)
            },
            
maxlength: 2
        
}).inject(container);


        new 
Element('input.ok', {
            
'type': 'submit',
            
value: Locale.get('DatePicker.time_confirm_button'),
            
events: {click: function(event){
                
event.stop();
                
date.set({
                    
hours: hoursInput.get('value').toInt(),
                    
minutes: minutesInput.get('value').toInt()
                });
                
fn(date.clone());
            }}
        }).
inject(container);

        return 
container;
    }

};


Picker.Date.defineRenderer = function(name, fn){
    
renderers[name] = fn;
    return 
this;
};

Picker.Date.getRenderer = function(name) {
    return 
renderers[name];
}

var 
limitDate = function(date, min, max){
    if (
min && date < min) return min;
    if (
max && date > max) return max;
    return 
date;
};

var 
isUnavailable = function(type, date, options){
    var 
minDate = options.minDate,
        
maxDate = options.maxDate,
        
availableDates = options.availableDates,
        
year, month, day, ms;

    if (!
minDate && !maxDate && !availableDates) return false;
    
date.clearTime();

    if (
type == 'year'){
        
year = date.get('year');
        return (
            (
minDate && year < minDate.get('year')) ||
            (
maxDate && year > maxDate.get('year')) ||
            (
                (
availableDates != null &&  !options.invertAvailable) && (
                    
availableDates[year] == null ||
                    
Object.getLength(availableDates[year]) == 0 ||
                    
Object.getLength(
                        
Object.filter(availableDates[year], function(days){
                            return (
days.length > 0);
                        })
                    ) == 
0
                
)
            )
        );
    }

    if (
type == 'month'){
        
year = date.get('year');
        
month = date.get('month') + 1;
        
ms = date.format('%Y%m').toInt();
        return (
            (
minDate && ms < minDate.format('%Y%m').toInt()) ||
            (
maxDate && ms > maxDate.format('%Y%m').toInt()) ||
            (
                (
availableDates != null && !options.invertAvailable) && (
                    
availableDates[year] == null ||
                    
availableDates[year][month] == null ||
                    
availableDates[year][month].length == 0
                
)
            )
        );
    }

    
// type == 'date'
    
year = date.get('year');
    
month = date.get('month') + 1;
    
day = date.get('date');

    var 
dateAllow = (minDate && date < minDate) || (maxDate && date > maxDate);
    if (
availableDates != null){
        
dateAllow = dateAllow
            
|| availableDates[year] == null
            
|| availableDates[year][month] == null
            
|| !availableDates[year][month].contains(day);
        if (
options.invertAvailable) dateAllow = !dateAllow;
    }

    return 
dateAllow;
};

})();
?>
Онлайн: 2
Реклама