Allow manual selection of deserializer for dropping or importing files

This commit is contained in:
Jermolene 2017-07-12 16:42:16 +01:00
parent 41b6c5c088
commit 596dfa1d50
4 changed files with 51 additions and 19 deletions

View File

@ -1220,10 +1220,14 @@ $tw.Wiki.prototype.processSafeMode = function() {
/*
Extracts tiddlers from a typed block of text, specifying default field values
*/
$tw.Wiki.prototype.deserializeTiddlers = function(type,text,srcFields) {
$tw.Wiki.prototype.deserializeTiddlers = function(type,text,srcFields,options) {
srcFields = srcFields || Object.create(null);
var deserializer = $tw.Wiki.tiddlerDeserializerModules[type],
options = options || {};
var deserializer = $tw.Wiki.tiddlerDeserializerModules[options.deserializer],
fields = Object.create(null);
if(!deserializer) {
deserializer = $tw.Wiki.tiddlerDeserializerModules[type];
}
if(!deserializer && $tw.utils.getFileExtensionInfo(type)) {
// If we didn't find the serializer, try converting it from an extension to a content type
type = $tw.utils.getFileExtensionInfo(type).type;

View File

@ -104,7 +104,10 @@ DropZoneWidget.prototype.handleDragLeaveEvent = function(event) {
};
DropZoneWidget.prototype.handleDropEvent = function(event) {
var self = this;
var self = this,
readFileCallback = function(tiddlerFieldsArray) {
self.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify(tiddlerFieldsArray)});
};
this.leaveDrag(event);
// Check for being over a TEXTAREA or INPUT
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) !== -1) {
@ -121,15 +124,14 @@ DropZoneWidget.prototype.handleDropEvent = function(event) {
// Import any files in the drop
var numFiles = 0;
if(dataTransfer.files) {
numFiles = this.wiki.readFiles(dataTransfer.files,function(tiddlerFieldsArray) {
self.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify(tiddlerFieldsArray)});
numFiles = this.wiki.readFiles(dataTransfer.files,{
callback: readFileCallback,
deserializer: this.dropzoneDeserializer
});
}
// Try to import the various data types we understand
if(numFiles === 0) {
$tw.utils.importDataTransfer(dataTransfer,this.wiki.generateNewTitle("Untitled"),function(fieldsArray) {
self.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify(fieldsArray)});
});
$tw.utils.importDataTransfer(dataTransfer,this.wiki.generateNewTitle("Untitled"),readFileCallback);
}
// Tell the browser that we handled the drop
event.preventDefault();
@ -138,6 +140,10 @@ DropZoneWidget.prototype.handleDropEvent = function(event) {
};
DropZoneWidget.prototype.handlePasteEvent = function(event) {
var self = this,
readFileCallback = function(tiddlerFieldsArray) {
self.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify(tiddlerFieldsArray)});
};
// Let the browser handle it if we're in a textarea or input box
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) == -1) {
var self = this,
@ -147,8 +153,9 @@ DropZoneWidget.prototype.handlePasteEvent = function(event) {
var item = items[t];
if(item.kind === "file") {
// Import any files
this.wiki.readFile(item.getAsFile(),function(tiddlerFieldsArray) {
self.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify(tiddlerFieldsArray)});
this.wiki.readFile(item.getAsFile(),{
callback: readFileCallback,
deserializer: this.dropzoneDeserializer
});
} else if(item.kind === "string") {
// Create tiddlers from string items
@ -176,6 +183,7 @@ DropZoneWidget.prototype.handlePasteEvent = function(event) {
Compute the internal state of the widget
*/
DropZoneWidget.prototype.execute = function() {
this.dropzoneDeserializer = this.getAttribute("deserializer");
// Make child widgets
this.makeChildWidgets();
};

View File

@ -1125,16 +1125,24 @@ exports.checkTiddlerText = function(title,targetText,options) {
/*
Read an array of browser File objects, invoking callback(tiddlerFieldsArray) once they're all read
*/
exports.readFiles = function(files,callback) {
exports.readFiles = function(files,options) {
var callback;
if(typeof options === "function") {
callback = options;
options = {};
} else {
callback = options.callback;
}
var result = [],
outstanding = files.length;
for(var f=0; f<files.length; f++) {
this.readFile(files[f],function(tiddlerFieldsArray) {
outstanding = files.length,
readFileCallback = function(tiddlerFieldsArray) {
result.push.apply(result,tiddlerFieldsArray);
if(--outstanding === 0) {
callback(result);
}
});
};
for(var f=0; f<files.length; f++) {
this.readFile(files[f],Object.assign({},options,{callback: readFileCallback}));
}
return files.length;
};
@ -1142,7 +1150,14 @@ exports.readFiles = function(files,callback) {
/*
Read a browser File object, invoking callback(tiddlerFieldsArray) with an array of tiddler fields objects
*/
exports.readFile = function(file,callback) {
exports.readFile = function(file,options) {
var callback;
if(typeof options === "function") {
callback = options;
options = {};
} else {
callback = options.callback;
}
// Get the type, falling back to the filename extension
var self = this,
type = file.type;
@ -1183,7 +1198,7 @@ exports.readFile = function(file,callback) {
});
} else {
// Otherwise, just try to deserialise any tiddlers in the file
callback(self.deserializeTiddlers(type,text,tiddlerFields));
callback(self.deserializeTiddlers(type,text,tiddlerFields,{deserializer: options.deserializer}));
}
};
// Kick off the read

View File

@ -1,6 +1,6 @@
caption: dropzone
created: 20131024141900000
modified: 20170328173334805
modified: 20170712153850528
tags: Widgets
title: DropzoneWidget
type: text/vnd.tiddlywiki
@ -13,7 +13,12 @@ It sends a [[WidgetMessage: tm-import-tiddlers]] carrying a JSON representation
! Content and Attributes
The dropzone widget has no attributes, and displays any contained content within the dropzone.
|!Attribute |!Description |
|deserializer |Optional name of deserializer to be used (by default the deserializer is derived from the file extension) |
The list of available deserializers can be inspected by executing `Object.keys($tw.Wiki.tiddlerDeserializerModules).sort().join("\n")` in the browser JavaScript console.
The dropzone widget displays any contained content within the dropzone.
! Display