1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-23 10:07:19 +00:00

Drag and drop images in the editor to import and insert (#5699)

* Merge

* Clean up

* More clean up

* Ensure image import works when type is not set, clean up post import actions

* Removed spurious new line

* For non image files insert a tiddler link

* Added documentation for new settings and features
This commit is contained in:
Saq Imtiaz 2021-05-19 22:52:43 +02:00 committed by GitHub
parent c7f6cedc43
commit 05d38054c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 301 additions and 28 deletions

View File

@ -1,5 +1,6 @@
title: $:/language/Import/
Editor/Import/Heading: Import images and insert into the editor.
Imported/Hint: The following tiddlers were imported:
Listing/Cancel/Caption: Cancel
Listing/Hint: These tiddlers are ready to import:

View File

@ -87,7 +87,20 @@ function FramedEngine(options) {
{name: "input",handlerObject: this,handlerMethod: "handleInputEvent"},
{name: "keydown",handlerObject: this.widget,handlerMethod: "handleKeydownEvent"},
{name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"}
]);
// Add drag and drop event listeners if fileDrop is enabled
if(this.widget.isFileDropEnabled) {
$tw.utils.addEventListeners(this.domNode,[
{name: "dragenter",handlerObject: this.widget,handlerMethod: "handleDragEnterEvent"},
{name: "dragover",handlerObject: this.widget,handlerMethod: "handleDragOverEvent"},
{name: "dragleave",handlerObject: this.widget,handlerMethod: "handleDragLeaveEvent"},
{name: "dragend",handlerObject: this.widget,handlerMethod: "handleDragEndEvent"},
{name: "drop", handlerObject: this.widget,handlerMethod: "handleDropEvent"},
{name: "paste", handlerObject: this.widget,handlerMethod: "handlePasteEvent"},
{name: "click",handlerObject: this.widget,handlerMethod: "handleClickEvent"}
]);
}
// Insert the element into the DOM
this.iframeDoc.body.appendChild(this.domNode);
}

View File

@ -186,6 +186,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.editRefreshTitle = this.getAttribute("refreshTitle");
this.editAutoComplete = this.getAttribute("autocomplete");
this.isDisabled = this.getAttribute("disabled","no");
this.isFileDropEnabled = this.getAttribute("fileDrop","no") === "yes";
// Get the default editor element tag and type
var tag,type;
if(this.editField === "text") {
@ -217,7 +218,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
EditTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
// Completely rerender if any of our attributes have changed
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled || changedAttributes.fileDrop) {
this.refreshSelf();
return true;
} else if (changedTiddlers[this.editRefreshTitle]) {
@ -297,19 +298,88 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
Propogate keydown events to our container for the keyboard widgets benefit
*/
EditTextWidget.prototype.propogateKeydownEvent = function(event) {
var newEvent = this.document.createEventObject ? this.document.createEventObject() : this.document.createEvent("Events");
if(newEvent.initEvent) {
newEvent.initEvent("keydown", true, true);
}
newEvent.keyCode = event.keyCode;
newEvent.which = event.which;
newEvent.metaKey = event.metaKey;
newEvent.ctrlKey = event.ctrlKey;
newEvent.altKey = event.altKey;
newEvent.shiftKey = event.shiftKey;
var newEvent = this.cloneEvent(event,["keyCode","which","metaKey","ctrlKey","altKey","shiftKey"]);
return !this.parentDomNode.dispatchEvent(newEvent);
};
EditTextWidget.prototype.cloneEvent = function(event,propertiesToCopy) {
var propertiesToCopy = propertiesToCopy || [],
newEvent = this.document.createEventObject ? this.document.createEventObject() : this.document.createEvent("Events");
if(newEvent.initEvent) {
newEvent.initEvent(event.type, true, true);
}
$tw.utils.each(propertiesToCopy,function(prop){
newEvent[prop] = event[prop];
});
return newEvent;
};
EditTextWidget.prototype.dispatchDOMEvent = function(newEvent) {
var dispatchNode = this.engine.iframeNode || this.engine.parentNode;
return dispatchNode.dispatchEvent(newEvent);
};
/*
Propogate drag and drop events with File data to our container for the dropzone widgets benefit.
If there are no Files, let the browser handle it.
*/
EditTextWidget.prototype.handleDropEvent = function(event) {
if(event.dataTransfer.files.length) {
event.preventDefault();
event.stopPropagation();
this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
}
};
EditTextWidget.prototype.handlePasteEvent = function(event) {
if(event.clipboardData.files.length) {
event.preventDefault();
event.stopPropagation();
this.dispatchDOMEvent(this.cloneEvent(event,["clipboardData"]));
}
};
EditTextWidget.prototype.handleDragEnterEvent = function(event) {
if($tw.utils.dragEventContainsFiles(event)) {
// Ignore excessive events fired by FF when entering and leaving text nodes in a text area.
if( event.relatedTarget && (event.relatedTarget.nodeType === 3 || event.target === event.relatedTarget)) {
return true;
}
event.preventDefault();
return this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
}
return true;
};
EditTextWidget.prototype.handleDragOverEvent = function(event) {
if($tw.utils.dragEventContainsFiles(event)) {
// Call preventDefault() in browsers that default to not allowing drop events on textarea
if($tw.browser.isFirefox || $tw.browser.isIE) {
event.preventDefault();
}
event.dataTransfer.dropEffect = "copy";
return this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
}
return true;
};
EditTextWidget.prototype.handleDragLeaveEvent = function(event) {
// Ignore excessive events fired by FF when entering and leaving text nodes in a text area.
if(event.relatedTarget && ((event.relatedTarget.nodeType === 3) || (event.target === event.relatedTarget))) {
return true;
}
event.preventDefault();
this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
};
EditTextWidget.prototype.handleDragEndEvent = function(event) {
this.dispatchDOMEvent(this.cloneEvent(event));
};
EditTextWidget.prototype.handleClickEvent = function(event) {
return !this.dispatchDOMEvent(this.cloneEvent(event));
};
return EditTextWidget;
}

View File

@ -205,4 +205,16 @@ function parseJSONTiddlers(json,fallbackTitle) {
return data;
};
exports.dragEventContainsFiles = function(event) {
if(event.dataTransfer.types) {
for(var i=0; i<event.dataTransfer.types.length; i++) {
if(event.dataTransfer.types[i] === "Files") {
return true;
break;
}
}
}
return false;
};
})();

View File

@ -115,6 +115,9 @@ DropZoneWidget.prototype.handleDragEnterEvent = function(event) {
if($tw.dragInProgress) {
return false;
}
if(this.filesOnly && !$tw.utils.dragEventContainsFiles(event)) {
return false;
}
this.enterDrag(event);
// Tell the browser that we're ready to handle the drop
event.preventDefault();
@ -133,7 +136,10 @@ 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
// Check if this is a synthetic event, IE does not allow accessing dropEffect outside of original event handler
if(event.isTrusted) {
event.dataTransfer.dropEffect = "copy"; // Explicitly show this is a copy
}
};
DropZoneWidget.prototype.handleDragLeaveEvent = function(event) {
@ -284,6 +290,7 @@ DropZoneWidget.prototype.execute = function() {
this.importTitle = this.getAttribute("importTitle",IMPORT_TITLE);
this.actions = this.getAttribute("actions");
this.contentTypesFilter = this.getAttribute("contentTypesFilter");
this.filesOnly = this.getAttribute("filesOnly","no") === "yes";
// Make child widgets
this.makeChildWidgets();
};

View File

@ -8,6 +8,7 @@ title: $:/core/ui/EditTemplate/body/editor
tabindex={{$:/config/EditTabIndex}}
focus={{{ [{$:/config/AutoFocus}match[text]then[true]] ~[[false]] }}}
cancelPopups="yes"
fileDrop={{{ [{$:/config/DragAndDrop/Enable}match[no]] :else[subfilter{$:/config/Editor/EnableImportFilter}then[yes]else[no]] }}}
><$set
@ -30,4 +31,12 @@ title: $:/core/ui/EditTemplate/body/editor
tiddler="$:/core/ui/EditTemplate/body/toolbar/button"
mode="inline"
/></$reveal></$list></$set></$edit>
/></$reveal></$list><$list
filter="[all[shadows+tiddlers]tag[$:/tags/EditorTools]!has[draft.of]]"
><$list
filter={{!!condition}}
variable="list-condition"
><$transclude/>
</$list></$list></$set></$edit>

View File

@ -5,6 +5,11 @@ tags: $:/tags/EditTemplate
\define config-visibility-title()
$:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$
\end
\define importFileActions()
<$action-popup $state=<<importState>> $coords="(0,0,0,0)" $floating="yes"/>
\end
<$list filter="[all[current]has[_canonical_uri]]">
<div class="tc-message-box">
@ -20,9 +25,8 @@ $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$
</$list>
<$list filter="[all[current]!has[_canonical_uri]]">
<$reveal state="$:/state/showeditpreview" type="match" text="yes">
<$vars importTitle=<<qualify $:/ImportImage>> importState=<<qualify $:/state/ImportImage>> >
<$dropzone importTitle=<<importTitle>> autoOpenOnImport="no" contentTypesFilter={{$:/config/Editor/ImportContentTypesFilter}} class="tc-dropzone-editor" enable={{{ [{$:/config/DragAndDrop/Enable}match[no]] :else[subfilter{$:/config/Editor/EnableImportFilter}then[yes]else[no]] }}} filesOnly="yes" actions=<<importFileActions>> ><$reveal state="$:/state/showeditpreview" type="match" text="yes">
<div class="tc-tiddler-preview">
<$transclude tiddler="$:/core/ui/EditTemplate/body/editor" mode="inline"/>
@ -38,7 +42,6 @@ $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$
</div>
</div>
</$reveal>
<$reveal state="$:/state/showeditpreview" type="nomatch" text="yes">
@ -46,5 +49,6 @@ $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$
<$transclude tiddler="$:/core/ui/EditTemplate/body/editor" mode="inline"/>
</$reveal>
</$list>
</$dropzone>
</$vars>
</$list>

View File

@ -0,0 +1,41 @@
title: $:/core/ui/EditorToolbar/file-import
tags: $:/tags/EditorTools
condition: [<targetTiddler>!has[type]] [<targetTiddler>type[text/vnd.tiddlywiki]]
\define lingo-base() $:/language/Import/
\define closePopupActions()
<$action-deletetiddler $filter="[title<importState>] [title<importTitle>]"/>
\end
\define replacement-text-image() [img[$title$]]
\define replacement-text-file() [[$title$]]
\define postImportActions()
<$list filter="[<importTitle>links[]] :reduce[get[type]prefix[image]then<replacement-text-image>else<replacement-text-file>search-replace[$title$],<currentTiddler>addprefix<accumulator>]" variable="imageTitle">
<$action-sendmessage
$message="tm-edit-text-operation"
$param="replace-selection"
text=<<imageTitle>>
/>
</$list>
<<closePopupActions>>
\end
\define buttons()
<$button class="tc-btn-invisible" actions=<<closePopupActions>> ><<lingo Listing/Cancel/Caption>></$button>
<$button class="tc-btn-invisible" message="tm-perform-import" param=<<importTitle>> actions=<<postImportActions>> ><<lingo Listing/Import/Caption>></$button>
\end
<$reveal type="popup" state=<<importState>> tag="div" class="tc-editor-importpopup">
<div class="tc-editor-import">
<$list filter="[<importTitle>field:plugin-type[import]]">
<h2><<lingo Editor/Import/Heading>></h2>
<$tiddler tiddler=<<importTitle>>>
{{||$:/core/ui/ImportListing}}
<<buttons>>
</$tiddler>
</$list>
</div>
</$reveal>

View File

@ -0,0 +1,4 @@
title: $:/config/Editor/EnableImportFilter
type: text/vnd.tiddlywiki
[all[current]type[text/vnd.tiddlywiki]] [all[current]!has[type]]

View File

@ -0,0 +1,4 @@
title: $:/config/Editor/ImportContentTypesFilter
type: text/vnd.tiddlywiki
[prefix[image/]]

View File

@ -1,6 +1,6 @@
created: 20130822080600000
list: [[SystemTag: $:/tags/AboveStory]] [[SystemTag: $:/tags/AdvancedSearch]] [[SystemTag: $:/tags/AdvancedSearch/FilterButton]] [[SystemTag: $:/tags/Alert]] [[SystemTag: $:/tags/BelowStory]] [[SystemTag: $:/tags/ControlPanel]] [[SystemTag: $:/tags/ControlPanel/Advanced]] [[SystemTag: $:/tags/ControlPanel/Appearance]] [[SystemTag: $:/tags/ControlPanel/Info]] [[SystemTag: $:/tags/ControlPanel/Saving]] [[SystemTag: $:/tags/ControlPanel/Settings]] [[SystemTag: $:/tags/ControlPanel/Toolbars]] [[SystemTag: $:/tags/EditorToolbar]] [[SystemTag: $:/tags/EditPreview]] [[SystemTag: $:/tags/EditTemplate]] [[SystemTag: $:/tags/EditToolbar]] [[SystemTag: $:/tags/Exporter]] [[SystemTag: $:/tags/Filter]] [[SystemTag: $:/tags/Image]] [[SystemTag: $:/tags/ImportPreview]] [[SystemTag: $:/tags/KeyboardShortcut]] [[SystemTag: $:/tags/Layout]] [[SystemTag: $:/tags/Macro]] [[SystemTag: $:/tags/Macro/View]] [[SystemTag: $:/tags/Manager/ItemMain]] [[SystemTag: $:/tags/Manager/ItemSidebar]] [[SystemTag: $:/tags/MoreSideBar]] [[SystemTag: $:/tags/MoreSideBar/Plugins]] [[SystemTag: $:/tags/PageControls]] [[SystemTag: $:/tags/PageTemplate]] [[SystemTag: $:/tags/Palette]] [[SystemTag: $:/tags/PluginLibrary]] [[SystemTag: $:/tags/RawMarkup]] [[SystemTag: $:/tags/RawMarkupWikified]] [[SystemTag: $:/tags/RawMarkupWikified/BottomBody]] [[SystemTag: $:/tags/RawMarkupWikified/TopBody]] [[SystemTag: $:/tags/RawMarkupWikified/TopHead]] [[SystemTag: $:/tags/RawStaticContent]] [[SystemTag: $:/tags/RemoteAssetInfo]] [[SystemTag: $:/tags/SearchResults]] [[SystemTag: $:/tags/ServerConnection]] [[SystemTag: $:/tags/SideBar]] [[SystemTag: $:/tags/SideBarSegment]] [[SystemTag: $:/tags/StartupAction]] [[SystemTag: $:/tags/StartupAction/Browser]] [[SystemTag: $:/tags/StartupAction/Node]] [[SystemTag: $:/tags/Stylesheet]] [[SystemTag: $:/tags/TagDropdown]] [[SystemTag: $:/tags/TextEditor/Snippet]] [[SystemTag: $:/tags/TiddlerInfo]] [[SystemTag: $:/tags/TiddlerInfo/Advanced]] [[SystemTag: $:/tags/TiddlerInfoSegment]] [[SystemTag: $:/tags/ToolbarButtonStyle]] [[SystemTag: $:/tags/TopLeftBar]] [[SystemTag: $:/tags/TopRightBar]] [[SystemTag: $:/tags/ViewTemplate]] [[SystemTag: $:/tags/ViewToolbar]]
modified: 20201123192434277
list: [[SystemTag: $:/tags/AboveStory]] [[SystemTag: $:/tags/AdvancedSearch]] [[SystemTag: $:/tags/AdvancedSearch/FilterButton]] [[SystemTag: $:/tags/Alert]] [[SystemTag: $:/tags/BelowStory]] [[SystemTag: $:/tags/ControlPanel]] [[SystemTag: $:/tags/ControlPanel/Advanced]] [[SystemTag: $:/tags/ControlPanel/Appearance]] [[SystemTag: $:/tags/ControlPanel/Info]] [[SystemTag: $:/tags/ControlPanel/Saving]] [[SystemTag: $:/tags/ControlPanel/Settings]] [[SystemTag: $:/tags/ControlPanel/Toolbars]] [[SystemTag: $:/tags/EditorTools]] [[SystemTag: $:/tags/EditorToolbar]] [[SystemTag: $:/tags/EditPreview]] [[SystemTag: $:/tags/EditTemplate]] [[SystemTag: $:/tags/EditToolbar]] [[SystemTag: $:/tags/Exporter]] [[SystemTag: $:/tags/Filter]] [[SystemTag: $:/tags/Image]] [[SystemTag: $:/tags/ImportPreview]] [[SystemTag: $:/tags/KeyboardShortcut]] [[SystemTag: $:/tags/Layout]] [[SystemTag: $:/tags/Macro]] [[SystemTag: $:/tags/Macro/View]] [[SystemTag: $:/tags/Manager/ItemMain]] [[SystemTag: $:/tags/Manager/ItemSidebar]] [[SystemTag: $:/tags/MoreSideBar]] [[SystemTag: $:/tags/MoreSideBar/Plugins]] [[SystemTag: $:/tags/PageControls]] [[SystemTag: $:/tags/PageTemplate]] [[SystemTag: $:/tags/Palette]] [[SystemTag: $:/tags/PluginLibrary]] [[SystemTag: $:/tags/RawMarkup]] [[SystemTag: $:/tags/RawMarkupWikified]] [[SystemTag: $:/tags/RawMarkupWikified/BottomBody]] [[SystemTag: $:/tags/RawMarkupWikified/TopBody]] [[SystemTag: $:/tags/RawMarkupWikified/TopHead]] [[SystemTag: $:/tags/RawStaticContent]] [[SystemTag: $:/tags/RemoteAssetInfo]] [[SystemTag: $:/tags/SearchResults]] [[SystemTag: $:/tags/ServerConnection]] [[SystemTag: $:/tags/SideBar]] [[SystemTag: $:/tags/SideBarSegment]] [[SystemTag: $:/tags/StartupAction]] [[SystemTag: $:/tags/StartupAction/Browser]] [[SystemTag: $:/tags/StartupAction/Node]] [[SystemTag: $:/tags/Stylesheet]] [[SystemTag: $:/tags/TagDropdown]] [[SystemTag: $:/tags/TextEditor/Snippet]] [[SystemTag: $:/tags/TiddlerInfo]] [[SystemTag: $:/tags/TiddlerInfo/Advanced]] [[SystemTag: $:/tags/TiddlerInfoSegment]] [[SystemTag: $:/tags/ToolbarButtonStyle]] [[SystemTag: $:/tags/TopLeftBar]] [[SystemTag: $:/tags/TopRightBar]] [[SystemTag: $:/tags/ViewTemplate]] [[SystemTag: $:/tags/ViewToolbar]]
modified: 20210519160636964
tags: Reference Concepts
title: SystemTags
type: text/vnd.tiddlywiki

View File

@ -1,10 +1,10 @@
created: 20200315143638556
modified: 20200315143638556
modified: 20210519155433742
tags: [[Hidden Settings]]
title: Hidden Setting: Disable Drag and Drop
type: text/vnd.tiddlywiki
<.from-version "5.1.22">> To disable all the drag and drop operations that are built into the core, set the following tiddler to "no":
<<.from-version "5.1.22">> To disable all the drag and drop operations that are built into the core, set the following tiddler to "no":
$:/config/DragAndDrop/Enable

View File

@ -0,0 +1,12 @@
created: 20210519155447339
modified: 20210519160010708
tags: [[Hidden Settings]]
title: Hidden Setting: Enable File Import in Editor
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">>
$:/config/Editor/EnableImportFilter
This filter determines whether dragging and dropping files in the editor works for a given tiddler or not. A non-empty result enables drag and drop in the editor for that tiddler.
This filter is used in such a manner that it respects the global drag and drop setting.

View File

@ -0,0 +1,11 @@
created: 20210519155910219
modified: 20210519160221219
tags: [[Hidden Settings]]
title: Hidden Settings: Import Content Types for Editor
type: text/vnd.tiddlywiki
<<.from-version "5.1.24">>
$:/config/Editor/ImportContentTypesFilter
This filter determines which `contentTypes` can be imported by dragging and dropping into the editor. It used by a DropzoneWidget wrapped around the editor, for the `contentTypesFilter` attribute.

View File

@ -1,6 +1,6 @@
caption: dropzone
created: 20131024141900000
modified: 20210410062410660
modified: 20210519154948743
tags: Widgets
title: DropzoneWidget
type: text/vnd.tiddlywiki
@ -21,6 +21,7 @@ It sends a [[WidgetMessage: tm-import-tiddlers]] carrying a JSON representation
|importTitle|<<.from-version "5.1.23">> Optional tiddler title to use for import process instead of ~$:/Import |
|actions|<<.from-version "5.1.24">> Optional actions string to be invoked after the `tm-import-tiddlers` message has been sent. The variable `importTitle` provides the title of the tiddler used for the import process. |
|contentTypesFilter |<<.from-version "5.1.24">> Optional filter that specifies the [[content types|ContentType]] accepted by the dropzone. |
|filesOnly|<<.from-version "5.1.24">> Optional. When set to "yes", the dropzone only accepts files and not string data. Defaults to "no" |
<<.tip """Use the `prefix` filter operator to easily accept multiple related content types. For example this filter will accept all image content types: `[prefix[image/]]`""">>
@ -30,7 +31,7 @@ The dropzone widget displays any contained content within the dropzone.
! Display
The dropzone widget creates an HTML `<div class="tc-dropzone">` to contain its content. During a drag operation the class `tc-dragover` is added. CSS is used to provide user feedback.
The dropzone widget creates an HTML `<div class="tc-dropzone">` to contain its content. During a drag operation the class `tc-dragover` is added. CSS is used to provide user feedback. For custom styling of this state where a drag is in progress, specify a custom class name with the `class` attribute and use CSS with the selector `.myclass.tc-dragover`.
! Data types supported

View File

@ -1,6 +1,6 @@
caption: edit-text
created: 20131024141900000
modified: 20201130184701532
modified: 20210519154352055
tags: Widgets
title: EditTextWidget
type: text/vnd.tiddlywiki
@ -36,6 +36,7 @@ The content of the `<$edit-text>` widget is ignored.
|inputActions |<<.from-version 5.1.23>> Optional actions that are triggered every time an input event occurs within the input field or textarea |
|refreshTitle |<<.from-version 5.1.23>> An optional tiddler title that makes the input field update whenever the specified tiddler changes |
|disabled|<<.from-version "5.1.23">> Optional, disables the text input if set to "yes". Defaults to "no"|
|fileDrop|<<.from-version "5.1.24">> Optional. When set to "yes" allows dropping or pasting images into the editor to import them. Defaults to "no"|
! Notes

View File

@ -1,6 +1,6 @@
caption: Images
created: 20131205160221762
modified: 20160617100358365
modified: 20210519160846733
tags: WikiText [[Working with TiddlyWiki]]
title: Images in WikiText
type: text/vnd.tiddlywiki
@ -64,3 +64,5 @@ Renders as:
Use the <<.button import>> button (under the <<.sidebar-tab Tools>> tab in the sidebar), or drag and drop.
See [[ImportingTiddlers]] for details.
<<.from-version "5.1.24">> You can also import images by dropping or pasting images into the tiddler editor.

View File

@ -124,8 +124,11 @@ function CodeMirrorEngine(options) {
self.widget.invokeActionString(self.widget.editInputActions);
}
});
this.cm.on("drop",function(cm,event) {
event.stopPropagation(); // Otherwise TW's dropzone widget sees the drop event
if(!self.widget.isFileDropEnabled) {
event.stopPropagation(); // Otherwise TW's dropzone widget sees the drop event
}
return false;
});
this.cm.on("keydown",function(cm,event) {
@ -136,6 +139,32 @@ function CodeMirrorEngine(options) {
$tw.popup.cancel(0);
}
});
// Add drag and drop event listeners if fileDrop is enabled
if(this.widget.isFileDropEnabled) {
// If the drag event contains Files, prevent the default CodeMirror handling
this.cm.on("dragenter",function(cm,event) {
if($tw.utils.dragEventContainsFiles(event)) {
event.preventDefault();
}
return true;
});
this.cm.on("dragleave",function(cm,event) {
event.preventDefault();
});
this.cm.on("dragover",function(cm,event) {
if($tw.utils.dragEventContainsFiles(event)) {
event.preventDefault();
}
});
this.cm.on("drop",function(cm,event) {
if($tw.utils.dragEventContainsFiles(event)) {
event.preventDefault();
}
});
this.cm.on("paste",function(cm,event) {
self.widget.handlePasteEvent.call(self.widget,event);
});
}
}
/*

View File

@ -1550,6 +1550,58 @@ html body.tc-body.tc-single-tiddler-window {
width: 10%;
}
/*
** Tiddler editor dropzone
*/
.tc-dropzone-editor {
position:relative;
}
.tc-dropzone-editor.tc-dragover .tc-editor-toolbar::after{
z-index: 10000;
top:0;
left:0;
right:0;
height: 100%;
background: <<colour dropzone-background>>;
content: "<<lingo DropMessage>>";
pointer-events: none;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
background-color: <<color background>>;
border: 4px dashed <<color modal-border>>;
font-weight: 600;
font-size: 150%;
opacity: 0.8;
color: <<color foreground>>;
}
.tc-editor-importpopup {
width: 100%;
height: 100%;
}
.tc-editor-import {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: <<color pre-background>>;
box-shadow: 2px 2px 10px <<colour foreground>>;
padding: 10px;
width: 96%;
border: 1px solid <<color tiddler-controls-foreground>>;
text-align:center;
}
.tc-editor-import img {
max-height: 500px;
}
/*
** Storyview Classes
*/