Use Google Sheets as JSON feed for image carousel - json

I am trying to build an image carousel that uses a Google sheet as the source for the information. I can get the carousel to work if I hard code the JSON, but I am having issues getting the Google Sheet JSON working.
I have opened everything up for viewing that I am working on:
Google Sheet (the script that creates the JSON output can be accessed through Tools/Script Editor)
Google Sheet JSON Output
Google Apps Script Project
Here is the Content Service Web App (generates the JSON from the Google Sheet):
// The name of the spreadsheet from the browser location bar.
// Copy after 'key=' until before the next URL parameter beginning w/&
var SPREADSHEET_ID = '1qolqEsn-hxkRwGfyY1O5ttWB9KzqB7MpgNNF6t3mfvk';
var source = SpreadsheetApp.openById(SPREADSHEET_ID);//Defines the source spreadsheet, in this example, the source is the current spreadsheet.
var source_sheet = source.getSheetByName("Sheet1");//Enter the name between the quotes of the sheet within the specified source spreadsheet that holds the data you want to transfer
var lastRow = source_sheet.getLastRow();//For checking last row with data in cell and formatting range
var lastColumn = source_sheet.getLastColumn();//For checking last row with data in cell and formatting range
var source_range = source_sheet.getRange(1,1,lastRow,lastColumn);//(StartRow,StartColumn,NumberofRowstoGet,NumberofColumnstoGet)
// The name of the sheet, displayed in a tab at the bottom of the spreadsheet.
// Default is 'Sheet1' if it's the first sheet.
var SHEET_NAME = 'Sheet1';
function doGet(request) {
// var callback = request.parameters.jsonp;
var callback = request.parameters.callback;
var json = callback + '(' + Utilities.jsonStringify(source_range.getValues()) + ')';
return ContentService.createTextOutput(json).setMimeType(ContentService.MimeType.JAVASCRIPT);
}
// Testing to see if the jsonp parameter is being used properly.
function testDoGet() {
var request = {parameters: {jsonp: 'callback'}};
var results = doGet(request);
Logger.log(results.getContent());
}
Below is a working code snippet with the hard coded JSON commented out, using the feed from the spreadsheet. Again, the script is fully functional using the hard coded JSON, but does not work when I attempt to use the feed URL.
$(function(){
$.getJSON('https://script.google.com/macros/s/AKfycbzpOcYAX9CrBxGKyQ18Nupe9EzGU-Byl7_A-fY-TSd1zbcvAw/exec?callback=?',
function(json) {
// console.log(json); //Testing
// console.log(json[0][0]); //Testing
var mhtml = '<ul>';
for (var i = 1; i < json.length; i++){ //For each item in the json array
// console.log('image: ' + json[i][0]); //Log the array field
// console.log('title: ' + json[i][1]); //Log the array field
// console.log('desc: ' + json[i][2]); //Log the array field
mhtml += '<li><div class="img-responsive"><img src="https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy?url='+json[i][0]+'&container=focus&resize_w=665" /></div>';
mhtml += '<div class="desc"><h1 class="title">'+json[i][1]+'</h1>';
mhtml += '<p class="expert">'+json[i][2]+'</p></div>';
mhtml += '</li>';
};
mhtml += '</ul>';
$('.slider').append($(mhtml));
slideshow();
});
function slideshow() {
// console.log('running slideshow'); //Testing
// console.log('slider length: ' + $(".slider ul> li").length); //Testing
$(".slider ul> li:gt(0)").css("opacity" , "0");
var j = 0;
var delay = 3000; //millisecond delay between cycles
function cycleThru(){
var jmax = $(".slider ul> li").length -1;
$(".slider ul> li:eq(" + j + ")")
.animate({"opacity" : "1.0"} ,400)
.animate({"opacity" : "1"}, delay)
.animate({"opacity" : "0"}, 400,
function(){
(j == jmax) ? j=0 : j++;
cycleThru();
});
};
cycleThru();
}
});
#import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:400,700);
*{
margin: 0;
padding: 0;
font-family: 'Yanone Kaffeesatz';
}
h1 {
font-size: 3em;
font-family: arial;
}
p {
font-size: 1em;
font-family: arial;
}
ul li { margin: 0;
padding: 0;list-style:none}
.slider {
display: block;
min-height: 345px;
max-width: 665px;
margin: auto;
border: 12px rgba(255,255,240,1) solid;
-webkit-box-shadow: 0px 0px 5px rgba(0,0,0,.8);
-moz-box-shadow: 0px 0px 5px rgba(0,0,0,.8);
box-shadow: 0px 0px 5px rgba(0,0,0,.8);
margin-top: 20px;
position: relative;
}
.slider ul{
display: block;
height: auto;
max-width: 640px;
overflow:hidden}
.slider>ul>li {
height: 320px;
float: left;
position: absolute;
}
.slider >ul>li>img {
margin: auto;
height: 100%;
min-height: 345px;
max-width: 665px;
}
.desc {
position: absolute;
bottom: 0;
left: 0;
width: 260px;
z-index: 1000;
background-color: rgba(255,255,240,0.5);
display: inline-block;
text-align: center;
padding-top: 7px;
border-top-right-radius: 15px;
border-bottom-right-radius: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://storage.googleapis.com/code.getmdl.io/1.0.4/material.min.js"></script>
<?!= include('css'); ?>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
</head>
<body>
<div class="slider"></div>
</body>
</html>

You need to add the callback parameter to your URL.
$.getJSON('https://script.google.com/macros/s/AKfycbzpOcYAX9CrBxGKyQ18Nupe9EzGU-Byl7_A-fY-TSd1zbcvAw/exec?callback=?', ...
In your contentservice app:
function doGet(request) {
var callback = request.parameters.callback;
var json = callback + '(' + Utilities.jsonStringify(source_range.getValues()) + ')';
return ContentService.createTextOutput(json).setMimeType(ContentService.MimeType.JAVASCRIPT);
}

I have this working now and have updated the code above. Thanks to #spencer-easton for helping with the JSON. Once I got the feed working, I had to make changes to get it to work. Significant changes to the original code to highlight are:
Added a for loop to iterate through the array that results from the JSON:
for (var i = 1; i < json.length; i++){ //For each item in the json array
mhtml += '<li><div class="img-responsive"><img src="https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy?url='+json[i][0]+'&container=focus&resize_w=665" /></div>';
mhtml += '<div class="desc"><h1 class="title">'+json[i][1]+'</h1>';
mhtml += '<p class="expert">'+json[i][2]+'</p></div>';
mhtml += '</li>';
};
Removed $(document).ready from the function that cycled the carousel, and instead called it at the end of the json response function:
$('.slider').append($(mhtml));
slideshow();
});
function slideshow() {
$(".slider ul> li:gt(0)").css("opacity" , "0");
var j = 0;
var delay = 3000; //millisecond delay between cycles
function cycleThru(){
var jmax = $(".slider ul> li").length -1

Related

When trying to set file description using one of form field return undefined

To be honest, I'm a novice trying combine shared scripts from web to make a google drive dropbox page for my wedding. Thanks to kind sharing of codes mainly from the community here stackoverflow, everything works fine except it doesn't update the file description by the name entered in the form. It returns undefined. After trying to fix it for a week by myself without knowing a thing, I ended up asking a help here. Can anyone kindly have a look on my script and tell me what I've done wrong? Thank you.
server.gs
function doGet(e) {
var output = HtmlService.createHtmlOutputFromFile('form.html');
output.addMetaTag('viewport', 'width=device-width, initial-scale=1');// See http://stackoverflow.com/a/42681526/470749
return output.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName, form) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var dropbox = "Wedding Photos"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
file.setDescription("Provided by " + form.myName);
return "Thank You" + uploadername + "!!! ";
}catch(e){
return 'Error: ' + e.toString();
}
}
form.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
Send Chiwoo&Sangah's Wedding Photos
</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
</head>
<body>
<div align="center">
<p><img src="https://static.wixstatic.com/media/d23d4c_44fcb98ffcf2490f9c8822f7c6caaf72~mv2.jpg" width="100%"></p>
<div id="formcontainer" align="center" style="text-align: center">
<p align="center"><label for="myForm"> Chiwoo & Sangah's Wedding Photo Uploader:</label></p>
<br><br>
<form id="myForm" align="center" style="text-align: center">
<label for="myForm">Your Name:</label>
<div width="600px" align="center">
<input type="text" name="myName" placeholder="You can leave your name here" style="text-align: center">
</div>
<br>
<div class="center" align="center" text-align="center" margin="auto">
<label for="myFile" align="center" style="text-align: center">Upload Attachment(s):</label>
<p align="center"><input type="file" name="filename" id="myFile" multiple></p>
<input type="button" value="Submit" onclick="iteratorFileUpload()">
<br>
</div>
</form>
</div>
<div id="output" align="center"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});//.append("<div class='caption'>37%</div>");
$(".progress-label").html('Preparing files for upload');
// Send each file at a time
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i]);
}
}
}
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
var currFolder = 'Wedding Photos';
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$("#progressbar").progressbar({value: porc });
$(".progress-label").text(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
//uploadsFinished();
numUploads.done = 0;
$(".progress-label").text($(".progress-label").text() + ': FINISHED!');
$("#progressbar").after('Thank You!!! Refresh this page if you have more to upload.');
};
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
text-align: center;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌​ -moz-box-sizing: border-box;
box-sizing: border-box;
text-align: center;
}
select {
margin: auto;
position: middle;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
margin: auto;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
</html>
A couple Small Changes
function uploadFileToDrive(base64Data, fileName, name) {//added name and removed form
Logger.log('filename: %s name: %s',fileName,name);
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var dropbox = "Wedding Photos"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
file.setDescription("Provided by " + name);//using name here
return "Thank You" + uploadername + "!!! ";
}catch(e){
return 'Error: ' + e.toString();
}
}
In html:
Changed the name line to this:
<input type="text" id="myName" name="myName" placeholder="You can leave your name here" style="text-align: center">
In javascript:
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
var name = document.getElementById("myName").value;//added this
console.log('name: %s',name);
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, name);//changed this line. I removed the currFolder since you were not using it. I could not use the form because I was getting an IllegalElementError and I didn't want to chase it.
}
reader.readAsDataURL(file);
}
Description:
I think that you should do some clean-up of your html file:
The style tag at the bottom it's better to include it inside the head tag
Remove the duplicated tags that load external files, like <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>. Actually, as someone to mixing code from different sources, whenever be possible avoid the use of frameworks like jQuery. Native Web APIs might require longer statements but this might be more efficient than trying to adapt code that uses different frameworks.
Remove the meta tags. Google Apps Script ignores them. Ref. https://developers.google.com/apps-script/reference/html/html-output?hl=en#addmetatagname,-content
Regarding your specific issue,
On the client-side code, add the following line
var name = document.querySelector("form input[name='myName]").value;
before
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
and on the above line replace currFolder by name
and on the following line of the server side code replace form by name
function uploadFileToDrive(base64Data, fileName, form)
and on the following line replace form.myName by name
file.setDescription("Provided by " + form.myName);

How to integrate a script into a function in HTML?

I want to make a html button that appears when you scroll down and when clicked it shows a random blogger post.
I have code to make it appear when you scroll down and code for a button that shows a random post. But I don't know how to make them work together.
This is my scroll button code, below is random post code. I don't know how to integrate it inside TopFunction.
Thank you very much for your help and insights!
#myBtn {
display: none;
position: fixed;
bottom: 20px;
right: 30px;
z-index: 99;
font-size: 18px;
border: none;
outline: none;
background-color: red;
color: white;
cursor: pointer;
padding: 15px;
border-radius: 4px;
}
#myBtn:hover {
background-color: #555;
}
</style>
<button onclick="topFunction()" id="myBtn"></button>
<script>
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
document.getElementById("myBtn").style.display = "block";
} else {
document.getElementById("myBtn").style.display = "none";
}
}
// When the user clicks on the button, show random post
function topFunction() {
}
</script>
RANDOM POST
<script type="text/javascript">
function showLucky(root){ var feed = root.feed; var entries = feed.entry || []; var entry = feed.entry[0]; for (var j = 0; j < entry.link.length; ++j){if (entry.link[j].rel == 'alternate'){window.location = entry.link[j].href;}}} function fetchLuck(luck){ script = document.createElement('script'); script.src = '/feeds/posts/summary?start-index='+luck+'&max-results=1&alt=json-in-script&callback=showLucky'; script.type = 'text/javascript'; document.getElementsByTagName('head')[0].appendChild(script); } function feelingLucky(root){ var feed = root.feed; var total = parseInt(feed.openSearch$totalResults.$t,10); var luckyNumber = Math.floor(Math.random()*total);luckyNumber++; a = document.createElement('a'); a.href = '#random'; a.rel = luckyNumber; a.onclick = function(){fetchLuck(this.rel);}; a.innerHTML = 'RANDOM POST'; document.getElementById('myBtn').appendChild(a); } </script><script src="/feeds/posts/summary?max-results=0&alt=json-in-script&callback=feelingLucky">
</script>
I have no idea if below is correct or not. In order to help you correctly we need to know WHERE the codes are coming from. And you need to explain into detail what you have tried.
Below might work: I have added a <div> for which should contain the random posts when button is clicked. Content can be styled as you wish.
Be aware of the path /feeds/posts/summary?max-results=0&alt=json-in-script&callback=feelingLucky. This is hardcoded and the JS script change some word in it. This needs to be the same (and the one in the code) to your own folderstructure.
I have also cleared up your code a little... Always use id for scripts and class for CSS styling.
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {
scrollFunction()
};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
document.getElementById("myBtn").style.display = "block";
} else {
document.getElementById("myBtn").style.display = "none";
}
}
// When the user clicks on the button, show random post
function topFunction() {
//Why is this empty?
};
function showLucky(root) {
var feed = root.feed;
var entries = feed.entry || [];
var entry = feed.entry[0];
for (var j = 0; j < entry.link.length; ++j) {
if (entry.link[j].rel == 'alternate') {
window.location = entry.link[j].href;
}
}
};
function fetchLuck(luck) {
script = document.createElement('script');
script.src = '/feeds/posts/summary?start-index=' + luck + '&max-results=1&alt=json-in-script&callback=showLucky';
script.type = 'text/javascript';
document.getElementsByTagName('randompost')[0].appendChild(script);
}
function feelingLucky(root) {
var feed = root.feed;
var total = parseInt(feed.openSearch$totalResults.$t, 10);
var luckyNumber = Math.floor(Math.random() * total);
luckyNumber++;
a = document.createElement('a');
a.href = '#random';
a.rel = luckyNumber;
a.onclick = function() {
fetchLuck(this.rel);
};
a.innerHTML = 'RANDOM POST';
document.getElementById('myBtn').appendChild(a);
};
.myBtn {
display: block;
position: fixed;
bottom: 20px;
right: 30px;
z-index: 99;
font-size: 18px;
border: none;
outline: none;
background-color: red;
color: white;
cursor: pointer;
padding: 15px;
border-radius: 4px;
}
.myBtn:hover {
background-color: #555;
}
.myDiv {
width: 50%;
height: auto;
background: rgba(255,0,0,0.5);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="showLucky()" id="myBtn" class="myBtn">Try me</button>
<div class="myDiv" id="randompost" >
<script src="/feeds/posts/summary?max-results=0&alt=json-in-script&callback=feelingLucky">
</script>
Something here...
</div>

Browse button that will display image file from a local directory folder in html

Hi I wanted to know if its possible to create a button in html that functions like a "Browse" button like when clicked it will show the computer directory such as the Local Drive, Documents etc.
What I wanted to do is use this "Browse" button to set a Folder path that has Images (.png/.jpeg) then once directory folder has been selected the image file name should show up in a list form.
*Note: The machine is connected on a LAN network everything is shared and with
out any restriction.
Sample
Path:
C:\Documents\TargetFolder (this is what will be browsed using the "Browse" button the path location may change could be from a different location within the same machine or different computer over the same network that is why a "Browse" button is needed)
Output:
From the Source(TargetFolder) lets say with 20 image file a list should show up with the image file name, path properties(created date and time )and the actual image pulled up. Switches as well base on what was selected on the list
Is this possible?
browse button window
webpage looks like this
What you want actually is a file manager (file gallery to be more precise) in web browser.
there is no such thing in that would help you get that without writing hundreds of lines of code.
This link might help you https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
and also follow the below code
var input = document.querySelector('input');
var preview = document.querySelector('.preview');
input.style.opacity = 0;input.addEventListener('change', updateImageDisplay);function updateImageDisplay() {
while(preview.firstChild) {
preview.removeChild(preview.firstChild);
}
var curFiles = input.files;
if(curFiles.length === 0) {
var para = document.createElement('p');
para.textContent = 'No files currently selected for upload';
preview.appendChild(para);
} else {
var list = document.createElement('ol');
preview.appendChild(list);
for(var i = 0; i < curFiles.length; i++) {
var listItem = document.createElement('li');
var para = document.createElement('p');
if(validFileType(curFiles[i])) {
para.textContent = 'File name ' + curFiles[i].name + ', file size ' + returnFileSize(curFiles[i].size) + '.';
var image = document.createElement('img');
image.src = window.URL.createObjectURL(curFiles[i]);
listItem.appendChild(image);
listItem.appendChild(para);
} else {
para.textContent = 'File name ' + curFiles[i].name + ': Not a valid file type. Update your selection.';
listItem.appendChild(para);
}
list.appendChild(listItem);
}
}
}var fileTypes = [
'image/jpeg',
'image/pjpeg',
'image/png'
]
function validFileType(file) {
for(var i = 0; i < fileTypes.length; i++) {
if(file.type === fileTypes[i]) {
return true;
}
}
return false;
}function returnFileSize(number) {
if(number < 1024) {
return number + 'bytes';
} else if(number >= 1024 && number < 1048576) {
return (number/1024).toFixed(1) + 'KB';
} else if(number >= 1048576) {
return (number/1048576).toFixed(1) + 'MB';
}
}
html {
font-family: sans-serif;
}
form {
width: 600px;
background: #ccc;
margin: 0 auto;
padding: 20px;
border: 1px solid black;
}
form ol {
padding-left: 0;
}
form li, div > p {
background: #eee;
display: flex;
justify-content: space-between;
margin-bottom: 10px;
list-style-type: none;
border: 1px solid black;
}
form img {
height: 64px;
order: 1;
}
form p {
line-height: 32px;
padding-left: 10px;
}
form label, form button {
background-color: #7F9CCB;
padding: 5px 10px;
border-radius: 5px;
border: 1px ridge black;
font-size: 0.8rem;
height: auto;
}
form label:hover, form button:hover {
background-color: #2D5BA3;
color: white;
}
form label:active, form button:active {
background-color: #0D3F8F;
color: white;
}
<form method="post" enctype="multipart/form-data">
<div>
<label for="image_uploads">Choose images to upload (PNG, JPG)</label>
<input type="file" id="image_uploads" name="image_uploads" accept=".jpg, .jpeg, .png" multiple>
</div>
<div class="preview">
<p>No files currently selected for upload</p>
</div>
<div>
<button>Submit</button>
</div>
</form>
Not exactly what you asked for, but (if it works for your use-case), the user could select multiple files from the same directory using the browse button.
There is a lovely example on MDN
https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications#example_showing_thumbnails_of_user-selected_images
<input type="file" id="input" multiple>
const inputElement = document.getElementById("input");
inputElement.addEventListener("change", handleFiles, false);
function handleFiles() {
const fileList = this.files; /* now you can work with the file list */
}
function handleFiles(files) {
for (let i = 0; i < files.length; i++) {
const file = files[i];
if (!file.type.startsWith('image/')){ continue }
const img = document.createElement("img");
img.classList.add("obj");
img.file = file;
preview.appendChild(img); // Assuming that "preview" is the div output where the content will be displayed.
const reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
reader.readAsDataURL(file);
}
}

XMLHttpRequest.onReadyStateChange not working in Chrome, Firefox, Internet Explorer

I am using Aptana Studio 3 text editor and working on Windows 7 Enterprise OS. I have the following AJAX code which is not working on the local system to fetch JSON files kept on an https website. This example is taken from the Youtube video:
JSON and AJAX Tutorial: With Real Examples
index.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta name="test" content="content"/>
<title>JSON and AJAX</title></head>
<header>
<h1>JSON and AJAX</h1>
<link rel="stylesheet" href="styles.css" type="text/css" media="screen" title="no title" charset="utf-8"/>
</header>
<body>
<script src="main.js"></script>
<button type="button" onclick="function()" id="btn">Fetch Info for 3 New Animals</button>
<div id="animal-info"> </div>
</body>
</html>
Styles.css:
html, body {
padding: 0;
margin: 0;
}
.hide-me {
visibility: hidden;
opacity: 0;
transform: scale(.75);
}
h1 {
margin-top: 0;
font-size: 2.4em;
font-weight: normal;
display: inline-block;
}
body {
font-family: Helvetica, sans-serif;
padding: 50px 10%;
}
button {
background-color: #046380;
color: #FFF;
border: none;
padding: 10px 15px;
font-size: 15px;
border-radius: 4px;
cursor: pointer;
outline: none;
box-shadow: 2px 2px 0 #034154;
margin-bottom: 10px;
margin-left: 18px;
transition: opacity .4s ease-out, transform .4s ease-out, visibility .4s ease-out;
position: relative;
top: -10px;
}
button:hover {
background-color: #034F66;
}
button:active {
background-color: #034154;
box-shadow: none;
position: relative;
top: -8px;
left: 2px;
}
p {
padding: 4px 0 2px 8px;
line-height: 1.7;
border-bottom: 1px dotted #DDD;
list-style: none;
margin: 0;
}
main.js:
var pageCounter = 1;
var animalContainer = document.getElementById("animal-info");
var btn = document.getElementById("btn");
btn.addEventListener("onClick", function() {
var ourRequest = new XMLHttpRequest();
ourRequest.open("GET", "https://learnwebcode.github.io/json-example/animals-" + pageCounter + ".json");
//ourRequest.open('GET', 'animals-' + pageCounter + '.json');
ourRequest.onload = function() {
if (ourRequest.status >= 200 && ourRequest.status < 400) {
var ourData = JSON.parse(ourRequest.responseText);
renderHTML(ourData);
} else {
console.log("We connected to the server, but it returned an error.");
}
};
ourRequest.onerror = function() {
console.log("Connection error");
};
ourRequest.send();
pageCounter++;
if (pageCounter > 3) {
btn.classList.add("hide-me");
}
}
);
function renderHTML(data) {
var htmlString = "";
for (i = 0; i < data.length; i++) {
htmlString += "<p>" + data[i].name + " is a " + data[i].species + " that likes to eat ";
for (ii = 0; ii < data[i].foods.likes.length; ii++) {
if (ii == 0) {
htmlString += data[i].foods.likes[ii];
} else {
htmlString += " and " + data[i].foods.likes[ii];
}
}
htmlString += ' and dislikes ';
for (ii = 0; ii < data[i].foods.dislikes.length; ii++) {
if (ii == 0) {
htmlString += data[i].foods.dislikes[ii];
} else {
htmlString += " and " + data[i].foods.dislikes[ii];
}
}
htmlString += '.</p>';
}
animalContainer.insertAdjacentHTML('beforeend', htmlString);
}
This code doesn't seem to work on my local machine. I tried running it by installing an http-server using NodeJs on my local machine, but still no joy!
Another JSON AJAX code on ww3Schools.com
though seems to work fine. This is an inline javascript code in the html file. Initially i thought onReadyStateChange was the culprit not working on IE, FF, CH etc., but this website code also has onReadyStateChange but it works fine!
Or is it the Button click event handler the cause why it is not working?
btn.addEventListener("onClick", function() {
My code is not inline, could that be the reason? If not, what am i missing or doing wrong?
I modified html file by moving "div" above "script" tag:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta name="test" content="content"/>
<title>JSON and AJAX</title></head>
<header>
<h1>JSON and AJAX</h1>
<link rel="stylesheet" href="styles.css" type="text/css" media="screen" title="no title" charset="utf-8"/>
<button type="button" onclick="function()" id="btn">Fetch Elements</button>
<div id="animal-info"> </div>
</header>
<body>
<script src="main.js"></script>
</body>
</html>
main.js:
var pageCounter = 1;
var animalContainer = document.getElementById("animal-info");
var btn = document.getElementById("btn");
btn.addEventListener("click", function() {
// function LoadJSON() {
if (window.XMLHttpRequest) {
// code for modern browsers
var ourRequest = new XMLHttpRequest();
} else {
//code for IE6, IE5
var ourRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
// ourRequest.onLoad = function() {
ourRequest.onreadystatechange = function() {
if (this.readyState = 4 && (this.status >= 200 && this.status < 400)) {
var ourData = JSON.parse(ourRequest.responseText);
renderHTML(ourData);
} else {
console.log("We connected to the server, but it returned an error.");
}
};
ourRequest.open("GET", "https://learnwebcode.github.io/json-example/animals-" + pageCounter + ".json");
// ourRequest.open('GET', 'animals-' + pageCounter + '.json');
ourRequest.send();
ourRequest.onerror = function() {
console.log("Connection error");
};
pageCounter++;
if (pageCounter > 3) {
btn.classList.add("hide-me");
}
}
);
function renderHTML(data) {
var htmlString = "";
for (i = 0; i < data.length; i++) {
htmlString += "<p>" + data[i].name + " is a " + data[i].species + " that likes to eat ";
for (ii = 0; ii < data[i].foods.likes.length; ii++) {
if (ii == 0) {
htmlString += data[i].foods.likes[ii];
} else {
htmlString += " and " + data[i].foods.likes[ii];
}
}
htmlString += ' and dislikes ';
for (ii = 0; ii < data[i].foods.dislikes.length; ii++) {
if (ii == 0) {
htmlString += data[i].foods.dislikes[ii];
} else {
htmlString += " and " + data[i].foods.dislikes[ii];
}
}
htmlString += '.</p>';
}
// animalContainer.insertAdjacentHTML('beforeend', htmlString);
animalContainer.innerHTML=htmlString;
}
This works now!
The only problem i am facing is if i have more json files on the server, how do i hide ("hide-me") the button based on the number of json files processed, when button is clicked a no of times?
Right now, it hides button if pageCounter exceeds 3.
if (pageCounter > 3) {
btn.classList.add("hide-me");
}
The other issue i see is if i enable "insertAdjacentHTML", it displays each json twice. Why is this happening?
// animalContainer.insertAdjacentHTML('beforeend', htmlString);
Use this:
btn.style.visibility = "hidden";

How to convert excel(xls) file to html and add sorting and filtering

Below code is working for excel to html conversion and partial sorting.
I want when any cells in the header(or first row) is clicked the entire table should get sorted
based on that column(either ascending or descending).
Note:Below Code is tested with any excel input file and supporting settings for activex in internet options in IE9.
<HTML>
<HEAD>
<TITLE>Test</TITLE> <script type="text/javascript" src="../jquery-latest.js"></script>
<script type="text/javascript">
</script>
<STYLE TYPE="text/css">body div * { font-family: Verdana; font-weight: normal; font-size: 10px; } body { background-color: #FFEEFF; } .tableContainer table { border: 0px solid #000000; } .tblHeader { font-weight: bold; text-align: center; background-color: #FFAAEE; color: black; } .oddRow, .evenRow { vertical-align: top; } .tblHeader td, .oddRow td, .evenRow td { border-left: 2px solid #FFFFFF; border-bottom: 0px solid #000000; border-top: 0px solid #000000;} .lastCol { border-right: 0px solid #000000; } .oddRow { background-color: #abcdef; } .evenRow { background-color: #f0f0f0; }</STYLE>
<script LANGUAGE="JavaScript">
function _ge(id) {
return document.getElementById(id);
}
function sortTable(){
var tbl = document.getElementById("tblExcel2Html").tBodies[0];
var store = [];
//alert(tbl.rows.length);
for(var i=0, len=tbl.rows.length; i<len; i++){
var row = tbl.rows[i];
//alert(row.cells[1].innerText);
var sortnr = parseFloat(row.cells[1].textContent || row.cells[1].innerText);
if(!isNaN(sortnr)){
alert(store.push([sortnr, row]));
//store.push([sortnr, row]);
}
}
store.sort(function(x,y){
//alert(x[0] - y[0]);
return x[0] - y[0];
});
//alert(store.length);
for(var i=0, len=store.length; i<len; i++){
alert(tbl.appendChild(store[i][1]));
//alert(tbl.appendChild(store[i][1]));
}
//alert(store);
store = null;
}
function convert2HTML() {
var ex;
try {
ex = new ActiveXObject("Excel.Application");
}
catch (e)
{
alert('Your browser does not support the Activex object.\nPlease switch to Internet Explorer.');
return false;
}
//alert(arraytext);
//var ef = ex.Workbooks.Open("D:\\JS_HTML5\\Vin\\Test.xlsx");
var ef = ex.Workbooks.Open("D:\\JS_HTML5\\docs\\filter4\\tests\\Test.xlsx");
var es = ef.Worksheets(1);
var colsCount = ef.Worksheets(1).UsedRange.Columns.Count;
//alert(colsCount);
var rowsCount = ef.Worksheets(1).UsedRange.Rows.Count;
//alert(rowsCount);
var rStart = parseInt(1,10);
var cStart = parseInt(1,10);
var cEnd = parseInt(colsCount,10);
var rEnd = parseInt(rowsCount,10);
var oc = _ge('tableContainer');
oc.innerHTML = '';
var tbl = document.createElement('TABLE');
tbl.id = 'tblExcel2Html';
tbl.border = '10';
tbl.cellPadding = '4';
tbl.cellSpacing = '0';
oc.appendChild(tbl);
var i,j,row,col,r,c;
for(i = rStart, r = 0; i <= rEnd; i++,r++) {
row = tbl.insertRow(r);
row.className = (i == rStart) ? 'tblHeader' : (i % 2 == 0) ? 'evenRow' : 'oddRow';
for(j = cStart, c = 0; j <= cEnd; j++,c++) {
col = row.insertCell(c);
col.className = (j == cEnd) ? 'lastCol' : '';
col.innerHTML = es.Cells(i,j).value || ' ';
}
}
ex.ActiveWorkbook.Close(true);
ex.Application.Quit();
ex = null;
sortTable();
}
</script>
</HEAD>
<BODY onload = "convert2HTML()">
<h2>Test</h2>
<hr><br>
<!-- <td colspan="6" align="CENTER"><INPUT TYPE="button" VALUE="Convert to HTML" ONCLICK="convert2HTML()"></td> -->
<div id="tableContainer"></div>
<div id="tblExcel2Html"></div>
<footer>
<br>
<center> ©Initial Draft V0.1 </center>
</footer>
<a href="Home.html" >Home</a>
</BODY>
Basically i want to convert excel to html with sorting and filtering support.
Thanks in Advance
Vinoth.S
The creation of the object by calling
ex = new ActiveXObject("Excel.Application");
works only in windows systems with Excel installed. I suggest you to use jqgrid as javascript data-viewer and a php library like phpexcel that parse the excel and return raw data.