Merge branch 'equip-items-in-character-sheet' into 'master'
make equip icon for items clickable in item list in character sheet See merge request dungeonslayers/ds4!14
This commit is contained in:
commit
7f6896236c
5 changed files with 137 additions and 29 deletions
|
@ -62,6 +62,8 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
|
||||||
li.slideUp(200, () => this.render(false));
|
li.slideUp(200, () => this.render(false));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
html.find(".item-change").on("change", this._onItemChange.bind(this));
|
||||||
|
|
||||||
// Rollable abilities.
|
// Rollable abilities.
|
||||||
html.find(".rollable").click(this._onRoll.bind(this));
|
html.find(".rollable").click(this._onRoll.bind(this));
|
||||||
}
|
}
|
||||||
|
@ -70,7 +72,7 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle creating a new Owned Item for the actor using initial data defined in the HTML dataset
|
* Handle creating a new Owned Item for the actor using initial data defined in the HTML dataset
|
||||||
* @param {Event} event The originating click event
|
* @param {JQuery.ClickEvent} event The originating click event
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private _onItemCreate(event: JQuery.ClickEvent): Promise<Item> {
|
private _onItemCreate(event: JQuery.ClickEvent): Promise<Item> {
|
||||||
|
@ -95,9 +97,93 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
|
||||||
return this.actor.createOwnedItem(itemData);
|
return this.actor.createOwnedItem(itemData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle changes to properties of an Owned Item from within character sheet.
|
||||||
|
* Can currently properly bind: see getValue().
|
||||||
|
* Assumes the item property is given as the value of the HTML element property 'data-property'.
|
||||||
|
* @param {JQuery.ChangeEvent<HTMLFormElement>} ev The originating change event
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _onItemChange(ev: JQuery.ChangeEvent<HTMLFormElement>): void {
|
||||||
|
ev.preventDefault();
|
||||||
|
console.log("Current target:", $(ev.currentTarget).get(0)["name"]);
|
||||||
|
const el: HTMLFormElement = $(ev.currentTarget).get(0);
|
||||||
|
const id = $(ev.currentTarget).parents(".item").data("itemId");
|
||||||
|
const item = duplicate(this.actor.getOwnedItem(id)); // getOwnedItem is typed incorrectly, it actually returns a ItemData<DS4ItemDataType>, not an Item
|
||||||
|
const property: string | undefined = $(ev.currentTarget).data("property");
|
||||||
|
|
||||||
|
// Early return:
|
||||||
|
// Disabled => do nothing
|
||||||
|
if (el.disabled || el.getAttribute("disabled")) return;
|
||||||
|
// name not given => raise
|
||||||
|
if (property === undefined) {
|
||||||
|
throw TypeError("HTML element does not provide 'data-property' attribute");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set new value
|
||||||
|
const newValue = this.getValue(el);
|
||||||
|
setProperty(item, property, newValue);
|
||||||
|
this.actor.updateOwnedItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect the value of a form element depending on the element's type
|
||||||
|
* The value is parsed to:
|
||||||
|
* - Checkbox: boolean
|
||||||
|
* - Text input: string
|
||||||
|
* - Number: number
|
||||||
|
* @param el the input element to collect the value of
|
||||||
|
*/
|
||||||
|
private getValue(el: HTMLFormElement): boolean | string | number {
|
||||||
|
// One needs to differentiate between e.g. checkboxes (value="on") and select boxes etc.
|
||||||
|
// Checkbox:
|
||||||
|
if (el.type === "checkbox") {
|
||||||
|
const value: boolean = el.checked;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text input:
|
||||||
|
else if (el.type === "text") {
|
||||||
|
const value: string = el.value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Numbers:
|
||||||
|
else if (el.type === "number") {
|
||||||
|
const value = Number(el.value.trim());
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Ranges:
|
||||||
|
// else if (el.type === "range") {
|
||||||
|
// const value: string = el.value.trim();
|
||||||
|
// return value;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Radio Checkboxes (untested, cf. FormDataExtended.process)
|
||||||
|
// else if (el.type === "radio") {
|
||||||
|
// const chosen: HTMLFormElement = el.find((r: HTMLFormElement) => r["checked"]);
|
||||||
|
// const value: string = chosen ? chosen.value : null;
|
||||||
|
// return value;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Multi-Select (untested, cf. FormDataExtended.process)
|
||||||
|
// else if (el.type === "select-multiple") {
|
||||||
|
// const value: Array<string> = [];
|
||||||
|
// el.options.array.forEach((opt: HTMLOptionElement) => {
|
||||||
|
// if (opt.selected) value.push(opt.value);
|
||||||
|
// });
|
||||||
|
// return value;
|
||||||
|
|
||||||
|
// unsupported:
|
||||||
|
else {
|
||||||
|
throw TypeError("Binding of item property to this type of HTML element not supported; given: " + el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle clickable rolls.
|
* Handle clickable rolls.
|
||||||
* @param {Event} event The originating click event
|
* @param {JQuery.ClickEvent} event The originating click event
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private _onRoll(event: JQuery.ClickEvent): void {
|
private _onRoll(event: JQuery.ClickEvent): void {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
@use "sass:color";
|
||||||
|
|
||||||
.items-list {
|
.items-list {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 7px 0;
|
margin: 7px 0;
|
||||||
|
@ -16,13 +18,26 @@
|
||||||
|
|
||||||
.item-image {
|
.item-image {
|
||||||
flex: 0 0 24px;
|
flex: 0 0 24px;
|
||||||
margin-right: 5px;
|
height: 100%;
|
||||||
|
//margin-right: 5px;
|
||||||
|
@include centered-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: auto;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name {
|
.item-name {
|
||||||
|
@ -36,6 +51,11 @@
|
||||||
|
|
||||||
.item-num-val {
|
.item-num-val {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
width: 2.5em;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.item-num-val:invalid {
|
||||||
|
background-color: color.mix(lightcoral, $c-light-grey, 25%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-description {
|
.item-description {
|
||||||
|
@ -43,6 +63,7 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
height: 100%;
|
||||||
p {
|
p {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
--}}
|
--}}
|
||||||
{{#*inline "addItemButton"}}
|
{{#*inline "addItemButton"}}
|
||||||
<div class="item-controls">
|
<div class="item-controls">
|
||||||
<a class="item-control item-create" title="Create item" data-type="{{dataType}}" {{!-- SPECIFIC --}}>
|
<a class="item-control item-create" title="Create item" data-type="{{dataType}}">
|
||||||
<i class="fas fa-plus"></i>
|
<i class="fas fa-plus"></i>
|
||||||
{{localize 'DS4.UserInteractionAddItem'}}</a>
|
{{localize 'DS4.UserInteractionAddItem'}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,14 +44,14 @@
|
||||||
<li class="item flexrow item-header">
|
<li class="item flexrow item-header">
|
||||||
{{!-- equipped --}}
|
{{!-- equipped --}}
|
||||||
{{#if (ne dataType 'equipment')}}
|
{{#if (ne dataType 'equipment')}}
|
||||||
<div title="{{localize 'DS4.ItemEquipped'}}" class="flex05">E</div>
|
<div class="flex05" title="{{localize 'DS4.ItemEquipped'}}">E</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{!-- image --}}
|
{{!-- image --}}
|
||||||
<div class="item-image" class="flex05"></div>
|
<div class="flex05 item-image"></div>
|
||||||
{{!-- amount --}}
|
{{!-- amount --}}
|
||||||
<div class="item-num-val" title="{{localize 'DS4.Quantity'}}" class="flex05">#</div>
|
<div class="flex05 item-num-val" title="{{localize 'DS4.Quantity'}}">#</div>
|
||||||
{{!-- name --}}
|
{{!-- name --}}
|
||||||
<div class="item-name flex3">{{localize 'DS4.ItemName'}}</div>
|
<div class="flex3 item-name">{{localize 'DS4.ItemName'}}</div>
|
||||||
{{!-- item type specifics --}}
|
{{!-- item type specifics --}}
|
||||||
{{> @partial-block }}
|
{{> @partial-block }}
|
||||||
{{!-- description --}}
|
{{!-- description --}}
|
||||||
|
@ -76,20 +76,19 @@
|
||||||
<li class="item flexrow" data-item-id="{{item._id}}">
|
<li class="item flexrow" data-item-id="{{item._id}}">
|
||||||
{{!-- equipped --}}
|
{{!-- equipped --}}
|
||||||
{{#if (ne item.data.data.equipped undefined)}}
|
{{#if (ne item.data.data.equipped undefined)}}
|
||||||
{{#if item.data.data.equipped}}<i class="fas fa-check-square flex05"></i>
|
<input class="flex05 item-change" type="checkbox" {{checked item.data.data.equipped}} data-dtype="Boolean"
|
||||||
{{else}}<i class="far fa-square flex05"></i>
|
data-property="data.equipped" title="{{localize 'DS4.ItemEquipped'}}">
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="flexrow flexnowrap flex15">
|
{{!-- image --}}
|
||||||
{{!-- image --}}
|
<div class="flex05 item-image">
|
||||||
<div class="item-image">
|
<img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
|
||||||
<img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
|
|
||||||
</div>
|
|
||||||
{{!-- amount --}}
|
|
||||||
<div class="item-num-val">{{item.data.data.quantity}}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
{{!-- amount --}}
|
||||||
|
<input class="flex05 item-num-val item-change" type="number" min="0" step="1" value="{{item.data.data.quantity}}" data-dtype="Number"
|
||||||
|
data-property="data.quantity" title="{{localize 'DS4.Quantity'}}">
|
||||||
{{!-- name --}}
|
{{!-- name --}}
|
||||||
<h4 class="item-name flex3">{{item.name}}</h4>
|
<input class="flex3 item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
|
||||||
|
data-property="name" title="{{localize 'DS4.ItemName'}}">
|
||||||
{{!-- item type specifics --}}
|
{{!-- item type specifics --}}
|
||||||
{{> @partial-block}}
|
{{> @partial-block}}
|
||||||
{{!-- description --}}
|
{{!-- description --}}
|
||||||
|
@ -109,22 +108,22 @@
|
||||||
<h4 class="items-list-title">{{localize 'DS4.ItemTypeWeapon'}}</h4>
|
<h4 class="items-list-title">{{localize 'DS4.ItemTypeWeapon'}}</h4>
|
||||||
<ol class="items-list">
|
<ol class="items-list">
|
||||||
{{#> itemListHeader dataType='weapon'}}
|
{{#> itemListHeader dataType='weapon'}}
|
||||||
<div title="{{localize 'DS4.AttackType'}}" class="flex05">{{localize 'DS4.AttackTypeAbbr'}}</div>
|
<div class="flex05 item-image" title="{{localize 'DS4.AttackType'}}">{{localize 'DS4.AttackTypeAbbr'}}</div>
|
||||||
<div class="item-num-val flex05" title="{{localize 'DS4.WeaponBonus'}}">
|
<div class="flex05 item-num-val" title="{{localize 'DS4.WeaponBonus'}}">
|
||||||
{{localize 'DS4.WeaponBonusAbbr'}}
|
{{localize 'DS4.WeaponBonusAbbr'}}
|
||||||
</div>
|
</div>
|
||||||
<div class="item-num-val flex05" title="{{localize 'DS4.OpponentDefense'}}">
|
<div class="flex05 item-num-val" title="{{localize 'DS4.OpponentDefense'}}">
|
||||||
{{localize 'DS4.OpponentDefenseAbbr'}}
|
{{localize 'DS4.OpponentDefenseAbbr'}}
|
||||||
</div>
|
</div>
|
||||||
{{/itemListHeader}}
|
{{/itemListHeader}}
|
||||||
{{#each itemsByType.weapon as |item id|}}
|
{{#each itemsByType.weapon as |item id|}}
|
||||||
{{#> itemListEntry item=item}}
|
{{#> itemListEntry item=item}}
|
||||||
<div class="flex05">
|
<div class="flex05 item-image">
|
||||||
<img src="{{lookup ../../config.attackTypesIcons item.data.data.attackType}}"
|
<img src="{{lookup ../../config.attackTypesIcons item.data.data.attackType}}"
|
||||||
title="{{lookup ../../config.attackTypes item.data.data.attackType}}" width="24" height="24" />
|
title="{{lookup ../../config.attackTypes item.data.data.attackType}}" width="24" height="24" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-num-val flex05">{{ item.data.data.weaponBonus}}</div>
|
<div class="flex05 item-num-val">{{ item.data.data.weaponBonus}}</div>
|
||||||
<div class="item-num-val flex05">{{ item.data.data.opponentDefense}}</div>
|
<div class="flex05 item-num-val">{{ item.data.data.opponentDefense}}</div>
|
||||||
{{/itemListEntry}}
|
{{/itemListEntry}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ol>
|
</ol>
|
||||||
|
@ -176,7 +175,8 @@
|
||||||
{{/itemListHeader}}
|
{{/itemListHeader}}
|
||||||
{{#each itemsByType.trinket as |item id|}}
|
{{#each itemsByType.trinket as |item id|}}
|
||||||
{{#> itemListEntry item=item }}
|
{{#> itemListEntry item=item }}
|
||||||
<div class="flex2">{{{item.data.data.storageLocation}}}</div>
|
<input class="flex2 item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
|
||||||
|
data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
|
||||||
{{/itemListEntry}}
|
{{/itemListEntry}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ol>
|
</ol>
|
||||||
|
@ -189,7 +189,8 @@
|
||||||
{{/itemListHeader}}
|
{{/itemListHeader}}
|
||||||
{{#each itemsByType.equipment as |item id|}}
|
{{#each itemsByType.equipment as |item id|}}
|
||||||
{{#> itemListEntry item=item }}
|
{{#> itemListEntry item=item }}
|
||||||
<div class="flex2">{{{item.data.data.storageLocation}}}</div>
|
<input class="flex2 item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
|
||||||
|
data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
|
||||||
{{/itemListEntry}}
|
{{/itemListEntry}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ol>
|
</ol>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="side-property">
|
<div class="side-property">
|
||||||
<label for="data.quantity">{{localize 'DS4.Quantity'}}</label>
|
<label for="data.quantity">{{localize 'DS4.Quantity'}}</label>
|
||||||
<input type="number" data-dtype="Number" name="data.quantity" value="{{data.quantity}}" />
|
<input type="number" min="0" step="1" data-dtype="Number" name="data.quantity" value="{{data.quantity}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="side-property">
|
<div class="side-property">
|
||||||
<label for="data.storageLocation">{{localize 'DS4.StorageLocation'}}</label>
|
<label for="data.storageLocation">{{localize 'DS4.StorageLocation'}}</label>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<div class="side-properties">
|
<div class="side-properties">
|
||||||
<div class="side-property">
|
<div class="side-property">
|
||||||
<label for="data.price">{{localize "DS4.PriceGold"}}</label>
|
<label for="data.price">{{localize "DS4.PriceGold"}}</label>
|
||||||
<input type="number" data-dtype="Number" name="data.price" value="{{data.price}}" />
|
<input type="number" min="0" data-dtype="Number" name="data.price" value="{{data.price}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="side-property">
|
<div class="side-property">
|
||||||
<label for="data.availability">{{localize "DS4.ItemAvailability"}}</label>
|
<label for="data.availability">{{localize "DS4.ItemAvailability"}}</label>
|
||||||
|
|
Loading…
Reference in a new issue