自定义日历

  1 (function () {
  2     var db = document.body;
  3     var Calendar = function (opts) {
  4         return new Calendar.prototype.init(opts);
  5     };
  6 
  7     Calendar.prototype = {
  8         constructor: Calendar,
  9         isHidden: true,
 10         init: function (opts) {
 11             this.opts = extend({
 12                 target: '',
 13                 initial: '09/27/2012',
 14                 format: 'MM/DD/YYYY',
 15                 callback: function () { }
 16             }, opts || {});
 17             var _this = this;
 18             this.target = $(this.opts.target);
 19             addEvent(this.target, 'click', function () { _this.create(); });
 20         },
 21         create: function () {
 22             var de = this.target.getAttribute('data-date');
 23             this.defaultValue = this.defaultValue || (de && new Date(de)) || (this.initial ? new Date(this.initial) : new Date());
 24             var year = this.defaultValue.getFullYear(), month = this.defaultValue.getMonth(), date = this.defaultValue.getDate(), _this = this;
 25             var days = this.calculateDays(year, month), fragment = document.createDocumentFragment(), ul = document.createElement('ul');
 26             this.close();
 27 
 28             var date_wrapper =  this.opts.target + 'date_wrapper';
 29             var date_header =  this.opts.target + 'date_header';
 30             var yearBox =  this.opts.target + 'yearBox';
 31             var prevYear =  this.opts.target + 'prevYear';
 32             var nextYear =  this.opts.target + 'nextYear';
 33             var monthBox =  this.opts.target + 'monthBox';
 34             var prevMonth =  this.opts.target + 'prevMonth';
 35             var nextMonth =  this.opts.target + 'nextMonth';
 36             var date_weekBox =  this.opts.target + 'date_weekBox';
 37             var date_dateBox =  this.opts.target + 'date_dateBox';
 38 
 39             var fmtdate_wrapper = this.opts.target + 'date_wrapper' + "' class='" + 'date_wrapper';
 40             var fmtdate_header = this.opts.target + 'date_header' + "' class='" + 'date_header';
 41             var fmtyearBox = this.opts.target + 'yearBox' + "' class='" + 'yearBox';
 42             var fmtprevYear = this.opts.target + 'prevYear' + "' class='" + 'prevYear';
 43             var fmtnextYear = this.opts.target + 'nextYear' + "' class='" + 'nextYear';
 44             var fmtmonthBox = this.opts.target + 'monthBox' + "' class='" + 'monthBox';
 45             var fmtprevMonth = this.opts.target + 'prevMonth' + "' class='" + 'prevMonth';
 46             var fmtnextMonth = this.opts.target + 'nextMonth' + "' class='" + 'nextMonth';
 47             var fmtdate_weekBox = this.opts.target + 'date_weekBox' + "' class='" + 'date_weekBox';
 48             var fmtdate_dateBox = this.opts.target + 'date_dateBox' + "' class='" + 'date_dateBox';
 49 
 50             var elstr =
 51             "<div id='" + fmtdate_wrapper + "'>" +
 52                 "<div id='" + fmtdate_header + "'>" +
 53                     "<div id='" + fmtyearBox + "'>" +
 54                         "<span id='" + fmtprevYear + "'>«</span><em>" + year + "</em>" + "<span id='" + fmtnextYear + "'>»</span>" +
 55                     "</div>" +
 56                     "<div id='" + fmtmonthBox + "'>" +
 57                         "<span id='" + fmtprevMonth + "'>«</span><em>" + (month + 1) + "</em><span id='" + fmtnextMonth + "'>»</span>" +
 58                     "</div>" +
 59                 "</div>" +
 60                 "<div id='" + fmtdate_weekBox + "'>" +
 61                     "<ul><li>Sun</li><li>Mon</li><li>Tue</li><li>Thu</li><li>Wed</li><li>Fri</li><li>Sat</li></ul>" +
 62                 "</div>" +
 63                 "<div id='" + fmtdate_dateBox + "'>" +
 64                 "</div>" +
 65             "</div>";
 66             this.wrapper = createEl(elstr, db);
 67 
 68             for (var i = 0, len = days.length; i < len; i++) {
 69                 var li = document.createElement('li');
 70                 var y = days[i].getFullYear(), m = days[i].getMonth(), d = days[i].getDate();
 71                 var f = m == month;
 72                 var fl = year == y && month == m && date == d;
 73                 li.setAttribute('data-date', days[i]);
 74                 li.innerHTML = d;
 75                 addClass(li, f ? 'black' : 'gray');
 76                 fl && addClass(li, 'current');
 77                 fragment.appendChild(li);
 78             }
 79             ul.appendChild(fragment);
 80             $(date_dateBox).appendChild(ul);
 81 
 82             setPosition(this.wrapper, this.target);
 83 
 84             addEvent($(prevYear), 'click', function () {
 85                 _this.defaultValue.setMonth(_this.defaultValue.getMonth() - 12, date);
 86                 _this.create();
 87             });
 88             addEvent($(nextYear), 'click', function () {
 89                 _this.defaultValue.setMonth(_this.defaultValue.getMonth() + 12, date);
 90                 _this.create();
 91             });
 92             addEvent($(prevMonth), 'click', function () {
 93                 _this.defaultValue.setMonth(_this.defaultValue.getMonth() - 1, date);
 94                 _this.create();
 95             });
 96             addEvent($(nextMonth), 'click', function () {
 97                 _this.defaultValue.setMonth(_this.defaultValue.getMonth() + 1, date);
 98                 _this.create();
 99             });
100             addEvent(ul, 'click', function (e) {
101                 e = e || window.event;
102                 var target = e.target || e.srcElement;
103                 if (hasClass(target, 'black')) {
104                     var date = target.getAttribute('data-date');
105                     _this.target.setAttribute('data-date', date);
106                     _this.defaultValue = new Date(date);
107                     if (_this.target.type == 'text') _this.target.value = formatDate(date, _this.opts.format);
108                     _this.opts.callback && _this.opts.callback(date);
109                     _this.close();
110                 };
111             });
112             addEvent(document.body, "click", function (e) {
113                 e = e || window.event;
114                 var target = e.target || e.srcElement;
115                 if (target != _this.wrapper && target != _this.target) {
116                     _this.close();
117                 }
118             });
119             this.isHidden = false;
120         },
121         set: function (d) {
122             this.defaultValue = d ? new Date(d) : new Date();
123             this.create();
124         },
125         get: function () {
126             return this.defaultValue;
127         },
128         close: function () {
129             if (!this.wrapper) return;
130             this.wrapper.parentNode.removeChild(this.wrapper);
131             this.wrapper.innerHTML = "";
132             this.wrapper = null;
133             this.isHidden = true;
134         },
135         trigger: function () {
136             this.create();
137         },
138         calculateDays: function (y, m) {
139             var offset, dFirstDay = new Date(y, m, 1), dLastDay = new Date(y, m + 1, 0), arr = [];
140             dFirstDay.setMonth(m, 1 - dFirstDay.getDay());
141             dLastDay.setMonth(m, dLastDay.getDate() + 6 - dLastDay.getDay());
142             offset = parseInt((dLastDay - dFirstDay) / (1000 * 60 * 60 * 24)) + 1;
143             var _y = dFirstDay.getFullYear(), _m = dFirstDay.getMonth(), _d = dFirstDay.getDate();
144             for (var i = 0; i < offset; i++) {
145                 var d = new Date(_y, _m, _d + i);
146                 arr.push(d);
147             }
148             return arr;
149         }
150     };
151     Calendar.prototype.init.prototype = Calendar.prototype;
152     window.Calendar = Calendar;
153 
154     function $(id) {
155         return typeof id == 'string' ? document.getElementById(id) : id;
156     };
157     function createEl(str, parent) {
158         var div = document.createElement('div'), el;
159         div.innerHTML = str;
160         el = div.firstChild;
161         parent && parent.appendChild(el);
162         return el;
163     };
164     function extend(t, s) {
165         for (var i in s) t[i] = s[i];
166         return t;
167     };
168     function getElementPos(el) {
169         var x = 0, y = 0;
170         if (el.getBoundingClientRect) {
171             var pos = el.getBoundingClientRect();
172             var d_root = document.documentElement, db = document.body;
173             x = pos.left + Math.max(d_root.scrollLeft, db.scrollLeft) - d_root.clientLeft;
174             y = pos.top + Math.max(d_root.scrollTop, db.scrollTop) - d_root.clientTop;
175         } else {
176             while (el != db) {
177                 x += el.offsetLeft;
178                 y += el.offsetTop;
179                 el = el.offsetParent;
180             };
181         };
182         return {
183             x: x,
184             y: y
185         };
186     };
187     function setPosition(target, reference) {
188         var pos = getElementPos(reference);
189         var left = pos.x, top = pos.y;
190         var width = reference.offsetWidth, height = reference.offsetHeight;
191         var w = target.offsetWidth, h = target.offsetHeight;
192         var st = Math.max(document.documentElement.scrollTop, document.body.scrollTop), sl = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
193         var cw = document.documentElement.clientWidth, ch = document.documentElement.clientHeight;
194         if (ch + st - top - height - 1 > h) {
195             target.style.top = top + height + 1 + 'px';
196         } else {
197             target.style.top = top - h - 1 + 'px';
198         };
199         if (cw + sl - left - width > w) {
200             target.style.left = left + 'px';
201         } else {
202             target.style.left = left + width - w + 'px';
203         };
204     };
205     function addEvent(el, type, fn) {
206         if (typeof el.addEventListener != 'undefined') {
207             el.addEventListener(type, fn, false);
208         } else if (typeof el.attachEvent != 'undefined') {
209             el.attachEvent('on' + type, fn);
210         };
211     };
212     function formatDate(t, tpl) {
213         var strs = [], w, keys, year, val, t = t ? new Date(t) : new Date();
214         w = 'Month,Date,FullYear'.split(',');
215         keys = [/MM/g, /M/g, /DD/g, /D/g, /YYYY/g, /YY/g];
216         for (var i = 0; i < 3; i++) {
217             val = t['get' + w[i]]() + (w[i] === 'Month' ? 1 : 0);
218             strs.push(('0' + val).slice(-2), val)
219         };
220         year = (strs.slice(0, 4)).concat([strs[5], strs[4]]);
221         for (var i = 0; i < 6; i++) {
222             tpl = tpl.replace(keys[i], year[i])
223         };
224         return tpl;
225     };
226     function clear(str) {
227         return str.replace(/^\s+|\s+$/g, '').replace(/\s+/, ' ');
228     };
229     function hasClass(el, oClass) {
230         return (' ' + el.className + ' ').indexOf(' ' + oClass + ' ') > -1;
231     };
232     function addClass(el, oClass) {
233         if (hasClass(el, oClass)) return;
234         var c = el.className;
235         el.className = clear(c ? c + ' ' + oClass : oClass);
236     };
237     function removeClass(el, oClass) {
238         if (!hasClass(el, oClass)) return;
239         var c = el.className;
240         el.className = clear((' ' + c + ' ').replace(' ' + oClass + ' ', ''));
241     };
242 })();

 

posted @ 2014-02-24 13:46  海之缘  阅读(178)  评论(0编辑  收藏  举报
如果你真的想做一件事,你一定会找到方法; 如果你不想做一件事,你一定会找到借口