1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-08-07 03:30:36 +00:00
TiddlyWiki5/core/modules/widgets/edit/editors/texteditor.js

166 lines
5.2 KiB
JavaScript

/*\
title: $:/core/modules/widgets/edit/editors/texteditor.js
type: application/javascript
module-type: editor
A plain text editor
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var MIN_TEXT_AREA_HEIGHT = 100;
var TextEditor = function(editWidget,tiddlerTitle,fieldName) {
this.editWidget = editWidget;
this.tiddlerTitle = tiddlerTitle;
this.fieldName = fieldName;
};
/*
Get the tiddler being edited and current value
*/
TextEditor.prototype.getEditInfo = function() {
// Get the current tiddler and the field name
var tiddler = this.editWidget.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle),
value;
// If we've got a tiddler, the value to display is the field string value
if(tiddler) {
value = tiddler.getFieldString(this.fieldName);
} else {
// Otherwise, we need to construct a default value for the editor
switch(this.fieldName) {
case "text":
value = "Type the text for the tiddler '" + this.tiddlerTitle + "'";
break;
case "title":
value = this.tiddlerTitle;
break;
default:
value = "";
break;
}
value = this.editWidget.renderer.getAttribute("default",value);
}
return {tiddler: tiddler, value: value};
};
TextEditor.prototype.render = function() {
// Get the initial value of the editor
var editInfo = this.getEditInfo();
// Create the editor nodes
var node = {
type: "element",
attributes: {}
};
var type = this.editWidget.renderer.getAttribute("type",this.fieldName === "text" ? "textarea" : "input");
switch(type) {
case "textarea":
node.tag = "textarea";
node.children = [{
type: "text",
text: editInfo.value
}];
break;
case "search":
node.tag = "input";
node.attributes.type = {type: "string", value: "search"};
node.attributes.value = {type: "string", value: editInfo.value};
break;
default: // "input"
node.tag = "input";
node.attributes.type = {type: "string", value: "text"};
node.attributes.value = {type: "string", value: editInfo.value};
break;
}
// Set the element details
this.editWidget.tag = this.editWidget.renderer.parseTreeNode.isBlock ? "div" : "span";
this.editWidget.attributes = {
"class": "tw-edit-texteditor"
};
if(this.editWidget.renderer.parseTreeNode.attributes["class"]) {
this.editWidget.attributes["class"] += " " + this.editWidget.renderer.parseTreeNode.attributes["class"].value;
}
if(this.editWidget.renderer.parseTreeNode.attributes.style) {
this.editWidget.attributes.style = this.editWidget.attributes.style || "";
this.editWidget.attributes.style += this.editWidget.renderer.parseTreeNode.attributes.style.value;
}
this.editWidget.children = this.editWidget.renderer.renderTree.createRenderers(this.editWidget.renderer,[node]);
this.editWidget.events = [
{name: "focus", handlerObject: this},
{name: "blur", handlerObject: this},
{name: "input", handlerObject: this}
];
};
TextEditor.prototype.handleEvent = function(event) {
// Get the value of the field if it might have changed
if(["input","focus","blur"].indexOf(event.type) !== -1) {
this.saveChanges();
}
// Fix the height of the textarea if required
if(["input","focus"].indexOf(event.type) !== -1) {
this.fixHeight();
}
return true;
};
TextEditor.prototype.saveChanges = function() {
var text = this.editWidget.children[0].domNode.value,
tiddler = this.editWidget.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle);
if(!tiddler) {
tiddler = new $tw.Tiddler({title: this.tiddlerTitle});
}
if(text !== tiddler.fields[this.fieldName]) {
var update = {};
update[this.fieldName] = text;
this.editWidget.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,update));
}
};
TextEditor.prototype.fixHeight = function() {
var self = this;
if(this.editWidget.children[0].domNode && this.editWidget.children[0].domNode.type === "textarea") {
$tw.utils.nextTick(function() {
// Resize the textarea to fit its content
var textarea = self.editWidget.children[0].domNode,
scrollPosition = $tw.utils.getScrollPosition(),
scrollTop = scrollPosition.y;
// Set its height to auto so that it snaps to the correct height
textarea.style.height = "auto";
// Calculate the revised height
var newHeight = Math.max(textarea.scrollHeight + textarea.offsetHeight - textarea.clientHeight,MIN_TEXT_AREA_HEIGHT);
// Only try to change the height if it has changed
if(newHeight !== textarea.offsetHeight) {
textarea.style.height = newHeight + "px";
// Make sure that the dimensions of the textarea are recalculated
$tw.utils.forceLayout(textarea);
// Check that the scroll position is still visible before trying to scroll back to it
scrollTop = Math.min(scrollTop,self.editWidget.renderer.renderTree.document.body.scrollHeight - window.innerHeight);
window.scrollTo(scrollPosition.x,scrollTop);
}
});
}
};
TextEditor.prototype.postRenderInDom = function() {
this.fixHeight();
};
TextEditor.prototype.refreshInDom = function() {
if(this.editWidget.renderer.renderTree.document.activeElement !== this.editWidget.children[0].domNode) {
var editInfo = this.getEditInfo();
this.editWidget.children[0].domNode.value = editInfo.value;
}
// Fix the height if needed
this.fixHeight();
};
exports["text/vnd.tiddlywiki"] = TextEditor;
exports["text/plain"] = TextEditor;
})();