Suggest Search when Focus được tạo ra mục đích làm cho ô tìm kiếm thêm màu mè hơn. Đơn giản khi người dùng vào trang của bạn, chỉ cần focus vào ô tìm kiếm, list bài viết sẽ được hiện ra, giúp họ dễ dàng truy cập bài viết mà không mất công chuyển hướng đến trang tìm kiếm
Xem demo (nhập địa chỉ blog của bạn vào và focus vào ô tìm kiếm để kiểm tra)
Ngoài việc build tiện ích, trong bài này tôi sẽ bổ sung thêm cho bạn 1 kĩ thuật để xử lý limited feeds nữa đó là ajax callback mà bài viết Blogger JSON Feed API - Limited Feeds chưa nhắc tới
Cách thức hoạt động của ajax callback này cũng tương tự như js callback đó là cộng dồn các giá trị entry cho tới khi bằng tổng số bài đăng
Bắt đầu thủ thuật, bài viết sử dụng font awesome 4 và jQuery 3.3.1
Code HTML
<div class='sg-wrap' id='sg-wrap'>
<form class='sg-form' action='/search' method='get'>
<input class='sg-input' placeholder='Type your text ...' type='search' autocomplete="off" />
<input class='sg-submit' type='submit' value="" />
<a class="sg-close"><i class='fa fa-times'></i></a>
</form>
<div class='sg-results'></div>
</div>
Code CSS (tương đối, bạn tự căn chỉnh sao cho phù hợp)
.sg-wrap {
position: relative;
width: 400px
}
.sg-form {
position: relative;
}
.sg-input {
outline: none;
width: 90%;
float: left;
display: block;
height: 34px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
}
.sg-submit {
width: 39px;
background: transparent;
font-family: fontawesome;
height: 34px;
-webkit-appearance: button;
cursor: pointer;
outline: 0;
border-radius: 3px;
border: 1px solid #ccc;
}
.sg-results {
display: none;
position: absolute;
top: 100%;
width: 100%;
border: 1px solid #ddd;
padding: 15px;
max-height: 445px;
overflow: auto;
background: #fff
}
.sg-item {
clear: both;
margin-bottom: 25px;
}
.sg-thumb img {
float: left;
width: 45px;
height: 45px;
border-radius: 100%;
margin-right: 10px;
margin-bottom: 15px;
}
.sg-title a {
text-decoration: none;
color: #000;
font-weight: bold;
font-family: arial, sans-serif;
font-size: 15px;
}
.sg-title a:hover {
color: #0088ff;
-webkit-transition: all .25s ease;
-moz-transition: all .25s ease;
-ms-transition: all .25s ease;
-o-transition: all .25s ease;
transition: all .25s ease;
}
.sg-close {
position: absolute;
top: 3px;
right: 13%;
font-size: 20px;
color: #000;
display: none;
cursor: pointer
}
JS trước </body>
<script>//<![CDATA[
// Suggest Search when focus by Hung1001
var count = 0, // đếm từ 0
total; // tổng số bài đăng
function getResults(json) { // hàm callback
if (json.feed.entry) {
total = json.feed.openSearch$totalResults.$t; // lấy tổng số bài đăng
count += json.feed.entry.length; // tăng biến sau mỗi lần callback
if (count < total) { // nếu vẫn còn nhỏ hơn tổng số bài thì tiếp tục callback lấy dữ liệu
$.ajax({
url: "/feeds/posts/default",
type: "GET",
data: {
"alt": "json",
"max-results": 150, // important
"start-index": count + 1, // important
},
dataType: "jsonp",
jsonpCallback: "getResults" // important
});
}
for (var i = 0; i < json.feed.entry.length; i++) {
// lấy href
for (var j = 0; j < json.feed.entry[i].link.length; j++)
if ("alternate" == json.feed.entry[i].link[j].rel) {
var b = json.feed.entry[i].link[j].href;
break
}
// lấy title
var c = json.feed.entry[i].title.$t;
// lấy thumb
try {
var d = json.feed.entry[i].media$thumbnail.url;
} catch (exeption) {
var d = "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXvoeWlnXfuDDxD0LIWf1tODuI3Wti5c3N2v73T19xj9fNAM45q8OWvY4cL-rRcVe0NisWEk9lZ0v4uuDUX4b54sx0uFOgNBRC6Gfoj7nUJaCh-JsZLVa-G-Nt0j5OrQ5vOfcCLsG-HqI/s72-c/nth.png"
}
// append dữ liệu
$(".sg-results").append("<div class='sg-item'><div class='sg-thumb'><a href='" + b + "'><img src='" + d + "'/></a></div><div class='sg-title'><a href='" + b + "'>" + c + "</a></div></div>")
}
};
}
function ajaxGet() { // hàm khởi tạo lấy 150 kết quả đầu
$.ajax({
url: "/feeds/posts/default",
type: "GET",
data: {
"alt": "json",
"max-results": 150, // important
},
dataType: "jsonp",
jsonpCallback: "getResults", // important
})
}
$(window).on("load", function() { // gửi request get dữ liệu sau khi trang tải xong trang
ajaxGet();
})
$(".sg-input").on("focus", function() { //khi người dùng focus vào ô input
$(".sg-close").show(); // hiện nút close
$(".sg-results").slideDown("500"); // hiện div suggest
});
$(".sg-input").on("keyup", function() { // sự kiện người dùng nhập từ khóa vào ô tìm kiếm
if ($(this).val().length > 0) { // nếu ô tìm kiếm có từ khóa
$(".sg-results").slideUp("500"); // ẩn div suggest
$(".sg-close").hide() // ẩn nút close
} else {
$(".sg-close").show(); // hiện nút close
$(".sg-results").slideDown("500"); // hiện div suggest
}
});
$(".sg-close").on("click", function() { // sự kiện đóng div suggest
$(".sg-results").slideUp("500");
$(this).hide()
});
//]]></script>
Như vậy qua bài này ta lại build được một tiện ích rất hay nữa từ blogger json feed api, và quan trọng hơn cả là bạn cần nắm chắc các kĩ thuật xử lý khi feeds bị giới hạn kết quả để tạo các widget dạng tổng hợp thống kê được thuận lợi
Good Luck !
1. Không vi phạm luật pháp nước CHXHCN Việt Nam
2. Không vi phạm thuần phong mỹ tục Việt Nam
3. Không bàn luận vấn đề liên quan đến tôn giáo, chính trị
4. Không đả kích, chửi bới hay đưa ra những lời nói không phù hợp với mục tiêu của website
5. Không bình luận với mục đích quảng cáo, trao đổi, mua bán
6. Khuyến khích sử dụng Tiếng Việt có dấu, hạn chế sử dụng tiếng lóng, viết tắt
7. Khi cần sự trợ giúp, vui lòng miêu tả chi tiết lỗi và để lại link đính kèm, tránh nói chung chung gây mất thời gian cho đôi bên