From bb80cdf5a6157ca1f3a276e12e9faae9a4739cb7 Mon Sep 17 00:00:00 2001
From: dh_ackergaul <dh_ackergaul@dh-software.de>
Date: Di, 23 Jun 2026 11:16:18 +0200
Subject: [PATCH] Update emvheya - 23.6.2026, 11:16:10 [JD]

---
 manufacturer/_furnview/_global/html/h/generic-katatree/dev/AdditionalPositions/index.html |  411 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 411 insertions(+), 0 deletions(-)

diff --git a/manufacturer/_furnview/_global/html/h/generic-katatree/dev/AdditionalPositions/index.html b/manufacturer/_furnview/_global/html/h/generic-katatree/dev/AdditionalPositions/index.html
new file mode 100644
index 0000000..c8e6d1d
--- /dev/null
+++ b/manufacturer/_furnview/_global/html/h/generic-katatree/dev/AdditionalPositions/index.html
@@ -0,0 +1,411 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta charset="UTF-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=11">
+    <title>GenericKataTree</title>
+    <script language="JavaScript" src="../../../js/default.js"></script>
+    <style>
+        body {
+            font-family: "Segoe UI", Calibri, Helvetica, Arial, sans-serif;
+            font-size: 14px;
+            color: #212121;
+            background-color: #ffffff;
+            margin: 0;
+            padding: 16px;
+        }
+
+        .articleForm {
+            max-width: 360px;
+            border: 1px solid #D1D3D4;
+            padding: 16px;
+        }
+
+        .articleForm h2 {
+            margin: 0 0 12px;
+            font-size: 16px;
+            font-weight: bold;
+        }
+
+        .articleForm .formRow {
+            margin-bottom: 10px;
+        }
+
+        .articleForm label {
+            display: block;
+            margin-bottom: 3px;
+            font-weight: bold;
+            color: #333333;
+        }
+
+        /* width 95% statt 100% + box-sizing: IE7 unterstuetzt box-sizing nicht */
+        .articleForm input {
+            width: 95%;
+            padding: 5px 7px;
+            border: 1px solid #bdbdbd;
+            background-color: #ffffff;
+            font-family: "Segoe UI", Calibri, Arial, sans-serif;
+            font-size: 13px;
+            color: #212121;
+        }
+
+        .articleForm input:focus {
+            border-color: #F7931E;
+        }
+
+        .articleForm .formActions {
+            margin-top: 14px;
+            text-align: right;
+        }
+
+        .articleForm button {
+            padding: 5px 14px;
+            margin-left: 6px;
+            border: 1px solid #bdbdbd;
+            background-color: #f0f0f0;
+            color: #212121;
+            font-family: inherit;
+            font-size: 13px;
+            cursor: pointer;
+        }
+
+        .articleForm button:hover {
+            background-color: #E8E8E8;
+            border-color: #808285;
+        }
+
+        .articleForm button.primary {
+            background-color: #F7931E;
+            border-color: #F7931E;
+            color: #ffffff;
+        }
+
+        .articleForm button.primary:hover {
+            background-color: #ff8014;
+            border-color: #ff8014;
+        }
+
+        /* ----- Artikelliste (Tabelle) ----- */
+        .articleTable {
+            margin-top: 24px;
+            border-collapse: collapse;
+            border: 1px solid #D1D3D4;
+            width: 600px;
+            font-family: "Segoe UI", Calibri, Arial, sans-serif;
+            font-size: 13px;
+        }
+
+        .articleTable th,
+        .articleTable td {
+            border: 1px solid #ECECEC;
+            padding: 6px 10px;
+            text-align: left;
+            vertical-align: middle;
+        }
+
+        .articleTable thead th {
+            background-color: #ECECEC;
+            color: #212121;
+            font-weight: bold;
+        }
+
+        .articleTable tbody tr {
+            background-color: #ffffff;
+        }
+
+        .articleTable tbody tr.alt {
+            background-color: #fbfbfb;
+        }
+
+        .articleTable .priceCell,
+        .articleTable .qtyCell {
+            text-align: right;
+            white-space: nowrap;
+        }
+
+        .articleTable .qtyCell {
+            width: 60px;
+        }
+
+        .articleTable .actionCell {
+            width: 80px;
+            text-align: center;
+        }
+
+        .articleTable .emptyState {
+            color: #707070;
+            font-style: italic;
+            text-align: center;
+            padding: 14px;
+        }
+
+        .articleTable button.deleteBtn {
+            padding: 3px 10px;
+            border: 1px solid #bdbdbd;
+            background-color: #f0f0f0;
+            color: #212121;
+            font-family: "Segoe UI", Calibri, Arial, sans-serif;
+            font-size: 12px;
+            cursor: pointer;
+        }
+
+        .articleTable button.deleteBtn:hover {
+            background-color: #808285;
+            border-color: #555555;
+            color: #ffffff;
+        }
+    </style>
+</head>
+
+<body>
+
+    <form id="articleForm" class="articleForm">
+
+        <div class="formActions">
+            <button type="button" onclick="openDialog()">Dialog anzeigen</button>
+        </div>
+        <h2>Artikel erfassen</h2>
+
+        <div class="formRow">
+            <label for="artNr">Artikelnummer</label>
+            <input type="text" id="artNr" name="artNr">
+        </div>
+
+        <div class="formRow">
+            <label for="artDescription">Artikelbeschreibung</label>
+            <input type="text" id="artDescription" name="artDescription">
+        </div>
+
+        <div class="formRow">
+            <label for="artPrice">Artikelpreis (&euro;)</label>
+            <input type="text" id="artPrice" name="artPrice" onkeyup="filterPriceInput(this);"
+                onchange="filterPriceInput(this);"
+                onpaste="setTimeout(function(){filterPriceInput(document.getElementById('artPrice'));},0);">
+        </div>
+
+        <div class="formRow">
+            <label for="artQuantity">Menge</label>
+            <input type="text" id="artQuantity" name="artQuantity" value="1" onkeyup="filterQuantityInput(this);"
+                onchange="filterQuantityInput(this);"
+                onpaste="setTimeout(function(){filterQuantityInput(document.getElementById('artQuantity'));},0);">
+        </div>
+
+        <div class="formActions">
+
+            <button type="button" class="primary" onclick="addArticle()">Speichern</button>
+        </div>
+    </form>
+
+    <table id="articleTable" class="articleTable" cellspacing="0">
+        <thead>
+            <tr>
+                <th>GUID</th>
+                <th>Artikelnummer</th>
+                <th>Beschreibung</th>
+                <th>Menge</th>
+                <th>Preis</th>
+                <th>&nbsp;</th>
+            </tr>
+        </thead>
+        <tbody id="articleTableBody">
+            <tr>
+                <td colspan="5" class="emptyState">Noch keine Artikel erfasst.</td>
+            </tr>
+        </tbody>
+    </table>
+
+</body>
+<script type="text/javascript">
+
+
+    var posList = DoSyncFPSAction("AdditionalPositions.GetArticleList", []);
+
+    debugger;
+
+    // ----- Liste & Render -----
+    var articleList = [];
+    // ----- Modell -----
+    function Artikel(id, artNr, description, price, quantity) {
+        this.id = id;
+        this.artNr = artNr;
+        this.description = description;
+        this.price = price;
+        this.quantity = quantity;
+    }
+    Artikel.prototype.getPriceFormatted = function () {
+        return this.price + " &euro;";
+    };
+    // ----- Submit -----
+    function addArticle() {
+        var artNr = document.getElementById("artNr");
+        var artDesc = document.getElementById("artDescription");
+        var artPrice = document.getElementById("artPrice");
+        var artQty = document.getElementById("artQuantity");
+
+        if (artNr.value.length === 0) {
+            // alert("Bitte Artikelnummer eingeben.");
+            // artNr.focus();
+            // return false;
+        }
+        if (artDesc.value.length === 0) {
+            alert("Bitte Artikelbeschreibung eingeben.");
+            artDesc.focus();
+            return false;
+        }
+        if (!isValidPrice(artPrice.value)) {
+            alert("Bitte einen gueltigen Preis aus Ziffern und optional einem Punkt eingeben (z.B. 12.50).");
+            artPrice.focus();
+            return false;
+        }
+        if (!isValidQuantity(artQty.value)) {
+            alert("Bitte eine ganzzahlige Menge groesser als 0 eingeben.");
+            artQty.focus();
+            return false;
+        }
+
+
+
+        var newPos = DoSyncFPSAction("AdditionalPositions.AddNeutralArticle", { "artNr": artNr.value, "artDesc": artDesc.value, "artPrice": artPrice.value, "artQty": artQty.value });
+        debugger;
+        articleList[articleList.length] = new Artikel(
+            newPos.id,
+            newPos.artNr,
+            newPos.artDesc,
+            newPos.artPrice,
+            newPos.artQty
+        );
+        renderArticleTable();
+    }
+
+
+    function deleteArticle(guid) {
+        // Array.prototype.splice ist in IE7 verfuegbar (ES3).
+        var list = DoSyncFPSAction("AdditionalPositions.DeleteArticle", { "artPosIds": [guid] });
+        debugger;
+        renderArticleTable();
+    }
+
+
+    function renderArticleTable() {
+        var tbody = document.getElementById("articleTableBody");
+        if (!tbody) return;
+
+        // IE wirft "Unknown runtime error" beim Setzen von innerHTML auf
+        // tbody/table/tr -> Zeilen ueber das DOM-Tableprogramming-Interface neu aufbauen.
+        while (tbody.rows.length > 0) {
+            tbody.deleteRow(0);
+        }
+
+        if (articleList.length === 0) {
+            var emptyRow = tbody.insertRow(-1);
+            var emptyCell = emptyRow.insertCell(-1);
+            emptyCell.colSpan = 6;
+            emptyCell.className = "emptyState";
+            emptyCell.appendChild(document.createTextNode("Noch keine Artikel erfasst."));
+            return;
+        }
+
+        for (var i = 0; i < articleList.length; i++) {
+            var a = articleList[i];
+            var row = tbody.insertRow(-1);
+            if (i % 2 === 1) {
+                row.className = "alt";
+            }
+
+            row.insertCell(-1).appendChild(document.createTextNode(a.id == null ? "" : String(a.id)));
+            row.insertCell(-1).appendChild(document.createTextNode(a.artNr == null ? "" : String(a.artNr)));
+            row.insertCell(-1).appendChild(document.createTextNode(a.description == null ? "" : String(a.description)));
+
+            var qtyCell = row.insertCell(-1);
+            qtyCell.className = "qtyCell";
+            qtyCell.appendChild(document.createTextNode(a.quantity == null ? "" : String(a.quantity)));
+
+            var priceCell = row.insertCell(-1);
+            priceCell.className = "priceCell";
+            priceCell.appendChild(document.createTextNode(a.getPriceFormatted()));
+
+            var actionCell = row.insertCell(-1);
+            actionCell.className = "actionCell";
+            // <input type="button"> statt <button>, weil im IE die "type"-
+            // Eigenschaft eines via createElement("button") erzeugten Elements
+            // nicht mehr aenderbar ist ("Das Objekt unterstuetzt diese Aktion nicht").
+            var btn = document.createElement("input");
+            btn.type = "button";
+            btn.className = "deleteBtn";
+            btn.value = "Löschen";
+            // Closure ueber i, damit jeder Button seinen eigenen Index behaelt.
+            btn.onclick = (function (idx) { return function () { deleteArticle(a.id); }; })(i);
+            actionCell.appendChild(btn);
+        }
+    }
+
+
+    function escapeHtml(s) {
+        if (s === null || s === undefined) return "";
+        return String(s)
+            .replace(/&/g, "&amp;")
+            .replace(/</g, "&lt;")
+            .replace(/>/g, "&gt;")
+            .replace(/"/g, "&quot;")
+            .replace(/'/g, "&#39;");
+    }
+
+    // ----- Preis-Filter / Validierung -----
+    function filterPriceInput(input) {
+        var val = input.value;
+        var cleaned = val.replace(/[^0-9.]/g, "");
+        var firstDot = cleaned.indexOf(".");
+        if (firstDot !== -1) {
+            cleaned = cleaned.substring(0, firstDot + 1)
+                + cleaned.substring(firstDot + 1).replace(/\./g, "");
+        }
+        if (cleaned !== val) {
+            input.value = cleaned;
+        }
+    }
+
+    function isValidPrice(val) {
+        if (val.length === 0) return false;
+        return /^[0-9]+(\.[0-9]+)?$/.test(val);
+    }
+
+    // Menge: nur Ziffern, kein Punkt, keine fuehrenden Nullen erzwungen, mindestens 1.
+    function filterQuantityInput(input) {
+        var cleaned = input.value.replace(/[^0-9]/g, "");
+        if (cleaned !== input.value) {
+            input.value = cleaned;
+        }
+    }
+
+    function isValidQuantity(val) {
+        if (val.length === 0) return false;
+        if (!/^[0-9]+$/.test(val)) return false;
+        return parseInt(val, 10) > 0;
+    }
+
+    function openDialog() {
+        var Version = DhMcControlObj.StringValueDest(-340, 0).value;
+        var FPVersion = DhMcControlObj.TableValueDest(32, 92715, 0, 0).value;
+
+        if (FPVersion === "Development EGGO" || FPVersion === "Furnplan Eggo") {
+            if (window.event && window.event.ctrlKey === true) {
+                // Bei EGGO mit gedrückter STRG-Taste neuen Dialog öffnen
+                DhMcControlObj.DoActionSimpleCL(17024);
+                return;
+            } else {
+                parent.parent.OpenConfigMenu("../zusatzpos.html");
+                return;
+            }
+        }
+
+        if (window.event && window.event.ctrlKey === true) {
+            parent.parent.OpenConfigMenu("../zusatzpos.html");
+            return;
+        }
+
+        DhMcControlObj.DoActionSimpleCL(17024);
+    }
+</script>
+
+</html>
\ No newline at end of file

--
Gitblit v1.9.3