How to edit image uploaded on the some box? - javascript

HTM like this :
<input type='file' multiple id="upload-file"/>
<?php
for($i=0;$i<5; $i++) {
?>
<div class="img-container" id="box<?php echo $i ?>">
<button style="display: none;" type="submit" class="btn btn-primary show-button">
<i class="glyphicon glyphicon-edit"></i>
</button>
</div>
<?php
}
?>
Javascript like this :
$(function () {
$(":file").change(function () {
var noOfFiles = this.files.length;
for(var i=0; i < noOfFiles; i++) {
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(this.files[i]);
}
});
});
function imageIsLoaded(e) {
var imgTmpl = '<img height="142" width="162" src='+e.target.result+'>';
var IsImgAdded=false;
$('.img-container').each(function(){
if($(this).find('img').length==0 && IsImgAdded==false){
$(this).append(imgTmpl);
IsImgAdded=true;
$(this).find('.show-button').show();
}
});
};
$(".show-button").click(function(){
$("#upload-file").click();
});
Demo and full code like this : http://phpfiddle.org/main/code/1g8t-h5kn
I try like that. But it does not fit
Should when I edit image on the box 2, it will change image on the box 2. Not box 3
How can I solve this issue?

You need to create a var to set the actual edited container than after the upload launch the function, check if the variable has a value different than null and append the img in the right place.
WORKING FIDDLE HERE: https://codepen.io/VLK_STUDIO/pen/wdQPRL
$(function() {
$(":file").change(function() {
var noOfFiles = this.files.length;
for (var i = 0; i < noOfFiles; i++) {
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(this.files[i]);
}
});
});
var actualEdited = "";
function imageIsLoaded(e) {
var imgTmpl = '<img height="142" width="162" src=' + e.target.result + ">";
var IsImgAdded = false;
$(".img-container").each(function() {
if ($(this).find("img").length == 0 && IsImgAdded == false) {
if (actualEdited == "") {
$(this).append(imgTmpl);
$(this).find(".show-button").show();
IsImgAdded = true;
return false;
} else {
$(actualEdited).find("img").remove();
$(actualEdited).append(imgTmpl);
$(actualEdited).find(".show-button").show();
actualEdited = "";
return false;
}
} else {
if (actualEdited != "") {
$(actualEdited).find("img").remove();
$(actualEdited).append(imgTmpl);
$(actualEdited).find(".show-button").show();
actualEdited = "";
return false;
}
}
});
}
$(".show-button").click(function() {
$("#upload-file").click();
actualEdited = $(this).parent();
});
.img-container {
width: 100px;
border: 1px solid black;
height: 100px;
margin: 20px;
display: inline-block;
}
img {
display: block;
width: 100%;
height: auto;
}
.show-button {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="upload-file" type="file">
<div class="img-container">
<div class="show-button">click
</div>
</div>
<div class="img-container">
<div class="show-button">click
</div>
</div>
<div class="img-container">
<div class="show-button">click
</div>
</div>
<div class="img-container">
<div class="show-button">click
</div>
</div>

$(function () {
$(":file").change(function () {
var noOfFiles = this.files.length;
for(var i=0; i < noOfFiles; i++) {
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(this.files[i]);
}
});
});
function imageIsLoaded(e) {
var imgTmpl = '<img height="142" width="162" src='+e.target.result+'>';
var IsImgAdded=false;
$('.img-container').each(function(){
if($(this).find('img').length==0 && IsImgAdded==false){
$(this).append(imgTmpl);
IsImgAdded=true;
$(this).find('.show-button').show();
} else {
if ($(this).id == sessionStorage.getItem('blockid')){
$(this).append(imgTmpl);
IsImgAdded=true;
$(this).find('.show-button').show();
}
}
});
};
$(".show-button").click(function(){
sessionStorage.setItem('blockid', $(this).id);
$("#upload-file").click();
});
You're forggeting to identify the edited blocks. I warn you this is not the best approach, but the faster one. Bind one object action to another is confusing and poor practice, i advise you to use better js functions/closures to get what you want with proper form.

Related

Create a file with the same name as the folder where a file was uploaded

I have an HTML form within a Web App, created with GAS.
This HTML form was created from this file upload script here:
drive-multi-upload
This is the HTML form:
The point is that I needed the files to be uploaded in folders that follow the following pattern:
The first number refers to the model selected on the form, the second number refers to the slot used.
Therefore, it was necessary to create a function to identify the input chosen in the Model and, according to this input, check which is the first empty folder, then take the ID of that folder and pass it to the client side to upload the file inside it.
With the help of some members of the community, some adaptations were made and the final function was this:
/** Modified version of script written by Tanaike */
function createOrGetFolder(folderName, parentFolderId) {
try {
var parentFolder = DriveApp.getFolderById(parentFolderId), folder;
if (parentFolder) {
var foldersIter = parentFolder.getFoldersByName("Video");
if (foldersIter.hasNext()) {
var videoFolder = foldersIter.next();
var nextFolderName = folderName + "-01";
while (!folder) {
video_folder = videoFolder.getFoldersByName(nextFolderName);
if (video_folder.hasNext()) {
folder = video_folder.next();
var files = folder.getFiles();
if (files.hasNext()) {
var [a, b] = nextFolderName.split("-");
nextFolderName = `${a}-${String(Number(b) + 1).padStart(2, "0")}`;
folder = null;
}
} else {
folder = videoFolder.createFolder(nextFolderName);
}
}
} else {
folder = parentFolder.createFolder("Video");
folder = folder.createFolder(folderName);
}
} else {
throw new Error("Parent Folder with id: " + parentFolderId + " not found");
}
return folder.getId();
} catch (error) {
return error;
}
}
It works perfectly, the point is that this form also has a function that generates a .csv file when the form is submitted, the function is this one:
.gs file:
const saveDataAsCSV = (data, folderId) => DriveApp.getFolderById(folderId).createFile("Sample.csv", data);
HTML file:
var name = $('#name01').val();
var description = $('#description').val();
var model = $('#Model').val();
upload_folder = model;
var color = $('#Color').val();
var form_values = [name, description, model, color];
var data = form_values.join(",");
google.script.run.saveDataAsCSV(data, uploadParentFolderId);
My goal is to make the .csv file be generated with the same name as the folder where the file was uploaded, that is, if the file is uploaded in folder 01-01, the file name has to be 01-01.csv, if the file is uploaded in the 02-02 folder, the file name has to be 02-02.csv, and so on.
How can I achieve this?
The complete script code can be viewed here:
.gs file:
function doGet(e) {
return HtmlService.createTemplateFromFile('forms0101.html').evaluate();
}
function getOAuthToken() {
return ScriptApp.getOAuthToken();
}
function getParent(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var id = ss.getId();
var parent = DriveApp.getFileById(id).getParents().next().getId();
return parent
}
function getLimitFolder(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pastapai = DriveApp.getFileById(ss.getId()).getParents();
var limitfolder = pastapai.next().getFoldersByName("_").next().getId();
return limitfolder;
}
function getFilesLimit(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pastapai = DriveApp.getFileById(ss.getId()).getParents();
var files = [];
Logger.log(pastapai);
//var limitfolder = pastapai.next().getFoldersByName("_").next().getId();
var limitfolder = pastapai.next().getFoldersByName("_").next().getFiles();
while(limitfolder.hasNext()){
var file = limitfolder.next();
files.push([file.getId()]);
}
console.log(files.length);
return files.length;
}
//function testenumeroarquivos(){
//console.log(checkForFiles()); // When you use this line, you can see the filename of the files.
//}
/**
* creates a folder under a parent folder, and returns it's id. If the folder already exists
* then it is not created and it simply returns the id of the existing one
*/
function createOrGetFolder(folderName, parentFolderId) {
try {
var parentFolder = DriveApp.getFolderById(parentFolderId), folder;
if (parentFolder) {
var foldersIter = parentFolder.getFoldersByName("Video");
if (foldersIter.hasNext()) {
var videoFolder = foldersIter.next();
var nextFolderName = folderName + "-01";
while (!folder) {
video_folder = videoFolder.getFoldersByName(nextFolderName);
if (video_folder.hasNext()) {
folder = video_folder.next();
var files = folder.getFiles();
if (files.hasNext()) {
var [a, b] = nextFolderName.split("-");
nextFolderName = `${a}-${String(Number(b) + 1).padStart(2, "0")}`;
folder = null;
}
} else {
folder = videoFolder.createFolder(nextFolderName);
}
}
} else {
folder = parentFolder.createFolder("Video");
folder = folder.createFolder(folderName);
}
} else {
throw new Error("Parent Folder with id: " + parentFolderId + " not found");
}
console.log("Test" + nextFolderName)
return folder.getId();
} catch (error) {
return error;
}
}
const saveDataAsCSV = (data, folderId) => {
const folder = DriveApp.getFolderById(folderId);
folder.createFile(`${nextFolderName.getName()}.csv`, data);
}
const increaseRequest = (data, folderId) => DriveApp.getFolderById(folderId).createFile("IncreaseRequest.csv", data);
// NOTE: always make sure we use DriveApp, even if it's in a comment, for google to import those
// libraries and allow the rest of the app to work. see https://github.com/tanaikech/Resumable_Upload_For_WebApps
HTML file:
<!DOCTYPE html>
<html>
<head>
<base target="_blank">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Drive Multi Large File Upload</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<style>
#import url('https://fonts.googleapis.com/css2?family=Rubik:wght#400;600;700&display=swap');
.disclaimer{
width: 480px;
color: #646464;
margin: 20px auto;
padding:0 16px;
text-align:center;
font:400 12px Rubik,sans-serif;
}
h5.center-align.teal-text {
font:700 26px Rubik,sans-serif;
color: #00F498!important;
}
.row {
font:600 14px Rubik,sans-serif;
}
.btn {
background-color: black;
}
.btn:hover {
background-color: #00F498;
}
body {
margin-top: -40px;
}
#progress {
color: #00000;
}
.disclaimer a{
color: #00BCAA;
}
#credit{
display:none
}
.btnOpenModal {
font-size: x-large;
padding: 10px;
border: none;
border-radius: 5px;
background-color: blueviolet;
color: white;
cursor: pointer;
}
hr {
border: 0px;
border-top: 1px solid lightgray;
}
.modal-container {
width: 100vw;
position: fixed;
top: 30px;
display: none;
z-index: 999;
justify-content: center;
}
.modal {
display: flex;
flex-direction: column;
padding: 30px;
background-color: white;
border-radius: 10px;
width: 50%;
}
.active {
display: flex;
}
.active .modal {
animation: modal .4s;
}
#keyframes modal {
from {
opacity: 0;
transform: translate3d(0, -60px, 0);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
.btns {
display: flex;
justify-content: space-between;
margin-top: 10px;
}
.btns button {
font-size: medium;
padding: 10px;
border: none;
border-radius: 5px;
color: white;
cursor: pointer;
}
.btnOK {
background-color: blue!important;
}
.btnClose {
background-color: brown!important;
}
</style>
</head>
<body>
<form class="main" id="form" novalidate="novalidate" style="max-width: 480px;margin: 40px auto;">
<div id="forminner">
<div class="modal-container">
<div class="modal">
<h2>Info</h2>
<hr />
<span>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text
ever since the 1500s, when an unknown printer took a galley of
type and scrambled it to make a type specimen book.
</span>
<hr />
<div class="btns">
<button class="btnOK" onclick="increaseRequest(); closeModal();">OK</button>
<button class="btnClose" onclick="closeModal()">Close</button>
</div>
</div>
</div>
<h5 class="center-align teal-text" style="margin-bottom: -10px; font-size: 20px; font-family: Rubik; ">YOUR NAME</h5>
<div class="row">
<div class="input-field col s12">
<input id="name01" type="text" name="Name" class="validate" required="required" aria-required="true">
<label for="name" class="">Name</label>
</div>
</div>
<h5 class="center-align teal-text" style="margin-bottom: -10px; font-size: 20px; font-family: Rubik; ">SOME DESCRIPTION</h5>
<div class="row">
<div class="input-field col s12">
<input id="description" type="text" name="Description" class="validate" required="required" aria-required="true">
<label for="name">Description</label>
</div>
</div>
<div class="row">
<div class="col-8 col-md-4">
<h6>Model</h6>
<select class="custom-select" id="Model">
<option selected="">Choose...</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
</select>
<h6>Color</h6>
<select class="custom-select" id="Color">
<option selected="">Choose...</option>
<option value="Red">Red</option>
<option value="Green">Green</option>
</select>
</div>
</div>
<div class="row">
<div class="col s12">
<h5 class="center-align teal-text">Upload the Video File</h5>
</div>
</div>
<div class="row">
<div class="file-field input-field col s12">
<div id="input-btn" class="btn">
<span>File</span>
<input id="files" type="file" single="">
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Select the file">
</div>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<button id="submit-btn" class="waves-effect waves-light btn submit-btn" type="submit" onclick="submitForm(); return false;">Submit</button>
</div>
</div>
<div class="row">
<div class="input-field col s12 hide" id="update">
<hr>
<p>
Por favor, aguarde enquanto seu arquivo está sendo carregado.<br><span style="color: #00000;"><b>Não feche ou atualize a janela durante o upload.</b></span>
</p>
</div>
</div>
<div class="row">
<div class="input-field col s12" id="progress">
</div>
</div>
</div>
</div>
<div id="success" style="display:none">
<h5 class="center-align teal-text">Tudo certo!</h5>
<p>Se você já preencheu todos os campos é só fechar essa janela e clicar em enviar!</p>
<button id="fechar" class="waves-effect waves-light btn submit-btn" style ="transform: translateX(160%);" type="button" onclick="google.script.host.close()">Fechar</button>
</div>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>
<script src="https://gumroad.com/js/gumroad.js"></script>
<script>
var upload_folder = "01";
const chunkSize = 5242880;
const uploadParentFolderId = <?=getParent()?>; // creates a folder inside of this folder
const limitfolder = <?=getLimitFolder()?>;
const fileslimit = <?=getFilesLimit()?>;
const modal = document.querySelector('.modal-container');
var name = $('#name01').val();
var description = $('#description').val();
var model = $('#Model').val();
upload_folder = model;
var color = $('#Color').val();
var form_values = [name, description, model, color];
form_values = form_values.map(r => r.replaceAll(",", "#")); // Essa linha substitui todas as "," por "#" antes de gerar o .csv
var data = form_values.join(",");
function submitForm() {
var name = $('#name01').val();
var description = $('#description').val();
var model = $('#Model').val();
upload_folder = model;
var color = $('#Color').val();
var form_values = [name, description, model, color];
form_values = form_values.map(r => r.replaceAll(",", "#")); // Essa linha substitui todas as "," por "#" antes de gerar o .csv
var data = form_values.join(",");
// Added the below script.
if ($('#submit-btn.disabled')[0]) return; // short circuit
var name = upload_folder
var files = [...$('#files')[0].files]; // convert from FileList to array
if (files.length === 0) {
showError("Por favor, selecione um arquivo");
return;
}
google.script.run.saveDataAsCSV(data, uploadParentFolderId);
google.script.run.saveDataAsCSV(data, limitfolder);
disableForm(); // prevent re submission
// the map and reduce are here to ensure that only one file is uploaded at a time. This allows
// the promises to be run sequentially
files.map(file => uploadFilePromiseFactory(file))
.reduce((promiseChain, currentTask) => {
return promiseChain.then(currentTask);
}, Promise.resolve([])).then( () => {
console.log("Completed all files upload");
showSuccess();
});
}
function checkforfiles() {
if (fileslimit <= 2) {
submitForm();
}
if (fileslimit == 3) {
openModal();
}
if (fileslimit >= 4) {
showError("erro");
return;
}
}
function openModal() {
modal.classList.add('active');
}
function closeModal() {
modal.classList.remove('active');
}
function increaseRequest() {
google.script.run.increaseRequest(data, limitfolder);
}
function disableForm() {
$('#submit-btn').addClass('disabled');
$('#input-btn').addClass('disabled');
$('#update').removeClass('hide');
$('#update').removeClass('hide');
}
function closer(){
google.script.host.close();
}
function uploadFilePromiseFactory(file) {
return () => {
console.log("Processing: ", file.name);
return new Promise((resolve, reject) => {
showProgressMessage("Seu arquivo está sendo carregado");
var fr = new FileReader();
fr.fileName = file.name;
fr.fileSize = file.size;
fr.fileType = file.type;
// not sure of a better way of passing the promise functions down
fr.resolve = () => resolve();
fr.reject = (error) => reject(error);
fr.onload = onFileReaderLoad;
fr.readAsArrayBuffer(file);
});
};
}
/**
* Gets called once the browser has loaded a file. The main logic that creates a folder
* and initiates the file upload resides here
*/
function onFileReaderLoad(onLoadEvent) {
var fr = this;
var newFolderName = upload_folder
createOrGetFolder(newFolderName, uploadParentFolderId).then(newFolderId => {
console.log("Found or created guest folder with id: ", newFolderId);
uploadFileToDriveFolder.call(fr, newFolderId).then(() => {
fr.resolve();
}, (error) => {
fr.reject(error);
});
},
(error) => {
if (error) {
showError(error.toString());
}
console.log("onFileReaderLoad Error2: ", error);
});
}
/**
* call to the DriveApp api. Wrapped in a promise in case I want to address timing issues between a
* createFolder and findFolderById
*/
function createOrGetFolder(folderName, parentFolderId) {
return new Promise((resolve, reject) => {
google.script.run.withSuccessHandler(response => {
console.log("createOrGetFolder response: ", response);
if (response && response.length) {
resolve(response);
}
reject(response);
}).createOrGetFolder(folderName, parentFolderId);
});
}
/**
* Helper functions modified from:
* https://github.com/tanaikech/Resumable_Upload_For_WebApps
*/
function uploadFileToDriveFolder(parentFolderId) {
var fr = this;
return new Promise((resolve, reject) => {
var fileName = fr.fileName;
var fileSize = fr.fileSize;
var fileType = fr.fileType;
console.log({fileName: fileName, fileSize: fileSize, fileType: fileType});
var buf = fr.result;
var chunkpot = getChunkpot(chunkSize, fileSize);
var uint8Array = new Uint8Array(buf);
var chunks = chunkpot.chunks.map(function(e) {
return {
data: uint8Array.slice(e.startByte, e.endByte + 1),
length: e.numByte,
range: "bytes " + e.startByte + "-" + e.endByte + "/" + chunkpot.total,
};
});
google.script.run.withSuccessHandler(oAuthToken => {
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable");
xhr.setRequestHeader('Authorization', "Bearer " + oAuthToken);
xhr.setRequestHeader('Content-Type', "application/json");
xhr.send(JSON.stringify({
mimeType: fileType,
name: fileName,
parents: [parentFolderId]
}));
xhr.onload = () => {
doUpload(fileName, {
location: xhr.getResponseHeader("location"),
chunks: chunks,
}).then(success => {
resolve(success);
console.log("Successfully uploaded: ", fileName);
},
error => {
reject(error);
});
};
xhr.onerror = () => {
console.log("ERROR: ", xhr.response);
reject(xhr.response);
};
}).getOAuthToken();
});
}
function showSuccess() {
$('#forminner').hide();
$('#success').show();
$('#fechar').show();
}
function showError(e) {
$('#progress').addClass('red-text').html(e);
}
function showMessage(e) {
$('#update').html(e);
}
function showProgressMessage(e) {
$('#progress').removeClass('red-text').html(e);
}
/**
* Helper functions modified from:
* https://github.com/tanaikech/Resumable_Upload_For_WebApps
*/
function doUpload(fileName, e) {
return new Promise((resolve, reject) => {
showProgressMessage("Carregando: <span style='color: #00F498 ;'>" + "0%</span>");
var chunks = e.chunks;
var location = e.location;
var cnt = 0;
var end = chunks.length;
var temp = function callback(cnt) {
var e = chunks[cnt];
var xhr = new XMLHttpRequest();
xhr.open("PUT", location, true);
console.log("content range: ", e.range);
xhr.setRequestHeader('Content-Range', e.range);
xhr.send(e.data);
xhr.onloadend = function() {
var status = xhr.status;
cnt += 1;
console.log("Uploading: " + status + " (" + cnt + " / " + end + ")");
showProgressMessage("Carregando: <span style='color: #00F498 ;'>"
+ Math.floor(100 * cnt / end) + "%</span>" );
if (status == 308) {
callback(cnt);
} else if (status == 200) {
$("#progress").text("Done.");
resolve();
} else {
$("#progress").text("Error: " + xhr.response);
reject();
}
};
}(cnt);
});
}
/**
* Helper functions modified from:
* https://github.com/tanaikech/Resumable_Upload_For_WebApps
*/
function getChunkpot(chunkSize, fileSize) {
var chunkPot = {};
chunkPot.total = fileSize;
chunkPot.chunks = [];
if (fileSize > chunkSize) {
var numE = chunkSize;
var endS = function(f, n) {
var c = f % n;
if (c == 0) {
return 0;
} else {
return c;
}
}(fileSize, numE);
var repeat = Math.floor(fileSize / numE);
for (var i = 0; i <= repeat; i++) {
var startAddress = i * numE;
var c = {};
c.startByte = startAddress;
if (i < repeat) {
c.endByte = startAddress + numE - 1;
c.numByte = numE;
chunkPot.chunks.push(c);
} else if (i == repeat && endS > 0) {
c.endByte = startAddress + endS - 1;
c.numByte = endS;
chunkPot.chunks.push(c);
}
}
} else {
var chunk = {
startByte: 0,
endByte: fileSize - 1,
numByte: fileSize,
};
chunkPot.chunks.push(chunk);
}
return chunkPot;
}
</script>
</body>
</html>
It can also be viewed by accessing this worksheet
Although I'm not sure whether I could correctly understand your actual expected result, please test the following modification.
Google Apps Script side:
Please modify saveDataAsCSV of Google Apps Script as follows.
const saveDataAsCSV = (data, folderId1, folderId2 = null) => {
if (folderId2) {
DriveApp.getFolderById(folderId1).createFile(`${DriveApp.getFolderById(folderId2).getName()}.csv`, data);
} else {
DriveApp.getFolderById(folderId1).createFile("sample.csv", data);
}
}
Javascript side:
Please remove google.script.run.saveDataAsCSV(data, uploadParentFolderId); in the function submitForm.
And, please modify onFileReaderLoad of Javascript as follows.
function onFileReaderLoad(onLoadEvent) {
var fr = this;
var newFolderName = upload_folder
createOrGetFolder(newFolderName, uploadParentFolderId).then(newFolderId => {
google.script.run.saveDataAsCSV(data, uploadParentFolderId, newFolderId);
console.log("Found or created guest folder with id: ", newFolderId);
uploadFileToDriveFolder.call(fr, newFolderId).then(() => {
fr.resolve();
}, (error) => {
fr.reject(error);
});
},
(error) => {
if (error) {
showError(error.toString());
}
console.log("onFileReaderLoad Error2: ", error);
});
}
By this modification, I think that a CSV file like 01-01.csv is created to uploadParentFolderId folder.

JSPrintManager isn't detecting my installed scanner

I am trying to scan a document with the click of a button in javascript. This is my code:
HTML:
<div class="mb-3" style="width: 50%; margin: 0 auto; border: 2px solid white;">
<label for="scannerName">Select preferred scanner :</label><br>
<select name="scannerName" id="scannerName" style="text-align: center; width: 50%;"></select><br><br>
<label for="pixelMode">Select pixel mode :</label><br>
<select name="pixelMode" id="pixelMode" style="text-align: center; width: 50%;"></select><br><br>
<label for="resolution">Select resolution :</label><br>
<select name="resolution" id="resolution" style="text-align: center; width: 50%;"></select><br><br>
<label for="imageFormat">Select image format :</label><br>
<select name="imageFormat" id="imageFormat" style="text-align: center; width: 50%;"></select><br><br>
</div>
<div class="d-grid gap-*" style="position: absolute; top: 100%; left: 46%;">
<button type="button" class="btn btn-primary btn-block" onclick="doScanning()">Upload</button>
</div>
JS:
var scannerDevices = null;
var _this = this;
//JSPrintManager WebSocket settings
JSPM.JSPrintManager.auto_reconnect = true;
JSPM.JSPrintManager.start();
JSPM.JSPrintManager.WS.onStatusChanged = function () {
if (jspmWSStatus()) {
//get scanners
JSPM.JSPrintManager.getScanners().then(function (scannersList) {
scannerDevices = scannersList;
var options = '';
if(scannerDevices.length>0){
for (var i = 0; i < scannerDevices.length; i++) {
options += '<option>' + scannerDevices[i] + '</option>';
}
}
else{
var options_new='';
options_new += '<option>' + "Not applicable" + '</option>';
$('#pixelMode').html(options_new);
$('#resolution').html(options_new);
$('#imageFormat').html(options_new);
options += '<option>' + "No scanners found installed" + '</option>';
}
$('#scannerName').html(options);
});
}
};
//Check JSPM WebSocket status
function jspmWSStatus() {
if (JSPM.JSPrintManager.websocket_status == JSPM.WSStatus.Open)
return true;
else if (JSPM.JSPrintManager.websocket_status == JSPM.WSStatus.Closed) {
console.warn('JSPrintManager (JSPM) is not installed or not running! Download JSPM Client App from https://neodynamic.com/downloads/jspm');
return false;
}
else if (JSPM.JSPrintManager.websocket_status == JSPM.WSStatus.Blocked) {
alert('JSPM has blocked this website!');
return false;
}
}
//Do scanning...
function doScanning() {
if (jspmWSStatus()) {
//create ClientScanJob
var csj = new JSPM.ClientScanJob();
//scanning settings
csj.scannerName = $('#scannerName').val();
csj.pixelMode = JSPM.PixelMode[$('#pixelMode').val()];
csj.resolution = parseInt($('#resolution').val());
csj.imageFormat = JSPM.ScannerImageFormatOutput[$('#imageFormat').val()];
let _this = this;
//get output image
csj.onUpdate = (data, last) => {
if (!(data instanceof Blob)) {
console.info(data);
return;
}
var imgBlob = new Blob([data]);
if (imgBlob.size == 0) return;
var data_type = 'image/jpg';
if (csj.imageFormat == JSPM.ScannerImageFormatOutput.PNG) data_type = 'image/png';
//create html image obj from scan output
var img = URL.createObjectURL(imgBlob, { type: data_type });
//scale original image to be screen size friendly
/*var imgScale = { width: Math.round(96.0 / csj.resolution * 100.0) + "%", height: 'auto' };
$('#scanOutput').css(imgScale);
$('#scanOutput').attr("src", img);*/
}
csj.onError = function (data, is_critical) {
console.error(data);
};
//Send scan job to scanner!
csj.sendToClient().then(data => console.info(data));
}
}
I've followed each and every step mentioned in this site:
https://www.neodynamic.com/articles/How-to-scan-documents-images-from-Javascript/
But I keep getting the message "No scanners are installed" in my scannerName select tag. In fact, when I go to the JS console, I get this message:
JSPrintManager License: Objectresult: "Invalid License"[[Prototype]]:
Object...
My scanner is a Canon canoscan lide 25. It's TWAIN compatible so it should be detected. How do I fix this issue? Do I have to buy the license?

How to Preview Multiple Selected Image [duplicate]

This question already has answers here:
Preview images before upload
(10 answers)
Closed 1 year ago.
I have a code for single Image preview, when we select a file from input field we can see the selected image in preview, but how can i do the same for multiple images preview.
here is my code for single image preview.
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#preview-image')
.attr('src', e.target.result)
.width(150)
.height(200);
};
reader.readAsDataURL(input.files[0]);
}
}
<img id="preview-image" class="img-prev rounded" src="#" alt="Upload" onerror=this.src="../assets/images/myfolder/no_image.png" />
<input type="file" name="featured_image" id="customFile" onchange="readURL(this);" required>
Jsfiddle : My Fiddle
You can Check all the things in this answer, and if not cleared, then modify as your need .
$(document).ready(function() {
/*multiple image preview first input*/
$("#files").on("change", handleFileSelect);
selDiv = $("#selectedFilesD");
$("#myForm").on("submit", handleForm);
$("body").on("click", ".selFile", removeFile);
/*end image preview */
/* Multiple image preview second input*/
$("#mobile").on("change", handleFileSelect);
selDivM = $("#selectFilesM");
$("#myForm").on("submit", handleForm);
$("body").on("click", ".selFile", removeFile);
console.log($("#selectFilesM").length);
});
/*multiple image preview*/
var selDiv = "";
// var selDivM="";
var storedFiles = [];
function handleFileSelect(e) {
var files = e.target.files;
var filesArr = Array.prototype.slice.call(files);
var device = $(e.target).data("device");
filesArr.forEach(function(f) {
if (!f.type.match("image.*")) {
return;
}
storedFiles.push(f);
var reader = new FileReader();
reader.onload = function(e) {
var html = "<div><img src=\"" + e.target.result + "\" data-file='" + f.name + "' class='selFile' title='Click to remove'>" + f.name + "<br clear=\"left\"/></div>";
if (device == "mobile") {
$("#selectedFilesM").append(html);
} else {
$("#selectedFilesD").append(html);
}
}
reader.readAsDataURL(f);
});
}
function handleForm(e) {
e.preventDefault();
var data = new FormData();
for (var i = 0, len = storedFiles.length; i < len; i++) {
data.append('files', storedFiles[i]);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', 'handler.cfm', true);
xhr.onload = function(e) {
if (this.status == 200) {
console.log(e.currentTarget.responseText);
alert(e.currentTarget.responseText + ' items uploaded.');
}
}
xhr.send(data);
}
function removeFile(e) {
var file = $(this).data("file");
for (var i = 0; i < storedFiles.length; i++) {
if (storedFiles[i].name === file) {
storedFiles.splice(i, 1);
break;
}
}
$(this).parent().remove();
}
#selectedFilesD img,
#selectFilesM img {
max-width: 200px;
max-height: 200px;
float: left;
margin-bottom: 10px;
}
#userActions input {
width: auto;
margin: auto;
}
#selectFiles img,
#selectedFilesM img {
max-width: 200px;
max-height: 200px;
float: left;
margin-bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="index.php" id="myForm" name="myForm" enctype="multipart/form-data" method="post" accept-charset="utf-8">
desktop:
<input data-device="desktop" type="file" id="files" name="files" multiple>
<div id="selectedFilesD"></div>
<br/>
mobile:
<input data-device="mobile" type="file" id="mobile" name="mobile" multiple>
<br/>
<div id="selectedFilesM"></div>
<button type="submit">Submit</button>
</form>

javascript replace background image in drawingBoard.js

I need to change the background image inside of canvas with the leimi drawingboard.js, but I have no idea how to make it.
I need to show different images so that the user can choose between them with which he is going to work
Here is my form:
<div id="container">
<div class="example" data-example="1"> // THIS DIV IS THE CANVAS
<div class="board" id="default-board"></div> //THIS ID HAVE A IMAGE AND THE CONTROLLERS
</div>
<form class="drawing-form" method="post" name="diagram" id="diagram" enctype="multipart/form-data">
<div id="board"></div>
<input type="hidden" name="image" value="">
<input type="hidden" name="idPac" value="<?php echo $id_paciente; ?>" />
<input type="hidden" name="idDoc" value="<?php echo $user_id; ?>" />
<br><hr>
<button class="btn btn-info" id="btnUpload"><?php $translate->__('Save Diagram'); ?></button>
</form>
<div id="ldiag" style="display:none;"><img src="images/loading4.gif" /></div>
</div>
And the javascript code is:
<script src="js/drawingboard.min.js"></script>
<script data-example="1">
var defaultBoard = new DrawingBoard.Board("default-board", {
background: "imagenes/canvas/cara.jpg", //THIS IS THE IMAGE I NEED TO CHANGE FOR OTHERS IF NEEDED, EXAMPLE /pie.png, /cuerpo.png
droppable: true,
webStorage: false,
enlargeYourContainer: true,
addToBoard: true,
stretchImg: false
});
defaultBoard.addControl("Download");
$(".drawing-form").on("submit", function(e) {
var img = defaultBoard.getImg();
var imgInput = (defaultBoard.blankCanvas == img) ? "" : img;
$(this).find("input[name=image]").val( imgInput );
defaultBoard.clearWebStorage();
});
$(function() {
$("#file-input").change(function(e) {
var file = e.target.files[0],
imageType = /image.*/;
if (!file.type.match(imageType))
return;
var reader = new FileReader();
reader.onload = fileOnload;
reader.readAsDataURL(file);
});
function fileOnload(e) {
var $img = $("<img>", { src: e.target.result });
var canvas = $("#default-board")[0];
var context = canvas.getContext("2d");
$img.load(function() {
context.drawImage(this, 0, 0);
});
}
});
</script>
<script src="js/yepnope.js"></script>
<script>
var iHasRangeInput = function() {
var inputElem = document.createElement("input"),
smile = ":)",
docElement = document.documentElement,
inputElemType = "range",
available;
inputElem.setAttribute("type", inputElemType);
available = inputElem.type !== "text";
inputElem.value = smile;
inputElem.style.cssText = "position:absolute;visibility:hidden;";
if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {
docElement.appendChild(inputElem);
defaultView = document.defaultView;
available = defaultView.getComputedStyle &&
defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== "textfield" &&
(inputElem.offsetHeight !== 0);
docElement.removeChild(inputElem);
}
return !!available;
};
yepnope({
test : iHasRangeInput(),
nope : ["css/fd-slider.min.css", "js/fd-slider.min.js"],
callback: function(id, testResult) {
if("fdSlider" in window && typeof (fdSlider.onDomReady) != "undefined") {
try { fdSlider.onDomReady(); } catch(err) {}
}
}
});
</script>

Hiding/Showing Div Elements

This should cycle through the <div> tags, but it isn't even showing the first one. It should show a "0", then 50ms later, show "1", then "2", and then "3". I get nothing.
Here's the HTML:
<div class="header" id="animation">
<div id="aniObj0" style="display: none;" onLoad="runAnimation();">0</div>
<div id="aniObj1" style="display: none;">1</div>
<div id="aniObj2" style="display: none;">2</div>
<div id="aniObj3" style="display: none;">3</div>
</div>
The JavaScript:
var aniNum = 0;
var animationDelay = 50;
var frameDelay = 50;
function runAnimation()
{
Console.log("runningAnimation");
var prevObj = document.getElementById('aniObj' + (aniNum - 1));
var aniObj = document.getElementById('aniObj' + aniNum);
if(aniObj != null){
if(prevObj != null){
aniObj.style.display = 'none;';
}
aniObj.style.display = 'block;';
aniNum++;
if(aniNum == 0){
setTimeout("runAnimation();", animationDelay);
}else{
setTimeout("runAnimation();", frameDelay);
}
}else{
aniNum = 0;
newAnimation();
}
}
You're very close. See code below (and comments in code).
HTML:
<div class="header" id="animation">
<!-- Removed onload="runAnimation()" - onload doesn't exist for a div -->
<div id="aniObj0" style="display: none;">0</div>
<div id="aniObj1" style="display: none;">1</div>
<div id="aniObj2" style="display: none;">2</div>
<div id="aniObj3" style="display: none;">3</div>
</div>
JavaScript:
var aniNum = 0;
var animationDelay = 500; //Changed to 500ms to you could see better
var frameDelay = 500; //Changed to 500ms to you could see better
function runAnimation()
{
var prevObj = document.getElementById('aniObj' + (aniNum - 1));
var aniObj = document.getElementById('aniObj' + aniNum);
if (aniObj != null) {
if (prevObj != null) {
aniObj.style.display = 'none;';
}
aniObj.style.display = '';
aniNum++;
if (aniNum == 0) {
//Changed setTimeout("runAnimation()", animationDelay); to
//setTimeout(runAnimation, animationDelay);
setTimeout(runAnimation, animationDelay);
} else {
setTimeout(runAnimation, frameDelay);
}
} else {
aniNum = 0;
newAnimation();
}
}
//You need to place this in a valid event. onload event of the body maybe?
runAnimation();
Here's a working fiddle.

Categories