CSS attribute selector using $=

Here is what we’ve been trying to achieve with $= (instead of *=). On my TW desktop, it’s possible to have one tiddler (i.e. window) overlaying another. This UI affordance provides a way to bring a background tiddler to the front. *= works but fails when there is a significant overlap in the tiddler names (as I said above, I’ve solved it for now by renaming them).

tiddlers-behind

It’s a text substitution problem. The <<t>> is included, but it produces CSS code that the browser can not read. I need a bit more time to experiment. will be back soon.

This works for me

title: New asdf

\procedure custom-css()
.tc-tiddler-frame[data-tiddler-title*="Draft of"], 
.tc-tiddler-frame[data-tiddler-title$="$(currentTiddler)$"] {
    outline: 2px solid blue;
}
\end

\function f.css() [<custom-css>substitute[]]

<style>
<<f.css>>
</style>

Nested seems to work too

\procedure custom-css()
.tc-tiddler-frame {
  &[data-tiddler-title*="Draft of"],
  &[data-tiddler-title$="$(currentTiddler)$"]
  {
    outline: 1px solid blue;
  }
}
\end

\function f.css() [<custom-css>substitute[]]

<style>
<<f.css>>
</style>

But if that’s the case, why does it work fine with *= ?

Coincidence? I do not really know, how thw browser CSS parser works.

The problem with something like this: some text<<variable>>more text is, that the TW renderer creates 3 text nodes in the DOM. So F12 will show something like this

some text
variable text
more text

Depending on the CSS rule, the extra line-break may break CSS syntax. If the browser does not understand CSS syntax, it will be ignored silently.

So creating a procedure with the right syntax and some text substitution placeholders seems to do the trick and IMO it is simpler to read and debug.

Using a function f.css() [<procedure>substitute[]] and calling it with <style><<f.css>></style> only creates 1 text node, that the browser CSS renderer seems to like more.

I came back to delete that post, when I realized that extra text could indeed cause a problem with endsWith but not includes. Too late.

This was a nasty one, but I think I found it.

The problem is that the draft title looks like

Draft of 'FooBar'
<!--            ^--- close single-quote   -->

Which doesn’t match – I assume – your value of t

If you replace [data-tiddler-title$=<<t>>] with [data-tiddler-title$=<<t>>\'], I think it will work:

title: FooBar
tags: bk-edit-positioned

\define pos-draft-tiddler() .tc-tiddler-frame.tc-tagged-bk-edit-positioned.tc-tagged-bk-edit-positioned[data-tiddler-title$=<<t>>\'][data-tiddler-title*="Draft of"] 

<p>Dummy Content</p>

<$let t ="Bar">
<style><<pos-draft-tiddler>> {background: #ffc;}</style>
</$let>
1 Like

@pmario thanks for the considerable thought you put into this, but, sadly, that didn’t work either. Which is actually not surprising when the key to the solution (yes, we have a solution) was pointed out by Scott.

@Scott_Sauyet :clap: :clap: :clap: You almost nailed it in one.

First, what didn’t work: <<t>>\'
Just looking at that had a smell to it. But you gotta try it when someone’s trying to help. Outcome: “missing [ in Filter expression” ← so that raised an eyebrow or six :wink:

But you made me revisit how t was being constructed. As we know, TW uses ' and ' to wrap the name when it’s a draft: Draft of 'tiddler name' and I was certainly tinkering with those quotes to get a clean name just for comparison purposes. While I was using *=, if something was a little broken at the end of the string it was of little consequence. When I then switched to $=, now the end of the string has to be perfect – that ending single quote was absolutely vital, but… using trim, I’d removed it.

  t={{{ [<currentTiddler>search-replace[Draft of '$:],[]trim[']addprefix["]addsuffix["]] }}}
  t={{{ [<currentTiddler>search-replace[Draft of '$:],[]addprefix["]addsuffix["]] }}}

et voila!

and “inline:6”

.tc-tiddler-frame.tc-tagged-bk-edit-positioned.tc-tagged-bk-edit-positioned[data-tiddler-title*="Draft of"][data-tiddler-title$="/.rgt/bk/list-tiddlers-behind'"] { ...

:heart: Thank you all for taking a look and digging in. Thanks to Scott for nudging me to step back and look a little closer at prior code that was setting me up to fail.

1 Like

Then an almost-bow from me!

Something is weird there, as this is—to my mind—procedure output and CSS text, neither of which should object to \'. And it works in my simplified test, when run in Edit/Preview mode:

FooBar.json (400 Bytes)

I didn’t try to follow all the complexities of how you built this, so I’m missing something important. But how did that \' end up in a filter expression?

And clearly it’s better to fix this at the source than after the fact. I didn’t know if t was being used for multiple purposes, but if you do want it clean, I’m still betting that appending \' would work. If you need t only for this, then of course you should clean it up.

Once I had mine working, I looked again at the conversation., knowing that I’d seen something about trimming quotes, but not finding it. But I don’t do well with screenshots of source code and even worse with videos of it changing, so I’m guessing I saw it in the video.

I’m glad this helped. Am I right that this is designed to do something interesting with Edit/Preview mode for tiddlers with a specific tag? If so, I’m intrigued by what you use this for, as it’s fairly rare for me to turn on preview mode. Or did I make unwarranted assumptions by inlining this in my tiddler?

In any case…

Six, huh? I knew there was something odd about you!

Baffling, I agree. Hence the eyebrows comment.

Nope. You saw the result. TW thinks we’re in a filter. :exploding_head: And besides, now that I’m not trimming the trailing quote, I don’t need to append it ← that was the true bug all along.

I think if you right-click → new window on the gif you’ll get a picture of what is intended. It’s a (cough) simple “bring to front” function. Tiddlers in my system can occupy the same screen coords. I need a way to choose one and bring it to the front.

Now that the whole thing has been cleaned up (all noisy CSS debugging removed) it’s much clearer, I believe:

<$let t={{{ [<currentTiddler>search-replace[Draft of '$:],[]addprefix["]addsuffix["]] }}}>
<style>
.tc-tiddler-frame.[data-tiddler-title*="Draft of"] {
  z-index:auto;
}
.tc-tiddler-frame.tc-tagged-bk-edit-positioned.tc-tagged-bk-edit-positioned[data-tiddler-title*="Draft of"][data-tiddler-title$=<<t>>] {
  z-index:{{!!z}};
}

I suppose the action that sets the {{!!z}} field might help…

  <!--$ bring-forward
    @inscope dom-target <tiddler>
    @private This is a private declaration in <<doc-link list-same-position-tiddlers>>.
    @comments Works through the StoryList searching for draft tiddlers tagged 
    `bk-edit-positioned` having the same screen position as the tiddler specified in 
    `dom-target`.
    Each matched tiddler has its `z` field set to a `z-index` value derived from 
    `EDIT-POSITIONED-DRAFT-Z-INDEX` minus its ordinal position in the list. 
    `dom-target` has its `z` field set to `EDIT-POSITIONED-DRAFT-Z-INDEX`, raising its 
    `z-index` to the top.
    <br><br>
    A CSS rule defined elsewhere in this tiddler uses the `z` field values as the 
    `z-index` value for each matched tiddler.
    <br><br>
    <<doc-link EDIT-POSITIONED-DRAFT-Z-INDEX>> is specified in [[$:/.rgt/bk/constants]].
  $-->
  \procedure bring-forward()
    <$let
      currentTiddler=<<dom-target>>
      pos={{{ [<currentTiddler>get[screen-position]] }}}
      current-z={{{ [<currentTiddler>get[z]] }}}
    >
      <<alog bring-forward "dom-target pos current-z">>
      <$list filter="[.get-positioned-drafts[]]" variable=tid counter=ix>
        <% if [<tid>get[screen-position]match<pos>] %>
          <$let z={{{ [<EDIT-POSITIONED-DRAFT-Z-INDEX>subtract<ix>] }}}>
            <<alog "bring-forward:adjusting-down" "z tid pos">>
            <$action-setfield $tiddler=<<tid>> $field=z $value=<<z>> />
          </$let>
        <% endif %>
      </$list>
      <<alog "bring-forward:adjusting-up" "EDIT-POSITIONED-DRAFT-Z-INDEX dom-target pos">>
      <$action-setfield $tiddler=<<dom-target>> $field=z 
        $value=<<EDIT-POSITIONED-DRAFT-Z-INDEX>> />
    </$let>
  \end bring-forward

@EricShulman I tested removing the doubled .tc-tagged-bk-edit-positioned but I still need it. Speaks to a structural/ordering issue somewhere in my CSS. That’s for another day :blush:

Oh, absolutely, if you don’t need the trimmed value, don’t trim!

I do wonder what’s the essential difference was between my simplification and your actual code that allows mine to run with \' and not yours, but it’s not really worth any more investigation.

I did that, but spent my time trying to read the code and not really watching what the behavior was supposed to be. Serves me right for not being a visual person! :wink:

Not often, but every now and then, I miss jQuery. This would likely be simpler there!

It’s been a very long time since I used that trick. I recognized it when seeing it, but I think it’s been at least 15 years…