I am trying to upload multiple images with File API. I want to show picture thumbnails and their names as title tag. The problem is I am not getting correct picture name as title tag. All pictures are showing same name.
Here is my Original code...
jQuery, CSS and HTML
var output = document.getElementById("result");
$(document).ready(function ()
{
//Check File API support
if (window.File && window.FileList && window.FileReader)
{
$('#files').on("change", function (event)
{
var files = event.target.files; //FileList object
var iCount = files.length;
for (var i = 0, f; i < iCount; i++)
{
var file = files[i];
//Only pics
if (file.type.match('image.*'))
{
var picReader = new FileReader();
picReader.addEventListener("load", function (event)
{
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + file['name'] + "'/>";
output.insertBefore(div, null);
});
//Read the image
$('#clear, #result').show();
picReader.readAsDataURL(file);
}
else
{
alert("You can only upload image file.");
$(this).val("");
}
}
});
}
else
{
console.log("Your browser does not support File API");
}
$("#upload").on('submit',(function()
{
var data = new FormData(this);
var iUploaded = 0;
setTimeout(function()
{
var iCount = document.getElementById('files').files.length;
for (var i = 0; i < iCount ; i++)
{
data.append("Index", i);
$.ajax(
{
url: "upload.php",
type: "POST",
data: data,
contentType: false,
cache: false,
processData:false,
async: false,
success: function(response)
{
var sRes = response.split("|-|");
if(sRes['0'] == 'success')
{
iUploaded = iUploaded + 1;
$("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
}
}
});
}
}, 500);
}));
$("#files").change(function()
{
$("#submit").trigger("click");
});
$('#clear').on("click", function ()
{
$('.thumbnail').parent().remove();
$('#result').hide();
$('#files').val("");
$(this).hide();
});
});
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
float: left;
}
#clear{
display:none;
}
#result {
border: 4px dotted #cccccc;
display: none;
float: left;
margin:0 auto;
}
#result > div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
<form id="upload" onsubmit="return false">
<label for="files">Select multiple files: </label><br /><br />
<input id="files" name="files[]" type="file" multiple/><br /><br />
<input type="Submit" value="submit" id="submit"></input>
<button type="button" id="clear">Clear</button><br /><br />
</form>
<div id="message"></div>
<output id="result" />
</article>
I tried to figure it out and come to know that the value of var i changes automatically inside the
addEventListener("load", function (event){
// value of “var i” is not the same here as the value coming from outside this function.
});
I have no idea why value is changing inside the “load” function.
I Googled to see how others are doing same and ended up with this working example on SitePoint http://www.sitepoint.com/html5-file-drag-and-drop/
In this example I see these 2 major differences which I do not understand (my little knowledge in programming).
1. Syntax of for loop he is using in example
for (var i = 0, f; f = files[i]; i++) {
See he is assigning value to var f instead of applying stop condition.
Now my question is how the loop is working without stop condition is specified?
2. Separate function for reading files
He has made a separate function ParseFile(); to read files.
When I tried to read files without a separate function for file reading it is not working (as shown in my original code). But when I put that code in a separate function showThumbnail() for reading files and call that function inside loop it is working as it should be (as showing in below snippet). Why is this so?
Anyone here explain these two things to me.
Thanks in advance.
I followed the example and rearranged my code which is working as it should be. (Code is in below snippet.)
var output = document.getElementById("result");
$(document).ready(function ()
{
//Check File API support
if (window.File && window.FileList && window.FileReader)
{
$('#files').on("change", function (event)
{
var files = event.target.files; //FileList object
var iCount = files.length;
for (var i = 0, f; f = files[i]; i++)
{
showThumbnail(f);
}
});
}
else
{
console.log("Your browser does not support File API");
}
$("#upload").on('submit',(function()
{
var data = new FormData(this);
var iUploaded = 0;
setTimeout(function()
{
var iCount = document.getElementById('files').files.length;
for (var i = 0; i < iCount ; i++)
{
data.append("Index", i);
$.ajax(
{
url: "upload.php",
type: "POST",
data: data,
contentType: false,
cache: false,
processData:false,
async: false,
success: function(response)
{
var sRes = response.split("|-|");
if(sRes['0'] == 'success')
{
iUploaded = iUploaded + 1;
$("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
}
}
});
}
}, 500);
}));
$("#files").change(function()
{
$("#submit").trigger("click");
});
$('#clear').on("click", function ()
{
$('.thumbnail').parent().remove();
$('#result').hide();
$('#files').val("");
$(this).hide();
});
});
function showThumbnail(file)
{
//Only pics
if (file.type.match('image.*'))
{
var picReader = new FileReader();
picReader.addEventListener("load", function (event)
{
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + file['name'] + "'/>";
output.insertBefore(div, null);
});
//Read the image
$('#clear, #result').show();
picReader.readAsDataURL(file);
}
else
{
alert("You can only upload image file.");
$(this).val("");
}
}
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
float: left;
}
#clear{
display:none;
}
#result {
border: 4px dotted #cccccc;
display: none;
float: left;
margin:0 auto;
}
#result > div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<article>
<form id="upload" onsubmit="return false">
<label for="files">Select multiple files: </label><br /><br />
<input id="files" name="files[]" type="file" multiple/><br /><br />
<input type="Submit" value="submit" id="submit"></input>
<button type="button" id="clear">Clear</button><br /><br />
</form>
<div id="message"></div>
<output id="result" />
</article>
Haven't seen the edits to question before posting + misread it
So for your questions :
1 This for loop is waiting for file[i] to be undefined. :
for( var i=0, f; f=files[i]; i++).
If files[x]is undefined, then the loop stops (even if files[x+1] is defined)
2 It is because in your first snippet, your file variable is in the global scope and gets replaced during the iteration. In the second, however, it is linked to the showThumbnail function scope, and then passed in the EventListener.
To avoid calling an external function, you will need to call a file binded function :
From mdn : reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
So for you,
picReader.addEventListener("load", (function(aImg) { return function (event)
{
var picFile = event.target;
console.log(picFile);
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + aImg['name'] + "'/>";
output.insertBefore(div, null);
}; })(file));
Example below :
var output = document.getElementById("result");
$(document).ready(function ()
{
//Check File API support
if (window.File && window.FileList && window.FileReader)
{
$('#files').on("change", function (event)
{
var files = event.target.files; //FileList object
var iCount = files.length;
for (var i = 0, f; i < iCount; i++)
{
var file = files[i];
//Only pics
if (file.type.match('image.*'))
{
var picReader = new FileReader();
picReader.addEventListener("load", (function(aImg) { return function (event)
{
var picFile = event.target;
console.log(picFile);
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + aImg['name'] + "'/>";
output.insertBefore(div, null);
}; })(file));
//Read the image
$('#clear, #result').show();
picReader.readAsDataURL(file);
}
else
{
alert("You can only upload image file.");
$(this).val("");
}
}
});
}
else
{
console.log("Your browser does not support File API");
}
$("#upload").on('submit',(function()
{
var data = new FormData(this);
var iUploaded = 0;
setTimeout(function()
{
var iCount = document.getElementById('files').files.length;
for (var i = 0; i < iCount ; i++)
{
data.append("Index", i);
$.ajax(
{
url: "upload.php",
type: "POST",
data: data,
contentType: false,
cache: false,
processData:false,
async: false,
success: function(response)
{
var sRes = response.split("|-|");
if(sRes['0'] == 'success')
{
iUploaded = iUploaded + 1;
$("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
}
}
});
}
}, 500);
}));
$("#files").change(function()
{
$("#submit").trigger("click");
});
$('#clear').on("click", function ()
{
$('.thumbnail').parent().remove();
$('#result').hide();
$('#files').val("");
$(this).hide();
});
});
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
float: left;
}
#clear{
display:none;
}
#result {
border: 4px dotted #cccccc;
display: none;
float: left;
margin:0 auto;
}
#result > div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
<form id="upload" onsubmit="return false">
<label for="files">Select multiple files: </label><br /><br />
<input id="files" name="files[]" type="file" multiple/><br /><br />
<input type="Submit" value="submit" id="submit"></input>
<button type="button" id="clear">Clear</button><br /><br />
</form>
<div id="message"></div>
<output id="result" />
</article>
Answer to question 1:
The for loop increments i with 1 on every iteration. When i is not an index of files the returned value will be undefined, which breaks the loop.
Answer to question 2:
I created a fiddle which shows how to put the code of showThumbnail in the for loop. It aslo explains the question.
The reason is behind the addEventListener function, which will run asynchronously with the for loop after load is triggered and has different scope. The function outside the loop is however permanent and the listener can use variables declared in that scope (the argument file).
What you can do however is to bind the listener function to the file object. The scope (this) of the function will be the file. See the fiddle for this to work.
Related
FIle upload process -
When we select a file from the system it runs the follwing process:
It checks whether the file had the defined types or not if not then stop the file upload.
When we select a file from the system then it adds a progress bar that informs about the percentage of file uploading progress.
Along with file progress bar it adds a cancel button, If you want to cancel the file upload in between the progress.
If the file is loaded 100% then show the success message with the KB/MB of file. Here file is not uploaded that means not sent through Ajax call.
Along with loaded 100% message show a Remove button. If a user want to remove the file then he can remove the file and then select the another file from the system.
Submit button action - On clicking on Submit button the Ajax call should fire and save the file to the defined loaction. Here I have used PHp to send file to the definde location.
The issue I am facing is - I want to perform the action from 1 to 5 (above mentioned numbers) without any ajax call. on clicking of the submit button then only the data should save otherwise it should not save.
In my case the file is getting save when it is loaded 100%. so If I click on remove button the file is already sent to the defined location.
How can I perform the onclick on submit button.
Below is the code -
HTML -
<section class="bulk-upload--sec">
<form action="#">
<label for="ccp-bulkupload__btn" class="ccp-bulkupload__label">Upload File</label>
<input type="file" id="ccp-bulkupload__btn" name="file" class="file-input" hidden>
</form>
<section class="progress-area"></section>
<section class="uploaded-area"></section>
<button class="btn btn-primary btn-submit" type="submit">Submit</button>
</section>
CSS -
body{
position: relative;
color: #000;
}
.bulk-upload--sec{
position: absolute;
top: 150px;
left: 150px;
}
form label{
cursor: pointer;
}
.progress-bar{
height: 6px;
width: 100%;
background: #d8d8d8;
margin-bottom: 4px;
}
.progress--1{
height: 100%;
width: 10%;
background: #6990f2;
border-radius: inherit;
}
.upload-status{
color: #000;
}
.disabled{
color: #ddd;
cursor: default;
}
.ccp-bulkupload__label{
cursor: pointer;
border-radius: 0;
border: 1px solid #5e10b1;
height: 50px;
width: 180px;
color: #5e10b1;
text-align: center;
}
JS-
let filArray = [];
let ajaxCall;
$('.btn-submit').on('click', function(e){
e.preventDefault();
alert("I am done");
})
$('.file-input').on('change', function({target}){
let file = target.files[0];
let allowedTypes = ['application/pdf', 'application/csv', 'application/vnd.ms-excel'];
let fileType = file.type;
console.log("target", file);
if(file && allowedTypes.includes(fileType)){
let fileName = file.name;
if(fileName.length >= 12){
let splitText = fileName.split('.');
console.log("splitText",splitText);
fileName = splitText[0].substring(0, 12) + '..' + splitText[1];
}
uploadFile(fileName);
fileStorage(file);
}else{
console.log("cannot save");
filArray.pop();
$('.fileType').val('');
return false;
}
});
function fileStorage(arr){
filArray.push(arr);
console.log("file array", filArray);
}
function uploadFile(name){
ajaxCall = $.ajax({
xhr: function(){
let xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", ({loaded, total}) =>{
console.log("loaded, total",loaded, total);
let fileLoaded = Math.floor((loaded / total) * 100);
let fileTotal = Math.floor(total / 1000);
let fileSize;
fileSize = (fileTotal < 1024) ? fileSize = fileTotal + 'KB' : fileSize = (loaded / (1024 * 1024)).toFixed(2) + 'MB';
let progressHtml = `<div class="row"><div class="details"><span class="name"> ${name}</span><span>- </span></div><div class="progress-bar"><div class="progress--1" style="width:${fileLoaded}%"></div></div></div>`
progressHtml += `<div class="upload-status"><span class="uploading-status">Uploading</span><span class="percentage">${fileLoaded}%</span></div></div>`
progressHtml += `<button class="btn btn-danger btn-cancel">Cancel</button>`
$('.progress-area').html(progressHtml);
if(loaded == total){
$('.progress-area').html('');
let uploadedHTML = `<div class="row"> <div class="uploaded"><div class="details"><span class="name"> ${name}</span><span>- </span> <p>Uploaded .<span class="size">${fileSize}</span></p></div></div><div class="success-msg"><p>Successfull!!</p></div></div>`
uploadedHTML += `<button class="btn btn-sucess btn-remove">Remove</button>`
$(".uploaded-area").html(uploadedHTML);
}
$('.btn-cancel').on('click', function(){
ajaxCall.abort();
filArray.pop();
$('form')[0].reset();
$('.fileType').val('');
$('.progress-area').html('');
})
$('.btn-remove').on('click', function(){
filArray.pop();
$('form')[0].reset();
$('.file-input').val('');
$('.uploaded-area').html('');
alert("file is removed");
console.log("cleared array", filArray);
})
}, false);
return xhr;
},
// Your server script to process the upload
type: 'POST',
url: "php/uploaded.php",
//formData
data: new FormData($('form')[0]),
cache: false,
contentType: false,
processData: false,
error: function(){
alert("This is an error");
},
success: function(){
alert("successfull");
}
})
}
PHP -
<?php
$file_name = $_FILES['file']['name'];
$tmp_name = $_FILES['file']['tmp_name'];
$file_up_name = time().$file_name;
move_uploaded_file($tmp_name, "files/".$file_up_name);
?>
When a file is selected, then perform just the check and store the file in variable.
After when the submit button is clicked, then call the ajax for upload.
let filArray = [];
let ajaxCall;
let fileName = "";
$('.btn-submit').on('click', function(e){
e.preventDefault();
uploadFile(fileName); // change <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
alert("I am done");
})
$('.file-input').on('change', function({target}){
let file = target.files[0];
let allowedTypes = ['application/pdf', 'application/csv', 'application/vnd.ms-excel'];
let fileType = file.type;
console.log("target", file);
if(file && allowedTypes.includes(fileType)){
fileName = file.name; // change <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
if(fileName.length >= 12){
let splitText = fileName.split('.');
console.log("splitText",splitText);
fileName = splitText[0].substring(0, 12) + '..' + splitText[1];
}
fileStorage(file);
}else{
console.log("cannot save");
filArray.pop();
$('.fileType').val('');
return false;
}
});
function fileStorage(arr){
filArray.push(arr);
console.log("file array", filArray);
}
function uploadFile(name){
ajaxCall = $.ajax({
xhr: function(){
let xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", ({loaded, total}) =>{
console.log("loaded, total",loaded, total);
let fileLoaded = Math.floor((loaded / total) * 100);
let fileTotal = Math.floor(total / 1000);
let fileSize;
fileSize = (fileTotal < 1024) ? fileSize = fileTotal + 'KB' : fileSize = (loaded / (1024 * 1024)).toFixed(2) + 'MB';
let progressHtml = `<div class="row"><div class="details"><span class="name"> ${name}</span><span>- </span></div><div class="progress-bar"><div class="progress--1" style="width:${fileLoaded}%"></div></div></div>`
progressHtml += `<div class="upload-status"><span class="uploading-status">Uploading</span><span class="percentage">${fileLoaded}%</span></div></div>`
progressHtml += `<button class="btn btn-danger btn-cancel">Cancel</button>`
$('.progress-area').html(progressHtml);
if(loaded == total){
$('.progress-area').html('');
let uploadedHTML = `<div class="row"> <div class="uploaded"><div class="details"><span class="name"> ${name}</span><span>- </span> <p>Uploaded .<span class="size">${fileSize}</span></p></div></div><div class="success-msg"><p>Successfull!!</p></div></div>`
uploadedHTML += `<button class="btn btn-sucess btn-remove">Remove</button>`
$(".uploaded-area").html(uploadedHTML);
}
$('.btn-cancel').on('click', function(){
ajaxCall.abort();
filArray.pop();
$('form')[0].reset();
$('.fileType').val('');
$('.progress-area').html('');
})
$('.btn-remove').on('click', function(){
filArray.pop();
$('form')[0].reset();
$('.file-input').val('');
$('.uploaded-area').html('');
alert("file is removed");
console.log("cleared array", filArray);
})
}, false);
return xhr;
},
// Your server script to process the upload
type: 'POST',
url: "php/uploaded.php",
//formData
data: new FormData($('form')[0]),
cache: false,
contentType: false,
processData: false,
error: function(){
alert("This is an error");
},
success: function(){
alert("successfull");
}
})
}
I'm trying to create a quiz that tests users awareness of real and fake emails. What I want to do is have the question displayed at the top saying "Real or Fake", then have an image displayed underneath which the user needs to look at to decided if it's real or fake. There are two buttons, real and fake, and regardless of whether they choose the right answer I want to swap the original image with annotated version - showing how users could spot that it was fake or real.
But I'm not sure how to show the annotated version once the answer has been submitted. Could someone help?
function Quiz(questions) {
this.score = 0;
this.questions = questions;
this.questionIndex = 0;
}
Quiz.prototype.getQuestionIndex = function() {
return this.questions[this.questionIndex];
}
Quiz.prototype.guess = function(answer) {
if (this.getQuestionIndex().isCorrectAnswer(answer)) {
this.score++;
}
this.questionIndex++;
}
Quiz.prototype.isEnded = function() {
return this.questionIndex === this.questions.length;
}
function Question(text, choices, answer) {
this.text = text;
this.choices = choices;
this.answer = answer;
}
Question.prototype.isCorrectAnswer = function(choice) {
return this.answer === choice;
}
function populate() {
if (quiz.isEnded()) {
showScores();
} else {
// show question
var element = document.getElementById("question");
element.innerHTML = quiz.getQuestionIndex().text;
// show options
var choices = quiz.getQuestionIndex().choices;
for (var i = 0; i < choices.length; i++) {
var element = document.getElementById("choice" + i);
element.innerHTML = choices[i];
guess("btn" + i, choices[i]);
}
showProgress();
}
};
function guess(id, guess) {
var button = document.getElementById(id);
button.onclick = function() {
quiz.guess(guess);
populate();
}
};
function showProgress() {
var currentQuestionNumber = quiz.questionIndex + 1;
var element = document.getElementById("progress");
element.innerHTML = "Question " + currentQuestionNumber + " of " + quiz.questions.length;
};
function showScores() {
var gameOverHTML = "<h1>Result</h1>";
gameOverHTML += "<h2 id='score'> Your scores: " + quiz.score + "</h2>";
var element = document.getElementById("quiz");
element.innerHTML = gameOverHTML;
};
// create questions here
var questions = [
new Question("<img src= 'netflix_fake.jpg' />", ["Real", "Fake"], "Fake"),
new Question("<img src= 'dropbox_real.jpg' />", ["Real", "Fake"], "Real"),
new Question("<img src= 'gov_real.jpg' />", ["Real", "Fake"], "Real"),
new Question("<img src= 'paypal_fake.jpg' />", ["Real", "Fake"], "Fake"),
new Question("<img src= 'gmail.jpg' />", ["Real", "Fake"], "Fake")
];
//create quiz
var quiz = new Quiz(questions);
// display
populate();
body {
background-color: #538a70;
}
.grid {
width: 600px;
height: 500px;
margin: 0 auto;
background-color: #fff;
padding: 10px 50px 50px 50px;
border: 2px solid #cbcbcb;
}
.grid h1 {
font-family: "sans-serif";
font-size: 60px;
text-align: center;
color: #000000;
padding: 2px 0px;
}
#score {
color: #000000;
text-align: center;
font-size: 30px;
}
.grid #question {
font-family: "monospace";
font-size: 30px;
color: #000000;
}
.buttons {
margin-top: 30px;
}
#btn0,
#btn1,
#btn2,
#btn3 {
background-color: #a0a0a0;
width: 250px;
font-size: 20px;
color: #fff;
border: 1px solid #1D3C6A;
margin: 10px 40px 10px 0px;
padding: 10px 10px;
}
#btn0:hover,
#btn1:hover,
#btn2:hover,
#btn3:hover {
cursor: pointer;
background-color: #00994d;
}
#btn0:focus,
#btn1:focus,
#btn2:focus,
#btn3:focus {
outline: 0;
}
#progress {
color: #2b2b2b;
font-size: 18px;
}
<div class="grid">
<div id="quiz">
<h1>Can you spot the fake email?</h1>
<hr style="margin-bottom: 20px">
<p id="question"></p>
<div class="buttons">
<button id="btn0"><span id="choice0"></span></button>
<button id="btn1"><span id="choice1"></span></button>
</div>
<hr style="margin-top: 50px">
<footer>
<p id="progress">Question x of y</p>
</footer>
</div>
</div>
When user clicks button I trigger class and I add it second name, on second I have written to get swapped, I wrote you basically full project, and please read the whole comments, to understand logic
//Calling Elements from DOM
const button = document.querySelectorAll(".check");
const images = document.querySelectorAll(".image");
const answer = document.querySelector("h1");
//Declaring variable to randomly insert any object there to insert source in DOM Image sources
let PreparedPhotos;
//Our Images Sources and With them are its fake or not
//fake: true - yes its fake
//fake: false - no its real
const image = [
[
{
src:
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/1200px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg",
fake: true
},
{
src:
"http://graphics8.nytimes.com/images/2012/04/13/world/europe/mona-lisa-like-new-images/mona-lisa-like-new-images-custom4-v3.jpg",
fake: false
}
],
[
{
src:
"https://cdn.shopify.com/s/files/1/0849/4704/files/Creacion_de_Adan__Miguel_Angel_f5adb235-bfa8-4caa-8ffb-c5328cbad953_grande.jpg?12799626327330268216",
fake: false
},
{
src:
"https://cdn.shopify.com/s/files/1/0849/4704/files/First-image_Fb-size_grande.jpg?10773543754915177139",
fake: true
}
]
];
//Genrating Random Photo on HTML
function setRandomPhoto() {
//Random Number which will be length of our array of Object
//if you array includes 20 object it will generate random number
// 0 - 19
const randomNumber = Math.floor(Math.random() * image.length);
//Decalaring our already set variable as Array Object
PreparedPhoto = image[randomNumber];
//Our first DOM Image is Variables first object source
images[0].src = PreparedPhoto[0].src;
//and next image is next object source
images[1].src = PreparedPhoto[1].src;
}
//when windows successfully loads, up function runs
window.addEventListener("load", () => {
setRandomPhoto();
});
//buttons click
//forEach is High Order method, basically this is for Loop but when you want to
//trigger click use forEach - (e) is single button whic will be clicked
button.forEach((e) => {
e.addEventListener("click", () => {
//decalring variable before using it
let filtered;
//finding from our DOM image source if in our long array exists
//same string or not as Image.src
//if it exists filtered variable get declared with that found obect
for (let i = 0; i < image.length; i++) {
for (let k = 0; k < 2; k++) {
if (image[i][k].src === images[0].src) {
filtered = image[i][k];
}
}
}
//basic if else statement, if clicked button is Fake and image is true
//it outputs You are correct
//if clicked button is Real and Image is false it outputs Correct
//Else its false
//Our image checking comes from filtered variable
if (e.innerText === "Fake" && filtered.fake === true) {
answer.innerText = "You Are Correct";
images.forEach((image) => {
image.classList.toggle("hidden");
});
} else if (e.innerText === "Real" && filtered.fake === false) {
answer.innerText = "You Are Correct";
images.forEach((image) => {
image.classList.toggle("hidden");
});
} else {
answer.innerHTML = "You are Wrong";
images.forEach((image) => {
image.classList.toggle("hidden");
});
}
});
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100%;
min-height: 100vh;
display: flex;
justify-content: space-around;
align-items: center;
flex-direction: column;
}
.image-fluid {
display: flex;
}
.image-fluid .image {
width: 200px;
margin: 0 10px;
transition: 0.5s;
}
.image-fluid .image:nth-child(1).hidden {
transform: translateX(110px);
}
.image-fluid .image:nth-child(2).hidden {
transform: translateX(-110px);
}
<div class="container">
<div class="image-fluid">
<img src="" class="image hidden">
<img src="" class="image hidden">
</div>
<div class="button-fluid">
<button class="check">Fake</button>
<button class="check">Real</button>
</div>
</div>
<h1></h1>
I've searched the internet but I can't seem to find anything that works for me.
Here is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Heating System Control</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
strLED1 = "";
strLED2 = "";
strText1 = "";
strText2 = "";
var LED1_state = 0;
var LED2_state = 0;
function GetArduinoIO()
{
nocache = "&nocache=" + Math.random() * 1000000;
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseXML != null)
{
// XML file received - contains analog values, switch values and LED states
document.getElementById("input1").innerHTML =
this.responseXML.getElementsByTagName('analog')[0].childNodes[0].nodeValue;
document.getElementById("input2").innerHTML =
this.responseXML.getElementsByTagName('analog')[1].childNodes[0].nodeValue;
// LED 1
if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "on") {
document.getElementById("LED1").innerHTML = "ON";
document.getElementById("LED1").style.backgroundColor = "green";
document.getElementById("LED1").style.color = "white";
LED1_state = 1;
}
else {
document.getElementById("LED1").innerHTML = "OFF";
document.getElementById("LED1").style.backgroundColor = "red";
document.getElementById("LED1").style.color = "white";
LED1_state = 0;
}
// LED 2
if (this.responseXML.getElementsByTagName('LED')[1].childNodes[0].nodeValue === "on") {
document.getElementById("LED2").innerHTML = "ON";
document.getElementById("LED2").style.backgroundColor = "green";
document.getElementById("LED2").style.color = "white";
LED2_state = 1;
}
else {
document.getElementById("LED2").innerHTML = "OFF";
document.getElementById("LED2").style.backgroundColor = "red";
document.getElementById("LED2").style.color = "white";
LED2_state = 0;
}
}
}
}
}
// send HTTP GET request with LEDs to switch on/off if any
request.open("GET", "ajax_inputs" + strLED1 + strLED2 + nocache, true);
request.send(null);
setTimeout('GetArduinoIO()', 1000);
strLED1 = "";
strLED2 = "";
}
function GetButton1()
{
if (LED1_state === 1)
{
LED1_state = 0;
strLED1 = "&LED1=0";
}
else
{
LED1_state = 1;
strLED1 = "&LED1=1";
}
}
function GetButton2()
{
if (LED2_state === 1)
{
LED2_state = 0;
strLED2 = "&LED2=0";
}
else
{
LED2_state = 1;
strLED2 = "&LED2=1";
}
}
function SendText1()
{
nocache = "&nocache=" + Math.random() * 1000000;
var request = new XMLHttpRequest();
strText2 = "&txt2=" + document.getElementById("txt_form1").form_text1.value + "&end2=end";
request.open("GET", "ajax_inputs" + strText2 + nocache, true);
request.send(null);
}
function SendText2()
{
nocache = "&nocache=" + Math.random() * 1000000;
var request = new XMLHttpRequest();
strText1 = "&txt1=" + document.getElementById("txt_form2").form_text2.value + "&end1=end";
request.open("GET", "ajax_inputs" + strText1 + nocache, true);
request.send(null);
}
function clsTxt1()
{
setTimeout(
function clearTxt()
{
document.getElementById("txt_form1").form_text1.value = "";
}, 500)
}
function clsTxt2()
{
setTimeout(
function clearTxt()
{
document.getElementById("txt_form2").form_text2.value = "";
}, 500)
}
function Threshold1()
{
var thr1 = document.getElementById("txt_form1").form_text1.value;
document.getElementById("thresh1").innerHTML = thr1;
}
function Threshold2()
{
var thr2 = document.getElementById("txt_form2").form_text2.value;
document.getElementById("thresh2").innerHTML = thr2;
}
</script>
<style>
.IO_box
{
float: left;
margin: 0 20px 20px 0;
border: 1px solid black;
padding: 0 5px 0 5px;
width: 100px;
height: 196px;
text-align: center;
}
h1
{
font-family: Helvetica;
font-size: 120%;
color: blue;
margin: 5px 0 10px 0;
text-align: center;
}
h2
{
font-family: Helvetica;
font-size: 85%;
color: black;
margin: 10px 0 5px 0;
text-align: center;
}
p, form
{
font-family: Helvetica;
font-size: 80%;
color: #252525;
text-align: center;
}
button
{
font-family: Helvetica;
font-size: 80%;
max-width: 100px;
width: 90px;
height: 25px;
margin: 0 auto;
text-align: center;
border: none;
}
input
{
font-family: Helvetica;
font-size: 80%;
max-width: 100px;
width: 90px;
height: 25px;
margin: 0 auto;
text-align: center;
border: none;
}
.small_text
{
font-family: Helvetica;
font-size: 70%;
color: #737373;
text-align: center;
}
textarea
{
resize: none;
max-width: 90px;
margin-bottom: 1px;
text-align: center;
}
</style>
</head>
<body onload="GetArduinoIO(); Threshold1()">
<h1>Heating System Control</h1>
<div class="IO_box">
<h2>Room One</h2>
<p>Temp1 is: <span id="input1">...</span></p>
<button type="button" id="LED1" onclick="GetButton1()" color="white" backgroundColor="red" style="border: none;">OFF</button><br /><br />
<form id="txt_form1" name="frmText">
<textarea name="form_text1" rows="1" cols="10"></textarea>
</form>
<input type="submit" value="Set Temp" onclick="SendText1(); clsTxt1(); Threshold1();" style ="background-color:#5F9EA0" />
<p>Threshold: <span id="thresh1">...</span></p>
</div>
<div class="IO_box">
<h2>Room Two</h2>
<p>Temp2 is: <span id="input2">...</span></p>
<button type="button" id="LED2" onclick="GetButton2()" color="white" backgroundColor="red" style="border: none;">OFF</button><br /><br />
<form id="txt_form2" name="frmText">
<textarea name="form_text2" rows="1" cols="10"></textarea>
</form>
<input type="submit" value="Set Temp" onclick="SendText2(); clsTxt2(); Threshold2();" style ="background-color:#5F9EA0" />
<p>Threshold: <span id="thresh2">...</span></p>
</div>
</body>
</html>
So my question is, How can I keep the value inserted in the text area even after I reload the page (from the "Threshold1()" function)? I found a few examples with "localStorage" and JQuery, but I have no idea how to call the saved value when I reload the page.
Any help would be appreciated.
Thanks in advance,
Stefan.
Local Storage Explained
The localStorage object likes to store strings, so how would one store large objects, let's say some complex data structure? - Simple, JavaScript has a neat function built in, look up JSON.stringify(object). So all you would need to do is something like below to store some complex object is something like the code I've provided below. Then to retrieve an object from the localStorage you'll want to use JSON.parse(object);.
To look into localStorage, I strongly suggest you take a look at the likes of MDN and if you want to look into the JSON.parse and JSON.stringify functions, you can also find them both here:
JSON.parse() link
JSON.stringify() link
// vanilla js version of $(document).ready(function(){/*code here*/});
window.ready = function(fnc) {
if (typeof fnc != "function") {
return console.error("You need to pass a function as a param.");
}
try { // try time out for some old IE bugs
setTimeout(function () {
document.addEventListener("DOMContentLoaded", fnc());
}, 10)
} catch (e) {
try { // sometimes timeout won't work
document.addEventListener("DOMContentLoaded", fnc());
} catch (ex) {
console.log(ex);
}
}
};
// shorter than $(document).ready();
ready(function() {
var object = {
name: "Jack",
age: 30,
location: "U.S.A.",
get_pay: function() {
console.log("test");
}
},
test;
console.log(object);
var obj_string = JSON.stringify(object);
// run a test
var run_test = function() {
// output the stored object
test = localStorage.getItem("test");
console.log(test);
// to make js turn it into an object again
test = JSON.parse(localStorage.getItem("test"));
console.log(test);
};
// demo of trying to store an actual object
try {
localStorage.setItem("test", object);
run_test();
} catch (e) {
console.log(e);
}
// demo of trying to store the string
try {
localStorage.setItem("test", obj_string);
run_test();
} catch (e) {
console.log(e);
}
});
You can use this JSFiddle : http://jsfiddle.net/xpvt214o/45115/
here we are using Cookie concept and jquery.cookie.js to accomplish what you are trying to do.
to properly check the fiddle you need to press "Run" every time, you can open the same fiddle in 2 tabs write something in the first fiddle then just press run in the 2nd fiddle tab the value should automatically update, here the
$(function(){}); replicates your pageload
My question isn't exactly answered, but I completely avoided storing info on a device. Now I'm just reading the value straight from the arduino and it works. But thanks to everyone that provided some help.
For a project im working on i want to make my hybrid app (phonegap) switch screens when the app detects the BluetoothLE signal from an Arduino. For this I made the code loop trough a couple of list items and check of the content of the li item is the same as "TEST123"(the name i gave the Arduino). If these would be the same, the app should switch to another page. I edited the code called "cordova-plugin-ble-central made by Don Coleman on GitHub) to reach this goal.
I made the code so it would scroll trough the li items within a ul, read the content and called the connect function if the string was the same as "TEST123", but my pages do not seem to switch.
Thanks for your help!
HTML:
<body>
<div class="app">
<h1>BluefruitLE</h1>
<div id="mainPage" class="show">
<ul id="deviceList">
</ul>
<button id="refreshButton">Refresh</button>
</div>
<div id="detailPage" class="hide">
<div id="resultDiv"></div>
<div>
<input type="text" id="messageInput" value="Hello"/>
<button id="sendButton">Send</button>
</div>
<button id="disconnectButton">Disconnect</button>
</div>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
app.initialize();
</script>
</body>
CSS:
body {
font-family: "Helvetica Neue";
font-weight: lighter;
color: #2a2a2a;
background-color: #f0f0ff;
-webkit-appearance: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-touch-callout: none; -webkit-user-select: none;
}
button {
margin: 15px;
-webkit-appearance:none;
font-size: 1.2em;
}
#mainPage {
text-align:center;
width: 100vw;
height: 100vh;
}
#detailPage {
text-align:center;
font-size: 2em;
width: 100vw;
height: 100vh;
background-color: red;
}
button {
-webkit-appearance: none;
font-size: 1.5em;
border-radius: 0;
}
#resultDiv {
font: 16px "Source Sans", helvetica, arial, sans-serif;
font-weight: 200;
display: block;
-webkit-border-radius: 6px;
width: 100%;
height: 140px;
text-align: left;
overflow: auto;
}
#mainPage.show{
display: block;
}
#mainPage.hide{
display: none;
}
#detailPage.show{
display: block;
}
#detailPage.hide{
display: none;
}
And ofcourse my JavaScript:
'use strict';
// ASCII only
function bytesToString(buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer));
}
// ASCII only
function stringToBytes(string) {
var array = new Uint8Array(string.length);
for (var i = 0, l = string.length; i < l; i++) {
array[i] = string.charCodeAt(i);
}
return array.buffer;
}
// this is Nordic's UART service
var bluefruit = {
serviceUUID: '6e400001-b5a3-f393-e0a9-e50e24dcca9e',
txCharacteristic: '6e400002-b5a3-f393-e0a9-e50e24dcca9e', // transmit is from the phone's perspective
rxCharacteristic: '6e400003-b5a3-f393-e0a9-e50e24dcca9e' // receive is from the phone's perspective
};
var app = {
initialize: function() {
this.bindEvents();
detailPage.hidden = true;
//ale paginas hidden behalve login
},
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
refreshButton.addEventListener('touchstart', this.refreshDeviceList, false);
sendButton.addEventListener('click', this.sendData, false);
disconnectButton.addEventListener('touchstart', this.disconnect, false);
deviceList.addEventListener('touchstart', this.connect, false); // assume not scrolling
},
onDeviceReady: function() {
app.refreshDeviceList();
},
refreshDeviceList: function() {
deviceList.innerHTML = ''; // empties the list
if (cordova.platformId === 'android') { // Android filtering is broken
ble.scan([], 5, app.onDiscoverDevice, app.onError);
} else {
ble.scan([bluefruit.serviceUUID], 5, app.onDiscoverDevice, app.onError);
}
},
onDiscoverDevice: function(device) {
var listItem = document.createElement('li'),
html = '<b>' + device.name + '</b><br/>' +
'RSSI: ' + device.rssi + ' | ' +
device.id;
listItem.dataset.deviceId = device.id;
listItem.innerHTML = html;
deviceList.appendChild(listItem);
},
ulScroll: function() {
var ul = document.getElementById("deviceList");
var items = ul.getElementsByTagName("li");
for (var i = 0; i < items.length; i++) {
if ((items.textContent || items.innerText) == "TEST123"){
connect: function(e) {
var deviceId = e.target.dataset.deviceId,
onConnect = function(peripheral) {
app.determineWriteType(peripheral);
// subscribe for incoming data
ble.startNotification(deviceId, bluefruit.serviceUUID, bluefruit.rxCharacteristic, app.onData, app.onError);
sendButton.dataset.deviceId = deviceId;
disconnectButton.dataset.deviceId = deviceId;
resultDiv.innerHTML = "";
app.showDetailPage();
};
ble.connect(deviceId, onConnect, app.onError);
},
}
}
}
disconnect: function(event) {
var deviceId = event.target.dataset.deviceId;
ble.disconnect(deviceId, app.showMainPage, app.onError);
},
showMainPage: function() {
document.getElementById("mainPage").className = "show";
document.getElementById("detailPage").className = "hide";
},
showDetailPage: function() {
document.getElementById("detailPage").className = "show";
document.getElementById("mainPage").className = "hide";
},
onError: function(reason) {
alert("ERROR: " + reason);
}
};
P.S. Very sorry for the unorganized code
How i would structure the code:
var app={
devices:[], //thats were the devices are stored
onDeviceReady:refreshDeviceList,
refreshDeviceList: function() {
deviceList.innerHTML = ''; // empties the list
this.devices=[];
if (cordova.platformId === 'android') { // Android filtering is broken
ble.scan([], 5, app.onDiscoverDevice, app.onError);
} else {
ble.scan([bluefruit.serviceUUID], 5, app.onDiscoverDevice, app.onError);
}
//all devices checked, lets search ours:
var my=this.devices.find(device => { device.name=="TEST123"});
if(my){
ble.connect(my.id,app.onconnect,errorhandling);
}else{
alert("my device not found");
}
},
onDiscoverDevice: function(device) {
//add to html
var listItem = document.createElement('li'),
html = '<b>' + device.name + '</b><br/>' +
'RSSI: ' + device.rssi + ' | ' +
device.id;
listItem.innerHTML = html;
deviceList.appendChild(listItem);
//add to devices:
this.devices.push(device);
},
onconnect:function(e){
//your connect function
}
}
Additional notes:
refreshButton etc are undefined. You need to find them:
var refreshButton=document.getElementById("refreshButton");
I have done this working fiddle:
HTML
<div id="container">
<div id="input_container">
<label for="increment_t">Set t-increment value (default 0.1):</label>
<input id="increment_t" type="number" min="0" max="1" step="0.1" value="0.1" />
</div>
<br />
<div id="generator_container">
<a id="downloadlink" download="outfile.txt">Download</a>
<button id="create_link">Export output</button>
</div>
</div>
CSS
#container {
position: absolute;
display: block;
left: 0;
top: 0;
padding: 10px 10px; /* (top-bottom) (left-right) */
z-index: 1;
}
#input_container {
display: block;
float: left;
margin-bottom: 10px;
}
#increment_t {
max-width: 50px;
}
#generator_container {
display: block;
float: right;
}
#downloadlink {
display: none;
margin-right: 10px;
}
#create_link {
float: right;
}
JavaScript
(function () {
var t_values;
var t_values_list = [];
for ( var t=0; t<=1; t+=0.1 ){
t_values = t.toFixed(1);
t_values_list.push(t_values);
}
var textFile = null;
makeTextFile = function (text) {
var data = new Blob([text], {type: 'text/plain'});
if (textFile !== null) {
window.URL.revokeObjectURL(textFile);
}
textFile = window.URL.createObjectURL(data);
return textFile;
};
var create_link = document.getElementById('create_link');
create_link.addEventListener('click', function () {
alert(t_values_list);
var link = document.getElementById('downloadlink');
link.href = makeTextFile(t_values_list.join('\n'));
link.style.display = 'inline-block';
}, false);
})();
but I want to set the increment value for the "t" variable (i.e. 0.1, in the for-loop) taking it from the input area. I tried in this way:
JavaScript
(function () {
var t_values;
var t_values_list = [];
alert(document.getElementById("increment_t").value); // test to get the t value, to use it in the following loop for
for ( var t=0, increment_t=document.getElementById("increment_t").value; t<=1; t+=increment_t ){
t_values = t.toFixed(1);
t_values_list.push(t_values);
}
var textFile = null;
makeTextFile = function (text) {
var data = new Blob([text], {type: 'text/plain'});
if (textFile !== null) {
window.URL.revokeObjectURL(textFile);
}
textFile = window.URL.createObjectURL(data);
return textFile;
};
var create_link = document.getElementById('create_link');
create_link.addEventListener('click', function () {
alert(t_values_list);
var link = document.getElementById('downloadlink');
link.href = makeTextFile(t_values_list.join('\n'));
link.style.display = 'inline-block';
}, false);
})();
but It doesn't work. Thanks for your help
If you getting numbers from somewhere else in javascript...always parse them. parseInt(..., 10) or in your example: parseFloat