Attempting to load file(s) into CKEditor 4 textarea using input button and javascript. The files contain simple HTML code and have extensions .inc and .txt
What I have works, BUT ONLY after using browser back/forward buttons (which a student discovered by mistake). Using the input loads file from local drive, textarea goes blank but the loaded file only appears after using browser back/forward buttons?
Here is the HTML we are using:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://cdn.ckeditor.com/4.5.11/standard/ckeditor.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
</head>
<body>
<textarea name="editor1" id="editor1" rows="10" cols="80">
Placeholder text...
</textarea>
<script>
CKEDITOR.replace( 'editor1' );
</script>
<input name="file" type="file" id="files" class="form-control" value="">
<script type="text/javascript">
function readTextFile(file, callback, encoding) {
var reader = new FileReader();
reader.addEventListener('load', function (e) {
callback(this.result);
});
if (encoding) reader.readAsText(file, encoding);
else reader.readAsText(file);
}
function fileChosen(input, output) {
if (input.files && input.files[0]) {
readTextFile(
input.files[0],
function (str) {
output.value = str;
}
);
}
}
$('#files').on('change', function () {
var result = $("#files").text();
//added this below testing
fileChosen(this, document.getElementById('editor1'));
CKEDITOR.instances['editor1'].setData(result);
});
</script>
</body>
</html>
Also placed on JSFiddle
and W3schools
FYI: The browser back/forward mystery does not work on above two sites, only when I am using local or on a server.
After 3 days of trying to solve this in classroom, I come here asking for input. We have spent hours trying different methods found here and numerous sites.
Security is not an issue on input file restrictions, only using in classroom for training purposes/examples.
Anyone?
Okay, I managed to make it work.
In order to replace the text, you need to call the setData(str); method on the CKEDITOR instance, not over the DOM element. You also need to tell the editor to update ("redraw") its contents.
So:
fileChosen
function fileChosen(input, output) {
if ( input.files && input.files[0] ) {
readTextFile(
input.files[0],
function (str) {
output.setData(str); // We use the setData() method
output.updateElement(); // Then we tell the CKEditor instance to update itself
}
);
}
}
File input change
$('#files').on('change', function () {
var result = $("#files").text();
fileChosen(this, CKEDITOR.instances.editor1); // We pass the CKEDITOR instance, not the DOM element
});
I also made the changes like importing jQuery before the CKEDITOR javascript file.
Check the results in this fiddle
Related
I'm making a pdf reader website using the pdfjs library, and I wanted to make something similar to this website https://pdfviewer.softgateon.net/ which also uses pdfjs, though it's too old, but a nice thing about that website is that when I upload my pdf file, and after I'm done reading it, I close my browser and then tomorrow when I open that website, the pdf is already there at the last page that I was reading, I wanted to make the same capability for my website, but I have no idea how it's done, my website is only made by javascript, and I uploaded it on github pages, https://smh6.github.io/PDFWIZ/
And how it works is that, you upload your file and then, I remove the home page HTML and then I add the HTML of the reading mode page, can I get that feature in my website too? it doesn't have any backend, it's pure javascript
Is it related to the host that I'm using or it can be done with javascript?
As said in comment, upon adding the PDF, store it in a clientside database, (like localforage), which will persistently store the PDF as a blob in storage, which then on next visit you can load it back then render it again.
Online Example: https://localforage-pdf.glitch.me
Fundamental Example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title></title>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js"
integrity="sha512-+BMamP0e7wn39JGL8nKAZ3yAQT2dL5oaXWr4ZYlTGkKOaoXM/Yj7c4oy50Ngz5yoUutAG17flueD4F6QpTlPng=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
</head>
<body>
<div id="pdf"></div>
<input type="file" onchange="loadPDF(this)" accept="application/pdf" />
<button id="clearPDF">
Remove PDF
</button>
<script>
// clear and initial display
document.getElementById("clearPDF").onclick = function() {
localforage.removeItem("lastPDF");
document.getElementById("pdf").style.display = "none";
};
document.getElementById("pdf").style.display = "none";
// render the pdf object, if you use a diff lib implement it here
const renderPDF = function(src) {
const resource = (window.URL || window.webkitURL).createObjectURL(
new Blob([src], { type: "application/pdf" })
);
const object = document.createElement("object");
object.setAttribute("data", resource);
object.setAttribute("type", "application/pdf");
object.setAttribute("width", "500");
object.setAttribute("height", "678");
const iframe = document.createElement("iframe");
iframe.setAttribute("src", resource);
iframe.setAttribute("width", "500");
iframe.setAttribute("height", "678");
iframe.innerHTML = "<p>This browser does not support PDF!</p>";
object.append(iframe);
document.getElementById("pdf").replaceChildren(object);
// show it
document.getElementById("pdf").style.display = "block";
};
// load the PDF from file input, render then store in storage
const loadPDF = elm => {
const fr = new FileReader();
fr.onload = () => {
// render
renderPDF(fr.result);
// store
localforage.setItem("lastPDF", fr.result);
};
fr.readAsArrayBuffer(elm.files[0]);
};
// load and render last stored pdf
localforage.getItem("lastPDF", (err, value) => {
if (err || !value) return;
renderPDF(value);
});
</script>
</body>
</html>
You can use a cookie to save it.
Here should put what you use to open the file (path, param or whatever)
var lastFile = document.cookie = "lastFile=file"
Then every time the page is loaded, just check if that cookie exists, if so, open the file.
if(lastFile){
// open file
}
I develop an application that use a WebView in a WinForm using VB.NET.
The HTML code displayed in WebView is dynamically generated using VB.NET code.
wvSelect.Settings.IsScriptNotifyAllowed = True
wvSelect.Settings.IsJavaScriptEnabled = True
wvSelect.NavigateToString(sHtmlText)
where sHtmlText contains HTML tags and values.
This work well.
My HTML string is generated in a module
Public eHtml =
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script type="text/javascript">
// script (see code below)
</script>
<style type="text/css">
That's working, but Javascript code crash every time I write a < characters and color formatting of Javascript code is not optimal.
I know that I can use
<script type="text/javascript">
// <![CDATA[
// ]]>
</script>
That works for < and > characters but color formatting is very bad.
So, I have decided to move all my Javascript code in .JS file.
My HTML now, look like this
Public eHtml =
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="file:///D:/Documents/app.js"></script>
<style type="text/css">
Since, I have made this change, what is displayed in WebView is different from what I obtained before !
I suppose that .JS file is not called, not found or something else.
You must know that just before loading HTML string in WebView, I save it in an .HTML file.
When I double click on this .HTML file, Chrome load it and what is displayed is correct.
The problem happens only when HTML string is displayed on WebView.
As you can see, I don't have any problem importing JQuery script.
This problem is only for LOCAL scripts.
For information, my Javascript file contains following lines (I have removed some lines)
It is just to show that JQuery is used.
var eUnicode;
var iCounter = 0;
var eDraggable;
$(document).ready(function () {
$('.button').attr('draggable', 'True');
$('.digit').click(function (ev) { clickDigit(ev); });
$(".button").click(function (ev) {
clickButton(ev.target);
});
showFirstTab();
});
function clickButton(eButton) {
var sName = event.srcElement.innerText;
hideAllOnglets();
eButton.style.background = "orange";
showOnglet(sName);
}
function showTab(sName) {
var eOnglet = document.getElementById(sName);
eOnglet.style.display = "block";
}
Has somebody already encountered and resolved this problem ?
I have solved my problem using an embedded file (VB.Net Resource).
This technic is more safe because embedded file in not modifiable by user on installation location.
The Javascript.js file is located my application file/folder tree and has been defined as embedded resource in Build Action property as explained on How do I include a .jpg into a dll?
.
I don't use <script src='location'> tag because it don't work and also because HTML string is already dynamically build from my code for other part.
My VB.Net code is following
Private Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim reader As StreamReader
Dim ass As Assembly = Assembly.GetExecutingAssembly()
sHtmlText = eHtml.ToString()
sHtmlText = sHtmlText.Replace("(%-ONGLET-%)", sOngletText)
sHtmlText = sHtmlText.Replace("(%-TABLE-%)", sTableText)
reader = New StreamReader(ass.GetManifestResourceStream("UnicodeInput.JavaScript.js"))
Dim sScriptText = reader.ReadToEnd()
reader.Close()
sHtmlText = sHtmlText.Replace("(%-SCRIPT-%)", sScriptText)
reader = New StreamReader(ass.GetManifestResourceStream("UnicodeInput.StyleSheet.css"))
Dim sStyleText = reader.ReadToEnd()
reader.Close()
sHtmlText = sHtmlText.Replace("(%-STYLE-%)", sStyleText)
wvSelect.Settings.IsScriptNotifyAllowed = True
wvSelect.Settings.IsJavaScriptEnabled = True
wvSelect.NavigateToString(sHtmlText)
Dim file As System.IO.StreamWriter
file = My.Computer.FileSystem.OpenTextFileWriter("output.html", False)
file.Write(sHtmlText)
file.Close()
As you can see I have done same improvement for CSS file and I have discovered that this file has some errors !
My 'pseudo' HTML code is following
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<!--
<script type="text/javascript" src="./app.js"></script>
<script type="text/javascript" src="file:///D:/Documents/+Informatique/Application/#Visual Basic.NET/UnicodeInput/app.js"></script>
<script src="file:///D:/Documents/app.js"></script>
-->
<script type="text/javascript">
(%-SCRIPT-%)
</script>
<style type="text/css">
(%-STYLE-%)
</style>
</head>
<body>
<div id="onglet">
<div class='button'>Keyboard</div>
(%-ONGLET-%)
<div class='button' onclick="GetNewCmdFile()">*ADD</div>
</div>
What is in comment is what I have already tried that doesn't work in WinForm VB.Net WebView but works perfectly in pure HTML on Chrome.
Im am currenlty working on a integration of a nps widget within a Chatbot. I cannot show you all the code, but i imported the html file inside the chat.ts file. I want to call the entire html file after a button press from the chatbot. I have tried a lot, but nothing seems to help.
this is the chat.ts code (small part of it)
private showAskNicely() {
// #ts-ignore
window.location.assign('npshtml.html');
}
private askNicelyButton() {
const el = document.getElementById('detractbut');
el.addEventListener('click', this.showAskNicely);
}
this is the npshtml file
<html>
<body id="try">
<p>
AskNicely Web Survey Popup Example for traditional websites.<br>
Running in 'force' mode.<br>
Responses will be recorded.
</p>
<script type="text/javascript" src="https://static.asknice.ly/dist/standalone/asknicely-in-app-conversation.js"></script>
<link href="https://static.asknice.ly/dist/standalone/asknicely-in-app-conversation.css" rel="stylesheet" type="text/css" charset="utf-8">
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
askNicelyConversation({
config: {
--- cannot show this part ---
},
customData: {
a_custom_property: 'business', // Optional - Send extra data about this customer for reporting and leaderboards
another_custom_property: 'New York' // Optional - Send extra data about this customer for reporting and leaderboards
}
});
});
</script>
</body>
</html>
I also have the button rendered inside another html file with css, but that all works fine.
I have it currently on windows.location.assign, so that it opens a new page. It would be ideal if the script could be triggered without opening a new page.
Using jquery.load does not work and does not give me a error of some sort.
To upload a local file to Google Drive, I have an HTML <form></form> (see code below) that displays in a modal overtop a Google Sheet the user has open. The HTML form has <input type="file" name="..."> in it, and when I click to send the form object, I successfully upload the file if this Google Apps Script is "bound" to a specific Sheets file (and was written using the Tools > Script Editor... menu).
If I save the script as a standalone script and then test it (installed and enabled) on a Sheets file of my choosing, then the <form>'s onclick action and the attempt to call google.script.run.aServerFunction(...) causes a "NetworkError: Connection failure due to HTTP 403". To clarify this is what I mean by creating a standalone script and testing it on a Sheets file: https://developers.google.com/apps-script/add-ons/#understand_the_development_cycle. In earlier code iterations I alternatively got a authorization scriptError of some kind. Same error when script is published privately for testers to use on a Sheet. Unfortunately, I think I need this as a standalone script that is later publishable as an add-on- not a side script bound to a single Sheet using the Tools > Script Editor... menu.
My first post to Stack Overflow- please forgive any jargon or typography mistakes, and thank you!
HTML adapted from tutorials:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script>
function failed(event) {
$("div.response").text(event);
//google.script.run.selectStuff();
//google.script.host.close();
}
</script>
</head>
<body>
<form id="myForm">
<label>Your Name</label>
<input type="text" name="myName">
<label>Pick a file</label>
<input type="file" name="myFile">
<input type="submit" value="Upload File"
onclick="google.script.run.withFailureHandler(failed)
.uploadFiles(this.parentNode);
return false;">
</form>
<div class="response"></div>
</body>
</html>
In the code.gs:
function uploadFiles(formObject) {
/*var sheet1 = SpreadsheetApp.getActiveSheet();
sheet1.setActiveRange(sheet1.getRange(2, 2, 4, 4));
var formBlob = formObject.myFile;
var driveFile = DriveApp.createFile(formBlob);
driveFile.addEditor("...");
SpreadsheetApp.getActive().toast(driveFile.getUrl());
sheet1.getRange(1,1,1,1).setValue(driveFile.getUrl());
return driveFile.getUrl();*/
return "it worked";
}
I believe the reason you are getting the HTTP 403 error is because form DOM elements are illegal arguments in google.script.run.myfunction(...) in sheet addons. Even though they are mentioned here as legal parameters here, I think add-on have the added restriction of not being able to pass any kind of DOM elements.
The solution I came up with is to convert the uploaded file to base64 encode string using Filereader.readAsDataUrl() function in native javascript and passing the string to google script and converting it back to a file to be uploaded into google drive.
The base64 encode string starts like this:
data:application/pdf;base64,JVBERi0xLjMKJcTl8uXrp/Og0MTG....
GAS
function uploadFiles(formObject) {
// extract contentType from the encoded string
var contentType = formObject.split(",")[0].split(";")[0].split(":")[1]
// New Blob(data,contentType,name)
// Use base64decode to get file data
var blob = Utilities.newBlob(Utilities.base64Decode(formObject.split(",")[1]), contentType, "trial")
var driveFile = DriveApp.getFolderById("your Folder ID here").createFile(blob);
//return contentType, can be anything you like
return blob.getContentType()
}
HTML script
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
</head>
<body>
<form id="myForm">
<label>Your Name</label>
<input type="text" name="myName">
<label>Pick a file</label>
<input type="file" id = "filemy" name="myFile">
<input type="button" value="Upload File"
onclick="upload(this.parentNode)">
</form>
<div class="response"></div>
</body>
<script>
function failed(event) {
$("div.response").text(event);
//google.script.run.selectStuff();
//google.script.host.close();
}
function upload(frmData){
var file = document.getElementById("filemy").files[0]
var reader = new FileReader()
//reader.onload is triggered when readAsDataURL is has finished encoding
//This will take a bit of time, so be patient
reader.onload = function(event) {
// The file's text will be printed here
console.log("File being Uploaded")
//console.log(event.target.result)
google.script.run.withFailureHandler(failed).withSuccessHandler(failed)
.uploadFiles(event.target.result);
};
reader.readAsDataURL(file);
console.log(reader.result)
}
</script>
</html>
Final notes: I have not extensively tested the code, I have got it to work with a pdf file and an image/png file with a Maximun size of 2.6MB. So please try these 2 file types out before going on to further types of file!
Also, files do take a while to upload so be patient(~5-10sec). Especially since there is no progress bar to show the upload progress, it feels like nothing is happening.
Hope that helps!
How do I get the contents of a file form a HTML form? Here is an example of what I'm working with. All it does it output something like "C:\Fake Path\nameoffile
<html>
<head>
<script type="text/javascript">
function doSomething(){
var fileContents = document.getElementById('idexample').value;
document.getElementById('outputDiv').innerHTML = fileContents;
}
</script>
</head>
<body >
<form name = "form_input" enctype="multipart/form-data">
<input type="file" name="whocares" id="idexample" />
<button type="button" onclick="doSomething()">Enter</button>
</form>
<div id="outputDiv"></div>
</body>
</html>
EDIT:
It seems the solution is difficult to implement this way. What I'm trying to accomplish is sending a file to a python script on my webserver. This is my first time trying this sort of thing so suggestions are welcome. I supposes I could put the python script in my cgi folder and pass the values to it using something like...
/cgi/pythonscript.py?FILE_OBJECT=fileobjecthere&OTHER_VARIABLES=whatever
Would this be a better solution for sending file content to a webserver rather than having javacript open it directly using FileReader?
You can actually do that with the new FileReader Object.
Try this working example
function doSomething()
{
var file = document.getElementById('idexample');
if(file.files.length)
{
var reader = new FileReader();
reader.onload = function(e)
{
document.getElementById('outputDiv').innerHTML = e.target.result;
};
reader.readAsBinaryString(file.files[0]);
}
}
(works with the newest versions of Chrome and Firefox)
yes. Replace line of input as given below, Then it will work :)
<input type="file" ACCEPT="text/html" name="whocares" id="idexample" />
You cannot get the contents of a file in a form without submitting the form to your server.