yasserrmd commited on
Commit
0d92062
Β·
verified Β·
1 Parent(s): aebe383

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +20 -20
index.html CHANGED
@@ -34,7 +34,7 @@
34
  </script>
35
 
36
  <style>
37
- /* ── formora.css ── */
38
  .frm-wrapper {
39
  font-family: 'Inter', system-ui, sans-serif;
40
  font-size: 0.875rem;
@@ -295,9 +295,9 @@
295
  <!-- ── Marked.js ─────────────────────────────────────────────────────────── -->
296
  <script src="https://cdn.jsdelivr.net/npm/marked@9/marked.min.js"></script>
297
 
298
- <!-- ── formora.js (inlined) ──────────────────────────────────────────────── -->
299
  <script>
300
- const FORMORA_PREFIX = '__formora__';
301
 
302
  class Rule {
303
  static required(msg = 'This field is required') { return { type: 'required', message: msg }; }
@@ -392,10 +392,10 @@ function renderField(f) {
392
  function renderForm(form) {
393
  if (form._multiStep && form._steps.length > 0) return renderMultiStep(form);
394
  const id = form._id;
395
- return `<div class="frm-wrapper" data-formora-id="${_fEsc(id)}">
396
  ${form._title?`<div class="frm-title">${_fEsc(form._title)}</div>`:''}
397
  ${form._description?`<div class="frm-desc">${_fEsc(form._description)}</div>`:''}
398
- <form class="frm-form" data-formora-id="${_fEsc(id)}" novalidate>
399
  ${form._fields.map(renderField).join('\n')}
400
  <div class="frm-actions"><button type="submit" class="frm-btn-submit">${_fEsc(form._submitLabel)}</button></div>
401
  <div class="frm-success" style="display:none">${_fEsc(form._successMsg)}</div>
@@ -411,11 +411,11 @@ function renderMultiStep(form) {
411
  ${step.title?`<div class="frm-step-title">${_fEsc(step.title)}</div>`:''}
412
  ${step.fields.map(renderField).join('\n')}
413
  </div>`).join('\n');
414
- return `<div class="frm-wrapper" data-formora-id="${_fEsc(id)}">
415
  ${form._title?`<div class="frm-title">${_fEsc(form._title)}</div>`:''}
416
  <div class="frm-progress-label">Step 1 of ${total}</div>
417
  <div class="frm-progress-bar"><div class="frm-progress-fill" id="${_fEsc(id)}-progress" style="width:${Math.round(100/total)}%"></div></div>
418
- <form class="frm-form" data-formora-id="${_fEsc(id)}" novalidate>
419
  ${stepsHtml}
420
  <div class="frm-nav">
421
  <button type="button" class="frm-btn-back" style="display:none">Back</button>
@@ -428,14 +428,14 @@ function renderMultiStep(form) {
428
  }
429
 
430
  function attachForms(container) {
431
- container.querySelectorAll('form[data-formora-id]').forEach(form => {
432
  _attachConditions(form); _attachMultiStep(form);
433
  form.addEventListener('submit', e => {
434
  e.preventDefault();
435
  if (!_validate(form)) return;
436
  const result = _collect(form);
437
  _showSuccess(form);
438
- window.dispatchEvent(new CustomEvent('formora:submit', { detail:{ raw:result.toMessage(), parsed:result } }));
439
  });
440
  });
441
  }
@@ -468,7 +468,7 @@ function _attachMultiStep(form) {
468
  const stepEls = form.querySelectorAll('.frm-step');
469
  if (!stepEls.length) return;
470
  const total = stepEls.length; let current = 0;
471
- const formId = form.getAttribute('data-formora-id') || form.closest('[data-formora-id]')?.getAttribute('data-formora-id') || '';
472
  const progress = document.getElementById(`${formId}-progress`);
473
  const label = form.closest('.frm-wrapper')?.querySelector('.frm-progress-label');
474
  const btnBack = form.querySelector('.frm-btn-back');
@@ -517,7 +517,7 @@ function _clearError(el) {
517
  el.parentNode?.querySelectorAll('.frm-error-msg').forEach(e=>e.remove());
518
  }
519
  function _collect(form) {
520
- const formId=form.getAttribute('data-formora-id')||form.closest('[data-formora-id]')?.getAttribute('data-formora-id')||'';
521
  const data={}, typed={};
522
  form.querySelectorAll('input,select,textarea').forEach(el => {
523
  if (!el.name) return;
@@ -536,13 +536,13 @@ function _showSuccess(form) {
536
 
537
  class FormResult {
538
  constructor(formId,data,typedData) { this.formId=formId; this.data=data; this.typedData=typedData; }
539
- toMessage() { return FORMORA_PREFIX+JSON.stringify({ form_id:this.formId, data:this.data, typed_data:this.typedData }); }
540
  asText() { return Object.entries(this.typedData).filter(([,v])=>v!==''&&v!==false).map(([k,v])=>`${k.replace(/_/g,' ')}: ${v}`).join(', '); }
541
  }
542
- function isFormoraMessage(msg) { return typeof msg==='string'&&msg.startsWith(FORMORA_PREFIX); }
543
  function parseFormoraMessage(msg) {
544
- if (!isFormoraMessage(msg)) return null;
545
- try { const p=JSON.parse(msg.slice(FORMORA_PREFIX.length)); return new FormResult(p.form_id,p.data,p.typed_data); } catch { return null; }
546
  }
547
  </script>
548
 
@@ -799,20 +799,20 @@ function injectForm(formHtml, intent) {
799
  const bubble = addBotRow('');
800
  bubble.style.padding = '12px';
801
  bubble.innerHTML = formHtml;
802
- const formEl = bubble.querySelector('form[data-formora-id]');
803
- const formId = formEl?.getAttribute('data-formora-id');
804
  attachForms(bubble);
805
- function onFormoraSubmit(e) {
806
  const { parsed } = e.detail;
807
  if (parsed.formId !== formId) return;
808
- window.removeEventListener('formora:submit', onFormoraSubmit);
809
  const requestNumber = nextTicket();
810
  const pill = document.createElement('div');
811
  pill.className = 'inc-pill'; pill.textContent = `βœ“ ${requestNumber}`;
812
  bubble.insertBefore(pill, bubble.firstChild);
813
  handleFormSubmit(parsed, requestNumber, intent);
814
  }
815
- window.addEventListener('formora:submit', onFormoraSubmit);
816
  scrollBottom();
817
  return bubble;
818
  }
 
34
  </script>
35
 
36
  <style>
37
+ /* ── barq-chat-form.css ── */
38
  .frm-wrapper {
39
  font-family: 'Inter', system-ui, sans-serif;
40
  font-size: 0.875rem;
 
295
  <!-- ── Marked.js ─────────────────────────────────────────────────────────── -->
296
  <script src="https://cdn.jsdelivr.net/npm/marked@9/marked.min.js"></script>
297
 
298
+ <!-- ── barq-chat-form.js (inlined) ──────────────────────────────────────────────── -->
299
  <script>
300
+ const BARQ_PREFIX = '__barq__';
301
 
302
  class Rule {
303
  static required(msg = 'This field is required') { return { type: 'required', message: msg }; }
 
392
  function renderForm(form) {
393
  if (form._multiStep && form._steps.length > 0) return renderMultiStep(form);
394
  const id = form._id;
395
+ return `<div class="frm-wrapper" data-barq-id="${_fEsc(id)}">
396
  ${form._title?`<div class="frm-title">${_fEsc(form._title)}</div>`:''}
397
  ${form._description?`<div class="frm-desc">${_fEsc(form._description)}</div>`:''}
398
+ <form class="frm-form" data-barq-id="${_fEsc(id)}" novalidate>
399
  ${form._fields.map(renderField).join('\n')}
400
  <div class="frm-actions"><button type="submit" class="frm-btn-submit">${_fEsc(form._submitLabel)}</button></div>
401
  <div class="frm-success" style="display:none">${_fEsc(form._successMsg)}</div>
 
411
  ${step.title?`<div class="frm-step-title">${_fEsc(step.title)}</div>`:''}
412
  ${step.fields.map(renderField).join('\n')}
413
  </div>`).join('\n');
414
+ return `<div class="frm-wrapper" data-barq-id="${_fEsc(id)}">
415
  ${form._title?`<div class="frm-title">${_fEsc(form._title)}</div>`:''}
416
  <div class="frm-progress-label">Step 1 of ${total}</div>
417
  <div class="frm-progress-bar"><div class="frm-progress-fill" id="${_fEsc(id)}-progress" style="width:${Math.round(100/total)}%"></div></div>
418
+ <form class="frm-form" data-barq-id="${_fEsc(id)}" novalidate>
419
  ${stepsHtml}
420
  <div class="frm-nav">
421
  <button type="button" class="frm-btn-back" style="display:none">Back</button>
 
428
  }
429
 
430
  function attachForms(container) {
431
+ container.querySelectorAll('form[data-barq-id]').forEach(form => {
432
  _attachConditions(form); _attachMultiStep(form);
433
  form.addEventListener('submit', e => {
434
  e.preventDefault();
435
  if (!_validate(form)) return;
436
  const result = _collect(form);
437
  _showSuccess(form);
438
+ window.dispatchEvent(new CustomEvent('barq:submit', { detail:{ raw:result.toMessage(), parsed:result } }));
439
  });
440
  });
441
  }
 
468
  const stepEls = form.querySelectorAll('.frm-step');
469
  if (!stepEls.length) return;
470
  const total = stepEls.length; let current = 0;
471
+ const formId = form.getAttribute('data-barq-id') || form.closest('[data-barq-id]')?.getAttribute('data-barq-id') || '';
472
  const progress = document.getElementById(`${formId}-progress`);
473
  const label = form.closest('.frm-wrapper')?.querySelector('.frm-progress-label');
474
  const btnBack = form.querySelector('.frm-btn-back');
 
517
  el.parentNode?.querySelectorAll('.frm-error-msg').forEach(e=>e.remove());
518
  }
519
  function _collect(form) {
520
+ const formId=form.getAttribute('data-barq-id')||form.closest('[data-barq-id]')?.getAttribute('data-barq-id')||'';
521
  const data={}, typed={};
522
  form.querySelectorAll('input,select,textarea').forEach(el => {
523
  if (!el.name) return;
 
536
 
537
  class FormResult {
538
  constructor(formId,data,typedData) { this.formId=formId; this.data=data; this.typedData=typedData; }
539
+ toMessage() { return BARQ_PREFIX+JSON.stringify({ form_id:this.formId, data:this.data, typed_data:this.typedData }); }
540
  asText() { return Object.entries(this.typedData).filter(([,v])=>v!==''&&v!==false).map(([k,v])=>`${k.replace(/_/g,' ')}: ${v}`).join(', '); }
541
  }
542
+ function isBarqMessage(msg) { return typeof msg==='string'&&msg.startsWith(BARQ_PREFIX); }
543
  function parseFormoraMessage(msg) {
544
+ if (!isBarqMessage(msg)) return null;
545
+ try { const p=JSON.parse(msg.slice(BARQ_PREFIX.length)); return new FormResult(p.form_id,p.data,p.typed_data); } catch { return null; }
546
  }
547
  </script>
548
 
 
799
  const bubble = addBotRow('');
800
  bubble.style.padding = '12px';
801
  bubble.innerHTML = formHtml;
802
+ const formEl = bubble.querySelector('form[data-barq-id]');
803
+ const formId = formEl?.getAttribute('data-barq-id');
804
  attachForms(bubble);
805
+ function onBarqSubmit(e) {
806
  const { parsed } = e.detail;
807
  if (parsed.formId !== formId) return;
808
+ window.removeEventListener('barq:submit', onBarqSubmit);
809
  const requestNumber = nextTicket();
810
  const pill = document.createElement('div');
811
  pill.className = 'inc-pill'; pill.textContent = `βœ“ ${requestNumber}`;
812
  bubble.insertBefore(pill, bubble.firstChild);
813
  handleFormSubmit(parsed, requestNumber, intent);
814
  }
815
+ window.addEventListener('barq:submit', onBarqSubmit);
816
  scrollBottom();
817
  return bubble;
818
  }