drop down search bar on click with history? - javascript

I want to add a feature to my current search bar where if I click, I am able to see a drop down of all the previous inputs. And if I were to click on this previous input, it will run my code again. I am a current boot camp student and I just need guidance into how to make this work. If someone to just point me in the right direction, or explain some sample functions that would be really helpful. Thanks in advance.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
/>
<link rel="stylesheet" href="./assets/style.css" />
<title>Weather Dashboard</title>
</head>
<body onload="load()">
<div class="container">
<div class="card">
<div class="row">
<div class="col-9 left">
<nav class="row top">
<div class="col" id="cityName">City Name</div>
<form class="form-outline">
<input
type="search"
id="userInput"
class="form-control"
placeholder="search for a city"
aria-label="Search"
/>
</form>
<div class="col" id="date">Date</div>
</nav>
<div class="row">
<div class="col-7 temp" id="temperature">15°</div>
<div class="col-5 time">
<p id="time">11:00</p>
<h2 id="today"><b>Saturday</b></h2>
<p id="conditions">Cloudy</p>
</div>
</div>
<div class="row bottom">
<div class="col"><hr /></div>
<div class="col">
<div class="row" id="condition1">Condition</div>
<div class="row data"><img id="conditionIcon1" /></div>
</div>
<div class="col">
<div class="row" id="condition2">Condition</div>
<div class="row data"><img id="conditionIcon2" /></div>
</div>
<div class="col">
<div class="row" id="condition3">Condition</div>
<div class="row data"><img id="conditionIcon3" /></div>
</div>
<div class="col">
<div class="row" id="condition4">Condition</div>
<div class="row data"><img id="conditionIcon4" /></div>
</div>
<div class="col">
<div class="row" id="condition5">Condition</div>
<div class="row data"><img id="conditionIcon5" /></div>
</div>
<div class="col"><hr /></div>
</div>
<div class="row bottom">
<div class="col"><hr /></div>
<div class="col">
<div class="row" id="date1">Sun</div>
<div class="row data" id="date1Temp"><b>0°</b></div>
</div>
<div class="col">
<div class="row" id="date2">Mon</div>
<div class="row data" id="date2Temp"><b>0°</b></div>
</div>
<div class="col">
<div class="row" id="date3">Tue</div>
<div class="row data" id="date3Temp"><b>0°</b></div>
</div>
<div class="col">
<div class="row" id="date4">Wed</div>
<div class="row data" id="date4Temp"><b>0°</b></div>
</div>
<div class="col">
<div class="row" id="date5">Thu</div>
<div class="row data" id="date5Temp"><b>0°</b></div>
</div>
<div class="col"><hr /></div>
</div>
<div class="row bottom">
<div class="col"><hr /></div>
<div class="col">
<div class="row">Humidity</div>
<div class="row data" id="humidity1"><b>0°</b></div>
</div>
<div class="col">
<div class="row">Humidity</div>
<div class="row data" id="humidity2"><b>0°</b></div>
</div>
<div class="col">
<div class="row">Humidity</div>
<div class="row data" id="humidity3"><b>0°</b></div>
</div>
<div class="col">
<div class="row">Humidity</div>
<div class="row data" id="humidity4"><b>0°</b></div>
</div>
<div class="col">
<div class="row">Humidity</div>
<div class="row data" id="humidity5"><b>0°</b></div>
</div>
<div class="col"><hr /></div>
</div>
<div class="row bottom">
<div class="col"><hr /></div>
<div class="col">
<div class="row">Wind Speed</div>
<div class="row data" id="windSpeed1"><b>0°</b></div>
</div>
<div class="col">
<div class="row">Wind Speed</div>
<div class="row data" id="windSpeed2"><b>0°</b></div>
</div>
<div class="col">
<div class="row">Wind Speed</div>
<div class="row data" id="windSpeed3"><b>0°</b></div>
</div>
<div class="col">
<div class="row">Wind Speed</div>
<div class="row data" id="windSpeed4"><b>0°</b></div>
</div>
<div class="col">
<div class="row">Wind Speed</div>
<div class="row data" id="windSpeed5"><b>0°</b></div>
</div>
<div class="col"><hr /></div>
</div>
</div>
<div class="col-3 right">
<div class="row top" id="right-header">Today's Statistics</div>
<div class="timely">
<div class="row">Temp High:<b id="tempHigh">0°</b></div>
<div class="row">Temp Low:<b id="tempLow">0°</b></div>
<div class="row">Feels Like:<b id="feelslike">0°</b></div>
<div class="row">Wind Speed:<b id="windspeed">0°</b></div>
<div class="row">Humidity:<b id="humidity">0°</b></div>
<div class="row">Pressure:<b id="pressure">0°</b></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs#1/dayjs.min.js"></script>
<script>
dayjs().format();
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="./assets/script.js"></script>
</body>
</html>
const date = document.querySelector("#date");
const time = document.querySelector("#time");
const dayOfWeek = document.querySelector("#today");
const input = document.querySelector("#userInput");
date.innerText = moment().format("MMMM Do YYYY");
time.innerText = moment().format("h:mm A");
dayOfWeek.innerText = moment().format("dddd");
// applies elements on page load with current position
function load() {
navigator.geolocation.getCurrentPosition((position) => {
let lat = position.coords.latitude;
let long = position.coords.longitude;
let fiveDayURL = `https://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${long}&appid=b169b31281ffa2a2b70b9e8ac22c3e88&units=imperial`;
fetch(fiveDayURL)
.then((res) => {
return res.json();
})
.then((data) => {
fiveDayWeather(data);
console.log(data);
localStorage.setItem("response", JSON.stringify(data.city.name));
loadUrl();
});
});
}
function loadUrl() {
let cityName = JSON.parse(localStorage.getItem("response"));
let requestURL = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=b169b31281ffa2a2b70b9e8ac22c3e88&units=imperial`;
fetch(requestURL)
.then((res) => {
return res.json();
})
.then((data) => {
// console.log(data);
displayWeather(data);
})
.catch(() => {
alert("Unable to connect to OpenWeather");
});
}
// uses user input as parameter to getApi()
input.addEventListener("keypress", function (e) {
if (e.key === "Enter") {
e.preventDefault();
// let cityName = document.querySelectro("#userInput").value;
// let li = document.createElement("li")
// li.innerText = cityName;
// document.querySelector('ul');
// ul.appendChild(li);
getApi();
input.value = "";
}
});
// fetches api using the user input
function getApi() {
let cityName = document.querySelector("#userInput").value;
let requestURL = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=b169b31281ffa2a2b70b9e8ac22c3e88&units=imperial`;
fetch(requestURL)
.then((res) => {
return res.json();
})
.then((data) => {
// console.log(data);
displayWeather(data);
})
.catch(() => {
alert("Unable to connect to OpenWeather");
});
}
// uses api data from getApi() and replaces text in html
let displayWeather = function (weatherData) {
document.querySelector("#cityName").innerText = weatherData.name;
document.querySelector("#temperature").innerText =
Math.floor(weatherData.main.temp) + "\u00B0";
document.querySelector("#conditions").innerText =
weatherData.weather[0].description;
document.querySelector("#tempHigh").innerText =
weatherData.main.temp_max + "\u00B0 F";
document.querySelector("#tempLow").innerText =
weatherData.main.temp_min + "\u00B0 F";
document.querySelector("#feelslike").innerText =
weatherData.main.feels_like + "\u00B0 F";
document.querySelector("#windspeed").innerText =
weatherData.wind.speed + " MPH";
document.querySelector("#humidity").innerText =
weatherData.main.humidity + "%";
document.querySelector("#pressure").innerText =
weatherData.main.pressure + " hPa";
let fiveDayURL = `https://api.openweathermap.org/data/2.5/forecast?lat=${weatherData.coord.lat}&lon=${weatherData.coord.lon}&appid=b169b31281ffa2a2b70b9e8ac22c3e88&units=imperial`;
fetch(fiveDayURL)
.then((res) => {
return res.json();
})
.then((data) => {
// console.log(data);
fiveDayWeather(data);
})
.catch(() => {
alert("Unable to connect to OpenWeather");
});
};
// obtains lon and lat from previous function then completes new fetch to display 5 day forecast
let fiveDayWeather = function (weatherValue) {
let todaysMonth = dayjs().$M;
for (let i = 1; i < 6; i++) {
document.querySelector("#date" + i).innerText = `${todaysMonth}/${
dayjs().$D + i
}`;
document.querySelector("#date" + i + "Temp").innerText =
weatherValue.list[i].main.temp + "\u00B0 F";
document.querySelector("#condition" + i).innerText =
weatherValue.list[i].weather[0].description;
document.querySelector("#conditionIcon" + i).src =
"http://openweathermap.org/img/wn/" +
weatherValue.list[i].weather[0].icon +
"#2x.png";
document.querySelector("#humidity" + i).innerText =
weatherValue.list[i].main.humidity + "%";
document.querySelector("#windSpeed" + i).innerText =
weatherValue.list[i].wind.speed + "MPH";
}
};

You can store and retrieve the search history as an array to the local storage this way:
// our array
var movies = ["Reservoir Dogs", "Pulp Fiction", "Jackie Brown",
"Kill Bill", "Death Proof", "Inglourious Basterds"];
// storing our array as a string
localStorage.setItem("quentinTarantino", JSON.stringify(movies));
// retrieving our data and converting it back into an array
var retrievedData = localStorage.getItem("quentinTarantino");
var movies2 = JSON.parse(retrievedData);
//making sure it still is an array
alert(movies2.length);
You retrieve the array from local storage and add it to the dropdown of the search box. When you search another query string, push it to the retrieved array and store it to local storage again. Hope it helps!

Hello I saw the code and I could suggest you few points-
Create an array and store the e.target.value from your #userinput when the enter key is pressed. If you want you can store the data in local storage as well at the later stage.
Then through an event listener in the input box mention the values stored in the array in list form(Probably use simple ul, li format combination and then style it later).
You also need to be able to pick the value of the history inputs which user selects and for that one way is to use event listeners in all the items of the array.
Now just call the api or whatever you want to do with the e.target.value from one of the event listeners.

Related

Puppeteer- Need help to extract the text from h2 and span

Absolute beginner here with JS. I need help to extract the text from DOM which looks like this.
Extracting can be done by querySelectorAll() or getElementsByTagName(). But what I'm looking for is to create an object with each h2 element as the key and the span as it's value. I don't have an idea of how this can be achieved. Any suggestions would be very helpful.
<div class ="product-list">
<div class="row column">
<div class="column medium-9 large-10">
<h2 class="product-name">Products List 1</h2>
</div>
</div>
<div class="row">
<span>First Product</span>
</div>
<div class="row">
<span> Second Product</span>
</div>
.
.
.
<div class="row">
<span>
Nth Product
</span>
</div>
<div class="row column">
<div class="column medium-9 large-10">
<h2 class="product-name">Products List 2</h2>
</div>
</div>
<div class="row">
<span>Thrid Product</span>
</div>
<div class="row">
<span> Fourth Product</span>
</div>
.
.
.
<div class="row">
<span>
Nth Product
</span>
</div>
</div>
From this DOM I need to store the data as
[
Products List 1 :[First Product,Second Product...Nth Product],
Products List 2 :[Third Product,Fourth Product...Nth Product]
]
JS:
const products=await page.evaluate(()=>{
const productsArray=[];
var pdName1=document.querySelectorAll('div.column > h2.product-name');
var pdName2=document.querySelectorAll("div.row > span")
pdName2.forEach(query=>{
productArray.push(query.innerText)
})
return productArray
})
You can try something like this:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const html = `
<!doctype html>
<html>
<head><meta charset='UTF-8'><title>Test</title></head>
<body>
<div class ="product-list">
<div class="row column">
<div class="column medium-9 large-10">
<h2 class="product-name">Products List 1</h2>
</div>
</div>
<div class="row"><span>First Product</span></div>
<div class="row"><span> Second Product</span></div>
<div class="row"><span>Nth Product</span></div>
<div class="row column">
<div class="column medium-9 large-10">
<h2 class="product-name">Products List 2</h2>
</div>
</div>
<div class="row"><span>Thrid Product</span></div>
<div class="row"><span> Fourth Product</span></div>
<div class="row"><span>Nth Product</span></div>
</div>
</body>
</html>`;
try {
const [page] = await browser.pages();
await page.goto(`data:text/html,${html}`);
const data = await page.evaluate(() => {
const elements = document.querySelectorAll('h2, div.row span');
const list = {};
let currentKey = null;
for (const element of elements) {
if (element.tagName === 'H2') {
currentKey = element.innerText;
list[currentKey] = [];
} else {
list[currentKey].push(element.innerText);
}
}
return list;
});
console.log(data);
} catch (err) { console.error(err); } finally { await browser.close(); }

Why do I get undefined when I change from querySelector to querySelectorAll? [duplicate]

This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 3 years ago.
When I change from querySelector to querySelectorAll I get undefined. I know that the spelling for the class name is correct. So, I posted the rest of the code assuming that there is something else that I must be missing.
//TAKES INPUT FORM AND PLACES TEXT ON CARD
var input1 = document.querySelector('.form1');
var input2 = document.querySelectorAll('.form2');
var textOnCard = document.getElementById('btn');
btn.addEventListener('click', function() {
document.getElementById('flashcard__front').innerHTML = input1.value
document.getElementById('flashcard__back').innerHTML = input2.value
});
//FUNCTION THAT ALLOWS CARD TO ROTATE
var flashcard = document.querySelector('.flashcard');
flashcard.addEventListener('click', function() {
flashcard.classList.toggle('flip');
});
//CREATES A NEW INPUT FIELD
var inputHtml = '<div class="container mt-5"><div class="row"><div class="col-lg-12 text-center"><form id="form" action=""><div><input type="text" class="form1">'+ ' ' + '<input type="text" class="form2">' + ' ' + '</div></form></div></div>'
var addInputField = document.getElementById('addInputField');
addInputField.addEventListener('click', function() {
textOnCard.insertAdjacentHTML("afterend", inputHtml)
});
//make array apppear on screen
var flashcardFront = [];
var flashcardBack = [];
var number = 0;
var rightArrow = document.getElementById('rightArrow');
var leftArrow = document.getElementById('leftArrow');
textOnCard.addEventListener('click', function(){
flashcardFront.push(input1.value);
flashcardBack.push(input2.value);
flashcard__front.innerHTML = flashcardFront[0];
flashcard__back.innerHTML = flashcardBack[0];
console.log(Array.from(input1));
})
rightArrow.addEventListener('click', function(){
if (number < flashcardFront.length - 1 && number < flashcardBack.length - 1){
number++;
} else {
number = 0
}
console.log(number);
document.getElementById('flashcard__front').innerHTML = flashcardFront[number];
document.getElementById('flashcard__back').innerHTML = flashcardBack[number];
});
leftArrow.addEventListener('click', function(){
if (number > flashcardFront.length && number > flashcardBack.length){
number--;
} else {
number = 0
}
console.log(number);
document.getElementById('flashcard__front').innerHTML = flashcardFront[number];
document.getElementById('flashcard__back').innerHTML = flashcardBack[number];
});
<div class="container mt-5">
<div class="row">
<div class="col-lg-12 text-center">
<input type="text" class="form1">
<input type="text" class="form2">
<button class="btn btn-primary text-center" id="btn">SUBMIT</button>
</div>
</div>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-lg-12 text-center">
<input type="text" class="form1">
<input type="text" class="form2">
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<button class="btn btn-primary" id="addInputField">ADD A NEW INPUT</button>
</div>
</div>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-lg-12">
<div class="flashcard">
<div class="flashcard__side flashcard__side--front">
<h1 id="flashcard__front" class="text-center m-3"></h1>
</div>
<div class="flashcard__side flashcard__side--back">
<h1 id="flashcard__back" class="text-center m-3"></h1>
</div>
</div>
</div>
</div>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-lg-12">
<h3 id="testField" class="pl-5"></h3>
</div>
</div>
<div class="row">
<div class="col-md-6">
<i class="fas fa-arrow-left" id="leftArrow"></i>
</div>
<div class="col-md-6">
<i class="fas fa-arrow-right" id="rightArrow"></i>
</div>
</div>
</div>
For context, I am trying to recreate the flashcard feature from quizlet.com for practice.
Because .querySelectorAll() returns a node-list (an array-like container object), not an individual node. So, this line:
var input2 = document.querySelectorAll('.form2');
Creates a collection of all the elements with a class of form2.
Later, when you do this:
document.getElementById('flashcard__back').innerHTML = input2.value
You are saying that you want to get the value of the collection, but the collection doesn't have a value property, individual nodes do, so the flashcard__back element gets .innerHTML of undefined.
You'll have to identify which node within the list you want by passing an index to the node-list and then you can work with properties/methods of nodes.

Variable incrementation is not working

I have a button in HTML, and I want to increase a JavaScript variable value when clicked:
<a id="right-btn" onclick="increasePokemon_ID()">
Here is the script:
var pokemon_ID = 1;
function increasePokemon_ID() {
pokemon_ID++;
}
I also tried this way, but none of them worked:
document.getElementById("right-btn").onclick = function() {
increasePokemon_ID();
}
The value is outputted in this div:
document.getElementById("id-number").innerHTML="no. 00" + pokemon_ID;
<div id="id-number"></div>
What is wrong in the code?
Full code:
<?php
require 'database.php';
$id = null;
if ( !empty($_GET['id'])) {
$id = $_REQUEST['id'];
}
if ( null==$id ) {
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM pokemons where id = ?";
$q = $pdo->prepare($sql);
$q->execute(array($id));
$data = $q->fetch(PDO::FETCH_ASSOC);
Database::disconnect();
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<div id="pokedex">
<div id="left">
<div id="top-left">
<div id="top-leds">
<div id="top-red-led"></div>
<div id="top-yellow-led"></div>
<div id="top-green-led"></div>
</div>
</div>
<div id="led"></div>
<div id="left-triangle"></div>
<div id="screen-border">
</div>
<div id="screen">
<div class="name"><?php echo $data['name'];?></div>
</div>
<div id="cross">
<div id="center">
<div id="cross-center">
<div id="center-circle"></div>
</div>
<div id="up-btn">
<div id="upAr"></div>
</div>
<a id="right-btn" onclick="increasePokemon_ID()">
<div id="rightAr"></div>
</a>
<div id="left-btn">
<div id="leftAr"></div>
</div>
<div id="down-btn">
<div id="downAr"></div>
</div>
</div>
</div>
<div id="id-number"></div>
<div id="blue-btn"></div>
</div>
<div id="middle">
<div id="charniere-haute"></div>
<div id="charniere-basse"></div>
</div>
<div id="right">
<div id="info-screen"></div>
<div id="right-triangle"></div>
<div id="left-arrow-button">
<div id="left-arrow"></div>
</div>
<div id="right-arrow-button">
<div id="right-arrow"></div>
</div>
<div id="keyboard">
<div class="top-key"></div>
<div class="top-key"></div>
<div class="top-key"></div>
<div class="top-key"></div>
<div class="top-key"></div>
<div class="bottom-key"></div>
<div class="bottom-key"></div>
<div class="bottom-key"></div>
<div class="bottom-key"></div>
<div class="bottom-key">Help</div>
</div>
<div id="type-display1"><?php echo $data['type'];?></div>
<div id="type-display2"></div>
</div>
</div>
<script>
var pokemon_ID = 0;
function increasePokemon_ID() {
pokemon_ID++;
document.getElementById("id-number").innerHTML="no. 00" + pokemon_ID;
}
document.getElementById("right-btn").onclick = function() {
increasePokemon_ID();
}
</script>
</body>
</html>
The value is actually being incremented, but you're not showing the updated value to the div.
Try this:
var pokemon_ID = 0;
var el = document.getElementById("id-number");
function increasePokemon_ID() {
pokemon_ID++;
el.innerHTML = "no. 00" + pokemon_ID;
}
<a id="right-btn" onclick="increasePokemon_ID()">
<div id="id-number">0</div>
This is because you are not updating the HTML on click, but just updating the value of a variable. You can add the document.getElementById("id-number").innerHTML="no. 00" + pokemon_ID; to your onclick function or to the increasePokemon_ID function.

Loop through an array of div's to determine if every element has a child

I am looping through an array of div's and I need to check to see if every element of the array has a child element.
Running the code below will console.log for each element, however I only want to console.log "a child exists!" on the condition that every tile in tilesArray has a child element. How can this be achieved?
function hasTile(tilesArray){
for(var i = 0; i < tilesArray.length; i++){
console.log(tilesArray[t]);
if(tilesArray[i].firstChild){
console.log("A child exists!");
}else{
console.log("No child.");
}
}
}
index.html
<div class="container" id="tileContainer">
<!-- id listed by row-column notation. -->
<div class="row">
<div class="col-xs-6 col-md-12 tile" id="r1c1" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r1c2" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r1c3" onclick="main(this)"></div>
</div>
<div class="row">
<div class="col-xs-6 col-md-12 tile" id="r2c1" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r2c2" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r2c3" onclick="main(this)"></div>
</div>
<div class="row">
<div class="col-xs-6 col-md-12 tile" id="r3c1" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r3c2" onclick="main(this)"></div>
<div class="col-xs-6 col-md-12 tile" id="r3c3" onclick="main(this)"></div>
</div>
</div>
<!-- End of tile container -->
<div class="container" id="turnDisplayContainer">
<div class="row">
<div class="col-xs-9 col-md-6 content" id="userTurnDisplay">
<h4>Your Turn</h4>
</div>
<div class="col-xs-9 col-md-6 content" id="computerTurnDisplay">
<h5>Computer's Turn</h5>
<iframe src="assets/media/loading-wheel.gif" width="50" height="50" scrolling="no" frameBorder="0"></iframe>
</div>
</div>
</div>
<!-- <div class="container" id="timerDisplayContainer">
<div class="row">
<div class="col-xs-18 col-md-12 content" id="timerDisplay">
<h5>Timer</h5>
</div>
</div>
</div> -->
<div class="container btnContainer">
<div class="row">
<button type="button" class="btn btn-danger" id="resetButton">Reset</button>
</div>
</div>
<img class="img img-responsive gameIcon" src="assets/img/green-ring.png" alt="Green Ring Icon" id="userIcon" />
<img class="img img-responsive gameIcon" src="assets/img/red-x.png" alt="Red X Icon" id="computerIcon" />
You should store an additional info in a local variable. Example:
function hasTile(tilesArray){
var bAllHaveChild = tilesArray.length > 0;
for(var i = 0; i < tilesArray.length; i++){
console.log(tilesArray[t]);
if(!tilesArray[i].firstChild){
bAllHaveChild=false;
}
}
if(bAllHaveChild)
console.log("A child exists!");
else
console.log("No child.");
}
I hope it helps. Bye
UPDATED
I came up with a much more performant way of doing this. This particular problem is well suited for XPath via document.evaluate. With XPath you have the ability to create a selection path on elements that have content.
While I believe these should beat out the other options here in a foot race, the XPath typically comes in 5 times faster than the querySelectorAll filtering version.
const xpath = 'boolean(.//div/div/text())'
const hasTileXPath = (id) => document.evaluate(xpath, document.getElementById(id)).booleanValue
const hasTile = (id) => Array.from(
document.querySelectorAll(`#${id} > div > div`)
).filter((x) => x.innerHTML).length > 0
const iterations = 1000
const iterable = Array(iterations).fill().map((x, i) => i)
const pre = performance.now()
for(let i of iterable) {
hasTileXPath('hasNoTiles')
hasTileXPath('hasTiles')
}
const mid = performance.now()
for(let i of iterable) {
hasTile('hasNoTiles')
hasTile('hasTiles')
}
const last = performance.now()
console.info(`XPath: ${iterations} iterations # ${(mid - pre) / 1000}s`)
console.info(`SHOULD NOT HAVE TILES (XPATH) => ${hasTile('hasNoTiles')}`)
console.info(`SHOULD HAVE TILES (XPATH) => ${hasTile('hasTiles')}`)
console.info(`querySelectorAll: ${iterations} iterations # ${(last - mid) / 1000}s`)
console.info(`SHOULD NOT HAVE TILES => ${hasTileXPath('hasNoTiles')}`)
console.info(`SHOULD HAVE TILES => ${hasTileXPath('hasTiles')}`)
<div id="hasNoTiles">
<div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
</div>
</div>
<div id="hasTiles">
<div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div>TILE</div>
</div>
<div>
<div></div>
<div>TILE</div>
</div>
</div>
A compact way of doing it would be to check the length of the .tile:empty collection by using querySelectorAll(). If it is 0 then all the divs have child elements; if not then you can loop through the array and console.log them all.
((tiles,len,x)=>{
if(!len=(tiles=document.querySelectorAll(".tile:empty")).length)
console.log("All .tile elements contain child elements.");
else
for(x=0;x<len;x++)
console.log("div#"+tiles[x].id+" does not contain any child elements.");
})();
(Apologies for the lack of a working example or for any potential typos; I wrote this up on my phone - I'll clean it up when I get back to a computer)
You could return out of the function whenever a div without a child is found. That way the console.log won't fire unless all divs has children.
function hasTile(tilesArray){
tilesArray.forEach(function(element) {
if (element.children.length < 1) {
return;
}
});
console.log("a child exists!");
}
var tilesArray = Array.prototype.slice.call(tilesArray);
var fails = tilesArray.some(function(element) {
return element.children.length === 0;
})
if (fails) {
console.log("No child.");
} else {
console.log("A child exists!");
}

Error in d3.js using jQuery and dc.js

I'm new in programming, and I'm trying to implement a search button that can enable me to filter datas .
I have on my serv a JSON data at the url /tweets_complet . Then I want to get another JSON which depends on the input from the search button . Once I have the two JSON, I wrote some code, which I think is not important .
Here is the js code :
function main(){
$.getJSON("/tweets_complet", insererDonneesJson);}
function insererDonneesJson(data){
$('button').on('click', get_data);
function get_data() {
var cashtagg=$('#cash').val();
$.getJSON("/"+cashtagg, filter);
function filter(data2) {
//Tweets datas
var tweets = data;
var dateFormat = d3.time.format("%Y-%m-%d %H:%M:%S");
tweets.forEach(function(d) {
d["cleandate"] = dateFormat.parse(d["cleandate"]);
d["cleandate"].setSeconds(0);
});
//Create a Crossfilter instance
var ndx = crossfilter(tweets);
//Define Dimensions
var cleandateDim = ndx.dimension(function(d) { return d["cleandate"]; });
var sentimentDim=ndx.dimension(function(d) { return d["sentiment"]; });
var bnscoreDim=ndx.dimension(function(d) { return d["bnscore"]; });
var tickerDim=ndx.dimension(function(d) { return d["collection_name"];});
var newTickerDim = tickerDim.filter(cashtagg);
//Calculate metrics
var numTweetsByTicker=newTickerDim.group()
var numTweetsByDate = cleandateDim.group();
var numTweetsByBnscore = bnscoreDim.group();
var totalScoreByDate = cleandateDim.group().reduceSum(function(d) {
return d["sentiment"]*10/(numTweetsByDate.size());})
var all = ndx.groupAll();
var numTweetsBySentiment = sentimentDim.group();
//Define values (to be used in charts)
var minDate = cleandateDim.bottom(1)[0]["cleandate"];
var maxDate = cleandateDim.top(1)[0]["cleandate"];
//Datas cashtag
var datas = data2;
var dateFormatO = d3.time.format("%Y-%m-%d");
datas.forEach(function(d) {
d["Date"] = dateFormatO.parse(d["Date"]);
});
// Create a Crossfilter instance
var ndxO = crossfilter(datas);
// Define Dimensions
var dateDimO = ndxO.dimension(function(d) { return d["Date"]; });
var volumeDimO=ndxO.dimension(function(d) { return d["Volume"]; });
var scoreDimO=ndxO.dimension(function(d) { return d["Low"]; });
// Calculate metrics
var groupeVolumeO = dateDimO.group().reduceSum(function(d) { return d["Volume"]/10000000;});
var groupeScoreO = dateDimO.group().reduceSum(function(d) { return d["Low"];});
var allO = ndxO.groupAll();
// Define values (to be used in charts)
var minDateO = dateDimO.bottom(1)[0]["Date"];
var maxDateO = dateDimO.top(1)[0]["Date"];
var minVolumeO = (volumeDimO.bottom(1)[0]["Volume"])/10000000;
var maxVolumeO = (volumeDimO.top(1)[0]["Volume"])/10000000;
var minScoreO = scoreDimO.bottom(1)[0]["Low"];
var maxScoreO = scoreDimO.top(1)[0]["Low"];
//Charts
var timeChart = dc.barChart("#time-chart");
var pieChart= dc.pieChart("#pie-chart")
var numberTweetsND = dc.numberDisplay("#number-tweets-nd");
var hitslineChart = dc.lineChart("#chart-line-hitsperday");
var shareChart = dc.lineChart("#share-chart");
var volumeChart = dc.lineChart("#volume-chart");
numberTweetsND
.formatNumber(d3.format("d"))
.valueAccessor(function(d){return d; })
.group(all);
timeChart
.width(800)
.height(160)
.margins({top: 10, right: 50, bottom: 30, left: 50})
.dimension(cleandateDim)
.group(numTweetsByDate)
.transitionDuration(500)
.x(d3.time.scale().domain([minDate, maxDate]))
.elasticY(true)
.xAxisLabel("Day")
.yAxis().ticks(8);
pieChart.width(350)
.height(330)
.dimension(sentimentDim)
.group(numTweetsBySentiment)
.colors(['red','black','green']);
hitslineChart
.width(600).height(330)
.dimension(cleandateDim)
.group(totalScoreByDate)
.x(d3.time.scale().domain([minDate,maxDate]));
volumeChart
.width(800).height(330)
.dimension(dateDimO)
.group(groupeVolumeO)
.x(d3.time.scale().domain([minDateO,maxDateO]));
// .y(d3.scale.linear().domain([minVolumeO,maxVolumeO]));
shareChart
.width(800).height(330)
.dimension(dateDimO)
.group(groupeScoreO)
.x(d3.time.scale().domain([minDateO,maxDateO]));
// .y(d3.scale.linear().domain([minScoreO,maxScoreO]));
dc.renderAll();
}}};
$(document).on('ready', main);
And the HTML code :
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
<link rel="stylesheet" href="./static/lib/css//bootstrap.min.css">
<link rel="stylesheet" href="./static/lib/css/keen-dashboards.css">
<link rel="stylesheet" href="./static/lib/css/dc.css">
<link rel="stylesheet" href="./static/css/custom.css">
</head>
<body class="application">
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="./">InTwittiv</a>
</div>
<div>
<ul class="nav navbar-nav">
<li class="active">Description</li>
<li>Analyse</li>
</ul>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<!-- <a href="#" class="btn btn-default btn-lg"><span class="glyphicon glyphicon-search"></span>
<div class="col-sm-10">
<input type="text" class="form-control" id="cashtag" placeholder="Cashtag">
</div>
</a> -->
<div class="col-sm-3 col-md-3 pull-right">
<div class="form-group">
<input id="cash" type="text" placeholder="Change Cashtag here" >
<button class="btn btn-sm btn-success">Chercher</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-sm-6">
<div class="row">
<div class="col-sm-12">
<div class="chart-wrapper">
<div class="chart-title">
Tweet Volume
</div>
<div class="chart-stage">
<div id="time-chart"></div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="chart-wrapper">
<div class="chart-title">
Sentiment repartition
</div>
<div class="chart-stage">
<div id="pie-chart"></div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="chart-wrapper">
<div class="chart-title">
Sentiment repartition
</div>
<div class="chart-stage">
<div id="chart-line-hitsperday"></div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="chart-wrapper">
<div class="chart-title">
Total nb of tweets
</div>
<div class="chart-stage">
<div id="number-tweets-nd"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="row">
<div class="col-sm-12">
<div class="chart-wrapper">
<div class="chart-title">
Volume (*10^6)
</div>
<div class="chart-stage">
<div id="volume-chart"></div>
</div>
</div>
</div>
<div class="col-sm-12">
<div class="chart-wrapper">
<div class="chart-title">
Share Price
</div>
<div class="chart-stage">
<div id="share-chart"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<hr>
<p class="small text-muted">Built by Keyrus Capital Markets</p>
</div>
<script src="http://code.jquery.com/jquery.min.js"></script>
<script src="./static/lib/js/bootstrap.min.js"></script>
<script src="./static/lib/js/crossfilter.js"></script>
<script src="./static/lib/js/d3.js"></script>
<script src="./static/lib/js/dc.js"></script>
<script src="./static/lib/js/queue.js"></script>
<script src="./static/lib/js/d3.layout.cloud.js"></script>
<script src="./static/lib/js/keen.min.js"></script>
<script src='./static/js/graph2.js' type='text/javascript'></script>
</body>
</html>
When I run the serv, I can enter a value in the input (FB for example) and it works . However, from here, I can't change the "cash" value into something else like AAPL since I get the error
Uncaught TypeError: undefined is not a function
d3.js:2716
This line is :
var n = d3_time_numberRe.exec(string.slice(i, i + 4));
I have no clue about the reason of the issue since I'm not familiar with $ and buttons...
Any help would be appreciated :)

Categories

Resources