Can a jQuery script be added to a dataviewjs snippet to change progress bar appearance?

527 views Asked by At

I am running a dataviewjs snippet in a markdown file, specifically Obsidian, but I am not happy with the progess bar appearance, which uses green for 'barely started or bad' and red for 'finished or good'. I'd like to reverse that. I found a jQuery script that I think would help, but I can't make it work (extreme js rookie, here).

Here is the dataviewjs snippet:

const createProgressBar = (char_count, char_goal, words_count, words_goal) => {
        let percents = 0
        if (char_goal != undefined) {
            percents = Math.round(char_count / char_goal * 100)
            else if (words_goal != undefined) {
                percents = Math.round(words_count / words_goal * 100)
            }
            dv.paragraph("<progress max=100 value=" + percents + "> </progress> " + percents + "%")
        }


        const getFirstSplit = (split) => {
                if (split.type == "tabs") {
                    return split
                    else if (split.type == "split") {
                        return getFirstSplit(split.children[0])
                    }
                }

                let firstSplit = getFirstSplit(app.workspace.rootSplit)

                let current = firstSplit.children[firstSplit.currentTab].view.file

                if (current != null) {
                    let page = dv.page(current.path)

                    if (page != undefined) {
                        let char_goal = page.char_goal
                        let words_goal = page.words_goal
                        let synopsis = page.synopsis
                        let POV = page.pov
                        let location = page.location
                        let characters = page.characters
                        let tags = page.tags
                        let project = page.project
                        let highlights


                        if (project != undefined) {
                            dv.header(4, "[[" + project + "]]")
                        }


                        if (synopsis != undefined) {
                            dv.span("***")
                            dv.header(5, "Synopsis")
                            dv.span(synopsis)
                        }


                        if (POV != undefined) {
                            dv.span("***")
                            dv.header(5, "POV")
                            dv.span(POV)
                        }


                        if (page.type == "writing scene") {


                            let content = await dv.io.load(current.path)
                            highlights = content.match(/==.*?==/g)
                            content = content.replace(/^---\n.*?\n---/ms, "").trim().replaceAll("—", "").replaceAll(/[\n]+/mg, " ").replaceAll(/[ ]+/mg, " ").replaceAll("==", "").replaceAll("*", "").replaceAll("#", "")
                            let words = content.split(" ")

                            dv.span("***")
                            dv.header(5, "Scene progress")


                            if (words_goal != undefined) {
                                dv.paragraph(words.length + " / " + words_goal + " words")
                            }

                            if (char_goal != undefined) {
                                dv.paragraph(content.length + " / " + char_goal + " characters")
                            }

                            createProgressBar(content.length, char_goal, words.length, words_goal)
                        }




                        if (page.type == "writing project") {
                            let path = '"' + page.file.folder + '"'
                            let scenePages = dv.pages(path).filter(p => p.type == "writing scene")
                            let words_count = 0
                            let char_count = 0

                            let scenesData = []

                            for (let scene of scenePages) {
                                let sceneContent = await dv.io.load(scene.file.path)
                                sceneContent = sceneContent.replace(/^---\n.*?\n---/ms, "").trim().replaceAll("—", "").replaceAll(/[\n]+/mg, " ").replaceAll(/[ ]+/mg, " ").replaceAll("==", "").replaceAll("*", "").replaceAll("#", "")
                                let sceneWords = sceneContent.split(" ")
                                words_count = words_count + sceneWords.length
                                char_count = char_count + sceneContent.length
                                scenesData.push({
                                    words_count: sceneWords.length,
                                    char_count: sceneContent.length,
                                    link: scene.file.link,
                                    words_goal: scene.words_goal,
                                    char_goal: scene.char_goal
                                })
                            }

                            dv.span("***")
                            dv.header(5, "Novel progress")

                            if (words_goal != undefined) {
                                dv.paragraph(words_count + " / " + words_goal + " words")
                            }
                            if (char_goal != undefined) {
                                dv.paragraph(char_count + " / " + char_goal + " characters")
                            }
                            createProgressBar(char_count, char_goal, words_count, words_goal)

                            dv.span("***")
                            dv.header(5, "Scenes progress")

                            scenesData.forEach(scene => {
                                dv.span(scene.link)
                                createProgressBar(scene.char_count, scene.char_goal, scene.words_count, scene.words_goal)
                            })
                        }



                        if (location != undefined) {
                            dv.span("***")
                            dv.header(5, "Location")
                            dv.span(location.map(c => " [[" + c + "]]") + "")
                        }

                        if (characters != undefined) {
                            dv.span("***")
                            dv.header(5, "Characters")
                            dv.span(characters.map(c => " [[" + c + "]]") + "")
                        }

                        if (tags != undefined) {
                            dv.span("***")
                            dv.header(5, "Tags")
                            dv.span(tags.map(c => " #" + c) + "")
                        }

                        if (highlights != undefined) {
                            highlights = highlights.map(h => h.replaceAll("==", ""))
                            dv.span("***")
                            dv.header(5, "Highlights")
                            dv.paragraph(highlights)
                        }
                    }
                }

Here is the jQuery script:

$(document).ready(function() {
            const show_percent = true;
            var progressBars = $(".progress-bar");
            for (i = 0; i < progressBars.length; i++) {
                var progress = $(progressBars[i]).attr("aria-valuenow");
                $(progressBars[i]).width(progress + "%");
                if (show_percent) {
                    $(progressBars[i]).text(progress + "%");
                }
                if (progress >= "90") {
                    //90 and above
                    $(progressBars[i]).addClass("bg-success");
                    else if (progress >= "30" && progress < "45") {
                        $(progressBars[i]).addClass("bg-warning"); //From 30 to 44
                        else if (progress >= "45" && progress < "90") {
                            $(progressBars[i]).addClass("bg-info"); //From 45 to 89
                            else {
                                //29 and under
                                $(progressBars[i]).addClass("bg-danger");
                            }
                        }
                    });

Is it possible to add the jquery to the dataview snippet, and if so, where and how would I do so?

I tried using the jQuery script with the attribute changed to match my dataviewjs parameters, but I got the following error message:

Evaluation Error: TypeError: Cannot set properties of undefined (setting '__k')
    at S$1 (plugin:dataview:14624:8423)
    at q$1 (plugin:dataview:14624:8598)
    at $ (plugin:dataview:14628:5017)
    at eval (eval at <anonymous> (plugin:dataview), <anonymous>:1:39)
    at DataviewInlineApi.eval (plugin:dataview:18404:16)
    at evalInContext (plugin:dataview:18405:7)
    at asyncEvalInContext (plugin:dataview:18415:32)
    at DataviewJSRenderer.render (plugin:dataview:18436:19)
    at DataviewJSRenderer.onload (plugin:dataview:18020:14)
    at e.load (app://obsidian.md/app.js:1:631581)
1

There are 1 answers

0
Srinjoy Santra On

I do NOT think jQuery is supported in Obsidian.

As an alternative, you can add the following CSS snippet

.progress-red::-webkit-progress-value {
  background-color: red !important;
}

.progress-orange::-webkit-progress-value {
    background-color: orange !important;
  }

.progress-greenyellow::-webkit-progress-value {
background-color: greenyellow !important;
}

And also tweak your JS createProgressBar as follows

const createProgressBar = (char_count, char_goal, words_count, words_goal) => {
    let percents = 0
    if (char_goal != undefined) {
        percents = Math.round(char_count / char_goal * 100)
    }
    else if (words_goal != undefined) {
        percents = Math.round(words_count / words_goal * 100)
    }
    let color='red';
    if(percents >=75)

        color = 'greenyellow';
    else if(percents >=50)
            color = 'orange';

    dv.paragraph(`<progress class="progress-${color}" max=100 value=${percents}></progress> ${percents}% `)
}

createProgressBar(12, undefined, 30.8, 100)
createProgressBar(400, 500, 30.8, 100)
createProgressBar(400, undefined, 234, 423)