diff --git a/core/modules/editor/factory.js b/core/modules/editor/factory.js index 7d186e1248..b500fc9247 100644 --- a/core/modules/editor/factory.js +++ b/core/modules/editor/factory.js @@ -210,6 +210,29 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { this.editShowToolbar = this.wiki.getTiddlerText(ENABLE_TOOLBAR_TITLE,"yes"); this.editShowToolbar = (this.editShowToolbar === "yes") && !!(this.children && this.children.length > 0) && (!this.document.isTiddlyWikiFakeDom); }; + + EditTextWidget.prototype.updateDomNodeClasses = function() { + var domNodeClasses = this.engine.domNode.className.split(/\s+/).filter(Boolean), + oldClasses = this.editClass.split(/\s+/).filter(Boolean), + newClasses; + + this.editClass = this.getAttribute("class",""); + newClasses = this.editClass.split(/\s+/).filter(Boolean); + + // Remove classes assigned from the old value of the class attribute + domNodeClasses = domNodeClasses.filter(function(className) { + return !oldClasses.includes(className); + }); + + // Add new classes from the updated class attribute + domNodeClasses = domNodeClasses.concat( + newClasses.filter(function(className) { + return !domNodeClasses.includes(className); + }) + ); + + this.engine.domNode.className = domNodeClasses.join(" "); + }; /* Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering @@ -217,7 +240,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] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || 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] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) { this.refreshSelf(); return true; } else if(changedTiddlers[this.editRefreshTitle]) { @@ -226,6 +249,9 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { var editInfo = this.getEditInfo(); this.updateEditor(editInfo.value,editInfo.type); } + if(changedAttributes["class"]) { + this.updateDomNodeClasses(); + } this.engine.fixHeight(); if(this.editShowToolbar) { return this.refreshChildren(changedTiddlers); diff --git a/core/modules/filters/x-listops.js b/core/modules/filters/x-listops.js index 97eb830043..d613c2430f 100644 --- a/core/modules/filters/x-listops.js +++ b/core/modules/filters/x-listops.js @@ -160,8 +160,14 @@ exports.sortby = function(source,operator) { if(!results || results.length < 2) { return results; } - const lookup = $tw.utils.parseStringArray(operator.operand,"true"); - return results.sort((a,b) => lookup.indexOf(a) - lookup.indexOf(b)); + const lookup = $tw.utils.parseStringArray(operator.operand,"true"), + // The "end" suffix places unlisted titles last, the default is first + unlisted = operator.suffix === "end" ? lookup.length : -1, + position = (title) => { + const index = lookup.indexOf(title); + return index === -1 ? unlisted : index; + }; + return results.sort((a,b) => position(a) - position(b)); }; diff --git a/core/ui/EditTemplate/fields.tid b/core/ui/EditTemplate/fields.tid index 8a09f74db6..946c835eb6 100644 --- a/core/ui/EditTemplate/fields.tid +++ b/core/ui/EditTemplate/fields.tid @@ -108,10 +108,10 @@ tags: $:/tags/EditTemplate storeTitle=<> searchListState=<> > -
+
get[text]] :intersection[fields[]] :then[[tc-edit-field-exists]] }$`> <$transclude $variable="keyboard-driven-input" cancelPopups="yes" - class=`tc-edit-texteditor tc-popup-handle ${ [get[text]] :intersection[fields[]] :then[[tc-edit-field-exists]] }$` + class="tc-edit-texteditor tc-popup-handle" configTiddlerFilter="[[$:/config/EditMode/fieldname-filter]]" default="" focus={{{ [{!!draft.of}is[tiddler]then{$:/config/AutoFocusEdit}match[fields]then[true]] :else[{$:/config/AutoFocus}match[fields]then[true]] :else[[false]] }}} @@ -178,4 +178,4 @@ tags: $:/tags/EditTemplate
- \ No newline at end of file + diff --git a/core/ui/EditTemplate/tags.tid b/core/ui/EditTemplate/tags.tid index 20e1cad8e5..5c29f52842 100644 --- a/core/ui/EditTemplate/tags.tid +++ b/core/ui/EditTemplate/tags.tid @@ -18,10 +18,12 @@ tags: $:/tags/EditTemplate <$button class="tc-btn-invisible tc-remove-tag-button" style.fill=<> > - <$action-listops $tiddler=<> $field=<> $subfilter="-[{!!title}]"/> - {{$:/core/images/close-button}} - - + <$action-listops $tiddler=<> $field=<> $subfilter="-[{!!title}]"/> + + <$action-setfield $tiddler="$:/temp/tags-edit-refresh" text=<>/> + {{$:/core/images/close-button}} + + \end diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index 9834090c78..54d08e8dd3 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -940,10 +940,20 @@ describe("Filter tests", function() { it("should handle the sortby operator", function() { expect(wiki.filterTiddlers("a b c +[sortby[d e]]").join(",")).toBe("a,b,c"); expect(wiki.filterTiddlers("a b c +[sortby[b c a]]").join(",")).toBe("b,c,a"); + // By default titles missing from the reference list sort to the start expect(wiki.filterTiddlers("aa a b c +[sortby[b c a cc]]").join(",")).toBe("aa,b,c,a"); expect(wiki.filterTiddlers("a bb b c +[sortby[b c a cc]]").join(",")).toBe("bb,b,c,a"); expect(wiki.filterTiddlers("a bb cc b c +[sortby[b c a cc]]").join(",")).toBe("bb,b,c,a,cc"); - + // The "end" suffix places missing titles after the listed ones + expect(wiki.filterTiddlers("aa a b c +[sortby:end[b c a cc]]").join(",")).toBe("b,c,a,aa"); + expect(wiki.filterTiddlers("a bb b c +[sortby:end[b c a cc]]").join(",")).toBe("b,c,a,bb"); + expect(wiki.filterTiddlers("a bb cc b c +[sortby:end[b c a cc]]").join(",")).toBe("b,c,a,cc,bb"); + // Missing titles keep their input order. Avoid a repeated title here, it would be moved to the end of the input + expect(wiki.filterTiddlers("zz a yy b +[sortby:end[b a]]").join(",")).toBe("b,a,zz,yy"); + // Two titles are the shortest input that is sorted rather than returned untouched + expect(wiki.filterTiddlers("a b +[sortby[b a]]").join(",")).toBe("b,a"); + expect(wiki.filterTiddlers("a +[sortby:end[b a]]").join(",")).toBe("a"); + expect(wiki.filterTiddlers("b a b c +[sortby[]]").join(",")).toBe("a,b,c"); expect(wiki.filterTiddlers("b a b c +[sortby[a b b c]]").join(",")).toBe("a,b,c"); expect(wiki.filterTiddlers("b a b c +[sortby[b a c b]]").join(",")).toBe("b,a,c"); diff --git a/editions/tw5.com/tiddlers/filters/examples/sortby.tid b/editions/tw5.com/tiddlers/filters/examples/sortby Operator (Examples).tid similarity index 83% rename from editions/tw5.com/tiddlers/filters/examples/sortby.tid rename to editions/tw5.com/tiddlers/filters/examples/sortby Operator (Examples).tid index 83b94a3c98..12cc155bc0 100644 --- a/editions/tw5.com/tiddlers/filters/examples/sortby.tid +++ b/editions/tw5.com/tiddlers/filters/examples/sortby Operator (Examples).tid @@ -9,3 +9,4 @@ type: text/vnd.tiddlywiki <<.operator-example 1 "10 6 4 9 3 2 8 +[sortby[1 2 3 4 5 6 7 8 9 10]]">> <<.operator-example 2 "Friday Tuesday Monday Thursday Sunday +[sortby{Days of the Week!!list}]">> <<.operator-example 3 "1 Mon 5 Fri 4 Tue Sun 2 +[sortby{Days of the Week!!short}]">> +<<.operator-example 4 "1 Mon 5 Fri 4 Tue Sun 2 +[sortby:end{Days of the Week!!short}]">> diff --git a/editions/tw5.com/tiddlers/filters/sortby.tid b/editions/tw5.com/tiddlers/filters/sortby Operator.tid similarity index 58% rename from editions/tw5.com/tiddlers/filters/sortby.tid rename to editions/tw5.com/tiddlers/filters/sortby Operator.tid index 773c6a5981..0e5e036070 100644 --- a/editions/tw5.com/tiddlers/filters/sortby.tid +++ b/editions/tw5.com/tiddlers/filters/sortby Operator.tid @@ -1,11 +1,12 @@ caption: sortby created: 20151017145021839 -modified: 20151108052142057 +modified: 20260811120000000 op-input: a list of items -op-output: all items sorted by lookup list +op-output: all items sorted by the order list, with unlisted items placed first, or last with the `end` suffix op-parameter: a list specifying the order in which to sort the current list op-parameter-name: order op-purpose: sort the current list in the order of the list referenced in the parameter +op-suffix: <<.from-version "5.5.0">> optional: `end` to place items missing from <<.place order>> after the listed ones. If omitted they are placed first tags: [[Filter Operators]] [[Order Operators]] [[Listops Operators]] title: sortby Operator type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9747-sortby-unlisted-placement.tid b/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9747-sortby-unlisted-placement.tid new file mode 100644 index 0000000000..fe80514061 --- /dev/null +++ b/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9747-sortby-unlisted-placement.tid @@ -0,0 +1,12 @@ +change-category: filters +change-type: enhancement +created: 20260711015656000 +description: sortby accepts an optional end suffix to place titles missing from the reference list after the listed ones +github-contributors: pmario +github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9747 +release: 5.5.0 +tags: $:/tags/ChangeNote +title: $:/changenotes/5.5.0/#9747 +type: text/vnd.tiddlywiki + +* The [[sortby|sortby Operator]] filter operator now accepts an optional `end` suffix that places input titles missing from the reference list after the listed ones. The default is unchanged, so with a list `Alpha Beta Gamma` the input `Delta Epsilon Alpha Beta Gamma` still sorts to `Delta Epsilon Alpha Beta Gamma`, while `sortby:end[...]` sorts it to `Alpha Beta Gamma Delta Epsilon` (addresses [[Issue #8342|https://github.com/TiddlyWiki/TiddlyWiki5/issues/8342]]) diff --git a/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9879.tid b/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9879.tid new file mode 100644 index 0000000000..bc886a322d --- /dev/null +++ b/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9879.tid @@ -0,0 +1,10 @@ +title: $:/changenotes/5.5.0/#9879 +description: Fix field-name inputs re-render +tags: $:/tags/ChangeNote +release: 5.5.0 +change-type: bugfix +change-category: usability +github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9879 +github-contributors: BurningTreeC + +Fixes the field-name input re-rendering and therefor loosing focus when inserting a field-name that already exists diff --git a/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9889.tid b/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9889.tid new file mode 100644 index 0000000000..9bd2612619 --- /dev/null +++ b/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9889.tid @@ -0,0 +1,10 @@ +title: $:/changenotes/5.4.1/#9889 +description: Make tags in Edit Mode animate instantly when removing +tags: $:/tags/ChangeNote +release: 5.5.0 +change-type: bugfix +change-category: usability +github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9889 +github-contributors: BurningTreeC + +Fixes an issue where tags of Tiddlers in Edit Mode don't animate instantly when they get removed diff --git a/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9965.tid b/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9965.tid new file mode 100644 index 0000000000..ecad671114 --- /dev/null +++ b/editions/tw5.com/tiddlers/releasenotes/5.5.0/#9965.tid @@ -0,0 +1,14 @@ +title: $:/changenotes/5.5.0/#9965 +created: 20260812171534862 +modified: 20260812171534862 +tags: $:/tags/ChangeNote +change-type: enhancement +change-category: usability +description: Change of the class attribute of editors does no more completely refresh the widget +release: 5.5.0 +github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9965 +github-contributors: BurningTreeC +type: text/vnd.tiddlywiki + +This pull request changes the way editors refresh when their `class` attribute changes. +They did refresh the widget completely. Now they just assign the new classes. diff --git a/package-lock.json b/package-lock.json index 70b62e841a..3c15a7a271 100644 --- a/package-lock.json +++ b/package-lock.json @@ -719,9 +719,9 @@ "license": "ISC" }, "node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, "funding": [ {