DataviewJS - Show all JPG files from a folder - show results in multiple columns

Hello everyone,
I’ve been digging this forum and google for half a day now and can’t find a solution…
I am a newb, a musician…

What I’m trying to do

I want to see all images from a specific folder in a dataviewJS list or table.

Why? —> Because I like to take screenshots of interesting mobile social media posts, trim, rename and save them to a folder in my (mobile) vault, and have them automatically – without further work – show up as a gallery in a particular note.

This is why “regular” markdown dataview is no option (searches only frontmatter or inline properties).
I would have to manually add every image to that note’s frontmatter or inline text. But I might upload a screenshot on the go and later forget to do the extra work…

And well, why do it manually in five seconds if I can spend a day to automate it :sweat_smile:

Things I have tried

Below is a Frankenstein dataviewJS query that I put together from different forums.
It finally shows a text-list of all jpg files in a folder and the actual embedded images as a list, each image in it’s own paragraph/row.

How can I turn these embedded images now into something that looks like a gallery with a certain number of results per row?

Ideally even with a CSS snippet that allows some additional styling like:

  • number of results per row
  • width & height
  • margins
  • background color

I also wasn’t able to turn this into a table instead of a list. Maybe Minimal Theme can turn this into cards as soon as the query returns a table.
But is it even possible to create a table from just a list of file links?
Each embedded link in one cell…? :man_shrugging:

Any help is highly appreciated! :pray:

```dataviewjs
let parentFolder = dv.current().file.folder

if (parentFolder == "")
  parentFolder = "/"
  
const jpgFiles = app.vault.getFiles()
  .filter(file => file.parent.path == parentFolder && file.path.includes('.jpg'))
  .map(file => dv.fileLink(file.path))

dv.list(jpgFiles)

jpgFiles.forEach(file => dv.paragraph(`![[${file.path}]]`))

Of course I also read the dataview documentation!

this could be of use:

you might need to tweak it with some bot help if it doesn’t work anymore

Hey @Yurcee, thanks a lot! Yes! Getting closer and closer… there is a lot to learn for me while trying to understand the code!
Unfortunately the snippet shows me only the whole vault when writing:

pages: ""

…as the location to parse data from. This is expected behaviour. But I can’t make it search in a specific folder like:

pages: "archives"

or

pages: "archives/images"

…which are in my root vault folder. Don’t know if I am doing something wrong here.
Any hint or idea?

normally you would use the syntax '"folder"', meaning you need to flank the double quotes with a pair of single quotes as well

target the markdown files not the attachments folder

@Yurcee thanks again! Flanked double quotes still not working.

But I also realize that the script is not really doing what I was looking for.

I want to “monitor” a folder that contains only images and hoped to get dataviewJS to spit out a gallery view of all images in that folder. I don’t want to write a note for every image and don’t want to do manual work like linking every image in a note (which of course I could do. But where is the fun in automating then?).

There might be other ways to do this involving more plugins.
My initial dataviewjs query “monitors” and spits out all images in a folder. But it is not rendering a gallery view. It shows a long collumn of of stretched (100%) images. One image per row… that means a lot of scolling to find a particular image (e.g. screenshot of an interesting instagram post about productivity…).

Do you @Yurcee maybe know how to adjust my initial query to show the results differently?
Scanning for jpg’s in a folder works fine. But I really don’t get how to show the results in a table that in the end looks like a gallery…

This part does what I wanted (at least I think so):

```dataviewjs
let parentFolder = dv.current().file.folder

if (parentFolder == "")
  parentFolder = "/"
  
const jpgFiles = app.vault.getFiles()
  .filter(file => file.parent.path == parentFolder && file.path.includes('.jpg'))
  .map(file => dv.fileLink(file.path))

The rest is my problem:

/* renders a (text) list */
dv.list(jpgFiles)

/* renders one fully stretched image per row */
jpgFiles.forEach(file => dv.paragraph(`![[${file.path}]]`)) 

The dataviewJS documentation is barely understandable for someone like me without any knowledge of JS and it’s syntax.

But I think this is actually a pretty nice usecase that others might be interested in, too.
Monitor a folder scan for certain file types (images, pdf’s…) and simply render everything as a gallery (table that wraps automatically or so…).

—> next level: - render a title from file.name
- render a small subtilte with date of creation/adding
- as a card view (maybe compatible with minimal themes cards…)

Maybe someone wants to bring that usecase to life! :blush:

i’m afraid you’re on your own here…
but i would also be interested in further developments for a second vault of mine i created through evernote migration…

1 Like

Looking at your usecase, I’d strongly suggest that you use the Note Gallery instead of trying to implement that yourself with a ton of js code.

It would simply be a matter of putting this code block in one of your file and you’re done!

```note-gallery
query: 'path: archives/images file: jpg'
```

The nice thing about this method is that any query that works within the core obsidian search should work here.

I’m not a fan of the border added around every images but you can always remove it via a css snippet if you feel like it.

Hey @Yurcee I did it!!!

Just had to throw a few thousand words at GPT-4 (dataview documentation), plus the script you showed me, discuss different approaches and now I have a basic solution that does the job perfectly.

Plus I have a basis for further adjustments and creating variants that I can call as a parameter in the query.

So here for you and anyone interested:


The query:

  • Replace “myView” with the folder you placed the two files in (view.js & view.css).
  • Between { } i hope to be able to call different variants in future (cards with some metadata or a title; bigger images; smaller images…)

```dataviewjs
dv.view("myView", { })


The files:

  • view.js
  • view.css

view.js

// Assuming input.pages contains paths to image files

let parentFolder = dv.current().file.folder;

if (parentFolder == "") parentFolder = "/";

const jpgFiles = app.vault.getFiles()
  .filter(file => file.parent.path == parentFolder && file.path.endsWith('.jpg'));



// Set Root Node

const rootNode = dv.el("div", "", {cls: "imageGallery"});



// Loop through each jpg file and add it to the gallery

jpgFiles.forEach(file => {
    const filePath = app.vault.getResourcePath(file);
    

    // Generate HTML for each image

    const imgHTML = `<img src="${filePath}" class="galleryImage"/>`;
    

    // Append to the gallery container

    rootNode.appendChild(dv.el("div", imgHTML, {cls: "galleryItem"}));
});

view.css

.imageGallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px;
}

.galleryItem {
    border: 1px solid #ccc;
    padding: 10px;
}

.galleryItem img {
    width: 100%;
    height: auto;
    display: block;
}

Still some questions:

Let me know if you see any possible improvements or flaws!


GPT-4 told me:

“The app.vault.getResourcePath(file) method is used to get the web-accessible path for local images, ensuring they can be displayed in the note.”

I am not sure what this means or if this is some kind of security risk?? Web-accessible path??

But I am quite happy that it is working now!
Thanks again for pointing me to that snippet and the view.js & view.css method… :pray:

Hey @Krakor, thanks for your reply!
I saw this a bit too late.
Do you think around 10 lines of JS code are already a ton?? Is it dangerous somehow to use JS code?
I found a solution now and I am quite happy…
The actual final query in my note is quite short:

```dataviewjs
dv.view("myView", {})

For the sake of exploring and learning (and a bit of cheating with ChatGPT) I didn’t want to use another plugin. I already have too many that I am slowly exploring… :sweat_smile:

will have a look at both solutions later!

1 Like

Oh I got carried away :sweat_smile: I honestly thought you would need more code than that to achieve the result you wanted. If you’re happy with it, that’s all that matters :raised_hands:
To answer your questions:

  • No, 10 lines of JS code represent nothing compared to the size of every plugins you have installed, not to mention Obsidian itself (with the app.js alone having 150k lines if I can trust the devtools).
  • Yes, it can be dangerous to run js code from untrusted sources. In your case it’s perfectly fine as all you are doing is calling Dataview and Obsidian APIs to query and load elements in the DOM.

Note that I completely understand your point of view, as I’m a fan of js views myself. I prefer js-engine though, but that’s a matter of preference.

1 Like

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