(function( $ ){
var monthNames = [ "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь",
"Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь" ];
var dayNames = ["Пн","Вт","Ср","Чт","Пт","Сб","Вс"];
var now = new Date();
var methods = {
init : function( options ) {
var settings = $.extend( {
'year' : now.getFullYear(),
'month' : now.getMonth(),
'link' : '%y/%m/%d',
'url' : '',
'dates' : []
}, options);
return this.each(function(){
if (!$(this).data('year')){
$(this).data('year',settings.year);
}
if (!$(this).data('month')){
$(this).data('month',settings.month);
}
if (!$(this).data('link')){
$(this).data('link',settings.link);
}
$(this).data('dates',settings.dates);
$(this).data('url',settings.url);
methods.render($(this));
});
},
destroy : function( ) {
return this.each(function(){
$(this).html('');
})
},
render : function( elem ) {
year = elem.data('year');
month = elem.data('month');
link = elem.data('link');
dates = elem.data('dates');
date = new Date(year,month,1);
elem.html('<table class="calendar"></table>');
var calendar=elem.find('.calendar');
calendar.append('<tr class="calendar-header"><th colspan="7"><a href="#" class="icon-chevron-left calendar-prev-month"></a>'+monthNames[month]+' '+year+'<a href="#" class="icon-chevron-right calendar-next-month"></a></th></tr>');
calendar.append('<tr class="calendar-week"><th>'+dayNames.join('</th><th>')+'</th></tr>');
var str = '<tr>';
var week = date.getDay();
if (week == 0) { week=7}
for (day=1;day<week;day++){
str=str+"<td></td>";
}
date.setMonth(month+1);
date.setDate(0);
for (day=1;day<=date.getDate();day++){
var link_href = link.replace("%y",year).replace("%m",month+1).replace("%d",day);
var day_text = '';
if ($.inArray(day, dates)>=0){
day_text = '<a href="'+link_href+'" class="calendar-day-link">'+day+'</a>';
} else {
day_text = day;
}
str=str+'<td>'+day_text+'</td>';
if (week++ % 7 == 0){
str=str+"</tr></tr>";
}
}
str = str + '</tr>';
calendar.append(str);
calendar.find('.calendar-next-month').click(methods.next_month);
calendar.find('.calendar-prev-month').click(methods.prev_month);
},
next_month : function( e ) {
e.preventDefault();
elem = $(this).parents('.calendar').parent();
year = elem.data('year');
month = elem.data('month')+1;
url = elem.data('url');
if (month>11){
year++;
month=0;
}
elem.data('year',year).data('month',month);
$.getJSON(url+'?year='+year+'&month='+(month+1),function(data) {
elem.data('dates',data);
methods.render(elem);
});
},
prev_month : function( e ) {
e.preventDefault();
elem = $(this).parents('.calendar').parent();
year = elem.data('year');
month = elem.data('month')-1;
url = elem.data('url');
if (month==-1){
year--;
month=11;
}
elem.data('year',year).data('month',month);
$.getJSON(url+'?year='+year+'&month='+(month+1),function(data) {
elem.data('dates',data);
methods.render(elem);
});
},
};
$.fn.calendar = function( method ) {
// Create some defaults, extending them with any options that were provided
if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
}
};
})( jQuery );
1 Answer
From a once over:
- THANK YOU for having all your code and variables in English, very nice
In init I would suggest you extract
data
, fill it in if needed and put it back, so going from thisreturn this.each(function(){ if (!$(this).data('year')){ $(this).data('year',settings.year); } if (!$(this).data('month')){ $(this).data('month',settings.month); } if (!$(this).data('link')){ $(this).data('link',settings.link); } $(this).data('dates',settings.dates); $(this).data('url',settings.url); methods.render($(this)); });
to this:
return this.each(function(){ var data = $(this).data() || {}; data.year = data.year || settings.year; data.month = data.month || settings.month; data.link = data.link || settings.link; data.dates = settings.dates; data.url = settings.url; $(this).data(data); methods.render($(this)); });
It looks DRY'er and the reduced amount of calls to
$(this).data()
should make it more efficient as well.- You could do the same with
year
andmonth
innext_month
andprev_month
. - lowerCamelCasing is how JavaScript ought to be done:
next_month
->nextMonth
,prev_month
->previousMonth
etc. - You should really look into a templating routine/library for building your HTML, extracting your HTML templates into
var
s and making it more readable by splitting over multiple lines. You could even use templating to construct the JSON URL's. - From JsHint ( jshint.com )
year
,month
,link
,dates
etc. are declared in your code withoutvar
, polluting the global namespace- If you want to compare with
0
, you should use===
not==