mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-27 03:57:21 +00:00
Improve support for drag and drop
Documentation TBD
This commit is contained in:
parent
c2391c5250
commit
eba1c3c160
41
core/modules/filters/insertbefore.js
Normal file
41
core/modules/filters/insertbefore.js
Normal file
@ -0,0 +1,41 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/insertbefore.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Insert an item before another item in a list
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Order a list
|
||||
*/
|
||||
exports.insertbefore = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
var target = options.widget && options.widget.getVariable(operator.suffix || "currentTiddler");
|
||||
if(target && target !== operator.operand) {
|
||||
// Remove the entry from the list if it is present
|
||||
var pos = results.indexOf(operator.operand);
|
||||
if(pos !== -1) {
|
||||
results.splice(pos,1);
|
||||
}
|
||||
// Insert the entry before the target marker
|
||||
pos = results.indexOf(target);
|
||||
if(pos !== -1) {
|
||||
results.splice(pos,0,operator.operand);
|
||||
} else {
|
||||
results.push(operator.operand);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
94
core/modules/utils/dom/datatransfer.js
Normal file
94
core/modules/utils/dom/datatransfer.js
Normal file
@ -0,0 +1,94 @@
|
||||
/*\
|
||||
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<importDataTypes.length; t++) {
|
||||
if(!$tw.browser.isIE || importDataTypes[t].IECompatible) {
|
||||
// Get the data
|
||||
var dataType = importDataTypes[t];
|
||||
var data = dataTransfer.getData(dataType.type);
|
||||
// Import the tiddlers in the data
|
||||
if(data !== "" && data !== null) {
|
||||
if($tw.log.IMPORT) {
|
||||
console.log("Importing data type '" + dataType.type + "', data: '" + data + "'")
|
||||
}
|
||||
var tiddlerFields = dataType.toTiddlerFieldsArray(data,fallbackTitle);
|
||||
callback(tiddlerFields);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var importDataTypes = [
|
||||
{type: "text/vnd.tiddler", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {
|
||||
return parseJSONTiddlers(data,fallbackTitle);
|
||||
}},
|
||||
{type: "URL", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {
|
||||
// Check for tiddler data URI
|
||||
var match = decodeURIComponent(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
if(match) {
|
||||
return parseJSONTiddlers(match[1],fallbackTitle);
|
||||
} else {
|
||||
return { // As URL string
|
||||
text: data
|
||||
};
|
||||
}
|
||||
}},
|
||||
{type: "text/x-moz-url", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {
|
||||
// Check for tiddler data URI
|
||||
var match = decodeURIComponent(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
if(match) {
|
||||
return parseJSONTiddlers(match[1],fallbackTitle);
|
||||
} else {
|
||||
return { // As URL string
|
||||
text: data
|
||||
};
|
||||
}
|
||||
}},
|
||||
{type: "text/html", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}},
|
||||
{type: "text/plain", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}},
|
||||
{type: "Text", IECompatible: true, toTiddlerFieldsArray: function(data,fallbackTitle) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}},
|
||||
{type: "text/uri-list", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}}
|
||||
];
|
||||
|
||||
function parseJSONTiddlers(json,fallbackTitle) {
|
||||
var data = JSON.parse(json);
|
||||
if(!$tw.utils.isArray(data)) {
|
||||
data = [data];
|
||||
}
|
||||
data.forEach(function(fields) {
|
||||
fields.title = fields.title || fallbackTitle;
|
||||
});
|
||||
return data;
|
||||
};
|
||||
|
||||
})();
|
160
core/modules/widgets/draggable.js
Normal file
160
core/modules/widgets/draggable.js
Normal file
@ -0,0 +1,160 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/draggable.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Draggable widget
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var DraggableWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
DraggableWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
DraggableWidget.prototype.render = function(parent,nextSibling) {
|
||||
var self = this;
|
||||
// Save the parent dom node
|
||||
this.parentDomNode = parent;
|
||||
// Compute our attributes
|
||||
this.computeAttributes();
|
||||
// Execute our logic
|
||||
this.execute();
|
||||
// Sanitise the specified tag
|
||||
var tag = this.draggableTag;
|
||||
if($tw.config.htmlUnsafeElements.indexOf(tag) !== -1) {
|
||||
tag = "div";
|
||||
}
|
||||
// Create our element
|
||||
var domNode = this.document.createElement(tag);
|
||||
// Assign classes
|
||||
var classes = ["tc-draggable"];
|
||||
if(this.draggableClasses) {
|
||||
classes.push(this.draggableClasses);
|
||||
}
|
||||
domNode.setAttribute("class",classes.join(" "));
|
||||
domNode.setAttribute("draggable","true");
|
||||
// Add event handlers
|
||||
$tw.utils.addEventListeners(domNode,[
|
||||
{name: "dragstart", handlerObject: this, handlerMethod: "handleDragStartEvent"},
|
||||
{name: "dragend", handlerObject: this, handlerMethod: "handleDragEndEvent"}
|
||||
]);
|
||||
// Insert the link into the DOM and render any children
|
||||
parent.insertBefore(domNode,nextSibling);
|
||||
this.renderChildren(domNode,null);
|
||||
this.domNodes.push(domNode);
|
||||
};
|
||||
|
||||
DraggableWidget.prototype.handleDragStartEvent = function(event) {
|
||||
var self = this;
|
||||
// Collect the tiddlers
|
||||
var titles = [];
|
||||
if(this.draggableTiddler) {
|
||||
titles.push(this.draggableTiddler);
|
||||
}
|
||||
if(this.draggableFilter) {
|
||||
titles.push.apply(titles,this.wiki.filterTiddlers(this.draggableFilter,this));
|
||||
}
|
||||
var titleString = titles.join("\n");
|
||||
if(titles.length > 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
|
||||
this.makeChildWidgets();
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
DraggableWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.tiddler || changedTiddlers.tag || changedTiddlers["class"]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
}
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
};
|
||||
|
||||
exports.draggable = DraggableWidget;
|
||||
|
||||
})();
|
144
core/modules/widgets/droppable.js
Normal file
144
core/modules/widgets/droppable.js
Normal file
@ -0,0 +1,144 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/droppable.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Droppable widget
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var DroppableWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
DroppableWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
DroppableWidget.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 = "tc-droppable";
|
||||
// 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"}
|
||||
]);
|
||||
// Insert element
|
||||
parent.insertBefore(domNode,nextSibling);
|
||||
this.renderChildren(domNode,null);
|
||||
this.domNodes.push(domNode);
|
||||
// Stack of outstanding enter/leave events
|
||||
this.currentlyEntered = [];
|
||||
};
|
||||
|
||||
DroppableWidget.prototype.enterDrag = function(event) {
|
||||
if(this.currentlyEntered.indexOf(event.target) === -1) {
|
||||
this.currentlyEntered.push(event.target);
|
||||
}
|
||||
// If we're entering for the first time we need to apply highlighting
|
||||
$tw.utils.addClass(this.domNodes[0],"tc-dragover");
|
||||
};
|
||||
|
||||
DroppableWidget.prototype.leaveDrag = function(event) {
|
||||
var pos = this.currentlyEntered.indexOf(event.target);
|
||||
if(pos !== -1) {
|
||||
this.currentlyEntered.splice(pos,1);
|
||||
}
|
||||
// Remove highlighting if we're leaving externally. The hacky second condition is to resolve a problem with Firefox whereby there is an erroneous dragenter event if the node being dragged is within the dropzone
|
||||
if(this.currentlyEntered.length === 0 || (this.currentlyEntered.length === 1 && this.currentlyEntered[0] === $tw.dragInProgress)) {
|
||||
this.currentlyEntered = [];
|
||||
$tw.utils.removeClass(this.domNodes[0],"tc-dragover");
|
||||
}
|
||||
};
|
||||
|
||||
DroppableWidget.prototype.handleDragEnterEvent = function(event) {
|
||||
this.enterDrag(event);
|
||||
// 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();
|
||||
};
|
||||
|
||||
DroppableWidget.prototype.handleDragOverEvent = function(event) {
|
||||
// Check for being over a TEXTAREA or INPUT
|
||||
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) !== -1) {
|
||||
return false;
|
||||
}
|
||||
// Tell the browser that we're still interested in the drop
|
||||
event.preventDefault();
|
||||
event.dataTransfer.dropEffect = "copy"; // Explicitly show this is a copy
|
||||
};
|
||||
|
||||
DroppableWidget.prototype.handleDragLeaveEvent = function(event) {
|
||||
this.leaveDrag(event);
|
||||
};
|
||||
|
||||
DroppableWidget.prototype.handleDropEvent = function(event) {
|
||||
var self = this;
|
||||
this.leaveDrag(event);
|
||||
// Check for being over a TEXTAREA or INPUT
|
||||
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) !== -1) {
|
||||
return false;
|
||||
}
|
||||
var dataTransfer = event.dataTransfer;
|
||||
// Remove highlighting
|
||||
$tw.utils.removeClass(this.domNodes[0],"tc-dragover");
|
||||
// Try to import the various data types we understand
|
||||
$tw.utils.importDataTransfer(dataTransfer,null,function(fieldsArray) {
|
||||
fieldsArray.forEach(function(fields) {
|
||||
if(fields.title) {
|
||||
self.performActions(fields.title,event);
|
||||
}
|
||||
});
|
||||
});
|
||||
// Tell the browser that we handled the drop
|
||||
event.preventDefault();
|
||||
// Stop the drop ripple up to any parent handlers
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
DroppableWidget.prototype.performActions = function(title,event) {
|
||||
if(this.dropzoneActions) {
|
||||
this.invokeActionString(this.dropzoneActions,this,event,{actionTiddler: title});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
DroppableWidget.prototype.execute = function() {
|
||||
this.dropzoneActions = this.getAttribute("actions");
|
||||
// Make child widgets
|
||||
this.makeChildWidgets();
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
DroppableWidget.prototype.refresh = function(changedTiddlers) {
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
};
|
||||
|
||||
exports.droppable = DroppableWidget;
|
||||
|
||||
})();
|
@ -104,6 +104,7 @@ DropZoneWidget.prototype.handleDragLeaveEvent = function(event) {
|
||||
};
|
||||
|
||||
DropZoneWidget.prototype.handleDropEvent = function(event) {
|
||||
var self = this;
|
||||
this.leaveDrag(event);
|
||||
// Check for being over a TEXTAREA or INPUT
|
||||
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) !== -1) {
|
||||
@ -123,7 +124,9 @@ DropZoneWidget.prototype.handleDropEvent = function(event) {
|
||||
});
|
||||
// Try to import the various data types we understand
|
||||
if(numFiles === 0) {
|
||||
this.importData(dataTransfer);
|
||||
$tw.utils.importDataTransfer(dataTransfer,this.wiki.generateNewTitle("Untitled"),function(fieldsArray) {
|
||||
self.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify(fieldsArray)});
|
||||
});
|
||||
}
|
||||
// Tell the browser that we handled the drop
|
||||
event.preventDefault();
|
||||
@ -131,77 +134,6 @@ DropZoneWidget.prototype.handleDropEvent = function(event) {
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
DropZoneWidget.prototype.importData = function(dataTransfer) {
|
||||
// Try each provided data type in turn
|
||||
for(var t=0; t<this.importDataTypes.length; t++) {
|
||||
if(!$tw.browser.isIE || this.importDataTypes[t].IECompatible) {
|
||||
// Get the data
|
||||
var dataType = this.importDataTypes[t];
|
||||
var data = dataTransfer.getData(dataType.type);
|
||||
// Import the tiddlers in the data
|
||||
if(data !== "" && data !== null) {
|
||||
if($tw.log.IMPORT) {
|
||||
console.log("Importing data type '" + dataType.type + "', data: '" + data + "'")
|
||||
}
|
||||
var tiddlerFields = dataType.convertToFields(data);
|
||||
if(!tiddlerFields.title) {
|
||||
tiddlerFields.title = this.wiki.generateNewTitle("Untitled");
|
||||
}
|
||||
this.dispatchEvent({type: "tm-import-tiddlers", param: JSON.stringify([tiddlerFields])});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DropZoneWidget.prototype.importDataTypes = [
|
||||
{type: "text/vnd.tiddler", IECompatible: false, convertToFields: function(data) {
|
||||
return JSON.parse(data);
|
||||
}},
|
||||
{type: "URL", IECompatible: true, convertToFields: function(data) {
|
||||
// Check for tiddler data URI
|
||||
var match = decodeURIComponent(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
if(match) {
|
||||
return JSON.parse(match[1]);
|
||||
} else {
|
||||
return { // As URL string
|
||||
text: data
|
||||
};
|
||||
}
|
||||
}},
|
||||
{type: "text/x-moz-url", IECompatible: false, convertToFields: function(data) {
|
||||
// Check for tiddler data URI
|
||||
var match = decodeURIComponent(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
if(match) {
|
||||
return JSON.parse(match[1]);
|
||||
} else {
|
||||
return { // As URL string
|
||||
text: data
|
||||
};
|
||||
}
|
||||
}},
|
||||
{type: "text/html", IECompatible: false, convertToFields: function(data) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}},
|
||||
{type: "text/plain", IECompatible: false, convertToFields: function(data) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}},
|
||||
{type: "Text", IECompatible: true, convertToFields: function(data) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}},
|
||||
{type: "text/uri-list", IECompatible: false, convertToFields: function(data) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}}
|
||||
];
|
||||
|
||||
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) {
|
||||
|
@ -145,7 +145,7 @@ LinkWidget.prototype.handleClickEvent = function(event) {
|
||||
LinkWidget.prototype.handleDragStartEvent = function(event) {
|
||||
if(event.target === this.domNodes[0]) {
|
||||
if(this.to) {
|
||||
$tw.dragInProgress = true;
|
||||
$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
|
||||
@ -185,7 +185,7 @@ LinkWidget.prototype.handleDragStartEvent = function(event) {
|
||||
|
||||
LinkWidget.prototype.handleDragEndEvent = function(event) {
|
||||
if(event.target === this.domNodes[0]) {
|
||||
$tw.dragInProgress = false;
|
||||
$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
|
||||
|
@ -512,7 +512,7 @@ Widget.prototype.invokeActions = function(triggeringWidget,event) {
|
||||
/*
|
||||
Invoke the action widgets defined in a string
|
||||
*/
|
||||
Widget.prototype.invokeActionString = function(actions,triggeringWidget,event) {
|
||||
Widget.prototype.invokeActionString = function(actions,triggeringWidget,event,variables) {
|
||||
actions = actions || "";
|
||||
var parser = this.wiki.parseText("text/vnd.tiddlywiki",actions,{
|
||||
parentWidget: this,
|
||||
@ -520,7 +520,8 @@ Widget.prototype.invokeActionString = function(actions,triggeringWidget,event) {
|
||||
}),
|
||||
widgetNode = this.wiki.makeWidget(parser,{
|
||||
parentWidget: this,
|
||||
document: this.document
|
||||
document: this.document,
|
||||
variables: variables
|
||||
});
|
||||
var container = this.document.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
|
@ -3,10 +3,22 @@ tags: $:/tags/SideBar
|
||||
caption: {{$:/language/SideBar/Open/Caption}}
|
||||
|
||||
\define lingo-base() $:/language/CloseAll/
|
||||
|
||||
\define drop-actions()
|
||||
<$action-listops $tiddler="$:/StoryList" $subfilter="+[insertbefore:currentTiddler<actionTiddler>]"/>
|
||||
\end
|
||||
|
||||
<$list filter="[list[$:/StoryList]]" history="$:/HistoryList" storyview="pop">
|
||||
|
||||
<div style="position: relative;">
|
||||
<$droppable actions=<<drop-actions>>>
|
||||
<div class="tc-droppable-placeholder">
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<$button message="tm-close-tiddler" tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class="tc-btn-invisible tc-btn-mini">×</$button> <$link to={{!!title}}><$view field="title"/></$link>
|
||||
|
||||
</div>
|
||||
</$droppable>
|
||||
</div>
|
||||
</$list>
|
||||
|
||||
<$button message="tm-close-all-tiddlers" class="tc-btn-invisible tc-btn-mini"><<lingo Button>></$button>
|
||||
|
@ -1,6 +1,24 @@
|
||||
title: $:/core/ui/TagTemplate
|
||||
|
||||
\define drop-actions()
|
||||
<!-- Save the current ordering of the tiddlers with this tag -->
|
||||
<$set name="order" filter="[<tag>tagging[]]">
|
||||
<!-- Remove any list-after or list-before fields from the tiddlers with this tag -->
|
||||
<$list filter="[<tag>tagging[]]">
|
||||
<$action-deletefield $field="list-before"/>
|
||||
<$action-deletefield $field="list-after"/>
|
||||
</$list>
|
||||
<!-- Assign the list field of the tag with the current ordering -->
|
||||
<$action-setfield $tiddler=<<tag>> $field="list" $value=<<order>>/>
|
||||
<!-- Add the newly inserted item to the list -->
|
||||
<$action-listops $tiddler=<<tag>> $field="list" $subfilter="+[insertbefore:currentTiddler<actionTiddler>]"/>
|
||||
<!-- Make sure the newly added item has the right tag -->
|
||||
<$action-listops $tiddler=<<actionTiddler>> $field="tags" $subfilter="+[<tag>]"/>
|
||||
</$set>
|
||||
\end
|
||||
|
||||
<span class="tc-tag-list-item">
|
||||
<$draggable tag="span" filter="[all[current]tagging[]]">
|
||||
<$set name="transclusion" value=<<currentTiddler>>>
|
||||
<$macrocall $name="tag-pill-body" tag=<<currentTiddler>> icon={{!!icon}} colour={{!!color}} palette={{$:/palette}} element-tag="""$button""" element-attributes="""popup=<<qualify "$:/state/popup/tag">>"""/>
|
||||
<$reveal state=<<qualify "$:/state/popup/tag">> type="popup" position="below" animate="yes" class="tc-drop-down">
|
||||
@ -9,7 +27,23 @@ title: $:/core/ui/TagTemplate
|
||||
<$transclude tiddler=<<listItem>>/>
|
||||
</$list>
|
||||
<hr>
|
||||
<$list filter="[all[current]tagging[]]" template="$:/core/ui/ListItemTemplate"/>
|
||||
<$set name="tag" value=<<currentTiddler>>>
|
||||
<$list filter="[all[current]tagging[]]">
|
||||
<div class="tc-menu-list-item" style="position: relative;">
|
||||
<$droppable actions=<<drop-actions>>>
|
||||
<div class="tc-droppable-placeholder">
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<$link to={{!!title}}>
|
||||
<$view field="title"/>
|
||||
</$link>
|
||||
</div>
|
||||
</$droppable>
|
||||
</div>
|
||||
</$list>
|
||||
</$set>
|
||||
</$reveal>
|
||||
</$set>
|
||||
</$draggable>
|
||||
</span>
|
||||
|
@ -312,6 +312,19 @@ a.tc-tiddlylink-external:hover {
|
||||
content: "<<lingo DropMessage>>";
|
||||
}
|
||||
|
||||
.tc-droppable .tc-droppable-placeholder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tc-droppable.tc-dragover .tc-droppable-placeholder {
|
||||
display: block;
|
||||
border: 2px dashed <<colour dropzone-background>>;
|
||||
}
|
||||
|
||||
.tc-draggable {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
/*
|
||||
** Plugin reload warning
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user