accessing local files?
Monkey Targets Forums/HTML5/accessing local files?
| ||
| don't suppose anyone has any code for reading text files off of the local harddrive? |
| ||
| That won't work in HTML5 because of this sandbox protection. HTML5 apps are simply not allowed to access anything outside as far as I know. |
| ||
| It can be done, but it has to happen under user control (they have to click a button and select the file) and then you might have to upload it to the same server as your app before you can access it (from there). I can't remember the exact details. More here: http://www.w3schools.com/jsref/dom_obj_fileupload.asp Also, search for FileReader. |
| ||
| That won't work in HTML5 because of this sandbox protection. HTML5 apps are simply not allowed to access anything outside as far as I know. I'm reading text files okally dokally.... in HTML5, looking for an example for you now... You don't need to upload the files to a server, they can be accessed from the user's device within the following example. As Beaker says, you need to select a 'browse' button first.... in my example below anyhow. [EDIT] There might be a bit much to chew on, but this code will load three separate 'text' files and do a bit of data parsing: (incidentally, I was trying to load an image of the user's choice using the following code. After a bit of digging it appears as though MonkeyX creates a small database of images at compile time - I haven't been able to find a work around to achieve my goal of loading a users image after compiling and have given up on that for now.... hope the following helps you out anyways ;)
Strict
' Preprocessor related:
#MOJO_AUTO_SUSPEND_ENABLED = False
' Imports:
Import mojo
Import brl.databuffer
Import brl.datastream
' Check if we're using HTML5:
#If TARGET = "html5"
Import dom
Import "native/file_to_databuffer.js"
' External bindings (JavaScript):
Extern
' Functions:
' File-to-DataBuffer:
Function LoadFile:DataBuffer(F:File, B_Out:DataBuffer)="loadFile"
' DOM:
Function log:Void(e:Event) = "window.console.log"
Function log:Void(f:FileList) = "window.console.log"
Function log:Void(f:File) = "window.console.log"
'Function log:Void(o:Object) = "window.console.log"
' Classes:
Class File
' Fields:
Field lastModified:Int
Field lastModifiedDate:String
Field name:String
Field size:Int
Field fileName:String
Field fileSize:Int
Field type:String
End
Class FileList Extends DOMObject
' Fields:
Field length:Int
' Methods:
Method item:File(index:Int)
End
Class HTMLFileInputElement Extends HTMLInputElement = "HTMLInputElement"
' Fields:
Field files:FileList
End
Public
Class AllDataHolder
' Globals
Field AllDataList:String[]
End
' Classes:
Class EventRepeater Extends EventListener
' Constructor(s):
Method New(Callback:EventHandler)
Self.Callback = Callback
End
' Methods:
Method handleEvent:Int(event:Event)
Return Callback.HandleEvent(event)
End
' Fields:
Field Callback:EventHandler
End
' Functions:
Function AddFileRequester:HTMLFileInputElement(listener:EventListener, node:dom.Node)
Local input:= HTMLFileInputElement(document.createElement("input")) ' HTMLInputElement
input.type = "file"
input.addEventListener("change", listener)
node.appendChild(input)
Return input
End
Function AddButton:HTMLInputElement(name:String, listener:EventListener, node:dom.Node)
Local button:= document.createElement("input")
button.setAttribute("type", "button")
button.setAttribute("name", name)
button.setAttribute("value", name)
button.addEventListener("click", listener)
node.appendChild(button)
Return HTMLInputElement(button)
End
#Else
#Error "Please build this application with the HTML5 target."
#End
' Interfaces:
Interface EventHandler
' Methods:
Method HandleEvent:Int(event:Event)
End
' Classes:
Class FileApp Extends App Implements EventHandler
' Constant variable(s):
Const FILES_NEEDED:= 3
' Methods:
Method OnCreate:Int()
SetUpdateRate(30) ' 0 ' 60
Self.running = False
Self.filesQueued = 0
' This is a dummy object used to get around the limitations of DOM:
Self.repeater = New EventRepeater(Self)
Self.bodyNode = dom.Node(Element(document.getElementsByTagName("body").item(0)).getElementsByTagName("div").item(0))
Self.fileButtons = New HTMLFileInputElement[FILES_NEEDED]
Self.files = New DataBuffer[FILES_NEEDED] ' Self.fileButtons.Length
For Local I:= 0 Until fileButtons.Length ' FILES_NEEDED
Self.fileButtons[I] = AddFileRequester(repeater, bodyNode)
Next
#If CONFIG = "debug"
MakeRunButton()
#End
Return 0
End
'============ Start of the Event handler - how do I invoke a file requester associated
'============ with one of 'my buttons' (as opposed to the procedurally generated 'Browse'
'============ button ........... - Specifically trying to associate a file requester
'============ with the 'LoadMyMap' button.
Method HandleEvent:Int(event:Event)
Select event.type
Case "change"
Local fileButton:= GetFileButton(event.target)
If (fileButton <> Null And files.Length > filesQueued) Then
Local f:File = fileButton.files.item(0)
Print("New file: ~q" + f.name + "~q - " + f.size + " bytes")
files[filesQueued] = LoadFile(f, New DataBuffer())
filesQueued += 1
Endif
Case "click"
If (event.target = runButton) Then
'Local runButton:= Self.runButton
OnRunButtonPressed()
Else If (event.target = LoadMyMapButton)
OnLoadMyMapButtonPressed()
Else If (event.target = scaleUpButton)
OnScaleUpButtonPressed()
Else If (event.target = scaleDownButton)
OnScaleDownButtonPressed()
Endif
End Select
Return 1
End
Method OnFilesLoaded:Void()
If (runButton <> Null) Then
Return
Endif
'Calls to generate required buttons
'Note: Require Bool to do this ONCE
If generateButtons = 0
generateButtons = 1
MakeLoadMyMapButton()
MakeScaleUpButton()
MakeScaleDownButton()
Endif
End
'===============Load My Image in button
Method MakeLoadMyMapButton:Void()
LoadMyMapButton = AddButton("Load My Map", repeater, bodyNode)
Return
End
Method OnLoadMyMapButtonPressed:Void()
Print("Map Picker Button Pressed: TO DO, suss how to open a file browser to pick image from users device....")
'------------- Attempt to open a file browser
'Local fileButton:= GetFileButton(event.target)
'If (fileButton <> Null And files.Length > filesQueued) Then
' Local f:File = fileButton.files.item(0)
' Print("New file: ~q" + f.name + "~q - " + f.size + " bytes")
' files[filesQueued] = LoadFile(f, New DataBuffer())
' filesQueued += 1
'Endif
'===============map out button
Return
End
Method OnScaleUpButtonPressed:Void()
If ScaleFloat <= 20 Then ScaleFloat = ScaleFloat+0.2
Print("Scale Up Button Pressed: ")+ScaleFloat
Return
End
Method OnScaleDownButtonPressed:Void()
If ScaleFloat >= 0.2 Then ScaleFloat = ScaleFloat-0.2
If ScaleFloat <= 0.2 Then ScaleFloat = ScaleFloat-0.05
Print("Scale Down Button Pressed: ")+ScaleFloat
Return
End
Method MakeScaleUpButton:Void()
'If (scaleUpButton <> Null) Then
' Return
'Endif
scaleUpButton = AddButton("Zoom Image In", repeater, bodyNode)
Return
End
Method MakeScaleDownButton:Void()
'If (scaleDownButton <> Null) Then
' Return
'Endif
scaleDownButton = AddButton("Zoom Image Out", repeater, bodyNode)
Return
End
Method OnRunButtonPressed:Void()
If (running Or Not AllFilesLoaded) Then
Return
Endif
running = True
Print("Starting the application properly.")
Return
End
Method MakeRunButton:Void()
If (runButton <> Null) Then
Return
Endif
runButton = AddButton("Show the data racing", repeater, bodyNode)
Return
End
Method GetFileButton:HTMLFileInputElement(target:EventTarget)
For Local I:= 0 Until fileButtons.Length
If (fileButtons[I] = target) Then ' EventTarget(...)
Return fileButtons[I]
Endif
Next
Return Null
End
Method OnUpdate:Int()
If (Not running) Then
If (AllFilesLoaded) Then
OnFilesLoaded() 'calling the readOnce within OnFilesLoaded.....
Endif
Return 0
Endif
If (MouseHit(MOUSE_LEFT)) Then
'If (Not readOnce)
'ReadLoadedFiles()
'If readOnce=True
'Print "returned from ReadLoaded Files, readOnce is: TRUE"
'Endif
'If (Not running)
'Print("Parsing Files Now.... Please Wait.")
'ParseLoadedFiles()
'DebugParsedFiles()
'Else
' Print ("Already parsed loaded files...")
' Print ("So what is calling the parser again....")
'Endif
'Endif
DrawText("Detected left mouse hit",8.0,32.0)
Endif
If (running And readOnce)
DisplayParsedFiles()
'Print "Called DisplayParsedFiles()..."
Else
If running
Print ("DEBUG: running is: TRUE")
Else
Print("DEBUG: runing is FALSE")
Endif
If readOnce
Print ("DEBUG: readonce is TRUE")
Else
Print ("DEBUG: readonce is FALSE")
Endif
Endif
Return 0
End
Method OnRender:Int()
Cls()
'###########################
'this is the issue I have with footprints - the rendering of the square has to happen here!!!!
'no biggy really.....
'2 Nov 16: sorting footprints to go in correct cardinal directions
'##########################
Local i:Int = 1
Local xarray:Int[5000]
Local yarray:Int[5000]
Local xct:Int = 1
Local yct:Int = 1
Local plotredfoots:Int = 1
Local howlong:Int = 1
If (Not running) Then
If (AllFilesLoaded) Then
DrawText("All files have been loaded.", 8.0, 8.0)
DrawText("Now to attempt to load and display an image for subsequent manipulation", 8.0, 19.0)
Endif
DrawImage map,xmap,ymap,MapRotate,MapZoom,MapZoom
Return 0
Else
' This basically never happens.
DrawText("Waiting for TCX files to be uploaded / imported; " + FilesCompleted + " completed.", 8.0, 8.0)
Endif
Return 0
End
Method ReadLoadedFiles:Void()
For Local I:= 0 Until files.Length
Local buffer:= files[I]
Local inputStream:= New DataStream(buffer)
Print("")
Print("Parsing file #" + (I+1) + ":")
Print("Last file length was:" +(lastNumberOfLines))
Print("")
While (Not inputStream.Eof())
' Read the current line.
Local line:= inputStream.ReadLine()
'Print("Line: " + line)
'Print(" 1_3_5_7_9_1_3_5_9_1_3_5_9_1_3_5_9")
'Copy line into an array for parsing
AllDataList = AllDataList.Resize(AllDataList.Length() + 1)
AllDataList[AllDataList.Length() - 1] = line
numberOfLines = numberOfLines + 1
'required to store where file 2 and file 3 start within the AllDataList buffer
lastNumberOfLines = numberOfLines
If I = 0
fileOneEnd = numberOfLines
Endif
If I = 1
fileTwoEnd = numberOfLines
Endif
If I = 2
fileThreeEnd = numberOfLines
endif
Wend
inputStream.Close()
Print "fileEndCounts -----------"
Print "fileOneEnd = " + fileOneEnd
Print "fileTwoEnd = " + fileTwoEnd
Print "fileThreeEnd = " + fileThreeEnd
readOnce = True
Next
Print(" ")
Print("========== End of parsing files===========")
Print(" Number of lines read: "+numberOfLines)
Print(" ")
If readOnce=True
Print ("In ReadLoadedFiles: readOnce is TRUE")
Endif
Return
End
Method ParseLoadedFiles:Void()
End
Method DisplayParsedFiles:Void()
'debug
'If displayOnce
End Method
Method AllFilesLoaded:Bool() Property
Return ((filesQueued = FILES_NEEDED) And FileBuffersLoaded)
End
Method FileBuffersLoaded:Bool() Property
For Local I:= 0 Until files.Length
Local file:= files[I]
If (file <> Null And file.Length = 0) Then
Return False
Endif
Next
Return True
End
Method FilesCompleted:Int() Property
Local count:= 0
For Local I:= 0 Until files.Length
Local file:= files[I]
If (file <> Null And file.Length <> 0) Then
count += 1
Endif
Next
Return count
End
'======================================================
' Fields
'======================================================
Field fileButtons:HTMLFileInputElement[]
Field runButton:HTMLInputElement
Field scaleUpButton:HTMLInputElement
Field scaleDownButton:HTMLInputElement
Field LoadMyMapButton:HTMLInputElement
Field running:Bool
Field readOnce:Bool
Field generateButtons:Int = 0
Field AllDataList:String[]
Field quitButton:HTMLInputElement
Field bodyNode:dom.Node
Field files:DataBuffer[]
Field filesQueued:Int
Field repeater:EventRepeater
'Image Vars
Field map:Image
Global MapSwitch:Int=0
Global MapRotate:Float=0.0
Global MapZoom:Float=1.0
Global xmap:Int=40
Global ymap:Int=40
Global ScaleFloat:Float=1.0
End
' Functions:
Function Main:Int()
New FileApp()
Return 0
End
you'll need to create a 'native' directory, at the same level as your monkey.data folder, with the following javascript function (file_to_databuffer.js) in it :--
function loadFile(file, buf)
{
var reader = new FileReader();
reader.onloadend = function ()
{
var rawData = reader.result;
if (rawData == null)
{
return;
}
buf._Init(rawData);
}
reader.readAsArrayBuffer(file);
return buf
}
The 'LoadMyMap' button doesn't do as advertised just yet - if anyone can help with this it'd be appreciated ;) |
| ||
| bookmarked, will look at it when i hit that point thanks for posting this. |