How to show assets folder in my windows-8 app? - javascript

I am new to window-8 application development. I want to create a simple javascript photo application. In my application, I want to show an assets folder for users to pick images they choose. Can someone help me with this?

Since you are using JS to construct your app, all you need to do is write up a small script that lists out the path to the assets you have put up in that folder and link it via a HTML page. Are you trying to dynamically do this? I don't think such a solution exists..
Edit: On second thoughts, have you considered using a promise to run the script everytime a new resource is added to the folder? Keep a check on the folder and raise a flag when a resource is added, based on flag status, call the promise to update the script will will contain the newly added resources. You may also need to consider the situation where a user may be selecting data while the promise may update the page. Appropriate use session storage to handle the situation.

There is a FilePicker control that lets you easily display images/files for the user to pick. Here is a code sample; download the JavaScript version. There are also guidelines with links to the API documentation here.
An excerpt from the code sample:
// Create the picker object and set options
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
// Users expect to have a filtered view of their folders depending on the scenario.
// For example, when choosing a documents folder, restrict the filetypes to documents for your application.
openPicker.fileTypeFilter.replaceAll([".png", ".jpg", ".jpeg"]);
// Open the picker for the user to pick a file
openPicker.pickSingleFileAsync().then(function (file) {
if (file) {
// Application now has read/write access to the picked file
WinJS.log && WinJS.log("Picked photo: " + file.name, "sample", "status");
} else {
// The picker was dismissed with no selected file
WinJS.log && WinJS.log("Operation cancelled.", "sample", "status");
}
});

Related

How to Launch a PDF from a UWP (Universal Windows Platform) Web Application

I've converted an existing web application (HTML5, JS, CSS, etc.) into a Windows UWP app so that (hopefully) I can distribute it via the Windows Store to Surface Hubs so it can run offline. Everything is working fine, except PDF viewing. If I open a PDF in a new window, the Edge-based browser window simply crashes. If I open an IFRAME and load PDFJS into it, that also crashes. What I'd really like to do is just hand off the PDF to the operating system so the user can view it in whatever PDF viewer they have installed.
I've found some windows-specific Javascript APIs that seem promising, but I cannot get them to work. For example:
Windows.System.Launcher.launchUriAsync(
new Windows.Foundation.Uri(
"file:///"+
Windows.ApplicationModel.Package.current.installedLocation.path
.replace(/\//g,"/")+"/app/"+url)).then(function(success) {
if (!success) {
That generates a file:// URL that I can copy into Edge and it shows the PDF, so I know the URL stuff is right. However, in the application it does nothing.
If I pass an https:// URL into that launchUriAsync function, that works. So it appears that function just doesn't like file:// URLs.
I also tried this:
Windows.ApplicationModel.Package.current.installedLocation.getFileAsync(url).then(
function(file) { Windows.System.Launcher.launchFileAsync(file) })
That didn't work either. Again, no error. It just didn't do anything.
Any ideas of other things I could try?
-- Update --
See the accepted answer. Here is the code I ended up using. (Note that all my files are in a subfolder called "app"):
if (location.href.match(/^ms-appx:/)) {
url = url.replace(/\?.+/, "");
Windows.ApplicationModel.Package.current.installedLocation.getFileAsync(("app/" + url).replace(/\//g,"\\")).then(
function (file) {
var fn = performance.now()+url.replace(/^.+\./, ".");
file.copyAsync(Windows.Storage.ApplicationData.current.temporaryFolder,
fn).then(
function (file2) {
Windows.System.Launcher.launchFileAsync(file2)
})
});
return;
}
Turns out you have to turn the / into \ or it won't find the file. And copyAsync refuses to overwrite, so I just use performance.now to ensure I always use a new file name. (In my application, the source file names of the PDFs are auto-generated anyway.) If you wanted to keep the filename, you'd have to add a bunch of code to check whether it's already there, etc.
LaunchFileAsync is the right API to use here. You can't launch a file directly from the install directory because it is protected. You need to copy it first to a location that is accessible for the other app (e.g. your PDF viewer). Use StorageFile.CopyAsync to make a copy in the desired location.
Official SDK sample: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/AssociationLaunching
I just thought I'd add a variation on this answer, which combines some details from above with this info about saving a blob as a file in a JavaScript app. My case is that I have a BLOB that represents the data for an epub file, and because of the UWP content security policy, it's not possible simply to force a click on a URL created from the BLOB (that "simple" method is explicitly blocked in UWP, even though it works in Edge). Here is the code that worked for me:
// Copy BLOB to downloads folder and launch from there in Edge
// First create an empty file in the folder
Windows.Storage.DownloadsFolder.createFileAsync(filename,
Windows.Storage.CreationCollisionOption.generateUniqueName).then(
function (file) {
// Open the returned dummy file in order to copy the data to it
file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (output) {
// Get the InputStream stream from the blob object
var input = blob.msDetachStream();
// Copy the stream from the blob to the File stream
Windows.Storage.Streams.RandomAccessStream.copyAsync(input, output).then(
function () {
output.flushAsync().done(function () {
input.close();
output.close();
Windows.System.Launcher.launchFileAsync(file);
});
});
});
});
Note that CreationCollisionOption.generateUniqueName handles the file renaming automatically, so I don't need to fiddle with performance.now() as in the answer above.
Just to add that one of the things that's so difficult about UWP app development, especially in JavaScript, is how hard it is to find coherent information. It took me hours and hours to put the above together from snippets and post replies, following false paths and incomplete MS documentation.
You will want to use the PDF APIs https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/PdfDocument/js
https://github.com/Microsoft/Windows-universal-samples/blob/master/Samples/PdfDocument/js/js/scenario1-render.js
Are you simply just trying to render a PDF file?

Open file by name then perform actions

I'm currently creating files using drive.makeCopy(Objects[i][1]); where Objects is the name of the various files I want to make from a template.
The script works fine in making these files from a template however after each one has been made I would like to open the new file, hide some sheets in it and to set its permissions. The addresses for the permissions are held in Objects[i][3] but I cannot work out how to open these new files, then make the changes accordingly and then close the file.
I'm assuming by drive.MakeCopy() you are referring to File.MakeCopy(). This is easy, the MakeCopy function returns the File object it has created. You can then set permission this File object using functions such as addEditor(), addViewer(), setSharing(), etc.
So if Objects[i][3] contained the email address of someone who should be able to edit the new file, then you could do:
var new_file = drive.makeCopy(Objects[i][1]);
new_file.addEditor(Objects[i][3]);
You don't really need to "Close" the file after working with it, Apps Script takes care of this automatically.
See:
https://developers.google.com/apps-script/reference/drive/file#addEditor(String)
https://developers.google.com/apps-script/reference/drive/file#setSharing(Access,Permission)
https://developers.google.com/apps-script/reference/drive/file

Is it possible to retrieve text files from HTML app directory without HTTP request or <input>?

I'm working on an HTML/javascript app intended to be run locally.
When dealing with img tags, it is possible to set the src attribute to a file name with a relative path and thereby quickly and easily load an image from the app's directory. I would like to use a similar method to retrieve a text file from the app's directory.
I have used TideSDK, but it is less lightweight. And I am aware of HTTP requests, but if I remember correctly only Firefox has taken kindly to my use of this for local file access (although accessing local images with src does not appear to be an issue). I am also aware of the FileReader object; however, my interface requires that I load a file based on the file name and not based on a file-browser selection as with <input type="file">.
Is there some way of accomplishing this type of file access, or am I stuck with the methods mentioned above?
The browser will not permit you to access files like that but you can make javascript files instead of text files like this:
text1.js:
document.write('This is the text I want to show in here.'); //this is the content of the javascript file
Now call it anywhere you like:
<script type="text/javascript" src="text1.js"></script>
There are too many security issues (restrictions) within browsers making many local web-apps impossible to implement so my solution to a similar problem was to move out of browsers and into node-webkit which combines Chromium + Node.js + your scripts, into an executable with full disk I/O.
http://nwjs.io/
[edit] I'm sorry I thought you wanted to do this with TideSDK, I'll let my answer in case you want to give another try to TideSDK [/edit]
I'm not sure if it's what you're looking for but I will try to explain my case.
I've an application which allow the user to save the state of his progress. To do this, I allow him to select a folder, enter a filename and write this file. When the user open the app, he can open the saved file, and get back his progress. So I assume this enhancement is similar of what you are looking for.
In my case, I use the native File Select to allow the user to select a specific save (I'm using CoffeeScript) :
Ti.UI.currentWindow.openFileChooserDialog(_fileSelected, {
title: 'Select a file'
path: Ti.Filesystem.getDocumentsDirectory().nativePath()
multiple: false
})
(related doc http://tidesdk.multipart.net/docs/user-dev/generated/#!/api/Ti.UI.UserWindow-method-openFileChooserDialog)
When this step is done I will open the selected file :
if !filePath?
fileToLoad = Ti.Filesystem.getFile(scope.fileSelected.nativePath())
else
fileToLoad = Ti.Filesystem.getFile(filePath)
data = Ti.JSON.parse(fileToLoad.read())
(related doc http://tidesdk.multipart.net/docs/user-dev/generated/#!/api/Ti.Filesystem)
Please note that those snippets are copy/paste from my project and they will not work without the rest of my code but I think it's enough to illustrate you how I manage to open a file, and read his content.
In this case I'm using Ti.JSON.parse because there is only javascript object in these files but in your case you can just get the content. The openFileChooserDialog isn't mandatory, if you already know the file name, or if you get it from another way you can use Ti.Filesystem in your own way.

save and change the name of the file with chrome.filesystem

Is this possible with chrome.fileSystem to save a file on the client's disk, but by changing the file name. For example, I compress a file and I want that file is stored on the disc with my new name newFile.min.js for example. I can save the file to disk, but not to change its name. And what I would like is that everything is done in a "silent" without a window that asks for the location.
Here is the function I use to save my files:
function saveToEntry(entry, result) {
setTitle();
var blob = new Blob([result], {type: 'text/plain'});
currentEntry.createWriter(function(writer) {
writer.onwrite = function() {
writer.onwrite = null;
writer.write(blob);
}
writer.truncate(blob.size);
});
}
function setTitle() {
chrome.fileSystem.getDisplayPath(
currentEntry,
function(path) {
console.log(path);
document.title = path;
});
}
Is this possible? And if so, if you have any example to guide me would be great. If not, would be great too :)
Thank you in advance for your advice!
For that (saving in a separate file), I'm afraid that you need to ask the user for write access for a folder, not an individual file. Then you will be able to create a new file in it.
I suggest that you either ask the user to select a "working" directory, present an in-app file picker from that folder, and save the result next to the normal file.
Alternatively, ask the user to select an "output" folder, and dump the results there.
Another solution would be to require a Native Host module. You'll be able to access the system with the same rights as the user. It will limit your deployment options though: you'll need a separate installer for your module that can't be hosted on Chrome Web Store.

How to handle File Activation in Windows Store / WinJS apps

I'm trying to make my text editor app handle a file launch. Microsoft has a sample of how to do this here:
http://msdn.microsoft.com/en-us/library/windows/apps/hh452684.aspx
Unfortunately, it stops at the point of receiving the file and doesn't give any info on how to actually open said file.
I can successfully handle the activated event, and I end up with an absolute path to the file. For example,
C:\Users\Rory\Documents\test.txt
Metro apps don't have permission to access absolute paths, except under certain conditions.
if the file is chosen by the user via a file picker
if the app has accessed the file before and the path has been stored in the Windows.Storage.AccessCache
if the app is being passed the file as a launch.
Even though number 3 applies in this case, I can't open the file.
I've tried Windows.Storage.StorageFile.getFileFromPathAsync(path_to_file) but I get this error
0x80070005 - JavaScript runtime error: Access is denied.
WinRT information: Cannot access the specified file or folder (඀6).
The item is not in a location that the application has access to (including
application data folders, folders that are accessible via capabilities
and persisted items in the StorageApplicationPermissions lists). Verify
that the file is not marked with system or hidden file attributes.
I've set my app package manifest to accept txt files already.
The StorageFile or StorageFiles are passed to your app in the WebUIFileActivatedEventArgs argument. Try this:
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.file) {
if (args.detail.files.size > 0) {
var storageFile = args.detail.files[0];
Windows.Storage.FileIO.readTextAsync(storageFile).then(function (text) {
// Do something with the content of the file.
});
}
}
// ...
}

Categories