Sdílet prostřednictvím


Kurz: Nahrání obrázků do rozhraní API pro vizuální vyhledávání Bingu

Upozornění

30. října 2020 se rozhraní API Vyhledávání Bingu přesunula ze služeb Azure AI na Vyhledávání Bingu Services. Tato dokumentace je k dispozici pouze pro referenci. Aktualizovanou dokumentaci najdete v dokumentaci k rozhraní API bingu pro vyhledávání. Pokyny k vytváření nových prostředků Azure pro vyhledávání Bingem najdete v tématu Vytvoření prostředku Vyhledávání Bingu prostřednictvím Azure Marketplace.

Rozhraní API vizuálního vyhledávání Bingu umožňuje hledat na webu obrázky podobné těm, které nahrajete. V tomto kurzu můžete vytvořit webovou aplikaci, která může odeslat obrázek do rozhraní API a zobrazit přehledy, které vrací na webové stránce. Všimněte si, že tato aplikace nesplňuje všechny požadavky na použití a zobrazení Bingu pro použití rozhraní API.

Úplný zdrojový kód pro tuto ukázku s dalšími chybami a poznámkami najdete na GitHubu.

Ukázková aplikace předvádí, jak:

  • Nahrání obrázku do rozhraní API pro vizuální vyhledávání Bingu
  • Zobrazení výsledků hledání obrázků ve webové aplikaci
  • Prozkoumání různých přehledů poskytovaných rozhraním API

Požadavky

Vytvoření prostředku Azure

Začněte používat rozhraní API Bingu pro vizuální vyhledávání vytvořením jednoho z následujících prostředků Azure:

prostředek Vyhledávání Bingu v7

  • Dostupné prostřednictvím Azure Portal, dokud prostředek neodstraníte.
  • Vyberte cenovou S9 úroveň.

Prostředek s více službami

  • Dostupné prostřednictvím Azure Portal, dokud prostředek neodstraníte.
  • Pro aplikace používejte stejný klíč a koncový bod napříč několika službami Azure AI.

Vytvoření a struktura webové stránky

Vytvořte stránku HTML, která odešle obrázek do rozhraní API Vizuálního vyhledávání Bingu, získá přehledy a zobrazí je. V oblíbeném editoru nebo integrovaném vývojovém prostředí (IDE) vytvořte soubor s názvem "uploaddemo.html". Přidejte do souboru následující základní strukturu HTML:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Visual Search Upload Demo</title>
    </head>

    <body>
    </body>
</html>

Rozdělte stránku na oddíl požadavku, ve kterém uživatel poskytne všechny informace požadované pro požadavek, a část odpovědi, kde se zobrazí přehledy. Přidejte do souboru následující <div> značky <body>. Značka <hr> vizuálně odděluje oddíl požadavku od oddílu odpovědi:

<div id="requestSection"></div>
<hr />
<div id="responseSection"></div>

<script> Přidejte do značky <head> značku, která bude obsahovat JavaScript pro aplikaci:

<script>
<\script>

Získání nahrání souboru

Aby uživatel vybral obrázek k nahrání, aplikace použije <input> značku s atributem type nastaveným na file. V uživatelském rozhraní musí být jasné, že aplikace k získání výsledků hledání používá Bing.

Do souboru přidejte následující kód <div>requestSection<div>. Vstup souboru přijímá jeden soubor libovolného typu obrázku (například .jpg, .gif, .png). Událost onchange určuje obslužnou rutinu, která je volána, když uživatel vybere soubor.

Značka <output> slouží k zobrazení miniatury vybraného obrázku:

<div>
    <p>Select image to get insights from Bing:
        <input type="file" accept="image/*" id="uploadImage" name="files[]" size=40 onchange="handleFileSelect('uploadImage')" />
    </p>

    <output id="thumbnail"></output>
</div>

Vytvoření obslužné rutiny souboru

Vytvořte funkci obslužné rutiny, která může číst obrázek, který chcete nahrát. Při iteraci souborů v objektu FileList by se obslužná rutina měla ujistit, že vybraný soubor je soubor obrázku a že jeho velikost je menší než 1 MB. Pokud je obrázek větší, musíte před nahráním zmenšit jeho velikost. Nakonec obslužná rutina zobrazí miniaturu obrázku:

function handleFileSelect(selector) {

    var files = document.getElementById(selector).files; // A FileList object

    for (var i = 0, f; f = files[i]; i++) {

        // Ensure the file is an image file.
        if (!f.type.match('image.*')) {
            alert("Selected file must be an image file.");
            document.getElementById("uploadImage").value = null;
            continue;
        }

        // Image must be <= 1 MB and should be about 1500px.
        if (f.size > 1000000) {
            alert("Image must be less than 1 MB.");
            document.getElementById("uploadImage").value = null;
            continue;
        }

        var reader = new FileReader();

        // Capture the file information.
        reader.onload = (function(theFile) {
            return function(e) {
                var fileOutput = document.getElementById('thumbnail');

                if (fileOutput.childElementCount > 0) {
                    fileOutput.removeChild(fileOutput.lastChild);  // Remove the current pic, if it exists
                }

                // Render thumbnail.
                var span = document.createElement('span');
                span.innerHTML = ['<img class="thumb" src="', e.target.result,
                                    '" title="', escape(theFile.name), '"/>'].join('');
                fileOutput.insertBefore(span, null);
            };
        })(f);

        // Read in the image file as a data URL.
        reader.readAsDataURL(f);
    }
}

Přidání a uložení klíče předplatného

Aplikace vyžaduje klíč předplatného pro volání rozhraní API Bingu pro vizuální vyhledávání. Pro účely tohoto kurzu ji poskytnete v uživatelském rozhraní. Přidejte následující <input> značku (s atributem type nastaveným na text) přímo <body> pod značku souboru <output> :

    <div>
        <p>Subscription key: 
            <input type="text" id="key" name="subscription" size=40 maxlength="32" />
        </p>
    </div>

Pomocí obrázku a klíče předplatného můžete volat vizuální vyhledávání Bingu, abyste získali přehledy o obrázku. V tomto kurzu volání použije výchozí tržní hodnotu (en-us) a bezpečnou hodnotu hledání (moderate).

Tato aplikace má možnost tyto hodnoty změnit. Pod klíč předplatného přidejte následující <div> kód <div>. Aplikace používá <select> značku k poskytnutí rozevíracího seznamu pro tržní a bezpečné vyhledávací hodnoty. Oba seznamy zobrazují výchozí hodnotu.

<div>
    <p><a href="#" onclick="expandCollapse(options.id)">Query options</a></p>

    <div id="options" style="display:none">
        <p style="margin-left: 20px">Market: 
            <select id="mkt">
                <option value="es-AR">Argentina (Spanish)</option>
                <option value="en-AU">Australia (English)</option>
                <option value="de-AT">Austria (German)</option>
                <option value="nl-BE">Belgium (Dutch)</option>
                <option value="fr-BE">Belgium (French)</option>
                <option value="pt-BR">Brazil (Portuguese)</option>
                <option value="en-CA">Canada (English)</option>
                <option value="fr-CA">Canada (French)</option>
                <option value="es-CL">Chile (Spanish)</option>
                <option value="da-DK">Denmark (Danish)</option>
                <option value="fi-FI">Finland (Finnish)</option>
                <option value="fr-FR">France (French)</option>
                <option value="de-DE">Germany (German)</option>
                <option value="zh-HK">Hong Kong SAR(Traditional Chinese)</option>
                <option value="en-IN">India (English)</option>
                <option value="en-ID">Indonesia (English)</option>
                <option value="it-IT">Italy (Italian)</option>
                <option value="ja-JP">Japan (Japanese)</option>
                <option value="ko-KR">Korea (Korean)</option>
                <option value="en-MY">Malaysia (English)</option>
                <option value="es-MX">Mexico (Spanish)</option>
                <option value="nl-NL">Netherlands (Dutch)</option>
                <option value="en-NZ">New Zealand (English)</option>
                <option value="no-NO">Norway (Norwegian)</option>
                <option value="zh-CN">People's Republic of China (Chinese)</option>
                <option value="pl-PL">Poland (Polish)</option>
                <option value="pt-PT">Portugal (Portuguese)</option>
                <option value="en-PH">Philippines (English)</option>
                <option value="ru-RU">Russia (Russian)</option>
                <option value="ar-SA">Saudi Arabia (Arabic)</option>
                <option value="en-ZA">South Africa (English)</option>
                <option value="es-ES">Spain (Spanish)</option>
                <option value="sv-SE">Sweden (Swedish)</option>
                <option value="fr-CH">Switzerland (French)</option>
                <option value="de-CH">Switzerland (German)</option>
                <option value="zh-TW">Taiwan (Traditional Chinese)</option>
                <option value="tr-TR">Türkiye (Turkish)</option>
                <option value="en-GB">United Kingdom (English)</option>
                <option value="en-US" selected>United States (English)</option>
                <option value="es-US">United States (Spanish)</option>
            </select>
        </p>
        <p style="margin-left: 20px">Safe search: 
            <select id="safesearch">
                <option value="moderate" selected>Moderate</option>
                <option value="strict">Strict</option>
                <option value="off">off</option>
            </select>
        </p>
    </div>
</div>

Přidání možností hledání na webovou stránku

Aplikace skryje seznamy ve sbalitelném <div> zařízení, které je řízeno odkazem Možnosti dotazu. Když kliknete na odkaz Možnosti dotazu, rozbalí se, <div> abyste mohli zobrazit a upravit možnosti dotazu. Pokud znovu kliknete na odkaz Možnosti dotazu, <div> sbalí se a skryje se. Následující fragment kódu ukazuje obslužnou rutinu onclick odkazu Možnosti dotazu. Obslužná rutina určuje, jestli <div> je rozbalený nebo sbalený. Přidejte tuto obslužnou rutinu do oddílu <script> . Obslužnou rutinu používají všechny sbalitelné <div> oddíly v ukázce.

// Contains the toggle state of divs.
var divToggleMap = {};  // divToggleMap['foo'] = 0;  // 1 = show, 0 = hide


// Toggles between showing and hiding the specified div.
function expandCollapse(divToToggle) {
    var div = document.getElementById(divToToggle);

    if (divToggleMap[divToToggle] == 1) {   // if div is expanded
        div.style.display = "none";
        divToggleMap[divToToggle] = 0;
    }
    else {                                  // if div is collapsed
        div.style.display = "inline-block";
        divToggleMap[divToToggle] = 1;
    }
}

Volání obslužné rutiny onclick

Pod možnosti <div> v textu přidejte následující "Get insights" tlačítko. Tlačítko umožňuje zahájit hovor. Po kliknutí na tlačítko se kurzor změní na rotující čekací kurzor a obslužná rutina onclick je volána.

<p><input type="button" id="query" value="Get insights" onclick="document.body.style.cursor='wait'; handleQuery()" /></p>

Přidejte obslužnou rutinu onclickhandleQuery() tlačítka do značky <script> .

Zpracování dotazu

Obslužná rutina handleQuery() zajišťuje, že klíč předplatného je k dispozici a má délku 32 znaků a že je vybrán obrázek. Vymaže také všechny přehledy z předchozího dotazu. Poté zavolá sendRequest() funkci, která provede volání.

function handleQuery() {
    var subscriptionKey = document.getElementById('key').value;

    // Make sure user provided a subscription key and image.
    // For this demo, the user provides the key but typically you'd
    // get it from secured storage.
    if (subscriptionKey.length !== 32) {
        alert("Subscription key length is not valid. Enter a valid key.");
        document.getElementById('key').focus();
        return;
    }

    var imagePath = document.getElementById('uploadImage').value;

    if (imagePath.length === 0)
    {
        alert("Please select an image to upload.");
        document.getElementById('uploadImage').focus();
        return;
    }

    var responseDiv = document.getElementById('responseSection');

    // Clear out the response from the last query.
    while (responseDiv.childElementCount > 0) {
        responseDiv.removeChild(responseDiv.lastChild);
    }

    // Send the request to Bing to get insights about the image.
    var f = document.getElementById('uploadImage').files[0];
    sendRequest(f, subscriptionKey);
}

Odeslání žádosti o hledání

Funkce sendRequest() naformátuje adresu URL koncového bodu, nastaví hlavičku Ocp-Apim-Subscription-Key na klíč předplatného, připojí binární soubor obrázku, který se má nahrát, určí obslužnou rutinu odpovědi a provede volání:

function sendRequest(file, key) {
    var market = document.getElementById('mkt').value;
    var safeSearch = document.getElementById('safesearch').value;
    var baseUri = `https://api.cognitive.microsoft.com/bing/v7.0/images/visualsearch?mkt=${market}&safesearch=${safeSearch}`;

    var form = new FormData();
    form.append("image", file);

    var request = new XMLHttpRequest();

    request.open("POST", baseUri);
    request.setRequestHeader('Ocp-Apim-Subscription-Key', key);
    request.addEventListener('load', handleResponse);
    request.send(form);
}

Získání a zpracování odpovědi rozhraní API

Funkce handleResponse() zpracovává odpověď z volání vizuálního vyhledávání Bingu. Pokud je volání úspěšné, naparsuje odpověď JSON do jednotlivých značek, které obsahují přehledy. Dále přidá výsledky hledání na stránku. Aplikace pak pro každou značku vytvoří sbalitelné <div> , aby bylo možné spravovat, kolik dat se zobrazí. Přidejte obslužnou rutinu do oddílu <script> .

function handleResponse() {
    if(this.status !== 200){
        alert("Error calling Bing Visual Search. See console log for details.");
        console.log(this.responseText);
        return;
    }

    var tags = parseResponse(JSON.parse(this.responseText));
    var h4 = document.createElement('h4');
    h4.textContent = 'Bing internet search results';
    document.getElementById('responseSection').appendChild(h4);
    buildTagSections(tags);

    document.body.style.cursor = 'default'; // reset the wait cursor set by query insights button
}

Parsování odpovědi

Funkce parseResponse převede odpověď JSON na objekt slovníku iterací přes json.tags.

function parseResponse(json) {
    var dict = {};

    for (var i =0; i < json.tags.length; i++) {
        var tag = json.tags[i];

        if (tag.displayName === '') {
            dict['Default'] = JSON.stringify(tag);
        }
        else {
            dict[tag.displayName] = JSON.stringify(tag);
        }
    }

    return(dict);
}

Vytvoření oddílu značek

Funkce buildTagSections() iteruje parsované značky JSON a zavolá buildDiv() funkci, která pro každou značku vytvoří <div> . Každá značka se zobrazí jako odkaz. Po kliknutí na odkaz se značka rozbalí a zobrazí přehledy přidružené ke značce. Když na odkaz kliknete znovu, oddíl se sbalí.

function buildTagSections(tags) {
    for (var tag in tags) {
        if (tags.hasOwnProperty(tag)) {
            var tagSection = buildDiv(tags, tag);
            document.getElementById('responseSection').appendChild(tagSection);
        }
    }  
}

function buildDiv(tags, tag) {
    var tagSection = document.createElement('div');
    tagSection.setAttribute('class', 'subSection');

    var link = document.createElement('a');
    link.setAttribute('href', '#');
    link.setAttribute('style', 'float: left;')
    link.text = tag;
    tagSection.appendChild(link);

    var contentDiv = document.createElement('div');
    contentDiv.setAttribute('id', tag);
    contentDiv.setAttribute('style', 'clear: left;')
    contentDiv.setAttribute('class', 'section');
    tagSection.appendChild(contentDiv);

    link.setAttribute('onclick', `expandCollapse("${tag}")`);
    divToggleMap[tag] = 0;  // 1 = show, 0 = hide

    addDivContent(contentDiv, tag, tags[tag]);

    return tagSection;
}

Zobrazení výsledků hledání na webové stránce

Funkce buildDiv() volá addDivContent funkci, aby sestavila obsah sbalitelné <div>značky .

Obsah značky zahrnuje kód JSON z odpovědi pro značku. Zpočátku se zobrazí jenom prvních 100 znaků JSON, ale kliknutím na řetězec JSON můžete zobrazit všechny kódy JSON. Pokud na něj kliknete znovu, řetězec JSON se sbalí zpět na 100 znaků.

V dalším kroku přidejte typy akcí nalezené ve značce. Pro každý typ akce zavolejte příslušné funkce a přidejte jejich přehledy:

function addDivContent(div, tag, json) {

    // Adds the first 100 characters of the json that contains
    // the tag's data. The user can click the text to show the
    // full json. They can click it again to collapse the json.
    var para = document.createElement('p');
    para.textContent = String(json).substr(0, 100) + '...';
    para.setAttribute('title', 'click to expand');
    para.setAttribute('style', 'cursor: pointer;')
    para.setAttribute('data-json', json);
    para.addEventListener('click', function(e) {
        var json = e.target.getAttribute('data-json');

        if (e.target.textContent.length <= 103) {  // 100 + '...'
            e.target.textContent = json;
            para.setAttribute('title', 'click to collapse');
        }
        else {
            para.textContent = String(json).substr(0, 100) + '...';
            para.setAttribute('title', 'click to expand');
        }
    });
    div.appendChild(para); 

    var parsedJson = JSON.parse(json);

    // Loop through all the actions in the tag and display them.
    for (var j = 0; j < parsedJson.actions.length; j++) {
        var action = parsedJson.actions[j];

        var subSectionDiv = document.createElement('div');
        subSectionDiv.setAttribute('class', 'subSection');
        div.appendChild(subSectionDiv);

        var h4 = document.createElement('h4');
        h4.innerHTML = action.actionType;
        subSectionDiv.appendChild(h4);

        if (action.actionType === 'ImageResults') {
            addImageWithWebSearchUrl(subSectionDiv, parsedJson.image, action);
        }
        else if (action.actionType === 'DocumentLevelSuggestions') {
            addRelatedSearches(subSectionDiv, action.data.value);
        }
        else if (action.actionType === 'RelatedSearches') {
            addRelatedSearches(subSectionDiv, action.data.value);
        }
        else if (action.actionType === 'PagesIncluding') {
            addPagesIncluding(subSectionDiv, action.data.value);
        }
        else if (action.actionType === 'VisualSearch') {
            addRelatedImages(subSectionDiv, action.data.value);
        }
        else if (action.actionType === 'Recipes') {
            addRecipes(subSectionDiv, action.data.value);
        }
        else if (action.actionType === 'ShoppingSources') {
            addShopping(subSectionDiv, action.data.offers);
        }
        else if (action.actionType === 'ProductVisualSearch') {
            addProducts(subSectionDiv, action.data.value);
        }
        else if (action.actionType === 'TextResults') {
            addTextResult(subSectionDiv, action);
        }
        else if (action.actionType === 'Entity') {
            addEntity(subSectionDiv, action);
        }
    }
}

Zobrazení přehledů pro různé akce

Následující funkce zobrazují přehledy pro různé akce. Funkce poskytují obrázek s možností kliknutí nebo odkaz s možností kliknutí, který vás pošle na webovou stránku s dalšími informacemi o obrázku. Tuto stránku hostuje Bing.com nebo původní web obrázku. V této aplikaci se nezobrazují všechna data přehledů. Pokud chcete zobrazit všechna pole dostupná pro přehled, podívejte se na referenční informace k obrázkům – vizuální vyhledávání .

Poznámka

Na stránce musíte zobrazit minimální množství informací o přehledech. Další informace najdete v požadavcích na použití a zobrazení rozhraní API Vyhledávání Bingu.

Přehledy RelatedImages

Funkce addRelatedImages() vytvoří název pro každý web, který je hostitelem souvisejícího obrázku, iterací seznamu RelatedImages akcí a přidáním <img> značky ven <div> pro každou z nich:

    function addRelatedImages(div, images) {
        var length = (images.length > 10) ? 10 : images.length;

        // Set the title to the website that hosts the image. The title displays
        // when the user hovers over the image.

        // Make the image clickable. If the user clicks the image, they're taken
        // to the image in Bing.com.

        for (var j = 0; j < length; j++) {
            var img = document.createElement('img');
            img.setAttribute('src', images[j].thumbnailUrl + '&w=120&h=120');
            img.setAttribute('style', 'margin: 20px 20px 0 0; cursor: pointer;');
            img.setAttribute('title', images[j].hostPageDisplayUrl);
            img.setAttribute('data-webSearchUrl', images[j].webSearchUrl)

            img.addEventListener('click', function(e) {
                var url = e.target.getAttribute('data-webSearchUrl');
                window.open(url, 'foo');
            })

            div.appendChild(img);
        }
    }

StránkyZačtené přehledy

Funkce addPagesIncluding() vytvoří odkaz pro každý web hostující nahraný obrázek tak, že iteruje seznam akcí a připojí <img> značku ven <div> pro každý z PagesIncluding nich:


    // Display links to the first 5 webpages that include the image.
    // TODO: Add 'more' link in case the user wants to see all of them.
    function addPagesIncluding(div, pages) {
        var length = (pages.length > 5) ? 5 : pages.length;

        for (var j = 0; j < length; j++) {
            var page = document.createElement('a');
            page.text = pages[j].name;
            page.setAttribute('href', pages[j].hostPageUrl);
            page.setAttribute('style', 'margin: 20px 20px 0 0');
            page.setAttribute('target', '_blank')
            div.appendChild(page);

            div.appendChild(document.createElement('br'));
        }
    }

Přehledy relatedSearches

Funkce addRelatedSearches() vytvoří odkaz na web, který je hostitelem obrázku, iterací seznamu akcí a přidáním značky <img> ven <div> pro každou z RelatedSearches nich:


    // Display the first 10 related searches. Include a link with the image
    // that when clicked, takes the user to Bing.com and displays the 
    // related search results.
    // TODO: Add 'more' link in case the user wants to see all of them.
    function addRelatedSearches(div, relatedSearches) {
        var length = (relatedSearches.length > 10) ? 10 : relatedSearches.length;

        for (var j = 0; j < length; j++) {
            var childDiv = document.createElement('div');
            childDiv.setAttribute('class', 'stackLink');
            div.appendChild(childDiv);

            var img = document.createElement('img');
            img.setAttribute('src', relatedSearches[j].thumbnail.url + '&w=120&h=120');
            img.setAttribute('style', 'margin: 20px 20px 0 0;');
            childDiv.appendChild(img);

            var relatedSearch = document.createElement('a');
            relatedSearch.text = relatedSearches[j].displayText;
            relatedSearch.setAttribute('href', relatedSearches[j].webSearchUrl);
            relatedSearch.setAttribute('target', '_blank');
            childDiv.appendChild(relatedSearch);

        }
    }

Přehledy receptů

Funkce addRecipes() vytvoří odkaz pro každý z receptů vrácených iterací v seznamu Recipes akcí a přidáním <img> značky ven <div> pro každou z nich:

    // Display links to the first 10 recipes. Include the recipe's rating,
    // if available.
    // TODO: Add 'more' link in case the user wants to see all of them.
    function addRecipes(div, recipes) {
        var length = (recipes.length > 10) ? 10 : recipes.length;

        for (var j = 0; j < length; j++) {
            var para = document.createElement('p');

            var recipe = document.createElement('a');
            recipe.text = recipes[j].name;
            recipe.setAttribute('href', recipes[j].url);
            recipe.setAttribute('style', 'margin: 20px 20px 0 0');
            recipe.setAttribute('target', '_blank')
            para.appendChild(recipe);

            if (recipes[j].hasOwnProperty('aggregateRating')) {
                var span = document.createElement('span');
                span.textContent = 'rating: ' + recipes[j].aggregateRating.text;
                para.appendChild(span);
            }

            div.appendChild(para);
        }
    }

Přehledy o nákupech

Funkce addShopping() vytvoří odkaz na všechny výsledky vrácených nákupů tak, že iteruje seznam akcí a pro každou z RelatedImages nich připojí <img> značku ven <div> :

    // Display links for the first 10 shopping offers.
    // TODO: Add 'more' link in case the user wants to see all of them.
    function addShopping(div, offers) {
        var length = (offers.length > 10) ? 10 : offers.length;

        for (var j = 0; j < length; j++) {
            var para = document.createElement('p');

            var offer = document.createElement('a');
            offer.text = offers[j].name;
            offer.setAttribute('href', offers[j].url);
            offer.setAttribute('style', 'margin: 20px 20px 0 0');
            offer.setAttribute('target', '_blank')
            para.appendChild(offer);

            var span = document.createElement('span');
            span.textContent = 'by ' + offers[j].seller.name + ' | ' + offers[j].price + ' ' + offers[j].priceCurrency;
            para.appendChild(span);

            div.appendChild(para);
        }
    }

Přehledy produktů

Funkce addProducts() vytvoří propojení pro všechny výsledky vrácených produktů tak, že iteruje seznam akcí a pro každou z Products nich připojí <img> značku ven <div> :


    // Display the first 10 related products. Display a clickable image of the
    // product that takes the user to Bing.com search results for the product.
    // If there are any offers associated with the product, provide links to the offers.
    // TODO: Add 'more' link in case the user wants to see all of them.
    function addProducts(div, products) {
        var length = (products.length > 10) ? 10 : products.length;

        for (var j = 0; j < length; j++) {
            var childDiv = document.createElement('div');
            childDiv.setAttribute('class', 'stackLink');
            div.appendChild(childDiv);

            var img = document.createElement('img');
            img.setAttribute('src', products[j].thumbnailUrl + '&w=120&h=120');
            img.setAttribute('title', products[j].name);
            img.setAttribute('style', 'margin: 20px 20px 0 0; cursor: pointer;');
            img.setAttribute('data-webSearchUrl', products[j].webSearchUrl)
            img.addEventListener('click', function(e) {
                var url = e.target.getAttribute('data-webSearchUrl');
                window.open(url, 'foo');
            })
            childDiv.appendChild(img);

            if (products[j].insightsMetadata.hasOwnProperty('aggregateOffer')) {
                if (products[j].insightsMetadata.aggregateOffer.offerCount > 0) {
                    var offers = products[j].insightsMetadata.aggregateOffer.offers;

                    // Show all the offers. Not all markets provide links to offers.
                    for (var i = 0; i < offers.length; i++) {  
                        var para = document.createElement('p');

                        var offer = document.createElement('a');
                        offer.text = offers[i].name;
                        offer.setAttribute('href', offers[i].url);
                        offer.setAttribute('style', 'margin: 20px 20px 0 0');
                        offer.setAttribute('target', '_blank')
                        para.appendChild(offer);

                        var span = document.createElement('span');
                        span.textContent = 'by ' + offers[i].seller.name + ' | ' + offers[i].price + ' ' + offers[i].priceCurrency;
                        para.appendChild(span);

                        childDiv.appendChild(para);
                    }
                }
                else {  // Otherwise, just show the lowest price that Bing found.
                    var offer = products[j].insightsMetadata.aggregateOffer;

                    var para = document.createElement('p');
                    para.textContent = `${offer.name} | ${offer.lowPrice} ${offer.priceCurrency}`; 

                    childDiv.appendChild(para);
                }
            }
        }
    }

Přehledy TextResult

Funkce addTextResult() zobrazí veškerý text rozpoznaný na obrázku:


    function addTextResult(div, action) {
        var text = document.createElement('p');
        text.textContent = action.displayName;
        div.appendChild(text);
    }

Funkce addEntity() zobrazí odkaz, který uživatele přenese do Bing.com kde může získat podrobnosti o typu entity na obrázku, pokud byly nějaké zjištěny:

    // If the image is of a person, the tag might include an entity
    // action type. Display a link that takes the user to Bing.com
    // where they can get details about the entity.
    function addEntity(div, action) {
        var entity = document.createElement('a');
        entity.text = action.displayName;
        entity.setAttribute('href', action.webSearchUrl);
        entity.setAttribute('style', 'margin: 20px 20px 0 0');
        entity.setAttribute('target', '_blank');
        div.appendChild(entity);
    }

Funkce addImageWithWebSearchUrl() zobrazí obrázek s možností kliknutí na <div> obrázek, který uživatele přenese do výsledků hledání na Bing.com:

    function addImageWithWebSearchUrl(div, image, action) {
        var img = document.createElement('img');
        img.setAttribute('src', image.thumbnailUrl + '&w=120&h=120');
        img.setAttribute('style', 'margin: 20px 20px 0 0; cursor: pointer;');
        img.setAttribute('data-webSearchUrl', action.webSearchUrl);
        img.addEventListener('click', function(e) {
            var url = e.target.getAttribute('data-webSearchUrl');
            window.open(url, 'foo');
        })
        div.appendChild(img);
    }

Přidání stylu CSS

Pokud chcete uspořádat rozložení webové stránky, přidejte do <head> značky následující <style> část:

        <style>

            .thumb {
                height: 75px;
                border: 1px solid #000;
            }

            .stackLink {
                width:180px;
                min-height:210px;
                display:inline-block;
            }
            .stackLink a {
                float:left;
                clear:left;
            }

            .section {
                float:left;
                display:none;
            }

            .subSection {
                clear:left;
                float:left;
            }

        </style>

Další kroky