Closed felixhayashi closed 2 years ago
Nice idea, list-fields are an important usecase.
list-fields are an important usecase.
Yes, exactly. Lists are a great way to deal with stuff. Also I highly dislike to always create a separate tiddler for every checkbox.
Good idea; it's quite a small change: the checkbox widget already has logic for adding and removing members of a list, but of course it's currently tied to using the "tags" field for the list.
Good idea; it's quite a small change: the checkbox widget already has logic for adding and removing members of a list, but of course it's currently tied to using the "tags" field for the list.
@Jermolene That is great! Even the recently added invert feature could be highly useful with lists in general.
I am toying with ideas for a show-fields plugin that could benefit. I was starting to build the addition to the settings in the control panel using a list filter for my global setting so I'd like to follow along. Could the checkbox be used with a list filter maybe?
@Infurnoape
You can always wrap the checkbox in a filter
<$list filter="…">
<$checkbox
This ticket is about writing the output of a checkbox into a field list-style.
I'm still advocating for some kind of $:/config/fields/myfield!!type:list
telling TiddlyWiki and plugins what to make of certain fields.
I'm still advocating for some kind of $:/config/fields/myfield!!type:list telling TiddlyWiki and plugins what to make of certain fields
While I think a meta tiddler for field types would be great for several reasons, I am not sure that this is easily implemented and it might slow down the wiki as well.
This issue was really just about a small change to the checkbox widget and as Jeremy pointed out this seems to be an easy win as the functionality is already there and just needs the js to be written more generic so it is possible to use other list fields as output but the tags field.
Yes, I understand, one can always tell a widget how to handle data and that's perhaps the safest, most explicit way to do it.
I'd suggest that we add a new tagField
attribute to the checkbox widget. Pull requests are welcome.
The core does include the idea of metadata about the format of tiddler fields. It is implemented in JavaScript, which was definitely a mistake, as it is not accessible to wikitext. But I've found that the whole idea of tiddler field metadata at that level is limiting, and I regret including it in the implementation. The alternative is that operations on fields should specify or imply the expected format of that field. That's pretty much always possible now; it's only a historical accident that the core has this tiddler metadata.
So I think that the conventions about fields like modified
, modifier
, created
, creator
, tags
and list
etc. should be manifested in the templates that display and edit those fields, referencing configuration tiddlers along the lines that @tobibeer is suggesting.
Anyhow, something as radical as removing the core JS metadata about tiddler fields wouldn't be something we could do in 5.1.x, but might be one of the things that's worthwhile to consider for 5.2.0!
I edited the checkbox widget to do this. The demo site with some test cases is here: http://ooktech.com/jed/ExampleWikis/ListManipulation/testcheckboxwidget.html I am going to do a pull request now. It may need some cleaning up because I copied the part specifically for tags instead of trying to combine the new functions with that. I am not sure how much can be done there though.
I edited the checkbox widget to do this.
Oh nice! Great you picked this up.
I have removed the unnecessary duplicate code from @inmysocks version -- seems to work OK. Some conflicts when both the field
and list
attribute point to the same field.
Anyway -- my version is posted here.
Needs refinement, but this will only be worthwhile once discussion on how to modify the widget is concluded. Perhaps, the checked
and unchecked
attributes should use a filter expression rather than a single title only. In that case, they would modify the list of items in the target field rather than overwriting it.
Hi guys,
May I make two alternative suggestions based on the previous discussions. Both avoid the introduction of a new widget.
Alternative 2 is pretty easy to realize based on @matabele existing code. Alternative 1 is similar but uses mode
instead of list
and field
.
Based on the discussion in https://github.com/Jermolene/TiddlyWiki5/pull/2003, picking up the comments of @tobibeer and @matabele from 24/25 Dec.
invert
, item
) suggested by @matabele and @tobibeer mode
attributeThis would, however, require that the mode attribute defaulted to list -- and to toggle a field, this default would need to be set to single :-/
I think this is solvable and I agree with @tobibeer here how to approach this issue (the widget first looks at what mode is used and then decides how to interpret the other attributes). Also I think it makes sense to add two new attributes.
invert
as @tobibeer suggested as alternative syntax for invertTag
(invertTag
should be marked as depreciated in the tw docs).item
as @matabele suggested as alternative syntax for tag
(tag
should be marked as depreciated in the tw docs).This way we have all we need!
Example: A checkbox is clicked
mode=list
tags
is specified
invert
item
mode=field
item
is specfied
selected
or unselect
as fallback depending on the checkbox "state".I'm unsure of the purpose of the field, checked and unchecked attributes -- better functionality is available with the $radio widget -- as in this example:
Yes, I agree. The checkbox widget should only act as toggle, just like a checkbox of an html form (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox). In contrast, the radio widget and the select widget are correct means to assign different values. This is why I suggest to use @matabele's idea to introduce an item
field (using selected
or unselect
as fallback).
I agree -- but changing invertTag to invert will break backward compatibility
No! ''We do not replace it, we use it as alternative syntax.'' invertTag
and tag
both stay alive, however deprecated and hidden in the docs at tiddlywiki.com in favour of invert
and item
! This way we do not break backwards compatibility and new users learn the new attributes.
I also like your idea to distinguish between list
and field
, field
being used for single-value fields and list
for lists. This is very similar to my intiatially suggested mode
attribute but more explicit.
Only addition to your demo:
the introduction invert
and item
attributes in favour of invertTag
and tag
(which, as said in Alternative 1, both stay alive), however deprecated and hidden in the docs at tiddlywiki.com! Again, this way we do not break backwards compatibility and new users learn the new attributes.
@felixhayashi
I have posted a new version here, which addresses most of the problems mentioned. The widget can manipulate a list in any field (the tags
field being the default), and can handle strings of 1 item. Thus no need to have different modes.
The next issue is to settle on the attribute names, to maintain sufficient backward compatibility, but encourage new terminology reflecting the general purpose nature of the widget.
I suggest attribute values of:
tiddler -- tiddler to manipulate (default to currentTiddler)
list -- list to manipulate (default to tags
field)
index -- data index to manipulate (overridden by list attribute if both are specified)
item -- item to toggle
alt -- alternate item when values are switched
invert -- invert the checkbox -- "true" or "yes"
class -- css class for the checkbox
To maintain complete backward compatibility, would need as alternative attributes (to be overridden by the new attributes if also specified):
field for list tag and checked for item unchecked for alt invertTag for invert
Which of these would be necessary?
@felixhayashi
As mentioned over here: https://github.com/Jermolene/TiddlyWiki5/pull/2003 -- a cleaner approach might be to create a new $checklist widget to be used alongside the legacy widget until depreciated.
@tobibeer
Yes -- a list of 1 item where the item contains spaces will be bracketed with the existing code -- I think this could be handled automatically, by recognising the case when a list drops to a single item and switching to other code which drops the brackets. Does present a problem when, however, someone tries to add another item to the list -- there is no way that the code can tell the difference between an item containing spaces and a list of items.
Looks as if another attribute will be required -- pity, this makes things messy :-(
field -- target field (default to tags) index -- target index (or else "true" or "yes") mode -- "list" or "string"
Why is this necessary -- would it not be better to move toward uniform handling of all data?
Upon reflection -- my preference:
Create a new $checklist widget which always treats the target field/index as a list (including the tags
list and 1 item lists), and uses attribute terminology reflecting this (this was the original functionality of the legacy widget, before the introduction of the field
attribute.)
Where fields need to be toggled between string values -- use the $radio widget (which has always targeted this usage case.)
Advise users that the $checkbox widget will be depreciated at some stage (as it is neither here nor there -- not really a list handling widget and inferior to the $radio widget for toggling field strings.)
I think this could be handled automatically, by recognising the case when a list drops to a single item and switching to other code which drops the brackets.
That would not be correct, I'm afraid. Either a field is handled as a list field and so it definitely requires list-encoding... or it is not to be handled as a list field and so we should never do list-encoding. The user has to be explicit about this point, there must not be any guessing about it... so long as we have no global field configuration (which I think we agreed was not something we want to pursue).
there is no way that the code can tell the difference between an item containing spaces and a list of items.
In other words, it must never attempt to guess. The user has to be specific and thus the code knows how to treat the addressed field data.
index -- target index (or else "true" or "yes")
I think it should be the explicit name of an index, no truthy thing.
Alternatatively, we could have the user specify a text-reference to be manipulated and then how to handle the target, i.e. as a list or not. Then it could be whatever text-references can handle, rather than however we chose to implement and interpret attributes.
@tobibeer
I'm a fan of TextReferences -- in this case, only 1 attribute to specify the target tiddler and field or index. Does, however depart from the schema used in most of the other widgets. I would prefer that the $action-setfield widget also used TextReferences (functionality that could be easily added.)
Hi @matabele
Create a new $checklist widget
Ok, I think I agree with you and @tobibeer here. This is also politically the best choice as it is less controversial and @Jermolene may favour this over a modification of the existing checkbox widget.
In this case, however, please do not add an alt
attribute, as we don't need that!
We only need: tiddler
field
, index
, item
, invert
, class
for our new widget.
<$checklist
tiddler="the tiddler to modify"
field="a list field"
index="an index of a data tiddler that holds a tiddler list"
item="the value to toggle"
invert="whether to invert the toggle"
class="html class">
bla
</$checkbox>
Advise users that the $checkbox widget will be depreciated at some stage (as it is neither here nor there -- not really a list handling widget and inferior to the $radio widget for toggling field strings.)
I would not do that. Just let it live and leave it as is. As said, it is often quite handy to have checked
unchecked
values, e.g. if you want to store true
or false
as field values when doing a toggle.
@tobibeer
When toggling values (such as true/false) -- I believe list format is best. When multiple instances are permitted, several such switches can be maintained in one field/index.
Take, for example, a list of values todo/done -- corresponding a list of shopping items/tasks. We need to maintain the positional information in this list. If the value is deleted, this is lost.
If strings are to be selected (such as Joe Bloggs/Amanda Stephens/Rafael Yates -- then use the $radio widget and avoid the list format.
Why, therefore, avoid the alt
attribute?
Also, I prefer the use of list
rather than field
-- this emphasises the usage for the widget and maintains consistency with the $action-listops widget, which also targets lists.
Hi @matabele
Why, therefore, avoid the alt attribute?
What is the purpose of alt
? A value is either toggled or removed, just like the checkbox widget currently toggles or removes a tag. Why would you want to switch values?
Also, I prefer the use of list rather than field -- this emphasises the usage for the widget and maintains consistency with the $action-listops widget, which also targets lists.
The word list is already contained in the widget name so it is clear that the purpose is to manipulate lists. It makes more sense to use field
as attribute name as (1) a list field is still a field (2) almost all TW widgets use the attribute tiddler
to denote the tiddler being changed in combination with field
to denote the field that is changed – so it fits with the convention to call the attribute field
not list
imo.
@felixhayashi
I am looking toward the eventuality of lists permitting multiple items with the same name. We may wish to maintain a list of tasks, for example, with a corresponding list of switches associated with these tasks (todo/done, for example.)
To maintain positional correspondence, the value must not be deleted, but must, at a minimum be replaced with a placeholder -- hence the need for the alt
attribute.
Actually, I think I must check that the code always switches values in place -- presently, values are sometimes removed and the replacement pushed to the list (although I'm unsure of when this occurs.)
There are all sorts of unresolved issues here, as several widgets assume uniqueness and search for the first instance of an item.
I am looking toward the eventuality of lists permitting multiple items with the same name. We may wish to maintain a list of tasks, for example, with a corresponding list of switches associated with these tasks (todo/done, for example.)
Ah I get it, you mean key:value pairs in a list? task1:todo task2:todo
and then toggling e.g. task2:done
? Ok, this would make sense.
But using exactly the same argument you used when comparing $checkbox to $radio, this would be better served with a new $radiolist
widget which would allow you to use more than binary switching values. Just saying.
@felixhayashi
Mmm -- still trying to find my way with this. Seems that the widget would need to obtain the positional index from one list (i.e.search for a unique item in a set, such as a set of tasks) , then toggle the value of the corresponding item in another list (for example, todo/done.) I'll have to think on that one.
At this stage, there are many possible approaches to take -- need to settle on one one of these before going down other roads with new functionality.
There is one approach to checklists possible with the existing widget.
We have one list of common shopping items (milk, cheese, bread, tea, sugar ...)
And in another we maintain a list which switches between the item and its alt-item (bread/needbread, for example.)
Then use a stack of $checklist widgets to toggle the values in the second list accordingly.
As you can see, I have checklists in mind here. And yes, a $radiolist widget would be useful.
I have posted an example of a checklist here
This uses two lists to create a checklist.
Thoughts? I haven't yet attended to the attribute name changes -- but I have changed the name of the widget, as this appears to be the consensus upon this.
OK -- this can be made without the alt
attribute -- delete the macro and the alt
and invertTag
attributes. Seems that, if two lists (or a filter and a list) are required to maintain a checklist -- then the alt
attribute may be redundant.
Hi @matabele
looks good :+1:
Seems that, if two lists (or a filter and a list) are required to maintain a checklist -- then the alt attribute may be redundant.
Sorry, didn't quite get that.
I haven't yet attended to the attribute name changes
In any case I highly recommend <$checklist field="shopping-list"
instead of <$checklist list="shopping-list"
.
@matabele, I very much like the specificity of $checklist. We're always handling list fields and only list-fields. Simplifies understanding what it does and how to use a lot.
What is the conclusion w.r.t. the alt
attribute? Does it have any possible use?
There's not much code associated with leaving it in, however, if it's no use, it only contributes to complexity and confusion.
This quotation may be of interest:
When to Use What Widgets
Ever since the first edition of Inside Macintosh in 1984, the rule has been the same for when to use checkboxes versus radio buttons. All subsequent GUI standards and the official W3C Web standards have included the same definition of these two controls:
- Radio buttons are used when there is a list of two or more options that are mutually exclusive and the user must select exactly one choice. In other words, clicking a non-selected radio button will deselect whatever other button was previously selected in the list.
- Checkboxes are used when there are lists of options and the user may select any number of choices, including zero, one, or several. In other words, each checkbox is independent of all other checkboxes in the list, so checking one box doesn't uncheck the others.
- A stand-alone checkbox is used for a single option that the user can turn on or off.
Looks as if: the alt
should go, and I must get busy writing a $radio-list widget. I favour $optionlist for this widget.
Hi @matabele
[…] Looks as if: the alt should go, and I must get busy writing a $radio-list widget. I favour $optionlist for this widget.
Well, I also think that the $checklist
widget should rather only toggle list items (i.e. adding an item to the list or removing it) and not replace item values with other values. So imo the widget doesn't need the alt
attribute. If there are some serious use cases, it can always be easily added later.
Looks as if: the alt should go, and I must get busy writing a $radio-list widget.
Hmm, not sure if this is easy to implement but I agree that radiobuttons are the way to go when having to choose from several options. Maybe you do not have to create a separate widget for this but can use a combination of list, radio and sendaction widgets… Anyway this is a different topic I guess.
Hi @felixhayashi
There is a considerable amount of shared code between the $checkbox and $radio widgets -- I also had the idea of creating a single widget with a style
attribute to choose between checkboxes and radio options. Would't be too difficult in the absence of the invert
attribute.
I think I'll have a go at starting off with the $radio widget and see how far this goes -- then get back to the $checklist widget once I'm done. Don't wont to end up with too many widgets though.
Hi @matabele,
but don't you want to finish the checklist widget first so a pull request can be created to add this widget to the core? I mean it appeared to me to function very well and only needs polishing. Also modifying list fields with checkboxes is a critical feature.
Hi @felixhayashi
I have done further work polishing up the code. Needs thorough testing though, as I seem to have removed a lot of code for which I couldn't see any purpose (but might be necessary in edge cases.)
The latest version can be found here: http://checkbox-list.tiddlyspot.com/
You appear to have a use case -- please check this out thoroughly; then I can create a pull request.
@felixhayashi @tobibeer @inmysocks
I have uploaded my first attempt at a $radiolist widget here: http://radio-list.tiddlyspot.com
A little more complex than I would have liked, but seems to work. Difficult to explain how to use this -- have a look at the examples. The list mode example targets the tags
field, but the widget works with any target field. The option lists must be stored in fields.
Thoughts?
@matabele, not exactly sure I understand the usecase for a "radio-list" widget, since the purpose of radio buttons is to select one out of many, thus always only store one.
So, the obivious question at hand would be: when would I want a list field manipulated via radio buttons and why? Wouldn't that be a design faux-pas?
Best wishes...
@tobibeer
I have similar thoughts -- as I was building the widget, it became apparent that a field was going to be needed to store each group of options -- so no storage advantage over the legacy widget. Consequently, I wasn't sure if the widget offered any advantage over the legacy widget. A list can, in any case, be assembled dynamically using a filter expression to 'collect' the selected values from each option group (using the legacy widget.)
Once built, however, it appeared that in one usage case -- the manipulation of a list, where each item in the list is to be chosen from an option group -- the syntax was a little briefer, and the maintenance of each option group facilitated.
One option is to build the option group from a filter expression rather than from a reference to 'static' list -- so both the $list filter
attribute and $radio widget options
attribute are specified with an identical filter expression. In many cases, a filter expression could be constructed which does not require a custom field, but can use all or part of a generic list e.g. select from the option group of 'days-of-the-week'. This may be a usage case for your make[] filter operator -- which can construct such an option group with ease.
At that point, I thought that I should post my efforts to see if anyone could see any practical use for the thing before spending more effort on it.
The widget is backward compatible with the legacy widget -- so I suppose there would be no problem with keeping the old name and adding the functionality in case someone might find a use for it -- its only a little added code. When taken in combination with the $checklist widget (where the code has been considerably simplified) the pair use about the same space as the pair of legacy widgets (yet offer enhanced functionality.)
Anyway -- I'll see what others make of the two widgets.
One possible use -- a system tag editor. Saves having to search for that elusive system tag :-) Although, I suppose, the checklist widget is more appropriate.
Similar reasoning applies to the field
, checked
, unchecked
and default
attributes of the $checkbox widget.
My preference for the core -- to leave the $radio widget as is, and replace the $checkbox widget with the $checklist widget. The legacy $checkbox and the $radiolist widgets can be consigned to a plugin (should anyone need their functionality.)
One question: some prefer the use of the name field
over list
-- what is the most elegant way of coding to make both options available -- as in: this.checklistList = this.getAttribute("list" || "field", "tags");
(which doesn't work.)
This seems rather cumbersome :-(
if (this.hasAttribute("list")) {
this.checklistList = this.getAttribute("list");
} else {
this.checklistList = this.getAttribute("field", "tags");
}
One possible use -- a system tag editor. Saves having to search for that elusive system tag :-) Although, I suppose, the checklist widget is more appropriate.
I'd be thinking more in terms of a (filterable) select widget... but then again, only a single value to be set as well, so no list-field-mgt needed, imho.
One question: some prefer the use of the name field over list -- what is the most elegant way of coding to make both options available
@matabele, sorry to dwell on this, but I would just call it field
because it goes with the convention of widgets having an attribute field
.
Think of it: When you would ask a user that doesn't know your checklist widget "how would you expect to tell this widget which tiddler to use as target?", the user will certainly answer "I am used to adding a tiddler
attribute", if you then ask "and how to decide in which field to store a result?" then the user will most inuitively say "well, I'll use the field
attribute", if you called it list
this intuition will not work. Of course you could allow several aliases for field
like tags
or list
, but why – this only bloats your code and looks cumbersome as you said it. The name of the widget <$checklist
makes it pretty clear you are dealing with lists.
Moreover calling the attribute list
can be confusing. The list
field is a special field in TiddlyWiki and users may think that <$checklist list="…"
somehow means that the checklist widget is only good to store values in the list
field. Moreover <$checklist list="list"
looks strange while <$checklist field="list"
doesn't. Also if you look at your variable this.checklistList
it would look better if it were called this.checklistField
.
@tobibeer
There's another option -- to move the functionality of the checked
, unchecked
and default
attributes from the $checkbox widget to the $radio widget. They form a shorthand for radio select options, and would be more at home there.
@matabele
There's another option -- to move the functionality of the checked, unchecked and default attributes from the $checkbox widget to the $radio widget.
Why would you think those need moving? To me it appears that $checkbox simply implements the (basic HTML) element behavior expected of a checkbox.
They form a shorthand for radio select options, and would be more at home there.
Can you give an example of what you mean here? Are you saying that a checkbox can be modeled as radio buttons whereas both states are radio options and if neither is selected we possibly got a default value? If so, then I don't quite see this proposal as a plan worth pursuing. After all, checkboxes exist for the very reasons for which they're used... possibly mildly overloaded, not sure. Is it that you find something missing in the RadioWidget and if so, what?
@tobibeer
The $checklist widget entirely duplicates the use of the $checkbox widget with respect the handling of tags (and extends this to other fields.) The $checkbox widget could then be removed, if the field
mode were moved to the $radio widget.
Although this usage seems to adhere more closely to the convention for radio buttons ...
By convention, radio buttons are used when there are two or more mutually exclusive options in an option group -- in this case we have a group of two items (clicking a non-selected radio button will deselect the other buttons.)
A checkbox is used for a single option that the user can turn on or off. When checkboxes are used in a list of options, the user may select any number of choices (the state of each checkbox being independent of all other checkboxes in the list.)
.. this would be confusing if a list of such radio buttons were presented to a user.
OK -- I concede.
Perhaps the better option is to remove the code for the tag
mode from the $checkbox widget -- leaving only the field
mode. This would be simpler, and the code in the $checkbox widget could be considerably abbreviated.
Three widgets:
-- the $checkbox widget for yes/no/default type situations (string mode)
-- the $radio widget for mutually exclusive options from an option group (string mode)
-- the $checklist widget for handling lists (including the tags
field)
The other advantage; the $checklist widget can be introduced without upsetting the status quo -- and the duplicated functionality can be removed from the $checkbox widget later.
@matabele
Perhaps the better option is to remove the code for the tag mode from the $checkbox widget -- leaving only the field mode. This would be simpler, and the code in the $checkbox widget could be considerably abbreviated.
Good thought, I strongly agree. It should be hidden from the docs and (once merged) only the $checklist widget should be responsible for this task.
The other advantage; the $checklist widget can be introduced without upsetting the status quo -- and the duplicated functionality can be removed from the $checkbox widget later.
That's how it should be done. I think we should create an issue for this once checklist is merged. However, we would need a period of one or two years where the attributes are marked as deprecated before it is legitmate to remove them.
@felixhayashi
I had a look through the tw5.com code.
field
modetag
mode in only a couple of examplestag
mode could easily be depreciated from tw5.com and removed from the docsMy suggestion is to move legacy widgets (or legacy forms of a widget, such as this) to a plugin "$:/plugins/legacy-code" -- which can be easily removed by those not using the legacy form of the widget.
Elsewhere, the widget is used in tag mode in only a couple of examples
Yes, once merged, we should create a PR where all these are replaced with checklist
My suggestion is to move legacy widgets (or legacy forms of a widget, such as this) to a plugin "$:/plugins/legacy-code" -- which can be easily removed by those not using the legacy form of the widget.
Very interesting idea
At the moment, a checkbox can be used to toggle a field. It would be nice if the checkbox widget could operate in a "list" mode, where a check would add the value to a field list-style and an uncheck would remove the value from the list again.
So if e.g. checkbox A B and C are toggled and they operate in "list" mode and store their values in field X then field X would be:
[[value of A]] [[value of B]] [[value of C]]
.If checkbox B is unchecked the list will be
[[value of A]] [[value of C]]