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 })();
原文:http://www.cnblogs.com/liguoxi134/p/3564496.html