3
\$\begingroup\$
        (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 );
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

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 this

            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));
            });
    

    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 and month in next_month and prev_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 vars 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 without var, polluting the global namespace
    • If you want to compare with 0, you should use === not ==
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.