好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用avalon MVVM框架打造jquery ui的日历

使用avalon MVVM框架打造jquery ui的日历

使用avalon MVVM框架打造jquery ui的日历

我直接把jquery datepicker的结构抄过来,类名也照搬。于是一个换肤的日历就诞生了。

< div   ms-controller = "datepicker" >

 

     < div   id = "ui-datepicker-div"   class = "ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"   style = "display:block" >

         < div   class = "ui-datepicker-header ui-widget-header ui-helper-clearfix ui-corner-all" >

             < a   class = "ui-datepicker-prev ui-corner-all"   title = "Prev"

                ms-click = "prevMonth"

                ms-hover = "ui-state-hover"

                ms-hover-1 = "ui-datepicker-prev-hover"

                >

                 < span   class = "ui-icon ui-icon-circle-triangle-w" >Prev</ span ></ a >

             < a   class = "ui-datepicker-next ui-corner-all"    title = "Next"

                ms-click = "nextMonth"

                ms-hover = "ui-state-hover"

                ms-hover-1 = "ui-datepicker-next-hover"

                >

                 < span   class = "ui-icon ui-icon-circle-triangle-e" >Next</ span ></ a >

             < div   class = "ui-datepicker-title" >

                 < select    ms-each-month = "$months"   ms-if = "changeMonth"   ms-model = "currentMonth"   >

                     < option   value = "{{month}}"   ms-selected = "currentMonth == month" >{{month+1}}月</ option >

                 </ select >

                 < select    ms-each-year = "candidateYears"   ms-if = "changeYear"   ms-model = "currentYear"   >

                     < option   value = "{{year}}"   ms-selected = "currentYear == year" >{{year}}年</ option >

                 </ select >

                 {{title}}

             </ div >

         </ div >

         < table   class = "ui-datepicker-calendar"   >

             < thead >

                 < tr   ms-each-date = "$weeks" >

                     < th   ms-class-ui-datepicker-week-end = "$first" >

                         < span   title = "星期{{date}}" >{{date}}</ span >

                     </ th >

                 </ tr >

             </ thead >

             < tbody   ms-each-week = "currentWeeks"   ms-click = "selectDay" >

                 < tr   ms-each-day = "week" >

                     < td   ms-class-ui-datepicker-other-month = "Number(day.split('-')[1]) != currentMonth"

                         ms-class-ui-datepicker-week-end = "$first || $last"

                         ms-class-ui-state-disabled = "day.split('-')[3] == 1"

                         ms-class-ui-datepicker-unselectable = "day.split('-')[3] == 1"

                         >

                         < a   class = "ui-state-default"    ms-title = 'currentMonth'   href = "#"

                            ms-if = "showOtherMonths || Number(day.split('-')[1]) == currentMonth"

                            ms-hover = "ui-state-hover"

                            ms-class-ui-state-highlight = "isToday"

                            >{{day.split('-')[2]}} </ a >

                     </ td >

             </ tbody >

         </ table >

         < div   class = "ui-datepicker-buttonpane ui-widget-content"   ms-if = "showButtonPanel" >

             < button   type = "button"   class = "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all"

                     ms-hover = "ui-state-hover"

                     ms-click = "backToday"

                     >Today</ button >

             < button   type = "button"   class = "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all"

                     ms-hover = "ui-state-hover"

                     >Done</ button >

         </ div >

     </ div >

     < link   rel = "stylesheet"   href = " http://code.jquery测试数据/ui/1.10.3/themes/ {{theme}}/jquery-ui.css"   >

     < div >< input   type = "radio"   ms-model = "changeMonth"   />可选择月份</ div >

     < div >< input   type = "radio"   ms-model = "changeYear"   />可选择年份</ div >

     < div >< input   type = "radio"   ms-model = "showButtonPanel"   />显示按钮面板</ div >

     < div >< input   type = "radio"   ms-model = "showOtherMonths"   />显示其他月份的日期</ div >

     < div >< select   ms-model = "theme" >

             < option   value = 'start' >start</ option >

             < option   value = 'smoothness' >smoothness</ option >

             < option   value = 'flick' >flick</ option >

             < option   value = 'sunny' >sunny</ option >

             < option   value = 'excite-bike' >excite bike</ option >

             < option   value = 'black-tie' >black tie</ option >

             < option   value = 'trontastic' >trontastic</ option >

             < option   value = 'swanky-purse' >swanky purse</ option >

             < option   value = 'le-frog' >le frog</ option >

             < option   value = 'blitzer' >blitzer</ option >

             < option   value = 'dot-luv' >dot luv</ option >

             < option   value = 'mint-choc' >mint-choc</ option >

             < option   value = 'hot-sneaks' >hot sneaks</ option >

             < option   value = 'south-street' > south street</ option >

             < option   value = 'humanity' >humanity</ option >

             < option   value = 'vader' >vader</ option >

             < option   value = 'eggplant' >eggplant</ option >

             < option   value = 'cupertino' >cupertino</ option >

             < option   value = 'overcast' >overcast</ option >

         </ select >你喜欢的皮肤</ div >

     < p >你选择的日期为 {{selectedDate | date('yyyy-MM-dd')}}</ p >

 

</ div >

上面的结构分两部分,最上的日历,下面的一些表单元素用于控制日历的配置。

avalon.ready( function () {

    avalon.define( "datepicker" , function (vm) {

         //配置

         vm.changeYear = false

         vm.changeMonth = false

         vm.minDate = new   Date(2013, 3, 25);

         //vm.maxDate

         vm.showOtherMonths = false ;

         vm.showButtonPanel = false ;

         //当前时间

         vm.selectedDate = new   Date;

         vm.currentDate = new   Date;

         vm.currentMonth = vm.currentDate.getMonth();

         vm.currentYear = vm.currentDate.getFullYear();

         vm.currentWeeks = getWeeks(vm.currentDate);

         //显示顶部的年份与月份

         vm.title = {

             get: function () {

                 var   format = "" ;

                 if   (! this .changeYear && this .changeMonth) {

                     format = "yyyy年" ;

                 } else   if   ( this .changeYear && ! this .changeMonth) {

                     format = "MMMM" ;

                 } else   if   (! this .changeYear && ! this .changeMonth) {

                     format = "MMMM yyyy年" ;

                 }

                 return   format && avalon.filters.date( this .currentDate, format);

             }

         };

         //星期显示

         vm.$weeks = "日一二三四五六" .split( "" );

         //月份下拉菜单

         vm.$months = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

         //当月的日期

         function   isDisabled(time) {

             var   disabled = false ;

             if   (vm.minDate) {

                 disabled = time < vm.minDate;

             }

             if   (disabled && vm.maxDate) {

                 disabled = time > vm.maxDate;

             }

             return   disabled - 0;

         }

         function    getWeeks(cur) {

             vm.currentDate = cur;

             var   year = cur.getFullYear();

             var   month = cur.getMonth(); //得到今天是几月(0 ~ 11)

             var   date = cur.getDate();  //得到今天是几号 (1 ~ 31)

             cur.setMonth(month + 1); //改为下一个月,

             //由于日期是1 ~ 31, 0则是退到上一个月的最后一天,于是得到这个月的总天数

             cur.setDate(0);

             var   num = cur.getDate();

             var   next = 6 - cur.getDay();

             var   dates = avalon.range(1, num + 1);

             dates = dates.map( function (d) {

                 var   time = new   Date(year, month, d)

                 return   [year, month, d, isDisabled(time)].join( "-" );

             });

             cur.setMonth(month);

             cur.setDate(1); //得到当月的第一天

             var   prev = cur.getDay(); //0 ~ 6

             cur.setDate(date); //还原

             for   ( var   i = 0; i < prev; i++) { //补上上一个月的日期

                 cur = new   Date(year, month, -1 * i)

                 dates.unshift([year, cur.getMonth(), cur.getDate(), isDisabled(cur)].join( "-" ))

             }

             for   ( var   i = 0; i < next; i++) { //补上下一个月的日期

                 cur = new   Date(year, month + 1, i + 1)

                 dates.push([year, cur.getMonth(), cur.getDate(), isDisabled(cur)].join( "-" ))

             }

             var   ret = [];

             while   (dates.length) { //每行七个分组

                 ret.push(dates.splice(0, 7));

             }

             return   ret; //一个三维数组

         }

 

         //取得当年的前后20年

         function   getYears() {

             var   y = vm.currentYear;

             return   avalon.range(y - 10, y + 10);

         }

         vm.candidateYears = getYears();

         //点击事件

         vm.theme = "start" ;

         vm.nextMonth = function (e) {

             e.preventDefault()

             var   d = vm.currentDate;

             var   m = d.getMonth();

             d.setMonth(m + 1);

             m = d.getMonth();

             if   (m === 0) {

                 var   y = d.getFullYear();

                 vm.currentYear = y;

             }

             vm.currentMonth = m;

         };

         //点击事件

         vm.prevMonth = function (e) {

             e.preventDefault()

             var   d = vm.currentDate;

             var   m = d.getMonth();

             d.setMonth(m - 1);

             m = d.getMonth();

             if   (m === 11) {

                 var   y = d.getFullYear();

                 vm.currentYear = y;

             }

             vm.currentMonth = m;

         };

         //侦听

         vm.$watch( "currentMonth" , function (val) {

             var   d = vm.currentDate;

             d.setMonth(val);

             vm.currentWeeks = getWeeks(d);

             vm.title = NaN;

         });

 

         vm.$watch( "currentYear" , function (val) {

             var   d = vm.currentDate;

             d.setFullYear(val)

             vm.currentWeeks = getWeeks(d);

             vm.title = NaN;

         });

         //高亮当前选中的日期

         vm.selectDay = function (e) {

             var   el = e.target;

             e.preventDefault()

             if   (el.tagName === "A"   && el.parentNode.tagName === "TD"   && !/disabled/.test(el.className)) {

                 vm.selected = el.innerHTML;

                 var   d = el.$scope.day.split( '-' )

                 vm.selectedDate = new   Date(d[0], d[1], d[2]);

             }

         };

 

         //高亮今天的日期

         var   today = new   Date;

         var   atoday = [today.getFullYear(), today.getMonth(), today.getDate()];

         vm.isToday = function () {

             var   day = this .$scope.day;

             return   day.slice(0, day.lastIndexOf( "-" )) === atoday.join( "-" );

         };

         vm.backToday = function () {

             vm.currentMonth = atoday[1];

             vm.currentYear = atoday[0];

         }

     });

     avalon.scan();

});

这个JS代码比起先前的更清晰,放弃使用$fire这个危险的操作,建议大家也不要用它。因为如果没有严格的值变动检测, 这很容易引起无限递归。 现在avalon已经完全重用现有的节点,不会像过去那样每次都清空然后又添加。因此性能更好。

Prev Next

5月 2013年

日 一 二 三 四 五 六       1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31  

可选择月份

可选择年份

显示按钮面板

显示其他月份的日期

                      start                       smoothness                       flick                       sunny                       excite bike                       black tie                       trontastic                       swanky purse                       le frog                       blitzer                       dot luv                       mint-choc                       hot sneaks                        south street                       humanity                       vader                       eggplant                       cupertino                       overcast                   选择你喜欢的皮肤(注:这些样式都受到博客园染指了)

所有JS代码不到150行,就能涵盖jquery ui datepicker(2000多行)的绝大多数功能。如果努力一点,把模板也封装一下,其他功能也跟进,最多也是500行的规模。可谓MVVM的威力。而且这样写JS,可读性非常好,思路不会像着jQuery那样跟着CSS表达式——“这个元素是在哪里,该添加类名还是移除类名……”

 

 

 

标签:  javascript

作者: Leo_wl

    

出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于使用avalon MVVM框架打造jquery ui的日历的详细内容...

  阅读:47次