diff --git a/src/components/widgets/ubg-card.js b/src/components/widgets/ubg-card.js index e49ee1bc4..51c3a22e2 100644 --- a/src/components/widgets/ubg-card.js +++ b/src/components/widgets/ubg-card.js @@ -811,6 +811,11 @@ ${SVG.elementSymbol(others[2], lively.pt(12.5, 8.5), 1.5)}`, lively.rect(0, 0, 1 }, cycling: (cost, who) => { + if (['acard', 'one', 'all'].includes(cost)) { + who = cost + cost = undefined + } + let whoToPrint = 'this' if (who === 'acard') { whoToPrint = 'a card' @@ -821,9 +826,9 @@ ${SVG.elementSymbol(others[2], lively.pt(12.5, 8.5), 1.5)}`, lively.rect(0, 0, 1 } if (cost) { - return `gear Pay (${cost}) and trash ${whoToPrint} to play a card of equal or lower cost.` + return `gear Pay (${cost}) and sacrifice ${whoToPrint} to play a card of equal or lower cost.` } - return `gear Trash ${whoToPrint} to play a card of equal or lower cost.` + return `gear Sacrifice ${whoToPrint} to play a card of equal or lower cost.` }, dash: (cost, who) => { @@ -885,7 +890,7 @@ ${SVG.elementSymbol(others[2], lively.pt(12.5, 8.5), 1.5)}`, lively.rect(0, 0, 1 if (who === 'one') { subject = 'the card'; } - return `gear Trash ${subject} to exec its blitz effects.` + return `gear Sacrifice ${subject} to exec its blitz effects.` }, impulse: () => { @@ -893,17 +898,21 @@ ${SVG.elementSymbol(others[2], lively.pt(12.5, 8.5), 1.5)}`, lively.rect(0, 0, 1 }, instant: () => { - return 'You may buy this as a free action.' + return 'gear Buy this.' }, invoke: () => { - return 'You may trash this from hand or field to exec the effect.' + return 'gear Discard or sacrifice this to exec the effect.' }, manaburst: () => { return 'Only activate manaburst abilities if x is 4+.' }, + magnetic: () => { + return 'gear Pay this card\'s cost to meld it from hand to a card on field. The melded card has all abilities and combined stats ((), vp, element, type) of its parts.' + }, + meld: () => { return 'The melded card has all abilities and combined stats ((), vp, element, type) of its parts.' }, @@ -913,7 +922,7 @@ ${SVG.elementSymbol(others[2], lively.pt(12.5, 8.5), 1.5)}`, lively.rect(0, 0, 1 }, potion: (...args) => { - return `Trash this from hand or field to exec the effect.` + return `Discard or sacrifice this to exec the effect.` }, quest: () => { @@ -997,7 +1006,7 @@ ${SVG.elementSymbol(others[2], lively.pt(12.5, 8.5), 1.5)}`, lively.rect(0, 0, 1 whoText = 'a card' } - return `gear 1/turn Trash ${whoText} from hand to draw a card.` + return `gear 1/turn Discard ${whoText} to draw a card.` }, upgrade: (diff, who) => { @@ -1076,6 +1085,7 @@ ${SVG.elementSymbol(others[2], lively.pt(12.5, 8.5), 1.5)}`, lively.rect(0, 0, 1 //'#3FDAA5' some turquise highlightKeyword(/trad(ed?|ing)\b/gmi, '#2E9F78', SVG.inlineSVG(tradeSVG.innerHTML, lively.rect(0, 0, 36, 36), 'x="10%" y="10%" width="80%" height="80%"', '')); highlightKeyword(/upgraded?\b/gmi, C_ORANGE, SVG.inlineSVG(upgradeSVG.innerHTML, lively.rect(0, 0, 36, 36), 'x="10%" y="10%" width="80%" height="80%"', '')); + highlightKeyword(/magnetic\b/gmi, C_RED_LIGHT, ' '); return printedRules } diff --git a/src/components/widgets/ubg-cards-editor.html b/src/components/widgets/ubg-cards-editor.html index 8edfe3aa2..3865f2ada 100644 --- a/src/components/widgets/ubg-cards-editor.html +++ b/src/components/widgets/ubg-cards-editor.html @@ -254,6 +254,8 @@ + + diff --git a/src/components/widgets/ubg-cards-editor.js b/src/components/widgets/ubg-cards-editor.js index ec6b58308..6bacc2717 100644 --- a/src/components/widgets/ubg-cards-editor.js +++ b/src/components/widgets/ubg-cards-editor.js @@ -37,28 +37,32 @@ export default class UBGCardsEditor extends Morph { } }); rating.addEventListener('keydown', evt => { - const key = evt.key; - lively.notify(key) - if (key >= '1' && key <= '9') { - const index = parseInt(key, 10) - 1; - lively.notify('key', index) - const radioButtonName = 'rating'; - const radioButtons = rating.querySelectorAll(`input[type="radio"][name="${radioButtonName}"]`); - - if (index < radioButtons.length) { // Check if the index is within the range of your radio buttons - const button = radioButtons[index] - button.checked = true; - button.focus() - const changeEvent = new Event('change', { - 'bubbles': true, // Allows the event to bubble up through the DOM - 'cancelable': false // Indicates the event cannot be canceled - }); - radioButtons[index].dispatchEvent(changeEvent); - } - } + this.setRatingFromKeyEvent(evt) }); } + setRatingFromKeyEvent(evt) { + // lively.notify(evt.key) + const key = evt.key; + if (key >= '1' && key <= '9') { + const index = parseInt(key, 10) - 1; + // lively.notify('key', index) + const radioButtonName = 'rating'; + const radioButtons = this.getAllSubmorphs(`input[type="radio"][name="${radioButtonName}"]`); + + if (index < radioButtons.length) { // Check if the index is within the range of your radio buttons + const button = radioButtons[index] + button.checked = true; + button.focus() + const changeEvent = new Event('change', { + 'bubbles': true, // Allows the event to bubble up through the DOM + 'cancelable': false // Indicates the event cannot be canceled + }); + radioButtons[index].dispatchEvent(changeEvent); + } + } + } + get ubg() { return lively.allParents(this, undefined, true).find(ele => ele.tagName === 'UBG-CARDS' || ele.tagName === 'JSPDF-EXAMPLE'); } diff --git a/src/components/widgets/ubg-cards-editor.js.l4a b/src/components/widgets/ubg-cards-editor.js.l4a new file mode 100644 index 000000000..5dff6bbb1 --- /dev/null +++ b/src/components/widgets/ubg-cards-editor.js.l4a @@ -0,0 +1,2 @@ +{"type":"Reference","version":"45560bee52223bed5aa637fe9c73e819f5d7437e","content":"import Morph from 'src/components/widgets/lively-morph.js';\n\nimport preloaWebComponents from 'src/client/preload-components.js'\nawait preloaWebComponents(['ubg-card'])\n\nexport default class UBGCardsEditor extends Morph {\n async initialize() {\n\n this.setAttribute(\"tabindex\", 0);\n this.windowTitle = \"UBGCardsEditor\";\n this.registerButtons();\n lively.html.registerKeys(this);\n this.prepareOnChangeCallbacks();\n }\n\n prepareOnChangeCallbacks() {\n // 'focus', 'blur', 'keyup', 'keypress', 'change', \n for (let eventName of ['input']) {\n this.$id.addEventListener(eventName, evt => this.modify$id(evt, eventName), false);\n this.$name.addEventListener(eventName, evt => this.modify$name(evt), false);\n this.$identity.addEventListener(eventName, evt => this.modify$identity(evt), false);\n this.$type.addEventListener(eventName, evt => this.modify$type(evt), false);\n this.$element.addEventListener(eventName, evt => this.modify$element(evt), false);\n this.$cost.addEventListener(eventName, evt => this.modify$cost(evt), false);\n this.$vp.addEventListener(eventName, evt => this.modify$vp(evt), false);\n this.$text.addEventListener(eventName, evt => this.modify$text(evt), false);\n this.$notes.addEventListener(eventName, evt => this.modify$notes(evt), false);\n this.$art.addEventListener(eventName, evt => this.modify$art(evt), false);\n this.$isPrinted.addEventListener(eventName, evt => this.modify$isPrinted(evt), false);\n }\n this.$text.addEventListener('keydown', evt => this.keydown$text(evt), false);\n this.$tagsInput.addEventListener('keydown', evt => this.keydown$tagInput(evt), false);\n const rating = this.get('#rating');\n rating.addEventListener('change', evt => {\n if (evt.target.name === 'rating') {\n this.modify$rating(evt)\n }\n });\n rating.addEventListener('keydown', evt => {\n this.setRatingFromKeyEvent(evt)\n });\n }\n \n setRatingFromKeyEvent(evt) {\n // lively.notify(evt.key)\n const key = evt.key;\n if (key >= '1' && key <= '9') {\n const index = parseInt(key, 10) - 1;\n // lively.notify('key', index)\n const radioButtonName = 'rating';\n const radioButtons = this.getAllSubmorphs(`input[type=\"radio\"][name=\"${radioButtonName}\"]`);\n\n if (index < radioButtons.length) { // Check if the index is within the range of your radio buttons\n const button = radioButtons[index]\n button.checked = true;\n button.focus()\n const changeEvent = new Event('change', {\n 'bubbles': true, // Allows the event to bubble up through the DOM\n 'cancelable': false // Indicates the event cannot be canceled\n });\n radioButtons[index].dispatchEvent(changeEvent);\n }\n }\n }\n \n get ubg() {\n return lively.allParents(this, undefined, true).find(ele => ele.tagName === 'UBG-CARDS' || ele.tagName === 'JSPDF-EXAMPLE');\n }\n\n // onKeyDown(evt) {\n // return;\n // if (evt.ctrlKey && evt.key == \"s\") {\n // evt.stopPropagation();\n // evt.preventDefault();\n // lively.warn(evt.key, 'key from editor')\n // }\n // }\n\n selectedEntries() {\n return Array.from(this.querySelectorAll(\"lively-bibtex-entry.selected\"));\n }\n\n onContextMenu(evt) {\n if (!evt.shiftKey) {\n evt.stopPropagation();\n evt.preventDefault();\n return;\n }\n }\n\n get src() {\n return this.card;\n }\n\n set src(card) {\n this.card = card;\n this.updateView();\n }\n\n get $id() {\n return this.get('#id');\n }\n get $name() {\n return this.get('#name');\n }\n get $identity() {\n return this.get('#identity');\n }\n get $type() {\n return this.get('#type');\n }\n get $element() {\n return this.get('#element');\n }\n get $cost() {\n return this.get('#cost');\n }\n get $vp() {\n return this.get('#vp');\n }\n get $text() {\n return this.get('#text');\n }\n get $tagsInput() {\n return this.get('#tags-input');\n }\n get $tagsList() {\n return this.get('#tags-list');\n }\n get $rating() {\n return this.get('#rating');\n }\n get $notes() {\n return this.get('#notes');\n }\n get $art() {\n return this.get('#art');\n }\n get $isPrinted() {\n return this.get('#isPrinted');\n }\n\n modify$id(evt) {\n const id = this.$id.value;\n const intId = parseInt(id);\n\n if (_.isNaN(intId)) {\n this.card.setId();\n } else {\n this.card.setId(intId);\n }\n\n this.propagateChange()\n }\n display$id() {\n const id = this.card.getId();\n\n if (id === undefined) {\n this.$id.value = '';\n return;\n }\n\n this.$id.value = id;\n }\n\n modify$name(evt) {\n const name = this.$name.value;\n if (name === '') {\n this.card.setName();\n } else {\n this.card.setName(name);\n }\n\n this.propagateChange()\n }\n display$name() {\n const name = this.card.getName();\n this.$name.value = name === undefined ? '' : name;\n }\n\n modify$identity(evt) {\n const identity = this.$identity.value;\n if (identity === '') {\n this.card.setIdentity();\n } else {\n this.card.setIdentity(identity);\n }\n\n this.propagateChange()\n }\n display$identity() {\n const identity = this.card.getIdentity();\n this.$identity.value = identity === undefined ? '' : identity;\n }\n\n modify$type(evt) {\n const type = this.$type.value;\n if (type === '') {\n this.card.setType();\n } else {\n this.card.setType(type);\n }\n\n this.propagateChange()\n }\n display$type() {\n const type = this.card.getType();\n this.$type.value = type === undefined ? '' : type;\n }\n\n modify$element(evt) {\n const element = this.$element.value;\n if (element === '') {\n this.card.setElement();\n } else if (element.includes(',')) {\n this.card.setElement(element.split(','));\n } else {\n this.card.setElement(element);\n }\n\n this.propagateChange()\n }\n display$element() {\n const element = this.card.getElement();\n\n if (element === undefined) {\n this.$element.value = '';\n return;\n }\n\n if (Array.isArray(element)) {\n this.$element.value = element.join(',');\n return;\n }\n\n this.$element.value = element;\n }\n\n modify$cost(evt) {\n const cost = this.$cost.value;\n\n if (cost === '') {\n this.card.setCost();\n } else if (cost.includes(',')) {\n const costs = cost.split(',');\n const parsedCosts = costs.map(c => parseInt(c)).filter(cost => !_.isNaN(cost));\n if (parsedCosts.length >= 1) {\n this.card.setCost(parsedCosts);\n } else {\n this.card.setCost();\n }\n } else {\n const intCost = parseInt(cost);\n if (_.isNaN(intCost)) {\n this.card.setCost();\n } else {\n this.card.setCost(intCost);\n }\n }\n\n this.propagateChange()\n }\n display$cost() {\n const cost = this.card.getCost();\n\n if (cost === undefined) {\n this.$cost.value = '';\n return;\n }\n\n if (Array.isArray(cost)) {\n this.$cost.value = cost.join(',');\n return;\n }\n\n this.$cost.value = cost;\n }\n\n modify$vp(evt) {\n const vp = this.$vp.value;\n \n if (vp === '') {\n this.card.setBaseVP();\n } else if ('*+-'.split('').some(char => vp.endsWith(char))) {\n this.card.setBaseVP(vp);\n } else {\n const intCost = parseInt(vp);\n if (_.isNaN(intCost)) {\n this.card.setBaseVP();\n } else {\n this.card.setBaseVP(intCost);\n }\n }\n\n this.propagateChange()\n }\n display$vp() {\n const vp = this.card.getBaseVP();\n\n if (vp === undefined) {\n this.$vp.value = '';\n return;\n }\n\n this.$vp.value = vp;\n }\n\n\n keydown$text(evt) {\n if (evt.key === 'Delete' && evt.ctrlKey) {\n evt.stopPropagation()\n return\n } \n }\n modify$text(evt) {\n const text = this.$text.value;\n if (text === '') {\n this.card.setText();\n } else {\n this.card.setText(text);\n }\n\n this.propagateChange()\n }\n display$text() {\n const text = this.card.getText();\n this.$text.value = text === undefined ? '' : text;\n }\n \n keydown$tagInput(evt) {\n const input = this.$tagsInput;\n if (evt.key === 'Escape') {\n input.value = ''\n return\n }\n if (evt.key === 'Enter') {\n const value = input.get('input').value;\n if (value) {\n this.card.addTag(value);\n input.value = ''\n this.propagateChange()\n } else {\n lively.warn('no tag to add.')\n }\n return\n }\n }\n display$tags() {\n const tags = _.sortBy(this.card.getTags());\n const editor = this;\n let previouslyFocussed = this.$tagsList.childNodes.find(n => n.matches(':focus'))\n previouslyFocussed = previouslyFocussed && previouslyFocussed.textContent\n \n function getElementIndex(element) {\n // Get all children of the parent element\n var children = Array.from(element.parentNode.children);\n\n // Find the index of 'element' among its siblings\n var index = children.indexOf(element);\n\n return index;\n }\n \n function onkeydown (evt) {\n function getDeepActiveElement() {\n let active = document.activeElement;\n while (active && active.shadowRoot && active.shadowRoot.activeElement) {\n active = active.shadowRoot.activeElement;\n }\n return active;\n }\n \n if (evt.key === 'Delete' || evt.key === 'Backspace') {\n evt.stopPropagation()\n evt.preventDefault()\n if (evt.repeat) {\n return;\n }\n \n if (getDeepActiveElement() === this) {\n lively.notify(123)\n const sibling = this.nextElementSibling || this.previousElementSibling\n if (sibling) {\n sibling.focus()\n } else {\n editor.$tagsInput.focus()\n }\n }\n \n editor.card.removeTag(this.textContent)\n editor.propagateChange()\n return\n }\n }\n\n this.$tagsList.innerHTML = ''\n this.$tagsList.append(...tags.map(tag => {\n return {tag}\n }));\n \n if (previouslyFocussed) {\n const tagElements = this.$tagsList.childNodes;\n if (tagElements.length === 0) {\n this.$tagsInput.focus()\n } else {\n // get best match from childnodes\n for (let tagElement of tagElements) {\n if (tagElement.textContent >= previouslyFocussed) {\n tagElement.focus()\n return\n }\n tagElements[tagElements.length - 1].focus()\n }\n }\n }\n }\n\n modify$rating(evt) {\n const rating = evt.target.value;\n if (rating === '') {\n this.card.setRating();\n } else {\n this.card.setRating(rating);\n }\n\n this.propagateChange()\n }\n display$rating() {\n const rating = this.card.getRating() || 'unset';\n\n const selectedOption = this.$rating.querySelector(`[value='${rating}']`)\n if (selectedOption) {\n selectedOption.checked = true;\n } else {\n lively.warn('Unknown rating ' + rating)\n }\n }\n\n modify$notes(evt) {\n const notes = this.$notes.value;\n if (notes === '') {\n this.card.setNotes();\n } else {\n this.card.setNotes(notes);\n }\n\n this.propagateChange()\n }\n display$notes() {\n const notes = this.card.getNotes();\n this.$notes.value = notes === undefined ? '' : notes;\n }\n \n modify$art(evt) {\n const art = this.$art.value;\n if (art === '') {\n this.card.setArtDirection();\n } else {\n this.card.setArtDirection(art);\n }\n\n this.propagateChange()\n }\n display$art() {\n const art = this.card.getArtDirection();\n this.$art.value = art === undefined ? '' : art;\n }\n\n modify$isPrinted(evt) {\n const isPrinted = this.$isPrinted.checked;\n if (isPrinted) {\n this.card.setIsPrinted(true);\n } else {\n this.card.setIsPrinted();\n }\n\n this.ubgMarkMyCardAsChanged()\n }\n display$isPrinted() {\n // lively.notify('update printed')\n const isPrinted = this.card.getIsPrinted();\n this.$isPrinted.checked = isPrinted === undefined ? false : isPrinted;\n }\n \n propagateChange() {\n this.ubgMarkMyCardAsChanged();\n this.display$isPrinted();\n this.display$tags();\n this.delayedUpdateCardPreview();\n }\n \n ubgMarkMyCardAsChanged() {\n this.ubg.markCardAsChanged(this.card);\n }\n\n updateTagSelection() {\n const tags = this.ubg.getAllTags()\n this.$tagsInput.setOptions(tags)\n }\n \n async updateView() {\n this.updateTagSelection();\n \n this.display$id();\n this.display$name();\n this.display$identity();\n this.display$type();\n this.display$element();\n this.display$cost();\n this.display$vp();\n this.display$text();\n this.display$tags();\n this.display$rating();\n this.display$notes();\n this.display$art();\n this.display$isPrinted();\n\n await this.updateCardPreview();\n }\n\n async delayedUpdateCardPreview() {\n this.setAttribute('preview-queued', true);\n this._delayedUpdateCardPreview = this._delayedUpdateCardPreview || _.debounce(() => this.updateCardPreview(), 500);\n\n this._delayedUpdateCardPreview();\n }\n\n async updateCardPreview() {\n this.removeAttribute('preview-queued');\n delete this._delayedUpdateCardPreview;\n\n this.renderToHTML()\n }\n \n renderToHTML() {\n const card = this.card;\n const ubg = this.ubg;\n \n const cardPreview = document.createElement('ubg-card')\n cardPreview.setAttribute('id', 'preview')\n this.get('#preview').replaceWith(cardPreview)\n \n cardPreview.setCard(card)\n cardPreview.setCards(ubg.cards)\n cardPreview.setSrc(ubg.src)\n cardPreview.render()\n }\n\n selectedEntry() {\n return this.table.asJSO()[this.table.currentRowIndex - 1];\n }\n\n focusOnText() {\n this.$text.focus()\n }\n \n livelyMigrate(other) {\n this.src = other.src;\n }\n}"} +{"from":2780,"to":2780,"name":"color","color":"#9ecae1"} \ No newline at end of file diff --git a/src/components/widgets/ubg-cards-entry.js b/src/components/widgets/ubg-cards-entry.js index ef84d3454..49e59167d 100644 --- a/src/components/widgets/ubg-cards-entry.js +++ b/src/components/widgets/ubg-cards-entry.js @@ -77,6 +77,7 @@ export default class UBGCardEntry extends Morph { unsure: 'yellow', 'needs revision': 'orange', remove: 'red', + 'test next': 'violet', 'to test': 'darkgray', }[card.getRating()] || 'lightgray'); id.innerHTML = card.id || '???'; diff --git a/src/components/widgets/ubg-cards.html b/src/components/widgets/ubg-cards.html index 4435b7432..afcfb1031 100644 --- a/src/components/widgets/ubg-cards.html +++ b/src/components/widgets/ubg-cards.html @@ -160,7 +160,7 @@