etiquette/frontends/etiquette_flask/templates/search.html

671 lines
22 KiB
HTML
Raw Normal View History

2016-09-18 08:33:46 +00:00
<!DOCTYPE html5>
<html>
<head>
2016-11-07 02:00:30 +00:00
{% import "photo_card.html" as photo_card %}
2016-09-18 08:33:46 +00:00
{% import "header.html" as header %}
{% import "tag_object.html" as tag_object %}
{% import "clipboard_tray.html" as clipboard_tray %}
2016-09-18 08:33:46 +00:00
<title>Search</title>
<meta charset="UTF-8">
2017-07-21 06:10:48 +00:00
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="/static/css/common.css">
<link rel="stylesheet" href="/static/css/photo_card.css">
<link rel="stylesheet" href="/static/css/clipboard_tray.css">
{% if theme %}<link rel="stylesheet" href="/static/css/theme_{{theme}}.css">{% endif %}
<script src="/static/js/common.js"></script>
<script src="/static/js/api.js"></script>
<script src="/static/js/hotkeys.js"></script>
<script src="/static/js/photo_clipboard.js"></script>
<script src="/static/js/tag_autocomplete.js"></script>
2016-11-27 09:06:11 +00:00
2016-09-18 08:33:46 +00:00
<style>
2018-11-05 02:36:17 +00:00
#search_builder_form
2016-09-18 08:33:46 +00:00
{
display: flex;
flex-direction: column;
justify-content: center;
}
2018-11-05 02:36:17 +00:00
#content_body
{
grid-template:
"left error_message_area" auto
"left happy_message_area" auto
"left right" 1fr
2018-11-05 02:36:17 +00:00
/ 310px 1fr;
}
2016-09-18 08:33:46 +00:00
#error_message_area
{
grid-area: error_message_area;
2016-09-18 08:33:46 +00:00
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
2016-09-18 08:33:46 +00:00
}
#happy_message_area
{
grid-area: happy_message_area;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.error_message
2016-09-18 08:33:46 +00:00
{
align-self: center;
2017-03-31 02:34:39 +00:00
2016-09-18 08:33:46 +00:00
padding: 2px;
2017-03-31 02:34:39 +00:00
background-color: #f00;
color: #fff;
2016-09-18 08:33:46 +00:00
}
#left
{
grid-area: left;
2017-03-31 02:34:39 +00:00
flex: 1;
padding: 8px;
background-color: var(--color_site_transparency);
2017-03-31 02:34:39 +00:00
word-wrap: break-word;
2016-09-18 08:33:46 +00:00
}
#tags_on_this_page_list
{
list-style-type: none;
padding: 0;
}
2016-09-18 08:33:46 +00:00
#right
{
grid-area: right;
2016-09-18 08:33:46 +00:00
flex: 1;
2017-03-31 02:34:39 +00:00
/* Keep the prev-next buttons from scraping the floor */
padding-bottom: 30px;
2016-09-18 08:33:46 +00:00
}
@media screen and (max-width: 800px) {
#content_body
{
grid-template:
"error_message_area"
"happy_message_area"
"right"
"left";
}
#left
{
max-width: none;
width: initial;
}
}
2016-11-07 02:00:30 +00:00
.prev_next_holder
{
display: flex;
flex-direction: row;
2016-11-07 02:00:30 +00:00
}
2016-09-18 08:33:46 +00:00
.prev_page
{
margin-right: 10px;
2016-09-18 08:33:46 +00:00
}
.next_page
{
margin-left: 10px;
2016-09-18 08:33:46 +00:00
}
.prev_page, .next_page
{
display: flex;
2017-03-31 02:34:39 +00:00
flex: 1;
justify-content: center;
2017-03-31 02:34:39 +00:00
border: 1px solid black;
background-color: var(--color_theme_secondary);
2017-03-31 02:34:39 +00:00
2016-09-18 08:33:46 +00:00
font-size: 20;
}
.search_builder_tagger,
#search_builder_orderby_ul
{
margin: 0;
}
</style>
{% macro prev_next_buttons() %}
{% if prev_page_url or next_page_url %}
<div class="prev_next_holder">
{% if prev_page_url %}
<a class="prev_page" href="{{prev_page_url}}">Previous</a>
{% else %}
<a class="prev_page"><br></a>
{% endif %}
{% if next_page_url %}
<a class="next_page" href="{{next_page_url}}">Next</a>
{% else %}
<a class="next_page"><br></a>
{% endif %}
</div>
{% endif %}
{% endmacro %}
{% macro create_orderby_li(selected_column, selected_sorter) %}
<li class="search_builder_orderby_li">
<select onchange="orderby_hide_direction_hook(event)">
<option value="created" {{"selected" if selected_column=="created" else ""}} >Creation date</option>
<option value="area" {{"selected" if selected_column=="area" else ""}} >Area</option>
<option value="width" {{"selected" if selected_column=="width" else ""}} >Width</option>
<option value="height" {{"selected" if selected_column=="height" else ""}} >Height</option>
<option value="ratio" {{"selected" if selected_column=="ratio" else ""}} >Aspect Ratio</option>
<option value="bytes" {{"selected" if selected_column=="bytes" else ""}} >File size</option>
<option value="duration" {{"selected" if selected_column=="duration" else ""}} >Duration</option>
<option value="tagged_at" {{"selected" if selected_column=="tagged_at" else ""}} >Recently tagged</option>
<option value="random" {{"selected" if selected_column=="random" else ""}} >Random</option>
2016-09-18 08:33:46 +00:00
</select>
<select {% if selected_column=="random" %}class="hidden"{% endif %}>
<option value="desc" {{"selected" if selected_sorter=="desc" else ""}} >Descending</option>
<option value="asc" {{"selected" if selected_sorter=="asc" else ""}} >Ascending</option>
2016-09-18 08:33:46 +00:00
</select>
<button class="remove_tag_button_perm red_button" onclick="orderby_remove_hook(this);"></button>
2016-09-18 08:33:46 +00:00
</li>
{% endmacro %}
2016-11-27 09:06:11 +00:00
</head>
2016-09-18 08:33:46 +00:00
<body>
2018-02-18 02:19:47 +00:00
{{header.make_header(session=session)}}
<div id="content_body">
2016-09-18 08:33:46 +00:00
<div id="left">
{% for tagtype in ["musts", "mays", "forbids"] %}
<div id="search_builder_{{tagtype}}" {% if search_kwargs["tag_expression"]%}style="display:none"{%endif%}>
<span>Tag {{tagtype}}:</span>
<ul class="search_builder_tagger">
{% set key="tag_" + tagtype %}
{% if search_kwargs[key] %}
2018-02-18 02:19:47 +00:00
{% for tagname in search_kwargs[key] %}
<li class="search_builder_{{tagtype}}_inputted">
<span class="tag_object">{{tagname}}</span>{{-''-}}
<button class="remove_tag_button red_button"
onclick="remove_searchtag(this, '{{tagname}}', inputted_{{tagtype}});"></button>
</li>
{% endfor %}
{% endif %}
<li><input id="search_builder_{{tagtype}}_input" type="text" list="tag_autocomplete_datalist"></li>
2016-09-18 08:33:46 +00:00
</ul>
</div>
{% endfor %}
<div id="search_builder_expression" {% if not search_kwargs["tag_expression"]%}style="display:none"{%endif%}>
<span>Tag Expression:</span>
<input id="search_builder_expression_input" name="tag_expression" type="text"
{% if search_kwargs["tag_expression"] %}
value="{{search_kwargs["tag_expression"]}}"
{% endif %}
>
</div>
<div id="search_builder_orderby">
<span>Order by</span>
<ul id="search_builder_orderby_ul">
{% if "orderby" in search_kwargs and search_kwargs["orderby"] %}
2018-02-18 02:19:47 +00:00
{% for orderby in search_kwargs["orderby"] %}
{% set column, sorter=orderby.split("-") %}
{{ create_orderby_li(selected_column=column, selected_sorter=sorter) }}
{% endfor %}
2016-09-18 08:33:46 +00:00
{% else %}
2018-02-18 02:19:47 +00:00
{{ create_orderby_li(selected_column=0, selected_sorter=0) }}
2016-09-18 08:33:46 +00:00
{% endif %}
<li id="search_builder_orderby_newrow"><button class="green_button" onclick="add_new_orderby()">+</button></li>
2016-09-18 08:33:46 +00:00
</ul>
</div>
<br>
<form id="search_builder_form" action="" onsubmit="return submit_search();">
2016-10-10 03:50:13 +00:00
<span>Min-max values</span>
<input type="text" class="basic_param"
{%if search_kwargs['area']%} value="{{search_kwargs['area']}}" {%endif%}
2016-10-10 03:50:13 +00:00
name="area" placeholder="Area: 1m-2m">
<input type="text" class="basic_param"
{%if search_kwargs['width']%} value="{{search_kwargs['width']}}" {%endif%}
2016-10-10 03:50:13 +00:00
name="width" placeholder="Width: 1k-2k">
<input type="text" class="basic_param"
{%if search_kwargs['height']%} value="{{search_kwargs['height']}}" {%endif%}
2016-10-10 03:50:13 +00:00
name="height" placeholder="Height: 1k-2k">
<input type="text" class="basic_param"
{%if search_kwargs['ratio']%} value="{{search_kwargs['ratio']}}" {%endif%}
2016-10-10 03:50:13 +00:00
name="ratio" placeholder="Aspect Ratio: 1.7-2">
<input type="text" class="basic_param"
{%if search_kwargs['bytes']%} value="{{search_kwargs['bytes']}}" {%endif%}
2016-10-10 03:50:13 +00:00
name="bytes" placeholder="File Size: 1mb-2mb">
<input type="text" class="basic_param"
{%if search_kwargs['duration']%} value="{{search_kwargs['duration']}}" {%endif%}
2016-10-10 03:50:13 +00:00
name="duration" placeholder="Duration: 10:00-20:00">
2018-01-14 04:02:12 +00:00
<input type="text" class="basic_param"
{%if search_kwargs['created']%} value="{{search_kwargs['created']}}" {%endif%}
2018-01-14 04:02:12 +00:00
name="created" placeholder="Created: 1483228800-1514764800">
2016-10-10 03:50:13 +00:00
<br>
<span>Other filters</span>
2016-10-30 01:46:23 +00:00
<input type="text" class="basic_param"
{%if search_kwargs['filename']%} value="{{search_kwargs['filename']}}" {%endif%}
2016-10-30 01:46:23 +00:00
name="filename" placeholder="Filename">
2016-10-10 03:50:13 +00:00
<input type="text" class="basic_param"
{%if search_kwargs['mimetype']%} value="{{search_kwargs['mimetype']}}" {%endif%}
2016-09-18 08:33:46 +00:00
name="mimetype" placeholder="Mimetype(s)">
2016-10-10 03:50:13 +00:00
<input type="text" class="basic_param"
{%if search_kwargs['extension']%} value="{{search_kwargs['extension']}}" {%endif%}
2016-09-18 08:33:46 +00:00
name="extension" placeholder="Extension(s)">
2016-10-10 03:50:13 +00:00
<input type="text" class="basic_param"
{%if search_kwargs['extension_not']%} value="{{search_kwargs['extension_not']}}" {%endif%}
2016-09-18 08:33:46 +00:00
name="extension_not" placeholder="Forbid extension(s)">
<input type="text" class="basic_param"
{%if search_kwargs['author']%} value="{{search_kwargs['author']}}" {%endif%}
name="author" placeholder="Author">
2016-10-10 03:50:13 +00:00
<select name="limit" class="basic_param">
{% set limit_options = [20, 50, 100, 200] %}
{% if search_kwargs['limit'] not in limit_options %}
{% do limit_options.append(search_kwargs['limit']) %}
{% do limit_options.sort() %}
{% endif %}
{% for limit_option in limit_options %}
<option value="{{limit_option}}" {{"selected" if search_kwargs['limit'] == limit_option else ""}}>
{{- limit_option }} items{{''-}}
</option>
{% endfor %}
2016-09-18 08:33:46 +00:00
</select>
2016-10-10 03:50:13 +00:00
<select name="has_tags" class="basic_param">
<option value="" {{"selected" if search_kwargs['has_tags']==None else ""}}>Tagged and untagged</option>
<option value="yes" {{"selected" if search_kwargs['has_tags']==True else ""}}>Tagged only</option>
<option value="no" {{"selected" if search_kwargs['has_tags']==False else ""}}>Untagged only</option>
2016-09-18 08:33:46 +00:00
</select>
<select name="has_thumbnail" class="basic_param">
<option value="" {{"selected" if search_kwargs['has_thumbnail']==None else ""}}>Thumbnail doesn't matter</option>
<option value="yes" {{"selected" if search_kwargs['has_thumbnail']==True else ""}}>Has thumbnail</option>
<option value="no" {{"selected" if search_kwargs['has_thumbnail']==False else ""}}>No thumbnail</option>
</select>
2016-11-07 02:00:30 +00:00
<select name="view" class="basic_param">
<option value="grid" {{"selected" if search_kwargs['view']=="grid" else ""}}>Grid</option>
<option value="list" {{"selected" if search_kwargs['view']=="list" else ""}}>List</option>
2016-11-07 02:00:30 +00:00
</select>
<button type="submit" id="search_go_button" class="green_button" value="">Search</button>
2016-09-18 08:33:46 +00:00
</form>
{% if total_tags %}
<h4>Tags on this page:</h4>
<ul id="tags_on_this_page_list">
2016-09-18 08:33:46 +00:00
{% for tag in total_tags %}
<li>
{{tag_object.tag_object(
tag,
link=None,
onclick="tags_on_this_page_add_must(event, '" + tag.name + "');",
innertext="(+)",
)}}
{{tag_object.tag_object(
tag,
link=None,
onclick="tags_on_this_page_add_may(event, '" + tag.name + "');",
innertext="(~)",
)}}
{{tag_object.tag_object(
tag,
link=None,
onclick="tags_on_this_page_add_forbid(event, '" + tag.name + "');",
innertext="(x)",
)}}
{{tag_object.tag_object(
tag,
link="info",
with_alt_description=True,
)}}
</li>
2016-09-18 08:33:46 +00:00
{% endfor %}
</ul>
{% endif %}
</div>
<div id="error_message_area">
{% for warning in warnings %}
<p class="error_message">{{warning}}</p>
{% endfor %}
</div>
<div id="happy_message_area">
<p>You got {{photos|length}} items.</p>
</div>
2016-09-18 08:33:46 +00:00
<div id="right">
{{prev_next_buttons()}}
<div id="search_results_holder">
2018-02-18 02:19:47 +00:00
{% for photo in photos %}
{{photo_card.create_photo_card(photo, view=search_kwargs["view"])}}
{% endfor %}
</div>
2016-09-18 08:33:46 +00:00
{{prev_next_buttons()}}
</div>
2018-02-18 02:19:47 +00:00
</div>
{{clipboard_tray.clipboard_tray()}}
2016-09-18 08:33:46 +00:00
</body>
<script type="text/javascript">
2017-05-13 22:27:08 +00:00
/*
These are defined so that we know we don't need to include them in the
constructed search URL, keeping it more tidy.
*/
2016-11-07 02:00:30 +00:00
PARAM_DEFAULTS = {
'limit': 50,
'view': 'grid',
}
2016-09-18 08:33:46 +00:00
function add_searchtag(box, value, inputted_list, li_class)
{
/*
2017-05-13 22:27:08 +00:00
Called by hitting Enter within a must/may/forbid field. Checks whether the
tag exists and adds it to the query.
2016-09-18 08:33:46 +00:00
*/
if (box.offsetParent === null)
{
// The box is hidden probably because we're in Expression mode.
return;
}
2016-09-18 08:33:46 +00:00
console.log("adding " + value);
var already_have = false;
// We're going to be doing some in-place splicing to remove,
// so make a duplicate for iterating
existing_tags = Array.from(inputted_list);
for (var index = 0; index < existing_tags.length; index += 1)
{
existing_tag = existing_tags[index];
if (existing_tag == value)
{
already_have = true;
}
else if (existing_tag.startsWith(value + ".") || value.startsWith(existing_tag + "."))
{
remove_searchtag(box, existing_tag, inputted_list);
}
}
if (already_have)
{return;}
inputted_list.push(value);
var new_li = document.createElement("li");
new_li.className = li_class;
var new_span = document.createElement("span");
new_span.className = "tag_object";
new_span.innerHTML = value;
var new_delbutton = document.createElement("button")
new_delbutton.classList.add("remove_tag_button");
new_delbutton.classList.add("red_button");
new_delbutton.onclick = function(){remove_searchtag(new_delbutton, value, inputted_list)};
new_li.appendChild(new_span);
new_li.appendChild(new_delbutton);
box_li = box.parentElement;
ul = box_li.parentElement;
ul.insertBefore(new_li, box_li);
// The datalist autocomplete box can sometimes stick around after the
// tag has already been submitted and the input box moves down -- now
// covered by the autocomplete. So we temporarily unfocus it to make
// that thing go away.
box.blur();
box.focus();
2016-09-18 08:33:46 +00:00
}
function remove_searchtag(li_member, value, inputted_list)
{
/*
Given a member of the same tag type as the one we intend to remove,
find the tag of interest and remove it from both the DOM and the
inputted_list.
Sorry for the roundabout technique.
*/
console.log("removing " + value);
var li = li_member.parentElement;
var ul = li.parentElement;
var lis = ul.children;
//console.log(lis);
for (var index = 0; index < lis.length; index += 1)
{
li = lis[index];
var span = li.children[0];
if (span.tagName != "SPAN")
{continue}
var tagname = span.innerHTML;
if (tagname != value)
{continue}
ul.removeChild(li);
splice_at = inputted_list.indexOf(tagname);
if (splice_at == -1)
{continue}
inputted_list.splice(splice_at, 1);
}
}
function add_new_orderby()
{
/* Called by the green + button */
var ul = document.getElementById("search_builder_orderby_ul");
var lis = ul.children;
if (lis.length >= 9)
2016-09-18 08:33:46 +00:00
{
/* 9 because there are only 9 sortable properties */
2016-09-18 08:33:46 +00:00
return;
}
prev_li = lis[lis.length - 2];
var new_li = prev_li.cloneNode(true);
ul.insertBefore(new_li, prev_li.nextSibling);
2016-09-18 08:33:46 +00:00
}
function orderby_remove_hook(button)
{
/* Called by the red button next to orderby dropdowns */
var li = button.parentElement;
var ul = li.parentElement;
// 2 because keep 1 row and the adder button
if (ul.children.length>2)
{
/* You can't remove the only one left */
ul.removeChild(li);
}
}
function orderby_hide_direction_hook(event)
{
if (event.target.value == "random")
{
event.target.nextElementSibling.classList.add("hidden");
}
else
{
event.target.nextElementSibling.classList.remove("hidden");
}
}
2016-10-10 03:50:13 +00:00
function simplify_tagnames(tags)
{
var new_tags = [];
for (var index = 0; index < tags.length; index += 1)
{
var tag = tags[index];
tag = tag.split(".");
tag = tag[tag.length - 1];
new_tags.push(tag);
}
return new_tags;
}
2016-09-18 08:33:46 +00:00
function submit_search()
{
/*
Gather up all the form data and tags and compose the search URL
*/
var url = window.location.origin + "/search";
var parameters = [];
var has_tag_params = false;
2016-10-10 03:50:13 +00:00
var musts = simplify_tagnames(inputted_musts).join(",");
2016-09-18 08:33:46 +00:00
if (musts) {parameters.push("tag_musts=" + musts); has_tag_params=true;}
2016-10-10 03:50:13 +00:00
var mays = simplify_tagnames(inputted_mays).join(",");
2016-09-18 08:33:46 +00:00
if (mays) {parameters.push("tag_mays=" + mays); has_tag_params=true;}
2016-10-10 03:50:13 +00:00
var forbids = simplify_tagnames(inputted_forbids).join(",");
2016-09-18 08:33:46 +00:00
if (forbids) {parameters.push("tag_forbids=" + forbids); has_tag_params=true;}
var expression = document.getElementsByName("tag_expression")[0].value;
if (expression)
{
//expression = expression.replace(new RegExp(" ", 'g'), "-");
2016-09-18 08:33:46 +00:00
parameters.push("tag_expression=" + expression);
has_tag_params=true;
}
2016-10-10 03:50:13 +00:00
var basic_inputs = document.getElementsByClassName("basic_param");
2016-09-18 08:33:46 +00:00
for (var index = 0; index < basic_inputs.length; index += 1)
{
2016-10-10 03:50:13 +00:00
var boxname = basic_inputs[index].name;
2016-09-18 08:33:46 +00:00
var box = document.getElementsByName(boxname)[0];
var value = box.value;
2016-11-06 00:58:37 +00:00
value = value.split("&").join("%26");
console.log(value);
2016-11-07 02:00:30 +00:00
if (PARAM_DEFAULTS[boxname] == value)
{
// Don't clutter url with default values.
continue;
}
2016-09-18 08:33:46 +00:00
if (value == "")
{
continue;
}
2016-11-06 00:58:37 +00:00
parameters.push(boxname + "=" + value);
2016-09-18 08:33:46 +00:00
}
orderby_rows = document.getElementsByClassName("search_builder_orderby_li");
orderby_params = [];
for (var index = 0; index < orderby_rows.length; index += 1)
{
var row = orderby_rows[index];
var column = row.children[0].value;
if (column == "random")
{
orderby_params.push(column);
}
else
{
var sorter = row.children[1].value;
orderby_params.push(column + "-" + sorter);
}
2016-09-18 08:33:46 +00:00
}
orderby_params = orderby_params.join(",");
2016-11-07 02:00:30 +00:00
if (orderby_params && orderby_params != "created-desc")
2016-09-18 08:33:46 +00:00
{
2016-11-07 02:00:30 +00:00
// Don't clutter url with default of created-desc
2016-09-18 08:33:46 +00:00
parameters.push("orderby=" + orderby_params);
}
2016-11-07 02:00:30 +00:00
if (parameters.length > 0)
2016-09-18 08:33:46 +00:00
{
parameters = parameters.join("&");
parameters = "?" + parameters;
url = url + parameters;
}
2016-11-06 00:58:37 +00:00
console.log(url);
2016-09-18 08:33:46 +00:00
window.location.href = url;
return false;
}
function tags_on_this_page_add_must(event, tagname)
2016-09-18 08:33:46 +00:00
{
add_searchtag(
input_musts,
tagname,
2016-09-18 08:33:46 +00:00
inputted_musts,
"search_builder_musts_inputted"
);
return false;
}
function tags_on_this_page_add_may(event, tagname)
{
add_searchtag(
input_mays,
tagname,
inputted_mays,
"search_builder_mays_inputted"
);
return false;
}
function tags_on_this_page_add_forbid(event, tagname)
{
add_searchtag(
input_forbids,
tagname,
inputted_forbids,
"search_builder_forbids_inputted"
);
return false;
}
2016-09-18 08:33:46 +00:00
function tag_input_hook(box, inputted_list, li_class)
{
/*
Assigned to the input boxes for musts, mays, forbids.
Hitting Enter will add the resovled tag to the search form.
*/
if (event.keyCode != 13)
{return;}
if (!box.value)
{return;}
var value = box.value;
value = tag_autocomplete.resolve(value);
if (value === null)
2016-09-18 08:33:46 +00:00
{
return;
}
console.log(inputted_list);
add_searchtag(box, value, inputted_list, li_class)
box.value = "";
}
tag_autocomplete.init_datalist();
2016-09-18 08:33:46 +00:00
var input_musts = document.getElementById("search_builder_musts_input");
var input_mays = document.getElementById("search_builder_mays_input");
var input_forbids = document.getElementById("search_builder_forbids_input");
var input_expression = document.getElementById("search_builder_expression_input");
/* Prefix the form with the parameters from last search */
var inputted_musts = [];
var inputted_mays = [];
var inputted_forbids = [];
{% for tagtype in ["musts", "mays", "forbids"] %}
{% set key="tag_" + tagtype %}
{% if search_kwargs[key] %}
2016-09-18 08:33:46 +00:00
{% for tagname in search_kwargs[key] %}
inputted_{{tagtype}}.push("{{tagname}}");
{% endfor %}
{% endif %}
2016-09-18 08:33:46 +00:00
{% endfor %}
input_musts.addEventListener("keyup", function(){tag_input_hook(this, inputted_musts, "search_builder_musts_inputted")});
input_musts.addEventListener("keyup", common.entry_with_tagname_replacements);
input_mays.addEventListener("keyup", function(){tag_input_hook(this, inputted_mays, "search_builder_mays_inputted")});
input_mays.addEventListener("keyup", common.entry_with_tagname_replacements);
input_forbids.addEventListener("keyup", function(){tag_input_hook(this, inputted_forbids, "search_builder_forbids_inputted")});
input_forbids.addEventListener("keyup", common.entry_with_tagname_replacements);
2018-07-23 02:12:08 +00:00
common.bind_box_to_button(input_expression, document.getElementById("search_go_button"));
2016-11-27 09:06:11 +00:00
</script>
</html>