{"id":6274,"date":"2025-06-25T16:37:15","date_gmt":"2025-06-25T21:37:15","guid":{"rendered":"https:\/\/federacioncolombianadeajedrez.com\/?page_id=6274"},"modified":"2025-08-19T08:12:27","modified_gmt":"2025-08-19T13:12:27","slug":"entrenadores","status":"publish","type":"page","link":"https:\/\/federacioncolombianadeajedrez.com\/noticias\/entrenadores\/","title":{"rendered":"Entrenadores"},"content":{"rendered":"<div style=\"display: flex; align-items: center; gap: 20px; flex-wrap: wrap; margin-bottom: 20px;\">\n  <img decoding=\"async\" \n    src=\"https:\/\/federacioncolombianadeajedrez.com\/wp-content\/uploads\/ebtre.jpg\" \n    alt=\"\" \n    width=\"120\" \n    style=\"border-radius: 8px; box-shadow: 0 4px 10px rgba(0,0,0,0.1);\" \n  \/><\/p>\n<div style=\"flex: 1; text-align: center;\">\n<h2 style=\"font-size: 2em; margin: 0; color: #2c3e50;\"><strong>ENTRENADORES<\/strong><\/h2>\n<p style=\"font-size: 1em; color: #666; margin-top: 5px;\">\n      Registro de entrenadores de Ajedrez en Colombia.\n    <\/p>\n<\/p><\/div>\n<\/div>\n<div class=\"container py-4\" id=\"entrenadoresPublicApp\">\n  <div class=\"card shadow-sm\">\n    <div class=\"card-body\">\n\n      <div class=\"d-flex flex-column flex-lg-row gap-3 mb-3 align-items-lg-end\">\n        <div class=\"flex-grow-1\">\n          <div class=\"input-group\"\n            data-bs-toggle=\"tooltip\" data-bs-placement=\"top\"\n            title=\"Busca por nombre o por ID FIDE\">\n            <span class=\"input-group-text\"><i class=\"bi bi-search\"><\/i><\/span>\n            <input type=\"text\" id=\"pubSearch\" class=\"form-control\" placeholder=\"Nombre o ID FIDE\">\n          <\/div>\n        <\/div>\n\n        <div>\n          <select id=\"pubTitFide\" class=\"form-select\"\n            data-bs-toggle=\"tooltip\" data-bs-placement=\"top\"\n            title=\"Filtrar por t\u00edtulo FIDE\">\n            <option value=\"\">FIDE<\/option>\n          <\/select>\n        <\/div>\n\n        <div>\n          <select id=\"pubTitEnt\" class=\"form-select\"\n            data-bs-toggle=\"tooltip\" data-bs-placement=\"top\"\n            title=\"Filtrar por t\u00edtulo de entrenador\">\n            <option value=\"\">Todos<\/option>\n          <\/select>\n        <\/div>\n\n        <div>\n          <select id=\"pubLiga\" class=\"form-select\"\n            data-bs-toggle=\"tooltip\" data-bs-placement=\"top\"\n            title=\"Filtrar por Liga\">\n            <option value=\"\">Liga<\/option>\n          <\/select>\n        <\/div>\n\n        <div class=\"d-flex gap-2\">\n          <button class=\"btn btn-outline-secondary\" id=\"pubReset\"\n            data-bs-toggle=\"tooltip\" data-bs-placement=\"top\"\n            title=\"Limpiar b\u00fasqueda y filtros\">\n            <i class=\"bi bi-arrow-counterclockwise me-1\"><\/i>\n          <\/button>\n\n          <button class=\"btn btn-outline-primary\" id=\"pubRefresh\"\n            data-bs-toggle=\"tooltip\" data-bs-placement=\"top\"\n            title=\"Recargar datos desde el servidor\">\n            <i class=\"bi bi-arrow-clockwise me-1\"><\/i>\n          <\/button>\n\n          <button class=\"btn btn-success\" id=\"pubExport\"\n            data-bs-toggle=\"tooltip\" data-bs-placement=\"top\"\n            title=\"Descargar CSV con los resultados actuales\">\n            <i class=\"bi bi-download me-1\"><\/i>\n          <\/button>\n        <\/div>\n      <\/div>\n\n      <div class=\"d-flex flex-wrap justify-content-between align-items-center mb-2 gap-2\">\n        <div class=\"d-flex align-items-center gap-2\">\n          <label for=\"pubPerPage\" class=\"form-label mb-0\">ver<\/label>\n          <select id=\"pubPerPage\" class=\"form-select form-select-sm\" style=\"width:auto;\"\n            data-bs-toggle=\"tooltip\" data-bs-placement=\"top\"\n            title=\"Cantidad de registros por p\u00e1gina\">\n            <option>10<\/option><option>25<\/option><option>50<\/option><option>100<\/option>\n          <\/select>\n          <span class=\"text-muted\">registros<\/span>\n        <\/div>\n        <div class=\"text-muted\" id=\"pubInfo\"><\/div>\n      <\/div>\n\n      <div id=\"pubTableWrap\" class=\"table-responsive\">\n        <div class=\"d-flex justify-content-center py-5\">\n          <div class=\"spinner-border text-primary\" role=\"status\"><span class=\"visually-hidden\">Cargando...<\/span><\/div>\n        <\/div>\n      <\/div>\n\n      <nav aria-label=\"Paginaci\u00f3n\" class=\"mt-3\">\n        <ul id=\"pubPagination\" class=\"pagination justify-content-center\"><\/ul>\n      <\/nav>\n\n    <\/div>\n  <\/div>\n<\/div>\n\n<script>\njQuery(function($){\n  const state={raw:[],rows:[],page:1,perPage:10,sort:{key:null,dir:'asc'}};\n\n  \/\/ ============================\n  \/\/ Tooltips Bootstrap 5 (encapsulado)\n  \/\/ ============================\n  function initTooltips(root){\n    if (!window.bootstrap || !window.bootstrap.Tooltip) return;\n    const el = root && root.length ? root[0] : document;\n\n    el.querySelectorAll('[data-bs-toggle=\"tooltip\"]').forEach(node=>{\n      const inst = window.bootstrap.Tooltip.getInstance(node);\n      if (inst) inst.dispose();\n      new window.bootstrap.Tooltip(node, {\n        container: 'body',\n        trigger: 'hover focus',\n        customClass: 'eji-tooltip',\n        delay: { show: 120, hide: 40 }\n      });\n    });\n  }\n\n  \/\/ Inicializa tooltips de controles superiores\n  initTooltips(document);\n\n  load();\n\n  $('#pubSearch, #pubTitFide, #pubTitEnt, #pubLiga').on('input change', applyAndRender);\n  $('#pubPerPage').on('change', function(){ state.perPage=parseInt(this.value,10)||10; state.page=1; render(); });\n  $('#pubReset').on('click', function(e){\n    e.preventDefault();\n    $('#pubSearch,#pubTitFide,#pubTitEnt,#pubLiga').val('');\n    state.page=1; state.sort={key:null,dir:'asc'}; applyAndRender();\n  });\n  $('#pubRefresh').on('click', function(e){ e.preventDefault(); load(); });\n  $('#pubExport').on('click', function(e){ e.preventDefault(); exportCSV(); });\n\n  function load(){\n    $('#pubTableWrap').html(`<div class=\"d-flex justify-content-center py-5\">\n      <div class=\"spinner-border text-primary\" role=\"status\"><span class=\"visually-hidden\">Cargando...<\/span><\/div>\n    <\/div>`);\n    $('#pubPagination').empty();\n\n    $.ajax({\n      url: eji_vars.ajax_url,\n      type: 'POST',\n      data: { action:'eji_get_entrenadores', nonce:eji_vars.nonce },\n      dataType: 'json'\n    }).done(resp=>{\n      if(resp && resp.success){\n        state.raw = Array.isArray(resp.data) ? resp.data : [];\n        buildFilterOptions(state.raw);\n        applyAndRender();\n      }else{\n        showError('Error al cargar: '+((resp && resp.data && resp.data.message) ? resp.data.message : ''));\n      }\n    }).fail((jqXHR, textStatus)=>{\n      showError('Error en solicitud: '+textStatus);\n    });\n  }\n\n  function showError(msg){\n    $('#pubTableWrap').html(`<div class=\"alert alert-danger\" role=\"alert\"\n      data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"Intenta recargar con el bot\u00f3n azul\">\n      <i class=\"bi bi-exclamation-triangle me-2\"><\/i>${msg}\n    <\/div>`);\n    initTooltips(document);\n  }\n\n  function uniqueSorted(arr, mapFn){\n    const set=new Set(arr.map(mapFn).filter(Boolean));\n    return Array.from(set).sort((a,b)=>a.localeCompare(b,'es',{sensitivity:'base'}));\n  }\n\n  function fillSelect($sel, items){\n    const cur=$sel.val();\n    $sel.find('option:not(:first)').remove();\n    items.forEach(v=>$sel.append($('<option>',{value:v,text:v})));\n    if(items.includes(cur)) $sel.val(cur);\n  }\n\n  function buildFilterOptions(rows){\n    fillSelect($('#pubTitFide'), uniqueSorted(rows,r=>(r.tit_fide||'').trim()));\n    fillSelect($('#pubTitEnt'),  uniqueSorted(rows,r=>(r.tit_ent ||'').trim()));\n    fillSelect($('#pubLiga'),    uniqueSorted(rows,r=>(r.liga    ||'').trim()));\n  }\n\n  function applyFilters(rows){\n    const term=(($('#pubSearch').val()||'')+'').toLowerCase();\n    const fFide=$('#pubTitFide').val()||'';\n    const fEnt=$('#pubTitEnt').val()||'';\n    const fLiga=$('#pubLiga').val()||'';\n    return rows.filter(r=>{\n      const okText=!term || (String(r.id_fide||'').toLowerCase().includes(term) || String(r.nombre||'').toLowerCase().includes(term));\n      const okFide=!fFide || (r.tit_fide||'')===fFide;\n      const okEnt=!fEnt || (r.tit_ent||'')===fEnt;\n      const okLiga=!fLiga || (r.liga||'')===fLiga;\n      return okText && okFide && okEnt && okLiga;\n    });\n  }\n\n  function applySort(rows){\n    const {key,dir}=state.sort; if(!key) return rows;\n    const m=dir==='desc'?-1:1;\n    return rows.slice().sort((a,b)=>{\n      const A=(a[key]??'').toString().toLowerCase();\n      const B=(b[key]??'').toString().toLowerCase();\n      if(A<B) return -1*m; if(A>B) return 1*m; return 0;\n    });\n  }\n\n  function applyAndRender(){\n    state.rows = applySort(applyFilters(state.raw));\n    state.page=1;\n    render();\n  }\n\n  function render(){\n    const total=state.rows.length;\n    const pages=Math.max(1, Math.ceil(total\/state.perPage));\n    state.page=Math.min(Math.max(1,state.page), pages);\n    const start=(state.page-1)*state.perPage;\n    const pageRows=state.rows.slice(start,start+state.perPage);\n\n    const from=total?(start+1):0;\n    const to=Math.min(start+state.perPage,total);\n    $('#pubInfo').text(`${from}-${to} de ${total}`);\n\n    const th=(key,label,tip)=>{\n      const active=state.sort.key===key;\n      const ind=active?(state.sort.dir==='asc'?'\u25b2':'\u25bc'):'';\n      return `<th class=\"sortable\" data-key=\"${key}\"\n        data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"${tip}\">\n        ${label}<span class=\"sort-ind\">${ind}<\/span><\/th>`;\n    };\n\n    let html=`<table class=\"table table-hover align-middle\"><thead><tr>\n      ${th('id_fide','ID FIDE','Ordenar por ID FIDE')}\n      ${th('nombre','Nombre','Ordenar por nombre')}\n      ${th('tit_fide','FIDE','Ordenar por t\u00edtulo FIDE')}\n      ${th('tit_ent',' Entrenador','Ordenar por t\u00edtulo de entrenador')}\n      ${th('tit_esc',' Escuela','Ordenar por t\u00edtulo escuela')}\n      ${th('liga','Liga','Ordenar por Liga')}\n    <\/tr><\/thead><tbody>`;\n\n    if(!pageRows.length){\n      html+=`<tr><td colspan=\"6\" class=\"text-center py-4\"\n        data-bs-toggle=\"tooltip\" data-bs-placement=\"top\"\n        title=\"Prueba limpiar filtros o cambiar la b\u00fasqueda\">\n        <i class=\"bi bi-exclamation-circle fs-1 text-muted\"><\/i>\n        <p class=\"mt-2 mb-0\">No se encontraron entrenadores<\/p><\/td><\/tr>`;\n    }else{\n      const safe = (v)=> (v===null||v===undefined||String(v).trim()==='') ? '-' : String(v);\n      pageRows.forEach(r=>{\n        const id = safe(r.id_fide);\n        const nom = safe(r.nombre);\n        const tf = safe(r.tit_fide);\n        const te = safe(r.tit_ent);\n        const ts = safe(r.tit_esc);\n        const li = safe(r.liga);\n\n        html+=`<tr>\n          <td data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"ID FIDE: ${id}\">${id}<\/td>\n          <td data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"${nom}\">${nom}<\/td>\n          <td data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"T\u00edtulo FIDE: ${tf}\">${tf}<\/td>\n          <td data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"T\u00edtulo Entrenador: ${te}\">${te}<\/td>\n          <td data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"T\u00edtulo Escuela: ${ts}\">${ts}<\/td>\n          <td data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"Liga: ${li}\">${li}<\/td>\n        <\/tr>`;\n      });\n    }\n    html+=`<\/tbody><\/table>`;\n    $('#pubTableWrap').html(html);\n\n    $('#pubTableWrap th.sortable').off('click').on('click', function(){\n      const key=$(this).data('key');\n      if(state.sort.key===key) state.sort.dir=(state.sort.dir==='asc')?'desc':'asc';\n      else state.sort={key,dir:'asc'};\n      applyAndRender();\n    });\n\n    renderPagination(pages);\n\n    \/\/ \u2705 Tooltips despu\u00e9s de repintar tabla + paginaci\u00f3n\n    initTooltips(document);\n  }\n\n  function renderPagination(pages){\n    const $p=$('#pubPagination');\n    if(pages<=1){$p.empty();return;}\n    let html='';\n    const item=(page,label,disabled=false,active=false,aria='',tip='')=>`\n      <li class=\"page-item ${disabled?'disabled':''} ${active?'active':''}\">\n        <a class=\"page-link\" href=\"#\" data-page=\"${page}\" ${aria}\n          data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"${tip}\">\n          ${label}\n        <\/a>\n      <\/li>`;\n\n    html+=item(state.page-1,'<i class=\"bi bi-chevron-left\"><\/i>',state.page<=1,false,'aria-label=\"Anterior\"','P\u00e1gina anterior');\n\n    const max=7;\n    const add=p=>{ html+=item(p,p,false,p===state.page,'',`Ir a p\u00e1gina ${p}`); };\n    const range=(a,b)=>{ for(let i=a;i<=b;i++) add(i); };\n\n    if(pages<=max){ range(1,pages); }\n    else{\n      const left=Math.max(1,state.page-2), right=Math.min(pages,state.page+2);\n      add(1);\n      if(left>2) html+=`<li class=\"page-item disabled\"><span class=\"page-link\">\u2026<\/span><\/li>`;\n      range(left,right);\n      if(right<pages-1) html+=`<li class=\"page-item disabled\"><span class=\"page-link\">\u2026<\/span><\/li>`;\n      add(pages);\n    }\n\n    html+=item(state.page+1,'<i class=\"bi bi-chevron-right\"><\/i>',state.page>=pages,false,'aria-label=\"Siguiente\"','P\u00e1gina siguiente');\n    $p.html(html);\n\n    $p.find('a.page-link').off('click').on('click', function(e){\n      e.preventDefault();\n      const p=parseInt($(this).data('page'),10);\n      if(!isNaN(p)){ state.page=p; render(); }\n    });\n  }\n\n  function exportCSV(){\n    const heads=['id_fide','nombre','tit_fide','tit_ent','tit_esc','liga'];\n    let csv=heads.join(',')+'\\n';\n    state.rows.forEach(r=>{\n      csv+=heads.map(h=>`\"${(r[h]||'').toString().replace(\/\"\/g,'\"\"')}\"`).join(',')+'\\n';\n    });\n    const blob=new Blob([\"\\uFEFF\"+csv],{type:'text\/csv;charset=utf-8;'});\n    const url=URL.createObjectURL(blob);\n    const a=document.createElement('a'); a.href=url; a.download='entrenadores_publico.csv';\n    document.body.appendChild(a); a.click(); document.body.removeChild(a);\n  }\n});\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>ENTRENADORES Registro de entrenadores de Ajedrez en Colombia.<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-6274","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/federacioncolombianadeajedrez.com\/noticias\/wp-json\/wp\/v2\/pages\/6274","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/federacioncolombianadeajedrez.com\/noticias\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/federacioncolombianadeajedrez.com\/noticias\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/federacioncolombianadeajedrez.com\/noticias\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/federacioncolombianadeajedrez.com\/noticias\/wp-json\/wp\/v2\/comments?post=6274"}],"version-history":[{"count":0,"href":"https:\/\/federacioncolombianadeajedrez.com\/noticias\/wp-json\/wp\/v2\/pages\/6274\/revisions"}],"wp:attachment":[{"href":"https:\/\/federacioncolombianadeajedrez.com\/noticias\/wp-json\/wp\/v2\/media?parent=6274"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}