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=<<title>>/>"? ConfirmOverwriteTiddler: Do you wish to overwrite the tiddler "<$text text=<<title>>/>"? +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=<<title>>/>"? InvalidFieldName: Illegal characters in field name "<$text text=<<fieldName>>/>". Fields can only contain lowercase letters and the characters underscore (`_`), hyphen (`-`) and period (`.`) MissingTiddler/Hint: Missing tiddler "<$text text=<<currentTiddler>>/>" - 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]]"> +<div class="tw-message-box"> + +<<lingo Body/ShadowWarning>> + +</div> +</$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]]