templates/template/template.html.twig line 1

  1. {% extends 'base.html.twig' %}
  2. {% block body %}
  3.     <div class="container">
  4.         {{ form_start(templateForm,{attr:{"id":"form-template"}}) }}
  5.         {% if template.id %}
  6.         <input type="hidden"  name="id" value="{{ template.id }}">
  7.         {% endif %}
  8.         <ul class="nav nav-tabs" role="tablist">
  9.             <li class="nav-item" role="presentation">
  10.                 <a class="nav-link active" data-bs-toggle="tab" href="#infos" aria-selected="true" role="tab">Informations</a>
  11.             </li>
  12.             <li class="nav-item" role="presentation">
  13.                 <a class="nav-link" data-bs-toggle="tab" href="#template" aria-selected="false" tabindex="-1" role="tab">Template</a>
  14.             </li>
  15.             {% if template.id %}
  16.             <li class="nav-item me-auto" role="presentation">
  17.                 <a class="nav-link" id="preview" data-bs-toggle="tab" target="_blank" href="{{ path('app_template_view', {id: template.id}) }}" aria-selected="false" tabindex="-1" role="tab">Preview</a>
  18.             </li>
  19.             {% endif %}
  20.         </ul>
  21.         <div id="tabTemplateContent" class="tab-content">
  22.             <div class="tab-pane fade show active" id="infos" role="tabpanel">
  23.                 {{ form_row(templateForm.titre) }}
  24.                 {{ form_row(templateForm.type) }}
  25.                 {{ include('form/_collection.html.twig',{  formFieldHolder:templateForm.parametres, nom:"parametres-fields-list",id:"addParam", libelle:"Ajouter un paramétre"}) }}
  26.             </div>
  27.             <div class="tab-pane fade" id="template" role="tabpanel">
  28.                 <div class="btn-group">
  29.                     <button class="btn btn-secondary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasEntities" aria-controls="offcanvasEntities">
  30.                         Afficher les entités disponible
  31.                     </button>
  32.                     <button class="btn btn-sm btn-info" type="button" onclick="addInput()">Input</button>
  33.                     <button class="btn btn-sm btn-primary" type="button" onclick="addText()">Texte</button>
  34.                     <div class="btn-group" role="group" aria-label="Button group with nested dropdown" >
  35.                         <button type="button" class="btn btn-sm btn-primary" onclick="addTitre()">Titre (h1)</button>
  36.                         <div class="btn-group" role="group">
  37.                             <button id="btnGroupTitre" type="button" class="btn btn-sm btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
  38.                             <div class="dropdown-menu" aria-labelledby="btnGroupTitre">
  39.                                 <a class="dropdown-item" href="#?" onclick="addTitre(2)">H2</a>
  40.                                 <a class="dropdown-item" href="#?" onclick="addTitre(3)">H3</a>
  41.                                 <a class="dropdown-item" href="#?" onclick="addTitre(4)">H4</a>
  42.                                 <a class="dropdown-item" href="#?" onclick="addTitre(5)">H5</a>
  43.                                 <a class="dropdown-item" href="#?" onclick="addTitre(6)">H6</a>
  44.                             </div>
  45.                         </div>
  46.                     </div>
  47.                     <button class="btn btn-sm btn-warning" type="button" onclick="addButton()">Bouton</button>
  48.                     <button class="btn btn-sm btn-outline-primary" type="button" onclick="addBr()">Saut à la ligne</button>
  49.                     <div class="btn-group" role="group" aria-label="Button group with nested dropdown" >
  50.                         <button type="button" class="btn btn-sm btn-success" onclick="addTable()">Tableau</button>
  51.                         <div class="btn-group" role="group">
  52.                             <button id="btnGroupTitre" type="button" class="btn btn-sm btn-success dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
  53.                             <div class="dropdown-menu" aria-labelledby="btnGroupTitre">
  54.                                 <a class="dropdown-item" href="#?" onclick="addDiv()">Div</a>
  55.                             </div>
  56.                         </div>
  57.                     </div>
  58.                 </div>
  59.                 <div class="template-view" ></div>
  60.             </div>
  61.         </div>
  62.             <button class="btn btn-success" type="submit" >Valider</button>
  63.         {{ form_end(templateForm) }}
  64.     </div>
  65.     <div class="off">
  66.         <div id="conditions"></div>
  67.         <div id="options"></div>
  68.         <div id="editors"></div>
  69.         <div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasEntities" aria-labelledby="offcanvasEntitiesLabel">
  70.             <div class="offcanvas-header">
  71.                 <h5 class="offcanvas-title" id="offcanvasEntitiesLabel">Entitées disponible</h5>
  72.                 <button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  73.             </div>
  74.             <div class="offcanvas-body">
  75.                 <div class="accordion" id="accordionEntities">
  76.                     {% for entity, fields in entitiesData %}
  77.                         <div class="accordion-item">
  78.                            <h2 class="accordion-header" id="headingOne">
  79.                                <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse{{ loop.index }}" aria-expanded="false" aria-controls="collapse{{ loop.index }}">
  80.                                   {{ entity }}
  81.                                </button>
  82.                            </h2>
  83.                            <div id="collapse{{ loop.index }}" class="accordion-collapse collapse" aria-labelledby="heading{{ loop.index }}" data-bs-parent="#accordionEntities">
  84.                                <div class="accordion-body">
  85.                                    <ul>
  86.                                        {% for f in fields %}
  87.                                         <li><a href="#?" onclick="addToTemplate('{{ entity }}','{{ f }}')">{{ f }}</a></li>
  88.                                        {% endfor %}
  89.                                    </ul>
  90.                                </div>
  91.                            </div>
  92.                         </div>
  93.                     {% endfor %}
  94.                 </div>
  95.             </div>
  96.         </div>
  97.         <div class="card border-primary hide editor" id="text-editor">
  98.             <h3 class="card-header">Edition de texte <button onclick="closeCard(this)" type="button" class="btn-close" data-bs-dismiss="text-editor1"></button></h3>
  99.             <div class="card-body">
  100.                 <h6 class="card-subtitle text-muted">Support card subtitle</h6>
  101.             </div>
  102.             <div class="card-body">
  103.                 <div id="text-edit"></div>
  104.                 <button class="btn btn-success valid" >Valider</button>
  105.             </div>
  106.         </div>
  107.         <div class="card border-primary hide editor" id="title-editor">
  108.             <h3 class="card-header">Edition de titre <button onclick="closeCard(this)" type="button" class="btn-close" data-bs-dismiss="title-editor"></button></h3>
  109.             <div class="card-body">
  110.                 <div id="title-edit"></div>
  111.                 <button class="btn btn-success valid" >Valider</button>
  112.             </div>
  113.         </div>
  114.         <div class="card border-info hide editor" id="input-editor">
  115.             <h3 class="card-header">Edition de champ <button onclick="closeCard(this)" type="button" class="btn-close" data-bs-dismiss="title-editor"></button></h3>
  116.             <div class="card-body">
  117.                 <div class="form-group">
  118.                     <label for="nom" class="form-label">Nom du champs</label>
  119.                     <input type="text" class="form-control dbspace" id="nom">
  120.                 </div>
  121.                 <h6>Label</h6>
  122.                 <div id="label-edit"></div>
  123.                 <div class="form-group">
  124.                     <label for="type" class="form-label">Type</label>
  125.                     <select class="form-select" id="type" onchange="updateTypeOptions(this)">
  126.                         <option value="text">Text</option>
  127.                         <option value="textarea">TextArea</option>
  128.                         <option value="select">Select</option>
  129.                         <option value="radio">Radio</option>
  130.                     </select>
  131.                 </div>
  132.                 <div class="type-options">
  133.                     <div class="option text textarea">
  134.                         <div class="form-group">
  135.                             <label class="form-label" for="placeholder">Placeholder</label>
  136.                             <input id="placeholder" type="text" class="form-control" >
  137.                         </div>
  138.                     </div>
  139.                     <div class="option select radio">
  140.                         <div class="form-group">
  141.                             <label class="form-label">Choix</label>
  142.                             <ul class="choix">
  143.                                 <li class="hide" id="template">
  144.                                     <div class="btn-group">
  145.                                         <input type="text" class="form-control" placeholder="Value">
  146.                                         <input type="text" class="form-control" placeholder="Display">
  147.                                         <button type="button" class="btn btn-sm btn-danger" onclick="removeChoix(this)">-</button>
  148.                                     </div>
  149.                                 </li>
  150.                             </ul>
  151.                             <button class="btn btn-success" type="button" onclick="addChoix(this)">+</button>
  152.                         </div>
  153.                     </div>
  154.                 </div>
  155.                 <button class="btn btn-success valid" >Valider</button>
  156.             </div>
  157.         </div>
  158.         <div class="card border-success hide editor" id="table-editor">
  159.             <h3 class="card-header">Edition de tableau <button onclick="closeCard(this)" type="button" class="btn-close" data-bs-dismiss="title-editor"></button></h3>
  160.             <div class="card-body">
  161.                 <div class="form-group">
  162.                     <label for="rows" class="form-label">Lignes</label>
  163.                     <input type="number" class="form-control" id="rows">
  164.                 </div>
  165.                 <div class="form-group">
  166.                     <label for="cols" class="form-label">Colones</label>
  167.                     <input type="number" class="form-control" id="cols">
  168.                 </div>
  169.                 <div class="form-group">
  170.                     <label for="couleur" class="form-label">Couleur</label>
  171.                     <select class="form-select" id="couleur">
  172.                         <option></option>
  173.                         {% for col in ["primary", "secondary", "success", "info", "warning", "danger", "dark", "light"] %}
  174.                         <option value="{{ col }}">{{ col|capitalize }}</option>
  175.                         {% endfor %}
  176.                     </select>
  177.                 </div>
  178.                 <div class="form-group">
  179.                     <label for="border" class="form-label">Bordure</label>
  180.                     <select class="form-select" id="border">
  181.                         <option value="Non">Non</option>
  182.                         <option value="Oui">Oui</option>
  183.                     </select>
  184.                 </div>
  185.                 <div class="form-group">
  186.                     <label for="striped" class="form-label">Rayé</label>
  187.                     <select class="form-select" id="striped">
  188.                         <option value="Non">Non</option>
  189.                         <option value="Oui">Oui</option>
  190.                     </select>
  191.                 </div>
  192.             </div>
  193.             <div class="card-body preview">
  194.                 <h6 class="card-subtitle text-muted">Preview</h6>
  195.                 <table class="table table-bordered table-striped " id="table-view"><tbody></tbody></table>
  196.             </div>
  197.             <div class="card-body">
  198.                 <button class="btn btn-success valid" >Valider</button>
  199.             </div>
  200.         </div>
  201.         <div class="card border-warning hide editor" id="button-editor">
  202.             <h3 class="card-header">Edition de bouton <button onclick="closeCard(this)" type="button" class="btn-close" data-bs-dismiss="title-editor"></button></h3>
  203.             <div class="card-body">
  204.                 <div id="button-edit"></div>
  205.                 <div class="form-group">
  206.                     <label for="size" class="form-label">Taille</label>
  207.                     <select class="form-select" id="size">
  208.                         {% for s,t in {"btn":"normal", "btn-sm":"petit", "btn-lg":"grand"} %}
  209.                             <option value="{{ s }}">{{ t }}</option>
  210.                         {% endfor %}
  211.                     </select>
  212.                 </div>
  213.                 <div class="form-group">
  214.                     <label for="couleur" class="form-label">Couleur</label>
  215.                     <select class="form-select" id="couleur">
  216.                         <option></option>
  217.                         {% for col in ["primary", "secondary", "success", "info", "warning", "danger", "dark", "light", "close"] %}
  218.                             <option value="{{ col }}">{{ col|capitalize }}</option>
  219.                         {% endfor %}
  220.                     </select>
  221.                 </div>
  222.                 <div class="form-group">
  223.                     <label for="type" class="form-label">Type</label>
  224.                     <select class="form-select" id="type">
  225.                         {% for t in ["submit", "reset", "button"] %}
  226.                             <option value="{{ t }}">{{ t }}</option>
  227.                         {% endfor %}
  228.                     </select>
  229.                 </div>
  230.                 <div class="form-group">
  231.                     <label for="action" class="form-label">Action</label>
  232.                     <select class="form-select" id="action">
  233.                         {% for name,acts  in actions|default([]) %}
  234.                             <optgroup label="{{ name }}">
  235.                             {% for a, t in acts %}
  236.                             <option value="{{ a }}">{{ t }}</option>
  237.                             {% endfor %}
  238.                             </optgroup>
  239.                         {% endfor %}
  240.                     </select>
  241.                 </div>
  242.                 <button class="btn btn-success valid" >Valider</button>
  243.             </div>
  244.         </div>
  245.         <div class="card border-success hide editor" id="div-editor">
  246.             <h3 class="card-header">Edition de div <button onclick="closeCard(this)" type="button" class="btn-close" data-bs-dismiss="title-editor"></button></h3>
  247.             <div class="card-body">
  248.                 <div class="form-group">
  249.                     <label for="cols" class="form-label">Colones</label>
  250.                     <input type="number" class="form-control" id="cols">
  251.                 </div>
  252.                 <div class="form-group">
  253.                     <label for="couleur" class="form-label">Couleur</label>
  254.                     <select class="form-select" id="couleur">
  255.                         <option></option>
  256.                         {% for col in ["primary", "secondary", "success", "info", "warning", "danger", "dark", "light"] %}
  257.                         <option value="{{ col }}">{{ col|capitalize }}</option>
  258.                         {% endfor %}
  259.                     </select>
  260.                 </div>
  261.             </div>
  262.             <div class="card-body preview">
  263.                 <h6 class="card-subtitle text-muted">Preview</h6>
  264.                 <div class="alert row" id="div-view"></div>
  265.             </div>
  266.             <div class="card-body">
  267.                 <button class="btn btn-success valid" >Valider</button>
  268.             </div>
  269.         </div>
  270.         <div class="card border-danger hide editor" id="conditions-editor">
  271.             <h3 class="card-header">Editions des conditions <button onclick="closeCard(this)" type="button" class="btn-close" data-bs-dismiss="title-editor"></button></h3>
  272.             <div class="card-body">
  273.                 <div class="option">
  274.                     <div class="form-group">
  275.                         <table class="choix table">
  276.                             <thead>
  277.                             <tr>
  278.                                 <th>Action</th>
  279.                                 <th>Champs</th>
  280.                                 <th colspan="3">Condition</th>
  281.                             </tr>
  282.                             </thead>
  283.                             <tbody>
  284.                                 <tr class="hide" id="template">
  285.                                     <td>
  286.                                         <select class="form-select" id="act" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Tooltip on top">
  287.                                             <option value="show">Afficher</option>
  288.                                             <option value="hide">Cacher</option>
  289.                                             <option value="readOnly">Lecture seule</option>
  290.                                             <option value="disabled">Désactivé</option>
  291.                                         </select>
  292.                                     </td>
  293.                                     <td>
  294.                                         <select class="form-select" id="champs"  data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Tooltip on top"></select>
  295.                                         <input type="text" class="form-control hide" placeholder="champ entité">
  296.                                     </td>
  297.                                     <td>
  298.                                         <select class="form-select">
  299.                                                 <option value="=">Egal</option>
  300.                                                 <option value=">">Sup</option>
  301.                                                 <option value=">=">Sup ou égal</option>
  302.                                                 <option value="<">Inférieur</option>
  303.                                                 <option value="<=">Inférieur ou égal</option>
  304.                                                 <option value="start">Commence par</option>
  305.                                                 <option value="end">Fini par</option>
  306.                                                 <option value="cont">Contient</option>
  307.                                             </select>
  308.                                     </td>
  309.                                     <td>
  310.                                         <input type="text" class="form-control" placeholder="condition">
  311.                                     </td>
  312.                                     <td>
  313.                                         <button type="button" class="btn btn-sm btn-danger" onclick="removeCondition(this)">-</button>
  314.                                     </td>
  315.                                 </tr>
  316.                             </tbody>
  317.                         </table>
  318.                         <button class="btn btn-success" type="button" onclick="addCondition(this)">+</button>
  319.                     </div>
  320.                 </div>
  321.                 <button class="btn btn-success valid" >Valider</button>
  322.             </div>
  323.         </div>
  324.         <div class="card border-dark hide editor" id="options-editor">
  325.             <h3 class="card-header">Editions des options <button onclick="closeCard(this)" type="button" class="btn-close" data-bs-dismiss="title-editor"></button></h3>
  326.             <div class="card-body">
  327.                 <div class="form-group">
  328.                     <label for="rows" class="form-label">Défaut</label>
  329.                     <select class="form-select" id="act">
  330.                         <option value="show">Afficher</option>
  331.                         <option value="hide">Cacher</option>
  332.                         <option value="readOnly">Lecture seule</option>
  333.                         <option value="disabled">Désactivé</option>
  334.                     </select>                </div>
  335.                 <div class="form-group">
  336.                     <label for="rows" class="form-label">Classes</label>
  337.                     <input type="text" class="form-control" id="classes">
  338.                 </div>
  339.                 <div class="form-group">
  340.                     <label for="css" class="form-label">CSS</label>
  341.                     <textarea  class="form-control" id="css"></textarea>
  342.                 </div>
  343.                 <button class="btn btn-success valid" >Valider</button>
  344.             </div>
  345.         </div>
  346.     </div>
  347. {% endblock %}
  348. {% block title %}
  349. Nouvelle template
  350. {% endblock %}
  351. {% block javascripts %}
  352.     <script>
  353.         let toolbarOptions = [
  354.             ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
  355.             ['blockquote', 'code-block'],
  356.             ['link', 'image'],
  357.             [{ 'list': 'ordered'}, { 'list': 'bullet' }],
  358.             [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
  359.             [{ 'indent': '-1'}, { 'indent': '+1' }],          // outdent/indent
  360.             [{ 'direction': 'rtl' }],                         // text direction
  361.             [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
  362.             [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
  363.             [{ 'font': [] }],
  364.             [{ 'align': [] }],
  365.             ['clean']                                         // remove formatting button
  366.         ];
  367.         let curElement=null;
  368.         let curContainer=null;
  369.         let dropped = false;
  370.         //Editors
  371.         function openTextEditor(e) {
  372.             let type="text-editor"
  373.             let [editor, cid, target] = openEditor(type, e)
  374.             if(editor===null)
  375.                 return
  376.             let textEdit =editor.find("#text-edit")
  377.             textEdit.attr("id", "text-edit"+cid)
  378.             textEdit.html(target.html())
  379.             editor.find(".valid").click(validTextEditor)
  380.             editor.show()
  381.             var quill = addQuillEditor('#text-edit'+cid)
  382.         }
  383.         function openTitleEditor(e) {
  384.             let type="title-editor"
  385.             let [editor, cid, target] = openEditor(type, e)
  386.             if(editor===null)
  387.                 return
  388.             let textEdit =editor.find("#title-edit")
  389.             textEdit.attr("id", "title-edit"+cid)
  390.             textEdit.html(target.html())
  391.             editor.find(".valid").click(validTitleEditor)
  392.             editor.show()
  393.             var quill = addQuillEditor('#title-edit'+cid)
  394.         }
  395.         function openInputEditor(e) {
  396.             let type="input-editor"
  397.             let [editor, cid, target] = openEditor(type, e)
  398.             if(editor===null)
  399.                 return
  400.             let nomEdit =editor.find("#nom")
  401.             let nomTarget = target.find("input, select, textarea").attr("name")??""
  402.             nomEdit.val(nomTarget.replaceAll("_", " "))
  403.             let input= target.find("input, select, textarea")
  404.             let inputType = getInputType(input)
  405.             let typeEdit =editor.find("#type")
  406.             typeEdit.val(inputType)
  407.             updateTypeOptions(typeEdit)
  408.             let labelEdit =editor.find("#label-edit")
  409.             labelEdit.attr("id", "label-edit"+cid)
  410.             labelEdit.html(target.find("label").html())
  411.             setCustomData(editor, getCustomData(input))
  412.             editor.find(".valid").click(validInputEditor)
  413.             editor.show()
  414.             var quill = addQuillEditor('#label-edit'+cid)
  415.         }
  416.         function openTableEditor(e) {
  417.             let type="table-editor"
  418.             let [editor, cid, target] = openEditor(type, e)
  419.             if(editor===null)
  420.                 return
  421.             let couleur = target.getClassStartingWith('table-', ["table-bordered", "table-striped"])??"";
  422.             editor.find("#couleur").val(couleur.replace("table-", ""))
  423.             editor.on("input", updateTablePreview)
  424.             let border = target.hasClass("table-bordered")?"Oui":"Non";
  425.             editor.find("#border").val(border)
  426.             let striped = target.hasClass("table-striped")?"Oui":"Non";
  427.             editor.find("#striped").val(striped)
  428.             let rows = target.find("tr").length;
  429.             editor.find("#rows").val(rows)
  430.             let cols = target.find("tr:first td").length;
  431.             editor.find("#cols").val(cols)
  432.             let tableView =editor.find("#table-view")
  433.             $(target.html()).appendTo(tableView)
  434.             resetDrag(tableView.find(".updatable"))
  435.             editor.find(".valid").click(validTableEditor)
  436.             editor.show()
  437.             updateTablePreview({target:editor})
  438.         }
  439.         function openButtonEditor(e) {
  440.             let type="button-editor"
  441.             let [editor, cid, target] = openEditor(type, e)
  442.             if(editor.length===0)
  443.                 return
  444.             let button = $(target.find("button"))
  445.             console.log(button, target)
  446.             let couleur = button.getClassStartingWith('btn-',["btn-lg", "btn-sm"])??"";
  447.             editor.find("#couleur").val(couleur.replace("btn-", ""))
  448.             let size = button.hasClass("btn-lg")?"btn-lg":(button.hasClass("btn-sm")?"btn-sm":"btn")
  449.             editor.find("#size").val(size)
  450.             let typeBt = button.attr("type")??"submit"
  451.             editor.find("#type").val(typeBt)
  452.             let action = button.attr("action")??"submit"
  453.             editor.find("#action").val(action)
  454.             let buttonEdit =editor.find("#button-edit")
  455.             buttonEdit.attr("id", "button-edit"+cid)
  456.             buttonEdit.html(button.html())
  457.             editor.find(".valid").click(validButtonEditor)
  458.             var quill = addQuillEditor('#button-edit'+cid)
  459.             editor.show()
  460.         }
  461.         function openDivEditor(e) {
  462.             let type="div-editor"
  463.             let [editor, cid, target] = openEditor(type, e)
  464.             if(editor===null)
  465.                 return
  466.             let couleur = target.getClassStartingWith('alert-')??"";
  467.             editor.find("#couleur").val(couleur.replace("alert-", ""))
  468.             editor.on("input", updateDivPreview)
  469.             let cols = target.find(".col").length;
  470.             editor.find("#cols").val(cols)
  471.             let tableView =editor.find("#div-view")
  472.             $(target.html()).appendTo(tableView)
  473.             resetDrag(tableView.find(".updatable"))
  474.             editor.find(".valid").click(validDivEditor)
  475.             editor.show()
  476.             updateDivPreview({target:editor})
  477.         }
  478.         function openConditionsEditor(e) {
  479.             let type="conditions-editor"
  480.             let [editor, cid, target] = openEditor(type, e)
  481.             if(editor===null)
  482.                 return
  483.             let champs = editor.find("#template #champs")
  484.             $(".template-view").find("input, textarea, select").each(function () {
  485.                 let id = $(this).attr("id")
  486.                 champs.append(`<option value='${id}'>${id}</option>`)
  487.             })
  488.             champs.append(`<option value='entity'>Entité</option>`)
  489.             let conditions = $(".off #conditions")
  490.             let div = conditions.find("#"+cid)
  491.             if(div.length>0){
  492.                 div.find(".conds").each(function () {
  493.                     let values = $(this).text().split("%%")
  494.                     editor.find(".btn.btn-success").click()
  495.                     let tr =editor.find("table tr:last")
  496.                     tr.find("select:eq(0)").val(values[0])
  497.                     tr.find("select:eq(1)").val(values[1])
  498.                     tr.find("input:eq(0)").val(values[2])
  499.                     tr.find("input:eq(0)").toggle( values[1] === "entity")
  500.                     tr.find("select:eq(2)").val(values[3])
  501.                     tr.find("input:eq(1)").val(values[4])
  502.                 })
  503.             }
  504.             editor.find(".valid").click(validConditionEditor)
  505.             editor.show()
  506.         }
  507.         function openOptionsEditor(e) {
  508.             let type="options-editor"
  509.             let [editor, cid, target] = openEditor(type, e)
  510.             if(editor===null)
  511.                 return
  512.             let options = $(".off #options")
  513.             let div = options.find("#"+cid)
  514.             if(div.length>0){
  515.                 let values = div.text().split("%%")
  516.                 editor.find("select").val(values[0])
  517.                 editor.find("input").val(values[1])
  518.                 editor.find("textarea").val(values[2])
  519.             }
  520.             editor.find(".valid").click(validOptionsEditor)
  521.             editor.show()
  522.             //var quill = addQuillEditor('#text-edit'+cid)
  523.         }
  524.         function openEditor(type, e) {
  525.             let target = ["conditions-editor", "options-editor"].includes(type)?($(e.target).hasClass("updatable")? $(e.target):$(e.target).parents(".updatable"))  :($(e.target).hasClass("has-"+type)? $(e.target):$(e.target).parents(".has-"+type))
  526.             let cid= target.attr("cid")
  527.             if($("#new-"+type+cid).length>0)
  528.                 return [null, null, null]
  529.             let editor = $("#"+type).clone()
  530.             editor.attr("id","new-"+type+cid)
  531.             editor.appendTo("#editors")
  532.             let count = $(".editor:visible").length
  533.             let left =window.innerWidth/2 -editor.outerWidth()/2  + count *20
  534.             let top = window.innerHeight/2 - editor.outerHeight()/2+ count *20
  535.             editor.css({
  536.                 left:left,
  537.                 top:top
  538.             })
  539.             editor.draggable({
  540.                 handle: "h3.card-header",
  541.                 containment : "window",
  542.                 iframeFix: true,
  543.                 start:function () {
  544.                     let modal = $(this)
  545.                     modal.parent().append(modal)
  546.                     target.addClass("dragging")
  547.                 },
  548.                 drag:function () {
  549.                 },
  550.                 stop:function () {
  551.                     target.removeClass("dragging")
  552.                 }
  553.             });
  554.             return [editor, cid, target];
  555.         }
  556.         function openGoodEditor(event) {
  557.             let el = $(this)
  558.             let editorType= $(el).getClassStartingWith("has-")??""
  559.             switch (editorType){
  560.                 case "has-text-editor":
  561.                     openTextEditor(event)
  562.                     break;
  563.                 case "has-title-editor":
  564.                     openTitleEditor(event)
  565.                     break;
  566.                 case "has-input-editor":
  567.                     openInputEditor(event)
  568.                     break;
  569.                 case "has-table-editor":
  570.                     openTableEditor(event)
  571.                     break;
  572.                 case "has-div-editor":
  573.                     openDivEditor(event)
  574.                     break;
  575.                 case "has-button-editor":
  576.                     openButtonEditor(event)
  577.                     break;
  578.             }
  579.         }
  580.         //Editors option
  581.         function addQuillEditor(el) {
  582.             var quill = new Quill(el, {
  583.                 theme: 'snow',
  584.                 modules:{
  585.                     toolbar:toolbarOptions
  586.                 }
  587.             });
  588.         }
  589.         function addCondition(el) {
  590.             let div =$(el).parents(".option").find(".choix")
  591.             let template =div.find("#template").clone()
  592.             template = template.attr("id", "")
  593.             template = template.removeClass("hide")
  594.             div.append(template)
  595.         }
  596.         function removeCondition(el) {
  597.             $(el).parents("tr").slideUp("normal", function () {
  598.                 $(el).parents("tr").remove()
  599.             })
  600.         }
  601.         function addChoix(el) {
  602.             let div =$(el).parents(".option").find(".choix")
  603.             let template =div.find("#template").clone()
  604.             template = template.attr("id", "")
  605.             template = template.removeClass("hide")
  606.             div.append(template)
  607.         }
  608.         function removeChoix(el) {
  609.             $(el).parents("li").slideUp("normal", function () {
  610.                 $(el).parents("li").remove()
  611.             })
  612.         }
  613.         function updateTypeOptions(el) {
  614.             let val = $(el).val()
  615.             let options = $(el).parents(".editor").find(".type-options")
  616.             options.find(".option").hide()
  617.             options.find("."+val).show()
  618.         }
  619.         function getInputType(el) {
  620.             if ($(el).is("input")){
  621.                 if($(el).is(":text"))return "text";
  622.                 if($(el).is(":radio"))return "radio";
  623.             }
  624.             if ($(el).is("textarea") ) return "textarea";
  625.             if ($(el).is("select") )return "select";
  626.         }
  627.         function getCustomData(input) {
  628.             let custom ={}
  629.             let type = getInputType(input)
  630.             switch (type){
  631.                 case "text":
  632.                 case "textarea":
  633.                     custom["placeholder"]=input.attr("placeholder")
  634.                     break;
  635.                 case "select":
  636.                     custom["choix"]={}
  637.                     input.find("option").each(function () {
  638.                         custom["choix"][$(this).val()]=$(this).text()
  639.                     })
  640.                     break;
  641.             }
  642.             return custom
  643.         }
  644.         function setCustomData(editor, custom) {
  645.             if(custom["placeholder"]){
  646.                 editor.find("#placeholder").val(custom["placeholder"])
  647.             }
  648.             if(custom["choix"]){
  649.                 let choix = editor.find(".choix").parents(".option")
  650.                 for (const [key, value] of Object.entries(custom["choix"])) {
  651.                     if(key==="" && value==="")
  652.                         continue
  653.                     addChoix(choix.find(".btn.btn-success"))
  654.                     let li = choix.find("li:not(#tempalte):last")
  655.                     li.find("input:eq(0)").val(key)
  656.                     li.find("input:eq(1)").val(value)
  657.                 }
  658.             }
  659.         }
  660.         //Save editors
  661.         function validTextEditor(e) {
  662.             let editor =  $(e.target).parents(".editor")
  663.             let html =editor.find(".ql-editor").html()
  664.             let id = editor.attr("id").replace("new-text-editor", "")
  665.             $(".has-text-editor[cid='"+id+"']").html(html)
  666.             editor.slideUp("normal", ()=>{
  667.                 editor.remove()
  668.             })
  669.         }
  670.         function validTitleEditor(e) {
  671.             let editor =  $(e.target).parents(".editor")
  672.             let html =editor.find(".ql-editor").html()
  673.             let id = editor.attr("id").replace("new-title-editor", "")
  674.             $(".has-title-editor[cid='"+id+"']").html(html)
  675.             editor.slideUp("normal", ()=>{
  676.                 editor.remove()
  677.             })
  678.         }
  679.         function validInputEditor(e) {
  680.             let editor =  $(e.target).parents(".editor")
  681.             let html =editor.find(".ql-editor").html()
  682.             let id = editor.attr("id").replace("new-input-editor", "")
  683.             let type = editor.find("#type").val()
  684.             let nom = editor.find("#nom").val().replaceAll(" ", "_").trim()
  685.             let div = $(".has-input-editor[cid='"+id+"']")
  686.             let exnom=div.find("input, select, textarea").attr("id")
  687.             div.html("")
  688.             div.append("<label for='"+nom+"'>"+html+"</label>")
  689.             let input =""
  690.             switch (type) {
  691.                 case "text":
  692.                 case "textarea":
  693.                     let placeholder = editor.find("#placeholder").val()
  694.                     input=$(type==="text"?"<input readonly class='form-control'>":"<textarea readonly class='form-control'>")
  695.                     input.attr("placeholder", placeholder)
  696.                     break;
  697.                 case "select":
  698.                     input = $("<select readonly class='form-select'>")
  699.                     let choix = editor.find(".choix li:not(#tempalte)")
  700.                     choix.each(function () {
  701.                         let v =$(this).find("input:eq(0)").val()
  702.                         let d =$(this).find("input:eq(1)").val()
  703.                         $(input).append("<option value='"+v+"'>"+d+"</option>")
  704.                     })
  705.                     break;
  706.             }
  707.             if(exnom!==nom){
  708.                 $(".off #conditions .conds").each(function () {
  709.                     let val  = $(this).text()
  710.                     if(val.includes("%%"+exnom+"%%"))
  711.                         $(this).text( $(this).text().replace("%%"+exnom+"%%", "%%"+nom+"%%"))
  712.                 })
  713.             }
  714.             $(input).attr("name", nom)
  715.             $(input).attr("id", nom)
  716.             div.append(input)
  717.             editor.slideUp("normal", ()=>{
  718.                 editor.remove()
  719.             })
  720.         }
  721.         function validTableEditor(e) {
  722.             let editor =  $(e.target).parents(".editor")
  723.             let id = editor.attr("id").replace("new-table-editor", "")
  724.             let couleur = editor.find("#couleur").val()
  725.             let border = editor.find("#border").val()==="Oui"
  726.             let striped = editor.find("#striped").val()==="Oui"
  727.             let div = $(".has-table-editor[cid='"+id+"']")
  728.             div.removeClass("table-primary table-secondary table-success table-info table-warning table-danger table-light table-dark")
  729.             if(couleur!=="")
  730.                 div.addClass("table-"+couleur)
  731.             div.toggleClass( "table-bordered",border)
  732.             div.toggleClass( "table-striped",striped)
  733.             let preview = editor.find("#table-view")
  734.             div.html(preview.html())
  735.             div.find(".updatable").css({
  736.                 position: "",
  737.                 left: "",
  738.                 top: "",
  739.             })
  740.             editor.slideUp("normal", ()=>{
  741.                 editor.remove()
  742.             })
  743.         }
  744.         function validButtonEditor(e) {
  745.             let editor =  $(e.target).parents(".editor")
  746.             let id = editor.attr("id").replace("new-button-editor", "")
  747.             let couleur = editor.find("#couleur").val()
  748.             let type = editor.find("#type").val()
  749.             let size = editor.find("#size").val()
  750.             let action = editor.find("#action").val()
  751.             let div = $(".has-button-editor[cid='"+id+"']")
  752.             let button = $(div.find("button"))
  753.             button.removeClass()
  754.             button.addClass("btn")
  755.             button.addClass(size)
  756.             button.addClass("btn-"+couleur)
  757.             button.attr("type",type)
  758.             button.attr("action",action)
  759.             let html =editor.find(".ql-editor").html()
  760.             button.html(html)
  761.             div.find(".updatable").css({
  762.                 position: "",
  763.                 left: "",
  764.                 top: "",
  765.             })
  766.             editor.slideUp("normal", ()=>{
  767.                 editor.remove()
  768.             })
  769.         }
  770.         function validDivEditor(e) {
  771.             let editor =  $(e.target).parents(".editor")
  772.             let id = editor.attr("id").replace("new-div-editor", "")
  773.             let couleur = editor.find("#couleur").val()
  774.             let div = $(".has-div-editor[cid='"+id+"']")
  775.             div.removeClass("alert-primary alert-secondary alert-success alert-info alert-warning alert-danger alert-light alert-dark")
  776.             if(couleur!=="")
  777.                 div.addClass("alert-"+couleur)
  778.             let preview = editor.find("#div-view")
  779.             div.html(preview.html())
  780.             div.find(".updatable").css({
  781.                 position: "",
  782.                 left: "",
  783.                 top: "",
  784.             })
  785.             editor.slideUp("normal", ()=>{
  786.                 editor.remove()
  787.             })
  788.         }
  789.         function validConditionEditor(e) {
  790.             let editor =  $(e.target).parents(".editor")
  791.             let id = editor.attr("id").replace("new-conditions-editor", "")
  792.             let conditions = $(".off #conditions")
  793.             let div = $(conditions.find("#"+id)[0]?? "<div id='"+id+"'></div>")
  794.             div.html("")
  795.             editor.find("table tbody tr:visible").each(function () {
  796.                 let vals =[]
  797.                 $(this).find("select, input, textarea").each(function () {
  798.                     vals.push($(this).val())
  799.                 })
  800.                 div.append("<div class='conds'>"+vals.join("%%")+"</div")
  801.             })
  802.             div.appendTo(conditions)
  803.             editor.slideUp("normal", ()=>{
  804.                 editor.remove()
  805.             })
  806.         }
  807.         function validOptionsEditor(e) {
  808.             let editor =  $(e.target).parents(".editor")
  809.             let id = editor.attr("id").replace("new-options-editor", "")
  810.             let options = $(".off #options")
  811.             let div = $(options.find("#"+id)[0]?? "<div id='"+id+"'></div>")
  812.             div.html("")
  813.             let vals=[];
  814.             editor.find("select, input, textarea").each(function () {
  815.                 vals.push($(this).val())
  816.             })
  817.             div.append("<div class='options'>"+vals.join("%%")+"</div")
  818.             div.appendTo(options)
  819.             editor.slideUp("normal", ()=>{
  820.                 editor.remove()
  821.             })
  822.         }
  823.         //Parametres
  824.         function addToParams(entity) {
  825.             let params = $("#parametres-fields-list")
  826.             let inputs = params.find("input")
  827.             let [vals , input ]=getEmptyInputs(inputs)
  828.             if (!vals.includes(entity)) {
  829.                 if (input === null) {
  830.                     $("#addParam").click()
  831.                     inputs = params.find("input")
  832.                     input = getEmptyInputs(inputs)[1]
  833.                 }
  834.                 input.val(entity)
  835.             }
  836.         }
  837.         function getEmptyInputs(inputs ) {
  838.             let vals =[]
  839.             let input = null
  840.             $(inputs).each(function () {
  841.                 let val = $(this).val()
  842.                 if (val === "") {
  843.                     input = $(this)
  844.                 }
  845.                 vals.push(val)
  846.             })
  847.             return [ vals, input]
  848.         }
  849.         function addToTemplate(entity, field) {
  850.             let value="<{"+entity.toLowerCase()+"."+field+"}>"
  851.             let update=$(".template-view .updating")
  852.             if(update.length===1){
  853.                 addToParams(entity.toLowerCase())
  854.                 addToElement(value, update)
  855.             }
  856.             $("#offcanvasEntities .offcanvas-header .btn-close").click()
  857.         }
  858.         //Add Elements
  859.         function addInput(bool=false){
  860.             let input = "<div class='form-group updatable has-input-editor'><label>Label</label><input readonly class='form-control'></div>"
  861.             addElement(input, bool)
  862.         }
  863.         function addText(bool=false) {
  864.             let txt= "<div class='has-text-editor'><p>Texte</p></div>"
  865.             addElement(txt, bool)
  866.         }
  867.         function addBr(bool=false) {
  868.             let txt= "<div class='br updatable'><br></div>"
  869.             addElement(txt, false)
  870.         }
  871.         function addTable(bool=false) {
  872.             let table= "<table class='updatable table has-table-editor'><tr><td>Case 1</td><td>Case 2</td></tr></table>"
  873.             addElement(table, bool)
  874.         }
  875.         function addDiv(bool=false) {
  876.             let div = '<div class="row alert updatable has-div-editor"><div class="col">col</div><div class="col">col</div>'
  877.             addElement(div, bool)
  878.         }
  879.         function addTitre(h=1, bool=false) {
  880.             let txt= "<div class='has-title-editor'><h"+h+">Texte</h"+h+"></div"
  881.             addElement(txt, bool)
  882.         }
  883.         function addButton( bool=false) {
  884.             let txt= "<div class='has-button-editor'><button>Texte</button></div>"
  885.             addElement(txt, bool)
  886.         }
  887.         function addElement(el, local=false, addId=true) {
  888.             let view = local?$(curContainer):$(".template-view")
  889.             el = $(el).addClass("updatable")
  890.             if (addId)
  891.                 el.attr("cid", Date.now())
  892.             view.append(el)
  893.             resetDrag($(el))
  894.         }
  895.         function addToElement(value, to) {
  896.             let txt = $(to).text()
  897.             $(to).text(txt+(txt===""?"":" ")+value)
  898.         }
  899.         //Elements options
  900.         function editElement(e) {
  901.             let target = $(e.target)
  902.             target = target.hasClass("updatable")?target:target.parents('.updatable')
  903.             let bool = !target.hasClass("updating")
  904.             $(".template-view *").removeClass("updating")
  905.             target.toggleClass("updating",bool )
  906.         }
  907.         function updateTablePreview(e) {
  908.             let editor =$(e.target).hasClass("editor")? $(e.target):$(e.target).parents(".editor")
  909.             let preview = editor.find("#table-view")
  910.             let rows = editor.find("#rows").val()
  911.             let cols = editor.find("#cols").val()
  912.             let border = editor.find("#border").val()==="Oui"
  913.             let striped = editor.find("#striped").val()==="Oui"
  914.             let couleur = editor.find("#couleur").val()
  915.             preview.removeClass("table-primary table-secondary table-success table-info table-warning table-danger table-light table-dark")
  916.             if(couleur!=="")
  917.                 preview.addClass("table-"+couleur)
  918.             preview.toggleClass( "table-bordered",border)
  919.             preview.toggleClass( "table-striped",striped)
  920.             let resRows= rows-preview.find("tr").length
  921.             if(resRows<0){
  922.                 for (let i = resRows; i <0 ; i++) {
  923.                     preview.find("tr:last").remove()
  924.                 }
  925.             }
  926.             else if (resRows>0) {
  927.                 preview.append("<tr></tr>".repeat(resRows))
  928.             }
  929.             let resCols= cols-preview.find("tr:first td").length
  930.             if(resCols<0){
  931.                 for (let i = resCols; i <0 ; i++) {
  932.                     preview.find("tr").find("td:last").remove()
  933.                 }
  934.             }
  935.             preview.find("tr").each(function () {
  936.                     if(cols > $(this).find("td").length)
  937.                         $(this).append("<td>Case</td>".repeat(cols - $(this).find("td").length))
  938.             })
  939.             preview.find("td").droppable({
  940.                 accept:".updatable",
  941.                 tolerance: "pointer",
  942.                 classes: {
  943.                     "ui-droppable-hover": "ui-state-highlight"
  944.                 },
  945.                 over:function (event, ui) {
  946.                 },
  947.                 drop: function( event, ui ) {
  948.                     dropped = $(this);
  949.                     let id =editor.attr("id")
  950.                     let matches = id.match(/(\d+)/);
  951.                     if($(ui.draggable).attr("cid")===matches[0]??""){
  952.                         $(ui.draggable).appendTo(".template-view")
  953.                     }
  954.                     else {
  955.                         $(ui.draggable).appendTo($(this))
  956.                     }
  957.                     $(ui.draggable).css({
  958.                         position: "",
  959.                         left: "0",
  960.                         top: "0",
  961.                         "z-index": 1,
  962.                     })
  963.                 }
  964.             })
  965.             preview.on("dblclick", ".updatable",openGoodEditor);
  966.             preview.on("contextmenu", "tbody>tr>td",openContextAddMenu);
  967.             preview.on("contextmenu", ".updatable",openContextMenu);
  968.         }
  969.         function updateDivPreview(e) {
  970.             let editor =$(e.target).hasClass("editor")? $(e.target):$(e.target).parents(".editor")
  971.             let preview = editor.find("#div-view")
  972.             let cols = editor.find("#cols").val()
  973.             let couleur = editor.find("#couleur").val()
  974.             preview.removeClass("alert-primary alert-secondary alert-success alert-info alert-warning alert-danger alert-light alert-dark")
  975.             if(couleur!=="")
  976.                 preview.addClass("alert-"+couleur)
  977.             let resCols= cols-preview.find(".col").length
  978.             if(resCols<0){
  979.                 for (let i = resCols; i <0 ; i++) {
  980.                     preview.find(".col:last").remove()
  981.                 }
  982.             }
  983.             else if(resCols>0){
  984.                 preview.append("<div class='col'>Col</div>".repeat(resCols))
  985.             }
  986.             preview.find("div.col").droppable({
  987.                 accept:".updatable",
  988.                 tolerance: "pointer",
  989.                 greedy: true,
  990.                 classes: {
  991.                     "ui-droppable-hover": "ui-state-highlight"
  992.                 },
  993.                 over:function (event, ui) {
  994.                 },
  995.                 drop: function( event, ui ) {
  996.                     dropped = $(this);
  997.                     let id =editor.attr("id")
  998.                     let matches = id.match(/(\d+)/);
  999.                     if($(ui.draggable).attr("cid")===matches[0]??""){
  1000.                         $(ui.draggable).appendTo(".template-view")
  1001.                     }
  1002.                     else {
  1003.                         let res = $(ui.draggable).appendTo($(this))
  1004.                     }
  1005.                     $(ui.draggable).css({
  1006.                         position: "",
  1007.                         left: "0",
  1008.                         top: "0",
  1009.                         "z-index": 1,
  1010.                     })
  1011.                 }
  1012.             })
  1013.             preview.on("dblclick", ".updatable",openGoodEditor);
  1014.             preview.on("contextmenu", "div.col",openContextAddMenu);
  1015.             preview.on("contextmenu", ".updatable",openContextMenu);
  1016.         }
  1017.         function resetDrag(el) {
  1018.             el.draggable({
  1019.                 revert: "invalid",
  1020.                 connectToSortable: ".template-view",
  1021.                 cursorAt: { top: -5, left: -5 },
  1022.                 iframeFix: true,
  1023.                 stop: function() {
  1024.                    $(this).css({
  1025.                        position: "relative",
  1026.                        width:"",
  1027.                        height:""
  1028.                    })
  1029.                 }
  1030.             });
  1031.         }
  1032.         function setSortable(template) {
  1033.             template.sortable({
  1034.                 placeholder: "ui-state-highlight",
  1035.                 cursor: "move",
  1036.                 stop: function(event, ui) {
  1037.                     if (dropped!==false) {
  1038.                         $(this).sortable("cancel");
  1039.                         ui.item.appendTo($(dropped));
  1040.                         dropped = false;
  1041.                     }
  1042.                 },
  1043.                 /*stop: function(event, ui) {
  1044.                     console.log("stop", event)
  1045.                     if (ui.item.hasClass("has-text-editor"))
  1046.                         $(this).sortable("cancel");
  1047.                     $(this).sortable("enable");
  1048.                 },*/
  1049.                 receive: function(event, ui) {
  1050.                     console.log("receive")
  1051.                 }
  1052.             })
  1053.         }
  1054.         //Context Menu
  1055.         function openContextMenu(event) {
  1056.             event.preventDefault();
  1057.             event.stopPropagation();
  1058.             curElement=event.currentTarget
  1059.             contextMenu(event)
  1060.         }
  1061.         function openContextAddMenu(event) {
  1062.             event.preventDefault();
  1063.             event.stopPropagation();
  1064.             curContainer=event.currentTarget
  1065.             contextMenu(event, "custom-context-add-menu")
  1066.         }
  1067.         //Context Menu Action
  1068.         function supprimer() {
  1069.             if(curElement!=null){
  1070.                 let supp = $(curElement)
  1071.                 let clss = supp.getClassStartingWith("has-")??""
  1072.                 let cid = supp.attr("cid")
  1073.                 let name = clss.replace("has-", "new-")+cid
  1074.                 let editor = $("#"+name)
  1075.                 $(".off #conditions #"+cid).remove()
  1076.                 $(".off #options #"+cid).remove()
  1077.                 editor.fadeOut("normal", ()=>editor.remove())
  1078.                 supp.slideUp("normal", ()=>supp.remove())
  1079.             }
  1080.             curElement=null
  1081.         }
  1082.         function dupliquer() {
  1083.             if(curElement!=null){
  1084.                 let el = $(curElement)
  1085.                 let clone = $(el.clone())
  1086.                 let curCid = el.attr("cid")
  1087.                 resetDrag(clone)
  1088.                 clone.insertBefore(el)
  1089.                 let cid =Date.now()
  1090.                 el.attr("cid", cid)
  1091.                 let curConditions =$(".off #conditions #"+curCid)
  1092.                 let cloneConditions =curConditions.clone()
  1093.                 cloneConditions.attr("id", cid)
  1094.                 $(".off #conditions").append(cloneConditions)
  1095.                 let curOptions =$(".off #options #"+curCid)
  1096.                 let cloneOptions =curOptions.clone()
  1097.                 cloneOptions.attr("id", cid)
  1098.                 $(".off #options").append(cloneOptions)
  1099.             }
  1100.             curElement=null
  1101.         }
  1102.         function conditions(e) {
  1103.             if(curElement!=null){
  1104.                 openConditionsEditor({
  1105.                     target:curElement,
  1106.                     pageX:(window).event.pageX,
  1107.                     pageY:(window).event.pageY,
  1108.                 })
  1109.             }
  1110.             curElement=null
  1111.         }
  1112.         function options(e) {
  1113.             if(curElement!=null){
  1114.                 openOptionsEditor({
  1115.                     target:curElement,
  1116.                     pageX:(window).event.pageX,
  1117.                     pageY:(window).event.pageY,
  1118.                 })
  1119.             }
  1120.             curElement=null
  1121.         }
  1122.         //Save
  1123.         function saveTemplate(e) {
  1124.             e.preventDefault()
  1125.             let html =$(".template-view").html()
  1126.             let conditions = $(".off #conditions ").html()
  1127.             let options = $(".off #options ").html()
  1128.             let res = {}
  1129.             res["html"]=html
  1130.             res["conditions"]=conditions
  1131.             res["options"]=options
  1132.             res["conditions_array"]={}
  1133.             $(".off #conditions>div").each(function(){
  1134.                 let id = $(this).attr("id")
  1135.                 res["conditions_array"][id]=[]
  1136.                 $(this).find(".conds").each(function(){
  1137.                     res["conditions_array"][id].push($(this).html())
  1138.                 })
  1139.             })
  1140.             $("#template_data").val(JSON.stringify(res))
  1141.             $.ajax({
  1142.                 url:"{{ path('app_template_save') }}",
  1143.                 data:$("#form-template").serializeArray(),
  1144.                 method:"POST",
  1145.                 success:function () {
  1146.                     notify("Template", "La Template <i>"+$("#template_titre").val()+"</i> a été enregistré")
  1147.                 }
  1148.             })
  1149.             return false
  1150.         }
  1151.         $(document).ready(function() {
  1152.             addMenu( "custom-context-menu", {
  1153.                 "Supprimer":"supprimer()",
  1154.                 "Dupliquer":"dupliquer()",
  1155.                 "Options":"options(this)",
  1156.                 "Conditions":"conditions(this)",
  1157.                 "Option b":"",
  1158.             },".off")
  1159.             addMenu( "custom-context-add-menu", {
  1160.                 "Titre":"addTitre(1,true)",
  1161.                 "Texte":"addText(true)",
  1162.                 "Input":"addInput(true)",
  1163.                 "Bouton":"addButton(true)",
  1164.                 "Option a":"alert('OK')",
  1165.                 "Option b":"",
  1166.             },".off")
  1167.             let template = $(".template-view")
  1168.             template.on("contextmenu", ">.updatable",openContextMenu);
  1169.             template.on("click", ">.updatable",editElement)
  1170.             template.on("dblclick", ">.updatable",openGoodEditor);
  1171.             setSortable(template)
  1172.             let data = $("#template_data").val()
  1173.             let res = data!==""?JSON.parse(data):[]
  1174.             if(res["html"])
  1175.                 template.html(res["html"])
  1176.             if(res["conditions"])
  1177.                 $(".off #conditions").html(res["conditions"])
  1178.             if(res["options"])
  1179.                 $(".off #options").html(res["options"])
  1180.             resetDrag(template.find(".updatable"))
  1181.             $("#form-template").submit(saveTemplate)
  1182.             $("#preview").off("keydown onkeydown")
  1183.             $(".off #editors").on("input","#champs" , function () {
  1184.                 let val = $(this).val()
  1185.                 $(this).next("input").toggle( val === "entity")
  1186.             })
  1187.             $('[data-bs-toggle="tooltip"]').tooltip()
  1188.         });
  1189.     </script>
  1190.     <script src="//cdn.quilljs.com/1.3.6/quill.min.js"></script>
  1191. {% endblock %}
  1192. {% block stylesheets %}
  1193.     <link href="//cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
  1194.     <style>
  1195.         .off #conditions, .off #options{
  1196.             display: none;
  1197.         }
  1198.         .off .editor{
  1199.             width: 40rem;
  1200.         }
  1201.         .updatable .updatable, .updatable .updatable:hover{
  1202.             border: 1px dashed black;
  1203.             cursor: pointer;
  1204.             background-color: white;
  1205.         }
  1206.         .updatable{
  1207.             border: 1px dashed rgba(128, 128, 128, 0.7);
  1208.             cursor: pointer;
  1209.             background-color: white;
  1210.             margin: 0;
  1211.         }
  1212.         .updatable:hover{
  1213.             border: 2px dashed blue;
  1214.         }
  1215.         .updating, .updating:hover{
  1216.             border: 1px solid red ;
  1217.         }
  1218.         .template-view{
  1219.             width: 100%;
  1220.             display:  inline-block;
  1221.             min-height: 20rem ;
  1222.             border: 1px solid gray;
  1223.         }
  1224.         .template-view input, .template-view textarea, .template-view select{
  1225.             cursor: pointer;
  1226.         }
  1227.         #parametres-fields-list>*{
  1228.             margin: 2px;
  1229.         }
  1230.         .type-options .option{
  1231.             display: none;
  1232.         }
  1233.         #table-view .updatable:not(.ui-draggable-dragging){
  1234.             position: initial !important;
  1235.             z-index: 1;
  1236.         }
  1237.         .template-view .updatable:not(.ui-draggable-dragging){
  1238.             z-index: 1 !important;
  1239.         }
  1240.         .updatable.ui-draggable-dragging{
  1241.             z-index: 3 !important;
  1242.             max-width:10rem ;
  1243.             max-height: 10rem;
  1244.             overflow: hidden;
  1245.         }
  1246.         .dragging{
  1247.             background-color: red;
  1248.         }
  1249.     </style>
  1250. {% endblock %}