templates/front/form/claim.html.twig line 1

Open in your IDE?
  1. {% extends "front/_common/_base.html.twig" %}
  2. {% block linkcanonical %}
  3.     <link rel="canonical" href="{{ absolute_url(path('claim')) }}">
  4. {% endblock %}
  5. {% block cssadicional %}
  6. <style>
  7.     .b21Firma { margin: 15px 0; }
  8.     .b21Firma canvas { border: 1px solid #ccc; border-radius: 4px; display: block; background: #fff; max-width: 100%; }
  9.     .b21Firma .btnLimpiar { margin-top: 5px; padding: 5px 15px; cursor: pointer; background-color: #6a6867; color: #fff; border: 0; height: 45px; width: 150px; }
  10.     .b21WrapMenorEdad .b21WrapInput { display: none; }
  11.     .b22Libro .b21WrapColCorrelative { height: 54px; }
  12.     .icon-iconos-10{
  13.         position: absolute;
  14.         right: 15px;
  15.         top: 20px;
  16.     }
  17.     .textlb{
  18.         margin:20px 0px;
  19.     }
  20.     .textlb p{
  21.         text-align: start;
  22.     }
  23. </style>
  24. {% endblock %}
  25. {% block classbody %}{% endblock %}
  26. {% block content %}
  27.     <div class="wanchoSecondary b22Libro">
  28.         <ul class="b21MigaCustom b10LeftMigaPan">
  29.             <li><a href="{{ path('home') }}">Home</a></li>&nbsp;/ &nbsp;
  30.             <li class="active"><a href="{{ path('claim') }}">Libro de reclamo</a></li>
  31.         </ul>
  32.         {{ form_start(form, {'attr': {'enctype': 'multipart/form-data'}}) }}
  33.             {% include 'front/templates/form_utm_fields.html.twig' %}
  34.             {{ form_widget(form.establishment) }}
  35.             {{ form_widget(form.good) }}
  36.             {{ form_widget(form.type) }}
  37.             {{ form_widget(form.authorization) }}
  38.             {% if forms.claimTitle %}
  39.                 <h4 class="titleStandard b22LibroTitle">{{ forms.claimTitle }}</h4>
  40.             {% endif %}
  41.             {% if forms.claimCompanyName or forms.claimCompanyRuc or forms.claimCompanyAddress %}
  42.                 <div class="b21WrapText " >
  43.                     {% if forms.claimCompanyName %}<p><strong>{{ forms.claimCompanyName }}</strong></p>{% endif %}
  44.                     {% if forms.claimCompanyRuc %}<p>RUC: {{ forms.claimCompanyRuc }}</p>{% endif %}
  45.                     {% if forms.claimCompanyAddress %}<p>Dirección: {{ forms.claimCompanyAddress|nl2br }}</p>{% endif %}
  46.                 </div>
  47.             {% endif %}
  48.             {% if forms.claimText %}
  49.                 <div class="b21WrapText">{{ forms.claimText|nl2br }}</div>
  50.             {% endif %}
  51.             {% if forms.claimEstablishmentTitle or forms.claimEstablishmentRuc or forms.claimEstablishmentRazonSocial or forms.claimEstablishmentDireccion %}
  52.                 <div class="b21WrapText textlb" >
  53.                     {% if forms.claimEstablishmentTitle %}<p><strong>{{ forms.claimEstablishmentTitle }}</strong></p>{% endif %}
  54.                     {% if forms.claimEstablishmentRuc %}<p>RUC: {{ forms.claimEstablishmentRuc }}</p>{% endif %}
  55.                     {% if forms.claimEstablishmentRazonSocial %}<p>Razón Social: {{ forms.claimEstablishmentRazonSocial }}</p>{% endif %}
  56.                     {% if forms.claimEstablishmentDireccion %}<p>Dirección: {{ forms.claimEstablishmentDireccion|nl2br }}</p>{% endif %}
  57.                 </div>
  58.             {% endif %}
  59.             <div class="b21WrapInput b21WrapInputDato">
  60.                 <div class="b21WrapCol">
  61.                     <div class="b21WrapColDate">
  62.                         <span>Fecha:</span>
  63.                         <span>{{ "now"|date('d/m/Y') }}</span>
  64.                     </div>
  65.                 </div>
  66.                 <div class="b21WrapCol b21WrapColCorrelative">
  67.                     <span>Nº {{ entity.code }}</span>
  68.                 </div>
  69.             </div>
  70.             <!-- {% if forms.claimEstablishmentsText %}
  71.                 <div class="b21WrapTextP">{{ forms.claimEstablishmentsText|nl2br }}</div>
  72.             {% endif %} -->
  73.             <!-- <div class="b21WrapInput">
  74.                 <div class="b21Select">
  75.                     <select class="form-contact-select" id="form-establecimiento">
  76.                         <option value="" disabled selected></option>
  77.                         {% for item in forms.claimEstablishmentsItems %}
  78.                             <option data-ruc="{{ item.ruc }}" value="{{ item.title }}">{{ item.title }}</option>
  79.                         {% endfor %}
  80.                     </select>
  81.                     <span class="form-label">Establecimiento</span>
  82.                     <i class="icon-iconos-10"></i>
  83.                 </div>
  84.                 <div class="b21Input b21InputNoLabel">
  85.                     <input class="form-contact" type="text" value="" id="form-ruc" readonly>
  86.                 </div>
  87.             </div> -->
  88.             <!-- {% if forms.claimEstablishmentsNote %}
  89.                 <div class="b21WrapTextP">{{ forms.claimEstablishmentsNote|nl2br }}</div>
  90.             {% endif %} -->
  91.             <div class="b21WrapRow">
  92.                 {% if forms.claimP1Title %}
  93.                     <h4 class="titleStandard">1. {{ forms.claimP1Title }}</h4>
  94.                 {% endif %}
  95.                 <div class="">
  96.                     <div class="b21Input">
  97.                         {{ form_widget(form.name, {'attr': {'data-expresion': 'text', 'class': 'validKeypress g-text form-contact validate[custom[onlyLetterSp]]'}}) }}
  98.                         <span class="form-label">Nombres</span>
  99.                     </div>
  100.                 </div>
  101.                 <div class="b21WrapInput">
  102.                     <div class="b21Input">
  103.                         {{ form_widget(form.lastname, {'attr': {'data-expresion': 'text', 'class': 'validKeypress g-text form-contact validate[custom[onlyLetterSp]]'}}) }}
  104.                         <span class="form-label">Apellido Paterno</span>
  105.                     </div>
  106.                     <div class="b21Input">
  107.                         {{ form_widget(form.apellido_materno, {'attr': {'data-expresion': 'text', 'class': 'validKeypress g-text form-contact validate[custom[onlyLetterSp]]'}}) }}
  108.                         <span class="form-label">Apellido Materno</span>
  109.                     </div>
  110.                 </div>
  111.                 <div class="b21WrapInput">
  112.                     <div class="b21Input">
  113.                         {{ form_widget(form.phone, {'attr': {'data-expresion': 'number', 'class': 'validKeypress g-number form-contact validate[custom[onlyNumberSp]]'}}) }}
  114.                         <span class="form-label">Teléfono</span>
  115.                     </div>
  116.                     <div class="b21Input">
  117.                         {{ form_widget(form.email, {'attr': {'class': 'form-contact validate[custom[email]]'}}) }}
  118.                         <span class="form-label">Correo</span>
  119.                     </div>
  120.                 </div>
  121.                 <div class="b21WrapInput">
  122.                     <div class="b21Select">
  123.                         {{ form_widget(form.documentType, {'attr': {'class': 'form-contact-select validate'}}) }}
  124.                         <span class="form-label">Tipo de documento</span>
  125.                         <i class="icon-iconos-10"></i>
  126.                     </div>
  127.                     <div class="b21Input">
  128.                         {{ form_widget(form.documentNumber, {'attr': {'data-expresion': 'text', 'class': 'form-contact validate'}}) }}
  129.                         <span class="form-label">N° de documento</span>
  130.                     </div>
  131.                 </div>
  132.                 <div class="b21WrapInput">
  133.                     <div class="b21Input">
  134.                         {{ form_widget(form.department, {'attr': {'class': 'form-contact validate'}}) }}
  135.                         <span class="form-label">Ciudad</span>
  136.                     </div>
  137.                     <div class="b21Input">
  138.                         {{ form_widget(form.address, {'attr': {'class': 'form-contact validate'}}) }}
  139.                         <span class="form-label">Dirección</span>
  140.                     </div>
  141.                 </div>
  142.                 <div class="b21WrapMenorEdad">
  143.                     <div class="b21WrapCheckbox b21WrapCheckboxP">
  144.                         <input type="checkbox" id="chk_menor_edad" class="form-input checkbox checkMenor">
  145.                         <label for="chk_menor_edad">Menor de edad</label>
  146.                         {{ form_widget(form.younger, {'attr': {'id': 'form_claim_younger', 'class': 'hidden'}}) }}
  147.                     </div>
  148.                 </div>
  149.                 <div id="bloque-apoderado" style="display: none;">
  150.                     <div class="">
  151.                         <div class="b21Input">
  152.                             {{ form_widget(form.tutorName, {'attr': {'data-expresion': 'text', 'class': 'validKeypress g-text form-contact'}}) }}
  153.                             <span class="form-label">Nombres del tutor</span>
  154.                         </div>
  155.                     </div>
  156.                     <div class="b21WrapInput">
  157.                         <div class="b21Input">
  158.                             {{ form_widget(form.tutorLastName, {'attr': {'data-expresion': 'text', 'class': 'validKeypress g-text form-contact'}}) }}
  159.                             <span class="form-label">Apellido Paterno del tutor</span>
  160.                         </div>
  161.                         <div class="b21Input">
  162.                             {{ form_widget(form.tutorApellidoMaterno, {'attr': {'data-expresion': 'text', 'class': 'validKeypress g-text form-contact'}}) }}
  163.                             <span class="form-label">Apellido Materno del tutor</span>
  164.                         </div>
  165.                     </div>
  166.                     <div class="b21WrapInput">
  167.                         <div class="b21Input">
  168.                             {{ form_widget(form.tutorPhone, {'attr': {'data-expresion': 'number', 'class': 'validKeypress g-number form-contact'}}) }}
  169.                             <span class="form-label">Teléfono</span>
  170.                         </div>
  171.                         <div class="b21Input">
  172.                             {{ form_widget(form.tutorEmail, {'attr': {'class': 'form-contact'}}) }}
  173.                             <span class="form-label">E-mail</span>
  174.                         </div>
  175.                     </div>
  176.                     <div class="b21WrapInput">
  177.                         <div class="b21Select">
  178.                             {{ form_widget(form.tutorDocumentType, {'attr': {'class': 'form-contact-select'}}) }}
  179.                             <span class="form-label">Tipo de documento</span>
  180.                             <i class="icon-iconos-10"></i>
  181.                         </div>
  182.                         <div class="b21Input">
  183.                             {{ form_widget(form.tutorDocumentNumber, {'attr': {'class': 'form-contact'}}) }}
  184.                             <span class="form-label">N° de documento</span>
  185.                         </div>
  186.                     </div>
  187.                 </div>
  188.             </div>
  189.             <div class="b21WrapRow">
  190.                 {% if forms.claimP2Title %}
  191.                     <h4 class="titleStandard">2. {{ forms.claimP2Title }}</h4>
  192.                 {% endif %}
  193.                 <div class="b21WrapRadio">
  194.                     {% for item in forms.claimGoods %}
  195.                         <div class="b21WrapRadioCol">
  196.                             <input type="radio" class="form_good" id="radio-good_{{ loop.index }}" name="tipo_reclamo" value="{{ item.title }}" />
  197.                             <label for="radio-good_{{ loop.index }}">{{ item.title }}</label>
  198.                         </div>
  199.                     {% endfor %}
  200.                 </div>
  201.                 <div class="b21WrapInput">
  202.                     <div class="b21Select">
  203.                         <select class="form-contact-select" id="form_claim_currency">
  204.                             <option value="" disabled selected></option>
  205.                             {% set monedas = forms.claimCurrencies is not empty ? forms.claimCurrencies : [{name: "Soles"}, {name: "Dolares"}] %}
  206.                             {% for currency in monedas %}
  207.                                 <option value="{{ currency.name }}">{{ currency.name }}</option>
  208.                             {% endfor %}
  209.                         </select>
  210.                         <span class="form-label">Moneda</span>
  211.                         <i class="icon-iconos-10"></i>
  212.                     </div>
  213.                     {{ form_widget(form.currency) }}
  214.                     <div class="b21Input">
  215.                         {{ form_widget(form.amount, {'attr': {'class': 'form-contact', 'onkeypress': 'return event.charCode >= 48 && event.charCode <= 57 || event.charCode == 46'}}) }}
  216.                         <span class="form-label">Valor del Producto/servicio</span>
  217.                     </div>
  218.                 </div>
  219.                 <div class="b21Textarea">
  220.                     {{ form_widget(form.description, {'attr': {'cols': '40', 'rows': '10', 'class': 'form-contact'}}) }}
  221.                     <span class="form-label">Descripción</span>
  222.                 </div>
  223.             </div>
  224.             <div class="b21WrapRow">
  225.                 {% if forms.claimP3Title %}
  226.                     <h4 class="titleStandard">3. {{ forms.claimP3Title }}</h4>
  227.                 {% endif %}
  228.                 <div class="b21WrapRadio">
  229.                     {% for item in forms.claimTypes %}
  230.                         <div class="b21WrapRadioCol">
  231.                             <input type="radio" class="form_type" id="radio-type_{{ loop.index }}" name="tipo_consumidor" value="{{ item.title }}" />
  232.                             <label for="radio-type_{{ loop.index }}">{{ item.title }}</label>
  233.                             <!-- <span>*</span> -->
  234.                         </div>
  235.                     {% endfor %}
  236.                 </div>
  237.                 <div class="b21WrapTextP">
  238.                     {% for item in forms.claimTypes %}
  239.                         <p>*{{ item.title }}: {{ item.description|nl2br }}</p>
  240.                     {% endfor %}
  241.                 </div>
  242.                 <div class="b21Textarea">
  243.                     {{ form_widget(form.detail, {'attr': {'cols': '40', 'rows': '10', 'class': 'form-contact validate'}}) }}
  244.                     <span class="form-label">Detalle</span>
  245.                 </div>
  246.                 <div class="b21Textarea">
  247.                     {{ form_widget(form.demand, {'attr': {'cols': '40', 'rows': '10', 'class': 'form-contact validate'}}) }}
  248.                     <span class="form-label">Pedido</span>
  249.                 </div>
  250.                 <div class="b21Firma">
  251.                     <label class="form-label">Firma</label>
  252.                     <canvas id="firmaCanvas" width="400" height="150"></canvas>
  253.                     <button type="button" class="btnLimpiar" id="limpiarFirma">Limpiar</button>
  254.                     <input type="hidden" id="firmaData" name="form[firma]" value="">
  255.                 </div>
  256.                 <div class="b21File">
  257.                     <div class="b21FileBox">
  258.                         <i class="icon-copy"></i>
  259.                         <span class="b21FileText">Adjuntar archivo</span>
  260.                         <label for="archivo_libro" class="b21FileTextFormat">Adjuntar archivo (PDF, PPTX, WORD o imágenes JPG, PNG)</label>
  261.                         <input size="40" id="archivo_libro" accept=".pdf,.pptx,.word,.jpg,.png" type="file" name="form_file">
  262.                     </div>
  263.                 </div>
  264.             </div>
  265.             <div class="b21WrapRow">
  266.                 {% if forms.claimP4Title %}
  267.                     <h4 class="titleStandard">4. {{ forms.claimP4Title }}</h4>
  268.                 {% endif %}
  269.                 <div class="b21Textarea">
  270.                     <textarea readonly></textarea>
  271.                 </div>
  272.                 <div class="b21WrapTextP">
  273.                     {% set f = entity.answerDate %}
  274.                     {% set answer_date = f|day ~ ', ' ~ f|date('d') ~ ' de ' ~ f|month|capitalize ~ ' del ' ~ f|date('Y') %}
  275.                     {{ forms.claimDescription|replace({'%fecha_respuesta%': answer_date})|raw }}
  276.                 </div>
  277.             </div>
  278.             <div class="b21WrapRow">
  279. {#                 {% if forms.claimP5Title %}
  280.                     <h4 class="titleStandard">5. {{ forms.claimP5Title }}</h4>
  281.                 {% endif %}
  282.                 <div class="b21WrapRadio">
  283.                     <div class="b21WrapRadioCol">
  284.                         <input type="radio" class="form_authorization" id="radio_authorization_yes" name="authorization_option" value="Sí" />
  285.                         <label for="radio_authorization_yes">Sí</label>
  286.                         <span>*</span>
  287.                     </div>
  288.                     <div class="b21WrapRadioCol">
  289.                         <input type="radio" class="form_authorization" id="radio_authorization_no" name="authorization_option" value="No" />
  290.                         <label for="radio_authorization_no">No</label>
  291.                         <span>*</span>
  292.                     </div>
  293.                 </div> #}
  294.                 <!-- <div class="b21Paragraph">
  295.                     (*) Campos obligatorios.
  296.                 </div> -->
  297.                 {% if forms.claimNotes|length > 0 %}
  298.                     <div class="b21WrapTextP">
  299.                         {% for item in forms.claimNotes %}
  300.                             <p>* {{ item.text|nl2br }}</p>
  301.                         {% endfor %}
  302.                     </div>
  303.                 {% endif %}
  304.             </div>
  305.             <div class="b21WrapCheckbox">
  306.                 <input type="checkbox" id="b21Checkbox" name="">
  307.                 <label for="b21Checkbox">He leído y acepto los <b><a href="{{ path('terms_and_conditions') }}" target="_blank">Términos y condiciones</a></b> y <b><a href="{{ path('privacy_policies') }}" target="_blank">Políticas de Privacidad</a></b> de UD Trucks</label>
  308.             </div>
  309.             <button class="buttonStandard gray b21Btn" id="BtnLibro">Enviar</button>
  310.             {% if info.showCaptcha %}
  311.                 <input type="hidden" name="recaptcha_token" id="recaptchaToken">
  312.             {% endif %}
  313.         {{ form_end(form) }}
  314.     </div>
  315. {% endblock %}
  316. {% block jsfinal %}
  317.     {% if info.showCaptcha %}
  318.         <script src="https://www.google.com/recaptcha/api.js?render={{ info.captchaSite }}"></script>
  319.         <script>
  320.             grecaptcha.ready(function() {
  321.                 grecaptcha.execute('{{ info.captchaSite }}', {action: 'submit'}).then(function(token) {
  322.                     document.getElementById('recaptchaToken').value = token;
  323.                 });
  324.             });
  325.         </script>
  326.     {% endif %}
  327.     <script type="text/javascript">
  328.         jQuery(function ($) {
  329.             $("form").validationEngine('attach', {
  330.                 promptPosition: "topLeft",
  331.                 autoHidePrompt: true,
  332.                 autoPositionUpdate: false,
  333.                 autoHideDelay: 2000,
  334.                 binded: false,
  335.                 scroll: false,
  336.                 validateNonVisibleFields: true
  337.             })
  338.             $('#form-establecimiento').on('change', function () {
  339.                 const value = $(this).val();
  340.                 const ruc = $(this).find('option:selected').data('ruc');
  341.                 const form_ruc = $('#form-ruc');
  342.                 $('#form_claim_establishment').val(value);
  343.                 form_ruc.val('');
  344.                 if (ruc) {
  345.                     form_ruc.val('RUC: ' + ruc);
  346.                 }
  347.             });
  348.             $('#BtnLibro').on('click', function (event) {
  349.                 event.preventDefault();
  350.                 const item = $(this);
  351.                 const form = item.closest('form');
  352.                 const firmaData = $('#firmaData').val();
  353.                 if (!firmaData) {
  354.                     alert('Por favor firme antes de enviar');
  355.                     return;
  356.                 }
  357.                 const valid = form.validationEngine('validate');
  358.                 if (valid) {
  359.                     item.prop('disabled', true).text('Enviando...');
  360.                     form.submit();
  361.                 } else {
  362.                     item.prop('disabled', false).text('Enviar');
  363.                 }
  364.             });
  365. //             $('.form_authorization').on('click', function () {
  366. //                 $('#form_claim_authorization').val($('.form_authorization:checked').val());
  367. //             })
  368.             $('.form_good').on('click', function () {
  369.                 $('#form_claim_good').val($('.form_good:checked').val());
  370.             })
  371.             $('.form_type').on('click', function () {
  372.                 $('#form_claim_type').val($('.form_type:checked').val());
  373.             })
  374.             $('#form_claim_currency').on('change', function () {
  375.                 const value = $(this).val();
  376.                 $('input[name="form_claim[currency]"]').val(value);
  377.             });
  378.             $('#chk_menor_edad').on('change', function () {
  379.                 if ($(this).is(':checked')) {
  380.                     $('#bloque-apoderado').show();
  381.                     $('#form_claim_younger').val('1');
  382.                 } else {
  383.                     $('#bloque-apoderado').hide();
  384.                     $('#form_claim_younger').val('0');
  385.                 }
  386.             });
  387.             const departmentField = $('#form_claim_department');
  388.             const provinceField = $('#form_claim_province');
  389.             const districtField = $('#form_claim_district');
  390.             const departmentSelect = $('#form_field_department');
  391.             const provinceSelect = $('#form_field_province');
  392.             const districtSelect = $('#form_field_district');
  393.             departmentSelect.on('change', function () {
  394.                 const department = $(this).find('option:selected').data('option');
  395.                 const value = $(this).val();
  396.                 departmentField.val(null);
  397.                 provinceField.val(null);
  398.                 districtField.val(null);
  399.                 if (department) {
  400.                     departmentField.val(value);
  401.                     loadProvinces();
  402.                 }
  403.             })
  404.             provinceSelect.on('change', function () {
  405.                 const province = $(this).find('option:selected').data('option');
  406.                 const value = $(this).val();
  407.                 provinceField.val(null);
  408.                 districtField.val(null);
  409.                 if (province) {
  410.                     provinceField.val(value);
  411.                     loadDistricts();
  412.                 }
  413.             })
  414.             districtSelect.on('change', function () {
  415.                 const district = $(this).find('option:selected').data('option');
  416.                 const value = $(this).val();
  417.                 districtField.val(null);
  418.                 if (district) {
  419.                     districtField.val(value);
  420.                 }
  421.             })
  422.             function loadProvinces() {
  423.                 const department = departmentSelect.find('option:selected').data('option');
  424.                 if (!department) {
  425.                     return false;
  426.                 }
  427.                 $.ajax({
  428.                     url: '{{ path('get_provinces_by_department') }}',
  429.                     type: 'post',
  430.                     data: {department: department},
  431.                     beforeSend: function () {
  432.                         departmentSelect.prop('disabled', true);
  433.                         provinceSelect.prop('disabled', true).html(createPlaceholder()).siblings('label').removeClass('fijar');
  434.                         districtSelect.prop('disabled', true).html(createPlaceholder()).siblings('label').removeClass('fijar');
  435.                         provinceField.val(null);
  436.                     },
  437.                     success: function (data) {
  438.                         provinceSelect.prop('disabled', false).html(createOptions(data));
  439.                     },
  440.                     complete: function () {
  441.                         departmentSelect.prop('disabled', false);
  442.                     }
  443.                 })
  444.             }
  445.             function loadDistricts() {
  446.                 const province = provinceSelect.find('option:selected').data('option');
  447.                 if (!province) {
  448.                     return false;
  449.                 }
  450.                 $.ajax({
  451.                     url: '{{ path('get_districts_by_province') }}',
  452.                     type: 'post',
  453.                     data: {province: province},
  454.                     beforeSend: function () {
  455.                         departmentSelect.prop('disabled', true);
  456.                         provinceSelect.prop('disabled', true);
  457.                         districtSelect.prop('disabled', true).html(createPlaceholder()).siblings('label').removeClass('fijar');
  458.                     },
  459.                     success: function (data) {
  460.                         districtSelect.prop('disabled', false).html(createOptions(data));
  461.                     },
  462.                     complete: function () {
  463.                         departmentSelect.prop('disabled', false);
  464.                         provinceSelect.prop('disabled', false);
  465.                     }
  466.                 })
  467.             }
  468.             function createPlaceholder() {
  469.                 return '<option value="" selected="selected"></option>';
  470.             }
  471.             function createOptions(data) {
  472.                 let options = createPlaceholder();
  473.                 $.each(data, function (i, v) {
  474.                     options += createOption(v);
  475.                 });
  476.                 return options
  477.             }
  478.             function createOption(item) {
  479.                 return '<option value="' + item['title'] + '" data-option="' + item['slug'] + '">' + item['title'] + '</option>';
  480.             }
  481.             var canvas = document.getElementById('firmaCanvas');
  482.             var ctx = canvas.getContext('2d');
  483.             var drawing = false;
  484.             var lastX = 0;
  485.             var lastY = 0;
  486.             function startPosition(e) {
  487.                 drawing = true;
  488.                 var pos = getPos(e);
  489.                 lastX = pos.x;
  490.                 lastY = pos.y;
  491.             }
  492.             function endPosition() {
  493.                 drawing = false;
  494.                 ctx.beginPath();
  495.                 document.getElementById('firmaData').value = canvas.toDataURL();
  496.             }
  497.             function getPos(e) {
  498.                 var rect = canvas.getBoundingClientRect();
  499.                 if (e.touches) {
  500.                     return {
  501.                         x: e.touches[0].clientX - rect.left,
  502.                         y: e.touches[0].clientY - rect.top
  503.                     };
  504.                 }
  505.                 return {
  506.                     x: e.clientX - rect.left,
  507.                     y: e.clientY - rect.top
  508.                 };
  509.             }
  510.             function draw(e) {
  511.                 if (!drawing) return;
  512.                 e.preventDefault();
  513.                 var pos = getPos(e);
  514.                 ctx.strokeStyle = '#000';
  515.                 ctx.lineWidth = 2;
  516.                 ctx.lineCap = 'round';
  517.                 ctx.beginPath();
  518.                 ctx.moveTo(lastX, lastY);
  519.                 ctx.lineTo(pos.x, pos.y);
  520.                 ctx.stroke();
  521.                 lastX = pos.x;
  522.                 lastY = pos.y;
  523.             }
  524.             canvas.addEventListener('mousedown', startPosition);
  525.             canvas.addEventListener('mouseup', endPosition);
  526.             canvas.addEventListener('mouseleave', function() {
  527.                 if (drawing) {
  528.                     drawing = false;
  529.                     ctx.beginPath();
  530.                     document.getElementById('firmaData').value = canvas.toDataURL();
  531.                 }
  532.             });
  533.             canvas.addEventListener('mousemove', draw);
  534.             canvas.addEventListener('touchstart', startPosition);
  535.             canvas.addEventListener('touchend', endPosition);
  536.             canvas.addEventListener('touchmove', draw);
  537.             document.addEventListener('mouseup', function() {
  538.                 if (drawing) {
  539.                     drawing = false;
  540.                     ctx.beginPath();
  541.                     document.getElementById('firmaData').value = canvas.toDataURL();
  542.                 }
  543.             });
  544.             document.getElementById('limpiarFirma').addEventListener('click', function() {
  545.                 ctx.clearRect(0, 0, canvas.width, canvas.height);
  546.                 document.getElementById('firmaData').value = '';
  547.             });
  548.             canvas.addEventListener('mouseup', function() {
  549.                 document.getElementById('firmaData').value = canvas.toDataURL();
  550.             });
  551.         })
  552.     </script>
  553. {% endblock %}