{"id":704,"date":"2025-11-16T17:26:37","date_gmt":"2025-11-16T17:26:37","guid":{"rendered":"https:\/\/bodafranyjose.com\/?page_id=704"},"modified":"2026-04-13T16:31:57","modified_gmt":"2026-04-13T16:31:57","slug":"time-line","status":"publish","type":"page","link":"https:\/\/bodafranyjose.com\/index.php\/time-line\/","title":{"rendered":"Time Line"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"704\" class=\"elementor elementor-704\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5fb451a e-flex e-con-boxed e-con e-parent\" data-id=\"5fb451a\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-28ea9b7 elementor-widget elementor-widget-html\" data-id=\"28ea9b7\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<style>\n  .timeline-wrapper {\n    max-width: 950px;\n    margin: 0 auto;\n    padding: 22px 18px;\n    background: #fff;\n    border-radius: 22px;\n    box-shadow: 0 6px 24px rgba(0,0,0,0.07);\n    font-family: 'Poppins', sans-serif;\n    color: #333;\n  }\n\n  .timeline-head {\n    text-align: center;\n    margin-bottom: 14px;\n  }\n\n  .timeline-title {\n    color: #b67b91;\n    font-size: 1.72rem;\n    font-weight: 700;\n    margin: 0 0 5px;\n    line-height: 1.15;\n  }\n\n  .timeline-subtitle {\n    color: #666;\n    margin: 0;\n    font-size: 0.9rem;\n    font-weight: 600;\n    line-height: 1.28;\n  }\n\n  .timeline-summary {\n    display: grid;\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n    gap: 9px;\n    margin-bottom: 14px;\n  }\n\n  .timeline-summary-card {\n    background: #faf6f8;\n    border: 1px solid transparent;\n    border-radius: 13px;\n    padding: 8px 10px;\n    text-align: center;\n    box-shadow: 0 2px 9px rgba(0,0,0,0.04);\n  }\n\n  .timeline-summary-card h3 {\n    margin: 0 0 4px;\n    color: #b67b91;\n    font-size: 0.76rem;\n    font-weight: 700;\n    line-height: 1.1;\n  }\n\n  .timeline-summary-card span {\n    display: block;\n    color: #333;\n    font-size: 1.14rem;\n    font-weight: 800;\n    line-height: 1.1;\n  }\n\n  .timeline-list {\n    display: grid;\n    gap: 8px;\n  }\n\n  .timeline-row {\n    display: grid;\n    grid-template-columns: 102px 1fr 42px;\n    gap: 9px;\n    align-items: center;\n    background: #faf6f8;\n    border: 1px solid #f0e6ea;\n    border-radius: 14px;\n    padding: 9px;\n    box-shadow: 0 2px 10px rgba(0,0,0,0.035);\n  }\n\n  .timeline-row:focus-within {\n    border-color: #b67b91;\n    box-shadow: 0 4px 14px rgba(182,123,145,0.13);\n    background: #fff;\n  }\n\n  .timeline-time,\n  .timeline-event,\n  .add-event input {\n    width: 100%;\n    min-height: 40px;\n    border: 1px solid #e2d4da;\n    border-radius: 10px;\n    padding: 8px 10px;\n    font-size: 16px;\n    box-sizing: border-box;\n    appearance: none;\n    background: #fff;\n    font-family: 'Poppins', sans-serif;\n    color: #333;\n  }\n\n  .timeline-time {\n    color: #b67b91;\n    font-weight: 800;\n    text-align: center;\n    padding-left: 7px;\n    padding-right: 7px;\n  }\n\n  .timeline-event {\n    font-weight: 700;\n  }\n\n  .timeline-time:focus,\n  .timeline-event:focus,\n  .add-event input:focus {\n    outline: 2px solid #f2e1e8;\n    border-color: #b67b91;\n  }\n\n  input[type=\"time\"]::-webkit-date-and-time-value {\n    text-align: center;\n  }\n\n  input[type=\"time\"]::-webkit-calendar-picker-indicator {\n    filter: invert(55%) sepia(15%) saturate(500%) hue-rotate(300deg);\n    cursor: pointer;\n  }\n\n  .btn-delete,\n  .btn-add {\n    cursor: pointer;\n    font-weight: 800;\n    border-radius: 10px;\n    transition: 0.25s ease;\n    font-family: 'Poppins', sans-serif;\n    min-height: 40px;\n    white-space: nowrap;\n  }\n\n  .btn-delete {\n    background: #fff;\n    color: #a5447d;\n    border: 1px solid #f0c8d6;\n    padding: 0;\n    font-size: 1rem;\n    line-height: 1;\n  }\n\n  .btn-delete:hover {\n    background: #fcefee;\n    color: #8f3568;\n  }\n\n  .add-event-wrap {\n    margin-top: 16px;\n    background: #faf6f8;\n    border: 1px solid #f0e6ea;\n    border-radius: 16px;\n    padding: 12px;\n    box-shadow: 0 2px 10px rgba(0,0,0,0.035);\n  }\n\n  .add-event-title {\n    margin: 0 0 10px;\n    color: #b67b91;\n    font-size: 0.92rem;\n    font-weight: 800;\n    text-align: center;\n  }\n\n  .add-event {\n    display: grid;\n    grid-template-columns: 102px 1fr auto;\n    gap: 10px;\n    align-items: center;\n  }\n\n  .btn-add {\n    background: #b67b91;\n    color: #fff;\n    border: none;\n    padding: 9px 14px;\n    font-size: 0.88rem;\n  }\n\n  .btn-add:hover {\n    background: #a56b82;\n  }\n\n  .timeline-empty {\n    text-align: center;\n    color: #b67b91;\n    background: #faf6f8;\n    border-radius: 14px;\n    padding: 16px 12px;\n    font-weight: 700;\n  }\n\n  @media (max-width: 700px) {\n    .timeline-wrapper {\n      padding: 16px 12px;\n      border-radius: 18px;\n    }\n\n    .timeline-head {\n      margin-bottom: 10px;\n    }\n\n    .timeline-title {\n      font-size: 1.36rem;\n      margin-bottom: 4px;\n    }\n\n    .timeline-subtitle {\n      font-size: 0.78rem;\n      line-height: 1.25;\n      max-width: 330px;\n      margin: 0 auto;\n    }\n\n    .timeline-summary {\n      gap: 7px;\n      margin-bottom: 12px;\n    }\n\n    .timeline-summary-card {\n      padding: 7px 8px;\n      border-radius: 11px;\n      min-height: 48px;\n    }\n\n    .timeline-summary-card h3 {\n      font-size: 0.66rem;\n      margin-bottom: 3px;\n    }\n\n    .timeline-summary-card span {\n      font-size: 0.96rem;\n    }\n\n    .timeline-list {\n      gap: 7px;\n    }\n\n    .timeline-row {\n      grid-template-columns: 78px 1fr 38px;\n      gap: 7px;\n      padding: 8px;\n      border-radius: 13px;\n    }\n\n    .timeline-time,\n    .timeline-event,\n    .add-event input {\n      min-height: 39px;\n      border-radius: 9px;\n      padding: 8px;\n    }\n\n    .timeline-time {\n      font-size: 0.86rem;\n      padding-left: 4px;\n      padding-right: 4px;\n    }\n\n    .timeline-event {\n      font-size: 0.9rem;\n    }\n\n    .btn-delete {\n      min-height: 39px;\n      border-radius: 9px;\n      font-size: 0.92rem;\n    }\n\n    .add-event-wrap {\n      margin-top: 14px;\n      padding: 11px;\n      border-radius: 15px;\n    }\n\n    .add-event-title {\n      font-size: 0.86rem;\n      margin-bottom: 9px;\n    }\n\n    .add-event {\n      grid-template-columns: 1fr;\n      gap: 8px;\n    }\n\n    .add-event input {\n      text-align: center;\n    }\n\n    .btn-add {\n      width: 100%;\n      min-height: 39px;\n      font-size: 0.84rem;\n      padding: 8px 10px;\n    }\n  }\n\n  @media (max-width: 380px) {\n    .timeline-title {\n      font-size: 1.28rem;\n    }\n\n    .timeline-summary-card h3 {\n      font-size: 0.62rem;\n    }\n\n    .timeline-summary-card span {\n      font-size: 0.9rem;\n    }\n\n    .timeline-row {\n      grid-template-columns: 72px 1fr 36px;\n      gap: 6px;\n      padding: 7px;\n    }\n\n    .timeline-time {\n      font-size: 0.78rem;\n    }\n\n    .timeline-event {\n      font-size: 0.84rem;\n    }\n  }\n<\/style>\n\n<div class=\"timeline-wrapper\">\n  <div class=\"timeline-head\">\n    <h2 class=\"timeline-title\">\ud83d\udd52 Cronograma de la Boda<\/h2>\n    <p class=\"timeline-subtitle\">Edita hora y evento directamente, sin desplegables.<\/p>\n  <\/div>\n\n  <div class=\"timeline-summary\">\n    <div class=\"timeline-summary-card\">\n      <h3>Eventos<\/h3>\n      <span id=\"totalEventos\">0<\/span>\n    <\/div>\n    <div class=\"timeline-summary-card\">\n      <h3>Pr\u00f3ximo<\/h3>\n      <span id=\"proximoEvento\">--:--<\/span>\n    <\/div>\n  <\/div>\n\n  <div class=\"timeline-list\" id=\"timeline\"><\/div>\n\n  <div class=\"add-event-wrap\">\n    <h3 class=\"add-event-title\">A\u00f1adir evento<\/h3>\n    <div class=\"add-event\">\n      <input type=\"time\" id=\"nuevaHora\">\n      <input type=\"text\" id=\"nuevoEvento\" placeholder=\"Nuevo evento...\">\n      <button class=\"btn-add\" onclick=\"agregarEvento()\">\u2795 A\u00f1adir<\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script>\nconst JSON_URL = 'https:\/\/bodafranyjose.com\/wp-content\/uploads\/timeline\/timeline.json';\nconst GUARDAR_URL = 'https:\/\/bodafranyjose.com\/wp-content\/uploads\/timeline\/guardar.php?key=bodafest2025KEY';\n\nlet timeline = [];\nlet guardadoTimer = null;\n\nfunction escaparHTML(valor) {\n  return String(valor || \"\")\n    .replace(\/&\/g, \"&amp;\")\n    .replace(\/<\/g, \"&lt;\")\n    .replace(\/>\/g, \"&gt;\")\n    .replace(\/\"\/g, \"&quot;\")\n    .replace(\/'\/g, \"&#039;\");\n}\n\nfunction minutosDesdeHora(hora) {\n  if (!hora || !hora.includes(\":\")) {\n    return 99999;\n  }\n\n  const partes = hora.split(\":\").map(Number);\n  const horas = partes[0] || 0;\n  const minutos = partes[1] || 0;\n\n  return horas * 60 + minutos;\n}\n\nfunction normalizarTimeline() {\n  timeline = timeline.map(function (item, index) {\n    return {\n      id: item.id || (\"evento-\" + Date.now() + \"-\" + index),\n      hora: item.hora || \"\",\n      evento: item.evento || \"\"\n    };\n  });\n}\n\nfunction ordenarTimeline() {\n  normalizarTimeline();\n  timeline.sort(function (a, b) {\n    return minutosDesdeHora(a.hora) - minutosDesdeHora(b.hora);\n  });\n}\n\nfunction programarGuardado() {\n  if (guardadoTimer) {\n    clearTimeout(guardadoTimer);\n  }\n\n  guardadoTimer = setTimeout(function () {\n    guardarTimeline(true);\n  }, 650);\n}\n\nasync function cargarTimeline() {\n  try {\n    const res = await fetch(JSON_URL + '?v=' + Date.now());\n\n    if (!res.ok) {\n      throw new Error(\"Error al cargar JSON\");\n    }\n\n    timeline = await res.json();\n\n    if (!Array.isArray(timeline)) {\n      timeline = [];\n    }\n  } catch (e) {\n    console.error(\"Error cargando timeline:\", e);\n    timeline = [];\n  }\n\n  ordenarTimeline();\n  renderTimeline();\n}\n\nfunction actualizarResumenTimeline() {\n  const total = timeline.length;\n  const proximo = timeline.find(function (item) {\n    return item.hora;\n  })?.hora || \"--:--\";\n\n  document.getElementById(\"totalEventos\").textContent = total;\n  document.getElementById(\"proximoEvento\").textContent = proximo;\n}\n\nfunction renderTimeline() {\n  const cont = document.getElementById(\"timeline\");\n  cont.innerHTML = \"\";\n\n  ordenarTimeline();\n  actualizarResumenTimeline();\n\n  if (!timeline.length) {\n    cont.innerHTML = '<p class=\"timeline-empty\">\ud83d\udd53 A\u00fan no hay eventos en el cronograma<\/p>';\n    return;\n  }\n\n  timeline.forEach(function (item, i) {\n    const card = document.createElement(\"div\");\n    card.className = \"timeline-row\";\n\n    card.innerHTML = `\n      <input\n        type=\"time\"\n        class=\"timeline-time\"\n        value=\"${escaparHTML(item.hora)}\"\n        onchange=\"actualizarHora(${i}, this.value)\"\n      >\n\n      <input\n        type=\"text\"\n        class=\"timeline-event\"\n        value=\"${escaparHTML(item.evento)}\"\n        placeholder=\"Evento sin t\u00edtulo\"\n        oninput=\"actualizarEvento(${i}, this.value)\"\n      >\n\n      <button class=\"btn-delete\" title=\"Eliminar evento\" onclick=\"eliminarEvento(${i})\">\u2715<\/button>\n    `;\n\n    cont.appendChild(card);\n  });\n}\n\nasync function actualizarHora(i, valor) {\n  if (!timeline[i]) {\n    return;\n  }\n\n  timeline[i].hora = valor;\n  actualizarResumenTimeline();\n  ordenarTimeline();\n  renderTimeline();\n  await guardarTimeline(true);\n}\n\nfunction actualizarEvento(i, valor) {\n  if (!timeline[i]) {\n    return;\n  }\n\n  timeline[i].evento = valor;\n  programarGuardado();\n}\n\nasync function agregarEvento() {\n  const horaInput = document.getElementById(\"nuevaHora\");\n  const eventoInput = document.getElementById(\"nuevoEvento\");\n\n  const hora = horaInput.value.trim();\n  const evento = eventoInput.value.trim();\n\n  if (!hora || !evento) {\n    alert(\"\u26a0\ufe0f Completa la hora y el nombre del evento.\");\n    return;\n  }\n\n  timeline.push({\n    id: \"evento-\" + Date.now(),\n    hora,\n    evento\n  });\n\n  horaInput.value = \"\";\n  eventoInput.value = \"\";\n\n  ordenarTimeline();\n  renderTimeline();\n  await guardarTimeline(true);\n}\n\nasync function eliminarEvento(i) {\n  if (!timeline[i]) {\n    return;\n  }\n\n  const evento = timeline[i].evento || \"este evento\";\n\n  if (confirm(`\u00bfEliminar \"${evento}\"?`)) {\n    timeline.splice(i, 1);\n    renderTimeline();\n    await guardarTimeline(true);\n  }\n}\n\nasync function guardarTimeline(silencioso = false) {\n  try {\n    ordenarTimeline();\n\n    const res = await fetch(GUARDAR_URL, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application\/json' },\n      body: JSON.stringify(timeline)\n    });\n\n    if (!res.ok) {\n      throw new Error(\"Error HTTP \" + res.status);\n    }\n\n    await res.text();\n\n    if (!silencioso) {\n      alert(\"\u2705 Timeline guardado correctamente\");\n    }\n  } catch (e) {\n    console.error(\"\u274c Error al guardar timeline:\", e);\n\n    if (!silencioso) {\n      alert(\"\u274c Error al guardar\");\n    }\n  }\n}\n\ncargarTimeline();\n\nwindow.guardarTimeline = guardarTimeline;\nwindow.guardarCambios = guardarTimeline;\n<\/script>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>\ud83d\udd52 Cronograma de la Boda Edita hora y evento directamente, sin desplegables. Eventos 0 Pr\u00f3ximo &#8211;:&#8211; A\u00f1adir evento \u2795 A\u00f1adir<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-704","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Time Line -<\/title>\n<meta name=\"robots\" content=\"noindex, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Time Line -\" \/>\n<meta property=\"og:description\" content=\"\ud83d\udd52 Cronograma de la Boda Edita hora y evento directamente, sin desplegables. Eventos 0 Pr\u00f3ximo &#8211;:&#8211; A\u00f1adir evento \u2795 A\u00f1adir\" \/>\n<meta property=\"og:url\" content=\"https:\/\/bodafranyjose.com\/index.php\/time-line\/\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-13T16:31:57+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data1\" content=\"6 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/bodafranyjose.com\\\/index.php\\\/time-line\\\/\",\"url\":\"https:\\\/\\\/bodafranyjose.com\\\/index.php\\\/time-line\\\/\",\"name\":\"Time Line -\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/bodafranyjose.com\\\/#website\"},\"datePublished\":\"2025-11-16T17:26:37+00:00\",\"dateModified\":\"2026-04-13T16:31:57+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/bodafranyjose.com\\\/index.php\\\/time-line\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/bodafranyjose.com\\\/index.php\\\/time-line\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/bodafranyjose.com\\\/index.php\\\/time-line\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/bodafranyjose.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Time Line\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/bodafranyjose.com\\\/#website\",\"url\":\"https:\\\/\\\/bodafranyjose.com\\\/\",\"name\":\"\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/bodafranyjose.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Time Line -","robots":{"index":"noindex","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"og_locale":"es_ES","og_type":"article","og_title":"Time Line -","og_description":"\ud83d\udd52 Cronograma de la Boda Edita hora y evento directamente, sin desplegables. Eventos 0 Pr\u00f3ximo &#8211;:&#8211; A\u00f1adir evento \u2795 A\u00f1adir","og_url":"https:\/\/bodafranyjose.com\/index.php\/time-line\/","article_modified_time":"2026-04-13T16:31:57+00:00","twitter_card":"summary_large_image","twitter_misc":{"Tiempo de lectura":"6 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/bodafranyjose.com\/index.php\/time-line\/","url":"https:\/\/bodafranyjose.com\/index.php\/time-line\/","name":"Time Line -","isPartOf":{"@id":"https:\/\/bodafranyjose.com\/#website"},"datePublished":"2025-11-16T17:26:37+00:00","dateModified":"2026-04-13T16:31:57+00:00","breadcrumb":{"@id":"https:\/\/bodafranyjose.com\/index.php\/time-line\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/bodafranyjose.com\/index.php\/time-line\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/bodafranyjose.com\/index.php\/time-line\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/bodafranyjose.com\/"},{"@type":"ListItem","position":2,"name":"Time Line"}]},{"@type":"WebSite","@id":"https:\/\/bodafranyjose.com\/#website","url":"https:\/\/bodafranyjose.com\/","name":"","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/bodafranyjose.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"}]}},"_links":{"self":[{"href":"https:\/\/bodafranyjose.com\/index.php\/wp-json\/wp\/v2\/pages\/704","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bodafranyjose.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bodafranyjose.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bodafranyjose.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bodafranyjose.com\/index.php\/wp-json\/wp\/v2\/comments?post=704"}],"version-history":[{"count":49,"href":"https:\/\/bodafranyjose.com\/index.php\/wp-json\/wp\/v2\/pages\/704\/revisions"}],"predecessor-version":[{"id":966,"href":"https:\/\/bodafranyjose.com\/index.php\/wp-json\/wp\/v2\/pages\/704\/revisions\/966"}],"wp:attachment":[{"href":"https:\/\/bodafranyjose.com\/index.php\/wp-json\/wp\/v2\/media?parent=704"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}