2011-05-10 30 views
6

Tengo un problema con beforeShowDay.jQuery Datepicker beforeShowDay funciona solo después del primer clic

Cuando se carga mi página, los días que he indicado destacar no se resaltan hasta que hago clic en un día en el calendario. Además, si hago clic en el botón del mes siguiente y vuelvo al mes original, los días 'seleccionados' se resaltan como se espera.

Por lo tanto, solo en el sorteo inicial del calendario las fechas no se resaltan como las he programado. Cualquier clic en el calendario se arregla solo.

¿Se echa en falta una opción init? Por favor, mira mi ejemplo de código a continuación. Mi url de prueba está en el directorio protegido con un usuario/pase de prueba/prueba. Mira el mini-cal en la parte inferior de la columna derecha. Pase al mes siguiente y vuelva para ver mi problema. Tenga en cuenta los días destacados de mayo. Además, tenga en cuenta que el menú desplegable 'año' también falta hasta que ocurre un clic.

http://www.urbanbands.com/dev/cgi-bin/links/eventmgr.cgi?do=list

El código:

<script> 
$(document).ready(function(){ 

    // get the current date 
    var today = new Date(); 
    var m = today.getMonth(), d = today.getDate(), y = today.getFullYear(); 

    // Need list of event dates for THIS month only from database. 
    // Declare 'dates' var before adding "beforeShowDay" option to the datepicker, 
    // otherwise, highlightDays() does not have the 'dates' array. 
    dates = []; 
    fetchEventDays(y, m+1); 

    $('#datepicker').datepicker({ 
     dateFormat: 'yy-mm-dd', 
     changeMonth: true, 
     changeYear: true, 
     setDate: today, 
     inline: false 
    }); 


    $('#datepicker').datepicker('option', 'onChangeMonthYear', fetchEventDays); 
    $('#datepicker').datepicker('option', 'beforeShowDay', highlightDays); 
    $('#datepicker').datepicker('option', 'onSelect', getday); 


    // ------------------------------------------------------------------ 
    // getday 
    // ------------------------------------------------------------------ 
    function getday(dateText, inst) { 
     $('#content').load('http://www.mydomain/eventmgr.cgi?do=view_day;date='+dateText+' #eventMgr_content', function() { 
    alert('Load was performed. '+dateText); 
     }); 
    } 

    // ------------------------------------------------------------------ 
    // fetchEventDays 
    // ------------------------------------------------------------------ 
    function fetchEventDays(year, month) { 
     var paramStr ='?do=get_event_dates&yr=' + year + '&mo=' + month; 
     $.get('<%config.db_cgi_url%>/eventmgr-ajax.cgi'+ paramStr, function(data) { 
      var recur_dates = data.split(','); 
      for(var i = 0; i < recur_dates.length; i++) { 
       var date_parts = recur_dates[i].split('-'); 
       dates.push(new Date(date_parts[0], date_parts[1]-1, date_parts[2])); 
      }      

// This causes dates with events to highlight on initial draw, but 
// when clicking to the next month, it switches back to orig month. 
//  $('#datepicker').datepicker('option', {}); // Refresh 

     }); 
    } 

    // ------------------------------------------------------------------ 
    // highlightDays 
    // ------------------------------------------------------------------ 
    function highlightDays(date) { 
     for (var i = 0; i < dates.length; i++) { 
      if ((dates[i].getTime() == date.getTime())) { 
       return [true, 'highlight']; 
      } 
     } 
     return [true, '']; 
    } 


}); 
    </script> 

Respuesta

1

no puedo ver su ejemplo, porque pasa eso lo se le solicite un nombre de usuario y contraseña. Sin embargo, vea a continuación lo que creo que está sucediendo.

$.get es simplemente una abreviatura para hacer una solicitud de obtención de AJAX. AJAX es asincrónico, lo que significa que lo llamas y no espera una respuesta. Entonces, básicamente, lo que probablemente está sucediendo es que el calendario se muestra antes de que se complete la solicitud de obtención.

Hay dos maneras en que puedo arreglar esto. Una sería cambiar tu llamada a Ajax completa y establecer async : true.

http://api.jquery.com/jQuery.ajax/

La otra opción (y probablemente la mejor opción) sería utilizar when. When básicamente le permite esperar que se complete una solicitud de Ajax antes de hacer cualquier otra cosa. Esto le permite seguir siendo asíncrono, pero asegura que el código dependiente no se ejecute prematuramente. De esta forma, se pueden realizar otras acciones entre la llamada ajax y el código dependiente.

http://api.jquery.com/jQuery.when/

4

Gracias @kingjiv Eras 100% correcto. El calendario se mostraba antes de que se completara la solicitud de obtención. Intenté utilizar el método when, pero no pude obtener las fechas de forma asíncrona. Básicamente, debo tener las fechas para resaltar antes de se muestra el calendario, así que tuve que usar async: false (no verdadero).

He incluido mi código completo que demuestra cómo destacar múltiples eventos extraídos de una base de datos usando la opción beforeShowDay. El uso de asyc: false solucionó el problema por el cual las fechas resaltadas no resaltaban en el sorteo inicial. También se incluye el CSS para cambiar el color de fondo de las celdas.

Todavía hay un pequeño problema donde el menú desplegable 'año' no se muestra en el sorteo inicial, pero he confirmado que esto solo ocurre en FireFox 4. Cualquier clic en el calendario hace que se muestre el menú anual. Safari muestra correctamente el menú del año en el sorteo inicial.

 <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/> 
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script> 
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script> 

<style type="text/css"> 
/* Dates with events on them. Text color - red, background - pastel yellow. */ 
td.highlight, table.ui-datepicker-calendar tbody td.highlight a { 
    background: none !important; 
    background-color: #fffac2 !important; 
    color: #FF0000; 
} 

/* This is Today's day in rightsidebar mini calendar (datepicker). */ 
/* Restore style to that of a default day, then just bold it. */ 
.ui-state-highlight, .ui-widget-content .ui-state-highlight { 
    border: 1px solid #d3d3d3; 
    background: #e6e6e6 url(http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; 
    font-weight: bold; 
    color: #555555; 
} 

/* This is the selected day in the inline datepicker. */ 
.ui-state-active, .ui-widget-content .ui-state-active { 
    color: #000000; 
    opacity: 1.0; 
    filter:Alpha(Opacity=100); 
    border: 1px solid #000000; 
} 

/* Add a little separation between month and year select menus */ 
.ui-datepicker select.ui-datepicker-month { 
    width: 42%; 
    margin-right: 6px; 
} 

</style> 

<script> 
$(document).ready(function(){ 

    // get the current date 
    var today = new Date(); 
    var m = today.getMonth(), d = today.getDate(), y = today.getFullYear(); 

    // Get a list of dates that contain events in THIS month only from database. 
    // Declare and populate 'eventDates' array BEFORE adding "beforeShowDay" option to 
    // the datepicker. Otherwise, highlightDays() will have an empty 'eventDates' array. 

    var eventDates = []; 
    fetchEventDays(y, m+1);  // Get events for the current year and month. 

    $('#datepicker').datepicker(); 
    $('#datepicker').datepicker('option', 'onChangeMonthYear', fetchEventDays); 
    $('#datepicker').datepicker('option', 'beforeShowDay', highlightDays); 
    $('#datepicker').datepicker('option', 'onSelect', getday); 
    $('#datepicker').datepicker('option', 'dateFormat', 'yy-mm-dd'); 
    $('#datepicker').datepicker('option', 'changeYear', true); 
    $('#datepicker').datepicker('option', 'changeMonth', true); 
    $('#datepicker').datepicker('option', 'yearRange', '2010:2012'); 
    $('#datepicker').datepicker('option', 'showButtonPanel', true); 

    // Disable all dates prior to today. 
    // $('#datepicker').datepicker('option', 'minDate', new Date(y, m, d)); 

    // ------------------------------------------------------------------ 
    // getday - Replaces the #content div of the current page with 
    // the content of the page that is created and displayed via perl 
    // ------------------------------------------------------------------ 
    function getday(dateText, inst) { 
     $('#content').load('<%config.db_cgi_url%>/eventmgr.cgi?do=view_day;date='+dateText+' #eventMgr_content', function() { 
//  alert('load was performed. '+dateText); 
     }); 
    } 

    // ------------------------------------------------------------------ 
    // fetchEventDays - The ajax call below is synchronous (NOT asynchronous). 
    // eventDates array must be populated prior to adding the beforeShowDay option 
    // to the datepicker, otherwise, highlightDays() will have an empty eventDates array. 
    // ------------------------------------------------------------------ 
    function fetchEventDays(year, month, inst) { 
     var url ='<%config.db_cgi_url%>/eventmgr-ajax.cgi?do=get_event_dates&yr=' + year + '&mo=' + month; 

     $.ajax({ 
      url: url, 
      async: false, 
      success: function(result){ 
       var event_dates = result.split(','); 
       for(var i = 0; i < event_dates.length; i++) { 
        var date_parts = event_dates[i].split('-'); 
        eventDates.push(new Date(date_parts[0], date_parts[1]-1, date_parts[2])); 
       }      
      } 
     }); 
    } 

    // ------------------------------------------------------------------ 
    // highlightDays - Add a custom css class to dates that exist in the 
    // eventDates array. Must also add the css for td.highlight (above). 
    // ------------------------------------------------------------------ 
    function highlightDays(date) { 
     for (var i = 0; i < eventDates.length; i++) { 
      if ((eventDates[i].getTime() == date.getTime())) { 
       return [true, 'highlight']; 
      } 
     } 
     return [true, '']; 
    } 

}); 
</script> 
2

no pude ver cómo jQuery.when ayudaría (que no se ve como que sería aplazar eventos desde el selector de fechas), pero logró evitar asíncrono = false desactivando el selector a continuación, actualiza cuando los datos se recibe en la devolución de llamada ajax

var available_days = []; 

var data = get_selected(); 
var today = new Date(); 
data['year'] = today.getFullYear(); 
data['month'] = today.getMonth() + 1; 
$.get('{% url views.get_availability %}', data, 
    function(get_data) { 
     $("#datepicker").datepicker("destroy"); 
     available_days = get_data['available_days']; 
     $("#datepicker").datepicker({ 
      onChangeMonthYear: function(year, month, inst) { 
       $("#datepicker").datepicker("disable"); 
       available_days = []; 
       data['year'] = year; 
       data['month'] = month; 
       $.get('{% url views.get_availability %}', data, 
        function(get_data) { 
         available_days = get_data["available_days"]; 
         $("#datepicker").datepicker("refresh"); 
         $("#datepicker").datepicker("enable"); 
        } 
       ); 
      },    
      beforeShowDay: function(date) { 
       return [$.inArray(date.getDate(), available_days) >= 0, '']; 
      }, 
      onSelect: function(dateText, inst) { showTimes(dateText, data); }, 
      dateFormat: "dd-mm-yy", 
     }); 
    } 
); 
Cuestiones relacionadas