jQuery UI datepicker选择日期后,日期层会再次加载
在项目中,使用jQuery UI的datepicker日期控件时,出现以下问题:
1、在IE浏览器下,选择好日期后,datepicker的日期显示会重新加载;
2、在Firefox浏览器下,选择好日期后,datepicker的日期显示不会重新加载,可是想再次修改日期时,焦点必须离开输入的日期框后,再点击进入才能出现datepicker的日期选择框。
百度得到的答案如下:
针对上述出现的问题,我对jQuery UI 1.8.15版本的源码进行了查看,发现jquery.ui.datepicker是由focus事情来显示日期选择层的,经检查代码发现_selectDate方法中默认的选择日期是选择日期赋值给输入框后,再重新对输入框设定focus。这样在IE浏览器下就会出现日期选择框重新加载了。
问题代码出现在jquery.ui.datepicker.js文件的909到930行,其具体如下:
- /* Update the input field with the selected date. */
- _selectDate: function(id, dateStr) {
- var target = $(id);
- var inst = this._getInst(target[0]);
- dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
- if (inst.input)
- inst.input.val(dateStr);
- this._updateAlternate(inst);
- var onSelect = this._get(inst, 'onSelect');
- if (onSelect)
- onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
- else if (inst.input)
- inst.input.trigger('change'); // fire the change event
- if (inst.inline)
- this._updateDatepicker(inst);
- else {
- this._hideDatepicker();
- this._lastInput = inst.input[0];
- inst.input.focus(); // restore focus
- this._lastInput = null;
- }
- },
将上面“inst.input.focus(); // restore focus”的代码注释掉后,进行测试。发现上述出现的两个问题都能解决,因此决定修改jQuery UI的代码。
通过代码研究发现,上述遇到的问题,应该也可以通过自定义onSelect方法来实现。只是简单试了下,效果没达到,所以就冒险对jQuery UI的代码进行修改了。
项目中引用的jQuery UI是min的js文件,也就是jQuery UI团队发布的,经过压缩后的文件。该文件和源码存在很大差别。主要区别有:
1、源码文件是分plugin来定义单个js文件的;
2、jquery-ui-1.8.15.custom.min.js文件是将所有发布的ui,集成在一个文件里;
3、jquery-ui-1.8.15.custom.min.js文件的代码经过了压缩。
不过还好,jquery-ui-1.8.15.custom.min.js文件的压缩主要是针对定义的变量进行的。经datepicker、_selectDate和focus()一路查找下来。终于找到了a.input.focus();这句代码。将其删除后,测试后达到了解决效果。
但是在实践的时候,出现一些小的出入,我使用的jquery-ui-1.8.11.custom.min.js这个版本中屏蔽了以下两个位置的focus方法,分别解决了上面两个问题
_selectDate: function (a, b) { if (d(a)[0]) { a = this._getInst(d(a)[0]); b = b != null ? b : this._formatDate(a); a.input && a.input.val(b); this._updateAlternate(a); var c = this._get(a, "onSelect"); if (c) c.apply(a.input ? a.input[0] : null, [b, a]); else a.input && a.input.trigger("change"); if (a.inline) this._updateDatepicker(a); else { this._hideDatepicker(); this._lastInput = a.input[0]; typeof a.input[0] != "object";//&& a.input.focus(); this._lastInput = null } } },
_updateDatepicker: function (a) { var b = this, c = d.datepicker._getBorders(a.dpDiv); a.dpDiv.empty().append(this._generateHTML(a)); var e = a.dpDiv.find("iframe.ui-datepicker-cover"); e.length && e.css({ left: -c[0], top: -c[1], width: a.dpDiv.outerWidth(), height: a.dpDiv.outerHeight() }); a.dpDiv.find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout", function () { d(this).removeClass("ui-state-hover"); this.className.indexOf("ui-datepicker-prev") != -1 && d(this).removeClass("ui-datepicker-prev-hover"); this.className.indexOf("ui-datepicker-next") != -1 && d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover", function () { if (!b._isDisabledDatepicker(a.inline ? a.dpDiv.parent()[0] : a.input[0])) { d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); d(this).addClass("ui-state-hover"); this.className.indexOf("ui-datepicker-prev") != -1 && d(this).addClass("ui-datepicker-prev-hover"); this.className.indexOf("ui-datepicker-next") != -1 && d(this).addClass("ui-datepicker-next-hover") } }).end().find("." + this._dayOverClass + " a").trigger("mouseover").end(); c = this._getNumberOfMonths(a); e = c[1]; e > 1 ? a.dpDiv.addClass("ui-datepicker-multi-" + e).css("width", 17 * e + "em") : a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); a.dpDiv[(c[0] != 1 || c[1] != 1 ? "add" : "remove") + "Class"]("ui-datepicker-multi"); a.dpDiv[(this._get(a, "isRTL") ? "add" : "remove") + "Class"]("ui-datepicker-rtl"); a == d.datepicker._curInst && d.datepicker._datepickerShowing && a.input && a.input.is(":visible") && !a.input.is(":disabled") &&a.input[0] != document.activeElement ;//&& a.input.focus(); if (a.yearshtml) { var f = a.yearshtml; setTimeout(function () { f === a.yearshtml && a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml); f = a.yearshtml = null }, 0) } },