Labels

Blogger JSON Feed API - Dropdown Suggest Search


Một ứng dụng nữa của Blogger JSON Feed API đó là phục vụ cho tính năng search trên blog. Trong bài viết này tôi sẽ hướng dẫn bạn cách kết hợp widget label cùng json feed api để load bài viết mà không cần tải lại trang

Xem demo
demo

Để làm được điều này, ngoài kiến thức cơ bản về HTML, JS, CSS bạn cũng cần biết thêm về thẻ b:section và b:widget của blog để có thể can thiệp vào bố cục của blog.

Cách thức hoạt động của tiện ích này rất đơn giản, đó là bạn sử dụng widget label của blog để thống kê toàn bộ các nhãn hiện có, với mỗi lựa chọn label từ phía người dùng, ta sẽ get dữ liệu theo label đó để hiển thị ra thanh tìm kiếm.

Việc sử dụng method ajax get sẽ giúp bạn không cần phải chuyển trang để tìm kiếm bài đăng (/search/label/label-name) đồng thời cũng giúp người dùng có nhiều lựa chọn hơn khi vào trang của bạn mà không biết tìm gì và xem gì

Trong bài này tôi dùng font awesome 4.7, bạn tự tích hợp jQuery nhé

Tạo mới 1 section để chứa 1 widget label và 1 widget HTML (thường ta sẽ đặt nó nằm trong vùng header)

<b:section class='search-wrap' id='search-wrap' showaddelement='no'>
    <b:widget id='Label69' locked='false' title='Category' type='Label' version='1'>
        <b:widget-settings>
            <b:widget-setting name='sorting'>ALPHA</b:widget-setting>
            <b:widget-setting name='display'>LIST</b:widget-setting>
            <b:widget-setting name='selectedLabelsList' />
            <b:widget-setting name='showType'>ALL</b:widget-setting>
            <b:widget-setting name='showFreqNumbers'>false</b:widget-setting>
        </b:widget-settings>
        <b:includable id='main'>
            <div expr:class='&quot;widget-content &quot; + data:display + &quot;-label-widget-content&quot;'>
                <b:if cond='data:display == &quot;list&quot;'>
                    <div class='droplabel'>
                        <select class='dropdown-select'>
                                <option class="labdrop" title="Select category" value="0">
                                    Select category
                                </option>
                                <b:loop values='data:labels' var='label'>
                                    <option class='labdrop' expr:title='data:label.name' expr:value='data:label.name'>
                                     <data:label.name/> (<data:label.count/>)
                                    </option>
                                </b:loop>
                            </select>
                    </div>
                </b:if>
            </div>
        </b:includable>
    </b:widget>
    <b:widget id='HTML777' locked='true' title='Search' type='HTML' version='1'>
        <b:widget-settings>
            <b:widget-setting name='content'>
                <![CDATA[
                    <form autocomplete="off" id="hh-search-form" method="get" action="/search">
                    <div class="hh-search-wrap">
                        <input id="hh-search" name="q" type="text" required="" placeholder="Search ...">
                        <button id="hh-submit" type="submit"><i class="fa fa-search"></i></button>
                        <input name="max-results" type="hidden" value="20">
                        <div class="filter-label"></div>
                    </div>
                </form>
                    ]]>
            </b:widget-setting>
        </b:widget-settings>
        <b:includable id='main'>
            <div class='widget-content'>
                <data:content/>
            </div>
        </b:includable>
    </b:widget>
</b:section>

Nếu trùng id của widget label hoặc widget HTML bạn thay thành con số khác nhé

Viết css cơ bản giống demo (code chưa responsive và chỉ giống demo, khi bạn áp vào template chắc chắn sẽ bị ảnh hưởng css, bạn tự căn chỉnh sao cho hợp lý)

.search-wrap .widget{float:left}
.search-wrap .Label .list-label-widget-content .droplabel>select{border:1px solid #ddd;padding:5px 10px 4px;font-size:15px;max-width:170px;overflow:hidden;outline:none}
.search-wrap .HTML .hh-search-wrap{position:relative}
.search-wrap .HTML .hh-search-wrap #hh-search{outline:none;border-bottom:1px solid #ddd;border-top:1px solid #ddd;border-left:0;border-right:0;padding:6px 10px 5px;float:left;min-width:250px;font-size:15px;color:#000}
.search-wrap .HTML .hh-search-wrap #hh-search::-webkit-input-placeholder{color:#000}
.search-wrap .HTML .hh-search-wrap #hh-search:-moz-placeholder{color:#000;opacity:1}
.search-wrap .HTML .hh-search-wrap #hh-search::-moz-placeholder{color:#000;opacity:1}
.search-wrap .HTML .hh-search-wrap #hh-search:-ms-input-placeholder{color:#000}
.search-wrap .HTML .hh-search-wrap #hh-search::-ms-input-placeholder{color:#000}
.search-wrap .HTML .hh-search-wrap #hh-search::placeholder{color:#000}
.search-wrap .HTML .hh-search-wrap #hh-submit{outline:none;background:#f1f1f1;border:1px solid #ddd;padding:6px 20px 7px;cursor:pointer}
.search-wrap .HTML .hh-search-wrap #hh-submit:hover{background:#e6e6e6;-webkit-transition:all .3s ease;-moz-transition:all .3s ease;-ms-transition:all .3s ease;-o-transition:all .3s ease;transition:all .3s ease}
.filter-label{display:none;position:absolute;top:100%;padding:15px 15px 0 10px;border-top:0;border:1px solid #eee;left:-1px;width:92%;max-height:350px;overflow:auto}
.filter-label .filter-inner .filter-thumb{clear:both}
.filter-label .filter-inner .filter-thumb img{float:left;width:80px;height:55px;margin:0 12px 15px 0;border-radius:4px}
.filter-label .filter-inner .filter-title a{text-decoration:none;color:#000}
.filter-label .filter-inner .filter-title a:hover{color:#2187e7;-webkit-transition:all .3s ease;-moz-transition:all .3s ease;-ms-transition:all .3s ease;-o-transition:all .3s ease;transition:all .3s ease}

Code js trước thẻ đóng </body>

<script type='text/javascript'>//<![CDATA[
// Dropdown Suggest Search by Hung1001
$('.dropdown-select').on('change', function() {
    if (this.value != 0) {
        $('.filter-label').show().empty();
        $.ajax({
            url: '/feeds/posts/default/-/' + this.value,
            type: 'GET',
            dataType: 'jsonp',
            data: {
                alt: 'json',
                'max-results': 150,
            },
        }).done(function(e) {
            var r = '';
            for (var n = 0; n < e.feed.entry.length; n++) {
                for (var s = 0; s < e.feed.entry[n].link.length; s++) {
                    if (e.feed.entry[n].link[s].rel === "alternate") {
                        t = e.feed.entry[n].link[s].href;
                        break
                    }
                }
                f = e.feed.entry[n].title.$t;
                if ("media$thumbnail" in e.feed.entry[n]) {
                    d = e.feed.entry[n].media$thumbnail.url.replace("s72-c", "s640");
                } else {
                    d = "https://3.bp.blogspot.com/-Yw8BIuvwoSQ/VsjkCIMoltI/AAAAAAAAC4c/s55PW6xEKn0/s1600-r/nth.png"
                }
                r += "<div class='filter-inner'><div class='filter-thumb'><a href='" + t + "'><img src='" + d + "'/></a></div><div class='filter-title'><a title='" + f + "' href='" + t + "'>" + f + "</a></div></div>";
            }
            $('.filter-label').append(r);
            r = "";
        })
    } else {
        $('.filter-label').hide().empty();
    }
});
//]]></script>

Về mã xml và js bạn không cần chỉnh sửa, chủ yếu là css sao cho hợp lý với bố cục template của bạn

Về phần tải feed tôi chỉ lấy tối đa 150 bài đầu, như vậy các label có trên 150 bài viết các bài từ 151 trở đi sẽ không được liệt kê vào list suggest. Điều này nếu bạn đọc hết chuyên mục json feed api của tôi chắc sẽ biết xử lý như nào rồi

Cuối cùng bạn lưu mẫu lại và xem kết quả thu được

Như vậy bạn có thể thấy được những ứng dụng rất thực tế và đầy quý tộc mà blogger json feed mang lại, cái chính là ý tưởng ta nghĩ ra để có thể build những tiện ích đẹp độc lạ, mà các blog khác không có

Để lại bình luận nếu bạn gặp khó khăn và chúc thành công !
Bạn được tự do bày tỏ quan điểm nhưng nghiêm cấm spam
  • Chèn ảnh theo mẫu [img]link[/img]
  • Chèn video Youtube theo mẫu [youtube]link[/youtube]
  • Chèn code theo mẫu [pre]code[/pre]. Lưu ý: mã hóa code trước khi bình luận

  • 1