From 3867a23c2d5f27d92db760b5772dac4553be89a2 Mon Sep 17 00:00:00 2001
From: Johannes Loher <johannes.loher@fg4f.de>
Date: Wed, 24 Feb 2021 04:52:32 +0100
Subject: [PATCH] Make item list a grid for items and spells

---
 src/ds4.scss                                  |  2 +-
 src/module/actor/sheets/actor-sheet.ts        |  6 +-
 src/scss/components/_items.scss               | 84 -----------------
 src/scss/components/_items_list.scss          | 89 +++++++++++++++++++
 .../actor/partials/character-inventory.hbs    |  6 +-
 .../actor/partials/items-overview.hbs         | 82 ++++++++---------
 .../actor/partials/spells-overview.hbs        | 33 +++----
 7 files changed, 147 insertions(+), 155 deletions(-)
 delete mode 100644 src/scss/components/_items.scss
 create mode 100644 src/scss/components/_items_list.scss

diff --git a/src/ds4.scss b/src/ds4.scss
index af018bb..6b6f6b0 100644
--- a/src/ds4.scss
+++ b/src/ds4.scss
@@ -16,7 +16,7 @@
     @import "scss/components/forms";
     @import "scss/components/basic_property";
     @import "scss/components/tabs";
-    @import "scss/components/items";
+    @import "scss/components/items_list";
     @import "scss/components/talents";
     @import "scss/components/description";
     @import "scss/components/character_values";
diff --git a/src/module/actor/sheets/actor-sheet.ts b/src/module/actor/sheets/actor-sheet.ts
index 1534131..de9a0e3 100644
--- a/src/module/actor/sheets/actor-sheet.ts
+++ b/src/module/actor/sheets/actor-sheet.ts
@@ -98,7 +98,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Data<DS4Actor>> {
 
         // Update Inventory Item
         html.find(".item-edit").on("click", (ev) => {
-            const li = $(ev.currentTarget).parents(".item");
+            const li = $(ev.currentTarget).parents(".item-row");
             const id = li.data("itemId");
             const item = this.actor.getOwnedItem(id);
             if (!item) {
@@ -112,7 +112,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Data<DS4Actor>> {
 
         // Delete Inventory Item
         html.find(".item-delete").on("click", (ev) => {
-            const li = $(ev.currentTarget).parents(".item");
+            const li = $(ev.currentTarget).parents(".item-row");
             this.actor.deleteOwnedItem(li.data("itemId"));
             li.slideUp(200, () => this.render(false));
         });
@@ -155,7 +155,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Data<DS4Actor>> {
     protected _onItemChange(ev: JQuery.ChangeEvent): void {
         ev.preventDefault();
         const el: HTMLFormElement = $(ev.currentTarget).get(0);
-        const id = $(ev.currentTarget).parents(".item").data("itemId");
+        const id = $(ev.currentTarget).parents(".item-row").data("itemId");
         const item = duplicate<DS4Item, "lenient">(this.actor.getOwnedItem(id));
         const property: string | undefined = $(ev.currentTarget).data("property");
 
diff --git a/src/scss/components/_items.scss b/src/scss/components/_items.scss
deleted file mode 100644
index 6382c58..0000000
--- a/src/scss/components/_items.scss
+++ /dev/null
@@ -1,84 +0,0 @@
-@use "sass:color";
-
-.items-list {
-    list-style: none;
-    margin: 7px 0;
-    padding: 0;
-    overflow-y: auto;
-
-    .item-header {
-        font-weight: bold;
-    }
-
-    .item {
-        height: 30px;
-        line-height: 24px;
-        padding: 3px 0;
-        border-bottom: 1px solid #bbb;
-
-        .item-image {
-            flex: 0 0 24px;
-            height: 100%;
-            //margin-right: 5px;
-            @include centered-content;
-        }
-
-        img {
-            display: block;
-            border: none;
-        }
-
-        input {
-            border: 0;
-            padding: 0;
-            background-color: transparent;
-        }
-
-        input[type="checkbox"] {
-            width: auto;
-            height: 100%;
-            margin: 0px;
-        }
-
-        @include mark-invalid-or-disabled-input;
-    }
-
-    .item-name {
-        margin: 0;
-    }
-
-    .item-controls {
-        flex: 0 0 86px;
-        text-align: right;
-    }
-
-    .item-num-val {
-        text-align: center;
-        width: 2.5em;
-        padding: 0;
-    }
-
-    .item-description {
-        font-size: 75%;
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        height: 100%;
-        p {
-            text-overflow: ellipsis;
-            overflow: hidden;
-        }
-        p:first-child {
-            margin-top: 0px;
-            padding-top: 0px;
-        }
-    }
-}
-
-.items-list-title {
-    margin-top: 2em;
-    margin-bottom: 0px;
-    padding-left: 1em;
-    border-bottom: 2px groove $c-border-groove;
-    font-weight: bold;
-}
diff --git a/src/scss/components/_items_list.scss b/src/scss/components/_items_list.scss
new file mode 100644
index 0000000..6c223c2
--- /dev/null
+++ b/src/scss/components/_items_list.scss
@@ -0,0 +1,89 @@
+@use "sass:color";
+
+.items-list {
+    $row-height: 1.75em;
+    display: grid;
+    grid-column-gap: 0.5em;
+    grid-row-gap: 0.2em;
+    align-items: center;
+    &.weapon {
+        grid-template-columns: $row-height $row-height 3ch 3fr $row-height 1fr 3ch 5fr 4ch;
+    }
+    &.armor {
+        grid-template-columns: $row-height $row-height 3ch 3fr 1fr 1fr 3ch 5fr 4ch;
+    }
+    &.shield {
+        grid-template-columns: $row-height $row-height 3ch 3fr 3ch 5fr 4ch;
+    }
+    &.equipment {
+        grid-template-columns: $row-height $row-height 3ch 3fr 10ch 5fr 4ch;
+    }
+    &.loot {
+        grid-template-columns: $row-height 3ch 3fr 10ch 5fr 4ch;
+    }
+    &.spell {
+        grid-template-columns: $row-height $row-height 2fr $row-height 1fr 1fr 1fr 1fr 4ch;
+    }
+
+    margin: 7px 0;
+    padding: 0;
+    overflow-y: auto;
+
+    .item-row {
+        display: contents;
+
+        &.item-header {
+            font-weight: bold;
+            display: contents;
+        }
+
+        > * {
+            height: $row-height;
+            line-height: $row-height;
+            white-space: nowrap;
+        }
+
+        .item-image {
+            background-repeat: no-repeat;
+            background-size: 100%;
+            background-position: center;
+        }
+
+        input {
+            border: 0;
+            padding: 0;
+            background-color: transparent;
+        }
+
+        input[type="checkbox"] {
+            width: 100%;
+            height: 100%;
+            margin: 0px;
+        }
+
+        @include mark-invalid-or-disabled-input;
+    }
+
+    .item-description {
+        //white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        :not(:first-child) {
+            display: none;
+        }
+        > * {
+            font-size: 0.75em;
+            text-overflow: ellipsis;
+            overflow: hidden;
+            margin: 0;
+        }
+    }
+}
+
+.items-list-title {
+    margin-top: 1em;
+    margin-bottom: 0;
+    padding-left: 1em;
+    border-bottom: 2px groove $c-border-groove;
+    font-weight: bold;
+}
diff --git a/src/templates/actor/partials/character-inventory.hbs b/src/templates/actor/partials/character-inventory.hbs
index b27fff6..07de73e 100644
--- a/src/templates/actor/partials/character-inventory.hbs
+++ b/src/templates/actor/partials/character-inventory.hbs
@@ -1,7 +1,7 @@
 <div class="tab inventory" data-group="primary" data-tab="inventory">
 
     {{!-- Money--}}
-    <h4 class="items-list-title">{{localize 'DS4.CharacterCurrency'}}</h4>
+    {{!-- <h4 class="items-list-title">{{localize 'DS4.CharacterCurrency'}}</h4>
     <ol class="items-list">
         <li class="item flexrow item-header">
             <label for="data.currency.gold" class="flex05">{{config.i18n.characterCurrency.gold}}</label>
@@ -14,8 +14,8 @@
             <input class="flex3 item-num-val item-change" type="number" min="0" step="1" name="data.currency.copper"
                 id="data.currency.copper" value="{{data.currency.copper}}" data-dtype="Number" />
         </li>
-    </ol>
+    </ol> --}}
 
     {{> systems/ds4/templates/actor/partials/items-overview.hbs}}
 
-</div>
\ No newline at end of file
+</div>
diff --git a/src/templates/actor/partials/items-overview.hbs b/src/templates/actor/partials/items-overview.hbs
index e0dc4e2..704cb49 100644
--- a/src/templates/actor/partials/items-overview.hbs
+++ b/src/templates/actor/partials/items-overview.hbs
@@ -22,31 +22,30 @@
 
 {{!--
 !-- Render a header row for a given data type.
-!-- It is a flexbox with a child for each column head.
 !-- An "equipped" heading is rendered except for the case dataType==='loot'.
 !-- The partial assumes a variable dataType to be given in the context.
 !-- If the partial is called with a partial block, the partial block
 !-- content is inserted before the description heading.
 
 !-- @param datType: hand over the dataType to the partial as hash parameter
-!-- @param partial-block: hand over custom children of the flexbox in the partial block.
+!-- @param partial-block: hand over custom children in the partial block.
 --}}
 {{#*inline "itemListHeader" }}
-<li class="item flexrow item-header">
+<li class="item-row item-header">
     {{!-- equipped --}}
     {{#if (ne dataType 'loot')}}
-    <div class="flex05" title="{{localize 'DS4.ItemEquipped'}}">{{localize 'DS4.ItemEquippedAbbr'}}</div>
+    <div title="{{localize 'DS4.ItemEquipped'}}">{{localize 'DS4.ItemEquippedAbbr'}}</div>
     {{/if}}
     {{!-- image --}}
-    <div class="flex05 item-image"></div>
+    <div class="item-image"></div>
     {{!-- amount --}}
-    <div class="flex05 item-num-val" title="{{localize 'DS4.Quantity'}}">#</div>
+    <div class="item-num-val" title="{{localize 'DS4.Quantity'}}">#</div>
     {{!-- name --}}
-    <div class="flex3 item-name">{{localize 'DS4.ItemName'}}</div>
+    <div class="item-name">{{localize 'DS4.ItemName'}}</div>
     {{!-- item type specifics --}}
     {{> @partial-block }}
     {{!-- description --}}
-    <div class="flex4">{{localize 'DS4.Description'}}</div>
+    <div>{{localize 'DS4.Description'}}</div>
     {{!-- control buttons placeholder --}}
     <div></div>
 </li>
@@ -54,36 +53,33 @@
 
 {{!--
 !-- Render a list row from a given item.
-!-- It is a flexbox with a child for each item value of interest.
 !-- An equipped checkbox is rendered except for the case item.data.type==='loot'.
 !-- The partial assumes a variable item to be given in the context.
 !-- If the partial is called with a partial block, the partial block
 !-- content is inserted before the description.
 
 !-- @param item: hand over the item to the partial as hash parameter
-!-- @param partial-block: hand over custom children of the flexbox in the partial block.
+!-- @param partial-block: hand over custom children in the partial block.
 --}}
 {{#*inline "itemListEntry"}}
-<li class="item flexrow" data-item-id="{{item._id}}">
+<li class="item-row" data-item-id="{{item._id}}">
     {{!-- equipped --}}
     {{#if (ne item.data.type 'loot')}}
-    <input class="flex05 item-change" type="checkbox" {{checked item.data.data.equipped}} data-dtype="Boolean"
+    <input class="item-change" type="checkbox" {{checked item.data.data.equipped}} data-dtype="Boolean"
         data-property="data.equipped" title="{{localize 'DS4.ItemEquipped'}}">
     {{/if}}
     {{!-- image --}}
-    <div class="flex05 item-image">
-        <img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
-    </div>
+    <div class="item-image" style="background-image: url('{{item.img}}')" title="{{item.name}}"></div>
     {{!-- amount --}}
-    <input class="flex05 item-num-val item-change" type="number" min="0" step="1" value="{{item.data.data.quantity}}"
+    <input class="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 --}}
-    <input class="flex3 item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
-        data-property="name" title="{{htmlToPlainText item.data.data.description}}" />
+    <input class="item-name item-change" type="text" value="{{item.name}}" data-dtype="String" data-property="name"
+        title="{{htmlToPlainText item.data.data.description}}" />
     {{!-- item type specifics --}}
     {{> @partial-block}}
     {{!-- description --}}
-    <div class="flex4 item-description" title="{{htmlToPlainText item.data.data.description}}">
+    <div class="item-description" title="{{htmlToPlainText item.data.data.description}}">
         {{{item.data.data.description}}}</div>
     {{!-- control buttons --}}
     {{> systems/ds4/templates/actor/partials/overview-control-buttons.hbs }}
@@ -95,41 +91,38 @@
 
 {{!-- WEAPONS --}}
 <h4 class="items-list-title">{{localize 'DS4.ItemTypeWeaponPlural'}}</h4>
-{{!-- {{#if (and (ne itemsByType.weapon undefined) (gt itemsByType.weapon.length 0)) }} --}}
 {{#> ifHasItemOfType itemsArray=itemsByType.weapon dataType='weapon' }}
-<ol class="items-list">
+<ol class="items-list weapon">
     {{#> itemListHeader dataType='weapon'}}
-    <div class="flex05 item-image" title="{{localize 'DS4.AttackType'}}">{{localize 'DS4.AttackTypeAbbr'}}</div>
-    <div class="flex05 item-num-val" title="{{localize 'DS4.WeaponBonus'}}">
+    <div class="item-image" title="{{localize 'DS4.AttackType'}}">{{localize 'DS4.AttackTypeAbbr'}}</div>
+    <div class="item-num-val" title="{{localize 'DS4.WeaponBonus'}}">
         {{localize 'DS4.WeaponBonusAbbr'}}
     </div>
-    <div class="flex05 item-num-val" title="{{localize 'DS4.OpponentDefense'}}">
+    <div class="item-num-val" title="{{localize 'DS4.OpponentDefense'}}">
         {{localize 'DS4.OpponentDefenseAbbr'}}
     </div>
     {{/itemListHeader}}
     {{#each itemsByType.weapon as |item id|}}
     {{#> itemListEntry item=item}}
-    <div class="flex05 item-image">
-        <img src="{{lookup ../../config.icons.attackTypes  item.data.data.attackType}}"
-            title="{{lookup ../../config.i18n.attackTypes  item.data.data.attackType}}" width="24" height="24" />
+    <div class="item-image"
+        style="background-image: url('{{lookup ../../config.icons.attackTypes  item.data.data.attackType}}')"
+        title="{{lookup ../../config.i18n.attackTypes  item.data.data.attackType}}">
     </div>
-    <div class="flex05 item-num-val">{{ item.data.data.weaponBonus}}</div>
-    <div class="flex05 item-num-val">{{ item.data.data.opponentDefense}}</div>
+    <div class="item-num-val">{{ item.data.data.weaponBonus}}</div>
+    <div class="item-num-val">{{ item.data.data.opponentDefense}}</div>
     {{/itemListEntry}}
     {{/each}}
 </ol>
-{{!-- {{else}}
-{{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType='weapon' }} --}}
 {{/ifHasItemOfType}}
 
 {{!-- ARMOR --}}
 <h4 class="items-list-title">{{localize 'DS4.ItemTypeArmorPlural'}}</h4>
 {{#> ifHasItemOfType itemsArray=itemsByType.armor dataType='armor' }}
-<ol class="items-list">
+<ol class="items-list armor">
     {{#> itemListHeader dataType='armor'}}
     <div title="{{localize 'DS4.ArmorMaterialType'}}">{{localize 'DS4.ArmorMaterialTypeAbbr'}}</div>
     <div title="{{localize 'DS4.ArmorType'}}">{{localize 'DS4.ArmorTypeAbbr'}}</div>
-    <div class="flex05 item-num-val" title="{{localize 'DS4.ArmorValue'}}">
+    <div class="item-num-val" title="{{localize 'DS4.ArmorValue'}}">
         {{localize 'DS4.ArmorValueAbbr'}}
     </div>
     {{/itemListHeader}}
@@ -141,7 +134,7 @@
     <div title="{{lookup ../../config.i18n.armorTypes  item.data.data.armorType}}">
         {{lookup ../../config.i18n.armorTypesAbbr item.data.data.armorType}}
     </div>
-    <div class="flex05 item-num-val">{{ item.data.data.armorValue}}</div>
+    <div class="item-num-val">{{ item.data.data.armorValue}}</div>
     {{/itemListEntry}}
     {{/each}}
 </ol>
@@ -149,32 +142,33 @@
 
 
 {{!-- SHIELD --}}
-<h4 class="items-list-title">{{localize 'DS4.ItemTypeShieldPlural'}}</h4> {{!-- SPECIFIC --}}
+<h4 class="items-list-title">{{localize 'DS4.ItemTypeShieldPlural'}}</h4>
 {{#> ifHasItemOfType itemsArray=itemsByType.shield dataType='shield' }}
-<ol class="items-list">
+<ol class="items-list shield">
     {{#> itemListHeader dataType='shield' }}
-    <div class="flex05 item-num-val" title="{{localize 'DS4.ArmorValue'}}">
+    <div class="item-num-val" title="{{localize 'DS4.ArmorValue'}}">
         {{localize 'DS4.ArmorValueAbbr'}}
     </div>
     {{/itemListHeader}}
     {{#each itemsByType.shield as |item id|}}
     {{#> itemListEntry item=item }}
-    <div class="flex05 item-num-val">{{item.data.data.armorValue}}</div> {{!-- SPECIFIC --}}
+    <div class="item-num-val">{{item.data.data.armorValue}}</div>
     {{/itemListEntry}}
     {{/each}}
 </ol>
 {{/ifHasItemOfType}}
 
 {{!-- EQUIPMENT --}}
+
 <h4 class="items-list-title">{{localize 'DS4.ItemTypeEquipmentPlural'}}</h4>
 {{#> ifHasItemOfType itemsArray=itemsByType.equipment dataType='equipment' }}
-<ol class="items-list">
+<ol class="items-list equipment">
     {{#> itemListHeader dataType='equipment'}}
-    <div class="flex2">{{localize 'DS4.StorageLocation'}}</div>
+    <div>{{localize 'DS4.StorageLocation'}}</div>
     {{/itemListHeader}}
     {{#each itemsByType.equipment as |item id|}}
     {{#> itemListEntry item=item }}
-    <input class="flex2 item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
+    <input class="item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
         data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
     {{/itemListEntry}}
     {{/each}}
@@ -184,13 +178,13 @@
 {{!-- LOOT --}}
 <h4 class="items-list-title">{{localize 'DS4.ItemTypeLootPlural'}}</h4>
 {{#> ifHasItemOfType itemsArray=itemsByType.loot dataType='loot' }}
-<ol class="items-list">
+<ol class="items-list loot">
     {{#> itemListHeader dataType='loot'}}
-    <div class="flex2">{{localize 'DS4.StorageLocation'}}</div>
+    <div>{{localize 'DS4.StorageLocation'}}</div>
     {{/itemListHeader}}
     {{#each itemsByType.loot as |item id|}}
     {{#> itemListEntry item=item }}
-    <input class="flex2 item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
+    <input class="item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
         data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
     {{/itemListEntry}}
     {{/each}}
diff --git a/src/templates/actor/partials/spells-overview.hbs b/src/templates/actor/partials/spells-overview.hbs
index 8bd974a..e10b34d 100644
--- a/src/templates/actor/partials/spells-overview.hbs
+++ b/src/templates/actor/partials/spells-overview.hbs
@@ -36,15 +36,14 @@ localizationString=localizationString}}
 
 
 <div class="tab spells" data-group="primary" data-tab="spells">
-    <ol class="items-list">
-        <li class="item flexrow item-header">
+    <ol class="items-list spell">
+        <li class="item-row item-header">
             {{!-- equipped --}}
-            <div class="flex05 item-image" title="{{localize 'DS4.ItemEquipped'}}">{{localize 'DS4.ItemEquippedAbbr'}}
-            </div>
+            <div title="{{localize 'DS4.ItemEquipped'}}">{{localize 'DS4.ItemEquippedAbbr'}}</div>
             {{!-- image --}}
-            <div class="flex05 item-image"></div>
+            <div class="item-image"></div>
             {{!-- name --}}
-            <div class="flex2 item-name">{{localize 'DS4.ItemName'}}</div>
+            <div class="item-name">{{localize 'DS4.ItemName'}}</div>
             {{!-- spell type --}}
             <div class="item-image" title="{{localize 'DS4.SpellType'}}">{{localize 'DS4.SpellTypeAbbr'}}</div>
             {{!-- spell bonus --}}
@@ -56,26 +55,22 @@ localizationString=localizationString}}
             {{!-- cooldown duration --}}
             <div class="item-num-val" title="{{localize 'DS4.SpellCooldownDuration'}}"><i
                     class="fas fa-hourglass-half"></i></div>
-            {{!-- description --}}
-            {{!-- <div class="flex3">{{localize 'DS4.Description'}}</div> --}}
             {{!-- control buttons placeholder --}}
             <div></div>
         </li>
         {{#each itemsByType.spell as |item id|}}
-        <li class="item flexrow" data-item-id="{{item._id}}">
-            <input class="flex05 item-image item-change" type="checkbox" {{checked item.data.data.equipped}}
-                data-dtype="Boolean" data-property="data.equipped" title="{{localize 'DS4.ItemEquipped'}}">
+        <li class="item-row" data-item-id="{{item._id}}">
+            <input class="item-change" type="checkbox" {{checked item.data.data.equipped}} data-dtype="Boolean"
+                data-property="data.equipped" title="{{localize 'DS4.ItemEquipped'}}">
             {{!-- image --}}
-            <div class="flex05 item-image">
-                <img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
-            </div>
+            <div class="item-image" style="background-image: url('{{item.img}}')" title="{{item.name}}"></div>
             {{!-- name --}}
-            <input class="flex2 item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
+            <input class="item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
                 data-property="name" title="{{htmlToPlainText item.data.data.description}}" />
             {{!-- spell type --}}
-            <div class="flex05 item-image">
-                <img src="{{lookup ../config.icons.spellTypes item.data.data.spellType}}"
-                    title="{{lookup ../config.i18n.spellTypes item.data.data.spellType}}" width="24" height="24" />
+            <div class="item-image"
+                style="background-image: url('{{lookup ../config.icons.spellTypes item.data.data.spellType}}')"
+                title="{{lookup ../config.i18n.spellTypes item.data.data.spellType}}">
             </div>
             {{!-- spell bonus --}}
             <input class="item-num-val item-change" type="text" data-dtype="String" data-property="data.bonus"
@@ -88,8 +83,6 @@ localizationString=localizationString}}
             {{!-- cooldown duration --}}
             {{> temporalUnit localizationString='DS4.SpellCooldownDuration' unitDatum=item.data.data.cooldownDuration
             config=../config}}
-            {{!-- description --}}
-            {{!-- <div class="flex3 item-description">{{{item.data.data.description}}}</div> --}}
             {{!-- control buttons --}}
             {{> systems/ds4/templates/actor/partials/overview-control-buttons.hbs }}
         </li>