Issues with HTML not populating multiple containers respectively - javascript

I have two on-click functions, which are leveraged by the addFields and addSites functions to pull in two different variables and populate them to their respective dynamically generated html containers. addFields is supposed to populate "container1" and addSites is supposed to populate "container2". For some reason though, only one of the containers is ever populated, the bottom one (container2).
I have a hunch that this is because the onClick function only invokes one of the data retrieval functions where I would need it to do both in order to populate both containers(Both containers should be populated with their respective data simultaneously). Nevertheless I am unsure of how to fix it, and I don't understand why it would only populate container2...
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
</head>
<body>
<div class="container">
<p align="justify" style="font-family:helvetica,garamond,serif;font-size:16px;font-style:regular;" class="light">
<b>BigQuery Function</b></p>
<p align="justify" style="font-family:helvetica,garamond,serif;font-size:12px;font-style:regular;" class="light">
Select from the library of popular BigQuery functions to add a sheet or update one that you've already added.</p>
</div>
<div class="row">
</div>
<div class="container">
<hr>
<div class="row">
<input href="#" class="btn blue rounded" id="runQuery" type="button" value=" Get Customer Accounts " />
<div class="container">
<p align="justify" style="font-family:helvetica,garamond,serif;font-size:12px;font-style:regular;" class="light">
Selects all accounts and adds them to a sheet called <b>'All Accounts'</b>.</p>
<div id="container1"></div>
</div>
<hr>
<div class="row">
<input href="#" class="btn blue rounded" id="runQuerySites" type="button" value=" Get Sites " />
<div class="container">
<p align="justify" style="font-family:helvetica,garamond,serif;font-size:12px;font-style:regular;" class="light">
Selects all Sites and adds them to a sheet called <b>'All Sites'</b>.</p>
<div id="container2"></div>
</div>
</div>
</div>
<div id="container"></div>
<div class="row">
<hr>
</div>
<style>
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background-color: light-grey;
color: light-grey;
text-align: center;
}
</style>
<div class="footer">
<input href="#" class="btn grey small rounded" id="showSidebarIntro" type="button" value="Return to Intro" />
</div>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script type='text/javascript'>
var g_fieldNames;
var g_siteNames;
console.log('calling get variables....');
getFieldNames();
getSiteNames();
function addFields(fieldNames) {
console.log('addFields is running');
// Container <div> where dynamic content will be placed
var container = document.getElementById("container1");
// Clear previous contents of the container
while (container.hasChildNodes()) {
container.removeChild(container.lastChild);
}
// Append a node with a random text
container.appendChild(document.createTextNode("Last update: " + fieldNames));
// Create an <input> element, set its type and name attributes
// Append a line break
container.appendChild(document.createElement("br"));
//add to global for other uses
g_fieldNames = fieldNames;
}
function addSites(siteNames) {
console.log('addFields is running');
// Container <div> where dynamic content will be placed
var container = document.getElementById("container2");
// Clear previous contents of the container
while (container.hasChildNodes()) {
container.removeChild(container.lastChild);
}
// Append a node with a random text
container.appendChild(document.createTextNode("Last update: " + siteNames));
// Create an <input> element, set its type and name attributes
// Append a line break
container.appendChild(document.createElement("br"));
//add to global for other uses
g_siteNames = siteNames;
}
document.getElementById('runQuery').addEventListener('click', function () {
google.script.run
.withFailureHandler(onFailure)
.withSuccessHandler(onSuccess)
.runQuery();
});
document.getElementById('runQuerySites').addEventListener('click', function () {
google.script.run
.withFailureHandler(onFailure)
.withSuccessHandler(onSuccess)
.runQuerySites();
});
document.getElementById('showSidebarIntro').addEventListener('click', function () {
google.script.run
.showSidebarIntro();
});
function getFieldNames() {
google.script.run
.withFailureHandler(onFailure)
.withSuccessHandler(onSuccess)
.BQaccountsUpdate();
console.log('getVariables1 ran!');
}
function getSiteNames() {
google.script.run
.withFailureHandler(onFailure)
.withSuccessHandler(onSuccess)
.BQsitesUpdate();
console.log('getVariables2 ran!');
}
function onSuccess(fieldNames_fromDoc) {
console.log('onSuccess ran!');
addFields(fieldNames_fromDoc);
}
function onSuccess(siteNames_fromDoc) {
console.log('onSuccess ran!');
addSites(siteNames_fromDoc);
}
function onFailure(){
console.log('Failure is just an oppertunity for growth!');
}
</script>
</html>

You've got a duplicate function name, and second is overwriting the first:
function onSuccess(fieldNames_fromDoc) {
console.log('onSuccess ran!');
addFields(fieldNames_fromDoc);
}
function onSuccess(siteNames_fromDoc) {
console.log('onSuccess ran!');
addSites(siteNames_fromDoc);
}
The first definition is never saved. You could simply rename the second function, then make sure you invoke it where you want to, ie .withSuccessHandler(onSuccessNewName) or whatever.

Related

Call JS function onclick

The sample code below loads a page with a "Show 3D" clickable div. Onclick, it should load a 3D viewer and display associated data.
function showPDB(path,id) {
var stage = new NGL.Stage(id, {backgroundColor:'white'});
stage.loadFile(path).then(function (o) {
o.addRepresentation("cartoon", {color: 'white' });
o.autoView();
});
};
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/ngl#latest/dist/ngl.min.js"></script>
</head>
<body>
<div class="row">
<div class="col" data-toggle="collapse" data-target="#show_0" id="_show_0" onclick="showPDB('https://alphafold.ebi.ac.uk/files/AF-P08047-F1-model_v4.pdb', 'viewport_0')">
<b>Show 3D</b>
</div>
</div>
<div id="show_0" class="collapse">
<div class="row">
<div class="col">
<div id="viewport_0" style="width:100%; height:800px;"></div>
</div>
</div>
</div>
</body>
</html>
It seems that "Show 3D" needs to be clicked twice for the 3D viewer to load. I would like it to load upon a single click.
I guess this function should be triggered only when the inside of the collapsible element has been fully loaded. I tried to tweak in this direction but I could not find a fix yet.
As it is a collapsible, just give some time to the collapsible to load. TO do that, you can wrap the entire script inside a set timeout like below
function showPDB(path,id) {
setTimeout(() => {
var stage = new NGL.Stage(id, {backgroundColor:'white'});
stage.loadFile(path).then(function (o) {
o.addRepresentation("cartoon", {color: 'white' });
o.autoView();
});
});
};

Can't save an API as an object

NETWORK TABWith the code I have I want the console log to pass 6983839 to the console but it stays empty the whole time and the page refreshes. The endpoint of the API is here. The function is executed by a button press which I'm 99% sure isnt the issue as it works when a change the function to do something else and I have jQuery in my folder for the project aswell and linked in the html file. The code is my JS file is below,
function showCard() {
var cardName = document.getElementById('un').value;
var cardNameProper = cardName.replace(/\s/g,'');
$.getJSON("https://db.ygoprodeck.com/api/v7/cardinfo.php?name=Tornado%20Dragon", null, function(info){
var result = info["data"][0]["id"]
console.log(result)
})
}
Also including the HTML code incase its relevant
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="jquery-3.5.1.js"></script>
<script type="text/javascript" src="javascript.js"></script>
<style>
.title{
color: white;
}
.cardSearch{
text-color: white;
}
#searchBox{
margin-right: 20px;
}
#chosenCard{
width: 177px;
height: 254px;
}
</style>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div id="header-img" class="container-fluid">
<div class="card card-body bg-dark">
<div class="rows">
<div class="col-ms-8">
<img src="yugioh.png" class = "img-responsive mx-auto d-block"/>
</div>
<div class="col-ms-4 text-center">
<h4 class="title">Combo Builder</h4>
<div id="searchBox">
<form id="cardSearch">
<input type="text" size="12" id="un" />
<input type="submit" onclick="showCard();" value="Submit Card"/>
</form>
<img id="chosenCard" scr="cardBack.jpg">
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

Using jquery and thymeleaf how do I create dynamic buttons each with their own event listener

My goal is to build a dynamic FAQ page where the questions are visible, and when you click on the said question the div with the answer would appear. Once you click the div again it would toggle again.
I've tried a few things and the best result I've accomplished was toggling the first question's answer regardless of what question was clicked.
<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<link href="./img/favicon.png" rel="shortcut icon"/>
<meta charset="utf-8"/>
<meta content="width=1280, maximum-scale=1.0" name="viewport"/>
<link th:href="#{css/faq.css}" rel="stylesheet" type="text/css"/>
<link th:href="#{css/faq-new.css}" rel="stylesheet" type="text/css"/>
</head>
<body style="margin: 0;
background: rgba(255, 255, 255, 1.0);">
<input id="anPageName" name="page" type="hidden" value="faq"/>
<div class="faq">
<th:block th:insert="_header.html :: header"></th:block>
<div class="rectangle2">
</div>
<div class="justaskus">
Just Ask Us
</div>
<!-------========= FAQ =========------------->
<div class="faq-container">
<div class="th-start" th:block th:each="faqType, stats : ${faqTypeDaoList}">
<div class="q-type-wrapper">
<div class="type-header">
<h4 th:text="${faqType.faqTypeName}"></h4>
</div>
<!----========= Question ========--------->
<div class="th-wrap" th:each="question, stat: ${faqTypeDaoList[_${stats.index}_].faqList}">
<a href="#">
<div id="box" class="question-box">
<div class="bullet"></div>
<img th:src="#{img/artboard-copy-3-unnamed-3#2x.png}" class="arrow"/>
<img th:src="#{img/artboard-copy-3-unnamed-13#2x.png}" class="unnamed" style="display:none;"/>
<div class="questions" th:text="${faqTypeDaoList[_${stats.index}].faqList[${stat.index}_].question}"></div>
<div id="answers" class="dropdown-answer" th:text="${faqTypeDaoList[_${stats.index}].faqList[${stat.index}_].answer}"></div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script>
$(document).ready(function() {
$('#box').on("click", ()=> {
$(this).children[3].toggle();
});
});
</script>
That is my current code and it does absolutely nothing. Here are a few attempts I took
/* One attempt */
$('.questions').on("click",function(){
// "this" in $(this) --> means the current clicked element
// .find() will search the CHILDREN of the clicked element with the class "sub-nav"
$(this).find("dropdown-answer").toggle();
});
/* Another attempt. This one toggled only the first question's answer regardless if what button was clicked. */
var click = document.getElementById("dropdown-answer");
if(click.style.display === "none") {
click.style.display = "block";
}
else {
click.style.display = "none";
}
Is this even possible?
find() will find children inside the element you provide (so in this case you put this in it so .questions) but your .dropdown-answer is not a child of that element.
you can write it like this
$(this " + .dropdown-answer").toggle();
Or place the element inside the .questions element and get it like this
$(this).find(".dropdown-answer").toggle();

Iterate through a JSON list with JS function

I'm looking for a way to append some JSON results, I'm working with a list (array?) and there's multiple elements, I know I can add some styling directly in the JS code but I'm more comfortable with this method. How can I iterate through elements and implement in some divs, then create similar divs with the next elements.
The only way to achieve that goal afaik is like this:
$("#article").append(data[i].datetime + data[i].headline + "<br />" + "<hr />" + data[i].summary);
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Project JS 02</title>
<link rel="stylesheet" href="assets/main.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div class="container container-table">
<div class="row vertical-center-row">
<div class="col-md-4 col-md-offset-4">
<button type="submit" class="btn btn-primary" style="width: 100%" class="search" id="getnews">Get News!</button>
<h1 id="headline"></h1><br>
<h3 id="datetime"></h3><br>
<div id="summary"></div><br>
<h6 id="source"></h6><br>
</div>
</div>
</div>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script>
document.getElementById("getnews").addEventListener("click", function () {
var newsurl = "https://api.iextrading.com/1.0/stock/aapl/news"
$.getJSON(newsurl, function (data) {
for (i in data)
{
$("#headline").append(data[i].headline);
$("#datetime").append(data[i].datetime);
$("#summary").append(data[i].summary);
$("#source").append(data[i].source);
}
})
})
</script>
</body>
</html>
You can do this by creating the elements (with jQuery) as needed, and appending them to a container:
$("#getnews").on("click", function () {
var newsurl = "https://api.iextrading.com/1.0/stock/aapl/news"
$('#data').text("...loading...");
$.getJSON(newsurl, function (data) {
$('#data').html("");
data.forEach(function (article) {
$('#data').append(
$('<h1>').text(article.headline),
$('<h3>').text(article.datetime),
$('<div>').text(article.summary),
$('<h6>').text(article.source)
);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btn btn-primary search"
style="width: 100%" id="getnews">Get News!</button>
<div id="data"></div>
First: remove the ids. If you want to create similar containers, the ids will be there multiple times, that won't work.
Second: Take the div with $('.row.vertical-center-row') and clone it.
Third: set the values at the cloned HTMLNode und append it to $('.container.container-table')
Something like that (untested):
<div class="container container-table">
<div class="row vertical-center-row">
<div class="col-md-4 col-md-offset-4">
<button type="submit" class="btn btn-primary" style="width: 100%" class="search" class="getnews">Get News!</button>
<h1 class="headline"></h1><br>
<h3 class="datetime"></h3><br>
<div class="summary"></div><br>
<h6 class="source"></h6><br>
</div>
</div>
</div>
<script>
document.getElementsByClassName("getnews").forEach((el)=>el.addEventListener("click", function () {
var newsurl = "https://api.iextrading.com/1.0/stock/aapl/news"
$.getJSON(newsurl, function (data) {
var $elClone = $('.row.vertical-center-row').clone(true).appendTo($('.container.container-table'));
for (i in data) {
$(".headline", $elClone).append(data[i].headline);
$(".datetime", $elClone).append(data[i].datetime);
$(".summary", $elClone).append(data[i].summary);
$(".source", $elClone).append(data[i].source);
}
})
}));
</script>

Angularjs fails to dynamic change image src

Hello i'm building an application where i want to dynamically change the source of an image in order to force reload it . The problem is that in order of this i only get a broken image on the browser. Instead , if a run the function manually by a button it runs perfect .
HTML document
<!DOCTYPE html>
<html lang="en" ng-app='cameraApp'>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Node JS Camera</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src='https://code.angularjs.org/1.4.4/angular-sanitize.min.js'></script>
<script src="cameraApp.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="jumbotron">
<h1>Welcome to NodeJS Camera v1</h1>
</div>
<div ng-controller="HomeController">
<div class="cameraControl col-md-5">
<p>Here is the camera control</p>
<button class="btn btn-default" ng-click="getSnapshot()">Snapshot</button>
<button class="btn btn-info" ng-click="intervalFunction()">Start Feed</button>
</div>
<div class="lifeFeed col-md-7">
<p>Here is the live feed</p>
<p><button class="btn btn-default" ng-click="readSnapshot()">Snapshot Read</button></p>
<img width='600' height='600' ng-src="{{snapshot}}" alt="SnapShot taken">
</div>
</div>
</div>
</body>
</html>
cameraApp.js
var cameraApp = angular.module('cameraApp',[]);
cameraApp.controller('HomeController', function($scope,$http,$timeout) {
function updateImage() {
var img = 'snapshots/camera.jpg'+ '?decache=' + Math.random();
console.log('Snapshot Loaded');
$scope.snapshot = img;
};
$scope.readSnapshot = updateImage;
$scope.getSnapshot = function() {
$http.get('/api/getSnapshot')
.then(function(response) {
// this callback will be called asynchronously
// when the response is available
console.log('Snapshot captured');
$scope.readSnapshot();
}, function(response) {
console.log('Error in capturing...');
});
}
$scope.intervalFunction = function() {
$timeout(function() {
$scope.getSnapshot();
$scope.intervalFunction();
}, 2000);
};
// Kick off the interval
$scope.intervalFunction();
});
There are two solutions I've used for this in the past.
1) Use an ng-if/ng-show on your img tag. This will prevent the broken image from displaying.
<img ng-if='snapshot'>
2) Set a default image that will load and then be replaced once the other images load.
$scope.snapshot = 'snapshots/default.png';

Categories

Resources