I'm a university student and I'm working with JsPsych on a Jatos server. Doing an excercise I receive an error about my jspointer.
Exactly the error is:
Uncaught ReferenceError: jsonpointer is not defined at jatos.batchSession.get (jatos.js:774:13) at start:33:25
I really don't know how to solve it, cause with this kind of error I cannot retrieve my Batch Session's data to make my experiment work.
I'll show you also there my code to help you understand (it's just the specific exercise code, cause the hole set of excercises is really more vast and complex):
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<title> BENVENUTO </title>
<script src="jatos.js"></script>
<script src="https://unpkg.com/jspsych#7.2.3"></script>
<script src="https://unpkg.com/#jspsych/plugin-html-keyboard-response#1.1.1"></script>
<link href="https://unpkg.com/jspsych#7.2.3/css/jspsych.css" rel="stylesheet" type="text/css" />
</head>
<body>
<style>
body {
background-color: white;
}
</style>
</body>
<script>
var jsPsych = initJsPsych ({
override_safe_mode: true,
on_finish: function(){
jatos.startComponentByPos(nextComponentPosition[componentCounter], data, JSON.stringify(data));
}
});
if (jatos.batchSession.get("level_attenzione") <= 1){
var attenzione = jsPsych.randomization.shuffle(jatos.studyInput.attenzione_1).slice(0,3)
};
if (jatos.batchSession.get("level_attenzione") == 2){
var attenzione = jsPsych.randomization.shuffle(jatos.studyInput.attenzione_2).slice(0,3)
};
if (jatos.batchSession.get("level_attenzione") > 2){
var attenzione = jsPsych.randomization.shuffle(jatos.studyInput.attenzione_3).slice(0,3)
};
if (jatos.batchSession.get("level_linguaggio") <= 1){
var linguaggio = jsPsych.randomization.shuffle(jatos.studyInput.linguaggio_1).slice(0,3)
};
if (jatos.batchSession.get("level_linguaggio") == 2){
var linguaggio = jsPsych.randomization.shuffle(jatos.studyInput.linguaggio_2).slice(0,3)
};
if (jatos.batchSession.get("level_linguaggio") > 2){
var linguaggio = jsPsych.randomization.shuffle(jatos.studyInput.linguaggio_3).slice(0,3)
};
if (jatos.batchSession.get("level_memoria_verbale") <= 1){
var memoria_verbale = jsPsych.randomization.shuffle(jatos.studyInput.memoria_verbale_1).slice(0,3)
};
if (jatos.batchSession.get("level_memoria_verbale") == 2){
var memoria_verbale = jsPsych.randomization.shuffle(jatos.studyInput.memoria_verbale_2).slice(0,3)
};
if (jatos.batchSession.get("level_memoria_verbale") > 2){
var memoria_verbale = jsPsych.randomization.shuffle(jatos.studyInput.memoria_verbale_3).slice(0,3)
};
if (jatos.batchSession.get("level_memoria_visiva") <= 1){
var memoria_visiva = jsPsych.randomization.shuffle(jatos.studyInput.memoria_visiva_1).slice(0,3)
};
if (jatos.batchSession.get("level_memoria_visiva") == 2){
var memoria_visiva = jsPsych.randomization.shuffle(jatos.studyInput.memoria_visiva_2).slice(0,3)
};
if (jatos.batchSession.get("level_memoria_visiva") > 2){
var memoria_visiva = jsPsych.randomization.shuffle(jatos.studyInput.memoria_visiva_3).slice(0,3)
};
var componentCounter = 0;
var nextComponentPosition = attenzione.concat(linguaggio).concat(memoria_verbale).concat(memoria_visiva)
nextComponentPosition = jsPsych.randomization.shuffle(nextComponentPosition)
nextComponentPosition.splice(nextComponentPosition.length/2, 0, 2)
nextComponentPosition = nextComponentPosition.concat(3);
var data = {
level_attenzione: BatchSession["level_attenzione"],
level_linguaggio: BatchSession["level_linguaggio"],
level_memoria_verbale: BatchSession["level_memoria_verbale"],
level_memoria_visiva: BatchSession["level_memoria_visiva"],
level_gradimento: BatchSession["level_gradimento"]
};
var empty = [];
sessionStorage.setItem("nextComponentPosition", nextComponentPosition);
sessionStorage.setItem("componentCounter", componentCounter);
sessionStorage.setItem('attenzione', empty);
sessionStorage.setItem('linguaggio', empty);
sessionStorage.setItem('memoria_verbale', empty);
sessionStorage.setItem('memoria_visiva', empty);
var instructions = {
type: jsPsychHtmlKeyboardResponse,
stimulus: '<h2 style="text-align-center"> Prema il tasto INVIO per proseguire </h2>',
choices: ['Enter'],
};
var timeline = [instructions];
jsPsych.run(timeline);
</script>
</html>
I've tryed to access to the JSONfile to understand where is the error about the missing jsonpointer, but what I obtained is just:
* Getter for a field in the batch session data. Takes a name
* and returns the matching value. Works only on the first
* level of the object tree. For all other levels use
* jatos.batchSession.find. Gets the object from the
* locally stored copy of the session and does not call
* the server.
* #param {string} name - name of the field
* #return {object}
*/
jatos.batchSession.get = function (name) {
var obj = jsonpointer.get(batchSessionData, "/" + name);
return cloneJsonObj(obj);
};
Related
I have a problem with displaying decrypted messages using the Gmail API, can someone help me and explain how to do it to make everything work properly.
The error that is displayed to me:
PS: Sorry for all grammar mistakes, i am not very advanced in English yet
I'm try decrypt messages using atob & i'm try split messages and use atob.
My HTML code:
<!--
Copyright 2018 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- [START gmail_quickstart] -->
<!DOCTYPE html>
<html>
<head>
<title>Gmail API Quickstart</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="css/mail-layout.css">
</head>
<body>
<p>Gmail API Quickstart</p>
<!--Add buttons to initiate auth sequence and sign out-->
<button id="authorize_button" style="display: none;">Authorize</button>
<button id="signout_button" style="display: none;">Sign Out</button>
<pre id="content" style="white-space: pre-wrap;"></pre>
<pre id="content2" style="white-space: pre-wrap;"></pre>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript" src="api.js"></script>
<script type="text/javascript" src="js-api/functions.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body>
</html>
<!-- [END gmail_quickstart] -->
api.js code:
// Client ID and API key from the Developer Console
var CLIENT_ID = '231998038190-410ifknsn879tle6uvmi8o0o3tlqtbt1.apps.googleusercontent.com';
var API_KEY = 'AIzaSyDiivbSVIZd0U5GChXELNswd9iGLGtL6QQ';
// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"];
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = 'https://www.googleapis.com/auth/gmail.readonly';
var authorizeButton = document.getElementById('authorize_button');
var signoutButton = document.getElementById('signout_button');
/**
* On load, called to load the auth2 library and API client library.
*/
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
/**
* Initializes the API client library and sets up sign-in state
* listeners.
*/
function initClient() {
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
}, function(error) {
appendPre(JSON.stringify(error, null, 2));
});
}
/**
* Called when the signed in status changes, to update the UI
* appropriately. After a sign-in, the API is called.
*/
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
//listLabels();
readMessages();
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
/**
* Sign in the user upon button click.
*/
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
/**
* Sign out the user upon button click.
*/
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
/**
* Append a pre element to the body containing the given message
* as its text node. Used to display the results of the API call.
*
* #param {string} message Text to be placed in pre element.
*/
function appendPre(message) {
var pre = document.getElementById('content');
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
/**
* Print all Labels in the authorized user's inbox. If no labels
* are found an appropriate message is printed.
*/
function listLabels() {
/*gapi.client.gmail.users.labels.list({
'userId': 'me'
}).then(function(response) {
var labels = response.result.labels;
appendPre('Labels:');
if (labels && labels.length > 0) {
for (i = 0; i < labels.length; i++) {
var label = labels[i];
appendPre(label.name)
}
} else {
appendPre('No Labels found.');
}
});*/
}
js-api/functions.js code
function append(subject, text){
$("body").prepend("<div class='mail_box' id='mail_box" + i + "'></div>")
$("#mail_box" + i).append("<div class='message'></div>")
$("#mail_box" + i + " .message").append("<div class='subject'>" + subject + "</div>")
$("#mail_box" + i + " .message").append("<div class='text'>" + text + "</div>")
i++
}
function splitStringBySegmentLength(source, segmentLength) {
if (!segmentLength || segmentLength < 1) throw Error('Segment length must be defined and greater than/equal to 1');
const target = [];
for (
const array = Array.from(source);
array.length;
target.push(array.splice(0,segmentLength).join('')));
return target;
}
function debug1Message(msgID){
gapi.client.gmail.users.messages.get({
'userId': 'me',
'id': msgID
}).then(function(response) {
var output = response.result;
console.warn("âš ï¸ Debug [Message: msgID:" + msgID + " ]");
console.warn(output)
});
}
function read1Message(msgID){
gapi.client.gmail.users.messages.get({
'userId': 'me',
'id': msgID
}).then(function(response) {
var output = response.result;
for (var headerIndex = 0; headerIndex < output.payload.headers.length; headerIndex++) {
if (response.result.payload.headers[headerIndex].name == 'Subject') {
x = output.payload.headers[headerIndex].value;
var subject = x;
}
}
console.warn("âš ï¸ Debug [msgID]:" + msgID);
//var messageHTML = output.payload.parts[1].body.data
try{
var ab = output.payload.parts.length
console.warn("âš :" + ab)
for (var headerIndex = 0; headerIndex < ab; headerIndex++) {
if (response.result.payload.parts[headerIndex].mimeType == 'text/html') {
x = output.payload.parts[headerIndex].body.data;
var messageHTML = x;
}
}
}
catch(err){
try{
var messageHTML = output.payload.body.data;
}
catch(err2){
var messageHTML = "Broken/Expired message"
}
}
//var messageHTMLdecrypted = atob(messageHTML)
var result = []
/*result.push(subject)
result.push(messageHTML)*/
console.log("Subject:", subject)
//console.log("Messsage (encrypted):", messageHTML)
//console.log("Messsage (HTML):", messageHTMLdecrypted)
//document.getElementById("content").innerHTML = x
$("#content").html(subject + ";?;" + messageHTML)
y = $("#content").html().split(";?;")
z = y[1].replaceAll("-", "+")
//z = z.replaceAll("+", "+;")
//console.log(y)
if (y && y.length > 0) {
/*for (i = 0; i < y.length; i++) {
var tmp = z[i];
/*console.log(z)*/
/*var tmp_decoded = atob(z.split("+")[i]) ///FAILED
tmp_decoded = tmp_decoded.replaceAll(";", "+")
$("#content2").append(tmp_decoded)
console.warn(tmp_decoded)
}*/
//zlen = z.length / 100+1
//console.error(zlen)
//var zout = splitStringBySegmentLength(z, zlen)
//console.log(zout)
/*for (i = 0; i < zout.length; i++){
console.warn(zout[i]) //PASSED
//var tmp_decoded = atob(zout[i]) ///FAILED
//console.warn(tmp_decoded)
//$("#content2").append(tmp_decoded)
}*/
console.error(z)
try{
var tmp_decoded = atob(z);
}
catch(err){
z2 = z.split("_");
for (i = 0; i < z2.length; i++){
$("#content2").html("")
var tmp_decoded = atob(z2[i])
var old = $("#content2").html()
$("#content2").html(old + tmp_decoded)
}
}
$("#content2").append(tmp_decoded)
var decoded = $("#content2").html()
var msg = y[0]
append(msg, decoded)
$("#content2").html("")
} else {
appendPre('Message Error receive data');
}
});
}
function readMessages(){
gapi.client.gmail.users.messages.list({
'userId': 'me'
}).then(function(response) {
var output = response.result.messages;
console.log(output)
if (output && output.length > 0) {
for (i = 0; i < output.length; i++) {
var msgID = output[i].id;
read1Message(msgID)
}
} else {
appendPre('No Labels found.');
}
});
}
The mistake you have is that somewhere you have a call to
atob(window)
however, the function expects a Base64 and converts it to a number.
You will need to find out what the intention of the code was and replace the parameter passed to atob with the proper Base64 value.
I am using mPDF and other library for generating PDF/ Image from HTML code or file. below I have mentioned my HTML code from which need to generate .JPG or .PNG or .PDF
<HTML>
<head>
<link rel="stylesheet" type="text/css" href="http://codeclippers.xyz/320x50/app.min.css" />
</head>
<body>
<div id="addsp320x50"></div>
</body>
<script src="http://codeclippers.xyz/320x50/app.min.js"></script>
<script type="text/javascript">
var availbleTitles = ["title1", "title2", "title3", "title"];
var availableVsprite =["https:\/\/dspbanners.s3.amazonaws.com\/creatives\/user_creatives_5f843d6b40d48_1602501995.jpeg", "https:\/\/dspbanners.s3.amazonaws.com\/creatives\/user_creatives_5f843d6b7e2b0_1602501995.jpeg"];
var availableVicons = [""];
var availbleBasicOptions = [""];
var availbleDescription = [""];
var selectedVsprite = availableVsprite[Math.floor(Math.random() * availableVsprite.length)];
var selectedVicons = availableVicons[Math.floor(Math.random() * availableVicons.length)];
var selectedTitles = availbleTitles[Math.floor(Math.random() * availbleTitles.length)];
var selectedDescription = availbleDescription[Math.floor(Math.random() * availbleDescription.length)];
var selectedBasicOpt = availbleBasicOptions[Math.floor(Math.random() * availbleBasicOptions.length)];
cOptions.isAnimated = true;
cOptions.animatedVariation = "vinfinite-scroll";
cOptions.titleText = selectedTitles;
cOptions.animationOptions[0].verticalInfiniteAnimation[0].backgroundSpriteURL = selectedVsprite;
if(selectedVicons != "") {
cOptions.animationOptions[0].verticalInfiniteAnimation[0].showIcon = true;
cOptions.animationOptions[0].verticalInfiniteAnimation[0].actionIconImage = selectedVicons;
}
cOptions.descrptionText = selectedDescription;
for(const [key, value] of Object.entries(selectedBasicOpt)) {
if(typeof value === 'boolean') {
cOptions[key] = value;
} else {
cOptions[key] = value.replace(/"/g, "").trim()
}
}
renderCreative();
</script>
</html>
Thanks in advance
I need your help on this!
I'm generating an array which corresponds to a question number.
var arrayCharge = [];
for (var i = 2; i <= 45; i++) {
arrayCharge.push(i);
}
then I use this number to append the corresponding question, answer then click.
Then I'm getting a new value from the array like this
const randomQ = arrayCharge;
const random = Math.floor(Math.random() * randomQ.length);
It works and a new question is charged but the array is still the same.
I've tried this
var remQ = arrayCharge.indexOf(randomQ[random]);
arrayCharge.splice(remQ,1);
But It doesn't work ;-(
Thanks a lot for your help.
Nicolas
Here is the entire code to help comprehension! sorry for that, I should have done it from the begining.
<!DOCTYPE HTML>
<!--
Hyperspace by HTML5 UP
html5up.net | #ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
<head>
<title>Repérez vos messages contraignants - Quiz</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" />
<noscript>
<link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
</head>
<body class="is-preload">
<!-- Sidebar -->
<!-- <section id="sidebar">
</section> -->
<!-- Wrapper -->
<div id="wrapper">
<!-- Intro -->
<section id="intro" class="wrapper style1 fullscreen fade-up">
<div class="inner">
<header>
<button id="start">Commencer</button>
<p> </p>
</header>
<form action="" method="post">
<p id="Qnum"></p>
<p id="Q" data-qnumber="" data-type=""></p>
<section id="answer">
<input type="submit" id="1" name="R1" value="Non">
<input type="submit" id="2" name="R2" value="Parfois">
<input type="submit" id="3" name="R3" value="Souvent">
<input type="submit" id="4" name="R4" value="Oui">
</section>
</form>
</div>
</section>
<!-- Footer -->
<!-- Scripts -->
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/jquery.scrollex.min.js"></script>
<script src="assets/js/jquery.scrolly.min.js"></script>
<script src="assets/js/browser.min.js"></script>
<script src="assets/js/breakpoints.min.js"></script>
<script src="assets/js/util.js"></script>
<script src="assets/js/main.js"></script>
<script>
$(document).ready(function() {
if (localStorage.getItem("clic") >= 45) {
console.log('45');
sessionStorage.clear();
localStorage.clear();
}
var Q1 = [1, "My first question", "FP"];
var Q2 = [2, "My second question", "SP"];
var Q3 = [3, "My third question", "SE"];
var Q4 = [4, "My foutrh question", "DP"];
var Q5 = [5, "My fifth question", "FP"];
//etc... until Q45
if (sessionStorage.getItem("FP") == null) {
$("form").attr("action", "driversV2.php");
$("#answer").hide();
$("#start").click(function() {
$("#Qnum").append(1+" / 45");
$("#Q").append(Q1[1]).attr("data-qnumber", Q1[0]).attr("data-type", Q1[2]);
$("#answer").show();
$("header").hide();
var pageType = $("#Q").attr("data-type");
$("input").click(function() {
var reponse = this.id;
sessionStorage.setItem(pageType, reponse);
localStorage.setItem("clic", 1);
});
});
} else {
$("header").hide();
var clicNum = parseInt(localStorage.getItem("clic"));
var QNumber = clicNum + 1;
var arrayCharge = [];
for (var i = 2; i <= 45; i++) {
arrayCharge.push(i);
}
const randomQ = arrayChargeNew;
const random = Math.floor(Math.random() * randomQ.length);
console.log('valeur random new = '+randomQ[random]);
var QCharge = "Q" + randomQ[random];
var Charge = eval(QCharge);
localStorage.setItem("random",randomQ[random]);
$("#Qnum").append(QNumber+" / 45");
$("#Q").append(Charge[1]).attr("data-qnumber", Charge[0]).attr("data-type", Charge[2]);
//création de la variable du type de question
var pageType = $("#Q").attr("data-type");
//alert(sessionStorage.getItem(pageType));
if (localStorage.getItem("clic") < 44) {
$("form").attr("action", "driversV2.php");
if (sessionStorage.getItem(pageType) != null) {
var x = parseInt(sessionStorage.getItem(pageType));
$("input").click(function() {
var reponse = parseInt(this.id);
var addition = reponse + x;
sessionStorage.setItem(pageType, addition);
var clic = parseInt(localStorage.getItem("clic"));
localStorage.setItem("clic", clic + 1);
});
} else {
$("input").click(function() {
var reponse = this.id;
sessionStorage.setItem(pageType, reponse);
var clic = parseInt(localStorage.getItem("clic"));
localStorage.setItem("clic", clic + 1);
});
}
} else {
$("form").attr("action", "driversResultat.php");
if (sessionStorage.getItem(pageType) != null) {
var x = parseInt(sessionStorage.getItem(pageType));
$("input").click(function() {
var reponse = parseInt(this.id);
var addition = reponse + x;
sessionStorage.setItem(pageType, addition);
var clic = parseInt(localStorage.getItem("clic"));
localStorage.setItem("clic", clic + 1);
});
} else {
$("input").click(function() {
var reponse = this.id;
sessionStorage.setItem(pageType, reponse);
var clic = parseInt(localStorage.getItem("clic"));
localStorage.setItem("clic", clic + 1);
});
}
}
}
});
</script>
</body>
</html>
Nicolas, this is the sort of thing you should end up with:
// From my library js file
// returns a random number in the given range
function getRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Variables for objects that need to be available throughout
let availableQuestions = [];
let rnd = 0;
let counter = 0;
// Populate the question array - how this is done depends on where the question data comes from
function createQuestions() {
availableQuestions.length = 0;
for (let i = 1; i <= 10; i++) {
availableQuestions.push({"questionnumber": i, "question": "Text for question " + i});
}
}
// Pick a random question and display that to the user
function getRandomQuestion() {
let osQuestions = availableQuestions.length;
let qnElement = document.getElementById("questionnumber");
let qElement = document.getElementById("question");
let sButton = document.getElementById("submit");
let rButton = document.getElementById("restart");
// If there are no more questions, stop
if (osQuestions == 0) {
qnElement.innerHTML = "Finished!";
qElement.innerHTML = "";
sButton.style.display = "none";
rButton.style.display = "inline";
} else {
// display a sequential question number rather than the actual question number
counter++;
rnd = getRandomNumber(0, osQuestions - 1);
let thisQuestion = availableQuestions[rnd];
qnElement.innerHTML = "Question: " + counter + " (Actually question: " + thisQuestion.questionnumber + ")";
qElement.innerHTML = thisQuestion.question;
}
}
// Process the user's answer and remove the question from the array
function submitAnswer() {
// ALSO Add in what needs to be done to update backend database etc when the user clicks submit
availableQuestions.splice(rnd, 1);
getRandomQuestion();
}
// Reset everything - for testing purposes only
function restart() {
let qnElement = document.getElementById("questionnumber");
let qElement = document.getElementById("question");
let sButton = document.getElementById("submit");
let rButton = document.getElementById("restart");
qnElement.innerHTML = "";
qElement.innerHTML = "";
sButton.style.display = "inline";
rButton.style.display = "none";
// Reset the displayed question number counter
counter = 0;
createQuestions();
getRandomQuestion();
}
// Needed to populate the array and display the first question
function runsetup() {
createQuestions();
getRandomQuestion();
}
window.onload = runsetup;
<div id="questionnumber"></div>
<hr>
<div id="question"></div>
<button id="submit" onclick="submitAnswer();">Submit</button>
<button id="restart" onclick="restart();" style="display:none;">Restart</button>
I've included a counter variable so that the user does't see the actual question number - just 1, 2, 3 etc but I've shown the actual question number so that you can see it working
Nicolas, this is what I think you should be doing:
// Create the array in whatever way you need to
var arrayCharge = [];
for (var i = 2; i <= 45; i++) {
arrayCharge.push({"questionnumber": i, "question": "Text of question " + i});
}
// Just confirm the length of the array - should be 44
console.log(arrayCharge.length);
// Generate a random number based on the length of the array
var rnd = Math.floor(Math.random() * arrayCharge.length);
// Get the question at the randomly generated index number
let thisQuestion = arrayCharge[rnd];
// Check that we have a random question
console.log(thisQuestion.questionnumber);
console.log(thisQuestion.question)
// Present the question to the user on the page
// The user completes question and clicks "Submit"
// Now remove the question, using the SAME index number
arrayCharge.splice(rnd,1);
// Check that the array has lost an entry - the size should now be 43
console.log(arrayCharge.length);
I am following a tutorial from Head First Javascript. In the tutorial, the showBlogs() method is called via the following html code
HTML button
<input type="button" id="showall" value="Show all blog entries" onclick="showBlogs();" />
function showBlogs(numberOfEntries){
//sort the blogs in reverse chronological order (most recent first)
blogs.sort(function(blog1, blog2){
return blog2.date - blog1.date;
})
//set the number of entires if non specified
if(!numberOfEntries){
numberOfEntries = blogs.length;
}
//set blog entries
var currenetBlog = 0; blogListHTML = "";
while(currenetBlog < blogs.length && currenetBlog < numberOfEntries){
blogListHTML += blogs[currenetBlog].toHTML(currenetBlog % 2 == 0);
currenetBlog++;
}
//display blog entries
blogsDOM.innerHTML = blogListHTML;
}
However, when I create another button and access it via javascript and call the same method with the event handler - nothing happens.
Button
<button type="button" id="showAllBlogs">Show All Posts</button>
Access Button within Javascript
const showBlogsButton = document.getElementById('showAllBlogs');
Call the showBlogs method
showBlogsButton.addEventListener('click', showBlogs);
I did try creating another function say 'foo()' and I called foo() with the new button and I was able to invoke the method. But when I call the showBlogs() method, nothing happens.
JAVASCRIPT CODE
`
//dom elements
const blogsDOM = document.getElementById('blog');
const query = document.getElementById('searchInput');
const searchButton = document.getElementById('searchButton');
const showBlogsButton = document.getElementById('showAllBlogs');
// Constructor
function Blog(body, dateString){
this.body = body;
this.date = new Date(dateString);
this.toString = function(){
return this.date.getMonth() + '/' + this.date.getDate() + '/' + this.date.getFullYear() + '/' +
this.body;
};
this.toHTML = function(highlight){
var htmlPost = "";
//determine to highlight post
htmlPost += highlight ? "<p style='background-color: #EEEEEE'>" : "<p>";
//generate formatted html
htmlPost += this.date.getMonth() + '/' + this.date.getDate() + '/' + this.date.getFullYear() + '/' +
this.body + "</p>";
//return html
return htmlPost;
};
this.containsText = function(text){
return this.body.toLowerCase().indexOf(text.toLowerCase()) > -1;
};
}
//Array of blogs
var blogs = [
new Blog("Got the new cube I ordered", "01/25/1986"),
new Blog("This new cube works just fine", "02/22/2000"),
new Blog("This is going to be the third one", "03/23/2005"),
new Blog("This is the final one", "03/21/2020")
]
blogs.sort(function(blog1, blog2){ return blog2.date - blog1.date; })
function getDaysBetweenDates(date1, date2){
var daysBetween = (date2 - date1) / (1000 * 60 * 60 * 24);
return Math.round(daysBetween);
}
function formatDate(date){
return date.getDay() + '/' + date.getMonth() + '/' + date.getYear();
}
function searchForPost(event){
let matchingBlogs = [];
event.preventDefault();
const searchQuery = query.value;
blogs.forEach(blog =>{
if(blog.body.toLowerCase().indexOf(searchQuery.toLowerCase()) > -1){
matchingBlogs.push(blog);
}
} )
showBlogs(matchingBlogs.length, matchingBlogs);
}
//show list of blog
function showBlogs(numberOfEntries, blogsToShow = blogs){
//sort the blogs in reverse chronological order (most recent first)
blogs.sort(function(blog1, blog2){
return blog2.date - blog1.date;
})
//set the number of entires if non specified
if(!numberOfEntries){
numberOfEntries = blogs.length;
}
//set blog entries
var currenetBlog = 0; blogListHTML = "";
while(currenetBlog < blogs.length && currenetBlog < numberOfEntries){
blogListHTML += blogs[currenetBlog].toHTML(currenetBlog % 2 == 0);
currenetBlog++;
}
//display blog entries
blogsDOM.innerHTML = blogListHTML;
}
searchButton.addEventListener('click', searchForPost);
showBlogsButton.addEventListener('click', showBlogs);`
HTML CODE
`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blog</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h3>Youtube - the Blog for Cube puzzlers</h3>
<div class="search-container">
<input type="text" id="searchInput" placeholder="Search for a blog"/>
<button type="button" id="searchButton">Search the blog</button>
</div>
<div id="blog"></div>
<input type="button" id="showall" value="Show all blog entries" onclick="showBlogs();" />
<button type="button" id="showAllBlogs">Show All Posts</button>
<script src="script.js"></script>
</body>
</html>`
I am using geolocation to collect coordinates and make an API call to get the weather in Fahrenheit. I'm assigning the global variable tempNum this value within one of my functions that adds the temperature to the page using function getWeatherByCoordinates(latitude, longitude).
Later, I am trying to access this variable and pass the value as an argument into another function typeConversion for which I am attempting to convert the temperature value to Celsius. It is returning NaN and when debugging, I can't figure out why.
Here is my HTML and JS. I feel like since I declared my variable at the global level and set "return varName" in the function that I assigned the value to it, that the value should be accessible throughout my JS; but I may have done something wrong or misunderstood variable scope. Please assist.
var place = document.getElementById("meat");
var header = document.getElementById("header");
var weather = document.getElementById("Weather");
var latitude;
var longitude;
var coordinates = document.getElementById("coordinates");
function success(position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
getWeatherByCoordinates(latitude, longitude);
};
//else {
// //Write Code to alternatively show a Zip-Code Search Box;
//};
navigator.geolocation.getCurrentPosition(success);
var city = document.getElementById("city");
var weatherDescription = document.getElementById("weather-description");
var roundTempF;
var roundTempC;
var tempNum;
var tempStringFFull
function getWeatherByCoordinates(latitude, longitude) {
var fullURL = "http://api.openweathermap.org/data/2.5/weather?lat=" + latitude + "&lon=" + longitude + "&APPID=75ed54453a6e806917cfa439b3fb1dd9&units=imperial";
$.getJSON(fullURL, function (data) {
var tempString = data.main.temp;
var tempNum = parseInt(tempString);
roundTempF = Math.floor(tempNum);
stringF = roundTempF.toString();
tempStringFFull = stringF + "\xB0" + " F";
weather.innerText = tempStringFFull;
city.innerText = data.name;
weatherDescription.innerText = data.weather[0].description;
if (data.dt > data.sys.sunrise && data.dt < data.sys.sunset) {
$("#whole-page").removeClass("whole");
$("#whole-page").removeClass("night");
$("#whole-page").addClass("day");
}
else {
$("#whole-page").removeClass("whole");
$("#whole-page").removeClass("night");
$("#whole-page").addClass("night");
};
event.preventDefault();
});
return tempNum;
};
function typeConversion(tempNum) {
if (changeTempType.innerText === "Celsius") {
var tempStringC;
var celsiusDecimal = (tempNum - 32) * (5 / 9);
roundTempC = Math.floor(celsiusDecimal);
tempStringC = roundTempC.toString();
tempStringC += "\xB0" + " C";
weather.innerText = tempStringC;
changeTempType.innerText = "Farenheit";
return;
}
else if (changeTempType.innerText === "Farenheit") {
weather.innerText = tempStringFFull;
changeTempType.innerText = "Celsius";
return;
}
else {
weather.innerText = "We are unable to retrieve the weather at this time. Please try again later";
changeTempType.innerText = "Celsius";
return;
};
};
var changeTempType = document.getElementById("change-temp-type");
changeTempType.addEventListener("click", typeConversion, false);
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet"/>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<title>Weather</title>
</head>
<body id="whole-page" class="whole">
<div class="wrapper">
<h2 id="header">Check the Current Temperaturate by Zip Code</h2>
<label>Farenheit</label>
<input type="radio" name="temp-type" value="C" id="Celsius-radio"/><label>Celsius</label>-->
<button id="change-temp-type">Celsius</button>
<form>
<p>Enter the Zip Code to see the Weather there!</p>
<input id = "Zip-Code" type="text"/>
<input id = "submit-zip" type="button" value="Get Weather!"/>
</form>
<div>
<h3 id="city"></h3>
<h3 id= "Weather" class="temp-text"></h3>
<h4 id="weather-description"></h4>
</div>
</div>
<script src= "https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.js"> </script>
<script src="javascript/main.js"></script>
</body>
</html>
You have a couple of issues:
You re-declare var tempNum = in your function, meaning it will be a new variable only accessible inside the function scope (leaving the global one unchanged)
Your code inside of $.getJSON is using an asynchronous callback - that means it will run sometime later than the code below it. When you return tempNum, that code has not run yet.
Your return statement isn't really doing anything... just reassigning the global variable will be sufficient.
UPDATE - issue I missed at first:
You are naming your function parameter in typeConversion "tempNum". Again, that will result in a new variable, only accessible within the scope of that function. If you want to affect the global, then this function does not need any parameters at all, and tempNum will then refer to the global variable as intended.
I've tried to clear up all issues below.
var place = document.getElementById("meat");
var header = document.getElementById("header");
var weather = document.getElementById("Weather");
var latitude;
var longitude;
var coordinates = document.getElementById("coordinates");
function success(position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
getWeatherByCoordinates(latitude, longitude);
};
//else {
// //Write Code to alternatively show a Zip-Code Search Box;
//};
navigator.geolocation.getCurrentPosition(success);
var city = document.getElementById("city");
var weatherDescription = document.getElementById("weather-description");
var roundTempF;
var roundTempC;
var tempNum;
var tempStringFFull
function getWeatherByCoordinates(latitude, longitude) {
var fullURL = "http://api.openweathermap.org/data/2.5/weather?lat=" + latitude + "&lon=" + longitude + "&APPID=75ed54453a6e806917cfa439b3fb1dd9&units=imperial";
$.getJSON(fullURL, function (data) {
var tempString = data.main.temp;
// removed "var tempNum"...
tempNum = parseInt(tempString);
roundTempF = Math.floor(tempNum);
stringF = roundTempF.toString();
tempStringFFull = stringF + "\xB0" + " F";
weather.innerText = tempStringFFull;
city.innerText = data.name;
weatherDescription.innerText = data.weather[0].description;
if (data.dt > data.sys.sunrise && data.dt < data.sys.sunset) {
$("#whole-page").removeClass("whole");
$("#whole-page").removeClass("night");
$("#whole-page").addClass("day");
}
else {
$("#whole-page").removeClass("whole");
$("#whole-page").removeClass("night");
$("#whole-page").addClass("night");
};
event.preventDefault();
});
//return tempNum;
};
// removed the argument "tempNum", just use the global
function typeConversion() {
if (changeTempType.innerText === "Celsius") {
var tempStringC;
var celsiusDecimal = (tempNum - 32) * (5 / 9);
roundTempC = Math.floor(celsiusDecimal);
tempStringC = roundTempC.toString();
tempStringC += "\xB0" + " C";
weather.innerText = tempStringC;
changeTempType.innerText = "Farenheit";
return;
}
else if (changeTempType.innerText === "Farenheit") {
weather.innerText = tempStringFFull;
changeTempType.innerText = "Celsius";
return;
}
else {
weather.innerText = "We are unable to retrieve the weather at this time. Please try again later";
changeTempType.innerText = "Celsius";
return;
};
};
var changeTempType = document.getElementById("change-temp-type");
changeTempType.addEventListener("click", typeConversion, false);
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet"/>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<title>Weather</title>
</head>
<body id="whole-page" class="whole">
<div class="wrapper">
<h2 id="header">Check the Current Temperaturate by Zip Code</h2>
<label>Farenheit</label>
<input type="radio" name="temp-type" value="C" id="Celsius-radio"/><label>Celsius</label>-->
<button id="change-temp-type">Celsius</button>
<form>
<p>Enter the Zip Code to see the Weather there!</p>
<input id = "Zip-Code" type="text"/>
<input id = "submit-zip" type="button" value="Get Weather!"/>
</form>
<div>
<h3 id="city"></h3>
<h3 id= "Weather" class="temp-text"></h3>
<h4 id="weather-description"></h4>
</div>
</div>
<script src= "https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.js"> </script>
<script src="javascript/main.js"></script>
</body>
</html>
Last note - this will work fine if the function where you need to access tempNum runs later, like in response to a user action. It may still be undefined for a few ms after your page loads, so if you try to use it right at page load time, it may still be undefined. You may want to initialize it to some default value in this case.
Hope this helps.