Closet For Anki [Official support]

I’ve been trying to use the “show” tag in the “Cmds1” field( [[show::ch2]] ) but it hasn’t been working. And If I change closet.recipes to closet.flashcard.recipes, the cards stop working properly.

closet.flashcard.recipes.activate({ tagname: 'show', storeId: 'flashcardShow' }),
closet.flashcard.recipes.activate({ tagname: 'hide', storeId: 'flashcardHide' }),

Other tags like “c” are working perfectly with the change:

closet.flashcard.recipes.cloze({
tagname: "c",
defaultBehavior: closet.flashcard.behaviors.Show,
}),
closet.flashcard.recipes.multipleChoice({
tagname: "mc",
defaultBehavior: closet.flashcard.behaviors.Show,
}),
closet.flashcard.recipes.sort({
tagname: "sort",
defaultBehavior: closet.flashcard.behaviors.Show,
}),

@kleinerpirat @dylanmcooper

Is it possible to combine incremental reveal with cloze?

I saw that one of your card types has almost what I want (from here: Closet Note Template - AnkiWeb) - but I’m basically just trying to get the cloze to reveal automatically when the IO is clicked

1 Like

@kleinerpirat

Hello!

I’m trying to set up Closet and wanted to add the Graphical Effects function to my cards.

I tried your suggestions from earlier in the thread and added the styling directly to the card as well as the edited code to the closet setup.

However, the changes aren’t actually showing up on the cards. Additionally there’s an error message at the bottom of the front and back templates.

Anki version: Version ⁨2.1.40 on macOS Big Sur

Front Template

{{Front}}

<div id="anki-am" data-name="Assets by ASSET MANAGER" data-version="2.1">
    <script data-name="Prevent reinclusion" data-version="v0.1">
        var ankiAms = document.querySelectorAll('#anki-am')
          if (ankiAms.length > 1) {
            for (const am of Array.from(ankiAms).slice(0, -1)) {
              am.outerHTML = ''
          }
        }
    </script>
    <script data-name="Closet Setup" data-version="v0.1">
        function closetUserLogic(
            closet,
            preset,
            chooseMemory,
        ) {
                const elements = closet.anki.getQaChildNodes()
            const memory = chooseMemory('closet__1')
            const filterManager = closet.FilterManager.make(preset, memory.map)

            const output = [[
                elements,
                memory,
                filterManager,
            ]]

            /* here goes the setup - change it to fit your own needs */

            /** Fancy multiple choice */

            const wrappedMultipleChoiceShow = closet.wrappers.aftermath(closet.flashcard.recipes.multipleChoice.show, (e, inter) => {
              document.querySelectorAll('.cl--child')
                .forEach(v => v.addEventListener('click', () => {
                  const container = document.querySelector('.cl--container')

                  if (container) {
                    container.classList.add('cl--reveal')
                  }
                }))

              const keyword = 'fancyMultipleChoice'

              if (!inter.environment.has(keyword)) {
                inter.environment.set(keyword, true)
              }
            })

            const wrapItem = (v, _i, cat) => `<div class="cl--card"><div class="cl--child cl--category-${cat}"><h3>${v}</h3></div></div>`

            filterManager.install(wrappedMultipleChoiceShow({
              tagname: 'mc',
              frontStylizer: closet.Stylizer.make({
                mapper: wrapItem,
                separator: '',
                processor: (v) => `<div class="cl--container">${v}</div>`,
              }),
              backStylizer: closet.Stylizer.make({
                mapper: wrapItem,
                separator: '',
                processor: (v) => `<div class="cl--container cl--reveal">${v}</div>`,
              }),
            }))
            return output
        }

        var getAnkiPrefix = () => globalThis.ankiPlatform === 'desktop'
            ? ''
            : globalThis.AnkiDroidJS
            ? 'https://appassets.androidplatform.net'
            : '.'

        var closetPromise = import(`${getAnkiPrefix()}/__closet-v0.3.0.js`)
            .then(
                closet => closet.anki.initialize(closet, closetUserLogic, '{{Card}}', '{{Tags}}', 'front'),
                error => console.log('An error occured while loading Closet:', error),
            ).catch(error => console.log('An error occured while executing Closet:', error))

        if (globalThis.onUpdateHook) {
            onUpdateHook.push(() => closetPromise)
        }
    </script>
</div>

Back Template

{{FrontSide}}

<hr id="answer">

{{Back}}

<div id="anki-am" data-name="Assets by ASSET MANAGER" data-version="2.1">
    <script data-name="Closet Setup" data-version="v0.1">
        function closetUserLogic(
            closet,
            preset,
            chooseMemory,
        ) {
                const elements = closet.anki.getQaChildNodes()
            const memory = chooseMemory('closet__1')
            const filterManager = closet.FilterManager.make(preset, memory.map)

            const output = [[
                elements,
                memory,
                filterManager,
            ]]

            /* here goes the setup - change it to fit your own needs */

            /** Fancy multiple choice */

            const wrappedMultipleChoiceShow = closet.wrappers.aftermath(closet.flashcard.recipes.multipleChoice.show, (e, inter) => {
              document.querySelectorAll('.cl--child')
                .forEach(v => v.addEventListener('click', () => {
                  const container = document.querySelector('.cl--container')

                  if (container) {
                    container.classList.add('cl--reveal')
                  }
                }))

              const keyword = 'fancyMultipleChoice'

              if (!inter.environment.has(keyword)) {
                inter.environment.set(keyword, true)
              }
            })

            const wrapItem = (v, _i, cat) => `<div class="cl--card"><div class="cl--child cl--category-${cat}"><h3>${v}</h3></div></div>`

            filterManager.install(wrappedMultipleChoiceShow({
              tagname: 'mc',
              frontStylizer: closet.Stylizer.make({
                mapper: wrapItem,
                separator: '',
                processor: (v) => `<div class="cl--container">${v}</div>`,
              }),
              backStylizer: closet.Stylizer.make({
                mapper: wrapItem,
                separator: '',
                processor: (v) => `<div class="cl--container cl--reveal">${v}</div>`,
              }),
            }))
            return output
        }

        var getAnkiPrefix = () => globalThis.ankiPlatform === 'desktop'
            ? ''
            : globalThis.AnkiDroidJS
            ? 'https://appassets.androidplatform.net'
            : '.'

        var closetPromise = import(`${getAnkiPrefix()}/__closet-v0.3.0.js`)
            .then(
                closet => closet.anki.initialize(closet, closetUserLogic, '{{Card}}', '{{Tags}}', 'back'),
                error => console.log('An error occured while loading Closet:', error),
            ).catch(error => console.log('An error occured while executing Closet:', error))

        if (globalThis.onUpdateHook) {
            onUpdateHook.push(() => closetPromise)
        }
    </script>
</div>

Styling



.cl--container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  grid-gap: 0px 40px;
  margin: 40px auto;
}

.cl--card {
  cursor: pointer;
  position: relative;
  height: 0;
  padding-bottom: 100%;
  transition: transform 0.6s ease;
  --translate: 0;
  transform: translate(var(--translate), var(--translate));
}

.cl--card:hover {
  --translate: calc(-5px);
  transition: transform 0.3s ease;
}

.cl--child {
  position: absolute;
  width: 100%;
  height: 80%;

  padding: 8px 16px;
  background: #fff;
  box-shadow: 0px 4px 8px rgba(128, 128, 128, 0.1), 0px -4px 8px rgba(255, 255, 255, 0.8);
  border-radius: 6px;
  transition: inherit;
  transform: translate(var(--translate), var(--translate));
  z-index: 5;
}

.cl--child > h3 {
  color: black;
}

.cl--reveal .cl--category-0 {
  background-color: lime;
}

.cl--reveal .cl--category-1 {
  background-color: coral;
}

**Closet Setup Code**

const elements = closet.anki.getQaChildNodes()
const memory = chooseMemory(‘closet__1’)
const filterManager = closet.FilterManager.make(preset, memory.map)

const output = [[
elements,
memory,
filterManager,
]]

/* here goes the setup - change it to fit your own needs */

filterManager.install(
closet.recipes.shuffle({ tagname: ‘mix’ }),
closet.recipes.order({ tagname: ‘ord’ }),
closet.recipes.cloze({ tagname: ‘c’ }),
closet.recipes.multipleChoice({ tagname: ‘mc’ }),
closet.browser.recipes.rect({ tagname: ‘rect’ }),
)

/** Fancy multiple choice */

const wrappedMultipleChoiceShow = closet.wrappers.aftermath(closet.flashcard.recipes.multipleChoice.show, (e, inter) => {
document.querySelectorAll(’.cl–child’)
.forEach(v => v.addEventListener(‘click’, () => {
const container = document.querySelector(’.cl–container’)

  if (container) {
    container.classList.add('cl--reveal')
  }
}))

const keyword = ‘fancyMultipleChoice’

if (!inter.environment.has(keyword)) {
inter.environment.set(keyword, true)
}
})

const wrapItem = (v, _i, cat) => <div class="cl--card"><div class="cl--child cl--category-${cat}"><h3>${v}</h3></div></div>

filterManager.install(wrappedMultipleChoiceShow({
tagname: ‘mc’,
frontStylizer: closet.Stylizer.make({
mapper: wrapItem,
separator: ‘’,
processor: (v) => <div class="cl--container">${v}</div>,
}),
backStylizer: closet.Stylizer.make({
mapper: wrapItem,
separator: ‘’,
processor: (v) => <div class="cl--container cl--reveal">${v}</div>,
}),
}))

There’s a few things I’m working on with that script that I need help with. I’ll add this to the list but I know next to nothing about coding, so no promises.
Other plans for that note template / script:

  • Get I/O incremental reveal to work for rect2 and rect3;
  • Keyboard shortcut for I/O incremental reveal;
  • Ditch the incremental reveal and let you click any I/O box to reveal it

If @kleinerpirat or @hengiesel wants to get involved, I would be willing to pay for their help.

@dylanmcooper, kleinerpirat’s latest IO note already includes all three of the things you mentioned, though I’m not sure where to find it.

@kronos, it sounds easy enough, I could give it a look if you sent your own note template, cause I’ve heavily modified own setup and css.

Okay, just went back through forum history and found where kleinerpirat got it working for rect2 and rect3 (here). But that still doesn’t allow you to click any occlusion to reveal, you have to go in the sequence. Also, I don’t see a keyboard shortcut to only reveal the I/O.

@kronos - I see where it has been discussed about how to reveal a cloze associated with an occlusion (here), however I don’t see a method on how to actually implement this feature. I am very interested if you figure it out.

-Edit: I saw where you made a script to reveal the obscure clozes via keyboard decimal, however I can’t get that to work for the I/O rect. Same concept though.

Kleinerpirat sent me this one which lets you reveal occlusions out of sequence too, though I haven't tried it yet as I'm using my own modified one.
(function () {
    var observer = new MutationObserver(() => {
        let rect = document.querySelector(".closet-rect.is-active")
        if (rect) {
            activate(rect)
            observer.disconnect()
            let rects = document.querySelectorAll(".closet-rect.is-active")
            for (let rect of rects) {
                rect.addEventListener("click", reveal)
                rect.addEventListener("touchstart", reveal)
            }
            if (!globalThis.AnKingIOListening) {
                document.addEventListener("keydown", (event) => {
                    if (event.key == "n") {
                        let active = document.querySelector(".closet-rect.is-highlighted")
                        if (active) incrementalReveal.call(active)
                    }
                    else if (event.key == "g") {
                        for (let rect of rects) {
                            incrementalReveal.call(rect)
                        }
                    }
                })
                globalThis.AnKingIOListening = true
            }
            let buttons = document.getElementsByClassName("extra-btn")

            function toggle() {
                if (!this.classList.contains("uncollapsed")) {
                    this.nextElementSibling.classList.remove("hidden")
                    this.classList.add("uncollapsed")
                }
                else {
                    this.nextElementSibling.classList.add("hidden")
                    this.classList.remove("uncollapsed")
                }
            }
            for (let button of buttons) {
                button.addEventListener("click", toggle)
                button.addEventListener("touchstart", toggle)
            }
        }
    })
    observer.observe(document.getElementById("qa"), {
        childList: true,
        subtree: true
    })

    function activate(rect) {
        rect.classList.add("is-highlighted")
        rect.addEventListener("click", incrementalReveal)
        rect.addEventListener("touchstart", incrementalReveal)
    }

    function incrementalReveal() {
        reveal.call(this)
        let next = this.nextElementSibling
        if (next) {
            while ((next.classList.contains("revealed") || next.classList.contains("is-inactive")) && next.nextElementSibling) {
                next = next.nextElementSibling
            }
            if (!next.classList.contains("revealed")) activate(next)
        }
        else {
            document.getElementById("extra-content").classList.remove("hidden")
        }
    }

    function reveal() {
        this.classList.remove("is-highlighted")
        this.classList.add("revealed")
    }
})()
1 Like

Is Closet working in version 2.1.49?

Yes. 2.1.49 was just a bugfix release.

1 Like

I just found this add on and it looks spectacular, but I have no idea how to get started. I tried clicking the link for the introduction video several times but it says it is private, so I cannot watch it. There is also nothing on the installation page of the website, so I’m very lost. Any help would be appreciated

2 Likes

@ maplun3280 Here’s a good place to start!

2 Likes

Anyone using the radio buttons / checkboxes for their multiple choice? Having trouble getting the template from the website to work.

Here’s where I am at so far. I am inserting the following script into the front and back template under the closet setup. It displays the answer options correctly, but when I try to click an option the first time, it rearranges the answer choices. Then when I try to click again, it will not check the box. If I click at an option a bunch, eventually it will check the box. Then, when I flip the card over, the answer options rearrange themselves, I lose the checked box input, and there is no color change in the displayed answers to show which one is correct (i.e. it resets it as if it were displaying the front again).

I also use the regular multiple choice script, and would like the two to not interfere

script:

/** Multiple choice with input */
const countRightAnswers = (tag, internals) => {
  const rightAnswerKeyword = `${tag.fullKey}:rightAnswers`
  const increaseByRightAnswers = (v) => v + (tag.values
    ? tag.values[0].length
    : 0)

  internals.cache.fold(rightAnswerKeyword, increaseByRightAnswers, 0)

  return tag.values
    ? tag.values.flatMap((v, i) => v.map((w) => [
      w,
      i,
      tag.fullKey,
      tag.fullOccur,
      internals.cache,
      internals.aftermath,
    ]))
    : []
}

const refreshInputChecked = (elementId, aftermath) => {
  const oldInput = document.getElementById(elementId)
  if (oldInput && oldInput.checked) {
    aftermath.register(`${elementId}:recheck`, () => {
      const newInput = document.getElementById(elementId)
      if (newInput) { newInput.checked = true }
    })
  }
}
const createInputElement = (classLabel) => (value, index, type, fullKey, fullOccur, cache, aftermath) => {
  const rightAnswerKeyword = `${fullKey}:rightAnswers`
  const rightAnswerCount = cache.get(rightAnswerKeyword, 0)
  const elementId = `${fullKey}-${fullOccur}-${index}`
  const inputType = rightAnswerCount === 1 ? 'radio' : 'checkbox'
  refreshInputChecked(elementId, aftermath)
  const className = type === 0 ? `class="${classLabel}" ` : ''
  return `
    <input type="${inputType}" id="${elementId}" name="${fullKey}" />
    <label ${className} for="${elementId}">${value}</label>
  `
}
const front = closet.Stylizer.make({ separator: '; ', mapper: createInputElement('')})
const backClassName = 'closet-mc-right-answer'
const back = closet.Stylizer.make({ separator: '; ', mapper: createInputElement(backClassName),})
const inputMultipleChoiceStyle = `.${backClassName} { color: lime; }`
const addHighlightCSS = (entry, internals) => { const keyword = 'inputMultipleChoice'
  if (!internals.environment.post(keyword, () => true, false)) {
    closet.browser.appendStyleTag(inputMultipleChoiceStyle)
  }
}
const wrappedMultipleChoiceShow = closet.wrappers.aftermath(closet.flashcard.recipes.multipleChoice.show, addHighlightCSS)
filterManager.install(wrappedMultipleChoiceShow({ tagname: 'mx', getValues: countRightAnswers, frontStylizer: front, backStylizer: back, }))




Multiple Choice Radiobutton

The video linked in the description is set to private.

Dear Dylan,

here’s another noob that just cannot get started without some additional help…

I have downloaded your sample deck and it is e x a c t l y what I was looking for!

But, being a noob, I just don’t know how to make cards like these myself… I’m willing to pay you for a video that shows step by step where to click and what to type in order to create one of these cards myself.

I’ve downloaded Anki for Mac, I’ve downloaded the extension, I have your sample deck, but I have no clue of how to copy/paste your samples on my personal anki version. I’m far from being a programmer and I’ve really spent a couple of hours searching for information, but it simply doesn’t lead me anywhere… If 50$ or € are a kind of motivation for you, I’m willing to send the sum via paypal immediately…

Thx in advance for a youtube video…

Kind regards,
Bernd

1 Like

Blanking Clozes
Change the code you pasted from the website
I changed it to the following. you can compare it with the code copied from the website

The main reason is:Can not be called closet. unicodeAlphanumericPattern , it may be a bug
So I copied the regular code of __closet-0.5.3.js directly



//-------  regular code

var qn = "A-Za-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B4\\u08B6-\\u08BD\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0AF9\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58-\\u0C5A\\u0C60\\u0C61\\u0C80\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D54-\\u0D56\\u0D5F-\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F5\\u13F8-\\u13FD\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16F1-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u1884\\u1887-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1C80-\\u1C88\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FD5\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA7AE\\uA7B0-\\uA7B7\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA8FD\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB65\\uAB70-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC";

var Hn = "0-9\\xB2\\xB3\\xB9\\xBC-\\xBE\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u09F4-\\u09F9\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0B72-\\u0B77\\u0BE6-\\u0BF2\\u0C66-\\u0C6F\\u0C78-\\u0C7E\\u0CE6-\\u0CEF\\u0D58-\\u0D5E\\u0D66-\\u0D78\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F33\\u1040-\\u1049\\u1090-\\u1099\\u1369-\\u137C\\u16EE-\\u16F0\\u17E0-\\u17E9\\u17F0-\\u17F9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19DA\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\u2070\\u2074-\\u2079\\u2080-\\u2089\\u2150-\\u2182\\u2185-\\u2189\\u2460-\\u249B\\u24EA-\\u24FF\\u2776-\\u2793\\u2CFD\\u3007\\u3021-\\u3029\\u3038-\\u303A\\u3192-\\u3195\\u3220-\\u3229\\u3248-\\u324F\\u3251-\\u325F\\u3280-\\u3289\\u32B1-\\u32BF\\uA620-\\uA629\\uA6E6-\\uA6EF\\uA830-\\uA835\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19";

var Jn = new RegExp("[" + qn + "]", "gu"); 
Kn = new RegExp("[" + Hn + "]", "gu");
Yn = new RegExp("[" + qn + Hn + "]", "gu");

// Can not be called closet. unicodeAlphanumericPattern , it may be a bug
const blank_old = function(tag) {
  return [tag.values[0].replace(closet. unicodeAlphanumericPattern, '_')]
};
const blank = function(tag) {
  if(tag.values[1] != null) return [`[${tag.values[1]}]`];
  return [tag.values[0].replace(Yn, '_')];
};


const afrontStylizer =closet.Stylizer.make({
    processor: v => `<span style="color: cornflowerblue">${v}</span>`,
    separator: '',
  });


const blankOptions = {
  frontEllipser: blank,
  frontStylizer: afrontStylizer,
};



filterManager.install(
  closet.flashcard.recipes.cloze.show({
    tagname: 'c',
    ...blankOptions,
  }),
  closet.flashcard.recipes.cloze.hide({
    tagname: 'ch',
    ...blankOptions,
  }),
  closet.flashcard.recipes.cloze.reveal({
    tagname: 'cr',
    ...blankOptions,
  }),
);;

And add a css

.closet-cloze.is-inactive .closet-cloze__ellipsis::before {
  content: "[...]";
}

This is basically the same as shown on the website

:disappointed_relieved:Can this image occlusion work on 2.1.49? I downloaded this template From Link,
but when I add a new card and select an area on the image, the field [cmds0] does not add rect.
When the image is closed, the field is still empty.
Did I do something wrong?

macos big sur 11.5.2
anki 2.1.49

:slightly_smiling_face: Solved already

Once done drawing occlusions, right click on the image and hit accept occlusions

1 Like

getting this failure message everytime I want to add a new card (and it doesn’t matter which card type I choose).
after I click close I can normally create cards. It’s just always when I want to add a card after opening a new add card window

Error
An error occurred. Please start Anki while holding down the shift key, which will temporarily disable the add-ons you have installed.
If the issue only occurs when add-ons are enabled, please use the Tools > Add-ons menu item to disable some add-ons and restart Anki, repeating until you discover the add-on that is causing the problem.
When you've discovered the add-on that is causing the problem, please report the issue on the add-on support site.
Debug info:
Anki 2.1.45 (355e66e8) Python 3.8.6 Qt 5.14.2 PyQt 5.14.2
Platform: Mac 10.16
Flags: frz=True ao=True sv=2
Add-ons, last update check: 2022-01-10 07:56:38
Add-ons possibly involved: <U+2068>Closet For Anki<U+2069>

Caught exception:
Traceback (most recent call last):
  File "aqt/webview.py", line 538, in handler
  File "aqt/editor.py", line 492, in <lambda>
  File "aqt/addcards.py", line 210, in _add_current_note
  File "aqt/addcards.py", line 248, in _note_can_be_added
  File "aqt/hooks_gen.py", line 108, in __call__
  File "/Users/Lukas/Library/Application Support/Anki2/addons21/272311064/src/addcards.py", line 18, in check_if_occlusion_editor_open
    if addcards.editor.occlusion_editor_active
AttributeError: 'NoneType' object has no attribute 'editor'

Help!

P.S.: I don’t know anything about python so I never touched the code though.

This seems like it would be caused by interactions with other add-ons: Could you turn off all of your other add-ons, and see whether that fixes it?

I tried one by one, it is conflicting with this plugin :frowning_face:
Opening the same window multiple time Opening the same window multiple time - AnkiWeb