Javascript code for extract a random line from a bullet list

What I’m trying to do

Hello. I’m trying to run a javascript code whose function is to scan a note in which there is a list of bullet point.

It has to find out a random row and display it.

I want to extract daily a random row from this bullet list but it runs without do it.

Things I have tried

I tried to find out a code correctly working but I found nothing.
When I try to run this code, it display nothing.

The code is:

// Controlla se l'editor è focalizzato
function isEditorFocused() {
    return app.workspace.activeLeaf && app.workspace.activeLeaf.view instanceof MarkdownView;

// Esegue il codice solo se l'editor è focalizzato
function runIfEditorFocused(callback) {
    if (isEditorFocused()) {
    } else {
        console.error("Editor is not focused");

// Codice per rilevare una riga casuale da una bullet list in un'altra nota
function getRandomLineFromBulletList() {
    runIfEditorFocused(() => {
        // Ottieni il contenuto della nota attualmente aperta
        const activeFile = app.workspace.getActiveFile();
        if (!activeFile) {
            console.error("No active file found.");

        // Sostituisci "NomeNota" con il nome della tua nota
        const targetNote = "Quadro degli Atteggiamenti-bullet_list";
        const targetNoteContent = app.metadataCache.getFileCache(activeFile).headings.filter(heading => heading.heading === targetNote)[0].content;

        // Trova le righe della bullet list
        const bulletListLines = targetNoteContent.split("\n").filter(line => line.trim().startsWith("-"));

        // Ottieni una riga casuale
        const randomIndex = Math.floor(Math.random() * bulletListLines.length);
        const randomLine = bulletListLines[randomIndex];

        console.log("Random line from bullet list:", randomLine);

// Esegui la funzione per ottenere una riga casuale dalla bullet list

Can someone help me to find out what I wrong about ?


Why do you call the content of activeFile for targetNoteContent?

And why don’t you use a much simpler dataview query to do this job?

Hi holroy.
I am not familiar with javascript.
I tried to use this code after researches online to extract a random line from a bullet point in another note and tried to custom it form my needs.
Are you saying that until now I am redirecting the code to this note instead to the other note ?
If yes, how do you correct it ?

I am not using Dataview because Dataview is always running. My needs are that I have to extract one time for today and not always. So I thought that Javascript was the solution using the Run button in reading mode to launch it.

I’m not (at all) fluent in Italian(?), but isn’t “Quadro degli Atteggiamenti-bullet_list” the name of an actual note in your vault? Or is it just a heading in the note that is the same as your active file with the query in it?

And all that heading filtering, are you looking at the bullet list note as a while, or just lists in a given section (under a given heading)? If only in a section, what is the name of that section?

Which exact plugin are you using to do “Run”? (Just so I can replicate it in my test vault…) I’m usually using templater combined with Dataview for this sort of task. Not saying it’s a better option, it’s just the combo I’m used to.

i am using the plugins: Dataview, Tamplater, Execute Code (for javascript).

Let’s say I would have in the note named “Super_Note” the following list:

  • aaa
  • bbb
  • ccc
  • ddd
  • eee
  • fff
  • ggg
  • hhh

and I would launch a javascript code (in another note) to select one item randomly and display it.

How would write the code ?

I did a workaround.
I created a task list instead of a bullet as below:


and with the following query:

FROM "List_of_task"
WHERE !completed 
GROUP BY meta(section).subpath

and it displays the task as below:

But it’s not RANDOM ordered. Has anyone a solution for random order ?

In its most basic rendition I would create a template with the following content:

const dv =["dataview"].api;

tR +="Super_Note").file.lists
  .sort(l => Math.random()).limit(1)
  .map(l => l.text)[0]

Each time you insert this template, it’ll give you a random element from that list. As it stands as full paragraph, but if you add "- " in front of it’ll present it as a list item instead.

The template can be insert through the insert template modal, or by assigning a hotkey to this particular template, or by inclusion from another template using tp.file.include().

That works holroy !!
It was so simple, thanks !

Another hint if you can:
if I have a bullet list with indented bullet, for example:

  • aaaa
    • 1111
    • 2222
  • bbbb
    • 3333
    • 4444
  • cccc
    • 5555
    • 6666

and I would extract random only one bullet of first level with its own sub-level bullet, for example, when it is extracted I would have:

  • bbbb
    • 3333
    • 4444


is there a way to do it ?

In general listing a list item with children is trickier then it sounds using Dataview, especially when dealing with lists, and not tasks. It’s not easy to do with pure javascript either, as you then need to parse all the lines.

But here is a query which might do the job, at least it does so in my test vault. This solution only includes the first level of children.

const dv =["dataview"].api

const result = await dv.query(`
  LIST rows[0].item.children.text
  FROM "ForumStuff/f77/f77307/"
  FLATTEN file.lists as item
  WHERE !item.parent
  GROUP BY "<!-- " + item.position.start.line + "-->" + item.text

// Pick one random item
const oneItem = result.value.values[ Math.trunc((Math.random()* result.value.values.length))]

tR += "\n" + dv.markdownList(dv.array(oneItem))
  .replace(/<!--.*-->/, "")
  .replace(/(- .*):\s*$/gm, "$1")

To get this query to work we need to make sure that each item is unique, so that we can group on it with certainty that it not pick up any other items. I’ve used the line number of the list item to get this uniqueness (which works since we’re working with just one file. In addition this query use the !item.parent to remove any sub-list items, since only items on the top level has “0” as their parent line number. Caveat with this script, is that if your lists starts on line 1, then also sub-lists will have parent = 0, so to avoid that you need to have at least one blank line (or some frontmatter) before the first list item.

Lastly, since we now need to use the dv.query, since we don’t have access to ListPairWidget from the Templater context, we now need to fully qualify the location of the file. This needs to match where your file is located within your vault.

The trickery with replace() near the end, is to remove the comment and the “:” introduce by the query earlier on.

i tried and got this error in console:

I am using the indented bullet list example as said above.
I put the exact path and name of the bullet note.

I used your code as here below:

const dv =[“dataview”].api

const result = await dv.query(
LIST rows[0].item.children.text
FROM “Hidden/My Lists/Scn/Quadro degli”
FLATTEN file.lists as item
WHERE !item.parent
GROUP BY “” + item.text

// Pick one random item
const oneItem = result.value.values[ Math.trunc((Math.random()* result.value.values.length))]

tR += “\n” + dv.markdownList(dv.array(oneItem))
.replace(//, “”)
.replace(/(- .):\s$/gm, “$1”)

Do you maybe understand what happening ?

It seems like the Dangling Links plugin is interfering. I’ve not got that installed, and it was last updated 3 years. But even when I installed that I didn’t get that error message, so I’m not sure why it’s doing that in your context.

I forgot a character from your code.
It works !!

My output:

  • cccc
    • 5555
    • 6666

holroy, you are a very professional programmer. Thanks a lot for your help.
Now I can complete my Daily note with triggers to print some information daily.

Have a good day !

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.