Skip to content

Commit

Permalink
Merge branch 'make-bing-search-async' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
jzohrab committed Jan 31, 2025
2 parents 5042622 + 4780be0 commit 382fdf5
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 25 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ ENV/
env.bak/
venv.bak/

# VS Code config
.vscode/

# Spyder project settings
.spyderproject
.spyproject
Expand Down
52 changes: 43 additions & 9 deletions lute/bing/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,43 @@
import hashlib
import re
import urllib.request
from flask import Blueprint, request, Response, render_template, jsonify, current_app
from flask import (
Blueprint,
request,
Response,
render_template,
jsonify,
current_app,
url_for,
)


bp = Blueprint("bing", __name__, url_prefix="/bing")


@bp.route(
"/search_page/<int:langid>/<string:text>/<string:searchstring>", methods=["GET"]
)
def bing_search_page(langid, text, searchstring):
"""
Load initial empty search page, passing real URL for subsequent ajax call to get images.
Sometimes Bing image searches block or fail, so providing the initial empty search page
lets the user know work is in progress. The user can therefore interact with the page
immediately. The template for this route then makes an ajax call to the "bing_search()"
method below which actually does the search.
"""

# Create URL for bing_search and pass into template.
search_url = url_for(
"bing.bing_search", langid=langid, text=text, searchstring=searchstring
)

return render_template(
"imagesearch/index.html", langid=langid, text=text, search_url=search_url
)


@bp.route("/search/<int:langid>/<string:text>/<string:searchstring>", methods=["GET"])
def bing_search(langid, text, searchstring):
"Do an image search."
Expand All @@ -36,7 +67,10 @@ def bing_search(langid, text, searchstring):
content = s.read().decode("utf-8")
except urllib.error.URLError as e:
content = ""
error_msg = e.reason
error_msg = str(e.reason)
except Exception as e: # pylint: disable=broad-exception-caught
content = ""
error_msg = str(e)

# Sample data returned by bing image search:
# <img class="mimg vimgld" ... data-src="https:// ...">
Expand All @@ -62,13 +96,13 @@ def build_struct(image):
# Also bing seems to throttle images if the count is higher (??).
images = images[:25]

return render_template(
"imagesearch/index.html",
langid=langid,
text=text,
images=images,
error_message=error_msg,
)
ret = {
"langid": langid,
"text": text,
"images": images,
"error_message": error_msg,
}
return jsonify(ret)


def _get_dir_and_filename(langid, text):
Expand Down
2 changes: 1 addition & 1 deletion lute/static/js/dict-tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class ImageLookupButton extends GeneralLookupButton {

const raw_bing_url = 'https://www.bing.com/images/search?q=[LUTE]&form=HDRSC2&first=1&tsc=ImageHoverTitle';
const binghash = raw_bing_url.replace('https://www.bing.com/images/search?', '');
const url = `/bing/search/${LookupButton.LANG_ID}/${encodeURIComponent(use_text)}/${encodeURIComponent(binghash)}`;
const url = `/bing/search_page/${LookupButton.LANG_ID}/${encodeURIComponent(use_text)}/${encodeURIComponent(binghash)}`;

iframe.setAttribute("src", url);
}; // end handler
Expand Down
72 changes: 57 additions & 15 deletions lute/templates/imagesearch/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,12 @@
then paste from your clipboard.
</p>

{% for image in images %}
<span class="initial"
style="margin: 2px; display:inline-block;"
onmouseover="highlight_image(this);"
onmouseout="un_highlight_image(this);"
onclick='save_image_locally("{{ image['src'] }}", {{ langid }}, "{{ text }}")'
>
{{ image['html'] | safe }}
</span>
{% endfor %}

{% if error_message != "" %}
<p><i>Error contacting image server: {{ error_message }}</i></p>
{% endif %}
<p id="image_search_feedback"><i>Searching ...</i></p>

</div>
</body>

<script>

let _update_term_form_image = function(filename, new_url) {
// Well, this took **far** too long to figure out ...
let fr = window.parent.frames['wordframe'];
Expand Down Expand Up @@ -141,6 +128,61 @@

});

$(document).ready(function() {
const searchUrl = '{{ search_url }}';
const container = document.getElementById('termimagesearch');

$.ajax({
url: searchUrl,
type: 'GET',
dataType: 'json',
success: function(data) {
if (data.error_message !== "") {
const msg = `Error: ${data.error_message}`;
console.error(msg);
$("#image_search_feedback").text(msg);
return;
}

$("#image_search_feedback").hide();
if (data.images.length === 0) {
const p = document.createElement('p');
p.textContent = 'No images found.';
container.appendChild(p);
return;
}

// Make Bing API call for images asynchronously
// This avoids blocking the page load
data.images.forEach(function(item) {
const imgWrapper = create_imageWrapper_element(item.src, data.langid, data.text);
container.appendChild(imgWrapper);
});
},
error: function(xhr, status, error) {
const msg = `Error ${error}; ${status}; ${xhr.responseText}`;
console.error(msg);
$("#image_search_feedback").val(msg);
}
});
});

function create_imageWrapper_element(src, langid, text) {
const imgWrapper = document.createElement('span');
imgWrapper.classList.add('initial');
imgWrapper.style.margin = '2px';
imgWrapper.style.display = 'inline-block';
imgWrapper.onmouseover = () => highlight_image(imgWrapper);
imgWrapper.onmouseout = () => un_highlight_image(imgWrapper);
imgWrapper.onclick = () => save_image_locally(src, langid, text);

const img = document.createElement('img');
img.src = src;

imgWrapper.appendChild(img);

return imgWrapper;
}
</script>

</html>

0 comments on commit 382fdf5

Please sign in to comment.