Martin Brodersen
Martin Brodersen

Reputation: 23

Python Flask application - How to make html input tag with dropdown updated by javascript ajax function

I am trying to make the input tag with id="livebox" be a live search box with surgestions from youtube. Does any one know how to add a dropdown surgestions box to the input tag with surgestions from res in the javascript?

The console.log(res) outputs ['sidemen', 'sannevillefamily', 'stor mand', 'spiderman', 'signe kragh', 'ssundee', 'sam and colby', 'speed', 'stille musik', 'speak no evil trailer', 'sleep music', 'stranger things season 4', 'spørg casper', 'shakira'] if "s" is typed in the input.

All the code used is as follows:

Flask code .py

import requests
import re
from isodate import parse_duration
from flask_youtube_search.common import myShelvedDict
from flask import Blueprint, render_template, current_app, request, redirect,jsonify,url_for  

main = Blueprint('main', __name__)

@main.route('/', methods=['GET', 'POST'])
def index():   
    return render_template('index.html',data=[])

@main.route("/livesearch",methods=["POST","GET"])
def livesearch():
    searchbox = request.form.get("text")
    URL = f"https://suggestqueries-clients6.youtube.com/complete/search?client=youtube&hl=da&gl=dk&gs_rn=64&gs_ri=youtube&ds=yt&cp=5&gs_id=l&q={searchbox}&xhr=t&xssi=t"
    r = requests.get(url = URL)
    data = r.text
    data = re.findall('"([^"]*)"', data)
    data = data[1:(len(data)-5)]
    myShelvedDict["data"] = data
    data = tuple(data)
    print(data)
    return jsonify(data)

html code for index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Search YouTube</title>

    <!-- Bootstrap core CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

    <style>
      .bd-placeholder-img {
        font-size: 1.125rem;
        text-anchor: middle;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
      }

      @media (min-width: 768px) {
        .bd-placeholder-img-lg {
          font-size: 3.5rem;
        }
      }
    </style>
    <!-- Custom styles for this template -->
    <link href="{{ url_for('static', filename='album.css') }}" rel="stylesheet">
  </head>
  <body>

<main role="main">
  <section class="jumbotron text-center">
    <div class="container">
      <h1 class="jumbotron-heading">Search YouTube</h1>
      <p class="lead text-muted">Get the top nine results on YouTube for your query!</p>
      <div class="input-group mb-3">
        <input list="surgestions" type="text" id = "livebox" name="query">
        <p>{{data}}</p>
      </div>
      <form action ="search" method="POST">
      <p>
        <button type="submit" name="submit" value="search" class="btn btn-primary my-2">YouTube Search</button>
      </p>
      </form>
    </div>
  </section>
  
</main>
</body>
<script>
  $(document).ready(function(){
      $("#livebox").on("input",function(e){
          $("#datalist").empty();
          $.ajax({
              method:"post",
              url:"/livesearch",
              data:{text:$("#livebox").val()},
              success:function(res){
                  console.log(res);
              }
          });
      });
  });
</script>
</html>

unimportant css code:

.jumbotron {
  padding-top: 3rem;
  padding-bottom: 3rem;
  margin-bottom: 0;
  background-color: #fff;
}
@media (min-width: 768px) {
  .jumbotron {
    padding-top: 6rem;
    padding-bottom: 6rem;
  }
}

.jumbotron p:last-child {
  margin-bottom: 0;
}

.jumbotron-heading {
  font-weight: 300;
}

.jumbotron .container {
  max-width: 40rem;
}

footer {
  padding-top: 3rem;
  padding-bottom: 3rem;
}

footer p {
  margin-bottom: .25rem;
}

.jumbotron-video {
  text-align: center;
}

.video-container {
  position: relative;
  padding-bottom: 56.25%; /* 16:9 */
  height: 0;
}
.video-container iframe {
  position: absolute;
  top: 0;
  left: 12.5%;
  width: 80%;
  height: 60%;
}

.embedded-video-16-9 {
  width:  90vw;
  height: 50.625vw; /* 90*9/16 */
  margin-left: 5vw;
  margin-right: 5vw;
}

@media (min-width: 893px) {
  .embedded-video-16-9 {
    width: 45vw;
    height: 25.3125vw; /* 45*9/16 */
    margin-left: 2vw;
    margin-right: 2vw
  }
}

Unimportant import commom.py

import shelve

myShelvedDict = shelve.open("my_shelved_dictionary.db")

Upvotes: 0

Views: 341

Answers (1)

Martin Brodersen
Martin Brodersen

Reputation: 23

Ok, I solved it now.

The fix was to use following script:

<script>
  $(document).ready(function(){
      $("#livebox").on("input",function(e){
          var _this = $(this);
          $("#datalist").empty();
          $.ajax({
              method:"post",
              url:"/livesearch",
              data:{text:$("#livebox").val()},
              success:function(res){
                $("#query").empty();
                for (var i in res) {
                    $("<option/>").html(res[i]).appendTo("#query");
                }
                _this.focus();
              }
          });
      });
  });
</script>

with the html:

<input autoComplete="off" list="query" type="text" id = "livebox" name="query">
<datalist id="query"></datalist>

Upvotes: 2

Related Questions