JavaScript >> Javascript 文檔 >  >> Tags >> CSS

使用 jQuery 的 Google 支持的站點搜索

到目前為止,Tutorialzine 的讀者最需要的功能之一是構建站點範圍的搜索。一種方法是從頭開始自己構建它。也就是說,使用像 PHP 這樣的服務器端語言並在您的數據庫上運行搜索查詢,將結果顯示給用戶。

另一種方法是使用一個已經了解每個人的一切的搜索引擎的服務。是的,你猜對了。在本教程中,我們將使用 Google 的 AJAX 搜索 API 創建一個自定義搜索引擎,您可以使用它在您的網站上搜索網絡結果、圖像、視頻和新聞項目。

HTML

讓我們從 HTML 標記開始。從新的 HTML5 文檔類型開始,我們繼續定義文檔的標題,並將樣式表包含到頁面的 head 部分。

search.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Google Powered Site Search | Tutorialzine Demo</title>

<link rel="stylesheet" type="text/css" href="styles.css" />

</head>
<body>

<div id="page">

    <h1>Google Powered Site Search</h1>

    <form id="searchForm" method="post">
        <fieldset>

            <input id="s" type="text" />

            <input type="submit" value="Submit" id="submitButton" />

            <div id="searchInContainer">
                <input type="radio" name="check" value="site" id="searchSite" checked />
                <label for="searchSite" id="siteNameLabel">Search</label>

                <input type="radio" name="check" value="web" id="searchWeb" />
                <label for="searchWeb">Search The Web</label>
            </div>

            <ul class="icons">
                <li class="web" title="Web Search" data-searchType="web">Web</li>
                <li class="images" title="Image Search" data-searchType="images">Images</li>
                <li class="news" title="News Search" data-searchType="news">News</li>
                <li class="videos" title="Video Search" data-searchType="video">Videos</li>
            </ul>

        </fieldset>
    </form>

    <div id="resultsDiv"></div>

</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="script.js"></script>
</body>
</html>

在正文部分,我們有主要的容器元素 - #page 分區。其中的表單不僅充當搜索表單,還充當容器。它具有 CSS3 圓角並應用了較深的背景顏色,這使得它更容易與頁面的其餘部分區分開來。

表單內部是文本輸入框,其後是用於在當前站點/網絡上搜索的單選組,以及四個搜索類型圖標,組織為無序列表。最後我們包括 jQuery 和我們的 scripts.js ,這將在本教程的最後一步中討論。

CSS

CSS 樣式位於 styles.css .這裡只包含更有趣的部分。

styles.css - 第 1 部分

#searchForm{
    /* The search form. */
    background-color:#4C5A65;
    padding:50px 50px 30px;
    margin:80px 0;
    position:relative;

    -moz-border-radius:16px;
    -webkit-border-radius:16px;
    border-radius:16px;
}

fieldset{
    border:none;
}

#s{
    /* The search text box. */

    border:none;
    color:#888888;
    background:url("img/searchBox.png") no-repeat;

    float:left;
    font-family:Arial,Helvetica,sans-serif;
    font-size:15px;
    height:36px;
    line-height:36px;
    margin-right:12px;
    outline:medium none;
    padding:0 0 0 35px;
    text-shadow:1px 1px 0 white;
    width:385px;
}

如上所述,表單的功能不僅限於提交數據,還可以充當常規容器元素。這樣可以最大限度地減少頁面上的標記,同時仍然提供豐富的功能。

文本輸入框,#s , 使用背景圖片和填充設置樣式,以便文本不會覆蓋放大鏡。

styles.css - 第 2 部分

.icons{
    list-style:none;
    margin:10px 0 0 335px;
    height:19px;
    position:relative;
}

.icons li{
    background:url("img/icons.png") no-repeat;
    float:left;
    height:19px;
    text-indent:-999px;
    cursor:pointer;
    margin-right:5px;
}

/* Styling each icon */

li.web{ width:15px;}
li.web.active,
li.web:hover{ background-position:left bottom;}

li.images{ width:22px; background-position:-18px 0;}
li.images.active,
li.images:hover{ background-position:-18px bottom;}

li.news{ width:14px; background-position:-44px 0;}
li.news.active,
li.news:hover{ background-position:-44px bottom;}

li.videos{ width:17px; background-position:right 0;}
li.videos.active,
li.videos:hover{ background-position:right bottom;}

span.arrow{
    /* The little arrow that moves below the icons */

    width:11px;
    height:6px;
    margin:21px 0 0 5px;
    position:absolute;
    background:url('img/arrow.png') no-repeat;
    left:0;
}

/* The submit button */

#submitButton{
    background:url('img/buttons.png') no-repeat;
    width:83px;
    height:36px;
    text-indent:-9999px;
    overflow:hidden;
    text-transform:uppercase;
    border:none;
    cursor:pointer;
}

#submitButton:hover{
    background-position:left bottom;
}

在上面的片段中,您可以看到搜索類型圖標都共享一個背景圖像。它與背景位置發生偏移,因此無論是默認狀態還是懸停狀態,都會顯示它的適當部分。

提交按鈕使用相同的技術。它的文本用否定的 text-indent 隱藏 , 和 buttons.png 顯示為其背景,默認情況下圖像的頂部可見,懸停時顯示底部。

styles.css - 第 3 部分

/* Web & news results */

.webResult{ text-shadow:1px 1px 0 #586a75;margin-bottom:50px;}
.webResult h2{
    background-color:#5D6F7B;
    font-size:18px;
    font-weight:normal;
    padding:8px 20px;

    /* Applying CSS3 rounded corners */
    -moz-border-radius:18px;
    -webkit-border-radius:18px;
    border-radius:18px;
}
.webResult h2 b{ color:#fff; }
.webResult h2 a{ color:#eee;border:none;}
.webResult p{ line-height:1.5;padding:15px 20px;}
.webResult p b{ color:white;}
.webResult > a{ margin-left:20px;}

/* Image & video search results */

.imageResult{
    float:left;
    height:170px;
    margin:0 0 20px 40px;
    text-align:center;
    width:150px;
}
.imageResult img{ display:block;border:none;}
.imageResult a.pic{
    border:1px solid #fff;
    outline:1px solid #777;
    display:block;
    margin:0 auto 15px;
}

/* The show more button */

#more{
    width:83px;
    height:24px;
    background:url('img/more.png') no-repeat;
    cursor:pointer;
    margin:40px auto;
}

#more:hover{
    background-position:left bottom;
}

在最後一個片段中,我們為結果設置樣式。雖然我們展示了四種類型的搜索結果 - 網絡、新聞、圖像和視頻,但它們僅由上述兩個類設置樣式 - .webResult.imageResult .最後,我們為 #more 設置樣式 按鈕,由jQuery根據谷歌返回的結果動態添加到頁面中。

jQuery

如開頭所述,此應用程序使用 Google 的 AJAX 搜索 API。 Google 確實提供了他們自己的 JavaScript 庫,但如果您選擇使用它,您會受到他們 UI 的限制。雖然功能齊全,但它可能不是您想為訪問者提供的。這就是為什麼在本教程中,我們使用“裸版本”,通過 jQuery 直接向其 API 發出 JSONp 調用。

在我們開始討論 jQuery 代碼之前,讓我們先來看看在我們使用 API 運行搜索之後,Google 為我們提供了哪些數據。

來自 Google API 的示例結果

{
    "GsearchResultClass": "GwebSearch",
    "unescapedUrl": "https://tutorialzine.com/2010/02/html5-css3-website-template/",
    "url": "https://tutorialzine.com/2010/02/html5-css3-website-template/",
    "visibleUrl": "tutorialzine.com",
    "cacheUrl": "http://www.google.com/search?q=cache:_NSLxH-cQMAJ:tutorialzine.com",
    "title": "Coding a <b>CSS3</b> & <b>HTML5</b> One-Page Website Template | Tutorialzine",
    "titleNoFormatting": "Coding a CSS3 & HTML5 One-Page Website Template | Tutorialzine",
    "content": "Feb 16, 2010 <b>...</b> Here we are using the new version of HTML.."
}

通過他們的 API 運行的搜索將返回您通常直接從他們的網站獲得的相同結果集。不同之處在於,這裡我們得到了一個 JavaScript 數組,其中填充了上述對象。這些對像中的每一個都包含搜索類型、標題、URL 以及包含我們正在搜索的術語的頁面中的文本。

使用 GsearchResultClass 屬性,我們可以確定如何顯示信息,稍後您將看到。此搜索應用僅支持網絡、圖片、新聞和視頻搜索,但您可以在 Google 的 AJAX 搜索文檔中查看可用搜索類型的完整列表。

script.js - 第 1 部分

$(document).ready(function(){

    var config = {
        siteURL     : 'tutorialzine.com',   // Change this to your site
        searchSite  : true,
        type        : 'web',
        append      : false,
        perPage     : 8,            // A maximum of 8 is allowed by Google
        page        : 0             // The start page
    }

    // The small arrow that marks the active search icon:
    var arrow = $('<span>',{className:'arrow'}).appendTo('ul.icons');

    $('ul.icons li').click(function(){
        var el = $(this);

        if(el.hasClass('active')){
            // The icon is already active, exit
            return false;
        }

        el.siblings().removeClass('active');
        el.addClass('active');

        // Move the arrow below this icon
        arrow.stop().animate({
            left        : el.position().left,
            marginLeft  : (el.width()/2)-4
        });

        // Set the search type
        config.type = el.attr('data-searchType');
        $('#more').fadeOut();
    });

    // Adding the site domain as a label for the first radio button:
    $('#siteNameLabel').append(' '+config.siteURL);

    // Marking the Search tutorialzine.com radio as active:
    $('#searchSite').click();   

    // Marking the web search icon as active:
    $('li.web').click();

    // Focusing the input text box:
    $('#s').focus();

    $('#searchForm').submit(function(){
        googleSearch();
        return false;
    });

    $('#searchSite,#searchWeb').change(function(){
        // Listening for a click on one of the radio buttons.
        // config.searchSite is either true or false.

        config.searchSite = this.id == 'searchSite';
    });

配置 對象包含一般配置選項,例如站點 URL、起始頁(用於分頁)和默認搜索類型(網絡搜索)。谷歌只允許我們一次選擇 8 個結果,這對於網絡搜索來說已經足夠了,但對於圖像來說就不行了。讓我們希望谷歌將來會提高這個限制。

當表單提交時,jQuery 調用我們的 googleSearch() 函數,你可以在下面看到。

script.js - 第 2 部分

  function googleSearch(settings){

        // If no parameters are supplied to the function,
        // it takes its defaults from the config object above:

        settings = $.extend({},config,settings);
        settings.term = settings.term || $('#s').val();

        if(settings.searchSite){
            // Using the Google site:example.com to limit the search to a
            // specific domain:
            settings.term = 'site:'+settings.siteURL+' '+settings.term;
        }

        // URL of Google's AJAX search API
        var apiURL = 'http://ajax.googleapis.com/ajax/services/search/'+settings.type+
                        '?v=1.0&callback=?';
        var resultsDiv = $('#resultsDiv');

        $.getJSON(apiURL,{
            q   : settings.term,
            rsz : settings.perPage,
            start   : settings.page*settings.perPage
        },function(r){

            var results = r.responseData.results;
            $('#more').remove();

            if(results.length){

                // If results were returned, add them to a pageContainer div,
                // after which append them to the #resultsDiv:

                var pageContainer = $('<div>',{className:'pageContainer'});

                for(var i=0;i<results.length;i++){
                    // Creating a new result object and firing its toString method:
                    pageContainer.append(new result(results[i]) + '');
                }

                if(!settings.append){
                    // This is executed when running a new search,
                    // instead of clicking on the More button:
                    resultsDiv.empty();
                }

                pageContainer.append('<div class="clear"></div>')
                             .hide().appendTo(resultsDiv)
                             .fadeIn('slow');

                var cursor = r.responseData.cursor;

                // Checking if there are more pages with results,
                // and deciding whether to show the More button:

                if( +cursor.estimatedResultCount > (settings.page+1)*settings.perPage){
                    $('<div>',{id:'more'}).appendTo(resultsDiv).click(function(){
                        googleSearch({append:true,page:settings.page+1});
                        $(this).fadeOut();
                    });
                }
            }
            else {

                // No results were found for this search.

                resultsDiv.empty();
                $('<p>',{
                    className   : 'notFound',
                    html        : 'No Results Were Found!'
                }).hide().appendTo(resultsDiv).fadeIn();
            }
        });
    }

googleSearch() 函數向 Google 的 API 發送 JSONp 請求,生成結果標記,並將其插入到 #resultsDiv 分區。它可以預先清空該 div(如果我們正在重新搜索)或附加結果(當我們單擊“更多”按鈕時會發生這種情況)。

兩條路徑遵循相同的邏輯 - 一個新的 .pageContainer 為每組結果創建 div(這個 div 有一個底部邊框,因此更容易區分一頁結果和下一頁結果)和 result 的對象 類(你可以在下面看到這個類),被初始化並且它的標記被附加到 pageContainer。

script.js - 第 3 部分

  function result(r){

        // This is class definition. Object of this class are created for
        // each result. The markup is generated by the .toString() method.

        var arr = [];

        // GsearchResultClass is passed by the google API
        switch(r.GsearchResultClass){

            case 'GwebSearch':
                arr = [
                    '<div class="webResult">',
                    '<h2><a href="',r.url,'">',r.title,'</a></h2>',
                    '<p>',r.content,'</p>',
                    '<a href="',r.url,'">',r.visibleUrl,'</a>',
                    '</div>'
                ];
            break;
            case 'GimageSearch':
                arr = [
                    '<div class="imageResult">',
                    '<a href="',r.url,'" title="',r.titleNoFormatting,
                    '" class="pic" style="width:',r.tbWidth,'px;height:',r.tbHeight,'px;">',
                    '<img src="',r.tbUrl,'" width="',r.tbWidth,'" height="',
                    r.tbHeight,'" /></a>','<div class="clear"></div>',
                    '<a href="',r.originalContextUrl,'">',r.visibleUrl,'</a>',
                    '</div>'
                ];
            break;
            case 'GvideoSearch':
                arr = [
                    '<div class="imageResult">',
                    '<a href="',r.url,'" title="',r.titleNoFormatting,'
                    " class="pic" style="width:150px;height:auto;">',
                    '<img src="',r.tbUrl,'" width="100%" /></a>',
                    '<div class="clear"></div>','<a href="',
                    r.originalContextUrl,'">',r.publisher,'</a>',
                    '</div>'
                ];
            break;
            case 'GnewsSearch':
                arr = [
                    '<div class="webResult">',
                    '<h2><a href="',r.unescapedUrl,'">',r.title,'</a></h2>',
                    '<p>',r.content,'</p>',
                    '<a href="',r.unescapedUrl,'">',r.publisher,'</a>',
                    '</div>'
                ];
            break;
        }

        // The toString method.
        this.toString = function(){
            return arr.join('');
        }
    }
});

此函數充當 result 的構造函數 班級。它獲取從 Google 的 API(您在 jQuery 步驟開始時看到的)返回的對象並初始化 arr 根據 GsearchResultClass 的值。請注意,arr 被分配一個數組而不是一個字符串。這比將多個字符串串聯在一起要快一些。

在類的底部,我們有 toString() 方法。它基本上調用了數組的內部 join 方法,把它變成一個字符串。 toString() 是一個神奇的方法,它在 script.js - Part 2 的 38 行隱式調用 .

這樣,我們自己的 Google 搜索引擎就完成了!

結論

配置此應用程序以搜索您的網站非常簡單。只需更改 siteURL 配置的屬性 script.js 中的對象。有很多方法可以改進這個例子。當前並未顯示所有來自 Google 的數據。您也可以使用 filetype: 搜索修飾符來查找特定類型的文件。

在評論部分分享您提出的所有有趣想法。


Tutorial JavaScript 教程
  1. 在 GatsbyJS 上獲取 URL 參數

  2. 如何使用 NEXTJS 和 Tailwind CSS(如 STRIPE.COM)創建漂亮的導航欄。

  3. 在 Remix 中渲染降價

  4. 您的 Next.js 應用程序的快速安全勝利

  5. 使用 React Hooks 將數據與 UI 分離

  6. 如何在 React Firebase 中使用 Redux

  7. 使用 Gatsby 函數和 Stripe 將開源軟件貨幣化

  1. 為什麼密碼驗證在 vuetify 的設置中不起作用?

  2. 代碼和 Scrum 100 天的第 57 天:將 Next.js 連接到 Ghost Headless CMS

  3. 嘗試將值輸入第一個空單元格時出現“找不到範圍”

  4. 重新設計我們的產品教會了我們如何在 React 中優化視頻通話性能

  5. 在 React 應用程序中模擬隔離服務

  6. 使用 GitHub Actions 和 Snyk 進行 CI

  7. 立即開始使用 HTML5 WebSockets

  1. 現代 Web 開發設置 #1

  2. ⬢ 節點任務列表

  3. 高級 JavaScript 系列 - 第 8 部分:2 個支柱~ 閉包和原型繼承

  4. 使用 GitHub Actions 在共享主機上持續部署