When I run this code it generates the appropriate file upload ui and adds the event listener to the upload button. However the first line in the upload function throws an error - Cannot read property 'style' of undefined - for this.missingFile. What am I doing wrong here?
function FileUploader(props) {
var div = document.querySelector(props.element);
var uid = generateGuid();
var templateHtml = "<p><div id=\"dvMissingFile-" + uid + "\" class=\"missing-file\"> Please choose a file.</div><input type=\"file\" id=\"flUploadedFile-" + uid + "\" name=\"flUploadedFile-" + uid + "\"/></p><div class=\"dvProgressBar\" id=\"progress-" + uid + "\"><div></div></div>";
div.innerHTML = templateHtml;
this.uploadButton = document.querySelector(props.uploadButton);
this.fileInput = document.querySelector("#flUploadedFile-" + uid);
this.missingFile = document.querySelector("#dvMissingFile-" + uid);
this.progress = document.querySelector("#progress-" + uid);
this.url = props.postUrl;
this.upload = function() {
this.missingFile.style.display = "none";
if (this.fileInput.files.length === 0) {
this.missingFile.style.display = "";
}
else {
var file = this.fileInput.files[0];
var xhr = new XMLHttpRequest();
var pbar = document.querySelector("#progress-" + uid + ">div");
if (xhr.upload) {
// do upload
}
}
}
this.uploadButton.addEventListener("click", this.upload);
}
Usage example
<div id="dvUploader"></div>
<button type="button" id="btnUpload" class="btn btn-primary">Upload</button>
<script>
var uploader = new FileUploader({
element: "#dvUploader",
uploadButton: "#btnUpload",
postUrl: "myposturl"
});
</script>
One small update to your code can help:
this.upload = function() {
// ...
}.bind(this);
Related
I have a conceptual issue about scopes on the following code.
The code is a simple client-side validation script for two forms.
I used a self-invoking function to try a something different approach by avoiding to set all global variables but its behavior seems a bit weird to me.
I am still learning to code with JavaScript and I'm not an expert, but these advanced features are a bit complicated.
I don't want to use jQuery but only pure JavaScript in order to learn the basis.
<!-- Forms handling -->
<script src="validate_functions.js"></script>
<script>
(function main() {
var frmPrev = document.getElementById('frmPrev');
var frmCont = document.getElementById('frmCont');
var btnPrev = frmPrev['btnPrev'];
var btnCont = frmCont['btnCont'];
var caller = '';
var forename = '';
var surname = '';
var phone = '';
var email = '';
var privacy = '';
var message = '';
var infoBox = document.getElementById('info-box');
var infoBoxClose = infoBox.getElementsByTagName('div')['btnClose'];
btnPrev.onclick = function(e) {
submit(e);
};
btnCont.onclick = function(e) {
submit(e);
};
function submit(which) {
caller = which.target.name;
var errors = '';
if(caller == 'btnPrev') {
forename = frmPrev['name'].value.trim();
surname = frmPrev['surname'].value.trim();
phone = frmPrev['phone'].value.trim();
email = frmPrev['email'].value.trim();
message = frmPrev['message'].value.trim();
privacy = frmPrev['privacy'].checked;
}
if(caller == 'btnCont') {
phone = frmCont['phone'].value.trim();
email = frmCont['email'].value.trim();
message = frmCont['message'].value.trim();
}
errors = validateFields(caller, forename, surname, phone, email, privacy, message);
if(errors == '') {
var params = 'which=' + caller;
params += '&fname=' + forename;
params += '&sname=' + surname;
params += '&tel=' + phone;
params += '&email=' + email;
params += '&priv=' + privacy;
params += '&mess=' + message;
var request = asyncRequest();
request.open('POST', "send-mail.php", true);
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
request.setRequestHeader('Content-length', params.length);
request.setRequestHeader('Connection', 'close');
request.onreadystatechange = function() {
if(this.readyState == 4) {
if(this.status == 200) {
if(this.responseText != null) {
infoBox.innerHTML = this.responseText;
} else {
infoBox.innerHTML = '<p>No data from server!</p>';
}
} else {
infoBox.innerHTML = '<p>Could not connect to server! (error: ' + this.statusText + ' )</p>';
}
}
}
request.send(params);
} else {
infoBox.innerHTML = errors;
}
infoBox.style.display = 'block';
}
infoBoxClose.onclick = function() {
infoBox.style.display = 'none';
infoBox.innerHTML = '';
};
function validateFields(_caller, _forename, _surname, _phone, _email, _privacy, _message) {
var errs = '';
if(_caller == 'btnPrev') {
errs += validateForename(_forename);
errs += validateSurname(_surname);
errs += validatePhone(_phone);
errs += validateEmail(_email);
errs += validateMessage(_message);
errs += validatePrivacy(_privacy);
}
if(_caller == "btnCont") {
errs += validatePhone(_phone);
errs += validateEmail(_email);
errs += validateMessage(_message);
}
return errs;
}
function asyncRequest() {
var request;
try {
request = new XMLHttpRequest();
}
catch(e1) {
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch(e2) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch(e3) {
request = null;
}
}
}
return request;
}
})();
Web console keeps telling me that single validate functions are not defined.
Why?
They should be loaded from the external script.. furthermore they should have a global scope.
Thank you in advance :)
Problem solved!
The path to the external script was incorrect.
Sorry for this rubbish! ^^"
I'm using the Phonegap file transfer plugin to upload a picture to the server. However I am getting error code: 1 (FileTransferError.FILE_NOT_FOUND_ERR). I've tested my server code with POSTMAN and I can upload and image successfully. However I get that error with the plugin. This is my code. The file is declared from "camera_image.src" and I can see the image when I append this to the src of an image on the fly. Any contributions? How is this code not perfect?
var fileURL = camera_image.src;
alert(fileURL);
var win = function (r) {
temp.push(r.response);
statusDom.innerHTML = "Upload Succesful!";
}
var fail = function (error) {
alert("An error has occurred: Code = " + error.code + " | Source:" + error.source + " | Target:" + error.target );
statusDom.innerHTML = "Upload failed!";
}
var options = new FileUploadOptions();
options.fileKey = "properties_photo";
options.fileName=fileURL.substr(fileURL.lastIndexOf('/') + 1);
options.headers = {
Connection: "close"
};
var params = {};
params.value1 = "test";
params.value2 = "param";
options.params = params;
var ft = new FileTransfer();
statusDom = document.querySelector('#status');
ft.onprogress = function(progressEvent) {
if (progressEvent.lengthComputable) {
var perc = Math.floor(progressEvent.loaded / progressEvent.total * 100);
statusDom.innerHTML = perc + "% uploaded...";
console.log(perc);
} else {
if(statusDom.innerHTML == "") {
statusDom.innerHTML = "Loading";
} else {
statusDom.innerHTML += ".";
}
}
};
ft.upload(fileURL, encodeURI("http://cloud10.me/clients/itsonshow/app/image_upload_process.php"), win, fail, options);
I had this problem because of spaces in the path or filename of the file to be uploaded.
You need to ensure the plugin isn't being passed a fileURL with %20 in the URL.
I'm pretty confident that there is something with this that I'm doing wrong. This question has been asked before, but even after reviewing the other questions and answers, I still can't get it to work.
Basically the issue is that I can't set file.fileType to be the value I need it to be from within the callback function within magic.detectFileType.
var Magic = mmm.Magic,
magic = new Magic(mmm.MAGIC_MIME_TYPE),
for (var i in files){
var file = new File(files[i])
file.detectFileType();
commandSelf.log("File Type: " + file.fileType);
commandSelf.log("File Name: " + file.filename);
commandSelf.log("Full Path: " + file.fullPath);
}
var File = function(filename){
this.filename = filename;
this.fullPath = null;
this.fileType = null;
};
File.prototype.detectFileType = function(){
this.fullPath = path + "/" + this.filename;
var self = this;
// Make sure this is an appropriate image file type
magic.detectFile(this.fullPath, function(err, result){
self.fileType = "test"
});
}
A more appropriate solution would be to have detectFileType accept a callback or return a Promise so that you know when the asynchronous task has completed and you can safely check the File instance properties. For example:
var Magic = mmm.Magic;
var magic = new Magic(mmm.MAGIC_MIME_TYPE);
files.forEach(function(file) {
file = new File(file);
file.detectFileType(function(err) {
if (err) throw err;
commandSelf.log("File Type: " + file.fileType);
commandSelf.log("File Name: " + file.filename);
commandSelf.log("Full Path: " + file.fullPath);
});
});
var File = function(filename){
this.filename = filename;
this.fullPath = null;
this.fileType = null;
};
File.prototype.detectFileType = function(cb){
this.fullPath = path + "/" + this.filename;
var self = this;
// Make sure this is an appropriate image file type
magic.detectFile(this.fullPath, function(err, result){
self.fileType = "test"
cb(err);
});
}
I'm trying to rewrite an vanilla ES5 closure to a ES2015 Class. The code overrides the window.onerror function and acts as a global error handler method for logging purposes.
My old code looks like this. I would like to know how to rewrite it in ES2015. How do i override the Window.onerror?
(function() {
window.onerror = function(errorMessage, url, line) {
try {
if (typeof(url) === "undefined") {
url = "";
}
if (typeof(line) === "undefined") {
line = "";
}
// Avoid error message being too long...
if (errorMessage.length > 300) {
errorMessage = errorMessage.slice(0,300) + "...";
}
errorMessage = errorMessage.replace(/&/g, "%26").replace(/ /g, "+");
url = url;
line = line;
var parentUrl = encodeURIComponent(document.location.href);
// Set error details
var parameters = "error_message=" + errorMessage +
"&url=" + url +
"&line=" + line +
"&parent_url=" + parentUrl;
// Set path to log target
var logUrl = "xxx";
// Set error details as image parameters
new Image().src = logUrl + '?' + parameters;
} catch (e) {}
};
}());
EDIT!
Now I'm trying to rewrite it in a JS Class. So I guess I have to extend the Window class or something like that (I have a Java background). But Window is not a class as I understand. This is what I have so far.
So I need help to override the window.onerror function, written in ES2015!
export const Logging = new class {
constructor() {
// todo
}
onerror(errorMessage, url, line) {
try {
if (typeof(url) === "undefined") {
url = "";
}
if (typeof(line) === "undefined") {
line = "";
}
// truncate error message if necessary
if (errorMessage.length > 300) {
errorMessage = errorMessage.slice(0,300) + "...";
}
// URI encoding
errorMessage = errorMessage.replace(/&/g, "%26").replace(/ /g, "+");
url = url;
line = line;
var parentUrl = encodeURIComponent(document.location.href);
// set error details
var parameters = "error_message=" + errorMessage +
"&url=" + url +
"&line=" + line +
"&parent_url=" + parentUrl;
// Set path to log target
var logUrl = "xxx";
// set error details as image parameters
var img = new Image().src = logUrl + '?' + parameters;
console.log(img);
}
catch (e) {}
}
}
/* ------------------------------------------------------------------------------------------------------------ */
export default Logging;
The only thing that might be useful here are parameter default values. Everything else that I changed was mistaken in ES5 already.
window.onerror = function(errorMessage, url="", line="") {
try {
// Avoid error message being too long...
if (errorMessage.length > 303) {
errorMessage = errorMessage.slice(0,300) + "...";
}
var parentUrl = document.location.href;
// Set error details
var parameters = "error_message=" + encodeURIComponent(errorMessage).replace(/%20/g, "+") +
"&url=" + encodeURIComponent(url) +
"&line=" + encodeURIComponent(line) +
"&parent_url=" + encodeURIComponent(parentUrl);
// Set path to log target
var logUrl = "xxx";
// Set error details as image parameters
new Image().src = logUrl + '?' + parameters;
} catch (e) {}
};
I want to access files in a particular document set in a document library .
So far i was able to get the particular document set name and ID using JSOM as below .
How to read all the files inside the document set
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"></script>
<script type="text/javascript" src="_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="_layouts/15/sp.js"></script>
<script type="text/javascript">
ExecuteOrDelayUntilScriptLoaded(MainFunction, "sp.js");
function MainFunction() {
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle('Planner Session');
var camlQuery = new SP.CamlQuery(); //initiate the query object
camlQuery.set_viewXml('<View><Query><Where><Lt><FieldRef Name="ID" /><Value Type="Counter">3</Value></Lt></Where><OrderBy><FieldRef Name="ID" Ascending="FALSE"/></OrderBy></Query><RowLimit>1</RowLimit></View>');
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded(sender, args) {
var DocSet = "";
var listItemEnum = collListItem.getEnumerator();
while (listItemEnum.moveNext()) {
var oListItem = listItemEnum.get_current();
DocSet += '\n\nID: ' + oListItem.get_id() + '\nName: ' + oListItem.get_item('FileLeafRef');
}
// Here i would like to get the file inside the documentSet
alert(DocSet.toString());
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
</script>
<input type="button" value="Get Products" onclick="MainFunction()"/>
How to get files of Document Set via SharePoint CSOM
Assume the following structure:
Documents (library)
|
2013 (Document set)
Query based approach
The following example demonstrates how to return Files located in Document Set using CAML query:
function getListItems(listTitle,folderUrl,success,error)
{
var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var list = web.get_lists().getByTitle(listTitle);
var qry = SP.CamlQuery.createAllItemsQuery();
qry.set_folderServerRelativeUrl(folderUrl);
var items = list.getItems(qry);
ctx.load(items,'Include(File)');
ctx.executeQueryAsync(
function() {
success(items);
},
error);
}
Key points:
SP.CamlQuery.folderServerRelativeUrl property is used to return
only files located under specific url
Usage
var listTitle = 'Documents';
var docSetUrl = '/Documents/2013';
getListItems(listTitle,docSetUrl,
function(items){
for(var i = 0; i < items.get_count();i++) {
var file = items.get_item(i).get_file();
console.log(file.get_title());
}
},
function logError(sender,args)
{
console.log(args.get_message());
});
Using SP.Web.getFolderByServerRelativeUrl method
Use SP.Web.getFolderByServerRelativeUrl Method to get Document Set object located at the specified server-relative URL and then SP.Folder.files property to gets the collection of all files contained in the Document Set
Complete example:
function getFiles(folderUrl,success,error)
{
var ctx = SP.ClientContext.get_current();
var files = ctx.get_web().getFolderByServerRelativeUrl(folderUrl).get_files();
ctx.load(files);
ctx.executeQueryAsync(
function() {
success(files);
},
error);
}
Usage
var docSetUrl = '/Documents/2013'; //<-- '2013'
getFiles(docSetUrl,
function(files){
for(var i = 0; i < files.get_count();i++) {
var file = files.get_item(i);
console.log(file.get_title());
}
},
function logError(sender,args)
{
console.log(args.get_message());
});
Please find the complete code which does the following
1. Gets the required docset based on my conditions
2. gets all the files in that particular document set by checking the value in the custom column
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"></script>
<script type="text/javascript" src="_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="_layouts/15/sp.js"></script>
<script type="text/javascript">
ExecuteOrDelayUntilScriptLoaded(MainFunction, "sp.js");
function MainFunction() {
var currentListID = getQueryStringValue("List");
var clientContext = new SP.ClientContext.get_current();
this.ListId = "{" + currentListID + "}";
var oList = clientContext.get_web().get_lists().getById(ListId);
var camlQuery = new SP.CamlQuery(); //initiate the query object
var currentDocSetID = getQueryStringValue("ID");
camlQuery.set_viewXml('<View><Query><Where><Lt><FieldRef Name="ID" /><Value Type="Counter">' + currentDocSetID + '</Value></Lt></Where><OrderBy><FieldRef Name="ID" Ascending="FALSE"/></OrderBy></Query><RowLimit>1</RowLimit></View>');
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded(sender, args) {
var DocSet = "";
var listItemEnum = collListItem.getEnumerator();
while (listItemEnum.moveNext()) {
var oListItem = listItemEnum.get_current();
DocSet += oListItem.get_item('FileLeafRef');
}
// Here i would like to get the file inside the documentSet
// alert(DocSet.toString());
var fsoType = oListItem.get_fileSystemObjectType();
if(oListItem.FileSystemObjectType == SP.FileSystemObjectType.Folder)
{
//var folderUrl = "/" + listName + "/" + DocSet.toString();
var RawFolderUrl = getQueryStringValue("RootFolder");
var pos = RawFolderUrl.lastIndexOf('/');
var folderUrl = RawFolderUrl.substring(0,pos) + "/" + DocSet.toString();
GetFilesFromFolder(folderUrl);
}
}
var allItems;
function GetFilesFromFolder(folderUrl)
{
var context = new SP.ClientContext.get_current();
var web = context.get_web();
var list = web.get_lists().getById(ListId);
// Use createAllItemsQuery to get items inside subfolders as well. Otherwise use new SP.CamlQuery() to get items from a single folder only
var query = SP.CamlQuery.createAllItemsQuery();
query.set_folderServerRelativeUrl(folderUrl);
allItems = list.getItems(query);
context.load(allItems, 'Include(File, FileSystemObjectType,Document_x0020_Type,Title)');
context.executeQueryAsync(Function.createDelegate(this, this.OnSuccess), Function.createDelegate(this, this.OnFailure));
}
function OnSuccess()
{
var listItemEnumerator = allItems.getEnumerator();
while(listItemEnumerator.moveNext())
{
var currentItem = listItemEnumerator.get_current();
if(currentItem.get_fileSystemObjectType() == "0")
{
var file = currentItem.get_file();
if(file != null && currentItem.get_item("Document_x0020_Type") == "03. Minutes")
{
// alert('File Name: ' + file.get_name() + '\n' + 'File Url: ' + file.get_serverRelativeUrl());
// alert(currentItem.get_item("Title"));
var link = document.getElementById("prvMinutes");
link.href= file.get_serverRelativeUrl();
// link.innerHTML = currentItem.get_item("Title");
link.innerHTML = file.get_name();
}
}
}
}
function OnFailure(sender, args) {
alert("Failed. Message:" + args.get_message());
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
function getQueryStringValue (key) {
return unescape(window.location.search.replace(new RegExp("^(?:.*[&\\?]" + escape(key).replace
(/[\.\+\*]/g, "\\$&") + "(?:\\=([^&]*))?)?.*$", "i"), "$1"));
}
</script>
<a id="prvMinutes" href="#" target="_blank"> </a>