/*\ title: $:/core/modules/widgets/import.js type: application/javascript module-type: widget Implements the import widget. ``` <$import> Import using the "browse..." button or drag files onto this text ``` \*/ (function(){ /*jslint node: true, browser: true */ /*global $tw: false */ "use strict"; var ImportWidget = function(renderer) { // Save state this.renderer = renderer; // Generate child nodes this.generate(); }; ImportWidget.prototype.generate = function() { // Get the parameters from the attributes this.browse = this.renderer.getAttribute("browse","yes"); this["class"] = this.renderer.getAttribute("class"); // Compute classes var classes = ["tw-import"]; if(this["class"]) { $tw.utils.pushTop(classes,this["class"]); } // Create the file input and container elements var fileInput = { type: "element", tag: "input", attributes: { type: {type: "string", value: "file"}, style: {type: "string", value: this.browse === "no" ? "display: none;" : "display: block;"} }, events: [{name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"}] }, container = { type: "element", tag: "div", children: this.renderer.parseTreeNode.children, events: [ {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"}] }; // Set the return element this.tag = "div"; this.attributes = { "class": classes.join(" ") }; this.children = this.renderer.renderTree.createRenderers(this.renderer,[fileInput,container]); }; ImportWidget.prototype.handleChangeEvent = function(event) { event.stopPropagation(); this.importFiles(event.target.files); }; ImportWidget.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.renderer.domNode,"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(); }; ImportWidget.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 }; ImportWidget.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.renderer.domNode,"tw-dragover"); } }; ImportWidget.prototype.handleDropEvent = function(event) { var dataTransfer = event.dataTransfer; // Reset the enter count this.dragEnterCount = 0; // Remove highlighting $tw.utils.removeClass(this.renderer.domNode,"tw-dragover"); // Try to import the various data types we understand this.importData(dataTransfer); // Import any files in the drop this.importFiles(dataTransfer.files); // Tell the browser that we handled the drop event.preventDefault(); // Stop the drop ripple up to any parent handlers event.stopPropagation(); }; ImportWidget.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