This commit is contained in:
Simon Huber 2024-04-25 23:45:33 +08:00 committed by GitHub
commit 1bd4e5efc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 150 additions and 121 deletions

View File

@ -30,122 +30,130 @@ exports.makeDraggable = function(options) {
if(!options.selector && ((domNode.tagName || "").toLowerCase() !== "a")) {
domNode.setAttribute("draggable","true");
}
// Add event handlers
$tw.utils.addEventListeners(domNode,[
{name: "dragstart", handlerFunction: function(event) {
if(event.dataTransfer === undefined) {
return false;
var dragStartHandlerFunction = function(event) {
if(event.dataTransfer === undefined) {
return false;
}
// Collect the tiddlers being dragged
var dragTiddler = options.dragTiddlerFn && options.dragTiddlerFn(),
dragFilter = options.dragFilterFn && options.dragFilterFn(),
titles = dragTiddler ? [dragTiddler] : [],
startActions = options.startActions,
variables,
domNodeRect;
if(dragFilter) {
titles.push.apply(titles,options.widget.wiki.filterTiddlers(dragFilter,options.widget));
}
var titleString = $tw.utils.stringifyList(titles);
// Check that we've something to drag
if(titles.length > 0 && (options.selector && $tw.utils.domMatchesSelector(event.target,options.selector) || event.target === domNode)) {
// Mark the drag in progress
$tw.dragInProgress = domNode;
// Set the dragging class on the element being dragged
$tw.utils.addClass(domNode,"tc-dragging");
// Invoke drag-start actions if given
if(startActions !== undefined) {
// Collect our variables
variables = $tw.utils.collectDOMVariables(domNode,null,event);
variables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event);
variables["actionTiddler"] = titleString;
options.widget.invokeActionString(startActions,options.widget,event,variables);
}
// 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 = "all";
if(dataTransfer.setDragImage) {
if(dragImageType === "pill") {
dataTransfer.setDragImage(dragImage.firstChild,-16,-16);
} else if(dragImageType === "blank") {
dragImage.removeChild(dragImage.firstChild);
dataTransfer.setDragImage(dragImage,0,0);
} else {
var r = domNode.getBoundingClientRect();
dataTransfer.setDragImage(domNode,event.clientX-r.left,event.clientY-r.top);
}
}
// Set up the data transfer
if(dataTransfer.clearData) {
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));
}
// If browser is Chrome-like and has a touch-input device do NOT .setData
if(!($tw.browser.isMobileChrome)) {
dataTransfer.setData("URL","data:text/vnd.tiddler," + encodeURIComponent(jsonData));
}
dataTransfer.setData("Text",titleString);
event.stopPropagation();
}
return false;
};
var dragEndHandlerFunction = function(event) {
if((options.selector && $tw.utils.domMatchesSelector(event.target,options.selector)) || event.target === domNode) {
// Collect the tiddlers being dragged
var dragTiddler = options.dragTiddlerFn && options.dragTiddlerFn(),
dragFilter = options.dragFilterFn && options.dragFilterFn(),
titles = dragTiddler ? [dragTiddler] : [],
startActions = options.startActions,
variables,
domNodeRect;
endActions = options.endActions,
variables;
if(dragFilter) {
titles.push.apply(titles,options.widget.wiki.filterTiddlers(dragFilter,options.widget));
}
var titleString = $tw.utils.stringifyList(titles);
// Check that we've something to drag
if(titles.length > 0 && (options.selector && $tw.utils.domMatchesSelector(event.target,options.selector) || event.target === domNode)) {
// Mark the drag in progress
$tw.dragInProgress = domNode;
// Set the dragging class on the element being dragged
$tw.utils.addClass(domNode,"tc-dragging");
// Invoke drag-start actions if given
if(startActions !== undefined) {
// Collect our variables
variables = $tw.utils.collectDOMVariables(domNode,null,event);
variables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event);
variables["actionTiddler"] = titleString;
options.widget.invokeActionString(startActions,options.widget,event,variables);
}
// 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 = "all";
if(dataTransfer.setDragImage) {
if(dragImageType === "pill") {
dataTransfer.setDragImage(dragImage.firstChild,-16,-16);
} else if(dragImageType === "blank") {
dragImage.removeChild(dragImage.firstChild);
dataTransfer.setDragImage(dragImage,0,0);
} else {
var r = domNode.getBoundingClientRect();
dataTransfer.setDragImage(domNode,event.clientX-r.left,event.clientY-r.top);
}
}
// Set up the data transfer
if(dataTransfer.clearData) {
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));
}
// If browser is Chrome-like and has a touch-input device do NOT .setData
if(!($tw.browser.isMobileChrome)) {
dataTransfer.setData("URL","data:text/vnd.tiddler," + encodeURIComponent(jsonData));
}
dataTransfer.setData("Text",titleString);
event.stopPropagation();
$tw.dragInProgress = null;
// Invoke drag-end actions if given
if(endActions !== undefined) {
variables = $tw.utils.collectDOMVariables(domNode,null,event);
variables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event);
variables["actionTiddler"] = titleString;
options.widget.invokeActionString(endActions,options.widget,event,variables);
}
return false;
}},
{name: "dragend", handlerFunction: function(event) {
if((options.selector && $tw.utils.domMatchesSelector(event.target,options.selector)) || event.target === domNode) {
// Collect the tiddlers being dragged
var dragTiddler = options.dragTiddlerFn && options.dragTiddlerFn(),
dragFilter = options.dragFilterFn && options.dragFilterFn(),
titles = dragTiddler ? [dragTiddler] : [],
endActions = options.endActions,
variables;
if(dragFilter) {
titles.push.apply(titles,options.widget.wiki.filterTiddlers(dragFilter,options.widget));
}
var titleString = $tw.utils.stringifyList(titles);
$tw.dragInProgress = null;
// Invoke drag-end actions if given
if(endActions !== undefined) {
variables = $tw.utils.collectDOMVariables(domNode,null,event);
variables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event);
variables["actionTiddler"] = titleString;
options.widget.invokeActionString(endActions,options.widget,event,variables);
}
// Remove the dragging class on the element being dragged
$tw.utils.removeClass(domNode,"tc-dragging");
// Delete the drag image element
if(dragImage) {
dragImage.parentNode.removeChild(dragImage);
dragImage = null;
}
// Remove the dragging class on the element being dragged
$tw.utils.removeClass(domNode,"tc-dragging");
// Delete the drag image element
if(dragImage) {
dragImage.parentNode.removeChild(dragImage);
dragImage = null;
}
return false;
}}
}
return false;
};
// Add the EventListener references to the widget
options.widget.dragStartReference = dragStartHandlerFunction;
options.widget.dragEndReference = dragEndHandlerFunction;
// Add event handlers
$tw.utils.addEventListeners(domNode,[
{name: "dragstart", handlerFunction: dragStartHandlerFunction},
{name: "dragend", handlerFunction: dragEndHandlerFunction}
]);
};

View File

@ -27,8 +27,7 @@ DraggableWidget.prototype = new Widget();
Render this widget into the DOM
*/
DraggableWidget.prototype.render = function(parent,nextSibling) {
var self = this,
tag,
var tag,
domNode,
classes = [];
// Save the parent dom node
@ -60,19 +59,8 @@ DraggableWidget.prototype.render = function(parent,nextSibling) {
// Insert the node into the DOM and render any children
parent.insertBefore(domNode,nextSibling);
this.renderChildren(domNode,null);
// Add event handlers
if(this.dragEnable) {
$tw.utils.makeDraggable({
domNode: domNode,
dragTiddlerFn: function() {return self.getAttribute("tiddler");},
dragFilterFn: function() {return self.getAttribute("filter");},
startActions: self.startActions,
endActions: self.endActions,
dragImageType: self.dragImageType,
widget: this,
selector: self.dragHandleSelector
});
}
// Make the DOM node draggable if needed
this.makeDraggable(domNode);
this.domNodes.push(domNode);
};
@ -92,6 +80,30 @@ DraggableWidget.prototype.execute = function() {
this.makeChildWidgets();
};
/*
Make a DOM node draggable or remove the draggable attr and the EventListeners
*/
DraggableWidget.prototype.makeDraggable = function(domNode) {
var self = this;
if(this.dragEnable) {
// Add event handlers
$tw.utils.makeDraggable({
domNode: domNode,
dragTiddlerFn: function() {return self.getAttribute("tiddler");},
dragFilterFn: function() {return self.getAttribute("filter");},
startActions: self.startActions,
endActions: self.endActions,
dragImageType: self.dragImageType,
widget: this,
selector: self.dragHandleSelector
});
} else if(this.dragStartReference && this.dragEndReference) {
domNode.removeAttribute("draggable");
domNode.removeEventListener("dragstart",this.dragStartReference,false);
domNode.removeEventListener("dragend",this.dragEndReference,false);
}
};
DraggableWidget.prototype.updateDomNodeClasses = function() {
var domNodeClasses = this.domNodes[0].className.split(" "),
@ -114,10 +126,19 @@ 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.tag || changedAttributes.selector || changedAttributes.dragimagetype || changedAttributes.enable || changedAttributes.startactions || changedAttributes.endactions) {
if(changedAttributes.tag || changedAttributes.selector || changedAttributes.dragimagetype || changedAttributes.startactions || changedAttributes.endactions) {
this.refreshSelf();
return true;
} else {
if(changedAttributes.enable) {
this.dragEnable = this.getAttribute("enable","yes") === "yes";
this.makeDraggable(this.domNodes[0]);
if(!this.dragHandleSelector && this.dragEnable && !this.domNodes[0].classList.contains("tc-draggable")) {
this.domNodes[0].classList.add("tc-draggable");
} else if(!this.dragHandleSelector && !this.dragEnable && this.domNodes[0].classList.contains("tc-draggable")) {
this.domNodes[0].classList.remove("tc-draggable");
}
}
if(changedAttributes["class"]) {
this.updateDomNodeClasses();
}