Hướng dẫn tạo khung search Autocomplete

Đăng bởi Bùi Thanh Sơn

Hướng dẫn tạo khung search Autocomplete



Bước 1: Tạo view search.ultimate-search.liquid dùng để lấy thông tin sản phẩm


{%layout none %}
[{%for product in search.results limit:10%}
{"title":"{{product.title }}","url":"{{product.url}}","price":"{{product.price}}","compare_at_price":"{{product.compare_at_price}}","featured_image":"{{product.featured_image}}","available":"{{product.available}}"}{%unless forloop.last%},{%endunless%}
{%endfor%}]

Download search.ultimate-search.liquid.txt


Bước 2: Tạo khung search Autocomplete [ html, js, css ]
Download  ultimate-search-with-thumb.liquid.txt

code demo:

<form id="searchauto" action="/search" class="searchform-categoris ultimate-search">

	<div class="wpo-search">

		<div class="wpo-search-inner">

			<div class="input-group">

				<input type="hidden" name="type" value="product" />

				<input id="searchtext" name="q" id="s" maxlength="40" class="form-control input-search" type="text" size="20" placeholder="Enter search...">

				<span class="input-group-addon">

					<input type="submit" id="searchsubmit" class="fa" value="">

				</span>

			</div>

		</div>

		<input type="hidden" class="collection_id" value="(collectionid:product>=0)" />

		<input type="hidden" class="collection_handle" value="all" />

		<input type="hidden" class="collection_name" value="all" />

	</div>

</form>




<script>


$('.ultimate-search').submit(function(e) {

	e.preventDefault();

	var q = $(this).find('input[name=q]').val();

	if( ! q ) {
		window.location = '/search?type=product&q=**';
		return;
	}
	else{
		window.location = '/search?type=product&q=' + q;
		return;
	}
});

function selectSuggest(act){

	cur = $('.smart-search-wrapper > .select').index();

	length = $('.smart-search-wrapper > a').length;

	if (act == 38)
	{

		if (cur == -1 || cur == 0)

			cur = length - 1;				

		else

			cur = cur - 1;

	}


	if (act == 40)
	{

		if (cur == -1 || cur == length - 1)

			cur = 0;				

		else

			cur = cur + 1;
	}

	$('.smart-search-wrapper>a').removeClass('select');

	$('.smart-search-wrapper>a:nth-child('+ ( cur + 1)+')').addClass('select');


	$('.ultimate-search input[name=q]').val($('.smart-search-wrapper>.select').attr('data-title'));
	return false;
}


(function($) {
	$.fn.smartSearch = function(_option) {


		var o, issending = false,

				timeout = null;

		var option = {
			smartoffset: true, //auto calc offset

			searchoperator: '**', //** contain, *= begin with, =* end with

			searchfield: "title",

			searchwhen: 'keyup', //0: after keydown, 1: after keypress, after space

			searchdelay: 500, //delay time before load data

		};

		if (typeof(_option) !== 'undefined') {

			$.each(_option, function(i, v) {

				if (typeof(_option[i]) !== 'undefined') option[i] = _option[i];

			})
		}

		o = $(this);

		o.attr('autocomplete', 'off');

		this.bind(option.searchwhen, function(event) {

			if (event.keyCode == 38 || event.keyCode == 40) {

				return selectSuggest(event.keyCode);

			} else {

				$(".smart-search-wrapper." + option.wrapper).remove();

				clearTimeout(timeout);

				timeout = setTimeout(l, option.searchdelay, $(this).val());

			}

		});     

		var l = function(t) {

			if (issending) return this;

			issending = true;

			coll=''

			if(option.collection != null)

				coll= $(option.collection).val() + "&&";

			$.ajax({

				url: "/search?q=filter=(" + coll + "(" + option.searchfield + ":product" + option.searchoperator + t + "))&view=ultimate-search",

				dataType: "JSON",

				async: false,

				success: function(data) {

					if( $('.smart-search-wrapper.' + option.wrapper).length == 0 ) {

						$('body').append("<div class='smart-search-wrapper "  + option.wrapper + "'></div>");

					}

					p();

					$.each(data, function(i, v) {

						$(".smart-search-wrapper." + option.wrapper).append("<a data-title='"+ v.title + "'class='thumbs' href='" + v.url + "'> <img src='"+Haravan.resizeImage(v.featured_image, 'icon')+"'/></a><a data-title='"+ v.title + "' href='" + v.url + "'>" + v.title + "<span class='price-search'>"+Haravan.formatMoney(v.price, '{{amount}}')+"đ</span></a>");

					});

					issending = false;

				},

				error: function (xhr, ajaxOptions, thrownError) {

					//alert(xhr.status);

					//alert(thrownError);

				}

			});

		}

		$(window).resize(function() {

			p();

		});

		$(window).scroll(function() {

			p();

		});

		$(this).blur(function(){

		$('.smart-search-wrapper.' + option.wrapper).slideUp();

		});

		var p = function() {

			if( ! o.offset() ) {

				return;

			}


			$(".smart-search-wrapper." + option.wrapper).css("width", o.outerWidth() + "px");

			$(".smart-search-wrapper." + option.wrapper).css("left", o.offset().left + "px");

			if (option.smartoffset) {


				h = $(".smart-search-wrapper." + option.wrapper).height();

				if (h + o.offset().top - $(window).scrollTop() + o.outerHeight() > $(window).height()) {

					$(".smart-search-wrapper." + option.wrapper).css('top', '');


					$(".smart-search-wrapper." + option.wrapper).css('bottom', ($(window).scrollTop() + $(window).height() - o.offset().top) + "px");

				} else {

					$(".smart-search-wrapper." + option.wrapper).css('bottom', '');

					$(".smart-search-wrapper." + option.wrapper).css('top', (o.offset().top - $(window).scrollTop() + o.outerHeight()) + "px");

				}

			} else {

				$(".smart-search-wrapper." + option.wrapper).css('top', (o.offset().top - $(window).scrollTop() + o.outerHeight()) + "px");

			}

		}

		return this;

	};
}(jQuery));



jQuery('.ultimate-search input[name=q]').smartSearch({searchdelay:400, wrapper: 'search-wrapper', collection:'.collection_id'});


</script>


<style>

	.smart-search-wrapper>a.thumbs{   
	width: 32px;
	display: inline-block;
	padding: 5px 0px;
	}



.smart-search-wrapper>a.thumbs img {
     position: absolute;
    top: 0px;
    width: 32px;
    height: 35px;
    left: 0px;
}
	.smart-search-wrapper{
	position: fixed;
	background: #fff;
	border: 1px solid rgb(215, 215, 215);

	border-top: none;
	z-index: 999;
	}

	.smart-search-wrapper>a {
	width: calc(100% - 32px);
	float: left;
	text-overflow: ellipsis;
	overflow: hidden;
	white-space: pre;
	color: #686767;
	text-decoration: none;
	line-height: 29px;
	font-size: 13px;
	font-family: sans-serif;
  padding: 5px 160px 5px 5px;
	position: relative;
	height: 35px;
	}

	.smart-search-wrapper>a.select, .smart-search-wrapper>a:hover {
    background: -webkit-linear-gradient(left, #fff,#EAEAEA); /* For Safari 5.1 to 6.0 */
    background: -o-linear-gradient(left, #fff,#EAEAEA); /* For Opera 11.1 to 12.0 */
    background: -moz-linear-gradient(left, #fff,#EAEAEA ); /* For Firefox 3.6 to 15 */
    background: linear-gradient(left, #fff,#EAEAEA ); /* Standard syntax (must be last) */
	color: #000;
	}

	.smart-search-wrapper>a>span.price-search {
	position: absolute;
	right: 5px;
	top:0px;
	}

</style>
Note:

Đây option của code Autocomplete ( đã bôi đen ở trên ) : 

var option = { smartoffset: true, //auto calc offset searchoperator: '**', //** contain, *= begin with, =* end with searchfield: "title", searchwhen: 'keyup', //0: after keydown, 1: after keypress, after space searchdelay: 500, //delay time before load data };
searchdelay: thời gian trễ trước khi load dữ liệu
searchoperator: toán tử dùng để tìm kiếm, ** chứa, *= bắt đầu bằng, =* kết thúc bằng
searchfield: mục tiêu tìm kiếm ( tittle: theo tên )
- vv...
Đây là phần hiển thị kết quả ( đã bôi đen ở trên )
    $(".smart-search-wrapper." + option.wrapper).append("<a data-title='"+ v.title + "'class='thumbs' href='" + v.url + "'> <img src='"+Haravan.resizeImage(v.featured_image, 'icon')+"'/></a><a data-title='"+ v.title + "' href='" + v.url + "'>" + v.title + "<span class='price-search'>"+Haravan.formatMoney(v.price, '{{amount}}')+"đ</span></a>");
- các bạn có thể tuỳ chỉnh cách hiển thị của kết tại đây. ( vd: bỏ ảnh, bỏ giá,.... ) 



Bạn là lập trình viên? Gia nhập gia đình haravan Chi tiết ›