I'm trying to build a video chat webapp using Twilio following https://www.twilio.com/blog/build-video-chat-application-python-javascript-twilio-programmable-video, but I keep getting the error listed in the title. From what I've gathered, I'm trying to call upon the attributes of an object (sid, name) that was never really defined (participant), but I'm not sure where in my code to define it.
<body>
<h1>join existing jam</h1>
<form>
<label for="username">Name: </label>
<input type="text" name="username" id="username">
<button id="join_leave">join</button>
</form>
<p id="count"></p>
<div id="container" class="container">
<div id="local" class="participant"><div></div><div>Me</div></div>
<div id="{{ participant.sid }}" class="participant">
<div></div> <!-- the video and audio tracks will be attached to this div -->
<div>{{participant.name}}</div>
</div>
</div>
<script src="//media.twiliocdn.com/sdk/js/video/releases/2.3.0/twilio-video.min.js"></script>
<script>
let connected=false;
const usernameInput = document.getElementById('username');
const button = document.getElementById('join_leave');
const container = document.getElementById('container');
const count = document.getElementById('count');
let room;
function addLocalVideo() {
Twilio.Video.createLocalVideoTrack().then(track => {
let video = document.getElementById('local').firstChild;
video.appendChild(track.attach());
});
};
function connectButtonHandler(event) {
event.preventDefault();
if (!connected) {
let username = usernameInput.value;
if (!username) {
alert('Enter your name before connecting');
return;
}
button.disabled = true;
button.innerHTML = 'connecting...';
connect(username).then(() => {
button.innerHTML = 'leave';
button.disabled = false;
}).catch(() => {
alert('Connection failed. Is the backend running?');
button.innerHTML = 'join';
button.disabled = false;
});
}
else {
disconnect();
button.innerHTML = 'join';
connected = false;
}
};
function connect(username) {
let promise = new Promise((resolve, reject) => {
// get a token from the back end
fetch('/login', {
method: 'POST',
body: JSON.stringify({'username': username})
}).then(res => res.json()).then(data => {
// join video call
return Twilio.Video.connect(data.token);
}).then(_room => {
room = _room;
room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
room.on('participantDisconnected', participantDisconnected);
connected = true;
updateParticipantCount();
resolve();
}).catch(() => {
reject();
});
});
return promise;
};
function updateParticipantCount() {
if (!connected)
count.innerHTML = 'Disconnected.';
else
count.innerHTML = (room.participants.size + 1) + ' participants online.';
};
function participantConnected(participant) {
let participantDiv = document.createElement('div');
participantDiv.setAttribute('id', participant.sid);
participantDiv.setAttribute('class', 'participant');
let tracksDiv = document.createElement('div');
participantDiv.appendChild(tracksDiv);
let labelDiv = document.createElement('div');
labelDiv.innerHTML = participant.identity;
participantDiv.appendChild(labelDiv);
container.appendChild(participantDiv);
participant.tracks.forEach(publication => {
if (publication.isSubscribed)
trackSubscribed(tracksDiv, publication.track);
});
participant.on('trackSubscribed', track => trackSubscribed(tracksDiv, track));
participant.on('trackUnsubscribed', trackUnsubscribed);
updateParticipantCount();
};
function participantDisconnected(participant) {
document.getElementById(participant.sid).remove();
updateParticipantCount();
};
function trackSubscribed(div, track) {
div.appendChild(track.attach());
};
function trackUnsubscribed(track) {
track.detach().forEach(element => element.remove());
};
function disconnect() {
room.disconnect();
while (container.lastChild.id != 'local')
container.removeChild(container.lastChild);
button.innerHTML = 'Join call';
connected = false;
updateParticipantCount();
};
addLocalVideo();
button.addEventListener('click', connectButtonHandler);
</script>
</body>
Also, if it helps, this is the app.py that I'm calling from terminal:
import os
from dotenv import load_dotenv
from flask import Flask, render_template, request, abort
from twilio.jwt.access_token.grants import VideoGrant
load_dotenv()
twilio_account_sid=os.environ.get("TWILIO_ACCOUNT_SID")
twilio_api_key_sid = os.environ.get('TWILIO_API_KEY_SID')
twilio_api_key_secret = os.environ.get('TWILIO_API_KEY_SECRET')
app=Flask(__name__)
#app.route('/')
def index():
return render_template('joinJam.html')
#app.route('/login',methods=['POST'])
def login():
username=request.get_json(force=True).get('username')
if not username:
abort(401)
token=AccessToken(twilio_account_sid, twilio_api_key_sid, twilio_api_key_secret, identity=username)
token.add_grant(VideoGrant(room='My Room'))
return {'token': token.to_jwt().decode()}
Twilio developer evangelist here.
Your issue is in the HTML here:
<div id="container" class="container">
<div id="local" class="participant"><div></div><div>Me</div></div>
<div id="{{ participant.sid }}" class="participant">
<div></div> <!-- the video and audio tracks will be attached to this div -->
<div>{{participant.name}}</div>
</div>
</div>
You are trying to refer to a participant object that does not exist.
In this case you are trying to render the participant information for the local participant. Instead of doing so directly in the HTML, you need to do this in the JavaScript once you have successfully requested the media of your local participant.
Your HTML should be:
<div id="container" class="container">
<div id="local" class="participant"><div></div><div>Me</div></div>
</div>
Then the showing of your media will be handled by the addLocalVideo method.
Related
i'm studying JS and at the moment i'm not really good with it. I created a page (a kind of social network) and i need to add an image from an URL when i fill a form. The form has 2 fields: Image title and URL
the initial cards that i have on the page, i handle to insert them from an array. But i can't understand how to add a single photo from a form.
The new photo should appear as first image, the previous 1st image should be at the 2nd place and so on, cards can be deleted when i click on a button but i didn't really got how to do it, and the like buttons should work for every single cards... i've was looking for it on google and i found some stuffs but they didn't work for me.
how can i solve it?
my code:
HTML
<section class="cards" id="cards">
<!-- images will be added here-->
<div class="cards__add-form-overlay">
<form class="cards__add-form">
<button class="cards__add-form-close-icon"></button>
<p class="cards__add-form-text">New place</p>
<input type="text" placeholder="Name" class="cards__add-form-first-field" id="ImageName" value= "">
<input type="text" placeholder="Image URL" class="cards__add-form-second-field" id="URL" value= "">
<button type="submit" class="cards__add-form-submit">create</button>
</form>
</div>
</section>
<template class="elements" id="elements">
<div class="element">
<div class="element__card">
<img class="element__photo" src="" alt="">
<div class="element__button-container">
<button type="button" class="element__trash-button" id="trashbutton">
</div>
<div class="element__text">
<p class="element__place"></p>
<button type="button" class="element__like-button" id="likebutton" onclick="toggle()"></button>
</div>
</div>
</template>
<script type="text/javascript" src="./script.js"></script>
</body>
</html>
JS
// IMAGES //
// description: adding photos in the page from an array with JS //
const initialCards = [
{ name:'', link:''},
{ name:'', link:''},
{ name:'', link:''},
{ name:'', link:''},
{ name:'', link:''},
{ name:'', link:''}
];
initialCards.forEach(card => cardItem(card));
function cardItem(cardData) {
const container = document.getElementById("cards");
const cardTemplate = document.getElementById("elements").content;
const newCard = cardTemplate.cloneNode(true);
const elementImage = newCard.querySelector('.element__photo');
const elementText = newCard.querySelector('.element__place');
elementImage.src = cardData.link;
elementText.textContent = cardData.name;
container.append(newCard);
}
----- Until here all good
// description: adding popup when clicking on + button, and close with X button //
document.querySelector('.profile__add-button').addEventListener('click', function () {
document.querySelector('.cards__add-form-overlay').style.visibility = 'visible';
});
document.querySelector('.cards__add-form-close-icon').addEventListener('click', function () {
document.querySelector('.cards__add-form-overlay').style.visibility = 'hidden';
});
document.querySelector('.cards__add-form-submit').addEventListener('click', function () {
document.querySelector('.cards__add-form-overlay').style.visibility = 'hidden';
});
document.querySelector('.profile__add-button').addEventListener('click', function () {
document.querySelector('.cards__add-form').style.visibility = 'visible';
});
document.querySelector('.cards__add-form-close-icon').addEventListener('click', function () {
document.querySelector('.cards__add-form').style.visibility = 'hidden';
});
document.querySelector('.cards__add-form-submit').addEventListener('click', function () {
document.querySelector('.cards__add-form').style.visibility = 'hidden';
});
// description: adding photo through popup with 2 fields, name and URL //
const addPhoto = document.querySelector('.cards__add-form');
const imageNameInput = document.querySelector('.cards__add-form-first-field');
const imageUrlInput = document.querySelector('.cards__add-form-first-field');
function handleAddCardFormSubmit(evt) {
evt.preventDefault();
const element = createCard(imageNameInput.value, imageUrlInput.value);
elements.prepend(element);
imageNameInput.value = '';
imageUrlInput.value = '';
closePopup(evt.target.closest('.cards__add-form'));
}
function createCard(name, link) {
const elementTemplate = document.querySelector('#element-template').content;
const element = elementTemplate.querySelector('.element').cloneNode(true);
const elementImage = element.querySelector('.element__photo');
const elementTitle = element.querySelector('.element__place');
elementImage.src = link;
elementTitle.textContent = name;
//like button//
const likeButton = element.querySelector('.element__like-button');
likeButton.addEventListener('click', () => likeButton.classList.toggle('element__like-button_active'));
//delete cards //
element.addEventListener('click', function (evt) {
if (evt.target.classList.contains('element__trash-button')) {
evt.currentTarget.remove();
}
if (evt.target.classList.contains('element__photo')) {
openImagePopup(name, link);
}
});
return element;
}
initialCards.forEach(({name, link}) => elements.append(createCard(name, link)));
with this code, the new image doesn't appear, about like button console says that toogle() is not defined, and delete button don't delete the image but no error in the console
I have a little problem or a big one, I don't know. I'm trying to send a form with ajax with Symfony, and native JavaScript, but I don't really know how. I managed to do ajax with GET request to try to find a city (which is included in this form).
So I've got my form, I also want to send 2 arrays 1 for images (multiple images with different input) the input are created with js via CollectionType::class, then I'm putting my images in array which I want to send.
And the other array is for the city I want my product to be in. I've got an input text and via ajax it's searching city then by clicking on the city I've got a function putting it on an array.
but now I find difficulties trying to send it everything I found on the web mostly uses jQuery.. but I want to learn JavaScript so I believe I have to train with native first.
so I tried to send my form, but nothing happened when I submit it, not even an error, it just reload the page, and in my console I've got a warning for CORB issues I think it's due to my browser blocking my request because something is wrong in it?
I'm trying to find a way to send it and save it in my database.
so here's the code:
{% extends "base.html.twig" %}
{% block body %}
<div class="container">
<div class="row">
<div class="col-lg-6 mx-auto mt-5">
{{form_start(form)}}
{{form_errors(form)}}
{{form_row(form.title)}}
{{form_row(form.description)}}
{{form_row(form.surface)}}
{{form_row(form.piece)}}
{{form_row(form.type)}}
<div class="container">
<div class="select-btn">
<span class="btn-text d-flex">
<input type="text" oninput="getData(this.value)" class="rel" name="ville" id="">
<span class="arrow-dwn">
<i class="fa-solid fa-chevron-down"></i>
</span>
</span>
</div>
<ul class="list-items js-result"></ul>
</div>
<button type="button" class="btn btn-primary btn-new opacity-100" data-collection="#foo">ajouter une image</button>
<div id="foo" class="row" data-prototype="{{include ("include/_Addimage.inc.html.twig", {form: form.image.vars.prototype})|e("html_attr")}}" data-index="{{form.image|length > 0 ? form.image|last.vars.name +1 : 0}}">
{% for image in form.image %}
<div class="col-4">
{{ include ("include/_Addimage.inc.html.twig", {form: image}) }}
</div>
{{form_errors(form.image)}}
{% endfor %}
</div>
<div class="col-4 mt-5">
{{form_row(form.submit)}}
</div>
{{form_widget(form._token)}}
{{form_end(form, {render_rest: false})}}
</div>
</div>
</div>
{% endblock %}
here the code of my JavaScript, everything is in my twig file, because as you will see I added eventListener on some input, I didn't see a better way maybe someone can correct me.
{% block javascripts %}
<script type="text/javascript">
/////////////// GET INPUT TEXT VALUE AND SHOW A LIST OF CITIES
function getData(text) {
const param = new URLSearchParams();
param.append('text', text);
const url = new URL(window.location.href);
fetch(url.pathname + "?" + param.toString() + "&ajax=1", {
header: {
"X-Requested-With": "XMLHttpRequest"
}
})
.then(response => response.json())
.then(data => {
handle_result(data);
});
}
////////////////////////////// CREATE MY OPTIONS WITH CITIES NAME
function handle_result(response)
{
let result_div = document.querySelector(".js-result");
let str = "";
for (let i = response.length - 1; i >= 0; i--) {
str += "<option" + ' ' + "onclick=" + "addTag(this.value)" + ' ' + "class=" + "item" + ' ' + "value=" + response[i].ville + ">" + response[i].ville + "</option>";
}
result_div.innerHTML = str;
};
// //////////////////////////// ADD THE CITY NAME IN A CONTAINER WHEN I USER CLICK ON IT
const selectBtn = document.querySelector(".select-btn");
const rel = document.querySelector(".rel");
items = document.querySelectorAll(".item");
rel.addEventListener("click", () => {
selectBtn.classList.toggle("open");
});
function createTag(label) {
const div = document.createElement('div');
div.setAttribute('class', 'tag');
const span = document.createElement('span');
span.innerText = label;
const closeBtn = document.createElement('i');
closeBtn.setAttribute('data-item', label);
closeBtn.setAttribute('onclick', 'remove(this)');
closeBtn.setAttribute('class', 'material-icons');
closeBtn.innerHTML = 'close';
div.appendChild(span);
div.appendChild(closeBtn);
return div;
}
btnText = document.querySelector(".btn-text");
let tags = [];
function addTags()
{
reset();
for (let a of tags.slice().reverse()) {
const tag = createTag(a);
selectBtn.prepend(tag);
}
}
function addTag(value) {
input = document.querySelector('.rel');
console.log(input);
if (tags.includes(value)) {
alreadyExist(value);
}
else {
tags.shift();
tags.push(value);
addTags();
}
input.value = "";
}
function alreadyExist(value) {
const index = tags.indexOf(value);
tags = [
... tags.slice(0, index),
... tags.slice(index + 1)
];
addTags();
}
function reset() {
document.querySelectorAll('.tag').forEach(function (tag) {
tag.parentElement.removeChild(tag);
})
}
function remove(value) {
const data = value.getAttribute('data-item');
const index = tags.indexOf(data);
tags = [
... tags.slice(0, index),
... tags.slice(index + 1)
];
addTags();
}
//////////////////////////////////////////////////////// CREATING IMAGE ARRAY TO SEND WITH AJAX REQUEST ?
images = [];
function image_to_array(value) {
if(!images.includes(value))
{
images.push(value);
}else{
return false;
}
}
const form =
{
title: document.getElementById('product_form_title'),
description: document.getElementById('product_form_description'),
surface: document.getElementById('product_form_surface'),
piece: document.getElementById('product_form_piece'),
type: document.getElementById('product_form_type'),
}
const submit = document.getElementById('submit', () => {
const request = new XMLHttpRequest();
const url = new URL(window.location.href);
const requestData =
`
title=${form.title.value}&
description=${form.description.value}&
surface=${form.surface.value}&
piece=${form.piece.value}&
image=${JSON.stringify(images)}&
type=${JSON.stringify(tags)}&
ville=${tags}
`;
fetch(requestData , url.pathname ,{
header: {
"X-Requested-With": "XMLHttpRequest"
}
})
request.addEventListener('load', function(event) {
console.log(requestData);
});
request.addEventListener('error', function(event) {
console.log(requestData);
});
});
////////////////////////////// CREATE NEW FILE INPUT
const newItem = (e) => {
const collectionHolder = document.querySelector(e.currentTarget.dataset.collection);
const item = document.createElement('div');
item.classList.add('col-4');
item.innerHTML = collectionHolder.dataset.prototype.replace(/__name__/g, collectionHolder.dataset.index);
item.querySelector('.btn-remove').addEventListener('click', () => item.remove());
collectionHolder.appendChild(item);
collectionHolder.dataset.index ++;
}
document.querySelectorAll('.btn-new').forEach(btn => btn.addEventListener('click', newItem));
</script>
{% endblock %}
here my controller but I don't think it is the issue, I didn't finish it since I'm quite lost on the js part
class AdminController extends AbstractController
{
#[Route('/admin/create_product', name: 'create_product', methods: ['POST', 'GET'])]
public function createProduct(EntityManagerInterface $em, SluggerInterface $slugger, Request $request, LieuxRepository $villeRepo, SerializerInterface $serializer): Response
{
$product = new Product;
$ville = new Lieux;
$form = $this->createForm(ProductFormType::class, $product);
$form->handleRequest($request);
$list = $villeRepo->findAll();
$query =$request->get('text');
if($request->get('ajax')){
return $this->json(
json_decode(
$serializer->serialize(
$villeRepo->handleSearch($query),
'json',
[AbstractNormalizer::IGNORED_ATTRIBUTES=>['region', 'departement', 'products']]
), JSON_OBJECT_AS_ARRAY
)
);
}
if($request->isXmlHttpRequest())
{
if ($form->isSubmitted() && $form->isValid()) {
$product->setCreatedAt(new DateTime());
$product->setUpdatedAt(new DateTime());
$product->setVille($form->get('ville')->getData());
$product->setType($form->get('type')->getData());
$em->persist($product);
$em->flush();
}
}
return $this->render(
'admin/create_product.html.twig',
['form' => $form->createView() ]
);
}
hope it's clear, thank you
I'm trying to upload an image on a Ruby on Rails view using a button that on-click should send an argument to a python script. However I am facing issues.
Here is the code in my index.html.erb:
<div class="container">
<div class="wrapper">
<div class="image">
<img src="" onerror="this.style.display='none'" id = 'image_file'/>
</div>
<div class="content">
<div class="icon">
<i class="fas fa-cloud-upload-alt"></i>
</div>
<div class="text" style="text-align:center;">
No Image
</div>
</div>
<div id="cancel-btn">
<i class="fas fa-times"></i>
</div>
<div class="file-name">
File name here
</div>
</div>
<button onclick="defaultBtnActive()" id="custom-btn" class="active-btn" name="default-btn">Choose a file</button>
<input id="default-btn" type="file" name ='file' hidden>
<button id="submit-btn" class="active-btn modal-btn">Submit</button>
</div>
<div class="bg-modal">
<div id="error">
<div class="close">+</div>
<h1>Error</h1>
<p>Error occurred with uploading image. Did you upload the right file type?</p>
</div>
</div>
</div>
<script>
const wrapper = document.querySelector(".wrapper");
const fileName = document.querySelector(".file-name");
const defaultBtn = document.querySelector("#default-btn");
const customBtn = document.querySelector("#custom-btn");
const cancelBtn = document.querySelector("#cancel-btn i");
const img = document.querySelector("img");
const submitBtn = document.querySelector("#submit-btn");
let regExp = /[0-9a-zA-Z\^\&\'\#\{\}\[\]\,\$\=\!\-\#\(\)\.\%\+\~\_ ]+$/;
function defaultBtnActive(){
defaultBtn.click();
}
defaultBtn.addEventListener("change", function(){
var file = this.files[0];
if(isFileImage(file)){
const reader = new FileReader();
reader.onload = function(){
const result = reader.result;
img.src = result;
img.style.display = 'inline';
const placeholder = document.querySelector(".content");
placeholder.style.visibility = "hidden";
wrapper.classList.add("active");
}
cancelBtn.addEventListener("click", function(){
img.src = "";
wrapper.classList.remove("active");
location.reload();
})
reader.readAsDataURL(file);
}
else {
modalBg.classList.add('bg-active');
}
if(this.value){
let valueStore = this.value.match(regExp);
fileName.textContent = valueStore;
}
});
var modalBtn = document.querySelector('.modal-btn');
var modalBg = document.querySelector('.bg-modal');
var modalClose = document.querySelector('.close');
let {PythonShell} = require('python-shell');
var cloudurl = 'gs://uscentralbucket-vcm/testus.csv';
let options = {
mode: 'text',
pythonOptions: ['-u'], // get print results in real-time
scriptPath: '../auto-ml/',
args: [cloudurl]
};
modalBtn.addEventListener('click', function() {
var file = defaultBtn.files[0];
if (isFileImage(file)) {
window.location.href = "<%= main_review_path %>";
python_script.stdout.on('data', (data) =>{
console.log('Data received from python script', data.toString())
});
PythonShell.run('consolidated_steps.py', options, function (err, results) {
if (err) throw err;
// results is an array consisting of messages collected during execution
console.log('results: %j', results);
});
}
else {
modalBg.classList.add('bg-active');
}
});
modalClose.addEventListener('click', function() {
modalBg.classList.remove('bg-active');
})
function isFileImage(file) {
const acceptedImageTypes = ['image/gif', 'image/jpeg', 'image/png'];
return file && acceptedImageTypes.includes(file['type'])
}
</script>
After applying the relevant PythonShell code, the button in my Rails view does not work anymore. It works if I comment out let{PythonShell} = require('python-shell').
Is there a way to fix the button to be functional again and run the function in the javascript code (and link to my python script), or is there another way to link Javascript within a .erb file to Python?
I'm trying to make modal when i close it it will resolved/return a true value to make the timer continue and delete element if it isn't return false/reject, i don't know how to write it at all. I feel like i can make it somehow with Promise resolved and reject but i don't know how :( .
(to make the timer continue i need to set "timer.pause = false")
class MODAL{
constructor(){
this.modal_container = document.createElement("div")
this.modal_container.classList.add("modal")
document.querySelector("body").appendChild(this.modal_container)
this.overlay = document.createElement("div")
this.overlay.classList.add("overlay")
this.modal_container.appendChild(this.overlay)
this.content_container = document.createElement("div")
this.content_container.classList.add("modal-content")
this.modal_container.appendChild(this.content_container)
this.boxContent = document.createElement("div")
this.boxContent.classList.add("modal-box")
this.content_container.appendChild(this.boxContent)
this.events()
}
close(){
this.modal_container.parentNode.removeChild(this.modal_container);
}
open(content){
this.boxContent.appendChild(content);
}
// EVENTS
events(){
this.closeEvent()
// need to add more
}
closeEvent(){
this.modal_container.addEventListener("click", e =>{
if(!e.target.closest(".modal-box")){
this.close();
}
})
}
}
function Open(issue){
issue.addEventListener("click", () => {
let content = document.createElement("div");
content.classList.add("rows");
let html = `
<div>
<h1 class = "title">TITLE</h1>
</div>
<div>
<input type = "text" placeholder = "מערכת">
</div>
<div>
<input type = "text" placeholder = "פורט">
</div>
<div>
<input type = "text" placeholder = "RIT">
</div>
<div>
<input type = "text" placeholder = "כמה זמן לקח">
</div>
<div>
<input type = "time" placeholder = "התחיל מ">
</div>
<div>
<input type = "time" placeholder = "נגמר ב">
</div>
`
content.innerHTML = html
timer.pause = true
new MODAL().open(content) // when close continue timer (timer.pause = false)
})
}
I think you can work with a callback. To give you some idea, something like:
From your Open(issue) function:
// pass the callback here to continue timer
new MODAL().open(content, () => timer.pause = false);
Then in your MODAL class:
open (content, callbackFn) {
this.boxContent.appendChild(content);
// referenced from your closeEvent() function
this.modal_container.addEventListener("click", e => {
if (!e.target.closest(".modal-box")) {
this.close();
callbackFn(); // trigger the callback function here.
}
});
}
Let me know if this satisfies what you're trying to do.
open(issue) function:
new MODAL().open(content)
.then(value => {
console.log(value);
})
.catch(value => {
console.log(value);
})
MODAL class:
open (content) {
this.boxContent.appendChild(content);
return new Promise((resolve, reject) => {
this.modal_container.addEventListener("click", e => {
if (!e.target.closest(".modal-box")) {
this.close();
reject(false)
}
if (e.target.closest(".submit")) {
this.close();
resolve(true)
}
});
})
}
I'm trying to implement a searchbar to search adresses and show the selected place on a map.
When I type in the searchbar the results are showing in a dropdown, now I want to edit my map and other stuff when I click on a result.
But I can't manage to add a listener to the elements (which are dynamically created when I got the results of the search), no matter what I try (addEventListener, JQuery, href) when I inspect the elements on my browser no listener is attached to any of them.
Here is my html :
<div class="container p-3 text-center text-md-left clearfix">
<h1>Smart-bornes</h1>
<p>Je localise les smart-bornes les plus proches</p>
<div class="input-group dropdown mx-auto w-75 float-md-left">
<input id="localisation_barreRecherche" class="form-control" type="text" placeholder="Rechercher un lieu"/>
<button id="localisation_boutonRecherche" class="btn btn-light">Rechercher</button>
<div id="localisation_dropdownRecherche" class="dropdown-menu w-100"></div>
</div>
</div>
<div class="container p-3">
<div id="map"></div>
</div>
And my JS:
function initBarreRecherche(){
let barreRecherche = document.getElementById('localisation_barreRecherche');
let boutonRecherche = document.getElementById('localisation_boutonRecherche');
let dropdownResultats = document.getElementById('localisation_dropdownRecherche');
barreRecherche.onkeyup = function (event) {
console.log('onkeyup');
if(event.key === 'Enter'){
}else if(event.key === 'keydown'){
}else if(barreRecherche.value !== '') {
rechercheAdr(barreRecherche.value);
$(dropdownResultats).show();
}else{
$(dropdownResultats).hide();
}
};
boutonRecherche.onclick = function () {
}
}
function rechercheAdr(entree){
console.log('recherche');
return new Promise((resolve, reject) => {
fetch(rechercheURL + entree)
.then(resp => {
return resp.text();
})
.then(adressesJSON => {
let adresses = JSON.parse(adressesJSON);
let dropdownResultats = document.getElementById('localisation_dropdownRecherche');
//dropdownResultats.style.width = '100%';
dropdownResultats.style.zIndex = '10000';
let resultats = document.createElement('ul');
resultats.className = 'list-group';
if(adresses.length > 0){
for(let [key, adr] of Object.entries(adresses)){
let result = document.createElement('li');
result.className = 'list-group-item list-group-item-action';
result.href = 'javascript : resultOnClick(adr)';
result.style.paddingLeft = '5px';
result.style.paddingRight = '5px';
result.style.cursor = 'pointer';
//result.style.overflow = 'hidden';
result.innerText = adr.display_name;
result.addEventListener('click', () => console.log('onclick'));
resultats.appendChild(result);
}
}else{
console.log('aucun résultat');
let msgAucunResultat = document.createElement('li');
msgAucunResultat.style.paddingLeft = '5px';
msgAucunResultat.style.paddingRight = '5px';
msgAucunResultat.innerText = 'Aucun résultat';
resultats.appendChild(msgAucunResultat);
}
dropdownResultats.innerHTML = resultats.innerHTML;
console.log(adresses)
})
})
}
manually call initBarreRecherche() at the end of response.
.then(adressesJSON => {
///....
this.initBarreRecherche()
})
You are using jquery so instead of all 'onClick' syntax, or addEventListener, you can attach click handler like:
$(dropdownResultats).on('click', 'li', event => {
alert('some li clicked')
})