diff --git a/boot/boot.js b/boot/boot.js
index 658f8e980..c54fa53d6 100644
--- a/boot/boot.js
+++ b/boot/boot.js
@@ -85,6 +85,18 @@ $tw.utils.each = function(object,callback) {
}
};
+/*
+Check if an array is equal by value and by reference.
+*/
+$tw.utils.isArrayEqual = function(array1,array2) {
+ if(array1 === array2) { return true; }
+ array1 = array1 || []; array2 = array2 || [];
+ if(array1.length !== array2.length) { return false; }
+ return array1.every(function(value,index) {
+ return value === array2[index];
+ });
+};
+
/*
Helper for making DOM elements
tag: tag name
@@ -779,6 +791,10 @@ $tw.Tiddler.prototype.hasField = function(field) {
return $tw.utils.hop(this.fields,field);
};
+$tw.Tiddler.prototype.isDraft = function() {
+ return this.hasField("draft.of");
+};
+
/*
Register and install the built in tiddler field modules
*/
@@ -1108,6 +1124,22 @@ $tw.Wiki.prototype.deserializeTiddlers = function(type,text,srcFields) {
}
};
+$tw.Wiki.prototype.isModifiedTiddler = function(title) {
+ var tiddler = this.getTiddler(title);
+ if(!tiddler.isDraft()) {
+ return false;
+ }
+ var ignoredFields = ["created", "modified", "title", "draft.title", "draft.of", "tags"],
+ origTiddler = this.getTiddler(tiddler.fields["draft.of"]);
+ if(!$tw.utils.isArrayEqual(tiddler.fields.tags,origTiddler.fields.tags)) {
+ return true;
+ }
+ return !Object.keys(tiddler.fields).every(function(field) {
+ if(ignoredFields.indexOf(field) >= 0) { return true; }
+ return tiddler.fields[field] === origTiddler.fields[field];
+ });
+};
+
/*
Register the built in tiddler deserializer modules
*/
diff --git a/core/language/en-GB/EditTemplate.multids b/core/language/en-GB/EditTemplate.multids
index 27572963c..d6eb2a525 100644
--- a/core/language/en-GB/EditTemplate.multids
+++ b/core/language/en-GB/EditTemplate.multids
@@ -4,6 +4,7 @@ Body/Hint: Use [[wiki text|http://tiddlywiki.com/static/WikiText.html]] to add f
Body/Placeholder: Type the text for this tiddler
Body/Preview/Button/Hide: hide preview
Body/Preview/Button/Show: show preview
+Body/ShadowWarning: You are editing a shadow tiddler. Any changes will override the default version.
Fields/Add/Button: add
Fields/Add/Name/Placeholder: field name
Fields/Add/Prompt: Add a new field:
diff --git a/core/language/en-GB/Misc.multids b/core/language/en-GB/Misc.multids
index e7dfd68c3..35502b737 100644
--- a/core/language/en-GB/Misc.multids
+++ b/core/language/en-GB/Misc.multids
@@ -6,6 +6,7 @@ CloseAll/Button: close all
ConfirmCancelTiddler: Do you wish to discard changes to the tiddler "<$text text=<
>/>"?
ConfirmDeleteTiddler: Do you wish to delete the tiddler "<$text text=<>/>"?
ConfirmOverwriteTiddler: Do you wish to overwrite the tiddler "<$text text=<>/>"?
+ConfirmEditShadowTiddler: Your about to edit a ShaddowTiddler. This will override the default system making upgrading non-trivial. Are you sure you want to edit "<$text text=<>/>"?
InvalidFieldName: Illegal characters in field name "<$text text=<>/>". Fields can only contain lowercase letters and the characters underscore (`_`), hyphen (`-`) and period (`.`)
MissingTiddler/Hint: Missing tiddler "<$text text=<>/>" - click {{$:/core/images/edit-button}} to create
RecentChanges/DateFormat: DDth MMM YYYY
diff --git a/core/modules/widgets/navigator.js b/core/modules/widgets/navigator.js
index c58caa2e3..40aaae9cf 100755
--- a/core/modules/widgets/navigator.js
+++ b/core/modules/widgets/navigator.js
@@ -181,9 +181,28 @@ NavigatorWidget.prototype.handleCloseOtherTiddlersEvent = function(event) {
// Place a tiddler in edit mode
NavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {
+ function isUnmodifiedShadow(title) {
+ // jshint eqnull:true
+ var tiddler = $tw.wiki.getTiddler(title);
+ return (
+ $tw.wiki.isShadowTiddler(title) &&
+ tiddler.fields.modified == null
+ );
+ }
+ function confirmEditShadow(title) {
+ return confirm($tw.language.getString(
+ "ConfirmEditShadowTiddler",
+ {variables:
+ {title: title}
+ }
+ ));
+ }
+ var title = event.param || event.tiddlerTitle;
+ if(isUnmodifiedShadow(title) && !confirmEditShadow(title)) {
+ return false;
+ }
// Replace the specified tiddler with a draft in edit mode
- var title = event.param || event.tiddlerTitle,
- draftTiddler = this.makeDraftTiddler(title),
+ var draftTiddler = this.makeDraftTiddler(title),
draftTitle = draftTiddler.fields.title,
storyList = this.getStoryList();
this.removeTitleFromStory(storyList,draftTitle);
@@ -281,8 +300,7 @@ NavigatorWidget.prototype.generateDraftTitle = function(title) {
NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
var title = event.param || event.tiddlerTitle,
tiddler = this.wiki.getTiddler(title),
- storyList = this.getStoryList(),
- storyTiddlerModified = false; // We have to special case saving the story tiddler itself
+ storyList = this.getStoryList();
// Replace the original tiddler with the draft
if(tiddler) {
var draftTitle = (tiddler.fields["draft.title"] || "").trim(),
@@ -297,12 +315,14 @@ NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
{title: draftTitle}
}
));
- }
- if(isConfirmed) {
+ } else if(!this.wiki.isModifiedTiddler(title)) {
+ event.type = "tw-cancel-tiddler";
+ this.dispatchEvent(event);
+ } else if(isConfirmed) {
// Save the draft tiddler as the real tiddler
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,{
title: draftTitle,
- "draft.title": undefined,
+ "draft.title": undefined,
"draft.of": undefined
},this.wiki.getModificationFields()));
// Remove the draft tiddler
diff --git a/core/ui/EditTemplate/shadowWarning.tid b/core/ui/EditTemplate/shadowWarning.tid
new file mode 100644
index 000000000..ba4da6a99
--- /dev/null
+++ b/core/ui/EditTemplate/shadowWarning.tid
@@ -0,0 +1,11 @@
+title: $:/core/ui/EditTemplate/shadowWarning
+tags: $:/tags/EditTemplate
+
+\define lingo-base() $:/language/EditTemplate/
+<$list filter="[all[current]get[draft.of]is[shadow]]">
+
+
+<>
+
+
+$list>
diff --git a/core/wiki/tags/EditTemplate.tid b/core/wiki/tags/EditTemplate.tid
index 9a0c11a89..9a405fb2d 100644
--- a/core/wiki/tags/EditTemplate.tid
+++ b/core/wiki/tags/EditTemplate.tid
@@ -1,2 +1,2 @@
title: $:/tags/EditTemplate
-list: [[$:/core/ui/EditTemplate/controls]] [[$:/core/ui/EditTemplate/title]] [[$:/core/ui/EditTemplate/tags]] [[$:/core/ui/ViewTemplate/classic]] [[$:/core/ui/EditTemplate/body]] [[$:/core/ui/EditTemplate/type]] [[$:/core/ui/EditTemplate/fields]]
+list: [[$:/core/ui/EditTemplate/controls]] [[$:/core/ui/EditTemplate/title]] [[$:/core/ui/EditTemplate/tags]] [[$:/core/ui/EditTemplate/shadowWarning]] [[$:/core/ui/ViewTemplate/classic]] [[$:/core/ui/EditTemplate/body]] [[$:/core/ui/EditTemplate/type]] [[$:/core/ui/EditTemplate/fields]]