Javascript – Vì sao phải sử dụng Autocomplete dropdown? Với 1 list tầm 100 items thì bạn dùng Dropdown thì hợp lý.
Nhưng lớn hơn thì chẳng lẽ người dùng phải đi cuộn cắm đầu xuống tìm cho ra item đó sao? Quá ko hợp lý. Khi đó chúng ta sẽ phải nghĩ tới trường hợp cho người dùng gõ vào và auto Suggest cho người ta những item theo ý của người dùng.
Nào bắt tay vào làm việc nhé
I. Chuẩn bị:
- Jquery
- 1 File Js
- 1 File Css
II. Coding:
Coding JS
(function ($) { $.fn.extend({ tAutoComplete: function (options) { var that = $(this); var _countPaging = 0; var _countPagingSearch = 0; var _combineId = that.attr("id"); var _divCoverId = 'dvCover' + _combineId; var _divTestId = 'dvTest' + _combineId; var _divCover = null; var _divTest = null; var _foundedItems = new Array(); var _coverDivTop = 0; var _coverDivLeft = 0; var _coverDivWidth = that.outerWidth(); var _body = $("body"); var _showMoreElement = $('<p class="TShowMore">MORE...</p>'); var _lowerArray = $.map(options.source, function (n, i) { return htmlDecode(n.toLowerCase()); }); //Settings list and the default values var defaults = { minChar: 60, maxLength: 10, numberOfRecords: 100, maxHeightCss: 250, source: new Array(), // select: function (index, item) { }, }; // extend the options from pre-defined values: var defaults = $.extend({ select: function () { } }, arguments[0] || {}); var options = $.extend(defaults, options); that.click(function (e) { _coverDivTop = $(this).offset().top + $(this).outerHeight() + 1; _coverDivLeft = $(this).offset().left; var val = that.val().toLowerCase();; if (val.length > 0) { searchStringInArray(val); } else { GenerateParentDiv(); } _divCover = _body.find("#" + _divCoverId); }); that.blur(function () { //// Check item exist in array var t = ''; clearTimeout(t); delay(function () { var val = that.val().toLowerCase(); //alert(val); var index = $.inArray(val, _lowerArray); //alert(index); if (index == -1) { that.val(''); } }, 20); }); that.keyup(function (e) { // Show list item if (!~$.inArray(e.which, [13, 27, 38, 40, 37, 39])) { var val = that.val().toLowerCase(); // Set Time after input var t = ''; if (val.length >= options.minChars) { clearTimeout(t); delay(function () { searchStringInArray(val); }, 200); } else { //that.last_val = val; //that.sc.hide(); } } }); that.keydown(function (e) { if (~$.inArray(e.which, [38, 40, 13, 9])) { if (event.keyCode == 38) { // Get current index of TSelected _divCover = _body.find("#" + _divCoverId); var $current = _divCover.find(".TSelected").first(); $current = $current.prev(); SetSelectedForItem(_divCover, $current); } if (event.keyCode == 40) { // Get current index of TSelected _divCover = _body.find("#" + _divCoverId); var $current = _divCover.find(".TSelected").first(); $current = $current.next(); SetSelectedForItem(_divCover, $current); } if (event.keyCode == 13 || event.keyCode == 9) { _divCover = _body.find("#" + _divCoverId); var $current = _divCover.find(".TSelected").first(); if ($current.length > 0) { that.val($current.text()); _divCover.hide(); if ($.isFunction(options.select)) { options.select.call(this, that, { value: $(this).text() }); } } } } }); $(document).mouseup(function (e) { var divCover = _body.find("#" + _divCoverId); if (!divCover.is(e.target) // if the target of the click isn't the container... && divCover.has(e.target).length === 0) // ... nor a descendant of the container { divCover.hide(); } }); function GenerateParentDiv() { var _topItems = options.source.slice(0, options.numberOfRecords); var _countItem = options.source.length / options.numberOfRecords; var parent = $('<div id="' + _divCoverId + '" style="position:absolute; top:' + _coverDivTop + 'px; left:' + _coverDivLeft + 'px; width:' + (_coverDivWidth - 2) + 'px; background:white; border:1px solid #666;max-height:' + options.maxHeightCss + 'px; overflow-y: auto; overflow-x: hidden; z-index:1000;"></div>'); if (!_body.find("#" + _divCoverId).length > 0) { // Reset value to default _countPaging = 0; // Append TOP element $.each(_topItems, function (index, item) { AppendItemToList(parent, item); }); // Append show more link var top = 0 + options.numberOfRecords; if (_topItems.length > 0 && (options.source.length - top > 0)) { AppendShowMoreItem(parent, _countPaging); } _body.append(parent); _divCover = parent; if (_topItems.length > 0) { ShowDataDiv(parent); // Focus to first item FocusToFirstItem(); } else { parent.hide(); } } else { // Reset value to default _countPaging = 0; _divCover = _body.find("#" + _divCoverId); _divCover.empty(); // Append TOP element $.each(_topItems, function (index, item) { AppendItemToList(_divCover, item); }); // Append show more link // Append show more link var top = 0 + options.numberOfRecords; if (_topItems.length > 0 && (options.source.length - top > 0)) { AppendShowMoreItem(_divCover, _countPaging); } if (_topItems.length > 0) { ShowDataDiv(_divCover); // Focus to first item FocusToFirstItem(); } } } function ShowMore(divTest) { _countPaging++; AppendMoreItem(divTest, _countPaging); } function AppendShowMoreItem(divTest, count) { var showMoreLink = _showMoreElement; showMoreLink.click(function () { var showMoreElement = $(this); $(this).remove(); ShowMore(divTest); }); divTest.append(showMoreLink); } function AppendMoreItem(divTest, count) { var bottom = count * options.numberOfRecords + 1; var top = bottom + options.numberOfRecords; var topItems = options.source.slice(bottom, top); // Append all element $.each(topItems, function (index, item) { AppendItemToList(divTest, item); }); if (topItems.length > 0 && (options.source.length - top > 0)) { AppendShowMoreItem(divTest, count); } that.focus(); } function AppendItemToList(divTest, item) { var currentItem = $('<p class="THoverAble">' + item + '</p>'); currentItem.click(function () { divTest.find(".TSelected").removeClass("TSelected"); $(this).addClass('TSelected'); that.val($(this).text()); divTest.hide(); if ($.isFunction(options.select)) { options.select.call(this, that , { value: $(this).text() }); } }); divTest.append(currentItem); } function searchStringInArray(str) { // Reset all value to default _countPagingSearch = 0; _foundedItems = new Array(); var divTest = _body.find("#" + _divCoverId); if (divTest.length < 1) { // Create div Test var parent = $('<div id="' + _divCoverId + '" style="position:absolute; top:' + _coverDivTop + 'px; left:' + _coverDivLeft + 'px; width:' + (_coverDivWidth - 2) + 'px; background:white; border:1px solid #666;max-height:' + options.maxHeightCss + 'px; overflow-y: auto; overflow-x: hidden; z-index:1000;"></div>'); _body.append(parent); divTest = parent; _divCover = parent; } else { _coverDivTop = that.offset().top + that.outerHeight() + 1; _coverDivLeft = that.offset().left; // Update css divTest.css("top", _coverDivTop + "px"); divTest.css("left", _coverDivLeft + "px"); } divTest.empty(); for (var j = 0; j < _lowerArray.length; j++) { var text = _lowerArray[j]; var resultTest = text.indexOf(str) > -1; if (resultTest) { _foundedItems.push(options.source[j]); } } var count = 0; var bottom = count * options.numberOfRecords; var top = bottom + options.numberOfRecords; var topItems = _foundedItems.slice(bottom, top); $.each(topItems, function (index, item) { AppendItemToList(divTest, item); }); if (topItems.length > 0 && (_foundedItems.length - top > 0)) { AppendShowMoreItemSearch(divTest, count); } if (topItems.length > 0) { ShowDataDiv(divTest); FocusToFirstItem(); } else { divTest.hide(); } } function AppendShowMoreItemSearch(divTest, count) { var showMoreLink = _showMoreElement; showMoreLink.click(function () { var showMoreElement = $(this); $(this).remove(); ShowMoreSearch(divTest); }); divTest.append(showMoreLink); } function ShowMoreSearch(divTest) { _countPagingSearch++; AppendMoreItemSearch(divTest, _countPagingSearch); } function AppendMoreItemSearch(divTest, count) { var bottom = count * options.numberOfRecords + 1; var top = bottom + options.numberOfRecords; var topItems = _foundedItems.slice(bottom, top); // Append all element $.each(topItems, function (index, item) { AppendItemToList(divTest, item); }); if (topItems.length > 0 && (_foundedItems.length - top > 0)) { AppendShowMoreItemSearch(divTest, count); } that.focus(); } function FocusToFirstItem() { _divCover = _body.find("#" + _divCoverId); _divCover.find(".THoverAble").removeClass("TSelected"); var first = _divCover.find(".THoverAble").first(); first.addClass("TSelected"); } function ShowDataDiv(divData) { divData.show(); // Set css divData.css({ "top": _coverDivTop + "px", "left": _coverDivLeft + "px" }); $(divData).scrollTop(0); } function SetSelectedForItem(divCover, currentItem) { currentItem = $(currentItem); divCover = $(divCover); if (currentItem.length > 0 && currentItem.hasClass("THoverAble")) { divCover.find(".TSelected").removeClass("TSelected"); currentItem.addClass("TSelected"); that.val(currentItem.text()); $(divCover).scrollTop(currentItem.index() * currentItem.outerHeight() - (currentItem.outerHeight() + 10)); } } function htmlDecode(value) { return $('<div/>').html(value).text(); } } }); })(jQuery);
Coding CSS
.TDropdownDiv{ position:relative; } .TDropdownUL{ position:absolute; width:99%; display:none; border-left: 1px solid #006498; border-right: 1px solid #006498; border-bottom: 1px solid #006498; background:white; z-index:999; max-height:250px; overflow-y:scroll; } .TDropdownUL li { list-style:none; position:relative; padding-left:3px; color:black; } .TDropdownUL li:hover{ background: #3399ff; color:white; } .TDropdownUL li.TSelected{ background: #3399ff; color:white; } .TDropdownUL li.Li_Header{ background: #cacaca; color:#666; font-weight:bold; } .TDropdownButton{ border:none; position:absolute; width:17px !important; height:18px; top:1px; right:3px; background: url('Images/btDropdown.png') no-repeat; } .LiValue{ display:block; } .LiValue:hover{ cursor:default; } .THoverAble{ padding:0px 2px; } .TShowMore{ color:blue; text-align:right; cursor:pointer; text-decoration:underline; text-transform:lowercase; padding-right: 10px; }
Tạo dữ liệu mẫu
$(document).ready(function(){ subNames = new Array(); @foreach (var item in Model.Subdivisions) { @:subNames.push('@item.SubName'); } $("#SubName").tAutoComplete({ minChars:0, minLength: 0, source: subNames, numberOfRecords: 200, maxHeightCss: 250, select: function (object, data) { var _this = $(object); //DoMoreThingWith(_this); } }); });
Chạy và xem kết quả
Các bạn thấy bài viết thế nào? 🙂
Cho mình ý kiến nhé