From 75231fec39f00578a75f0e075fc826d6238ca240 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Fri, 25 Oct 2013 21:16:03 +0100 Subject: [PATCH] Add browse and dropzone widgets We're splitting out the two aspects of the old import widget --- core/modules/new_widgets/browse.js | 77 +++++++++++++ core/modules/new_widgets/dropzone.js | 159 +++++++++++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 core/modules/new_widgets/browse.js create mode 100644 core/modules/new_widgets/dropzone.js diff --git a/core/modules/new_widgets/browse.js b/core/modules/new_widgets/browse.js new file mode 100644 index 000000000..7005ad3f8 --- /dev/null +++ b/core/modules/new_widgets/browse.js @@ -0,0 +1,77 @@ +/*\ +title: $:/core/modules/new_widgets/browse.js +type: application/javascript +module-type: new_widget + +Browse widget for browsing for files to import + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/new_widgets/widget.js").widget; + +var BrowseWidget = function(parseTreeNode,options) { + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +BrowseWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +BrowseWidget.prototype.render = function(parent,nextSibling) { + var self = this; + // Remember parent + this.parentDomNode = parent; + // Compute attributes and execute state + this.computeAttributes(); + this.execute(); + // Create element + var domNode = this.document.createElement("input"); + domNode.setAttribute("type","file"); + // Add a click event handler + domNode.addEventListener("change",function (event) { + self.wiki.readFiles(event.target.files,function(tiddlerFields) { + self.dispatchEvent({type: "tw-import-tiddlers", param: JSON.stringify([tiddlerFields])}); + }); + return false; + },false); + // Insert element + parent.insertBefore(domNode,nextSibling); + this.renderChildren(domNode,null); + this.domNodes.push(domNode); +}; + +/* +Compute the internal state of the widget +*/ +BrowseWidget.prototype.execute = function() { +}; + +/* +Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering +*/ +BrowseWidget.prototype.refresh = function(changedTiddlers) { + return false; +}; + +/* +Remove any DOM nodes created by this widget or its children +*/ +BrowseWidget.prototype.removeChildDomNodes = function() { + $tw.utils.each(this.domNodes,function(domNode) { + domNode.parentNode.removeChild(domNode); + }); + this.domNodes = []; +}; + +exports.browse = BrowseWidget; + +})(); diff --git a/core/modules/new_widgets/dropzone.js b/core/modules/new_widgets/dropzone.js new file mode 100644 index 000000000..df450fa33 --- /dev/null +++ b/core/modules/new_widgets/dropzone.js @@ -0,0 +1,159 @@ +/*\ +title: $:/core/modules/new_widgets/dropzone.js +type: application/javascript +module-type: new_widget + +Dropzone widget + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/new_widgets/widget.js").widget; + +var DropZoneWidget = function(parseTreeNode,options) { + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +DropZoneWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +DropZoneWidget.prototype.render = function(parent,nextSibling) { + var self = this; + // Remember parent + this.parentDomNode = parent; + // Compute attributes and execute state + this.computeAttributes(); + this.execute(); + // Create element + var domNode = this.document.createElement("div"); + domNode.className = "tw-dropzone"; + // Add event handlers + $tw.utils.addEventListeners(domNode,[ + {name: "dragenter", handlerObject: this, handlerMethod: "handleDragEnterEvent"}, + {name: "dragover", handlerObject: this, handlerMethod: "handleDragOverEvent"}, + {name: "dragleave", handlerObject: this, handlerMethod: "handleDragLeaveEvent"}, + {name: "drop", handlerObject: this, handlerMethod: "handleDropEvent"}, + {name: "paste", handlerObject: this, handlerMethod: "handlePasteEvent"} + ]); + domNode.addEventListener("click",function (event) { + },false); + // Insert element + parent.insertBefore(domNode,nextSibling); + this.renderChildren(domNode,null); + this.domNodes.push(domNode); +}; + +DropZoneWidget.prototype.handleDragEnterEvent = function(event) { + // We count enter/leave events + this.dragEnterCount = (this.dragEnterCount || 0) + 1; + // If we're entering for the first time we need to apply highlighting + if(this.dragEnterCount === 1) { + $tw.utils.addClass(this.domNodes[0],"tw-dragover"); + } + // Tell the browser that we're ready to handle the drop + event.preventDefault(); + // Tell the browser not to ripple the drag up to any parent drop handlers + event.stopPropagation(); +}; + +DropZoneWidget.prototype.handleDragOverEvent = function(event) { + // Tell the browser that we're still interested in the drop + event.preventDefault(); + event.dataTransfer.dropEffect = "copy"; // Explicitly show this is a copy +}; + +DropZoneWidget.prototype.handleDragLeaveEvent = function(event) { + // Reduce the enter count + this.dragEnterCount = (this.dragEnterCount || 0) - 1; + // Remove highlighting if we're leaving externally + if(this.dragEnterCount <= 0) { + $tw.utils.removeClass(this.domNodes[0],"tw-dragover"); + } +}; + +DropZoneWidget.prototype.handleDropEvent = function(event) { + var self = this, + dataTransfer = event.dataTransfer; + // Reset the enter count + this.dragEnterCount = 0; + // Remove highlighting + $tw.utils.removeClass(this.domNodes[0],"tw-dragover"); + // Try to import the various data types we understand +// this.importData(dataTransfer); + // Import any files in the drop + this.wiki.readFiles(dataTransfer.files,function(tiddlerFields) { + self.dispatchEvent({type: "tw-import-tiddlers", param: JSON.stringify([tiddlerFields])}); + }); + // Tell the browser that we handled the drop + event.preventDefault(); + // Stop the drop ripple up to any parent handlers + event.stopPropagation(); +}; + +DropZoneWidget.prototype.handlePasteEvent = function(event) { + // 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, + items = event.clipboardData.items; + // Enumerate the clipboard items + for(var t = 0; t