Willing to pay $50 for a special thingy

Hi everyone

I am seeing via Google searches that there seems to be a jquery way to force all details elements in a webpage open. See here and here

Perhaps it is necessary to give the details elements id’s as part of this process, as in the second example above. I could work with that, if that were a necessary condition.

I would be willing to pay $50 to get a tiddler that I could toggle on and off with a tag, so that all the details elements in my file would be displayed as open when tagged and closed when untagged, or vice versa.

The hitch is that the details can’t be macros. They have to be html details elements. Otherwise I will have three levels of tiddlers: article tiddlers that use macros to transclude ‘block’ tiddlers, block tiddlers that contain macros that transclude tidlders with details elements, and the tiddlers with the details elements.

I could either pay someone directly, or contribute toward the TiddlyWiki initiative as I did the other day when Saq gave me a solution I needed for something else. Please message me before creating a solution in order to avoid duplication of efforts. I will be traveling this weekend so my reply may be delayed.

Thanks in advance, Dave

2 Likes

Here: toggle-details.json (881 Bytes)

Demo: Toggle every details — a non-linear personal web notebook

Try it

This use CSS: when the tag $:/tags/Stylesheet is added to the tiddler “Open details element with css”, the content of every detail element become hidden.

So in order to works, the content of every detail element need to be open by default (when the stylesheet is not active), meaning you need to add the attribute “open” in the detail element, e.g:

<details open>
<summary>Summary</summary>

The details here
</details>

If this answer satisfy you, please donate to the development fund of tiddlywiki :slight_smile:

6 Likes

Thanks @telumire, I will try it out on Monday when I get home but it looks like a winner. I will make the donation after I try it out. Blessings.

2 Likes

I wonder if the shortcoming is going to be that with the tag in place, you can no longer open the details elements by clicking on them. I might be wrong but am guessing Dave would still want to be able to toggle an individual details element by clicking on it.

This would be a nice use case for custom widgets that will become available with the parametrized transclusions work. It would be possible to write a custom widget <$$details> that created a details element open or closed by default depending on a configuration tiddler.

2 Likes

how important is it that the trigger is having a tag on a tiddler or not? An action widget that just iterates over all the details elements on teh page to open/close each one would probably be easiest and it wouldn’t have the problem of preventing any of the normal interactions with a details element.
But it would be a button or any action that would trigger an action widget instead of adding or removing a tag.

3 Likes

Yes it’s a limitation of css (and javascript, according to this stackoverflow user), the detail content can’t be displayed when it’s closed so I simulate the closing with CSS. However, it is possible to disable the custom css using an attribute selector so that the detail element can be manually toggled even while the stylesheet is active:

details[open]:not([open=""]) {
     display:contents;
     font-size: 0;
     line-height: 0
}

details > summary {
     line-height:initial;
     list-style:none;
     font-size:initial
}

details>summary:is(::marker,::-webkit-details-marker){
     display:none 
}

summary::before{
     content:'▾';
     font-size:15pt
}

details[open]>summary::before{
     content:'▸'
}

It’s not perfect, you need to click it twice to restore the default behavior, but it works …
The first click remove the open attribute, then the second reset the open attribute, like this:

  • first click: <details open> (the content is hidden by the stylesheet)
  • second click: <details> (the details content is hidden by the browser)
  • third click: <details open=""> (the style doesnt apply anymore, so the content become visible, and at this point the details element can be used like normal - however to override the behavior of the widget we need to refresh the tiddler content).

If macro were allowed, it would be possible to set the open attribute with a field value for example instead of using CSS.

@DaveGifford , would that be okay if the output of the macro is a html detail element ?

2 Likes

I’m thinking a tm-message that closes (or opens) everything. It would have to be activated by an action, of course.

I found a solution ! The solution was to use “:focus-within” AND “pointer-events:none;” :

details:focus-within{
pointer-events:none;
}

details *:not(summary){
pointer-events:all;
}

details[open]:not(:focus-within) {
     font-size: 0;
     line-height: 0;
}

summary {
     line-height:initial;
     list-style:none;
     font-size:initial
}

summary:is(::marker,::-webkit-details-marker){
     display:none 
}

summary::before{
     content:'▸';
     font-size:15pt
}

details:is([open=""],:focus-within)>summary::before{
     content:'▾'
}

This way, I can prevent the open attribute to be modified when clicking the details with “pointer-events:none”, BUT the summary tag can still get the focus and I can use that to disable the CSS on a click. Problem solved!

Demo: Toggle every details — a non-linear personal web notebook

Try it

EDIT: Mh not exactly, pointer-events disable the links in the detail element. I will update this comment if I find a workaround.
EDIT2: I think I got it now! Let me know if I overlooked something.
EDIT3: Ok so the trade-off is that since this lock the open attribute, while the stylesheet is active you can open a detail element but clicking outside of the detail will close the detail element. To store the state of the detail element an input would be needed. Something like <input type="checkbox"><summary>..</summary></input> + some css to hide the checkbox. I dont know if that would be alright with you @DaveGifford

2 Likes

David, @telumire may have the answer to your question, but I wonder if a more useful solution could be designed?, if we revisit the question.

Just to clarify out of interest;

  • What if you use the html details element but the attribute(s) are macros?
    • I wonder if this constraint is valid, see questioning the constraints.
  • You point to notes to “force all details elements in a webpage open”, but what do you perceive as the “webpage” when you are talking about tiddlywiki?
    • All open tiddlers?
    • All tiddlers open or not?
    • In the current tiddler? - I assume this one because you want it toggled using a tag on the current tiddler?
  • Also where is the content of the details widget?
    • Inline in the tiddler
    • Transcluded from a named tiddler
    • Somewhere else?
    • All of the above

Questioning the constraints

  • This seems to me more a “problem” you perceive because of where you currently are in developing a solution.
  • Even the tag being the “switch” is a potentially unnecessary constraint.

So give the above would it be fair to say?

Whenever the html details tag is used be able to globally toggle all open and all closed, regardless whether each is open or closed already by the user?

  • Is this really what you want, or something else?

Hi everyone

Thanks for all the attention lavished on my request.

I came home sick, so I have not played with Telumire’s request yet. I am going back to bed. But before I do, I think I can answer a couple of questions:

  1. I am fine with the trigger being something other than tagging. I just want to click a button to toggle details open or closed.

  2. My use case means that:
    a. Printed pdfs, and editing, can have the details all open, and I won’t need to close any individual details. So if they are all ‘locked open’ I can live with that.
    b. For exporting to static htmls I will need all details closed, but with the ability to open and close individual details.

  3. An example of the type of files I will use is at evangelismo/misiones (giffmex). Click the articles tab, and open an article. You will see I use macros to transclude ‘block’ tiddlers. Now go to the block tab and open a block with a details element to see what I did.

I want to be able to write the content in the block tiddler, not paste a macro there that transcludes a third tiddler. But if there needs to be a macro “define” at the top of the block tiddler, I am fine with that as long as I can hit edit and start addling content, and not have to scroll down somewhere first in order to do that. I hope that is clear.

Thanks again for all your help. I will try telumire’s efforts tomorrow, or later today if I feel better. Writing this explanation is way easier for my foggy brain right now than experimenting and comparing etc.

FYI: I have a solution I am building that works through transclusion and as a result has other helpful features eg {{tiddlername||local-details}} but the content will always need to exist in a seperate tiddler eg tiddlername.

  • I am just working on a open all and close all buttons.

Let me know if you would like to try it.

I know you said no macros…but I made one anyway. :stuck_out_tongue: Could still be useful

You can put all of your articles content, wikitext included, right inside the macro parameter. Try this out…

title: $:/.giffmex/ui/details
tags: $:/tags/Macro
text:

\define details(sum det)
<$list filter="[[$:/.giffmex/ui/details]get[state]] +[else[]match[open]]"
emptyMessage="""
<details><summary>$sum$</summary><div>

<div style="text-align:right;"><$checkbox tiddler="$:/.giffmex/ui/details" field="state" checked="open" unchecked="" default="">&nbsp;open all details</$checkbox></div><br>

$det$
</div></details>""">
<details open><summary>$sum$</summary><div>

<div style="text-align:right;"><$checkbox tiddler="$:/.giffmex/ui/details" field="state" checked="open" unchecked="" default="">&nbsp;open all details</$checkbox></div>

$det$
</div></details>
</$list>
\end

Here’s what your article code could look like:

Here’s one details opened

ViewMode1

And after checking the box in the first example, both examples are opened
unchecking either checkbox will close both. You can put the checkbox anywhere you want, it doesn’t have to be inside the macro

Hi everyone

Thanks again for your replies and assistance.

Brian’s macro is what I am trying to avoid, but I may have to settle for it. But first…

None of you did anything with the idea of using an “id”. There is information about this in the second link in my OP, and I even mentioned it in that post.

<details id="target-me">

Could something be set up so that if details has id of target-me, tagging a CSS tiddler similar to @telumire’s would apply a rule to force it open? And untagging the Stylesheet would just revert it back to normal “closed” details element behavior?

The link in my OP mentions applying this js document.getElementById("target-me").open = true; but I know nothing about js, so I just mention it in case it is helpful.

Hi Dave,

Using an “id” isn’t really necessary. Assuming you want a button, or set of buttons, that when clicked toggles all details elements in open tiddlers between open and closed, this can be done with a small JavaScript plugin. I think the efforts so far in this thread have been trying to focus on getting the job done with just wikitext.

You could even get more control and only toggle details elements that have a class that you have specified like “toggleme”.

If you don’t mind that the solution is JavaScript based you might get something closer to you what you are describing.

Regards,
Saq

Hi Saq, yes the use of JavaScript is fine. Just that when the details are closed, I would like users to be able to open individual details elements normally, and be able to select the contents, if they wish, to copy and paste. @telumire 's solution doesn’t allow that.

2 Likes

This should do what you describe it to do, it has absolutely no effect on the normal behaviour of the details elements. The biggest caveat on it is that since the open property of the details element is a dom property it will default to closed every time a tiddler is opened, this action widget can only affect details elements that are currently rendered (that is they are in open tiddlers), and if you open a new tiddler any details elements on it will be closed like normal.

here is an example of it in use:

<$button>Open Details<$action-showdetails state=open/></$button>
<$button>Close Details<$action-showdetails state=close/></$button>

<details><summary>Look at me!!</summary> And now it is open</details>

Put this is a tiddler, make a field called module-type and set it to widget and set the tiddler type to application/javascript

/*\
title: $:/widgets/action-showdetails.js
type: application/javascript
module-type: widget

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

const Widget = require("$:/core/modules/widgets/widget.js").widget;

const ActionShowDetails = function(parseTreeNode,options) {
  this.initialise(parseTreeNode,options);
};

/*
Inherit from the base widget class
*/
ActionShowDetails.prototype = new Widget();

/*
Render this widget into the DOM
*/
ActionShowDetails.prototype.render = function(parent,nextSibling) {
  this.computeAttributes();
  this.execute();
};

/*
Compute the internal state of the widget
*/
ActionShowDetails.prototype.execute = function() {
  this.state = this.getAttribute('state',undefined)
};

/*
Refresh the widget by ensuring our attributes are up to date
*/
ActionShowDetails.prototype.refresh = function(changedTiddlers) {
  const changedAttributes = this.computeAttributes();
  if(Object.keys(changedAttributes).length) {
    this.refreshSelf();
    return true;
  }
  return this.refreshChildren(changedTiddlers);
};

/*
Invoke the action associated with this widget
*/
ActionShowDetails.prototype.invokeAction = function(triggeringWidget,event) {
    const elList = document.getElementsByTagName('details')
    const self = this
    Object.keys(elList).forEach(function(element) {
        console.log(element)
        elList[element].open = (self.state === 'open');
    })
  return true; // Action was invoked
}

exports["action-showdetails"] = ActionShowDetails;

})();
1 Like

Hi, @inmysocks , I followed your directions to the letter. But something isn’t working. Can you check it again? Does it need a tag? Or maybe something got clipped when you pasted it?

The buttons show as Open DetailsUndefined widget 'action-showdetails' and clicking on them does nothing.

This part is key, and you need to save and re-load the wiki.

Yes, I did that, Saq. Then I put the buttons in a sidebar tiddler.

Try importing the attached file, which is my attempt at solving the same problem, its just been slow going on a touch screen. Import, save, reload, open the Buttons tiddler.

tiddlers.json (2.1 KB)

1 Like