uwp javascript list files in music library folder - javascript

The following lists files in a folder "Assets" in app and functions correctly.
// Get the path to the app's Assets folder.
var root = Windows.ApplicationModel.Package.current.installedLocation.path;
var path = root + "\\Assets";
//var path = Windows.Storage.KnownFolders.musicLibrary;
var StorageFolder = Windows.Storage.StorageFolder;
var folderPromise = StorageFolder.getFolderFromPathAsync(path);
folderPromise.done(function getFolderSuccess(folder) {
var filesInFolderPromise = folder.getFilesAsync();
filesInFolderPromise.done(function getFilesSuccess(filesInFolder) {
s = "";
filesInFolder.forEach(function forEachFile(item) {
s = s + item.name + "<br />";
});
document.getElementById('filelist').innerHTML = s;
});
});
I want to modify it to list the files in the musicLibrary. When I change the path name to
var path = Windows.Storage.KnownFolders.musicLibrary;
I get
JavaScript runtime error: The parameter is incorrect
Please help me with the appropriate syntax. The musicLibrary capability is set in the manifest.

Windows.Storage.KnownFolders.musicLibrary
is not a path string. This is StorageFolder class. Thus the call of getFolderFromPathAsync fails. Please refer the Microsoft docs.
KnownFolders Class (You can select 'JavaScript' from the language combobox on the right pane)

The object is to get the files async from the Music folder. This is done directly as follows:
var f = Windows.Storage.KnownFolders.musicLibrary;
f.getFilesAsync().done(function getFilesSuccess(filelist) {
s = "";
filelist.forEach(function forEachFile(item) {
s = s + item.name + "<br />";
});
document.getElementById('filelist').innerHTML = s;
});
Thanks to pnp0a03, and a quick re reading of the documentation.

For those struggling with syntax, this answer is equivalent:
var f = Windows.Storage.KnownFolders.musicLibrary;
f.getFilesAsync().then(success42);
function success42(filelist) {
s = "";
filelist.forEach(function forEachFile(item) {
s = s + item.name + "<br />";
});
document.getElementById('filelist').innerHTML = s;
}

Related

Copying Files based on a custom column value between document libraries in SharePoint using javascript

I am new to Javascript and currently working on a task where I need to copy files based on a custom column name "PID" from One Document Library to the other.
I was able to get the below code to work which copies all the files
$scope.copyFiles=function()
{
var sourceLib = '/sites/Protocol/ProtocolDocument';
var destLib = '/sites/Protocol/FinalProtocolDocuments';
var context = new SP.ClientContext.get_current();
var web = context.get_web().get_lists();
var folderSrc = web.getFolderByServerRelativeUrl(sourceLib);
//var cq = "<Query><Where><Eq><FieldRef Name="ProtocolID" LookupId="TRUE"/><Value Type="Text">' + 466 + '</Value></Eq></Where></Query>"
context.load(folderSrc,'Files');
context.executeQueryAsync(
function() {
console.log("Got the source folder right here!");
var files = folderSrc.get_files();
var e = files.getEnumerator();
var dest = [];
while (e.moveNext()) {
var file = e.get_current();
var destLibUrl = destLib + "/" + file.get_name();
dest.push(destLibUrl); //delete this when we're happy we got the file paths right
file.copyTo(destLibUrl, true);
}
console.log(dest); //delete this when we're happy we got the file paths right
context.executeQueryAsync(function() { console.log("Files moved successfully!");}, function(sender, args) {console.log("error: ") + args.get_message()});
},
function(sender, args){console.log("Sorry, something messed up: " + args.get_message());}
);
}
I did some research online to get the Filenames based on a custom column value with no luck
Also tried to use CAML , however not sure how to use it in the code.
Would appreciate if anyone could help me get the filenames from a Document Library based on custom column name "PID" so that only selected/filtered files are moved to the destination Library.
UPDATED CODE
$scope.copyFiles=function()
{
var sourceLib = '/sites/Protocol/ProtocolDocument';
var destLib = '/sites/Protocol/FinalProtocolDocuments';
PID='466'
var context = new SP.ClientContext();
var list = context.get_web().get_lists().getByTitle("ProtocolDocument");
var cq = new SP.CamlQuery();
cq.set_viewXml("<View><Query>" +
"<Where>" +
"<Eq><FieldRef Name=\"ProtocolID\"/><Value Type=\"Text\">PID</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>");
var items = list.getItems(cq);
context.load(items);
context.executeQueryAsync(
function() {
var e = items.getEnumerator();
var dest = [];
while (e.moveNext())
{
var file = e.get_current();
var destLibUrl = destLib + "/" + file.get_name();
dest.push(destLibUrl); //delete this when we're happy we got the file paths right
file.copyTo(destLibUrl, true);
}
console.log(dest); //delete this when we're happy we got the file paths right
context.executeQueryAsync(function() { console.log("Files moved successfully!");}, function(sender, args) {console.log("error: ") + args.get_message()});
},
function(sender, args){console.log("Sorry, something messed up: " + args.get_message());}
);
}
});
Here is my attempt. I tested it successfully on SharePoint 2013, and it copies files from one document library to another, but only the files with a lookup field set to a specific value. I have included a short summary, but if you only want the code then jump down to Now to the actual code.
Please note that I have used syntax not supported by Internet Explorer, so let me know if you need to support that browser. I also believe that a function or method should only do one thing, so I split the functionality into three separate functions. This also helps keep the code clean and easier to read.
To summarize: The first function, findAndCopyFiles(), will run once and find all the files with the lookup field value you set. It will then send each file to the loadAndCopyFile() function to load the file object. This function will run once for every file that should be copied. When the file object is loaded, it is sent to the third and final function, copyFileTo(), that will actually copy the file to the destination document library. This function will also run once per file.
Now to the actual code
First you need to set these configuration variables according to your setup:
const destinationLibraryPath = 'The path to your destination document library';
const sourceLibraryName = 'The name (not path) of your source document library';
const lookupField = 'The name of your lookup field';
const lookupValue = 'The value your lookup field should equal for files to be copied';
findAndCopyFiles()
This function is responsible for finding all the files in the source document library with the lookup field set to the value of lookupValue. We use what is known as a CAML query to filter the files. You can filter on all available fields and columns, not only lookup fields.
const findAndCopyFiles = () => {
const clientContext = SP.ClientContext.get_current();
const sourceList = clientContext.get_web().get_lists().getByTitle(sourceLibraryName);
const camlQuery = new SP.CamlQuery();
const whereQuery = `<Eq><FieldRef Name="${lookupField}"/><Value Type="Text">${lookupValue}</Value></Eq>`;
camlQuery.set_viewXml(`<View><Query><Where>${whereQuery}</Where></Query></View>`);
const sourceListItems = sourceList.getItems(camlQuery);
clientContext.load(sourceListItems);
clientContext.executeQueryAsync(
() => {
const filesEnumerator = sourceListItems.getEnumerator();
while (filesEnumerator.moveNext()) {
loadAndCopyFile(filesEnumerator.get_current(), clientContext);
}
},
(_sender, args) => {
console.log(args.get_message());
}
);
}
When the query executes, we use the getEnumerator() method to iterate through all the files returned by the query, in other words all the files that will be copied.
loadAndCopyFile()
After finding all the relevant files, we send each file to the next function to continue our process. This function will load the file object (as in the actual file) and construct the destination URL using the path to the destination document library and the filename of the file.
const loadAndCopyFile = (file, clientContext) => {
const fileRef = file.get_file();
clientContext.load(fileRef);
clientContext.executeQueryAsync(
() => {
const destinationUrl = `${destinationLibraryPath}/${fileRef.get_name()}`;
copyFileTo(fileRef, destinationUrl, clientContext);
},
(_sender, args) => {
console.log(args.get_message());
}
);
}
copyFileTo()
The final function is responsible for actually copying the file to the destination document library. It is quite simple, and looks like this:
const copyFileTo = (file, destinationUrl, clientContext) => {
file.copyTo(destinationUrl, true);
clientContext.executeQueryAsync(
() => {
console.log(`File copied to ${destinationUrl}!`);
},
(_sender, args) => {
console.log(args.get_message());
}
);
}
Putting it all together
And finally, we execute the findAndCopyFiles() function when all the required libraries are ready:
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', () => {
findAndCopyFiles();
});
Disclaimer: I wrote this post on another computer than the one where I tested the code, so if something does not work it may be because of a simple syntax error. In that case, add a comment and let me know!

How to get FolderIterator containing only direct children of a folder in Google Drive

I am trying to create a script to print a list of full file paths for everything in my Google drive. The goal is to have a list like this:
./Docs/Doc1.gdoc
./Docs/Doc2.gdoc
./Docs/Doc3.gdoc
./Pics/2011/img1.jpg
./Pics/2011/img2.jpg
./Pics/2011/img3.jpg
...
It appears that this is not as simple as I thought, since Google Drive methods like getFolders() treat all folders as subfolders.
I tried writing something recursive to do this, until I realized the subfolders issue:
function getChildFolders(parent) {
var childFolders = parent.getFolders();
while (childFolders.hasNext()) {
var childFolder = childFolders.next();
var pathString = childFolder.getName()
var files = childFolder.getFiles();
while (files.hasNext()) {
var fullPath = parent.getName()
var fileName = files.next().getName()
fullFilePath = pathString.concat('/', fileName)
Logger.log(fullFilePath);
}
// Recursive call
getChildFolders(childFolder);
}
}
I can't figure out a way to list the files in this manner in a hierarchical way. Has anyone been able to do this?
This should dump what you are looking for:
function dumpFilesInFolder(folder, path)
{
path = (path || "") + "/" + folder.getName();
Logger.log(path);
var subFolders = folder.getFolders();
while(subFolders.hasNext())
{
dumpFilesInFolder(subFolders.next(), path);
}
var files = folder.getFiles();
while(files.hasNext())
{
Logger.log(path + "/" + files.next().getName());
}
}
function startIt()
{
dumpFilesInFolder(DriveApp.getRootFolder());
}

How to use searchFile and searchFolder at the same time correctly? - App Script

The next script what it does is to search all the spreadsheets with a certain name in the drive starting from a certain folder.
function searchSSH(folder, path) {
if (folder == null && path == null) {
return
searchSSH(DriveApp.getFolderById("ID"), "");
}
var files = [];
path = path + "/" + folder.getName();
var searchFile = "fullText contains 'Project <>' and mimeType='" + MimeType.GOOGLE_SHEETS + "'";
var fileIterate = folder.searchFiles(searchFile);
while ( fileIterate.hasNext() ) {
var file = fileIterate.next();
var fileId = file.getId();
var name = file.getName();
files.push(name);
for (var i=0; i<files.length; i++){
Logger.log(files[i]);
}
}
var folderIterate = folder.getFolders();
while(folderIterate.hasNext()) {
var searchFold = searchSSH(folderIterate.next(), path);
for (var i = 0; i < searchFold.length; i++) {
files.push(searchFold[i]);
}
}
return files;
}
What I am trying to do is to see how I can do it so that I can also look for a certain folder just like the searchFile does and I try to do it like this...
function searchSSH() {
var Folder = DriveApp.getFolderById("ID");
var folders = Folder.searchFolders('fullText contains "project"');
while (folders.hasNext()) {
var folder1 = folders.next();
Logger.log(folder1.getName());
for (var i = 0; i < folder1.length; i++) {
files.push(folder1[i]);
}
}
var files = [];
var searchFile = "fullText contains 'test <>' and mimeType='" + MimeType.GOOGLE_SHEETS + "'";
var fileIterate = Folder.searchFiles(searchFile);
while ( fileIterate.hasNext() ) {
var file = fileIterate.next();
var fileId = file.getId();
var name = file.getName();
files.push(name);
for (var i=0; i<files.length; i++){
Logger.log(files[i]);
}
}
return files;
}
But doesn´t works. What I'm trying to do is to iterate through all the folders until I find the folder with the name project and keep iterating in that folder until I find all the spreadsheets with the test name but only search in the first folder.
I try to iterate between folders until I find the folder with the name Project and inside that folder keep iterating until I find the file with the name Test and that it is type spreadsheet.
The first script if it finds the file but I want to specify I look inside the folders with the name Project to improve the performance of the script
The second script I'm trying is not iterating, so it does not work because when I run it, it only finds the first folder and dont searching inside the others folders, Thanks for trying to help me. I hope that now it has given me to understand
From your this reply, I could understand as follows.
You want to retrieve Spreadsheet with the filename of Test under the folder with the name of Project. You want to do this with low process cost.
If my understanding is correct, how about these sample scripts? Please choose from them for your situation. I think that there are several answers for your situation. So please think of this answer as one of them.
Pattern 1:
Flow:
Retrieve files from filename of Test using getFilesByName().
Retrieve parent folders of each file using getParents().
If the folder name is Project and the mimeType is Spreadsheet, it retrieves the file.
Sample script:
var fileName = "Test";
var folderName = "Project";
var files = DriveApp.getFilesByName(fileName);
while (files.hasNext()) {
var file = files.next();
var parents = file.getParents();
while (parents.hasNext()) {
var parent = parents.next();
if (file.getMimeType() == MimeType.GOOGLE_SHEETS && parent.getName() == folderName) {
// do something
}
}
}
Pattern 2:
Flow:
Retrieve folders from folder name of Project using getFoldersByName().
Retrieve files in each folders using getFilesByName().
If the filename is Test and the mimeType is Spreadsheet, it retrieves the file.
Sample script:
var fileName = "Test";
var folderName = "Project";
var folders = DriveApp.getFoldersByName(folderName);
while (folders.hasNext()) {
var folder = folders.next();
var files = folder.getFilesByName(fileName);
while (files.hasNext()) {
var file = files.next();
if (file.getMimeType() == MimeType.GOOGLE_SHEETS && file.getName() == fileName) {
// do something
}
}
}
Pattern 3:
Flow:
Retrieve folder IDs of folder name of Project using getFoldersByName().
Retrieve files with the parent folder of Project and the filename of Test and the mimeType of Spreadsheet using searchFiles().
Sample script:
var fileName = "Test";
var folderName = "Project";
var folders = DriveApp.getFoldersByName(folderName);
var folderIds = [];
while (folders.hasNext()) {
folderIds.push(folders.next().getId());
}
folderIds.forEach(function(id) {
var params = "'" + id + "' in parents and title='" + fileName + "' and mimeType='" + MimeType.GOOGLE_SHEETS + "'";
var files = DriveApp.searchFiles(params);
while (files.hasNext()) {
var file = files.next();
// do something
}
});
References:
getFilesByName()
getFoldersByName()
getParents()
searchFiles()
If these were not what you want, I'm sorry.

Error when using node.js method path.extname()

I am using Electron. I have written a program that recursively reads the files of a directory. Now I want that files with a certain extname (file extension) are not shown. In order to do that I need the node.js method path.extname(path) which return the extname.
My problem is that the path.extname() method does not work at that place in the code I need it.
Outside of my function scan_directory_to_html() it works and returns .jpg but inside of the function I get the error Uncaught TypeError: path.extname is not a function.
const fs = require('fs');
const path = require('path');
const {ipcRenderer} = require('electron')
//This works:
console.log(path.extname(`${__dirname}/../../project_files/sprites/Appenzell.jpg`));
function scan_directory_to_html(directory){
var zw_directory_array = fs.readdirSync(directory);
var zw_to_html = "";
for(var i = 0; i < zw_directory_array.length; i++){
var path = directory + zw_directory_array[i];
//This produces the error message
console.log(path.extname(`${__dirname}/../../project_files/sprites/Appenzell.jpg`));
if(fs.lstatSync(path).isFile()){
zw_to_html += "<a href='#' onClick='create_sprite_window(`"+ path +"`)'><li><img src='" + path + "'/>" + zw_directory_array[i] + "</li></a>";
}else if(fs.lstatSync(path).isDirectory()){
zw_to_html += "<li class='li_directory'>" + zw_directory_array[i] + "</li>";
zw_to_html += "<ul>";
zw_to_html += scan_directory_to_html(path + "/");
zw_to_html += "</ul>";
}else{
console.log("Error in function scan_directory_to_html(): Path is neither directory nor file.");
}
}
return zw_to_html;
}
document.getElementById('sidebar_left_sprites').innerHTML = scan_directory_to_html(`${__dirname}/../../project_files/sprites/`);
I have also tried to put const path = require('path'); inside the function as well but it then says that the Identifier 'path' has already been declared.
How can I use the path.extname() method inside of the function?
The path is conflicted in your code. Use another name in below.
var filepath = directory + zw_directory_array[i];
instead
var path = directory + zw_directory_array[i];

My custom javascript function is "not a function"?

I wrote a small .js file that has 3 functions in it for easy in-site cookie management. Here is the source for that file:
// Make Cookie
function Bake(name,value) {
var oDate = new Date();
oDate.setYear(oDate.getFullYear()+1);
var oCookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + ';expires=' + oDate.toGMTString() + ';path=/';
document.cookie= oCookie;
}
// Read Cookie
function Eat(name){
name = name.toLowerCase();
var oCrumbles = document.cookie.split(';');
for(var i=0; i<oCrumbles.length;i++)
{
var oPair= oCrumbles[i].split('=');
var oKey = decodeURIComponent(oPair[0].trim().toLowerCase());
var oValue = oPair.length>1?oPair[1]:'';
if(oKey == name)
return decodeURIComponent(oValue);
}
return '';
}
// Delete / Void Cookie
function Burn(name){
Bake(name,'');
}
I put that .js file into my "/models" folder on Cloud9. In my index.js I do have the line: var OCookie = require('../models/oatmealcookie'); to include my custom "library". However, still in index.js, I attempt to call the OCookie.Bake('test','testvalue'); before a redirect, and an error comes up on the page as TypeError: OCookie.Bake is not a function. Any help as to why it's not able to recognise my function as a function?
If that is your whole file, you aren't exporting any of your functions through module.exports. Effectively, your file is run once, and Bake, Eat, and Burn are declared as functions for the module but no other module can use them.
You would need something like:
module.exports = {
Bake: Bake,
Eat: Eat,
Burn: Burn
};
So that other modules can use your functions.
You need an exports.Bake = Bake at the end of the module.
You need to export your functions so that node.js recognises them when you require them.
See here: http://www.sitepoint.com/understanding-module-exports-exports-node-js/ for example.
var exports = module.exports = {
// Make Cookie
'Bake': function (name,value) {
var oDate = new Date();
oDate.setYear(oDate.getFullYear()+1);
var oCookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + ';expires=' + oDate.toGMTString() + ';path=/';
document.cookie= oCookie;
}
// Read Cookie
'Eat': function (name){
name = name.toLowerCase();
var oCrumbles = document.cookie.split(';');
for(var i=0; i<oCrumbles.length;i++)
{
var oPair= oCrumbles[i].split('=');
var oKey = decodeURIComponent(oPair[0].trim().toLowerCase());
var oValue = oPair.length>1?oPair[1]:'';
if(oKey == name)
return decodeURIComponent(oValue);
}
return '';
}
// Delete / Void Cookie
'Burn': function (name){
Bake(name,'');
}
}
By convention though, you would start your function names with lower case.

Categories

Resources