User Tools

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
lxplan [2026/01/25 02:22] – [js version] ssm2017lxplan [2026/01/27 12:47] (current) – [js version] ssm2017
Line 1924: Line 1924:
     <meta charset="UTF-8">     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>Lecteur XML avec XPath</title+    <title>Lxplan lib builder</title>
-    <script src="https://cdn.jsdelivr.net/npm/xmldom@0.6.0/xmldom.js"></script> +
-    <script src="https://cdn.jsdelivr.net/npm/xpath@0.0.3/xpath.js"></script>+
     <style>     <style>
         body {         body {
Line 1951: Line 1949:
         button:hover {         button:hover {
             background-color: #0056b3;             background-color: #0056b3;
 +        }
 +
 +        .test-result>span {
 +            font-weight: bold;
 +            padding: 5px;
 +        }
 +
 +        .valid {
 +            color: white;
 +            background-color: green;
 +        }
 +
 +        .invalid {
 +            color: white;
 +            background-color: red;
 +        }
 +
 +        .no-answer {
 +            color: black;
 +            background-color: white;
 +        }
 +
 +        .container {
 +            border: 1px solid black;
 +            border-radius: 5px;
 +            margin: 5px;
 +            padding: 10px;
         }         }
     </style>     </style>
Line 1957: Line 1982:
 <body> <body>
     <h1>Lxplan lib builder</h1>     <h1>Lxplan lib builder</h1>
-    <div>+    <div class="container"> 
 +        <details> 
 +            <summary>Cliquer içi pour lire la doc</summary> 
 +            <p>Pour créer une librairie, il faut : <br /> 
 +            <ul> 
 +                <li>Dessiner le symbole dans lxplan</li> 
 +                <li>Le symbole doit etre sur le premier layer</li> 
 +                <li>Une fois fini, le symbole doit etre dans un groupe</li> 
 +                <li>Enregistrer le projet dans un fichier .lxxplot</li> 
 +                <li>Utiliser ce script en important le fichier lxxplot puis en remplissant les champs obligatoires et 
 +                    les autres si besoin</li> 
 +                <li>Sauvegarder le fichier qui va donner un fichier .lxkey qui sera à mettre dans le dossier de la 
 +                    bibliotheque (voir l'onglet "library" dans les options de lxplan)</li> 
 +            </ul> 
 +            </p> 
 +        </details> 
 +    </div> 
 +    <div class="container">
         <h2>Charger le fichier lxxplot</h2>         <h2>Charger le fichier lxxplot</h2>
         <p>Sélectionnez un fichier llxplot sur votre appareil :</p>         <p>Sélectionnez un fichier llxplot sur votre appareil :</p>
-        <input type="file" id="fileInput" accept=".lxxplot" onclick="resetResults()" />+        <input type="file" id="fileInput" accept=".lxxplot" onclick="resetChecks()" />
     </div>     </div>
-    <div> +    <div class="container"
-        <h2>Tests</h2> +        <h2>Tester le fichier lxxplot</h2> 
-        <div>Le fichier est il un lxxplot ? : <span id="isLxxplot">Sans avis</span></div> +        <div>Le fichier est il un lxxplot ? : <span id="isLxxplot" class="test-result">...</span></div> 
-        <div>Le fichier possede t il une shape sur le premier layer ? :<span id="hasShape">Sans avis</span></div> +        <div>Le fichier possede t il une shape sur le premier layer ? :<span id="hasShape
-        <div>La shape, commence t elle par un groupe ? :<span id="hasGroup">Sans avis</span></div>+                class="test-result">...</span></div> 
 +        <div>La shape, commence t elle par un groupe ? :<span id="hasGroup" class="test-result">...</span></div>
         <button onclick="loadFile()">Tester le fichier</button>         <button onclick="loadFile()">Tester le fichier</button>
 +    </div>
 +    <div id="dataFields" class="container" hidden>
 +        <h2>Données de la librairie</h2>
 +        <div class="form-section">
 +            <div id="mandatoryFields">
 +                <h3>Champs obligatoires</h3>
 +                <div>
 +                    <label for="name">Type</label>
 +                    <input type="text" id="name" name="name" required />
 +                </div>
 +                <div>
 +                    <label for="fname">Full Name</label>
 +                    <input type="text" id="fname" name="fname" required />
 +                </div>
 +                <div>
 +                    <label for="id">Id</label>
 +                    <input type="text" id="id" name="id" required />
 +                </div>
 +                <div>
 +                    <label for="dataType">Type d'appareil</label>
 +                    <select id="dataType">
 +                        <option value="">Sélectionner un type d'appareil</option>
 +                    </select>
 +                </div>
 +            </div>
 +            <div id="optionalFields">
 +                <h3>Champs optionnels</h3>
 +                <details>
 +                    <summary>
 +                        Cliquer içi pour editer les champs optionnels
 +                    </summary>
 +                    <div id="dynamicFields">Selectionner d'abord un type d'appareil</div>
 +                </details>
 +            </div>
 +            <button id="saveButton" onclick="buildOutput()">Créer la librairie</button>
 +        </div>
     </div>     </div>
  
     <script>     <script>
-        // Charger le fichier XML sélectionné +        // declaration des variables 
-        var xmlContent = "";+        var xmlInputContent = ""; 
 +        var xmlOutputContent = ""; 
 +        var shape = "";
         var isLxxplot = false;         var isLxxplot = false;
         var hasShape = false;         var hasShape = false;
         var hasGroup = false;         var hasGroup = false;
 +        var filledOptionalFields = undefined;
 +        var filledFields = [];
         var isLxxplotDiv = document.getElementById("isLxxplot");         var isLxxplotDiv = document.getElementById("isLxxplot");
         var hasShapeDiv = document.getElementById("hasShape");         var hasShapeDiv = document.getElementById("hasShape");
         var hasGroupDiv = document.getElementById("hasGroup");         var hasGroupDiv = document.getElementById("hasGroup");
 +        var dataFields = document.getElementById("dataFields");
 +        var dataTypeSelect = document.getElementById('dataType');
 +        var dynamicFields = document.getElementById('dynamicFields');
 +
 +        // Tableau des options de la liste de sélection
 +        const selectOptions = [
 +            { id: "ers", label: "ERS", fields: "sid;have;lamp;watts;frame;beam;cd;abm;wt;note;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "zers", label: "Zoom Leko / ERS", fields: "sid;have;lamp;watts;frame;bm_w;bm_t;cd_w;cd_t;abm_w;abm_t;wt;note;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "fres", label: "Fresnel / PC", fields: "sid;have;lamp;watts;frame;bm_w;bm_t;cd_w;cd_t;abm_w;abm_t;wt;note;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "par", label: "PAR", fields: "sid;have;lamp;watts;frame;bm_x;bm_y;cd;abm_x;abm_y;wt;note;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "fl", label: "Flood", fields: "sid;have;lamp;watts;frame;beam;cd;abm;wt;note;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "strip", label: "Striplight", fields: "sid;have;lamp;watts;frame;bm_x;bm_y;cd;abm_x;abm_y;wt;cpf;lpc;dbl;note;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "scroll", label: "DMX Device", fields: "sid;have;note;scroll;dmode;d_mk;acc_loc" },
 +            { id: "mirror", label: "Mirror", fields: "sid;have;note;scroll;dmode;d_mk;acc_loc" },
 +            { id: "focus", label: "Focus Point", fields: "sid" },
 +            { id: "misc", label: "Other", fields: "sid;have;acc_loc" },
 +            { id: "mover", label: "Automated Fixture", fields: "sid;have;lamp;watts;frame;bm_w;bm_t;cd_w;cd_t;abm_w;abm_t;wt;note;scroll;dmode;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "cmymvr", label: "Color Mixing Automated Fixture", fields: "sid;have;lamp;watts;frame;bm_w;bm_t;cd_w;cd_t;abm_w;abm_t;wt;note;scroll;dmode;mixtype;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "rgb", label: "Color Mixing Rectangular Beam (obsolete rgb)", fields: "sid;have;lamp;watts;frame;bm_x;bm_y;cd;abm_x;abm_y;wt;note;scroll;dmode;mixtype;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "rgba", label: "Color Mixing Rectangular Beam (obsolete rgba)", fields: "sid;have;lamp;watts;frame;bm_x;bm_y;cd;abm_x;abm_y;wt;note;scroll;dmode;mixtype;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "led7", label: "Color Mixing Rectangular Beam", fields: "sid;have;lamp;watts;frame;bm_x;bm_y;cd;abm_x;abm_y;wt;note;scroll;dmode;mixtype;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "led7s", label: "Color Mixing Striplight", fields: "sid;have;lamp;watts;frame;bm_x;bm_y;cd;abm_x;abm_y;wt;cpf;lpc;dbl;note;scroll;dmode;mixtype;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "cmers", label: "Color Mixing Leko / ERS", fields: "sid;have;lamp;watts;frame;beam;cd;abm;wt;note;scroll;dmode;mixtype;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "cmzers", label: "Color Mixing Zoom ERS", fields: "sid;have;lamp;watts;frame;bm_w;bm_t;cd_w;cd_t;abm_w;abm_t;wt;note;scroll;dmode;mixtype;d_mk;d_adj_x;d_adj_y;d_adj_z" },
 +            { id: "cmscroll", label: "Color Mixing DMX Device", fields: "sid;have;note;scroll;dmode;mixtype;d_mk" },
 +            { id: "netnode", label: "Network Device", fields: "sid;have;note;dmode" },
 +        ];
 +
 +        // Tableau des champs disponibles
 +        const availableFields = [
 +            { id: "name", label: "Type", type: "text" },
 +            { id: "fname", label: "Full Name", type: "text" },
 +            { id: "id", label: "ID", type: "text" },
 +            { id: "sid", label: "Symbol ID", type: "text" },
 +            { id: "have", label: "Inventory", type: "number" },
 +            { id: "balance", label: "Balance", type: "number" },
 +            { id: "lamp", label: "Lamp", type: "text" },
 +            { id: "watts", label: "Watts", type: "number" },
 +            { id: "frame", label: "Color Frame", type: "text" },
 +            { id: "beam", label: "Field Angle", type: "number" },
 +            { id: "bm_x", label: "Field X", type: "number" },
 +            { id: "bm_y", label: "Field Y", type: "number" },
 +            { id: "bm_w", label: "Field Wide", type: "number" },
 +            { id: "bm_t", label: "Field Tight", type: "number" },
 +            { id: "cd", label: "Candela", type: "number" },
 +            { id: "cd_w", label: "Candela Wide", type: "number" },
 +            { id: "cd_t", label: "Candela Tight", type: "number" },
 +            { id: "abm", label: "Beam Angle", type: "number" },
 +            { id: "abm_x", label: "Beam X", type: "number" },
 +            { id: "abm_y", label: "Beam Y", type: "number" },
 +            { id: "abm_w", label: "Beam Wide", type: "number" },
 +            { id: "abm_t", label: "Beam Tight", type: "number" },
 +            { id: "wt", label: "Weight", type: "number" },
 +            { id: "cpf", label: "Sections Per Fixture", type: "number" },
 +            { id: "lpc", label: "Lamps Per Circuit", type: "number" },
 +            { id: "dbl", label: "Distance Between Lamps", type: "number" },
 +            { id: "note", label: "More Info", type: "text" },
 +            { id: "scroll", label: "Device Params", type: "text" },
 +            { id: "dmode", label: "Mode", type: "text" },
 +            { id: "mixtype", label: "Mix Type", type: "text" },
 +            { id: "d_mk", label: "Default Mark", type: "text" },
 +            { id: "acc_loc", label: "Placement", type: "text" },
 +            { id: "d_adj_x", label: "Default X Offset", type: "number" },
 +            { id: "d_adj_y", label: "Default Y Offset", type: "number" },
 +            { id: "d_adj_z", label: "Default Z Offset", type: "number" },
 +        ];
 +
 +        // reinitialise les resultats du test de fichier
 +        function resetChecks() {
 +            let content = '<span class="no-answer">Sans avis</span>';
 +            isLxxplotDiv.innerHTML = content;
 +            hasShapeDiv.innerHTML = content;
 +            hasGroupDiv.innerHTML = content;
 +            dataFields.hidden = true;
 +        }
 +
 +        // action quand le document est bien chargé
 +        document.addEventListener('DOMContentLoaded', () => {
 +            resetChecks();
 +            fillSelectOptions();
 +        });
 +
 +        // Remplit la liste déroulante de type d'appareil
 +        function fillSelectOptions() {
 +            dataTypeSelect.innerHTML = '<option value="">Sélectionner un type d\'appareil</option>';
 +            selectOptions.forEach((option) => {
 +                const optElement = document.createElement("option");
 +                optElement.value = option.id;
 +                optElement.textContent = option.label;
 +                dataTypeSelect.appendChild(optElement);
 +            });
 +        }
 +
 +        // ecoute si le type d'appareil est changé
 +        dataTypeSelect.addEventListener("change", () => {
 +            const selectedOptionId = dataTypeSelect.value;
 +            displayDynamicFields(selectedOptionId);
 +        });
 +
 +        // Affiche les champs optionnels en fonction du type d'appareil sélectionné
 +        function displayDynamicFields(selectedOptionId) {
 +            dynamicFields.innerHTML = "";// Efface les champs précédents
 +
 +            // Trouve l'option sélectionnée
 +            const selectedOption = selectOptions.find((option) => option.id === selectedOptionId);
 +
 +            if (!selectedOption || !selectedOption.fields) return;
 +
 +            // Récupère les IDs des champs à afficher
 +            const fieldIds = selectedOption.fields.split(";");
 +
 +            // Affiche chaque champ
 +            fieldIds.forEach((fieldId) => {
 +
 +                const field = availableFields.find((f) => f.id === fieldId);
 +
 +                if (field) {
 +                    const fieldDiv = document.createElement("div");
 +                    fieldDiv.innerHTML = `
 +        <label for="${field.id}">${field.label}:</label>
 +        <input type="${field.type}" id="${field.id}" name="${field.id}" />
 +      `;
 +                    dynamicFields.appendChild(fieldDiv);
 +                }
 +            });
 +        }
  
 +        // charge le fichier lxxplot
         function loadFile() {         function loadFile() {
             const fileInput = document.getElementById('fileInput');             const fileInput = document.getElementById('fileInput');
Line 1990: Line 2200:
             const reader = new FileReader();             const reader = new FileReader();
             reader.onload = function (e) {             reader.onload = function (e) {
-                xmlContent = e.target.result; +                xmlInputContent = e.target.result; 
-                if (runChecks()) { +                dataFields.hidden = !runChecks();
-                    buildOutput(); +
-                }+
             };             };
             reader.readAsText(file);             reader.readAsText(file);
         }         }
  
-        function resetResults() { +        // verifie le contenu du fichier lxxplot
-            isLxxplotDiv.textContent = "Sans avis"; +
-            hasShapeDiv.textContent = "Sans avis"; +
-            hasGroupDiv.textContent = "Sans avis"; +
-        } +
         function runChecks() {         function runChecks() {
             isLxxplot = checkIfValidPath("/lxplot", 'isLxxplot');             isLxxplot = checkIfValidPath("/lxplot", 'isLxxplot');
             hasShape = checkIfValidPath("/lxplot/layers/layer/shape", 'hasShape');             hasShape = checkIfValidPath("/lxplot/layers/layer/shape", 'hasShape');
 +            if (hasShape) {
 +                getShape();
 +            }
             hasGroup = checkIfValidPath("/lxplot/layers/layer/shape/class[text() = 'LXGroup']", 'hasGroup');             hasGroup = checkIfValidPath("/lxplot/layers/layer/shape/class[text() = 'LXGroup']", 'hasGroup');
             return (isLxxplot && hasShape && hasGroup);             return (isLxxplot && hasShape && hasGroup);
         }         }
  
-        function buildOutput() { +        // petit utilitaire pour tester le contenu du fichier lxxplot
-            console.log("todo"); +
-            generateTextFile(xmlContent); +
-        } +
         function checkIfValidPath(xpathQuery, resultDiv) {         function checkIfValidPath(xpathQuery, resultDiv) {
             resultDiv = document.getElementById(resultDiv);             resultDiv = document.getElementById(resultDiv);
 +            let status = parseXml(xpathQuery).status;
 +            resultDiv.innerHTML = status ? '<span class="valid">oui</span>' : '<span class="invalid">non</span>';
 +            return status;
 +        }
 +
 +        // petit utilitaire permettant de tester le xml du fichier lxxplot
 +        function parseXml(xpathQuery) {
             try {             try {
                 // Parser le XML                 // Parser le XML
                 const parser = new DOMParser();                 const parser = new DOMParser();
-                const xmlDoc = parser.parseFromString(xmlContent, "text/xml");+                const xmlDoc = parser.parseFromString(xmlInputContent, "text/xml");
  
                 // Exécuter la requête XPath                 // Exécuter la requête XPath
Line 2041: Line 2250:
                 // Afficher le résultat                 // Afficher le résultat
                 if (result.length > 0) {                 if (result.length > 0) {
-                    resultDiv.textContent = "oui"+                    return { "status"true, "data": result };
-                    return true;+
                 } else {                 } else {
-                    resultDiv.textContent = "non"+                    return { "status"false, "data": "Not found" };
-                    return false;+
                 }                 }
             } catch (e) {             } catch (e) {
-                resultDiv.textContent = "Erreur : e.message; +                console.error("error parsing xml"e.message)
-                return undefined;+                return { "status": false, "data": "Error : " + e.message };
             }             }
         }         }
  
-        function generateTextFile(content, filename = "output.txt") { +        // reuperer la shape depuis le fichier lxxplot 
-            const blob = new Blob([content]{ type: "text/plain;charset=utf-8}); +        function getShape() { 
-            const link = document.createElement("a"); +            try { 
-            link.href = URL.createObjectURL(blob); +                // Parser le XML 
-            link.download filename+                const parser = new DOMParser(); 
-            document.body.appendChild(link); +                const xmlDoc = parser.parseFromString(xmlInputContent, "text/xml"); 
-            link.click(); + 
-            document.body.removeChild(link)+                // Exécuter la requête XPath 
-            URL.revokeObjectURL(link.href);+                const xpathResult = document.evaluate( 
 +                    "/lxplot/layers/layer/shape", 
 +                    xmlDoc, 
 +                    null, 
 +                    XPathResult.FIRST_ORDERED_NODE_TYPE, 
 +                    null 
 +                ); 
 + 
 +                shape xpathResult.singleNodeValue
 +            } catch (e{ 
 +                console.error("error parsing xml", e.message); 
 +                return { "status": false, "data": "Error : " + e.message }
 +            }
         }         }
  
 +        // action quand on appuie sur le bouton "creer la librairie"
 +        function buildOutput() {
 +            if (checkFilledFields()) {
 +                buildXmlOutput();
 +            }
 +        }
 +
 +        // verifier que les champs soient bien remplis
 +        function checkFilledFields() {
 +            filledFields = [];
 +            getFilledChildren('mandatoryFields');
 +            if (Object.keys(filledFields).length < 3 || dataTypeSelect.value === '') {
 +                alert("Les 4 champs obligatoires doivent être remplis.");
 +                return false;
 +            }
 +            getFilledChildren('dynamicFields');
 +            return true;
 +        }
 +
 +        function getFilledChildren(id) {
 +            // recupere les champs
 +            const divElement = document.getElementById(id);
 +            const inputNodes = divElement.getElementsByTagName('input');
 +
 +            // teste les champs un par un
 +            for (let i = 0; i < inputNodes.length; i++) {
 +                if (inputNodes[i].value.trim() !== '') {
 +                    filledFields.push({ "id": inputNodes[i].id, "value": inputNodes[i].value });
 +                }
 +            }
 +        }
 +
 +        // fabrique le fichier de sortie et l'envoie a l'utilisateur
 +        function buildXmlOutput() {
 +            // creation du document xml
 +            const xmlDoc = new DOMParser().parseFromString('<key></key>', 'application/xml');
 +            const root = xmlDoc.documentElement;
 +
 +            // creation des elements basiques
 +            const kentryElement = xmlDoc.createElement('kentry');
 +            const customElement = xmlDoc.createElement("custom");
 +            const symbolElement = xmlDoc.createElement("symbol");
 +            const groupElement = xmlDoc.createElement("group");
 +            const kindElement = xmlDoc.createElement("kind");
 +            kindElement.textContent = dataTypeSelect.value;
 +
 +            // ajout des elements basiques dans l'arbre xml
 +            groupElement.appendChild(shape);
 +            symbolElement.appendChild(groupElement);
 +            customElement.appendChild(symbolElement);
 +            kentryElement.appendChild(kindElement);
 +
 +            // ajout de chaque champ rempli
 +            filledFields.forEach((item) => {
 +                const newItem = xmlDoc.createElement(item.id);
 +                newItem.textContent = item.value;
 +                kentryElement.appendChild(newItem);
 +            });
 +
 +            kentryElement.appendChild(customElement);
 +            root.appendChild(kentryElement);
 +
 +            // conversion en chaine de characteres
 +            const xmlString = "<?xml version='1.0' encoding='utf-8'?>\n" + new XMLSerializer().serializeToString(xmlDoc);
 +            console.log(xmlString);
 +
 +            // creation fichier
 +            const blob = new Blob([xmlString], { type: 'application/xml;charset=utf-8' });
 +            const url = URL.createObjectURL(blob);
 +
 +            // envoi du fichier
 +            const a = document.createElement('a');
 +            a.href = url;
 +            a.download = 'mylib.lxkey';
 +            a.click();
 +
 +            // nettoyage
 +            URL.revokeObjectURL(url);
 +        }
     </script>     </script>
 </body> </body>

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also, you acknowledge that you have read and understand our Privacy Policy. If you do not agree, please leave the website.

More information