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)
I do NOT think jQuery is supported in Obsidian.
As an alternative, you can add the following CSS snippet
And also tweak your JS
createProgressBar
as follows