From 8f1114960a20ba3d84dd1633ad1976db9461a41c Mon Sep 17 00:00:00 2001 From: Jermolene Date: Thu, 23 Mar 2017 14:23:33 +0000 Subject: [PATCH] Refactor draggable stuff for easier reuse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And in the process, make the button widget draggable. Unfortunately, Firefox has a bug that prevents buttons from being dragged (see https://bugzilla.mozilla.org/show_bug.cgi?id=568313 and https://bugzilla.mozilla.org/show_bug.cgi?id=646823). So we have to use the “tag” attribute to make it use a different element. --- core/modules/utils/dom/datatransfer.js | 82 ------------ core/modules/utils/dom/dragndrop.js | 172 +++++++++++++++++++++++++ core/modules/widgets/button.js | 13 +- core/modules/widgets/draggable.js | 86 +------------ core/modules/widgets/link.js | 63 +-------- core/ui/TagTemplate.tid | 4 +- 6 files changed, 198 insertions(+), 222 deletions(-) delete mode 100644 core/modules/utils/dom/datatransfer.js create mode 100644 core/modules/utils/dom/dragndrop.js diff --git a/core/modules/utils/dom/datatransfer.js b/core/modules/utils/dom/datatransfer.js deleted file mode 100644 index de8dac46a..000000000 --- a/core/modules/utils/dom/datatransfer.js +++ /dev/null @@ -1,82 +0,0 @@ -/*\ -title: $:/core/modules/utils/dom/datatransfer.js -type: application/javascript -module-type: utils - -Browser data transfer utilities, used with the clipboard and drag and drop - -\*/ -(function(){ - -/*jslint node: true, browser: true */ -/*global $tw: false */ -"use strict"; - -exports.importDataTransfer = function(dataTransfer,fallbackTitle,callback) { - // Try each provided data type in turn - for(var t=0; t 0 && event.target === domNode) { + // Mark the drag in progress + $tw.dragInProgress = domNode; + // Set the dragging class on the element being dragged + $tw.utils.addClass(event.target,"tc-dragging"); + // Create the drag image elements + dragImage = options.widget.document.createElement("div"); + dragImage.className = "tc-tiddler-dragger"; + var inner = options.widget.document.createElement("div"); + inner.className = "tc-tiddler-dragger-inner"; + inner.appendChild(options.widget.document.createTextNode( + titles.length === 1 ? + titles[0] : + titles.length + " tiddlers" + )); + dragImage.appendChild(inner); + options.widget.document.body.appendChild(dragImage); + // Set the data transfer properties + var dataTransfer = event.dataTransfer; + // Set up the image + dataTransfer.effectAllowed = "copy"; + if(dataTransfer.setDragImage) { + dataTransfer.setDragImage(dragImage.firstChild,-16,-16); + } + // Set up the data transfer + dataTransfer.clearData(); + var jsonData = []; + if(titles.length > 1) { + titles.forEach(function(title) { + jsonData.push(options.widget.wiki.getTiddlerAsJson(title)); + }); + jsonData = "[" + jsonData.join(",") + "]"; + } else { + jsonData = options.widget.wiki.getTiddlerAsJson(titles[0]); + } + // IE doesn't like these content types + if(!$tw.browser.isIE) { + dataTransfer.setData("text/vnd.tiddler",jsonData); + dataTransfer.setData("text/plain",titleString); + dataTransfer.setData("text/x-moz-url","data:text/vnd.tiddler," + encodeURIComponent(jsonData)); + } + dataTransfer.setData("URL","data:text/vnd.tiddler," + encodeURIComponent(jsonData)); + dataTransfer.setData("Text",titleString); + event.stopPropagation(); + } else { + event.preventDefault(); + } + return false; + }}, + {name: "dragend", handlerFunction: function(event) { + if(event.target === domNode) { + $tw.dragInProgress = null; + // Remove the dragging class on the element being dragged + $tw.utils.removeClass(event.target,"tc-dragging"); + // Delete the drag image element + if(dragImage) { + dragImage.parentNode.removeChild(dragImage); + dragImage = null; + } + } + return false; + }} + ]); +}; + +exports.importDataTransfer = function(dataTransfer,fallbackTitle,callback) { + // Try each provided data type in turn + for(var t=0; t 0 && event.target === this.domNodes[0]) { - $tw.dragInProgress = this.domNodes[0]; - // Set the dragging class on the element being dragged - $tw.utils.addClass(event.target,"tc-dragging"); - // Create the drag image elements - this.dragImage = this.document.createElement("div"); - this.dragImage.className = "tc-tiddler-dragger"; - var inner = this.document.createElement("div"); - inner.className = "tc-tiddler-dragger-inner"; - inner.appendChild(this.document.createTextNode( - titles.length === 1 ? - titles[0] : - titles.length + " tiddlers" - )); - this.dragImage.appendChild(inner); - this.document.body.appendChild(this.dragImage); - // Set the data transfer properties - var dataTransfer = event.dataTransfer; - // Set up the image - dataTransfer.effectAllowed = "copy"; - if(dataTransfer.setDragImage) { - dataTransfer.setDragImage(this.dragImage.firstChild,-16,-16); - } - // Set up the data transfer - dataTransfer.clearData(); - var jsonData = []; - if(titles.length > 1) { - titles.forEach(function(title) { - jsonData.push(self.wiki.getTiddlerAsJson(title)); - }); - jsonData = "[" + jsonData.join(",") + "]"; - } else { - jsonData = this.wiki.getTiddlerAsJson(titles[0]); - } - // IE doesn't like these content types - if(!$tw.browser.isIE) { - dataTransfer.setData("text/vnd.tiddler",jsonData); - dataTransfer.setData("text/plain",titleString); - dataTransfer.setData("text/x-moz-url","data:text/vnd.tiddler," + encodeURIComponent(jsonData)); - } - dataTransfer.setData("URL","data:text/vnd.tiddler," + encodeURIComponent(jsonData)); - dataTransfer.setData("Text",titleString); - event.stopPropagation(); - } else { - event.preventDefault(); - } -}; - -DraggableWidget.prototype.handleDragEndEvent = function(event) { - if(event.target === this.domNodes[0]) { - $tw.dragInProgress = null; - // Remove the dragging class on the element being dragged - $tw.utils.removeClass(event.target,"tc-dragging"); - // Delete the drag image element - if(this.dragImage) { - this.dragImage.parentNode.removeChild(this.dragImage); - } - } -}; - /* Compute the internal state of the widget */ DraggableWidget.prototype.execute = function() { // Pick up our attributes - this.draggableTiddler = this.getAttribute("tiddler"); - this.draggableFilter = this.getAttribute("filter"); this.draggableTag = this.getAttribute("tag","div"); this.draggableClasses = this.getAttribute("class"); // Make the child widgets @@ -148,7 +76,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ DraggableWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.tiddler || changedTiddlers.tag || changedTiddlers["class"]) { + if(changedTiddlers.tag || changedTiddlers["class"]) { this.refreshSelf(); return true; } diff --git a/core/modules/widgets/link.js b/core/modules/widgets/link.js index 04c8edfbe..4d8b5cfc0 100755 --- a/core/modules/widgets/link.js +++ b/core/modules/widgets/link.js @@ -111,11 +111,13 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) { $tw.utils.addEventListeners(domNode,[ {name: "click", handlerObject: this, handlerMethod: "handleClickEvent"}, ]); + // Make the link draggable if required if(this.draggable === "yes") { - $tw.utils.addEventListeners(domNode,[ - {name: "dragstart", handlerObject: this, handlerMethod: "handleDragStartEvent"}, - {name: "dragend", handlerObject: this, handlerMethod: "handleDragEndEvent"} - ]); + $tw.utils.makeDraggable({ + domNode: domNode, + dragTiddlerFn: function() {return self.to;}, + widget: this + }); } // Insert the link into the DOM and render any children parent.insertBefore(domNode,nextSibling); @@ -142,59 +144,6 @@ LinkWidget.prototype.handleClickEvent = function(event) { return false; }; -LinkWidget.prototype.handleDragStartEvent = function(event) { - if(event.target === this.domNodes[0]) { - if(this.to) { - $tw.dragInProgress = this.domNodes[0]; - // Set the dragging class on the element being dragged - $tw.utils.addClass(event.target,"tc-tiddlylink-dragging"); - // Create the drag image elements - this.dragImage = this.document.createElement("div"); - this.dragImage.className = "tc-tiddler-dragger"; - var inner = this.document.createElement("div"); - inner.className = "tc-tiddler-dragger-inner"; - inner.appendChild(this.document.createTextNode(this.to)); - this.dragImage.appendChild(inner); - this.document.body.appendChild(this.dragImage); - // Set the data transfer properties - var dataTransfer = event.dataTransfer; - // First the image - dataTransfer.effectAllowed = "copy"; - if(dataTransfer.setDragImage) { - dataTransfer.setDragImage(this.dragImage.firstChild,-16,-16); - } - // Then the data - dataTransfer.clearData(); - var jsonData = this.wiki.getTiddlerAsJson(this.to), - textData = this.wiki.getTiddlerText(this.to,""), - title = (new RegExp("^" + $tw.config.textPrimitives.wikiLink + "$","mg")).exec(this.to) ? this.to : "[[" + this.to + "]]"; - // IE doesn't like these content types - if(!$tw.browser.isIE) { - dataTransfer.setData("text/vnd.tiddler",jsonData); - dataTransfer.setData("text/plain",title); - dataTransfer.setData("text/x-moz-url","data:text/vnd.tiddler," + encodeURIComponent(jsonData)); - } - dataTransfer.setData("URL","data:text/vnd.tiddler," + encodeURIComponent(jsonData)); - dataTransfer.setData("Text",title); - event.stopPropagation(); - } else { - event.preventDefault(); - } - } -}; - -LinkWidget.prototype.handleDragEndEvent = function(event) { - if(event.target === this.domNodes[0]) { - $tw.dragInProgress = null; - // Remove the dragging class on the element being dragged - $tw.utils.removeClass(event.target,"tc-tiddlylink-dragging"); - // Delete the drag image element - if(this.dragImage) { - this.dragImage.parentNode.removeChild(this.dragImage); - } - } -}; - /* Compute the internal state of the widget */ diff --git a/core/ui/TagTemplate.tid b/core/ui/TagTemplate.tid index f1a5a582a..243062be7 100644 --- a/core/ui/TagTemplate.tid +++ b/core/ui/TagTemplate.tid @@ -2,9 +2,7 @@ title: $:/core/ui/TagTemplate <$set name="transclusion" value=<>> -<$draggable tag="span" filter="[all[current]tagging[]]"> -<$macrocall $name="tag-pill-body" tag=<> icon={{!!icon}} colour={{!!color}} palette={{$:/palette}} element-tag="""$button""" element-attributes="""popup=<>"""/> - +<$macrocall $name="tag-pill-body" tag=<> icon={{!!icon}} colour={{!!color}} palette={{$:/palette}} element-tag="""$button""" element-attributes="""popup=<> dragFilter='[all[current]tagging[]]' tag='span'"""/> <$reveal state=<> type="popup" position="below" animate="yes" class="tc-drop-down"> <$transclude tiddler="$:/core/ui/ListItemTemplate"/> <$list filter="[all[shadows+tiddlers]tag[$:/tags/TagDropdown]!has[draft.of]]" variable="listItem">