Changeset 53497 in spip-zone


Ignore:
Timestamp:
Oct 15, 2011, 8:36:24 PM (8 years ago)
Author:
ngombe@…
Message:

V 0.1.4
FullCalendar? v1.5.2, calendrier mini, source d’évènements par rubrique, bugs (articles non-publiés...), internationalisation...

Location:
_plugins_/fullcalendar
Files:
52 added
2 deleted
11 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/fullcalendar/css/fullcalendar.css

    r45054 r53497  
    11/*
    2  * FullCalendar v1.4.10 Stylesheet
     2 * FullCalendar v1.5.2 Stylesheet
    33 *
    4  * Feel free to edit this file to customize the look of FullCalendar.
    5  * When upgrading to newer versions, please upgrade this file as well,
    6  * porting over any customizations afterwards.
     4 * Copyright (c) 2011 Adam Shaw
     5 * Dual licensed under the MIT and GPL licenses, located in
     6 * MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
    77 *
    8  * Date: Sat Jan 1 23:46:27 2011 -0800
     8 * Date: Sun Aug 21 22:06:09 2011 -0700
    99 *
    1010 */
    11  
    12  
    13 /* TODO: make font sizes look the same in all doctypes */
    14 
    15 
    16 .fc,
    17 .fc .fc-header,
    18 .fc .fc-content {
    19         font-size: 1em;
    20         }
    21        
     11
     12
    2213.fc {
    2314        direction: ltr;
     
    3021        }
    3122       
    32 .fc td, .fc th {
     23html .fc,
     24.fc table {
     25        font-size: 1em;
     26        }
     27       
     28.fc td,
     29.fc th {
    3330        padding: 0;
    3431        vertical-align: top;
     
    3936/* Header
    4037------------------------------------------------------------------------*/
    41        
    42 table.fc-header {
    43         width: 100%;
    44         }
    45        
     38
     39.fc-header td {
     40        white-space: nowrap;
     41        }
     42
    4643.fc-header-left {
    4744        width: 25%;
    48         }
    49        
    50 .fc-header-left table {
    51         float: left;
     45        text-align: left;
    5246        }
    5347       
    5448.fc-header-center {
    55         width: 50%;
    5649        text-align: center;
    57         }
    58        
    59 .fc-header-center table {
    60         margin: 0 auto;
    6150        }
    6251       
    6352.fc-header-right {
    6453        width: 25%;
    65         }
    66        
    67 .fc-header-right table {
    68         float: right;
     54        text-align: right;
    6955        }
    7056       
    7157.fc-header-title {
     58        display: inline-block;
     59        vertical-align: top;
     60        }
     61       
     62.fc-header-title h2 {
    7263        margin-top: 0;
    7364        white-space: nowrap;
    7465        }
    7566       
    76 .fc-header-space {
     67.fc .fc-header-space {
    7768        padding-left: 10px;
    7869        }
    7970       
    80 /* right-to-left */
    81 
    82 .fc-rtl .fc-header-title {
    83         direction: rtl;
    84         }
    85 
    86 
    87 
    88 /* Buttons
    89 ------------------------------------------------------------------------*/
    90 
    91 .fc-header .fc-state-default,
    92 .fc-header .ui-state-default {
     71.fc-header .fc-button {
    9372        margin-bottom: 1em;
    94         cursor: pointer;
    95         }
    96        
    97 .fc-header .fc-state-default {
    98         border-width: 1px 0;
    99         padding: 0 1px;
    100         }
    101        
    102 .fc-header .fc-state-default,
    103 .fc-header .fc-state-default a {
    104         border-style: solid;
    105         }
    106        
    107 .fc-header .fc-state-default a {
    108         display: block;
    109         border-width: 0 1px;
    110         margin: 0 -1px;
    111         width: 100%;
    112         text-decoration: none;
    113         }
    114        
    115 .fc-header .fc-state-default span {
    116         display: block;
    117         border-style: solid;
    118         border-width: 1px 0 1px 1px;
    119         padding: 3px 5px;
    120         }
    121        
    122 .fc-header .ui-state-default {
    123         padding: 4px 6px;
    124         }
    125        
    126 .fc-header .fc-state-default span,
    127 .fc-header .ui-state-default span {
    128         white-space: nowrap;
    129         }
    130        
    131 /* for adjacent buttons */
    132        
    133 .fc-header .fc-no-right {
    134         padding-right: 0;
    135         }
    136        
    137 .fc-header .fc-no-right a {
    138         margin-right: 0;
    139         border-right: 0;
    140         }
    141        
    142 .fc-header .ui-no-right {
    143         border-right: 0;
    144         }
    145        
    146 /* for fake rounded corners */
    147        
    148 .fc-header .fc-corner-left {
    149         margin-left: 1px;
    150         padding-left: 0;
     73        vertical-align: top;
     74        }
     75       
     76/* buttons edges butting together */
     77
     78.fc-header .fc-button {
     79        margin-right: -1px;
    15180        }
    15281       
    15382.fc-header .fc-corner-right {
    154         margin-right: 1px;
    155         padding-right: 0;
    156         }
    157        
    158 /* DEFAULT button COLORS */
    159        
    160 .fc-header .fc-state-default,
    161 .fc-header .fc-state-default a {
    162         border-color: #777; /* outer border */
    163         color: #333;
    164         }
    165 
    166 .fc-header .fc-state-default span {
    167         border-color: #fff #fff #d1d1d1; /* inner border */
    168         background: #e8e8e8;
    169         }
    170        
    171 /* PRESSED button COLORS (down and active) */
    172        
    173 .fc-header .fc-state-active a {
    174         color: #fff;
    175         }
    176        
    177 .fc-header .fc-state-down span,
    178 .fc-header .fc-state-active span {
    179         background: #888;
    180         border-color: #808080 #808080 #909090; /* inner border */
    181         }
    182        
    183 /* DISABLED button COLORS */
    184        
    185 .fc-header .fc-state-disabled a {
    186         color: #999;
    187         }
    188        
    189 .fc-header .fc-state-disabled,
    190 .fc-header .fc-state-disabled a {
    191         border-color: #ccc; /* outer border */
    192         }
    193        
    194 .fc-header .fc-state-disabled span {
    195         border-color: #fff #fff #f0f0f0; /* inner border */
    196         background: #f0f0f0;
    197         }
    198        
    199        
    200        
    201 /* Content Area & Global Cell Styles
    202 ------------------------------------------------------------------------*/
    203        
    204 .fc-widget-content {
    205         border: 1px solid #ccc; /* outer border color */
    206         }
     83        margin-right: 1px; /* back to normal */
     84        }
     85       
     86.fc-header .ui-corner-right {
     87        margin-right: 0; /* back to normal */
     88        }
     89       
     90/* button layering (for border precedence) */
     91       
     92.fc-header .fc-state-hover,
     93.fc-header .ui-state-hover {
     94        z-index: 2;
     95        }
     96       
     97.fc-header .fc-state-down {
     98        z-index: 3;
     99        }
     100
     101.fc-header .fc-state-active,
     102.fc-header .ui-state-active {
     103        z-index: 4;
     104        }
     105       
     106       
     107       
     108/* Content
     109------------------------------------------------------------------------*/
    207110       
    208111.fc-content {
     
    210113        }
    211114       
    212 .fc-content .fc-state-default {
    213         border-style: solid;
    214         border-color: #ccc; /* inner border color */
    215         }
    216        
    217 .fc-content .fc-state-highlight { /* today */
     115.fc-view {
     116        width: 100%; /* needed for view switching (when view is absolute) */
     117        overflow: hidden;
     118        }
     119       
     120       
     121
     122/* Cell Styles
     123------------------------------------------------------------------------*/
     124
     125.fc-widget-header,    /* <th>, usually */
     126.fc-widget-content {  /* <td>, usually */
     127        border: 1px solid #ccc;
     128        }
     129       
     130.fc-state-highlight { /* <td> today cell */ /* TODO: add .fc-today to <th> */
    218131        background: #ffc;
    219         }
    220        
    221 .fc-content .fc-not-today { /* override jq-ui highlight (TODO: ui-widget-content) */
    222         background: none;
    223132        }
    224133       
     
    229138        }
    230139       
    231 .fc-view { /* prevents dragging outside of widget */
    232         width: 100%;
     140
     141
     142/* Buttons
     143------------------------------------------------------------------------*/
     144
     145.fc-button {
     146        position: relative;
     147        display: inline-block;
     148        cursor: pointer;
     149        }
     150       
     151.fc-state-default { /* non-theme */
     152        border-style: solid;
     153        border-width: 1px 0;
     154        }
     155       
     156.fc-button-inner {
     157        position: relative;
     158        float: left;
    233159        overflow: hidden;
    234160        }
    235161       
    236        
    237        
    238 
     162.fc-state-default .fc-button-inner { /* non-theme */
     163        border-style: solid;
     164        border-width: 0 1px;
     165        }
     166       
     167.fc-button-content {
     168        position: relative;
     169        float: left;
     170        height: 1.9em;
     171        line-height: 1.9em;
     172        padding: 0 .6em;
     173        white-space: nowrap;
     174        }
     175       
     176/* icon (for jquery ui) */
     177       
     178.fc-button-content .fc-icon-wrap {
     179        position: relative;
     180        float: left;
     181        top: 50%;
     182        }
     183       
     184.fc-button-content .ui-icon {
     185        position: relative;
     186        float: left;
     187        margin-top: -50%;
     188        *margin-top: 0;
     189        *top: -50%;
     190        }
     191       
     192/* gloss effect */
     193       
     194.fc-state-default .fc-button-effect {
     195        position: absolute;
     196        top: 50%;
     197        left: 0;
     198        }
     199       
     200.fc-state-default .fc-button-effect span {
     201        position: absolute;
     202        top: -100px;
     203        left: 0;
     204        width: 500px;
     205        height: 100px;
     206        border-width: 100px 0 0 1px;
     207        border-style: solid;
     208        border-color: #fff;
     209        background: #444;
     210        opacity: .09;
     211        filter: alpha(opacity=9);
     212        }
     213       
     214/* button states (determines colors)  */
     215       
     216.fc-state-default,
     217.fc-state-default .fc-button-inner {
     218        border-style: solid;
     219        border-color: #ccc #bbb #aaa;
     220        background: #F3F3F3;
     221        color: #000;
     222        }
     223       
     224.fc-state-hover,
     225.fc-state-hover .fc-button-inner {
     226        border-color: #999;
     227        }
     228       
     229.fc-state-down,
     230.fc-state-down .fc-button-inner {
     231        border-color: #555;
     232        background: #777;
     233        }
     234       
     235.fc-state-active,
     236.fc-state-active .fc-button-inner {
     237        border-color: #555;
     238        background: #777;
     239        color: #fff;
     240        }
     241       
     242.fc-state-disabled,
     243.fc-state-disabled .fc-button-inner {
     244        color: #999;
     245        border-color: #ddd;
     246        }
     247       
     248.fc-state-disabled {
     249        cursor: default;
     250        }
     251       
     252.fc-state-disabled .fc-button-effect {
     253        display: none;
     254        }
     255       
     256       
    239257
    240258/* Global Event Styles
    241259------------------------------------------------------------------------*/
    242 
    243 .fc-event,
    244 .fc-agenda .fc-event-time,
    245 .fc-event a {
    246         border-style: solid;
    247         border-color: #36c;     /* default BORDER color (probably the same as background-color) */
     260         
     261.fc-event {
     262        border-style: solid;
     263        border-width: 0;
     264        font-size: .85em;
     265        cursor: default;
     266        }
     267       
     268a.fc-event,
     269.fc-event-draggable {
     270        cursor: pointer;
     271        }
     272       
     273a.fc-event {
     274        text-decoration: none;
     275        }
     276       
     277.fc-rtl .fc-event {
     278        text-align: right;
     279        }
     280       
     281.fc-event-skin {
     282        border-color: #36c;     /* default BORDER color */
    248283        background-color: #36c; /* default BACKGROUND color */
    249284        color: #fff;            /* default TEXT color */
    250285        }
    251286       
    252         /* Use the 'className' CalEvent property and the following
    253          * example CSS to change event color on a per-event basis:
    254          *
    255          * .myclass,
    256          * .fc-agenda .myclass .fc-event-time,
    257          * .myclass a {
    258          *     background-color: black;
    259          *     border-color: black;
    260          *     color: red;
    261          *     }
    262          */
    263          
    264 .fc-event {
    265         text-align: left;
    266         }
    267        
    268 .fc-event a {
     287.fc-event-inner {
     288        position: relative;
     289        width: 100%;
     290        height: 100%;
     291        border-style: solid;
     292        border-width: 0;
    269293        overflow: hidden;
    270         font-size: .85em;
    271         text-decoration: none;
    272         cursor: pointer;
    273         }
    274        
    275 .fc-event-editable {
    276         cursor: pointer;
    277294        }
    278295       
     
    282299        }
    283300       
    284 /* for fake rounded corners */
    285 
    286 .fc-event a {
    287         display: block;
    288         position: relative;
    289         width: 100%;
    290         height: 100%;
    291         }
    292        
    293 /* right-to-left */
    294 
    295 .fc-rtl .fc-event a {
    296         text-align: right;
    297         }
    298        
    299 /* resizable */
    300        
    301 .fc .ui-resizable-handle { /*** TODO: don't use ui-resizable anoymore, change class ***/
     301.fc .ui-resizable-handle { /*** TODO: don't use ui-resizable anymore, change class ***/
    302302        display: block;
    303303        position: absolute;
    304304        z-index: 99999;
    305         border: 0 !important; /* important overrides pre jquery ui 1.7 styles */
    306         background: url(data:image/gif;base64,AAAA) !important; /* hover fix for IE */
     305        overflow: hidden; /* hacky spaces (IE6/7) */
     306        font-size: 300%;  /* */
     307        line-height: 50%; /* */
    307308        }
    308309       
     
    315316        border-width: 1px 0;
    316317        margin-bottom: 1px;
    317         }
    318        
    319 .fc-event-hori a {
    320         border-width: 0;
    321         }
    322        
    323 /* for fake rounded corners */
    324        
    325 .fc-content .fc-corner-left {
    326         margin-left: 1px;
    327         }
    328        
    329 .fc-content .fc-corner-left a {
    330         margin-left: -1px;
    331         border-left-width: 1px;
    332         }
    333        
    334 .fc-content .fc-corner-right {
    335         margin-right: 1px;
    336         }
    337        
    338 .fc-content .fc-corner-right a {
    339         margin-right: -1px;
    340         border-right-width: 1px;
    341318        }
    342319       
     
    365342       
    366343       
     344/* Fake Rounded Corners (for buttons and events)
     345------------------------------------------------------------*/
     346       
     347.fc-corner-left {
     348        margin-left: 1px;
     349        }
     350       
     351.fc-corner-left .fc-button-inner,
     352.fc-corner-left .fc-event-inner {
     353        margin-left: -1px;
     354        }
     355       
     356.fc-corner-right {
     357        margin-right: 1px;
     358        }
     359       
     360.fc-corner-right .fc-button-inner,
     361.fc-corner-right .fc-event-inner {
     362        margin-right: -1px;
     363        }
     364       
     365.fc-corner-top {
     366        margin-top: 1px;
     367        }
     368       
     369.fc-corner-top .fc-event-inner {
     370        margin-top: -1px;
     371        }
     372       
     373.fc-corner-bottom {
     374        margin-bottom: 1px;
     375        }
     376       
     377.fc-corner-bottom .fc-event-inner {
     378        margin-bottom: -1px;
     379        }
     380       
     381       
     382       
     383/* Fake Rounded Corners SPECIFICALLY FOR EVENTS
     384-----------------------------------------------------------------*/
     385       
     386.fc-corner-left .fc-event-inner {
     387        border-left-width: 1px;
     388        }
     389       
     390.fc-corner-right .fc-event-inner {
     391        border-right-width: 1px;
     392        }
     393       
     394.fc-corner-top .fc-event-inner {
     395        border-top-width: 1px;
     396        }
     397       
     398.fc-corner-bottom .fc-event-inner {
     399        border-bottom-width: 1px;
     400        }
     401       
     402       
     403       
     404/* Reusable Separate-border Table
     405------------------------------------------------------------*/
     406
     407table.fc-border-separate {
     408        border-collapse: separate;
     409        }
     410       
     411.fc-border-separate th,
     412.fc-border-separate td {
     413        border-width: 1px 0 0 1px;
     414        }
     415       
     416.fc-border-separate th.fc-last,
     417.fc-border-separate td.fc-last {
     418        border-right-width: 1px;
     419        }
     420       
     421.fc-border-separate tr.fc-last th,
     422.fc-border-separate tr.fc-last td {
     423        border-bottom-width: 1px;
     424        }
     425       
     426.fc-border-separate tbody tr.fc-first td,
     427.fc-border-separate tbody tr.fc-first th {
     428        border-top-width: 0;
     429        }
     430       
     431       
    367432
    368433/* Month View, Basic Week View, Basic Day View
    369434------------------------------------------------------------------------*/
    370435
    371 .fc-grid table {
    372         width: 100%;
    373         }
    374        
    375 .fc .fc-grid th {
    376         border-width: 0 0 0 1px;
     436.fc-grid th {
    377437        text-align: center;
    378         }
    379        
    380 .fc .fc-grid td {
    381         border-width: 1px 0 0 1px;
    382         }
    383        
    384 .fc-grid th.fc-leftmost,
    385 .fc-grid td.fc-leftmost {
    386         border-left: 0;
    387438        }
    388439       
     
    402453.fc-grid .fc-day-content {
    403454        clear: both;
    404         padding: 2px 2px 0; /* distance between events and day edges */
     455        padding: 2px 2px 1px; /* distance between events and day edges */
    405456        }
    406457       
     
    412463       
    413464/* right-to-left */
    414 
    415 .fc-rtl .fc-grid {
    416         direction: rtl;
    417         }
    418465       
    419466.fc-rtl .fc-grid .fc-day-number {
     
    425472        }
    426473       
     474       
     475
    427476/* Agenda Week View, Agenda Day View
    428477------------------------------------------------------------------------*/
    429478
    430 .fc .fc-agenda th,
    431 .fc .fc-agenda td {
    432         border-width: 1px 0 0 1px;
    433         }
    434        
    435 .fc .fc-agenda .fc-leftmost {
    436         border-left: 0;
    437         }
    438        
    439 .fc-agenda tr.fc-first th,
    440 .fc-agenda tr.fc-first td {
    441         border-top: 0;
    442         }
    443        
    444 .fc-agenda-head tr.fc-last th {
    445         border-bottom-width: 1px;
    446         }
    447        
    448 .fc .fc-agenda-head td,
    449 .fc .fc-agenda-body td {
    450         background: none;
    451         }
    452        
    453 .fc-agenda-head th {
     479.fc-agenda table {
     480        border-collapse: separate;
     481        }
     482       
     483.fc-agenda-days th {
    454484        text-align: center;
    455485        }
    456486       
    457 /* the time axis running down the left side */
    458        
    459 .fc-agenda .fc-axis {
     487.fc-agenda .fc-agenda-axis {
    460488        width: 50px;
    461489        padding: 0 4px;
    462490        vertical-align: middle;
     491        text-align: right;
    463492        white-space: nowrap;
    464         text-align: right;
    465493        font-weight: normal;
    466494        }
    467495       
    468 /* all-day event cells at top */
    469        
    470 .fc-agenda-head tr.fc-all-day th {
    471         height: 35px;
    472         }
    473        
    474 .fc-agenda-head td {
    475         padding-bottom: 10px;
    476         }
    477        
    478 .fc .fc-divider div {
    479         font-size: 1px; /* for IE6/7 */
     496.fc-agenda .fc-day-content {
     497        padding: 2px 2px 1px;
     498        }
     499       
     500/* make axis border take precedence */
     501       
     502.fc-agenda-days .fc-agenda-axis {
     503        border-right-width: 1px;
     504        }
     505       
     506.fc-agenda-days .fc-col0 {
     507        border-left-width: 0;
     508        }
     509       
     510/* all-day area */
     511       
     512.fc-agenda-allday th {
     513        border-width: 0 1px;
     514        }
     515       
     516.fc-agenda-allday .fc-day-content {
     517        min-height: 34px; /* TODO: doesnt work well in quirksmode */
     518        _height: 34px;
     519        }
     520       
     521/* divider (between all-day and slots) */
     522       
     523.fc-agenda-divider-inner {
    480524        height: 2px;
    481         }
    482        
    483 .fc .fc-divider .fc-state-default {
    484         background: #eee; /* color for divider between all-day and time-slot events */
    485         }
    486 
    487 /* body styles */
    488        
    489 .fc .fc-agenda-body td div {
    490         height: 20px; /* slot height */
    491         }
    492        
    493 .fc .fc-agenda-body tr.fc-minor th,
    494 .fc .fc-agenda-body tr.fc-minor td {
     525        overflow: hidden;
     526        }
     527       
     528.fc-widget-header .fc-agenda-divider-inner {
     529        background: #eee;
     530        }
     531       
     532/* slot rows */
     533       
     534.fc-agenda-slots th {
     535        border-width: 1px 1px 0;
     536        }
     537       
     538.fc-agenda-slots td {
     539        border-width: 1px 0 0;
     540        background: none;
     541        }
     542       
     543.fc-agenda-slots td div {
     544        height: 20px;
     545        }
     546       
     547.fc-agenda-slots tr.fc-slot0 th,
     548.fc-agenda-slots tr.fc-slot0 td {
     549        border-top-width: 0;
     550        }
     551
     552.fc-agenda-slots tr.fc-minor th,
     553.fc-agenda-slots tr.fc-minor td {
    495554        border-top-style: dotted;
    496555        }
    497556       
    498 .fc-agenda .fc-day-content {
    499         padding: 2px 2px 0; /* distance between events and day edges */
    500         }
    501        
    502 /* vertical background columns */
    503 
    504 .fc .fc-agenda-bg .ui-state-highlight {
    505         background-image: none; /* tall column, don't want repeating background image */
     557.fc-agenda-slots tr.fc-minor th.ui-widget-header {
     558        *border-top-style: solid; /* doesn't work with background in IE6/7 */
    506559        }
    507560       
     
    515568        }
    516569       
    517 .fc-event-vert a {
    518         border-width: 0;
    519         }
    520        
    521 /* for fake rounded corners */
    522        
    523 .fc-content .fc-corner-top {
    524         margin-top: 1px;
    525         }
    526        
    527 .fc-content .fc-corner-top a {
    528         margin-top: -1px;
    529         border-top-width: 1px;
    530         }
    531        
    532 .fc-content .fc-corner-bottom {
    533         margin-bottom: 1px;
    534         }
    535        
    536 .fc-content .fc-corner-bottom a {
    537         margin-bottom: -1px;
    538         border-bottom-width: 1px;
    539         }
    540        
    541 /* event content */
    542        
    543 .fc-event-vert span {
    544         display: block;
     570.fc-event-vert .fc-event-head,
     571.fc-event-vert .fc-event-content {
    545572        position: relative;
    546573        z-index: 2;
    547         }
    548        
    549 .fc-event-vert span.fc-event-time {
     574        width: 100%;
     575        overflow: hidden;
     576        }
     577       
     578.fc-event-vert .fc-event-time {
    550579        white-space: nowrap;
    551         _white-space: normal;
    552         overflow: hidden;
    553         border: 0;
    554580        font-size: 10px;
    555581        }
    556582       
    557 .fc-event-vert span.fc-event-title {
    558         line-height: 13px;
    559         }
    560        
    561 .fc-event-vert span.fc-event-bg { /* makes the event lighter w/ a semi-transparent overlay  */
     583.fc-event-vert .fc-event-bg { /* makes the event lighter w/ a semi-transparent overlay  */
    562584        position: absolute;
    563585        z-index: 1;
     
    568590        background: #fff;
    569591        opacity: .3;
    570         filter: alpha(opacity=30); /* for IE */
     592        filter: alpha(opacity=30);
     593        }
     594       
     595.fc .ui-draggable-dragging .fc-event-bg, /* TODO: something nicer like .fc-opacity */
     596.fc-select-helper .fc-event-bg {
     597        display: none\9; /* for IE6/7/8. nested opacity filters while dragging don't work */
    571598        }
    572599       
     
    577604        width: 100%      !important;
    578605        height: 8px      !important;
     606        overflow: hidden !important;
    579607        line-height: 8px !important;
    580608        font-size: 11px  !important;
     
    584612        }
    585613       
    586        
     614.fc-agenda .ui-resizable-resizing { /* TODO: better selector */
     615        _overflow: hidden;
     616        }
     617       
     618       
  • _plugins_/fullcalendar/css_fullcalendar.html

    r46420 r53497  
    11#CACHE{3600*24*30}
    22#HTTP_HEADER{Content-Type: text/css;}
    3 <?php
    4         $res = sql_select('*', 'spip_fullcalendar_styles');
    5         while ( $row = sql_fetch($res))
    6                 $CSS.=".f_".$row['id_style'].", .fc-agenda .f_".$row['id_style']." .fc-event-time, .f_".$row['id_style']." a {background-color:".$row['bgcolor'].";border-color:".$row['bordercolor'].";color:".$row['textcolor'].";}\n";
    7         sql_free($res);
    8         print $CSS;
    9 ?>
     3<B_style_css>
     4<BOUCLE_style_css(spip_fullcalendar_styles)>.f_#ID_STYLE, .fc-agenda .f_#ID_STYLE .fc-event-skin, .f_#ID_STYLE a {background-color:#BGCOLOR;border-color:#BORDERCOLOR;color:#TEXTCOLOR;}
     5</BOUCLE_style_css>
     6</B_style_css>
  • _plugins_/fullcalendar/exec/fullcalendar_add.php

    r46420 r53497  
    88 *
    99 * Auteur : Grégory PASCAL - ngombe at gmail dot com
    10  * Modifs : 06/04/2011
     10 * Modifs : 10/10/2011
    1111 *
    1212 */
     
    3232  ){
    3333        sql_insert("spip_fullcalendar_main","(type, nom)","(".sql_quote($_POST['CalSource']).", ".sql_quote($_POST['CalName']).")");
    34         $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Ajout d'un nouveau calendrier.</center><br/>";
     34        $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:calendar_add').".</center><br/>";
    3535 }
    3636
     
    4343  ){
    4444        sql_update('spip_fullcalendar_main', array('nom' => sql_quote($_POST['CalName'])), "id_fullcalendar=".sql_quote(intval($_POST['id_calendrier'])) );
    45         $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Modification d'un calendrier.</center><br/>";
     45        $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:calendar_edit').".</center><br/>";
    4646 }
    4747
     
    5555  ){
    5656        sql_delete("spip_fullcalendar_events", "id_fullcalendar=".$_POST['id_calendrier']);
    57         $INFO="Efface les évènements du calendrier ".$_POST['id_calendrier']."<br/><br/>";
     57        $INFO=_T('fullcalendar:calendar_del_events')." ".$_POST['id_calendrier']."<br/><br/>";
    5858        sql_delete("spip_fullcalendar_main", "id_fullcalendar=".$_POST['id_calendrier']);
    59         $INFO.="Efface le calendrier ".$_POST['id_calendrier']."<br/><br/>";
     59        $INFO.=_T('fullcalendar:calendar_del_events')." ".$_POST['id_calendrier']."<br/><br/>";
    6060 }
    6161
     
    6363
    6464 $NOM='';
    65  $BUTTON='<input type="submit" name="ajouter" value=" Ajouter " class="fondo" />';
     65 $BUTTON='<input type="submit" name="ajouter" value=" '._T('fullcalendar:add').' " class="fondo" />';
    6666 $SOURCE='<select name="CalSource" id="CalSource">
    67                         <option value="mysql">Base de donnée MySQL locale</option>
    68                         <option value="google">Google Agenda publique</option>
    69                         <option value="article">Articles par mots clés et date de rédaction antérieure</option>
     67                        <option value="mysql">'._T('fullcalendar:source_mysql').'</option>
     68                        <option value="article">'._T('fullcalendar:source_art').'</option>
     69                        <option value="rub">'._T('fullcalendar:source_rub').'</option>
     70                        <option value="google">'._T('fullcalendar:source_google').'</option>
    7071                </select>';
    7172 $ACTION='add';
     73 $TEXT=_T('fullcalendar:calendar_add');
    7274 $ID='';
    7375
     
    7880
    7981 if(!$num_calendar) $INFO="
    80  <b>Bienvenu dans FullCalendar pour SPIP !</b><br/>
    81  <br/>Commencez par créer votre premier calendrier en utilisant le formulaire ci-contre.</center><br/>
     82 <b>"._T('fullcalendar:welcome_title')."</b><br/>
     83 <br/>"._T('fullcalendar:welcome_text')."</center><br/>
    8284 ";
    8385 else {
    8486        $LISTE='<br/>';
    8587        $class='row_odd';
    86         $INFO.= "<center>Vous avez ".$num_calendar." calendrier(s)</center><br/>";
     88        $INFO.= "<center>"._T('fullcalendar:vous_avez')." ".$num_calendar." ";
     89        $INFO.=($num_calendar==1)?_T('fullcalendar:calendar'):_T('fullcalendar:calendars');
     90        $INFO.="</center><br/>";
    8791        $HTML = "
    8892
     
    9195        function EffacerCalendrier(id){
    9296                if(!document.getElementById) return false;
    93                 if(confirm('Effacer ce calendrier ?')){
     97                if(confirm('"._T('fullcalendar:calendar_del')." ?')){
    9498                        document.Formulaire.id_calendrier.value=id;
    9599                        document.Formulaire.action_to_take.value='del';
     
    111115
    112116
    113         <table class='spip' style='width:100%'><tr class='row_first'><th>Nom</th><th>Source</th><th>balise</th><th>&nbsp;</th></tr>";
     117        <table class='spip' style='width:100%'>
     118        <tr class='row_first'>
     119                <th>"._T('fullcalendar:calendar')."</th>
     120                <th>Source</th>
     121                <th>"._T('fullcalendar:shortcut')."</th>
     122                <th>&nbsp;</th>
     123        </tr>";
     124
     125        $icons['mysql']="<img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/mysql-24.png'>";
     126        $icons['google']="<img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/google-24.png'>";
     127        $icons['rub']='<img src="../prive/images/rubrique-24.gif">';
     128        $icons['article']='<img src="../prive/images/mot-cle-24.gif">';
     129
    114130        while ($row = sql_fetch($res)) {
    115131
    116132                $id   = $row['id_fullcalendar'];
    117133                $type = $row['type'];
     134                $icon=$icons[$type];
    118135                $nom  = $row['nom'];
    119136
     
    123140                ){
    124141                        $NOM=$nom;
    125                         $BUTTON='<input type="submit" name="enregistrer" value=" Enregistrer " class="fondo" />';
     142                        $BUTTON='<input type="submit" name="enregistrer" value=" '._T('bouton_enregistrer').' " class="fondo" />
     143                        <input type="submit" name="cancel" value=" '._T('bouton_annuler').' " class="fondo" />';
    126144                        $SOURCE='<b>'.$type.'</b>';
    127145                        $ACTION='update';
    128146                        $ID=$id;
     147                        $TEXT=_T('fullcalendar:calendar_edit');
    129148                }
    130149
     
    134153                <tr class='".$class."'>
    135154                        <td style='text-align:center'><b>".$nom."</b></td>
    136                         <td style='text-align:center'>".$type."</td>
    137                         <td style='text-align:center'>&lt;fullcalendar".$id."&gt;</td>
     155                        <td style='text-align:center'>".$icon."</td>
     156                        <td style='text-align:center'><b>&lt;fullcalendar".$id."&gt;</b></td>
    138157                        <td style='text-align:center;width:44px;'>
    139                                 <a href=\"javascript:ModifierCalendrier('".$id."')\"><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/calendar_edit.png'></a> &nbsp;
    140                                 <a href=\"javascript:EffacerCalendrier('".$id."')\"><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/calendar_remove.png'></a>
     158                                <a href=\"javascript:ModifierCalendrier('".$id."')\"><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/calendar_edit.png'></a> &nbsp;
     159                                <a href=\"javascript:EffacerCalendrier('".$id."')\"><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/calendar_remove.png'></a>
    141160                        </td>
    142161                </tr>";
     
    148167
    149168 $commencer_page = charger_fonction('commencer_page', 'inc');
    150  print $commencer_page(_T('Fullcalendar'), "", "") ;
     169 print $commencer_page(_T('fullcalendar:fullcalendar'), "", "") ;
    151170 print "<br/><br/>";
    152  print gros_titre(_T('Gestion des calendriers'),'',false);
     171 print gros_titre(_T('fullcalendar:fullcalendar')." : "._T('fullcalendar:gestion_calendriers'),'',false);
    153172 print debut_gauche ("",true);
    154173
    155174 print debut_boite_info(true);
    156  print "<center><b>"._T('FullCalendar')."</b></center>";
    157  print "<br/><center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/fullcalendar.jpg'></center><br/>";
     175 print "<center><b>"._T('fullcalendar:fullcalendar')."</b></center>";
     176 print "<br/><center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/fullcalendar.jpg'></center><br/>";
    158177 print $INFO;
    159178 print fin_boite_info(true);
     
    161180 print debut_cadre_enfonce('',true,'','','');
    162181 print "<table class=\"cellule-h-table\" style=\"vertical-align: middle;\" cellpadding=\"0\"><tbody><tr>
    163  <td><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\"><span class=\"cell-i\"><img src='../plugins/cfg/cfg-22.png' alt=\"CFG : configuration\"></span></a></td>
    164  <td class=\"cellule-h-lien\"><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\">CFG - configuration</a></td>
     182 <td><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\"><span class=\"cell-i\"><img src='../plugins/cfg/cfg-22.png' alt=\"CFG : "._T('fullcalendar:configuration')."\"></span></a></td>
     183 <td class=\"cellule-h-lien\"><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\">CFG - "._T('fullcalendar:configuration')."</a></td>
    165184 </tr></tbody></table>";
    166185 print fin_cadre_enfonce(true);
     
    168187 print debut_cadre_enfonce('',true,'','','');
    169188 print "<table class=\"cellule-h-table\" style=\"vertical-align: middle;\" cellpadding=\"0\"><tbody><tr>
    170  <td><a href=\"?exec=fullcalendar_css\" class=\"cellule-h\"><span class=\"cell-i\"><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/edit_css.png' alt=\"Styles de fullcalendar : configuration\"></span></a></td>
    171  <td class=\"cellule-h-lien\"><a href=\"?exec=fullcalendar_css\" class=\"cellule-h\">CSS - configuration</a></td>
     189 <td><a href=\"?exec=fullcalendar_css\" class=\"cellule-h\"><span class=\"cell-i\"><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/edit_css.png' alt=\"CSS : "._T('fullcalendar:configuration')."\"></span></a></td>
     190 <td class=\"cellule-h-lien\"><a href=\"?exec=fullcalendar_css\" class=\"cellule-h\">CSS - "._T('fullcalendar:configuration')."</a></td>
    172191 </tr></tbody></table>";
    173192 print fin_cadre_enfonce(true);
    174193
    175194 if(strlen($LISTE)){
    176         print debut_cadre_enfonce('',true,'',_T('Vos calendriers'),'');
     195        print debut_cadre_enfonce('',true,'',_T('fullcalendar:vos_calendriers'),'');
    177196        print $LISTE;
    178197        print fin_cadre_enfonce(true);
     
    181200 print creer_colonne_droite('',true);
    182201 print debut_droite("", true);
    183  print debut_cadre_trait_couleur("", true, "", $titre=_T('JQUERY FullCalendar pour SPIP'),"","");
     202 print debut_cadre_trait_couleur("", true, "", $titre=_T('fullcalendar:plugin_name'),"","");
    184203
    185204# INTERFACE D'AJOUT
     
    191210 <input type="hidden" name="action_to_take" value="'.$ACTION.'">
    192211 <input type="hidden" name="id_calendrier" value="'.$ID.'">
    193         <p><label> Créer un nouveau calendrier : <input type="text" name="CalName" style="width:60%" value="'.$NOM.'"></label></p>
    194         <p><label> Source pour les évènements de ce calendrier : '.$SOURCE.'</label>
     212        <p><label>'.$TEXT.' : <input type="text" name="CalName" style="width:60%" value="'.$NOM.'"></label></p>
     213        <p><label>'._T('fullcalendar:source_select').' : '.$SOURCE.'</label>
    195214        </p>
    196215   </div>
  • _plugins_/fullcalendar/exec/fullcalendar_css.php

    r46420 r53497  
    88 *
    99 * Auteur : Grégory PASCAL - ngombe at gmail dot com
    10  * Modifs : 06/04/2011
     10 * Modifs : 10/10/2011
    1111 *
    1212 */
     
    3434  && strlen($_POST['textcolor'])
    3535  ){
    36         $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Ajout d'un nouveau style.</center><br/>";
     36        $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:style_add').".</center><br/>";
    3737        sql_insert("spip_fullcalendar_styles",
    3838        "(titre, bordercolor, bgcolor, textcolor)",
     
    5757  && $_POST['id_style']
    5858  ){
    59         $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Modification d'un style.</center><br/>";
     59        $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:style_edit').".</center><br/>";
    6060        sql_update('spip_fullcalendar_styles',
    6161                array(
     
    7575  && $_POST['id_style']
    7676  ){
    77         $INFO.="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Efface le style ".$_POST['id_style']."</center><br/>";
     77        $INFO.="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:style_del')." ".$_POST['id_style']."</center><br/>";
    7878        sql_delete('spip_fullcalendar_styles', "id_style=".$_POST['id_style']);
    7979 }
     
    9696 $TEXT='#141666';
    9797 $BG='#becde9';
    98  $BUTTON='<input type="submit" name="ajouter" value=" Ajouter " class="fondo" />';
     98 $BUTTON='<input type="submit" name="ajouter" value=" '._T('fullcalendar:add').' " class="fondo" />';
    9999
    100100 # Récupère les styles
     
    102102 $res = sql_select('*', 'spip_fullcalendar_styles');
    103103 $num_style = sql_count($res);
    104  if(!$num_style) $INFO="<b>Vous n'avez pas encore définit de style !</b><br/><br/>Les définition de styles permettent de modifier l'apparence des évènements dans les agendas qui utilisent MySQL comme source de donnée.";
     104 if(!$num_style) $INFO="<b>"._T('fullcalendar:style_welcome')."</b><br/><br/>"._T('fullcalendar:style_info');
    105105 else {
    106106
    107         $INFO.= "<center>Vous avez ".$num_style." styles(s)</center><br/>";
     107        $INFO.= "<center>"._T('fullcalendar:vous_avez')." ".$num_style." "._T('fullcalendar:styles')."</center><br/>";
    108108        $HTML = "
    109109
     
    150150                         $TEXT=$text;
    151151                         $BG=$bg;
    152                          $BUTTON='<input type="submit" name="enregistrer" value=" Enregistrer " class="fondo" />';
     152                         $BUTTON='<input type="submit" name="enregistrer" value=" '._T('bouton_enregistrer').' " class="fondo" />';
    153153                }
    154154
     
    156156                $rw = sql_count($rs);
    157157
    158                 if(!$rw) $DELETE="<a href=\"javascript:EffacerStyle('".$id."')\"><img style=\"margin-left:10px;\" src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/css_remove.png' align='right'></a>";
     158                if(!$rw) $DELETE="<a href=\"javascript:EffacerStyle('".$id."')\"><img style=\"margin-left:10px;\" src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/css_remove.png' align='right'></a>";
    159159                else {
    160                         $DELETE="&nbsp;&nbsp;Lié à ".$rw." évènement";
     160                        $DELETE="&nbsp;&nbsp;"._T('fullcalendar:linked_to')." ".$rw." "._T('fullcalendar:event');
    161161                        $DELETE.=($rw>1)?'s.':'.';
    162162                }
     
    167167                        <b>".$nom."</b>
    168168                        ".$DELETE."
    169                         <a href=\"javascript:ModifierStyle('".$id."')\">&nbsp;<img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/css_edit.png' align='right'></a>
     169                        <a href=\"javascript:ModifierStyle('".$id."')\">&nbsp;<img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/css_edit.png' align='right'></a>
    170170                </div><br/>";
    171171
     
    175175
    176176 $commencer_page = charger_fonction('commencer_page', 'inc');
    177  print $commencer_page(_T('Fullcalendar'), "documents", "forms") ;
     177 print $commencer_page(_T('fullcalendar:fullcalendar'), "documents", "forms") ;
    178178 print "<br/><br/>";
    179  print gros_titre(_T('Gestion du style des évènements'),'',false);
     179 print gros_titre(_T('fullcalendar:gestion_styles'),'',false);
    180180 print debut_gauche ("",true);
    181181
    182182 print debut_boite_info(true);
    183  print "<center><b>"._T('FullCalendar')."</b></center>";
    184  print "<br/><center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/fullcalendar.jpg'></center><br/>";
     183 print "<center><b>"._T('fullcalendar:fullcalendar')."</b></center>";
     184 print "<br/><center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/fullcalendar.jpg'></center><br/>";
    185185 print $INFO;
    186186 print fin_boite_info(true);
     
    188188 print debut_cadre_enfonce('',true,'','','');
    189189 print "<table class=\"cellule-h-table\" style=\"vertical-align: middle;\" cellpadding=\"0\"><tbody><tr>
    190  <td><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\"><span class=\"cell-i\"><img src='../plugins/cfg/cfg-22.png' alt=\"CFG : configuration\"></span></a></td>
    191  <td class=\"cellule-h-lien\"><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\">CFG - configuration</a></td>
     190 <td><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\"><span class=\"cell-i\"><img src='../plugins/cfg/cfg-22.png' alt=\"CFG : "._T('fullcalendar:configuration')."\"></span></a></td>
     191 <td class=\"cellule-h-lien\"><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\">CFG - "._T('fullcalendar:configuration')."</a></td>
    192192 </tr></tbody></table>";
    193193 print fin_cadre_enfonce(true);
     
    195195 print debut_cadre_enfonce('',true,'','','');
    196196 print "<table class=\"cellule-h-table\" style=\"vertical-align: middle;\" cellpadding=\"0\"><tbody><tr>
    197  <td><a href=\"?exec=fullcalendar_add\" class=\"cellule-h\"><span class=\"cell-i\"><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/calendar.png' alt=\"Agenda fullcalendar : configuration\"></span></a></td>
    198  <td class=\"cellule-h-lien\"><a href=\"?exec=fullcalendar_add\" class=\"cellule-h\">FullCalendar - Gestion</a></td>
     197 <td><a href=\"?exec=fullcalendar_add\" class=\"cellule-h\"><span class=\"cell-i\"><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/calendar.png' alt=\""._T('fullcalendar:fullcalendar')." : "._T('fullcalendar:gestion')."\"></span></a></td>
     198 <td class=\"cellule-h-lien\"><a href=\"?exec=fullcalendar_add\" class=\"cellule-h\">FullCalendar - "._T('fullcalendar:gestion')."</a></td>
    199199 </tr></tbody></table>";
    200200 print fin_cadre_enfonce(true);
    201201
    202202 if(strlen($LISTE)){
    203         print debut_cadre_enfonce('',true,'',_T('Vos calendriers'),'');
     203        print debut_cadre_enfonce('',true,'',_T('fullcalendar:vos_calendriers'),'');
    204204        print $LISTE;
    205205        print fin_cadre_enfonce(true);
     
    208208 print creer_colonne_droite('',true);
    209209 print debut_droite("", true);
    210  print debut_cadre_trait_couleur("", true, "", $titre=_T('Les CSS de FullCalendar pour SPIP'),"","");
     210 print debut_cadre_trait_couleur("", true, "", $titre=_T('fullcalendar:style_title'),"","");
    211211
    212212# INTERFACE D'AJOUT
     
    218218 <input type="hidden" name="action_to_take" value="'.$ACTION.'">
    219219 <input type="hidden" name="id_style" value="'.$ID_STYLE.'">
    220         <p><label> Créer un nouveau style : <input type="text" name="StyleName" style="width:60%" value="'.$NOM.'"></label></p>
    221         <p><label>Couleurs des bordures <input type="text" name="bordercolor" class="palette" id="_ir_bordercolor" size="7" value="'.$BORDER.'" /></label></p>
    222         <p><label>Couleur du fond <input type="text" name="bgcolor" class="palette" id="_ir_bgcolor" size="7" value="'.$BG.'" /></label></p>
    223         <p><label>Couleur du texte <input type="text" name="textcolor" class="palette" id="_ir_textcolor" size="7" value="'.$TEXT.'" /></label></p>
     220        <p><label>'._T('fullcalendar:style_name').' : <input type="text" name="StyleName" style="width:60%" value="'.$NOM.'"></label></p>
     221        <p><label>'._T('fullcalendar:style_border').' : <input type="text" name="bordercolor" class="palette" id="_ir_bordercolor" size="7" value="'.$BORDER.'" /></label></p>
     222        <p><label>'._T('fullcalendar:style_background').' : <input type="text" name="bgcolor" class="palette" id="_ir_bgcolor" size="7" value="'.$BG.'" /></label></p>
     223        <p><label>'._T('fullcalendar:style_text').' : <input type="text" name="textcolor" class="palette" id="_ir_textcolor" size="7" value="'.$TEXT.'" /></label></p>
    224224   </div>
    225225        <div class="boutons">'.$BUTTON.'</div>
     
    231231
    232232 if(strlen($HTML)){
    233         print debut_cadre_relief("", false,"", $titre = _T('Vos styles'));
     233        print debut_cadre_relief("", false,"", $titre = _T('fullcalendar:vos_styles'));
    234234        print $HTML;
    235235        print fin_cadre_relief(false);
  • _plugins_/fullcalendar/exec/fullcalendar_edit.php

    r46420 r53497  
    88 *
    99 * Auteur : Grégory PASCAL - ngombe at gmail dot com
    10  * Modifs : 06/04/2011
     10 * Modifs : 10/10/2011
    1111 *
    1212 */
     
    5252                && strlen($_POST['id_mot'])
    5353        ){
    54                 $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Ajout d'une mot clé pour cet agenda.</center><br/>";
     54                $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:action_mot_add').".</center><br/>";
    5555                sql_insert('spip_fullcalendar_events', '(id_fullcalendar, lien)', "(".sql_quote(intval($_POST['id_calendrier'])).", ".sql_quote(intval($_POST['id_mot'])).")");
    5656        }
     
    6666                && strlen($_POST['id_mot'])
    6767        ){
    68                 $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Mise à jour du mot clé pour cet agenda.</center><br/>";
     68                $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:action_mot_edit').".</center><br/>";
    6969                sql_update('spip_fullcalendar_events', array('lien' => sql_quote(intval($_POST['id_mot'])) ), "id_fullcalendar=".sql_quote(intval($_POST['id_calendrier'])) );
     70        }
     71
     72        ########################
     73        # Ajout d'une rubrique #
     74        ########################
     75
     76        if(
     77                        $_POST['action_to_take']=='add_rubrique'
     78                        && $_POST['ajouter']
     79                        && $_POST['id_calendrier']
     80                        && strlen($_POST['id_rubrique'])
     81        ){
     82                        $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:action_rub_add').".</center><br/>";
     83                        sql_insert('spip_fullcalendar_events', '(id_fullcalendar, lien)', "(".sql_quote(intval($_POST['id_calendrier'])).", ".sql_quote(intval($_POST['id_rubrique'])).")");
     84        }
     85
     86        ########################
     87        # Modifier la rubrique #
     88        ########################
     89
     90        if(
     91                        $_POST['action_to_take']=='update_rubrique'
     92                        && $_POST['ajouter']
     93                        && $_POST['id_calendrier']
     94                        && strlen($_POST['id_rubrique'])
     95        ){
     96                        $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:action_rub_edit').".</center><br/>";
     97                        sql_update('spip_fullcalendar_events', array('lien' => sql_quote(intval($_POST['id_rubrique'])) ), "id_fullcalendar=".sql_quote(intval($_POST['id_calendrier'])) );
    7098        }
    7199
     
    80108                && strlen($_POST['gcalID'])
    81109        ){
    82                 $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Ajout d'une clé Google Agenda.</center><br/>";
     110                $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:action_key_add').".</center><br/>";
    83111                sql_insert('spip_fullcalendar_events', '(id_fullcalendar, lien)', "(".sql_quote(intval($_POST['id_calendrier'])).", ".sql_quote($_POST['gcalID']).")");
    84112        }
     
    94122                && strlen($_POST['gcalID'])
    95123        ){
    96                 $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Mise à jour de la clé pour cet agenda.</center><br/>";
     124                $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:action_key_edit').".</center><br/>";
    97125                sql_update('spip_fullcalendar_events', array('lien' => sql_quote(trim($_POST['gcalID'])) ), "id_fullcalendar=".sql_quote(intval($_POST['id_calendrier'])) );
    98126        }
     
    109137
    110138                $t = explode('/',$_POST['Date']);
    111                 $date = $t[2].'-'.$t[1].'-'.$t[0];
     139                $date = $t['2'].'-'.$t['1'].'-'.$t['0'];
    112140                $t = explode('/',$_POST['Date_Fin']);
    113                 $date_fin = $t[2].'-'.$t[1].'-'.$t[0];
     141                $date_fin = $t['2'].'-'.$t['1'].'-'.$t['0'];
    114142                unset($t);
    115143
     
    125153                 )");
    126154
    127                 $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Ajout d'un nouvel évènement.</center><br/>";
     155                $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:event_add').".</center><br/>";
    128156
    129157        }
     
    158186                );
    159187
    160                 $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Modification d'un évènement.</center><br/>";
     188                $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:event_edit').".</center><br/>";
    161189
    162190        }
     
    172200        ){
    173201                sql_delete("spip_fullcalendar_events", "id_event=".sql_quote(intval($_POST['id_evenement'])) );
    174                 $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/ok.png'> &nbsp; Efface un évènement !</center><br/>";
     202                $INFO="<center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/ok.png'> &nbsp; "._T('fullcalendar:event_del')."</center><br/>";
    175203        }
    176204
     
    181209        $req = sql_select('*', 'spip_fullcalendar_main', 'id_fullcalendar='.$id_fullcalendar);
    182210        $num_calendar = sql_count($req);
    183         if(!$num_calendar) $INFO="<center style=\"color:red\">Ce calendrier n'existe plus !</center><br/>";
     211        if(!$num_calendar) $INFO="<center style=\"color:red\">"._T('fullcalendar:unknown_error')."</center><br/>";
    184212        else {
    185213
     
    194222                $req = sql_select('*', 'spip_fullcalendar_styles');
    195223                $num_style = sql_count($req);
    196                 if(!$num_style) $STYLES="Vous n'avez pas définit de style pour vos évènements, il seront donc affichés avec les couleurs par défaut. Pour créer un nouveau style d'évènement <a href=\"?exec=fullcalendar_css\">cliquez ici</a>.";
     224                if(!$num_style) $STYLES=_T('fullcalendar:no_style');
    197225                else {
    198                         $STYLES="<p>Style de l'évènement:<select name='id_style' id='id_style'>";
     226                        $STYLES="<p>"._T('fullcalendar:event_style').":<select name='id_style' id='id_style'>";
    199227                        while ($rw = sql_fetch($req)) {
    200228                                $STYLES.="<option value=\"".$rw['id_style']."\">".$rw['titre']."</option>";
     
    228256                        $START = substr($rw['start'],11,5);
    229257                        $END = substr($rw['end'],11,5);
    230                         $BUTTON = "<input type=\"submit\" name=\"enregistrer\" value=\" Enregistrer \" class=\"fondo\" />";
     258                        $BUTTON = "<input type=\"submit\" name=\"enregistrer\" value=\" "._T('bouton_enregistrer')." \" class=\"fondo\" />";
    231259
    232260                } else {
     
    238266                        $START=(strlen($_POST['HeureDebut'])==5)?stripslashes($_POST['HeureDebut']):Date("H:m");
    239267                        $END=(strlen($_POST['HeureFin'])==5)?stripslashes($_POST['HeureFin']):Date("H:m");
    240                         $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" Ajouter \" class=\"fondo\" />";
     268                        $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" "._T('fullcalendar:add')." \" class=\"fondo\" />";
    241269
    242270                }
     271
     272                        # Récupère les style css
     273                        $HTML.="<style type='text/css'>";
     274                        $result = sql_select('*', 'spip_fullcalendar_styles');
     275                        while ( $row = sql_fetch($result)){
     276                                $HTML.=".f_".$row['id_style'].", .f_".$row['id_style']." a {background-color:".$row['bgcolor'].";border-color:".$row['bordercolor'].";color:".$row['textcolor'].";}\n";
     277                                $style[$row['id_style']]['back'] = $row['bgcolor'];
     278                                $style[$row['id_style']]['text'] = $row['textcolor'];
     279                                $style[$row['id_style']]['bord'] = $row['bordercolor'];
     280                        }
     281                        sql_free($result);
     282                        $HTML.="</style>";
    243283
    244284                        # Récupère les évènements du calendrier MySQL
     
    247287                        $req = sql_select('*', 'spip_fullcalendar_events', 'id_fullcalendar='.$id_fullcalendar, '', 'start ASC');
    248288                        $num_events = sql_count($req);
    249                         if(!$num_events) $INFO.="Aucun évènement dans ce calendrier!";
     289                        if(!$num_events) $INFO.=_T('fullcalendar:no_event');
    250290                        else {
    251291
    252                                 $HTML="
     292                                $HTML.="
    253293
    254294                                <script type=\"text/javascript\">
     
    256296                                function EffacerEvenement(id){
    257297                                        if(!document.getElementById) return false;
    258                                         if(confirm('Effacer cet évènement ?')){
     298                                        if(confirm('"._T('fullcalendar:delete_event')."')){
    259299                                                document.Formulaire.id_evenement.value=id;
    260300                                                document.Formulaire.action_to_take.value='del';
     
    275315
    276316                                <table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">
    277                                         <tbody>
    278                                         <tr>
    279                                                 <th>Nom</th>
    280                                                 <th>Début</th>
    281                                                 <th>Fin</th>
     317                                        <tbody>";
     318
     319                                $entete="<tr>
     320                                                <th>"._T('fullcalendar:event_title')."</th>
     321                                                <th>"._T('fullcalendar:event_start')."</th>
     322                                                <th>"._T('fullcalendar:event_end')."</th>
    282323                                                <th>&nbsp;</th>
    283324                                        </tr>";
     
    296337                                        $fc_end = explode(':',substr($row['end'],11,5));
    297338
    298                                         if(strlen($row['id_style']))
    299                                                 $class=",className: 'f_".$row['id_style']."'";
     339                                        if($row['id_style']>0){
     340                                                $class=",backgroundColor: '".$style[$row['id_style']]['back']."', textColor: '".$style[$row['id_style']]['text']."', borderColor: '".$style[$row['id_style']]['bord']."'";
     341                                        } else $class='';
    300342
    301343                                        if(strlen(trim($row['lien']))){
     
    304346                                        }
    305347
     348                                        $bloc='';
     349                                        $t=substr($date,5,2);
     350                                        if($bloc_mois!=$t){
     351                                                $bloc_mois=$t;
     352                                                $annee=substr($date,0,4);
     353                                                $bloc.="<tr class='spip_large'><th colspan=4 style=\"border-bottom:1px solid #000;padding-top:4px;\">
     354                                                ".MyMonth($t)." ".$annee."
     355                                                </th></tr>".$entete;
     356                                        }
     357
    306358                                        $url="url:\"javascript:ModifierEvenement('".$row['id_event']."')\",";
    307359
    308360                                        $events.="{title: '".texte_script($row['titre'])."',start: new Date(".$fc_date[0].", ".($fc_date[1]-1).", ".$fc_date[2].", ".$fc_start[0].", ".$fc_start[1]."),end: new Date(".$fc_date_fin[0].", ".($fc_date_fin[1]-1).", ".$fc_date_fin[2].", ".$fc_end[0].", ".$fc_end[1]."),".$url." allDay: false ".$class."},";
    309361
    310                                         $HTML.= "<tr class=\"tr_liste\">
     362                                        $HTML.= "$bloc<tr class=\"tr_liste f_".$row['id_style']."\">
    311363                                                                <td class=\"verdana12\">".$lien_start."".$row['titre']."".$lien_end."</td>
    312364                                                                <td class=\"arial1\">".MyDateEnLettre ($date)."<br/>".$start."</td>
    313365                                                                <td class=\"arial1\">".MyDateEnLettre ($date_fin)."<br/>".$end."</td>
    314366                                                                <td>
    315                                                                         <a href=\"javascript:ModifierEvenement('".$row['id_event']."')\"><img src=\""._DIR_PLUGIN_FULLCALENDAR."img_pack/event_edit.png\"></a> &nbsp;
    316                                                                         <a href=\"javascript:EffacerEvenement('".$row['id_event']."')\"><img src=\""._DIR_PLUGIN_FULLCALENDAR."img_pack/event_remove.png\"></a>
     367                                                                        <a href=\"javascript:ModifierEvenement('".$row['id_event']."')\"><img src=\""._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/event_edit.png\"></a> &nbsp;
     368                                                                        <a href=\"javascript:EffacerEvenement('".$row['id_event']."')\"><img src=\""._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/event_remove.png\"></a>
    317369                                                                </td>
    318370                                                         </tr>
     
    325377                                $events=substr($events,0,strlen($events)-1);
    326378
    327                                 # Pond la CSS des évènements
    328 
    329                                 $HTML.="<style type='text/css'>";
    330                                 $res = sql_select('*', 'spip_fullcalendar_styles');
    331                                 while ( $row = sql_fetch($res))
    332                                         $HTML.=".f_".$row['id_style'].", .fc-agenda .f_".$row['id_style']." .fc-event-time, .f_".$row['id_style']." a {background-color:".$row['bgcolor'].";border-color:".$row['bordercolor'].";color:".$row['textcolor'].";}\n";
    333                                 $HTML.="</style>";
    334                                 sql_free($res);
    335 
    336379                        }
    337380
     
    347390                        $.datepicker.regional['fr'] = {
    348391                                closeText: 'Fermer',
    349                 prevText: '&#x3c;Préc',
    350                 nextText: 'Suiv&#x3e;',
    351                 currentText: 'Courant',
    352                 monthNames: ['Janvier','F&eacute;vrier','Mars','Avril','Mai','Juin',
    353                 'Juillet','Ao&ucirc;t','Septembre','Octobre','Novembre','D&eacute;cembre'],
    354                 monthNamesShort: ['Jan','F&eacute;v','Mar','Avr','Mai','Jun',
    355                 'Jul','Ao&ucirc;','Sep','Oct','Nov','Déc'],
    356                 dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
    357                 dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
    358                 dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
    359                 weekHeader: 'Sm',
    360                 dateFormat: 'dd/mm/yy',
    361                 firstDay: 1,
    362                 isRTL: false,
    363                 showMonthAfterYear: false,
    364                 yearSuffix: ''
    365             };
     392                                prevText: '&#x3c;Préc',
     393                                nextText: 'Suiv&#x3e;',
     394                                currentText: 'Courant',
     395                                monthNames: ['Janvier','F&eacute;vrier','Mars','Avril','Mai','Juin',
     396                                'Juillet','Ao&ucirc;t','Septembre','Octobre','Novembre','D&eacute;cembre'],
     397                                monthNamesShort: ['Jan','F&eacute;v','Mar','Avr','Mai','Jun',
     398                                'Jul','Ao&ucirc;','Sep','Oct','Nov','Déc'],
     399                                dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
     400                                dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
     401                                dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
     402                                weekHeader: 'Sm',
     403                                dateFormat: 'dd/mm/yy',
     404                                firstDay: 1,
     405                                isRTL: false,
     406                                showMonthAfterYear: false,
     407                                yearSuffix: ''
     408                        };
    366409
    367410                        $.datepicker.setDefaults($.datepicker.regional['fr']);
     
    404447                                }));
    405448
     449                        var day =$('#Date').datepicker('getDate');
     450                        $('#Date_Fin').datepicker('option','minDate',day);
    406451
    407452                        $('#calendar_aff').fullCalendar({
     
    446491                        <div class=\"formulaire_spip formulaire_config\">
    447492                                <div class=\"cadre_padding\">
    448 
    449493                                <form class=\"noajax\" action=\"\" name=\"Formulaire\" method=\"POST\">
    450494                                <input type=\"hidden\" name=\"action_to_take\" value=\"".$ACTION."\">
    451495                                <input type=\"hidden\" name=\"id_evenement\" value=\"".$ID_EVENEMENT."\">
    452                                 <p>Calendrier : <select name=\"id_calendrier\">".$LISTE_CALENDRIER."</select></p>
    453 
    454                                 <p>Du :
    455                                 <input type='text' name='Date' id='Date' size='10' value=\"".$DATE."\">
     496                                <p>"._T('fullcalendar:calendar')." : <select name=\"id_calendrier\" style=\"width:84%\">".$LISTE_CALENDRIER."</select></p>
     497                                <p>"._T('fullcalendar:event_from')." : <input type='text' name='Date' id='Date' size='10' value=\"".$DATE."\">
    456498                                <input type='text' name='HeureDebut' id='HeureDebut' size='5' value=\"".$START."\">
    457                                 &nbsp;&nbsp; Au : <input type='text' name='Date_Fin' id='Date_Fin' size='10' value=\"".$DATE_FIN."\">
    458                                 <input type='text' name='HeureFin' id='HeureFin' size='5' value=\"".$END."\"></p>
    459 
    460 <p>Titre de l'évènement : <input type='text' name='Nom_Evenement' class=\"forml\" style=\"width:98%\" value=\"".$NOM."\"></p>
    461 
    462                                 <p>Lien : <input type='text' name='Lien_Evenement' class=\"forml\" style=\"width:98%\" value=\"".$LIEN."\"></p>
    463 
     499                                </p>
     500                                <p>"._T('fullcalendar:event_to')." : <input type='text' name='Date_Fin' id='Date_Fin' size='10' value=\"".$DATE_FIN."\">
     501                                <input type='text' name='HeureFin' id='HeureFin' size='5' value=\"".$END."\">
     502                                </p>
     503                                <p>"._T('fullcalendar:event_title')." : <input type='text' name='Nom_Evenement' class=\"forml\" style=\"width:98%\" value=\"".$NOM."\"></p>
    464504                                ".$STYLES."
    465 
     505                                <p>"._T('fullcalendar:lien')." : <input type='text' name='Lien_Evenement' class=\"forml\" style=\"width:98%\" value=\"".$LIEN."\"></p>
    466506                                </div>
    467507                                <div class=\"boutons\">".$BUTTON."</div>
     
    472512                } else if($type=='google') {
    473513
    474                 $INFO="<b>Agenda Google</b><br/><br/>Vérifier bien que votre agenda est <u>public</u> puis renseignez l'ID dans le formulaire ci-contre.<br/><br/>".$INFO;
     514                $INFO="<b>"._T('fullcalendar:google_agenda')."</b><br/><br/>"._T('fullcalendar:google_agenda_info')."<br/><br/>".$INFO;
    475515
    476516                # Récupère le lien Google dans les évènements
     
    483523                        $URL_AGENDA = "http://www.google.com/calendar/feeds/".$rw['lien']."/public/basic";
    484524                        $ACTION='update';
    485                         $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" Modifier cette clé \" class=\"fondo\" />";
     525                        $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" "._T('fullcalendar:key_update')." \" class=\"fondo\" />";
    486526                } else { # on ajoute la clé
    487527                        $ACTION='add';
    488528                        $gcalID='';
    489                         $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" Enregistrer la clé \" class=\"fondo\" />";
     529                        $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" "._T('fullcalendar:key_save')." \" class=\"fondo\" />";
    490530                }
    491531
     
    494534                        <div class="formulaire_spip formulaire_config">
    495535                                <div class="cadre_padding">
    496 
    497536                                <form action="" name="Formulaire" method="POST">
    498537                                <input type="hidden" name="action_to_take" value="'.$ACTION.'">
    499538                                <input type="hidden" name="id_calendrier" value="'.$id.'">
    500                                 <p><label>ID de l\'agenda : <input type="text" name="gcalID" style="width:75%"  value="'.$gcalID.'" /></label></p>
    501 
     539                                <p><label>'._T('fullcalendar:google_agenda_id').' : <input type="text" name="gcalID" style="width:75%" value="'.$gcalID.'" /></label></p>
    502540                                </div>
    503541                                <div class="boutons">'.$BUTTON.'</div>
    504542                                </form>
    505                         </div>
    506 
    507                  ';
     543                        </div>';
     544
     545                } else if($type=='rub')     {
     546
     547                        $INFO="<b>"._T('fullcalendar:rub_agenda')."</b><br/><br/>"._T('fullcalendar:rub_agenda_info')."<br/><br/>".$INFO;
     548
     549                        # Récupère le secteur utilisé pour les évènements
     550
     551                        $req = sql_select('lien', 'spip_fullcalendar_events', 'id_fullcalendar='.$id);
     552                        if(sql_count($req)){ # Une rubrique est déjà renseignée
     553                                        $rw = sql_fetch($req);
     554                                        $ID_MOT=intval($rw['lien']);
     555                                        sql_free($req);
     556                                        $ACTION='update_rubrique';
     557                                        $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" "._T('fullcalendar:rub_agenda_change')." \" class=\"fondo\" />";
     558                        } else { # on ajoute la clé
     559                                        $ACTION='add_rubrique';
     560                                        $ID_MOT='';
     561                                        $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" "._T('bouton_enregistrer')." \" class=\"fondo\" />";
     562                        }
     563
     564                        # Rubriques du site (contenant des articles)
     565
     566                        $LISTE_RUBRIQUES='';
     567
     568                        $req = sql_select(
     569                                        array(
     570                                                        "DISTINCT R.id_rubrique",
     571                                                        "R.titre" ),
     572                                        array(
     573                                                        "spip_rubriques AS R",
     574                                                        "spip_articles AS A" ),
     575                                        array(
     576                                                        "R.id_parent=0",
     577                                                        "R.id_rubrique=A.id_rubrique",
     578                                                        "R.id_parent=0" ),
     579                                        "",
     580                                        "R.titre ASC");
     581
     582                        if(sql_count($req)){
     583
     584                                        while ($row = sql_fetch($req)) {
     585                                                        $LISTE_RUBRIQUES.="<option value=\"".$row['id_rubrique']."\"";
     586                                                        $LISTE_RUBRIQUES.=($row['id_rubrique']==$ID_MOT)?' SELECTED':'';
     587                                                        $LISTE_RUBRIQUES.=">".$row['titre']."</option>";
     588                                        }
     589                                        sql_free($req);
     590
     591                        }
     592
     593                        $INTERFACE="
     594                        <div class=\"formulaire_spip formulaire_config\">
     595                                        <div class=\"cadre_padding\">
     596                                                        <form class=\"noajax\" action=\"\" name=\"Formulaire\" method=\"POST\">
     597                                                        <input type=\"hidden\" name=\"action_to_take\" value=\"".$ACTION."\">
     598                                                        <input type=\"hidden\" name=\"id_calendrier\" value=\"".$id."\">
     599                                                        <p>"._T('fullcalendar:rub_agenda_source')." : <select name=\"id_rubrique\">".$LISTE_RUBRIQUES."</select></p>
     600                                        </div>
     601                                        <div class=\"boutons\">".$BUTTON."</div>
     602                        </form>
     603                        </div>";
     604
     605                        # dans le cas de sous-rubriques, récupère les ids des rubriques filles
     606
     607                        $req = sql_select(
     608                                        array(
     609                                                        "id_rubrique",
     610                                                        ),
     611                                        array(
     612                                                        "spip_rubriques" ),
     613                                        array(
     614                                        "id_parent='".$ID_MOT."'"
     615                                        ),
     616                                        "",
     617                                        "");
     618
     619                        while ($row = sql_fetch($req)) {
     620                                $ID_RUBRIQUES.="'".$row['id_rubrique']."',";
     621                        }
     622
     623                        $ID_RUBRIQUES.="'".$ID_MOT."'";
     624
     625                        # Récupère les article liés à ce secteur/rubrique
     626
     627                        $req = sql_select(
     628                                        array(
     629                                                        "A.id_article",
     630                                                        "A.titre",
     631                                                        "A.date",
     632                                                        "A.date_redac" ),
     633                                        array(
     634                                                        "spip_articles AS A",
     635                                                        "spip_rubriques AS R" ),
     636                                        array(
     637                                                        "A.id_rubrique IN (".$ID_RUBRIQUES.")",
     638                                                        "A.id_rubrique=R.id_rubrique" ),
     639                                        "",
     640                                        "A.date ASC");
     641
     642                        $num_events = sql_count($req);
     643                        if(!$num_events) $INFO.=_T('fullcalendar:no_event');
     644                        else {
     645                                        $HTML="
     646                                        <table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">
     647                                                        <tbody>
     648                                                        <tr>
     649                                                                        <th>"._T('fullcalendar:event_title')."</th>
     650                                                                        <th>"._T('fullcalendar:event_start')."</th>
     651                                                                        <th>"._T('fullcalendar:event_end')."</th>
     652                                                        </tr>";
     653                                        while ($row = sql_fetch($req)) {
     654                                                        $date = substr($row['date'],0,10);
     655                                                        $date_fin = substr($row['date_redac'],0,10);
     656                                                        $start = substr($row['date'],11,5);
     657                                                        $end = substr($row['date_redac'],11,5);
     658                                                        $erreur = ($date_fin=="0000-00-00")?' ortho':'';
     659                                                        # repère un incohérence dans les dates
     660                                                        $test_debut = $row['date'];
     661                                                        $test_fin = $row['date_redac'];
     662                                                        $diff = strtotime($test_fin) - strtotime($test_debut); // Ecart en secondes
     663                                                        if($diff<0){
     664                                                                $erreur =' ortho';
     665                                                                $end.="<- <b>"._T('fullcalendar:event_error')."</b>";
     666                                                        }
     667                                                        $HTML.= "<tr class=\"tr_liste\">
     668                                                                                <td class=\"verdana12\"><a href=\"?exec=articles&id_article=".$row['id_article']."\">".supprimer_numero($row['titre'])."</a></td>
     669                                                                                <td class=\"arial1\">".MyDateEnLettre ($date)."<br/>".$start."</td>
     670                                                                                <td class=\"arial1".$erreur."\">".MyDateEnLettre ($date_fin)."<br/>".$end."</td>
     671                                                                         </tr>";
     672                                                }
     673                                        sql_free($req);
     674                                        $HTML.="</table>";
     675                                }
    508676
    509677                } else if($type=='article')     {
    510678
    511                         $INFO="<b>Agenda d'articles avec mot clé</b><br/><br/>Sélectionnez le mot clé à lier aux articles qui serviront d'évènements pour ce calendrier.<br/><br/>".$INFO;
     679                        $INFO="<b>"._T('fullcalendar:mot_agenda')."</b><br/><br/>"._T('fullcalendar:mot_agenda_info')."<br/><br/>".$INFO;
    512680
    513681                        # Récupère le mot clé dans les évènements
     
    519687                                sql_free($req);
    520688                                $ACTION='update_mot';
    521                                 $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" Modifier ce mot clé \" class=\"fondo\" />";
     689                                $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" "._T('fullcalendar:mot_agenda_change')." \" class=\"fondo\" />";
    522690                        } else { # on ajoute la clé
    523691                                $ACTION='add_mot';
    524692                                $ID_MOT='';
    525                                 $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" Enregistrer \" class=\"fondo\" />";
     693                                $BUTTON = "<input type=\"submit\" name=\"ajouter\" value=\" "._T('bouton_enregistrer')." \" class=\"fondo\" />";
    526694                        }
    527695
     
    584752
    585753                        $num_events = sql_count($req);
    586                         if(!$num_events) $INFO.="Aucun évènement dans ce calendrier!";
     754                        if(!$num_events) $INFO.=_T('fullcalendar:no_event');
    587755                        else {
    588756                                $HTML="
     
    590758                                        <tbody>
    591759                                        <tr>
    592                                                 <th>Article</th>
    593                                                 <th>Début</th>
    594                                                 <th>Fin</th>
     760                                                <th>"._T('fullcalendar:event_title')."</th>
     761                                                <th>"._T('fullcalendar:event_start')."</th>
     762                                                <th>"._T('fullcalendar:event_end')."</th>
    595763                                        </tr>";
    596764
    597765                                while ($row = sql_fetch($req)) {
    598 
    599766                                        $date = substr($row['date'],0,10);
    600767                                        $date_fin = substr($row['date_redac'],0,10);
     
    602769                                        $end = substr($row['date_redac'],11,5);
    603770                                        $erreur = ($date_fin=="0000-00-00")?' ortho':'';
     771                                        # repère un incohérence dans les dates
     772                                        $test_debut = $row['date'];
     773                                        $test_fin = $row['date_redac'];
     774                                        $diff = strtotime($test_fin) - strtotime($test_debut); // Ecart en secondes
     775                                        if($diff<0){
     776                                                $erreur =' ortho';
     777                                                $end.="<- <b>"._T('fullcalendar:event_error')."</b>";
     778                                        }
    604779                                        $HTML.= "<tr class=\"tr_liste\">
    605780                                                                <td class=\"verdana12\"><a href=\"?exec=articles&id_article=".$row['id_article']."\">".supprimer_numero($row['titre'])."</a></td>
    606781                                                                <td class=\"arial1\">".MyDateEnLettre ($date)."<br/>".$start."</td>
    607782                                                                <td class=\"arial1".$erreur."\">".MyDateEnLettre ($date_fin)."<br/>".$end."</td>
    608                                                          </tr>
    609                                                         ";
     783                                                         </tr>";
    610784                                }
    611785                                sql_free($req);
     
    618792
    619793 $commencer_page = charger_fonction('commencer_page', 'inc');
    620  print $commencer_page(_T('Fullcalendar'), "", "") ;
     794 print $commencer_page(_T('fullcalendar:fullcalendar'), "", "") ;
    621795 print "<br/><br/>";
    622  print gros_titre(_T('Gestion des évènements'),'',false);
     796 print gros_titre(_T('fullcalendar:fullcalendar')." : "._T('fullcalendar:gestion_evenements'),'',false);
    623797 print debut_gauche ("",true);
    624798
    625799 print debut_boite_info(true);
    626  print "<center><b>"._T('FullCalendar')."</b></center>";
    627  print "<br/><center><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/fullcalendar.jpg'></center><br/>";
     800 print "<center><b>"._T('fullcalendar:fullcalendar')."</b></center>";
     801 print "<br/><center><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/fullcalendar.jpg'></center><br/>";
    628802 print $INFO;
    629803 print fin_boite_info(true);
     
    631805 print debut_cadre_enfonce('',true,'','','');
    632806 print "<table class=\"cellule-h-table\" style=\"vertical-align: middle;\" cellpadding=\"0\"><tbody><tr>
    633  <td><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\"><span class=\"cell-i\"><img src='../plugins/cfg/cfg-22.png' alt=\"CFG : configuration\"></span></a></td>
    634  <td class=\"cellule-h-lien\"><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\">CFG - configuration</a></td>
     807 <td><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\"><span class=\"cell-i\"><img src='../plugins/cfg/cfg-22.png' alt=\"CFG : "._T('fullcalendar:configuration')."\"></span></a></td>
     808 <td class=\"cellule-h-lien\"><a href=\"?exec=cfg&cfg=fullcalendar\" class=\"cellule-h\">CFG - "._T('fullcalendar:configuration')."</a></td>
    635809 </tr></tbody></table>";
    636810 print fin_cadre_enfonce(true);
     
    638812 print debut_cadre_enfonce('',true,'','','');
    639813 print "<table class=\"cellule-h-table\" style=\"vertical-align: middle;\" cellpadding=\"0\"><tbody><tr>
    640  <td><a href=\"?exec=fullcalendar_add\" class=\"cellule-h\"><span class=\"cell-i\"><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/calendar.png' alt=\"Agenda fullcalendar : configuration\"></span></a></td>
    641  <td class=\"cellule-h-lien\"><a href=\"?exec=fullcalendar_add\" class=\"cellule-h\">FullCalendar - Gestion</a></td>
     814 <td><a href=\"?exec=fullcalendar_add\" class=\"cellule-h\"><span class=\"cell-i\"><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/calendar.png' alt=\""._T('fullcalendar:fullcalendar')." : "._T('fullcalendar:gestion')."\"></span></a></td>
     815 <td class=\"cellule-h-lien\"><a href=\"?exec=fullcalendar_add\" class=\"cellule-h\">FullCalendar - "._T('fullcalendar:gestion')."</a></td>
    642816 </tr></tbody></table>";
    643817 print fin_cadre_enfonce(true);
     
    645819 print debut_cadre_enfonce('',true,'','','');
    646820 print "<table class=\"cellule-h-table\" style=\"vertical-align: middle;\" cellpadding=\"0\"><tbody><tr>
    647  <td><a href=\"?exec=fullcalendar_css\" class=\"cellule-h\"><span class=\"cell-i\"><img src='"._DIR_PLUGIN_FULLCALENDAR."img_pack/edit_css.png' alt=\"Styles de fullcalendar : configuration\"></span></a></td>
    648  <td class=\"cellule-h-lien\"><a href=\"?exec=fullcalendar_css\" class=\"cellule-h\">CSS - configuration</a></td>
     821 <td><a href=\"?exec=fullcalendar_css\" class=\"cellule-h\"><span class=\"cell-i\"><img src='"._DIR_PLUGIN_FULLCALENDAR."prive/themes/spip/images/edit_css.png' alt=\"CSS : "._T('fullcalendar:configuration')."\"></span></a></td>
     822 <td class=\"cellule-h-lien\"><a href=\"?exec=fullcalendar_css\" class=\"cellule-h\">CSS - "._T('fullcalendar:configuration')."</a></td>
    649823 </tr></tbody></table>";
    650824 print fin_cadre_enfonce(true);
    651825
    652826 if(strlen($LISTE)){
    653         print debut_cadre_enfonce('',true,'',_T('Vos calendriers'),'');
     827        print debut_cadre_enfonce('',true,'',_T('fullcalendar:vos_calendriers'),'');
    654828        print $LISTE;
    655829        print fin_cadre_enfonce(true);
     
    666840 # GESTION DES EVENEMENTS
    667841
    668  if(($type=='mysql'||$type=='article')
     842 if(($type=='mysql'||$type=='article'||$type=='rub')
    669843         && strlen($HTML)
    670844        ){
    671         print debut_cadre_relief("", false,"", $titre = _T('Tous les évènements de ce calendrier'));
     845        print debut_cadre_relief("", false,"", $titre = _T('fullcalendar:tous_evenements'));
    672846        print $HTML;
    673847        print fin_cadre_relief(false);
    674848 }else if(strlen($URL_AGENDA)){
    675         print debut_cadre_enfonce('',true,'',_T('Aperçu du flux'),'');
    676         print "Votre lien : <a href='".$URL_AGENDA."'>".$URL_AGENDA."</a>";
     849        print debut_cadre_enfonce('',true,'',_T('fullcalendar:flux'),'');
     850        print _T('fullcalendar:votre_lien')." : <a href='".$URL_AGENDA."'>".$URL_AGENDA."</a>";
    677851        print "<iframe src=\"".$URL_AGENDA."\" style=\"width:98%;height:250px\"></iframe>";
    678852        print fin_cadre_enfonce(true);
     
    681855
    682856 print fin_cadre_trait_couleur(true);
     857 
    683858 print fin_gauche();
    684859 print fin_page();
    685860
     861}
     862
     863function MyMonth($v){
     864        $mois = array("","Janvier","F&eacute;vrier","Mars","Avril","Mai","Juin","Juillet","Ao&ucirc;t","Septembre","Octobre","Novembre","D&eacute;cembre");
     865        $v=intval($v);
     866        return $mois[$v];
    686867}
    687868
  • _plugins_/fullcalendar/fonds/cfg_fullcalendar.html

    r46359 r53497  
    1 <!-- titre=Fullcalendar -->
    2 <!-- icone=img_pack/fullcalendar-24.png -->
    3 <!-- logo=img_pack/fullcalendar-48.png-->
    4 [(#REM) descriptif=&nbsp;]
    5 
    6 <style type='text/css'>.clear {clear:both;}</style>
    7 
     1<!-- titre=<:fullcalendar:cfg_titre_accueil:> -->
     2<!-- icone=prive/themes/spip/images/fullcalendar-24.png -->
     3<!-- logo=prive/themes/spip/images/fullcalendar-48.png-->
     4<!-- boite=<:fullcalendar:cfg_titre_boite:>-->
     5<!-- onglet=oui -->
     6[(#SET{logo, <img src='[(#CHEMIN{prive/themes/spip/images/fullcalendar-48.png})]'  alt='' style="float:#LANG_RIGHT;" /> })]
     7<!-- descriptif=[(#GET{logo})] <:fullcalendar:cfg_boite_info:> -->
    88#CACHE{0}
    9 
    10 <!-- boite=JQUERY Fullcalendar pour SPIP -->
    11 
    12 <script type="text/javascript">
    13         $(document).ready(function() {
    14                 $('#navigation .cadre_padding').empty().append('<center><h4>CFG Fullcalendar</h4><img src="#EVAL{_DIR_PLUGIN_FULLCALENDAR}img_pack/fullcalendar.jpg"><br/><br/>Configuration du plugin FullCalendar</center><ul class="formulaire_spip"><li><a href="&#35;CFG_options">Affichage global</a></li><li><a href="&#35;CFG_header">En-tête</a></li><li><a href="&#35;CFG_month">Vue mensuelle</a></li><li><a href="&#35;CFG_week">Vue par semaines</a></li><li><a href="&#35;CFG_day">Calendrier journalier</a></li></ul>');
    15                 $('#navigation').append('<div class="cadre cadre-e" style=""><div class="cadre_padding"><table class="cellule-h-table" style="vertical-align: middle;" cellpadding="0"><tbody><tr><td><a href="?exec=fullcalendar_add" class="cellule-h"><span class="cell-i"><img src="#EVAL{_DIR_PLUGIN_FULLCALENDAR}img_pack/calendar.png" alt="Agenda fullcalendar : configuration"></span></a></td><td class="cellule-h-lien"><a href="?exec=fullcalendar_add" class="cellule-h">FullCalendar - Gestion</a></td></tr></tbody></table><div class="nettoyeur"></div></div></div>');
    16                 $('#navigation').append('<div class="cadre cadre-e" style=""><div class="cadre_padding"><table class="cellule-h-table" style="vertical-align: middle;" cellpadding="0"><tbody><tr><td><a href="?exec=fullcalendar_css" class="cellule-h"><span class="cell-i"><img src="#EVAL{_DIR_PLUGIN_FULLCALENDAR}/img_pack/edit_css.png" alt="Styles de fullcalendar : configuration"></span></a></td><td class="cellule-h-lien"><a href="?exec=fullcalendar_css" class="cellule-h">CSS - configuration</a></td></tr></tbody></table><div class="nettoyeur"></div></div></div>');
    17         });
    18 </script>
    19 
    20 <form method="post" action="#SELF">
    21 
    22         [(#ENV{_cfg_}|form_hidden)]
    23 
    24         <p><a name="CFG_options"><h1>Affichage global</h1></a></p>
    25         <hr>
    26         <p>
    27                 <label for="_ir_defaultView">Vue par défaut :</label>
    28                 <select name="defaultView" id="_ir_defaultView">
    29                         <option value="month" [(#CONFIG{fullcalendar/defaultView}|=={#VAL{'month'}}|?{selected="selected",''})]>Mois</option>
    30                         <option value="basicWeek" [(#CONFIG{fullcalendar/defaultView}|=={#VAL{'basicWeek'}}|?{selected="selected",''})]>Semaines</option>
    31                         <option value="agendaWeek" [(#CONFIG{fullcalendar/defaultView}|=={#VAL{'agendaWeek'}}|?{selected="selected",''})]>Semaines et heures</option>
    32                         <option value="basicDay" [(#CONFIG{fullcalendar/defaultView}|=={#VAL{'basicDay'}}|?{selected="selected",''})]>Jours</option>
    33                         <option value="agendaDay" [(#CONFIG{fullcalendar/defaultView}|=={#VAL{'agendaDay'}}|?{selected="selected",''})]>Jours et heures</option>
    34                 </select> <a href="http://arshaw.com/fullcalendar/docs/views/Available_Views/" target="_blank">[aide]</a>
    35         </p>
    36         <p>
    37                 <label for="_ir_theme">theme :</label>
    38                 <select name="useTheme" id="_ir_theme">
    39                         <option value="true" [(#CONFIG{fullcalendar/useTheme}|=={#VAL{'true'}}|?{selected="selected",''})]>oui</option>
    40                         <option value="false" [(#CONFIG{fullcalendar/useTheme}|=={#VAL{'false'}}|?{selected="selected",''})]>non</option>
    41                 </select> <a href="http://arshaw.com/fullcalendar/docs/display/theme/" target="_blank">[aide]</a>
    42         </p>
    43         <p>
    44          <label for="_ir_aspectRatio">aspectRatio :</label>
    45          <input type="text" name="aspectRatio" class="type_txt" value="#ENV{aspectRatio, '1.35'}" id="_ir_aspectRatio" style="width:20%" />
    46           <a href="http://arshaw.com/fullcalendar/docs/display/aspectRatio/" target="_blank">[aide]</a>
    47         </p>
    48         <p>
    49                 <label for="_ir_weekends">Afficher les weekends :</label>
    50                 <select name="weekends" id="_ir_weekends">
    51                         <option value="true" [(#CONFIG{fullcalendar/weekends}|=={#VAL{'true'}}|?{selected="selected",''})]>oui</option>
    52                         <option value="false" [(#CONFIG{fullcalendar/weekends}|=={#VAL{'false'}}|?{selected="selected",''})]>non</option>
    53                 </select> <a href="http://arshaw.com/fullcalendar/docs/display/weekends/" target="_blank">[aide]</a>
    54         </p>
    55         <p>
    56                 <label for="_ir_firstDay">La semaine commence :</label>
    57                 <select name="firstDay" id="_ir_firstDay">
    58                         <option value="1" [(#CONFIG{fullcalendar/firstDay}|=={#VAL{'1'}}|?{selected="selected",''})]>Lundi</option>
    59                         <option value="2" [(#CONFIG{fullcalendar/firstDay}|=={#VAL{'2'}}|?{selected="selected",''})]>Mardi</option>
    60                         <option value="3" [(#CONFIG{fullcalendar/firstDay}|=={#VAL{'3'}}|?{selected="selected",''})]>Mercredi</option>
    61                         <option value="4" [(#CONFIG{fullcalendar/firstDay}|=={#VAL{'4'}}|?{selected="selected",''})]>Jeudi</option>
    62                         <option value="5" [(#CONFIG{fullcalendar/firstDay}|=={#VAL{'5'}}|?{selected="selected",''})]>Vendredi</option>
    63                         <option value="6" [(#CONFIG{fullcalendar/firstDay}|=={#VAL{'6'}}|?{selected="selected",''})]>Samedi</option>
    64                         <option value="7" [(#CONFIG{fullcalendar/firstDay}|=={#VAL{'7'}}|?{selected="selected",''})]>Dimanche</option>
    65                 </select>
    66         </p>
    67 
    68 
    69        
    70         <br/><br/>
    71         <p><a name="CFG_header"><h1>En-tête</h1></a></p>
    72         <hr>
    73         <div class="formulaire_spip" style="width:47%;float:right">
    74                 <div class="cadre_padding">
    75                         <p><b>Options :</b> <a href="http://arshaw.com/fullcalendar/docs/display/header/" target="_blank">[aide]</a></p>
    76                         <hr>
    77                         <p><b>title</b> : Titre</p>
    78                         <p><b>prev, next</b>  : Reculer, avancer</p>
    79                         <p><b>prevYear</b> : Reculer d'un an</p>
    80                         <p><b>nextYear</b> : Avancer d'un an</p>
    81                         <p><b>today</b> : Aller sur aujourd'hui</p>
    82                         <p><b>month</b> : Afficher la vue par mois</p>
    83                         <p><b>agendaWeek</b> : Afficher la vue par semaines</p>
    84                         <p><b>agendaDay</b> : Afficher la vue par jours</p>
    85                 </div>
    86         </div>
    87         <div style="width:52%;float:left">
    88                 <p>
    89                         <label for='_ir_left'>Gauche :</label>
    90                         <input type="text" name="headerLeft" class="type_txt" value="#ENV{headerLeft, 'prev,next'}" id="_ir_left" style="width:90%" />
    91                 </p>
    92                 <p>
    93                         <label for='_ir_center'>Centre :</label>
    94                         <input type="text" name="headerCenter" class="type_txt" value="#ENV{headerCenter, 'title'}" id="_ir_center" style="width:90%" />
    95                 </p>
    96                 <p>
    97                         <label for='_ir_right'>Droite :</label>
    98                         <input type="text" name="headerRight" class="type_txt" value="#ENV{headerRight, 'month,agendaWeek,agendaDay'}" id="_ir_right" style="width:90%" />
    99                 </p>
    100                
    101         </div>
    102         <br class='clear'/>
    103        
    104         <br/><br/>
    105         <p><a name="CFG_month"><h1>Vue mensuelle</h1></a></p>
    106         <hr> <a href="http://arshaw.com/fullcalendar/docs/utilities/formatDate/" target="_blank">[aide]</a></p>
    107         <p>
    108                 <label for='_ir_month_titleFormat'>Titre : </label>
    109                 <input type="text" name="month_titleFormat" class="type_txt" value="#ENV{month_titleFormat, 'MMMM yyyy'}" id="_ir_month_titleFormat" style="width:98%" />
    110         </p>
    111         <p>
    112                 <label for='_ir_month_columnFormat'>Colonnes : </label>
    113                 <input type="text" name="month_columnFormat" class="type_txt" value="#ENV{month_columnFormat, 'dddd'}" id="_ir_month_columnFormat" style="width:98%" />
    114         </p>
    115         <p>
    116                 <label for='_ir_month_timeFormat'>Temps : </label>
    117                 <input type="text" name="month_timeFormat" class="type_txt" value="#ENV{month_timeFormat, ''}" id="_ir_month_timeFormat" style="width:98%" />
    118         </p>
    119 
    120         <br/><br/>
    121         <p><h1>Vue par semaines</h1></p><a name="CFG_week"></a>
    122         <hr> <a href="http://arshaw.com/fullcalendar/docs/utilities/formatDate/" target="_blank">[aide]</a></p>
    123         <p>
    124                 <label for='_ir_week_titleFormat'>Titre : </label>
    125                 <input type="text" name="week_titleFormat" class="type_txt" value="#ENV{week_titleFormat, 'd [MMMM] [ yyyy]{  -  d MMMM yyyy}'}" id="_ir_week_titleFormat" style="width:98%" />
    126         </p>
    127         <p>
    128                 <label for='_ir_week_columnFormat'>Colonnes : </label>
    129                 <input type="text" name="week_columnFormat" class="type_txt" value="#ENV{week_columnFormat, 'dddd d'}" id="_ir_week_columnFormat" style="width:98%" />
    130         </p>
    131         <p>
    132                 <label for='_ir_week_timeFormat_basic'>Temps (basic) : </label>
    133                 <input type="text" name="week_timeFormat_basic" class="type_txt" value="#ENV{week_timeFormat_basic, 'H(:mm)'}" id="_ir_week_timeFormat_basic" style="width:98%" />
    134         </p>
    135         <p>
    136                 <label for='_ir_week_timeFormat_agenda'>Temps (agenda) : </label>
    137                 <input type="text" name="week_timeFormat_agenda" class="type_txt" value="#ENV{week_timeFormat_agenda, 'H(:mm)'}" id="_ir_week_timeFormat_agenda" style="width:98%" />
    138         </p>
    139 
    140         <br/><br/>
    141         <p><h1>Calendrier journalier</h1></p><a name="CFG_day"></a>
    142         <hr> <a href="http://arshaw.com/fullcalendar/docs/utilities/formatDate/" target="_blank">[aide]</a></p>
    143         <p>
    144                 <label for='_ir_day_titleFormat'>Titre : </label>
    145                 <input type="text" name="day_titleFormat" class="type_txt" value="#ENV{day_titleFormat, 'dddd d MMMM yyyy'}" id="_ir_day_titleFormat" style="width:98%" />
    146         </p>
    147         <p>
    148                 <label for='_ir_day_columnFormat'>Colonnes : </label>
    149                 <input type="text" name="day_columnFormat" class="type_txt" value="#ENV{day_columnFormat, 'dddd d MMMM'}" id="_ir_day_columnFormat" style="width:98%" />
    150         </p>
    151         <p>
    152                 <label for='_ir_day_timeFormat_basic'>Temps (basic) : </label>
    153                 <input type="text" name="day_timeFormat_basic" class="type_txt" value="#ENV{day_timeFormat_basic, 'H:mm{ - H:mm}'}" id="_ir_day_timeFormat_basic" style="width:98%" />
    154         </p>
    155         <p>
    156                 <label for='_ir_day_timeFormat_agenda'>Temps (agenda) : </label>
    157                 <input type="text" name="day_timeFormat_agenda" class="type_txt" value="#ENV{day_timeFormat_agenda, 'H:mm{ - H:mm}'}" id="_ir_day_timeFormat_agenda" style="width:98%" />
    158         </p>
    159 
    160         <br/><br/>
    161         <div class="formulaire_spip formulaire_config">
    162                 <div class="boutons">
    163                         <input type="submit" name="_cfg_delete" value="<:supprimer:>" class="fondo" />
    164                         <input type="submit" name="_cfg_ok" value="<:ok:>" class="fondo" />
    165                 </div>
    166         </div>
    167 
    168 </form>
     9<div class="ajax">
     10#FORMULAIRE_CONFIG_FULLCALENDAR
     11</div>
  • _plugins_/fullcalendar/fullcalendar_pipelines.php

    r46420 r53497  
    99        if($done) return $flux_;
    1010        $done = true;
    11         $flux  = "<!-- FULLCALENDAR INSERT HEAD CSS START -->
    12 ";
    13         $flux .= "<link rel='stylesheet' type='text/css' href='".find_in_path('css/redmond/theme.css')."' />
     11        $flux .= "<link rel='stylesheet' type='text/css' href='".find_in_path('css/cupertino/theme.css')."' />
    1412";
    1513        $flux .= "<link rel='stylesheet' type='text/css' href='".find_in_path('css/fullcalendar.css')."' />
    1614";
    17         $flux .= "<link rel='stylesheet' type='text/css' href='".url_absolue(generer_url_public('css_fullcalendar'))."' media='all' />
    18 ";
    19         $flux .= "<!-- FULLCALENDAR INSERT HEAD CSS END -->
     15        $flux .= "<link rel='stylesheet' type='text/css' media='print' href='".find_in_path('css/fullcalendar.print.css')."' />
    2016";
    2117        return $flux_ . $flux;
     
    2319
    2420function fullcalendar_insert_head($flux_){
    25         $flux  = "<!-- FULLCALENDAR INSERT HEAD START -->
    26 ";
    2721        $flux .= "<script type='text/javascript' src='".find_in_path('js/fullcalendar.js')."'></script>
    2822";
    2923        $flux .= "<script type='text/javascript' src='".find_in_path('js/gcal.js')."'></script>
    30 ";
    31         $flux .= "<!-- FULLCALENDAR INSERT HEAD END -->
    3224";
    3325        return $flux_ . fullcalendar_insert_head_css() . $flux;
     
    5951        $flux .= "<link rel='stylesheet' type='text/css' href='".url_absolue(find_in_path('css/jquery-ui-timepicker.css'))."' />
    6052";
    61         $flux .= "<link rel='stylesheet' type='text/css' href='".url_absolue(find_in_path('css/redmond/theme.css'))."' />
     53        $flux .= "<link rel='stylesheet' type='text/css' href='".find_in_path('css/cupertino/theme.css')."' />
    6254";
    6355        $flux .= "<link rel='stylesheet' type='text/css' href='".url_absolue(find_in_path('css/fullcalendar.css'))."' />
     
    6759        return $flux_ . $flux;
    6860}
     61
     62function fullcalendar_affiche_milieu($flux) {
     63#       $exec = $flux["args"]["exec"];
     64#       if ($exec == "naviguer") {
     65#               if($flux['args']['id_rubrique']){
     66#                       $ret = "<div id='pave_selection'>";
     67#                       $ret .= recuperer_fond("prive/contenu/fullcalendar_rubriques", array('id_auteur'=>$flux['args']['id_rubrique']));
     68#                       $ret .= "</div>";
     69#                       $flux["data"] .= $ret;
     70#               }
     71#       }
     72        return $flux;
     73}
     74
     75function fullcalendar_affiche_gauche($flux){
     76#       include_spip('inc/presentation');
     77#       if ($flux['args']['exec'] == 'articles'){
     78#               $flux['data'] .=
     79#               debut_cadre_relief('',true,'', _T('fullcalendar:fullcalendar')) .
     80#               recuperer_fond('prive/contenu/fullcalendar_articles', array('id_auteur'=>$flux['args']['id_article'])) .
     81#               fin_cadre_relief(true);
     82#       }
     83        return $flux;
     84}
     85
    6986
    7087/*************
     
    7996        $scripts[] = "jquery.effects.scale";
    8097        $scripts[] = "jquery.ui.dialog";
     98        $scripts[] = "jquery.ui.tabs";
    8199        return $scripts;
    82100}
  • _plugins_/fullcalendar/js/fullcalendar.js

    r46359 r53497  
    11/**
    22 * @preserve
    3  * FullCalendar v1.4.10
     3 * FullCalendar v1.5.2
    44 * http://arshaw.com/fullcalendar/
    55 *
     
    88 * For event resizing, requires jQuery UI resizable.
    99 *
    10  * Copyright (c) 2010 Adam Shaw
     10 * Copyright (c) 2011 Adam Shaw
    1111 * Dual licensed under the MIT and GPL licenses, located in
    1212 * MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
    1313 *
    14  * Date: Sat Jan 1 23:46:27 2011 -0800
     14 * Date: Sun Aug 21 22:06:09 2011 -0700
    1515 *
    1616 */
     
    5959        },
    6060       
     61        // locale
     62        isRTL: false,
     63
    6164        firstDay: 1,
    6265        monthNames: ['Janvier','F\351vrier','Mars','Avril','Mai','Juin','Juillet','Ao\373t','Septembre','Octobre','Novembre','D\351cembre'],
     
    7477                day: 'jour'
    7578        },
    76 
    7779       
    7880        // jquery-ui theming
     
    111113
    112114
    113 var fc = $.fullCalendar = { version: "1.4.10" };
     115var fc = $.fullCalendar = { version: "1.5.2" };
    114116var fcViews = fc.views = {};
    115117
     
    189191        t.reportEvents = reportEvents;
    190192        t.reportEventChange = reportEventChange;
     193        t.rerenderEvents = rerenderEvents;
    191194        t.changeView = changeView;
    192195        t.select = select;
     
    260263                        element.addClass('ui-widget');
    261264                }
    262                 content = $("<div class='fc-content " + tm + "-widget-content' style='position:relative'/>")
     265                content = $("<div class='fc-content' style='position:relative'/>")
    263266                        .prependTo(element);
    264267                header = new Header(t, options);
     
    291294                header.destroy();
    292295                content.remove();
    293                 element.removeClass('fc fc-rtl fc-ui-widget');
     296                element.removeClass('fc fc-rtl ui-widget');
    294297        }
    295298       
     
    310313        -----------------------------------------------------------------------------*/
    311314       
     315        // TODO: improve view switching (still weird transition in IE, and FF has whiteout problem)
    312316       
    313317        function changeView(newViewName) {
     
    440444                }
    441445                else if (options.height) {
    442                         suggestedViewHeight = options.height - (headerElement ? headerElement.height() : 0) - vsides(content[0]);
     446                        suggestedViewHeight = options.height - (headerElement ? headerElement.height() : 0) - vsides(content);
    443447                }
    444448                else {
     
    696700                var sections = options.header;
    697701                if (sections) {
    698                         element = $("<table class='fc-header'/>")
    699                                 .append($("<tr/>")
    700                                         .append($("<td class='fc-header-left'/>")
    701                                                 .append(renderSection(sections.left)))
    702                                         .append($("<td class='fc-header-center'/>")
    703                                                 .append(renderSection(sections.center)))
    704                                         .append($("<td class='fc-header-right'/>")
    705                                                 .append(renderSection(sections.right))));
     702                        element = $("<table class='fc-header' style='width:100%'/>")
     703                                .append(
     704                                        $("<tr/>")
     705                                                .append(renderSection('left'))
     706                                                .append(renderSection('center'))
     707                                                .append(renderSection('right'))
     708                                );
    706709                        return element;
    707710                }
     
    714717       
    715718       
    716         function renderSection(buttonStr) {
     719        function renderSection(position) {
     720                var e = $("<td class='fc-header-" + position + "'/>");
     721                var buttonStr = options.header[position];
    717722                if (buttonStr) {
    718                         var tr = $("<tr/>");
    719723                        $.each(buttonStr.split(' '), function(i) {
    720724                                if (i > 0) {
    721                                         tr.append("<td><span class='fc-header-space'/></td>");
     725                                        e.append("<span class='fc-header-space'/>");
    722726                                }
    723727                                var prevButton;
    724728                                $.each(this.split(','), function(j, buttonName) {
    725729                                        if (buttonName == 'title') {
    726                                                 tr.append("<td><h2 class='fc-header-title'>&nbsp;</h2></td>");
     730                                                e.append("<span class='fc-header-title'><h2>&nbsp;</h2></span>");
    727731                                                if (prevButton) {
    728732                                                        prevButton.addClass(tm + '-corner-right');
     
    741745                                                }
    742746                                                if (buttonClick) {
    743                                                         if (prevButton) {
    744                                                                 prevButton.addClass(tm + '-no-right');
    745                                                         }
    746                                                         var button;
    747                                                         var icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null;
    748                                                         var text = smartProperty(options.buttonText, buttonName);
    749                                                         if (icon) {
    750                                                                 button = $("<div class='fc-button-" + buttonName + " ui-state-default'>" +
    751                                                                         "<a><span class='ui-icon ui-icon-" + icon + "'/></a></div>");
    752                                                         }
    753                                                         else if (text) {
    754                                                                 button = $("<div class='fc-button-" + buttonName + " " + tm + "-state-default'>" +
    755                                                                         "<a><span>" + text + "</span></a></div>");
    756                                                         }
     747                                                        var icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null; // why are we using smartProperty here?
     748                                                        var text = smartProperty(options.buttonText, buttonName); // why are we using smartProperty here?
     749                                                        var button = $(
     750                                                                "<span class='fc-button fc-button-" + buttonName + " " + tm + "-state-default'>" +
     751                                                                        "<span class='fc-button-inner'>" +
     752                                                                                "<span class='fc-button-content'>" +
     753                                                                                        (icon ?
     754                                                                                                "<span class='fc-icon-wrap'>" +
     755                                                                                                        "<span class='ui-icon ui-icon-" + icon + "'/>" +
     756                                                                                                "</span>" :
     757                                                                                                text
     758                                                                                                ) +
     759                                                                                "</span>" +
     760                                                                                "<span class='fc-button-effect'><span></span></span>" +
     761                                                                        "</span>" +
     762                                                                "</span>"
     763                                                        );
    757764                                                        if (button) {
    758765                                                                button
     
    784791                                                                                }
    785792                                                                        )
    786                                                                         .appendTo($("<td/>").appendTo(tr));
    787                                                                 if (prevButton) {
    788                                                                         prevButton.addClass(tm + '-no-right');
    789                                                                 }else{
     793                                                                        .appendTo(e);
     794                                                                if (!prevButton) {
    790795                                                                        button.addClass(tm + '-corner-left');
    791796                                                                }
     
    799804                                }
    800805                        });
    801                         return $("<table/>").append(tr);
    802                 }
     806                }
     807                return e;
    803808        }
    804809       
    805810       
    806811        function updateTitle(html) {
    807                 element.find('h2.fc-header-title')
     812                element.find('h2')
    808813                        .html(html);
    809814        }
     
    811816       
    812817        function activateButton(buttonName) {
    813                 element.find('div.fc-button-' + buttonName)
     818                element.find('span.fc-button-' + buttonName)
    814819                        .addClass(tm + '-state-active');
    815820        }
     
    817822       
    818823        function deactivateButton(buttonName) {
    819                 element.find('div.fc-button-' + buttonName)
     824                element.find('span.fc-button-' + buttonName)
    820825                        .removeClass(tm + '-state-active');
    821826        }
     
    823828       
    824829        function disableButton(buttonName) {
    825                 element.find('div.fc-button-' + buttonName)
     830                element.find('span.fc-button-' + buttonName)
    826831                        .addClass(tm + '-state-disabled');
    827832        }
     
    829834       
    830835        function enableButton(buttonName) {
    831                 element.find('div.fc-button-' + buttonName)
     836                element.find('span.fc-button-' + buttonName)
    832837                        .removeClass(tm + '-state-disabled');
    833838        }
     
    836841}
    837842
     843fc.sourceNormalizers = [];
     844fc.sourceFetchers = [];
     845
     846var ajaxDefaults = {
     847        dataType: 'json',
     848        cache: false
     849};
     850
    838851var eventGUID = 1;
    839852
    840 function EventManager(options, sources) {
     853
     854function EventManager(options, _sources) {
    841855        var t = this;
    842856       
     
    861875       
    862876        // locals
     877        var stickySource = { events: [] };
     878        var sources = [ stickySource ];
    863879        var rangeStart, rangeEnd;
    864880        var currentFetchID = 0;
     
    866882        var loadingLevel = 0;
    867883        var cache = [];
     884       
     885       
     886        for (var i=0; i<_sources.length; i++) {
     887                _addEventSource(_sources[i]);
     888        }
    868889       
    869890       
     
    894915                _fetchEventSource(source, function(events) {
    895916                        if (fetchID == currentFetchID) {
    896                                 for (var i=0; i<events.length; i++) {
    897                                         normalizeEvent(events[i]);
    898                                         events[i].source = source;
    899                                 }
    900                                 cache = cache.concat(events);
     917                                if (events) {
     918                                        for (var i=0; i<events.length; i++) {
     919                                                events[i].source = source;
     920                                                normalizeEvent(events[i]);
     921                                        }
     922                                        cache = cache.concat(events);
     923                                }
    901924                                pendingSourceCnt--;
    902925                                if (!pendingSourceCnt) {
     
    909932       
    910933        function _fetchEventSource(source, callback) {
    911                 if (typeof source == 'string') {
    912                         var params = {};
    913                         params[options.startParam] = Math.round(rangeStart.getTime() / 1000);
    914                         params[options.endParam] = Math.round(rangeEnd.getTime() / 1000);
    915                         if (options.cacheParam) {
    916                                 params[options.cacheParam] = (new Date()).getTime(); // TODO: deprecate cacheParam
    917                         }
    918                         pushLoading();
    919                         // TODO: respect cache param in ajaxSetup
    920                         $.ajax({
    921                                 url: source,
    922                                 dataType: 'json',
    923                                 data: params,
    924                                 cache: options.cacheParam || false, // don't let jquery prevent caching if cacheParam is being used
    925                                 success: function(events) {
     934                var i;
     935                var fetchers = fc.sourceFetchers;
     936                var res;
     937                for (i=0; i<fetchers.length; i++) {
     938                        res = fetchers[i](source, rangeStart, rangeEnd, callback);
     939                        if (res === true) {
     940                                // the fetcher is in charge. made its own async request
     941                                return;
     942                        }
     943                        else if (typeof res == 'object') {
     944                                // the fetcher returned a new source. process it
     945                                _fetchEventSource(res, callback);
     946                                return;
     947                        }
     948                }
     949                var events = source.events;
     950                if (events) {
     951                        if ($.isFunction(events)) {
     952                                pushLoading();
     953                                events(cloneDate(rangeStart), cloneDate(rangeEnd), function(events) {
     954                                        callback(events);
    926955                                        popLoading();
    927                                         callback(events);
    928                                 }
    929                         });
    930                 }
    931                 else if ($.isFunction(source)) {
    932                         pushLoading();
    933                         source(cloneDate(rangeStart), cloneDate(rangeEnd), function(events) {
    934                                 popLoading();
     956                                });
     957                        }
     958                        else if ($.isArray(events)) {
    935959                                callback(events);
    936                         });
    937                 }
    938                 else {
    939                         callback(source); // src is an array
     960                        }
     961                        else {
     962                                callback();
     963                        }
     964                }else{
     965                        var url = source.url;
     966                        if (url) {
     967                                var success = source.success;
     968                                var error = source.error;
     969                                var complete = source.complete;
     970                                var data = $.extend({}, source.data || {});
     971                                var startParam = firstDefined(source.startParam, options.startParam);
     972                                var endParam = firstDefined(source.endParam, options.endParam);
     973                                if (startParam) {
     974                                        data[startParam] = Math.round(+rangeStart / 1000);
     975                                }
     976                                if (endParam) {
     977                                        data[endParam] = Math.round(+rangeEnd / 1000);
     978                                }
     979                                pushLoading();
     980                                $.ajax($.extend({}, ajaxDefaults, source, {
     981                                        data: data,
     982                                        success: function(events) {
     983                                                events = events || [];
     984                                                var res = applyAll(success, this, arguments);
     985                                                if ($.isArray(res)) {
     986                                                        events = res;
     987                                                }
     988                                                callback(events);
     989                                        },
     990                                        error: function() {
     991                                                applyAll(error, this, arguments);
     992                                                callback();
     993                                        },
     994                                        complete: function() {
     995                                                applyAll(complete, this, arguments);
     996                                                popLoading();
     997                                        }
     998                                }));
     999                        }else{
     1000                                callback();
     1001                        }
    9401002                }
    9411003        }
     
    9461008        -----------------------------------------------------------------------------*/
    9471009       
    948        
    949         // first event source is reserved for "sticky" events
    950         sources.unshift([]);
    951        
    9521010
    9531011        function addEventSource(source) {
    954                 sources.push(source);
    955                 pendingSourceCnt++;
    956                 fetchEventSource(source, currentFetchID); // will eventually call reportEvents
     1012                source = _addEventSource(source);
     1013                if (source) {
     1014                        pendingSourceCnt++;
     1015                        fetchEventSource(source, currentFetchID); // will eventually call reportEvents
     1016                }
     1017        }
     1018       
     1019       
     1020        function _addEventSource(source) {
     1021                if ($.isFunction(source) || $.isArray(source)) {
     1022                        source = { events: source };
     1023                }
     1024                else if (typeof source == 'string') {
     1025                        source = { url: source };
     1026                }
     1027                if (typeof source == 'object') {
     1028                        normalizeSource(source);
     1029                        sources.push(source);
     1030                        return source;
     1031                }
    9571032        }
    9581033       
     
    9601035        function removeEventSource(source) {
    9611036                sources = $.grep(sources, function(src) {
    962                         return src != source;
     1037                        return !isSourcesEqual(src, source);
    9631038                });
    9641039                // remove all client events from that source
    9651040                cache = $.grep(cache, function(e) {
    966                         return e.source != source;
     1041                        return !isSourcesEqual(e.source, source);
    9671042                });
    9681043                reportEvents(cache);
     
    10001075                                e.className = event.className;
    10011076                                e.editable = event.editable;
     1077                                e.color = event.color;
     1078                                e.backgroudColor = event.backgroudColor;
     1079                                e.borderColor = event.borderColor;
     1080                                e.textColor = event.textColor;
    10021081                                normalizeEvent(e);
    10031082                        }
     
    10121091                if (!event.source) {
    10131092                        if (stick) {
    1014                                 sources[0].push(event);
    1015                                 event.source = sources[0];
     1093                                stickySource.events.push(event);
     1094                                event.source = stickySource;
    10161095                        }
    10171096                        cache.push(event);
     
    10261105                        // clear all array sources
    10271106                        for (var i=0; i<sources.length; i++) {
    1028                                 if (typeof sources[i] == 'object') {
    1029                                         sources[i] = [];
     1107                                if ($.isArray(sources[i].events)) {
     1108                                        sources[i].events = [];
    10301109                                }
    10311110                        }
     
    10401119                        // remove events from array sources
    10411120                        for (var i=0; i<sources.length; i++) {
    1042                                 if (typeof sources[i] == 'object') {
    1043                                         sources[i] = $.grep(sources[i], filter, true);
    1044                                         // TODO: event objects' sources will no longer be correct reference :(
     1121                                if ($.isArray(sources[i].events)) {
     1122                                        sources[i].events = $.grep(sources[i].events, filter, true);
    10451123                                }
    10461124                        }
     
    10891167       
    10901168        function normalizeEvent(event) {
     1169                var source = event.source || {};
     1170                var ignoreTimezone = firstDefined(source.ignoreTimezone, options.ignoreTimezone);
    10911171                event._id = event._id || (event.id === undefined ? '_fc' + eventGUID++ : event.id + '');
    10921172                if (event.date) {
     
    10961176                        delete event.date;
    10971177                }
    1098                 event._start = cloneDate(event.start = parseDate(event.start, options.ignoreTimezone));
    1099                 event.end = parseDate(event.end, options.ignoreTimezone);
     1178                event._start = cloneDate(event.start = parseDate(event.start, ignoreTimezone));
     1179                event.end = parseDate(event.end, ignoreTimezone);
    11001180                if (event.end && event.end <= event.start) {
    11011181                        event.end = null;
     
    11031183                event._end = event.end ? cloneDate(event.end) : null;
    11041184                if (event.allDay === undefined) {
    1105                         event.allDay = options.allDayDefault;
     1185                        event.allDay = firstDefined(source.allDayDefault, options.allDayDefault);
    11061186                }
    11071187                if (event.className) {
     
    11141194                // TODO: if there is no start date, return false to indicate an invalid event
    11151195        }
    1116 
    1117 
    1118 }
     1196       
     1197       
     1198       
     1199        /* Utils
     1200        ------------------------------------------------------------------------------*/
     1201       
     1202       
     1203        function normalizeSource(source) {
     1204                if (source.className) {
     1205                        // TODO: repeat code, same code for event classNames
     1206                        if (typeof source.className == 'string') {
     1207                                source.className = source.className.split(/\s+/);
     1208                        }
     1209                }else{
     1210                        source.className = [];
     1211                }
     1212                var normalizers = fc.sourceNormalizers;
     1213                for (var i=0; i<normalizers.length; i++) {
     1214                        normalizers[i](source);
     1215                }
     1216        }
     1217       
     1218       
     1219        function isSourcesEqual(source1, source2) {
     1220                return source1 && source2 && getSourcePrimitive(source1) == getSourcePrimitive(source2);
     1221        }
     1222       
     1223       
     1224        function getSourcePrimitive(source) {
     1225                return ((typeof source == 'object') ? (source.events || source.url) : '') || source;
     1226        }
     1227
     1228
     1229}
     1230
     1231
     1232fc.addDays = addDays;
     1233fc.cloneDate = cloneDate;
     1234fc.parseDate = parseDate;
     1235fc.parseISO8601 = parseISO8601;
     1236fc.parseTime = parseTime;
     1237fc.formatDate = formatDate;
     1238fc.formatDates = formatDates;
     1239
     1240
     1241
     1242/* Date Math
     1243-----------------------------------------------------------------------------*/
     1244
     1245var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
     1246        DAY_MS = 86400000,
     1247        HOUR_MS = 3600000,
     1248        MINUTE_MS = 60000;
     1249       
     1250
     1251function addYears(d, n, keepTime) {
     1252        d.setFullYear(d.getFullYear() + n);
     1253        if (!keepTime) {
     1254                clearTime(d);
     1255        }
     1256        return d;
     1257}
     1258
     1259
     1260function addMonths(d, n, keepTime) { // prevents day overflow/underflow
     1261        if (+d) { // prevent infinite looping on invalid dates
     1262                var m = d.getMonth() + n,
     1263                        check = cloneDate(d);
     1264                check.setDate(1);
     1265                check.setMonth(m);
     1266                d.setMonth(m);
     1267                if (!keepTime) {
     1268                        clearTime(d);
     1269                }
     1270                while (d.getMonth() != check.getMonth()) {
     1271                        d.setDate(d.getDate() + (d < check ? 1 : -1));
     1272                }
     1273        }
     1274        return d;
     1275}
     1276
     1277
     1278function addDays(d, n, keepTime) { // deals with daylight savings
     1279        if (+d) {
     1280                var dd = d.getDate() + n,
     1281                        check = cloneDate(d);
     1282                check.setHours(9); // set to middle of day
     1283                check.setDate(dd);
     1284                d.setDate(dd);
     1285                if (!keepTime) {
     1286                        clearTime(d);
     1287                }
     1288                fixDate(d, check);
     1289        }
     1290        return d;
     1291}
     1292
     1293
     1294function fixDate(d, check) { // force d to be on check's YMD, for daylight savings purposes
     1295        if (+d) { // prevent infinite looping on invalid dates
     1296                while (d.getDate() != check.getDate()) {
     1297                        d.setTime(+d + (d < check ? 1 : -1) * HOUR_MS);
     1298                }
     1299        }
     1300}
     1301
     1302
     1303function addMinutes(d, n) {
     1304        d.setMinutes(d.getMinutes() + n);
     1305        return d;
     1306}
     1307
     1308
     1309function clearTime(d) {
     1310        d.setHours(0);
     1311        d.setMinutes(0);
     1312        d.setSeconds(0);
     1313        d.setMilliseconds(0);
     1314        return d;
     1315}
     1316
     1317
     1318function cloneDate(d, dontKeepTime) {
     1319        if (dontKeepTime) {
     1320                return clearTime(new Date(+d));
     1321        }
     1322        return new Date(+d);
     1323}
     1324
     1325
     1326function zeroDate() { // returns a Date with time 00:00:00 and dateOfMonth=1
     1327        var i=0, d;
     1328        do {
     1329                d = new Date(1970, i++, 1);
     1330        } while (d.getHours()); // != 0
     1331        return d;
     1332}
     1333
     1334
     1335function skipWeekend(date, inc, excl) {
     1336        inc = inc || 1;
     1337        while (!date.getDay() || (excl && date.getDay()==1 || !excl && date.getDay()==6)) {
     1338                addDays(date, inc);
     1339        }
     1340        return date;
     1341}
     1342
     1343
     1344function dayDiff(d1, d2) { // d1 - d2
     1345        return Math.round((cloneDate(d1, true) - cloneDate(d2, true)) / DAY_MS);
     1346}
     1347
     1348
     1349function setYMD(date, y, m, d) {
     1350        if (y !== undefined && y != date.getFullYear()) {
     1351                date.setDate(1);
     1352                date.setMonth(0);
     1353                date.setFullYear(y);
     1354        }
     1355        if (m !== undefined && m != date.getMonth()) {
     1356                date.setDate(1);
     1357                date.setMonth(m);
     1358        }
     1359        if (d !== undefined) {
     1360                date.setDate(d);
     1361        }
     1362}
     1363
     1364
     1365
     1366/* Date Parsing
     1367-----------------------------------------------------------------------------*/
     1368
     1369
     1370function parseDate(s, ignoreTimezone) { // ignoreTimezone defaults to true
     1371        if (typeof s == 'object') { // already a Date object
     1372                return s;
     1373        }
     1374        if (typeof s == 'number') { // a UNIX timestamp
     1375                return new Date(s * 1000);
     1376        }
     1377        if (typeof s == 'string') {
     1378                if (s.match(/^\d+(\.\d+)?$/)) { // a UNIX timestamp
     1379                        return new Date(parseFloat(s) * 1000);
     1380                }
     1381                if (ignoreTimezone === undefined) {
     1382                        ignoreTimezone = true;
     1383                }
     1384                return parseISO8601(s, ignoreTimezone) || (s ? new Date(s) : null);
     1385        }
     1386        // TODO: never return invalid dates (like from new Date(<string>)), return null instead
     1387        return null;
     1388}
     1389
     1390
     1391function parseISO8601(s, ignoreTimezone) { // ignoreTimezone defaults to false
     1392        // derived from http://delete.me.uk/2005/03/iso8601.html
     1393        // TODO: for a know glitch/feature, read tests/issue_206_parseDate_dst.html
     1394        var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/);
     1395        if (!m) {
     1396                return null;
     1397        }
     1398        var date = new Date(m[1], 0, 1);
     1399        if (ignoreTimezone || !m[13]) {
     1400                var check = new Date(m[1], 0, 1, 9, 0);
     1401                if (m[3]) {
     1402                        date.setMonth(m[3] - 1);
     1403                        check.setMonth(m[3] - 1);
     1404                }
     1405                if (m[5]) {
     1406                        date.setDate(m[5]);
     1407                        check.setDate(m[5]);
     1408                }
     1409                fixDate(date, check);
     1410                if (m[7]) {
     1411                        date.setHours(m[7]);
     1412                }
     1413                if (m[8]) {
     1414                        date.setMinutes(m[8]);
     1415                }
     1416                if (m[10]) {
     1417                        date.setSeconds(m[10]);
     1418                }
     1419                if (m[12]) {
     1420                        date.setMilliseconds(Number("0." + m[12]) * 1000);
     1421                }
     1422                fixDate(date, check);
     1423        }else{
     1424                date.setUTCFullYear(
     1425                        m[1],
     1426                        m[3] ? m[3] - 1 : 0,
     1427                        m[5] || 1
     1428                );
     1429                date.setUTCHours(
     1430                        m[7] || 0,
     1431                        m[8] || 0,
     1432                        m[10] || 0,
     1433                        m[12] ? Number("0." + m[12]) * 1000 : 0
     1434                );
     1435                if (m[14]) {
     1436                        var offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0);
     1437                        offset *= m[15] == '-' ? 1 : -1;
     1438                        date = new Date(+date + (offset * 60 * 1000));
     1439                }
     1440        }
     1441        return date;
     1442}
     1443
     1444
     1445function parseTime(s) { // returns minutes since start of day
     1446        if (typeof s == 'number') { // an hour
     1447                return s * 60;
     1448        }
     1449        if (typeof s == 'object') { // a Date object
     1450                return s.getHours() * 60 + s.getMinutes();
     1451        }
     1452        var m = s.match(/(\d+)(?::(\d+))?\s*(\w+)?/);
     1453        if (m) {
     1454                var h = parseInt(m[1], 10);
     1455                if (m[3]) {
     1456                        h %= 12;
     1457                        if (m[3].toLowerCase().charAt(0) == 'p') {
     1458                                h += 12;
     1459                        }
     1460                }
     1461                return h * 60 + (m[2] ? parseInt(m[2], 10) : 0);
     1462        }
     1463}
     1464
     1465
     1466
     1467/* Date Formatting
     1468-----------------------------------------------------------------------------*/
     1469// TODO: use same function formatDate(date, [date2], format, [options])
     1470
     1471
     1472function formatDate(date, format, options) {
     1473        return formatDates(date, null, format, options);
     1474}
     1475
     1476
     1477function formatDates(date1, date2, format, options) {
     1478        options = options || defaults;
     1479        var date = date1,
     1480                otherDate = date2,
     1481                i, len = format.length, c,
     1482                i2, formatter,
     1483                res = '';
     1484        for (i=0; i<len; i++) {
     1485                c = format.charAt(i);
     1486                if (c == "'") {
     1487                        for (i2=i+1; i2<len; i2++) {
     1488                                if (format.charAt(i2) == "'") {
     1489                                        if (date) {
     1490                                                if (i2 == i+1) {
     1491                                                        res += "'";
     1492                                                }else{
     1493                                                        res += format.substring(i+1, i2);
     1494                                                }
     1495                                                i = i2;
     1496                                        }
     1497                                        break;
     1498                                }
     1499                        }
     1500                }
     1501                else if (c == '(') {
     1502                        for (i2=i+1; i2<len; i2++) {
     1503                                if (format.charAt(i2) == ')') {
     1504                                        var subres = formatDate(date, format.substring(i+1, i2), options);
     1505                                        if (parseInt(subres.replace(/\D/, ''), 10)) {
     1506                                                res += subres;
     1507                                        }
     1508                                        i = i2;
     1509                                        break;
     1510                                }
     1511                        }
     1512                }
     1513                else if (c == '[') {
     1514                        for (i2=i+1; i2<len; i2++) {
     1515                                if (format.charAt(i2) == ']') {
     1516                                        var subformat = format.substring(i+1, i2);
     1517                                        var subres = formatDate(date, subformat, options);
     1518                                        if (subres != formatDate(otherDate, subformat, options)) {
     1519                                                res += subres;
     1520                                        }
     1521                                        i = i2;
     1522                                        break;
     1523                                }
     1524                        }
     1525                }
     1526                else if (c == '{') {
     1527                        date = date2;
     1528                        otherDate = date1;
     1529                }
     1530                else if (c == '}') {
     1531                        date = date1;
     1532                        otherDate = date2;
     1533                }
     1534                else {
     1535                        for (i2=len; i2>i; i2--) {
     1536                                if (formatter = dateFormatters[format.substring(i, i2)]) {
     1537                                        if (date) {
     1538                                                res += formatter(date, options);
     1539                                        }
     1540                                        i = i2 - 1;
     1541                                        break;
     1542                                }
     1543                        }
     1544                        if (i2 == i) {
     1545                                if (date) {
     1546                                        res += c;
     1547                                }
     1548                        }
     1549                }
     1550        }
     1551        return res;
     1552};
     1553
     1554
     1555var dateFormatters = {
     1556        s       : function(d)   { return d.getSeconds() },
     1557        ss      : function(d)   { return zeroPad(d.getSeconds()) },
     1558        m       : function(d)   { return d.getMinutes() },
     1559        mm      : function(d)   { return zeroPad(d.getMinutes()) },
     1560        h       : function(d)   { return d.getHours() % 12 || 12 },
     1561        hh      : function(d)   { return zeroPad(d.getHours() % 12 || 12) },
     1562        H       : function(d)   { return d.getHours() },
     1563        HH      : function(d)   { return zeroPad(d.getHours()) },
     1564        d       : function(d)   { return d.getDate() },
     1565        dd      : function(d)   { return zeroPad(d.getDate()) },
     1566        ddd     : function(d,o) { return o.dayNamesShort[d.getDay()] },
     1567        dddd: function(d,o)     { return o.dayNames[d.getDay()] },
     1568        M       : function(d)   { return d.getMonth() + 1 },
     1569        MM      : function(d)   { return zeroPad(d.getMonth() + 1) },
     1570        MMM     : function(d,o) { return o.monthNamesShort[d.getMonth()] },
     1571        MMMM: function(d,o)     { return o.monthNames[d.getMonth()] },
     1572        yy      : function(d)   { return (d.getFullYear()+'').substring(2) },
     1573        yyyy: function(d)       { return d.getFullYear() },
     1574        t       : function(d)   { return d.getHours() < 12 ? 'a' : 'p' },
     1575        tt      : function(d)   { return d.getHours() < 12 ? 'am' : 'pm' },
     1576        T       : function(d)   { return d.getHours() < 12 ? 'A' : 'P' },
     1577        TT      : function(d)   { return d.getHours() < 12 ? 'AM' : 'PM' },
     1578        u       : function(d)   { return formatDate(d, "yyyy-MM-dd'T'HH:mm:ss'Z'") },
     1579        S       : function(d)   {
     1580                var date = d.getDate();
     1581                if (date > 10 && date < 20) {
     1582                        return 'th';
     1583                }
     1584                return ['st', 'nd', 'rd'][date%10-1] || 'th';
     1585        }
     1586};
     1587
     1588
     1589
     1590fc.applyAll = applyAll;
     1591
     1592
     1593/* Event Date Math
     1594-----------------------------------------------------------------------------*/
     1595
     1596
     1597function exclEndDay(event) {
     1598        if (event.end) {
     1599                return _exclEndDay(event.end, event.allDay);
     1600        }else{
     1601                return addDays(cloneDate(event.start), 1);
     1602        }
     1603}
     1604
     1605
     1606function _exclEndDay(end, allDay) {
     1607        end = cloneDate(end);
     1608        return allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end);
     1609}
     1610
     1611
     1612function segCmp(a, b) {
     1613        return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);
     1614}
     1615
     1616
     1617function segsCollide(seg1, seg2) {
     1618        return seg1.end > seg2.start && seg1.start < seg2.end;
     1619}
     1620
     1621
     1622
     1623/* Event Sorting
     1624-----------------------------------------------------------------------------*/
     1625
     1626
     1627// event rendering utilities
     1628function sliceSegs(events, visEventEnds, start, end) {
     1629        var segs = [],
     1630                i, len=events.length, event,
     1631                eventStart, eventEnd,
     1632                segStart, segEnd,
     1633                isStart, isEnd;
     1634        for (i=0; i<len; i++) {
     1635                event = events[i];
     1636                eventStart = event.start;
     1637                eventEnd = visEventEnds[i];
     1638                if (eventEnd > start && eventStart < end) {
     1639                        if (eventStart < start) {
     1640                                segStart = cloneDate(start);
     1641                                isStart = false;
     1642                        }else{
     1643                                segStart = eventStart;
     1644                                isStart = true;
     1645                        }
     1646                        if (eventEnd > end) {
     1647                                segEnd = cloneDate(end);
     1648                                isEnd = false;
     1649                        }else{
     1650                                segEnd = eventEnd;
     1651                                isEnd = true;
     1652                        }
     1653                        segs.push({
     1654                                event: event,
     1655                                start: segStart,
     1656                                end: segEnd,
     1657                                isStart: isStart,
     1658                                isEnd: isEnd,
     1659                                msLength: segEnd - segStart
     1660                        });
     1661                }
     1662        }
     1663        return segs.sort(segCmp);
     1664}
     1665
     1666
     1667// event rendering calculation utilities
     1668function stackSegs(segs) {
     1669        var levels = [],
     1670                i, len = segs.length, seg,
     1671                j, collide, k;
     1672        for (i=0; i<len; i++) {
     1673                seg = segs[i];
     1674                j = 0; // the level index where seg should belong
     1675                while (true) {
     1676                        collide = false;
     1677                        if (levels[j]) {
     1678                                for (k=0; k<levels[j].length; k++) {
     1679                                        if (segsCollide(levels[j][k], seg)) {
     1680                                                collide = true;
     1681                                                break;
     1682                                        }
     1683                                }
     1684                        }
     1685                        if (collide) {
     1686                                j++;
     1687                        }else{
     1688                                break;
     1689                        }
     1690                }
     1691                if (levels[j]) {
     1692                        levels[j].push(seg);
     1693                }else{
     1694                        levels[j] = [seg];
     1695                }
     1696        }
     1697        return levels;
     1698}
     1699
     1700
     1701
     1702/* Event Element Binding
     1703-----------------------------------------------------------------------------*/
     1704
     1705
     1706function lazySegBind(container, segs, bindHandlers) {
     1707        container.unbind('mouseover').mouseover(function(ev) {
     1708                var parent=ev.target, e,
     1709                        i, seg;
     1710                while (parent != this) {
     1711                        e = parent;
     1712                        parent = parent.parentNode;
     1713                }
     1714                if ((i = e._fci) !== undefined) {
     1715                        e._fci = undefined;
     1716                        seg = segs[i];
     1717                        bindHandlers(seg.event, seg.element, seg);
     1718                        $(ev.target).trigger(ev);
     1719                }
     1720                ev.stopPropagation();
     1721        });
     1722}
     1723
     1724
     1725
     1726/* Element Dimensions
     1727-----------------------------------------------------------------------------*/
     1728
     1729
     1730function setOuterWidth(element, width, includeMargins) {
     1731        for (var i=0, e; i<element.length; i++) {
     1732                e = $(element[i]);
     1733                e.width(Math.max(0, width - hsides(e, includeMargins)));
     1734        }
     1735}
     1736
     1737
     1738function setOuterHeight(element, height, includeMargins) {
     1739        for (var i=0, e; i<element.length; i++) {
     1740                e = $(element[i]);
     1741                e.height(Math.max(0, height - vsides(e, includeMargins)));
     1742        }
     1743}
     1744
     1745
     1746// TODO: curCSS has been deprecated (jQuery 1.4.3 - 10/16/2010)
     1747
     1748
     1749function hsides(element, includeMargins) {
     1750        return hpadding(element) + hborders(element) + (includeMargins ? hmargins(element) : 0);
     1751}
     1752
     1753
     1754function hpadding(element) {
     1755        return (parseFloat($.curCSS(element[0], 'paddingLeft', true)) || 0) +
     1756               (parseFloat($.curCSS(element[0], 'paddingRight', true)) || 0);
     1757}
     1758
     1759
     1760function hmargins(element) {
     1761        return (parseFloat($.curCSS(element[0], 'marginLeft', true)) || 0) +
     1762               (parseFloat($.curCSS(element[0], 'marginRight', true)) || 0);
     1763}
     1764
     1765
     1766function hborders(element) {
     1767        return (parseFloat($.curCSS(element[0], 'borderLeftWidth', true)) || 0) +
     1768               (parseFloat($.curCSS(element[0], 'borderRightWidth', true)) || 0);
     1769}
     1770
     1771
     1772function vsides(element, includeMargins) {
     1773        return vpadding(element) +  vborders(element) + (includeMargins ? vmargins(element) : 0);
     1774}
     1775
     1776
     1777function vpadding(element) {
     1778        return (parseFloat($.curCSS(element[0], 'paddingTop', true)) || 0) +
     1779               (parseFloat($.curCSS(element[0], 'paddingBottom', true)) || 0);
     1780}
     1781
     1782
     1783function vmargins(element) {
     1784        return (parseFloat($.curCSS(element[0], 'marginTop', true)) || 0) +
     1785               (parseFloat($.curCSS(element[0], 'marginBottom', true)) || 0);
     1786}
     1787
     1788
     1789function vborders(element) {
     1790        return (parseFloat($.curCSS(element[0], 'borderTopWidth', true)) || 0) +
     1791               (parseFloat($.curCSS(element[0], 'borderBottomWidth', true)) || 0);
     1792}
     1793
     1794
     1795function setMinHeight(element, height) {
     1796        height = (typeof height == 'number' ? height + 'px' : height);
     1797        element.each(function(i, _element) {
     1798                _element.style.cssText += ';min-height:' + height + ';_height:' + height;
     1799                // why can't we just use .css() ? i forget
     1800        });
     1801}
     1802
     1803
     1804
     1805/* Misc Utils
     1806-----------------------------------------------------------------------------*/
     1807
     1808
     1809//TODO: arraySlice
     1810//TODO: isFunction, grep ?
     1811
     1812
     1813function noop() { }
     1814
     1815
     1816function cmp(a, b) {
     1817        return a - b;
     1818}
     1819
     1820
     1821function arrayMax(a) {
     1822        return Math.max.apply(Math, a);
     1823}
     1824
     1825
     1826function zeroPad(n) {
     1827        return (n < 10 ? '0' : '') + n;
     1828}
     1829
     1830
     1831function smartProperty(obj, name) { // get a camel-cased/namespaced property of an object
     1832        if (obj[name] !== undefined) {
     1833                return obj[name];
     1834        }
     1835        var parts = name.split(/(?=[A-Z])/),
     1836                i=parts.length-1, res;
     1837        for (; i>=0; i--) {
     1838                res = obj[parts[i].toLowerCase()];
     1839                if (res !== undefined) {
     1840                        return res;
     1841                }
     1842        }
     1843        return obj[''];
     1844}
     1845
     1846
     1847function htmlEscape(s) {
     1848        return s.replace(/&/g, '&amp;')
     1849                .replace(/</g, '&lt;')
     1850                .replace(/>/g, '&gt;')
     1851                .replace(/'/g, '&#039;')
     1852                .replace(/"/g, '&quot;')
     1853                .replace(/\n/g, '<br />');
     1854}
     1855
     1856
     1857function cssKey(_element) {
     1858        return _element.id + '/' + _element.className + '/' + _element.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig, '');
     1859}
     1860
     1861
     1862function disableTextSelection(element) {
     1863        element
     1864                .attr('unselectable', 'on')
     1865                .css('MozUserSelect', 'none')
     1866                .bind('selectstart.ui', function() { return false; });
     1867}
     1868
     1869
     1870/*
     1871function enableTextSelection(element) {
     1872        element
     1873                .attr('unselectable', 'off')
     1874                .css('MozUserSelect', '')
     1875                .unbind('selectstart.ui');
     1876}
     1877*/
     1878
     1879
     1880function markFirstLast(e) {
     1881        e.children()
     1882                .removeClass('fc-first fc-last')
     1883                .filter(':first-child')
     1884                        .addClass('fc-first')
     1885                .end()
     1886                .filter(':last-child')
     1887                        .addClass('fc-last');
     1888}
     1889
     1890
     1891function setDayID(cell, date) {
     1892        cell.each(function(i, _cell) {
     1893                _cell.className = _cell.className.replace(/^fc-\w*/, 'fc-' + dayIDs[date.getDay()]);
     1894                // TODO: make a way that doesn't rely on order of classes
     1895        });
     1896}
     1897
     1898
     1899function getSkinCss(event, opt) {
     1900        var source = event.source || {};
     1901        var eventColor = event.color;
     1902        var sourceColor = source.color;
     1903        var optionColor = opt('eventColor');
     1904        var backgroundColor =
     1905                event.backgroundColor ||
     1906                eventColor ||
     1907                source.backgroundColor ||
     1908                sourceColor ||
     1909                opt('eventBackgroundColor') ||
     1910                optionColor;
     1911        var borderColor =
     1912                event.borderColor ||
     1913                eventColor ||
     1914                source.borderColor ||
     1915                sourceColor ||
     1916                opt('eventBorderColor') ||
     1917                optionColor;
     1918        var textColor =
     1919                event.textColor ||
     1920                source.textColor ||
     1921                opt('eventTextColor');
     1922        var statements = [];
     1923        if (backgroundColor) {
     1924                statements.push('background-color:' + backgroundColor);
     1925        }
     1926        if (borderColor) {
     1927                statements.push('border-color:' + borderColor);
     1928        }
     1929        if (textColor) {
     1930                statements.push('color:' + textColor);
     1931        }
     1932        return statements.join(';');
     1933}
     1934
     1935
     1936function applyAll(functions, thisObj, args) {
     1937        if ($.isFunction(functions)) {
     1938                functions = [ functions ];
     1939        }
     1940        if (functions) {
     1941                var i;
     1942                var ret;
     1943                for (i=0; i<functions.length; i++) {
     1944                        ret = functions[i].apply(thisObj, args) || ret;
     1945                }
     1946                return ret;
     1947        }
     1948}
     1949
     1950
     1951function firstDefined() {
     1952        for (var i=0; i<arguments.length; i++) {
     1953                if (arguments[i] !== undefined) {
     1954                        return arguments[i];
     1955                }
     1956        }
     1957}
     1958
     1959
    11191960
    11201961fcViews.month = MonthView;
     
    11642005                t.visStart = visStart;
    11652006                t.visEnd = visEnd;
    1166                 renderBasic(rowCnt, nwe ? 5 : 7, true);
     2007                renderBasic(6, rowCnt, nwe ? 5 : 7, true);
    11672008        }
    11682009       
     
    12102051                t.visStart = visStart;
    12112052                t.visEnd = visEnd;
    1212                 renderBasic(1, weekends ? 7 : 5, false);
     2053                renderBasic(1, 1, weekends ? 7 : 5, false);
    12132054        }
    12142055       
     
    12472088                t.start = t.visStart = cloneDate(date, true);
    12482089                t.end = t.visEnd = addDays(cloneDate(t.start), 1);
    1249                 renderBasic(1, 1, false);
    1250         }
    1251        
    1252        
    1253 }
    1254 
    1255 var tdHeightBug;
     2090                renderBasic(1, 1, 1, false);
     2091        }
     2092       
     2093       
     2094}
    12562095
    12572096setDefaults({
     
    12722111        t.renderSelection = renderSelection;
    12732112        t.clearSelection = clearSelection;
     2113        t.reportDayClick = reportDayClick; // for selection (kinda hacky)
    12742114        t.dragStart = dragStart;
    12752115        t.dragStop = dragStop;
     
    12822122        t.cellDate = cellDate;
    12832123        t.cellIsAllDay = function() { return true };
    1284         t.allDayTR = allDayTR;
     2124        t.allDayRow = allDayRow;
    12852125        t.allDayBounds = allDayBounds;
    12862126        t.getRowCnt = function() { return rowCnt };
     
    13052145       
    13062146        // locals
     2147       
     2148        var head;
     2149        var headCells;
     2150        var body;
     2151        var bodyRows;
     2152        var bodyCells;
     2153        var bodyFirstCells;
     2154        var bodyCellTopInners;
     2155        var daySegmentContainer;
     2156       
     2157        var viewWidth;
     2158        var viewHeight;
     2159        var colWidth;
     2160       
     2161        var rowCnt, colCnt;
     2162        var coordinateGrid;
     2163        var hoverListener;
     2164        var colContentPositions;
     2165       
    13072166        var rtl, dis, dit;
    13082167        var firstDay;
    13092168        var nwe;
    1310         var rowCnt, colCnt;
    1311         var colWidth;
    1312         var viewWidth, viewHeight;
    1313         var thead, tbody;
    1314         var daySegmentContainer;
    1315         var coordinateGrid;
    1316         var hoverListener;
    1317         var colContentPositions;
     2169        var tm;
     2170        var colFormat;
    13182171       
    13192172       
     
    13262179       
    13272180       
    1328         function renderBasic(r, c, showNumbers) {
    1329        
     2181        function renderBasic(maxr, r, c, showNumbers) {
    13302182                rowCnt = r;
    13312183                colCnt = c;
     2184                updateOptions();
     2185                var firstTime = !body;
     2186                if (firstTime) {
     2187                        buildSkeleton(maxr, showNumbers);
     2188                }else{
     2189                        clearEvents();
     2190                }
     2191                updateCells(firstTime);
     2192        }
     2193       
     2194       
     2195       
     2196        function updateOptions() {
    13322197                rtl = opt('isRTL');
    13332198                if (rtl) {
     
    13402205                firstDay = opt('firstDay');
    13412206                nwe = opt('weekends') ? 0 : 1;
     2207                tm = opt('theme') ? 'ui' : 'fc';
     2208                colFormat = opt('columnFormat');
     2209        }
     2210       
     2211       
     2212       
     2213        function buildSkeleton(maxRowCnt, showNumbers) {
     2214                var s;
     2215                var headerClass = tm + "-widget-header";
     2216                var contentClass = tm + "-widget-content";
     2217                var i, j;
     2218                var table;
    13422219               
    1343                 var tm = opt('theme') ? 'ui' : 'fc';
    1344                 var colFormat = opt('columnFormat');
     2220                s =
     2221                        "<table class='fc-border-separate' style='width:100%' cellspacing='0'>" +
     2222                        "<thead>" +
     2223                        "<tr>";
     2224                for (i=0; i<colCnt; i++) {
     2225                        s +=
     2226                                "<th class='fc- " + headerClass + "'/>"; // need fc- for setDayID
     2227                }
     2228                s +=
     2229                        "</tr>" +
     2230                        "</thead>" +
     2231                        "<tbody>";
     2232                for (i=0; i<maxRowCnt; i++) {
     2233                        s +=
     2234                                "<tr class='fc-week" + i + "'>";
     2235                        for (j=0; j<colCnt; j++) {
     2236                                s +=
     2237                                        "<td class='fc- " + contentClass + " fc-day" + (i*colCnt+j) + "'>" + // need fc- for setDayID
     2238                                        "<div>" +
     2239                                        (showNumbers ?
     2240                                                "<div class='fc-day-number'/>" :
     2241                                                ''
     2242                                                ) +
     2243                                        "<div class='fc-day-content'>" +
     2244                                        "<div style='position:relative'>&nbsp;</div>" +
     2245                                        "</div>" +
     2246                                        "</div>" +
     2247                                        "</td>";
     2248                        }
     2249                        s +=
     2250                                "</tr>";
     2251                }
     2252                s +=
     2253                        "</tbody>" +
     2254                        "</table>";
     2255                table = $(s).appendTo(element);
     2256               
     2257                head = table.find('thead');
     2258                headCells = head.find('th');
     2259                body = table.find('tbody');
     2260                bodyRows = body.find('tr');
     2261                bodyCells = body.find('td');
     2262                bodyFirstCells = bodyCells.filter(':first-child');
     2263                bodyCellTopInners = bodyRows.eq(0).find('div.fc-day-content div');
     2264               
     2265                markFirstLast(head.add(head.find('tr'))); // marks first+last tr/th's
     2266                markFirstLast(bodyRows); // marks first+last td's
     2267                bodyRows.eq(0).addClass('fc-first'); // fc-last is done in updateCells
     2268               
     2269                dayBind(bodyCells);
     2270               
     2271                daySegmentContainer =
     2272                        $("<div style='position:absolute;z-index:8;top:0;left:0'/>")
     2273                                .appendTo(element);
     2274        }
     2275       
     2276       
     2277       
     2278        function updateCells(firstTime) {
     2279                var dowDirty = firstTime || rowCnt == 1; // could the cells' day-of-weeks need updating?
    13452280                var month = t.start.getMonth();
    13462281                var today = clearTime(new Date());
    1347                 var s, i, j, d = cloneDate(t.visStart);
     2282                var cell;
     2283                var date;
     2284                var row;
     2285       
     2286                if (dowDirty) {
     2287                        headCells.each(function(i, _cell) {
     2288                                cell = $(_cell);
     2289                                date = indexDate(i);
     2290                                cell.html(formatDate(date, colFormat));
     2291                                setDayID(cell, date);
     2292                        });
     2293                }
    13482294               
    1349                 if (!tbody) { // first time, build all cells from scratch
     2295                bodyCells.each(function(i, _cell) {
     2296                        cell = $(_cell);
     2297                        date = indexDate(i);
     2298                        if (date.getMonth() == month) {
     2299                                cell.removeClass('fc-other-month');
     2300                        }else{
     2301                                cell.addClass('fc-other-month');
     2302                        }
     2303                        if (+date == +today) {
     2304                                cell.addClass(tm + '-state-highlight fc-today');
     2305                        }else{
     2306                                cell.removeClass(tm + '-state-highlight fc-today');
     2307                        }
     2308                        cell.find('div.fc-day-number').text(date.getDate());
     2309                        if (dowDirty) {
     2310                                setDayID(cell, date);
     2311                        }
     2312                });
    13502313               
    1351                         var table = $("<table/>").appendTo(element);
    1352                        
    1353                         s = "<thead><tr>";
    1354                         for (i=0; i<colCnt; i++) {
    1355                                 s += "<th class='fc-" +
    1356                                         dayIDs[d.getDay()] + ' ' + // needs to be first
    1357                                         tm + '-state-default' +
    1358                                         (i==dit ? ' fc-leftmost' : '') +
    1359                                         "'>" + formatDate(d, colFormat) + "</th>";
    1360                                 addDays(d, 1);
    1361                                 if (nwe) {
    1362                                         skipWeekend(d);
    1363                                 }
    1364                         }
    1365                         thead = $(s + "</tr></thead>").appendTo(table);
    1366                        
    1367                         s = "<tbody>";
    1368                         d = cloneDate(t.visStart);
    1369                         for (i=0; i<rowCnt; i++) {
    1370                                 s += "<tr class='fc-week" + i + "'>";
    1371                                 for (j=0; j<colCnt; j++) {
    1372                                         s += "<td class='fc-" +
    1373                                                 dayIDs[d.getDay()] + ' ' + // needs to be first
    1374                                                 tm + '-state-default fc-day' + (i*colCnt+j) +
    1375                                                 (j==dit ? ' fc-leftmost' : '') +
    1376                                                 (rowCnt>1 && d.getMonth() != month ? ' fc-other-month' : '') +
    1377                                                 (+d == +today ?
    1378                                                 ' fc-today '+tm+'-state-highlight' :
    1379                                                 ' fc-not-today') + "'>" +
    1380                                                 (showNumbers ? "<div class='fc-day-number'>" + d.getDate() + "</div>" : '') +
    1381                                                 "<div class='fc-day-content'><div style='position:relative'>&nbsp;</div></div></td>";
    1382                                         addDays(d, 1);
    1383                                         if (nwe) {
    1384                                                 skipWeekend(d);
    1385                                         }
    1386                                 }
    1387                                 s += "</tr>";
    1388                         }
    1389                         tbody = $(s + "</tbody>").appendTo(table);
    1390                         dayBind(tbody.find('td'));
    1391                        
    1392                         daySegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(element);
    1393                
    1394                 }else{ // NOT first time, reuse as many cells as possible
    1395                
    1396                         clearEvents();
    1397                
    1398                         var prevRowCnt = tbody.find('tr').length;
    1399                         if (rowCnt < prevRowCnt) {
    1400                                 tbody.find('tr:gt(' + (rowCnt-1) + ')').remove(); // remove extra rows
    1401                         }
    1402                         else if (rowCnt > prevRowCnt) { // needs to create new rows...
    1403                                 s = '';
    1404                                 for (i=prevRowCnt; i<rowCnt; i++) {
    1405                                         s += "<tr class='fc-week" + i + "'>";
    1406                                         for (j=0; j<colCnt; j++) {
    1407                                                 s += "<td class='fc-" +
    1408                                                         dayIDs[d.getDay()] + ' ' + // needs to be first
    1409                                                         tm + '-state-default fc-new fc-day' + (i*colCnt+j) +
    1410                                                         (j==dit ? ' fc-leftmost' : '') + "'>" +
    1411                                                         (showNumbers ? "<div class='fc-day-number'></div>" : '') +
    1412                                                         "<div class='fc-day-content'><div style='position:relative'>&nbsp;</div></div>" +
    1413                                                         "</td>";
    1414                                                 addDays(d, 1);
    1415                                                 if (nwe) {
    1416                                                         skipWeekend(d);
    1417                                                 }
    1418                                         }
    1419                                         s += "</tr>";
    1420                                 }
    1421                                 tbody.append(s);
    1422                         }
    1423                         dayBind(tbody.find('td.fc-new').removeClass('fc-new'));
    1424                        
    1425                         // re-label and re-class existing cells
    1426                         d = cloneDate(t.visStart);
    1427                         tbody.find('td').each(function() {
    1428                                 var td = $(this);
    1429                                 if (rowCnt > 1) {
    1430                                         if (d.getMonth() == month) {
    1431                                                 td.removeClass('fc-other-month');
    1432                                         }else{
    1433                                                 td.addClass('fc-other-month');
    1434                                         }
    1435                                 }
    1436                                 if (+d == +today) {
    1437                                         td.removeClass('fc-not-today')
    1438                                                 .addClass('fc-today')
    1439                                                 .addClass(tm + '-state-highlight');
     2314                bodyRows.each(function(i, _row) {
     2315                        row = $(_row);
     2316                        if (i < rowCnt) {
     2317                                row.show();
     2318                                if (i == rowCnt-1) {
     2319                                        row.addClass('fc-last');
    14402320                                }else{
    1441                                         td.addClass('fc-not-today')
    1442                                                 .removeClass('fc-today')
    1443                                                 .removeClass(tm + '-state-highlight');
    1444                                 }
    1445                                 td.find('div.fc-day-number').text(d.getDate());
    1446                                 addDays(d, 1);
    1447                                 if (nwe) {
    1448                                         skipWeekend(d);
    1449                                 }
    1450                         });
    1451                        
    1452                         if (rowCnt == 1) { // more changes likely (week or day view)
    1453                        
    1454                                 // redo column header text and class
    1455                                 d = cloneDate(t.visStart);
    1456                                 thead.find('th').each(function(i, th) {
    1457                                         $(th).text(formatDate(d, colFormat));
    1458                                         th.className = th.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
    1459                                         addDays(d, 1);
    1460                                         if (nwe) {
    1461                                                 skipWeekend(d);
    1462                                         }
    1463                                 });
    1464                                
    1465                                 // redo cell day-of-weeks
    1466                                 d = cloneDate(t.visStart);
    1467                                 tbody.find('td').each(function(i, td) {
    1468                                         td.className = td.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
    1469                                         addDays(d, 1);
    1470                                         if (nwe) {
    1471                                                 skipWeekend(d);
    1472                                         }
    1473                                 });
    1474                                
    1475                         }
    1476                
    1477                 }
    1478                
    1479         }
     2321                                        row.removeClass('fc-last');
     2322                                }
     2323                        }else{
     2324                                row.hide();
     2325                        }
     2326                });
     2327        }
     2328       
    14802329       
    14812330       
    14822331        function setHeight(height) {
    14832332                viewHeight = height;
    1484                 var leftTDs = tbody.find('tr td:first-child'),
    1485                         tbodyHeight = viewHeight - thead.height(),
    1486                         rowHeight1, rowHeight2;
     2333               
     2334                var bodyHeight = viewHeight - head.height();
     2335                var rowHeight;
     2336                var rowHeightLast;
     2337                var cell;
     2338                       
    14872339                if (opt('weekMode') == 'variable') {
    1488                         rowHeight1 = rowHeight2 = Math.floor(tbodyHeight / (rowCnt==1 ? 2 : 6));
     2340                        rowHeight = rowHeightLast = Math.floor(bodyHeight / (rowCnt==1 ? 2 : 6));
    14892341                }else{
    1490                         rowHeight1 = Math.floor(tbodyHeight / rowCnt);
    1491                         rowHeight2 = tbodyHeight - rowHeight1*(rowCnt-1);
    1492                 }
    1493                 if (tdHeightBug === undefined) {
    1494                         // bug in firefox where cell height includes padding
    1495                         var tr = tbody.find('tr:first'),
    1496                                 td = tr.find('td:first');
    1497                         td.height(rowHeight1);
    1498                         tdHeightBug = rowHeight1 != td.height();
    1499                 }
    1500                 if (tdHeightBug) {
    1501                         leftTDs.slice(0, -1).height(rowHeight1);
    1502                         leftTDs.slice(-1).height(rowHeight2);
    1503                 }else{
    1504                         setOuterHeight(leftTDs.slice(0, -1), rowHeight1);
    1505                         setOuterHeight(leftTDs.slice(-1), rowHeight2);
    1506                 }
     2342                        rowHeight = Math.floor(bodyHeight / rowCnt);
     2343                        rowHeightLast = bodyHeight - rowHeight * (rowCnt-1);
     2344                }
     2345               
     2346                bodyFirstCells.each(function(i, _cell) {
     2347                        if (i < rowCnt) {
     2348                                cell = $(_cell);
     2349                                setMinHeight(
     2350                                        cell.find('> div'),
     2351                                        (i==rowCnt-1 ? rowHeightLast : rowHeight) - vsides(cell)
     2352                                );
     2353                        }
     2354                });
     2355               
    15072356        }
    15082357       
     
    15122361                colContentPositions.clear();
    15132362                colWidth = Math.floor(viewWidth / colCnt);
    1514                 setOuterWidth(thead.find('th').slice(0, -1), colWidth);
     2363                setOuterWidth(headCells.slice(0, -1), colWidth);
    15152364        }
    15162365       
     
    15282377       
    15292378        function dayClick(ev) {
    1530                 if (!opt('selectable')) { // SelectionManager will worry about dayClick
    1531                         var n = parseInt(this.className.match(/fc\-day(\d+)/)[1]),
    1532                                 date = addDays(
    1533                                         cloneDate(t.visStart),
    1534                                         Math.floor(n/colCnt) * 7 + n % colCnt
    1535                                 );
    1536                         // TODO: what about weekends in middle of week?
     2379                if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick
     2380                        var index = parseInt(this.className.match(/fc\-day(\d+)/)[1]); // TODO: maybe use .data
     2381                        var date = indexDate(index);
    15372382                        trigger('dayClick', this, date, true, ev);
    15382383                }
     
    15992444       
    16002445       
     2446        function reportDayClick(date, allDay, ev) {
     2447                var cell = dateCell(date);
     2448                var _element = bodyCells[cell.row*colCnt + cell.col];
     2449                trigger('dayClick', _element, date, allDay, ev);
     2450        }
     2451       
     2452       
    16012453       
    16022454        /* External Dragging
     
    16362488        coordinateGrid = new CoordinateGrid(function(rows, cols) {
    16372489                var e, n, p;
    1638                 var tds = tbody.find('tr:first td');
    1639                 if (rtl) {
    1640                         tds = $(tds.get().reverse());
    1641                 }
    1642                 tds.each(function(i, _e) {
     2490                headCells.each(function(i, _e) {
    16432491                        e = $(_e);
    16442492                        n = e.offset().left;
     
    16502498                });
    16512499                p[1] = n + e.outerWidth();
    1652                 tbody.find('tr').each(function(i, _e) {
    1653                         e = $(_e);
    1654                         n = e.offset().top;
    1655                         if (i) {
    1656                                 p[1] = n;
    1657                         }
    1658                         p = [n];
    1659                         rows[i] = p;
     2500                bodyRows.each(function(i, _e) {
     2501                        if (i < rowCnt) {
     2502                                e = $(_e);
     2503                                n = e.offset().top;
     2504                                if (i) {
     2505                                        p[1] = n;
     2506                                }
     2507                                p = [n];
     2508                                rows[i] = p;
     2509                        }
    16602510                });
    16612511                p[1] = n + e.outerHeight();
     
    16672517       
    16682518        colContentPositions = new HorizontalPositionCache(function(col) {
    1669                 return tbody.find('td:eq(' + col + ') div div');
     2519                return bodyCellTopInners.eq(col);
    16702520        });
    16712521       
     
    16812531       
    16822532       
    1683         function dayOfWeekCol(dayOfWeek) {
    1684                 return (dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt;
    1685         }
    16862533       
    16872534       
     
    16892536                return {
    16902537                        row: Math.floor(dayDiff(date, t.visStart) / 7),
    1691                         col: dayOfWeekCol(date.getDay())*dis + dit
     2538                        col: dayOfWeekCol(date.getDay())
    16922539                };
    16932540        }
     
    16952542       
    16962543        function cellDate(cell) {
    1697                 return addDays(cloneDate(t.visStart), cell.row*7 + cell.col*dis+dit);
    1698                 // TODO: what about weekends in middle of week?
    1699         }
    1700        
    1701        
    1702         function allDayTR(i) {
    1703                 return tbody.find('tr:eq('+i+')');
     2544                return _cellDate(cell.row, cell.col);
     2545        }
     2546       
     2547       
     2548        function _cellDate(row, col) {
     2549                return addDays(cloneDate(t.visStart), row*7 + col*dis+dit);
     2550                // what about weekends in middle of week?
     2551        }
     2552       
     2553       
     2554        function indexDate(index) {
     2555                return _cellDate(Math.floor(index/colCnt), index%colCnt);
     2556        }
     2557       
     2558       
     2559        function dayOfWeekCol(dayOfWeek) {
     2560                return ((dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt) * dis + dit;
     2561        }
     2562       
     2563       
     2564       
     2565       
     2566        function allDayRow(i) {
     2567                return bodyRows.eq(i);
    17042568        }
    17052569       
     
    17302594        var opt = t.opt;
    17312595        var trigger = t.trigger;
     2596        //var setOverflowHidden = t.setOverflowHidden;
     2597        var isEventDraggable = t.isEventDraggable;
     2598        var isEventResizable = t.isEventResizable;
    17322599        var reportEvents = t.reportEvents;
    17332600        var reportEventClear = t.reportEventClear;
     
    17922659       
    17932660        function bindDaySeg(event, eventElement, seg) {
     2661                if (isEventDraggable(event)) {
     2662                        draggableDayEvent(event, eventElement);
     2663                }
     2664                if (seg.isEnd && isEventResizable(event)) {
     2665                        resizableDayEvent(event, eventElement, seg);
     2666                }
    17942667                eventElementHandlers(event, eventElement);
    1795                 if (event.editable || event.editable === undefined && opt('editable')) {
    1796                         draggableDayEvent(event, eventElement);
    1797                         if (seg.isEnd) {
    1798                                 resizableDayEvent(event, eventElement, seg);
    1799                         }
    1800                 }
     2668                        // needs to be after, because resizableDayEvent might stopImmediatePropagation on click
    18012669        }
    18022670       
     
    18082676       
    18092677        function draggableDayEvent(event, eventElement) {
    1810                 if (!opt('disableDragging') && eventElement.draggable) {
    1811                         var hoverListener = getHoverListener();
    1812                         var dayDelta;
    1813                         eventElement.draggable({
    1814                                 zIndex: 9,
    1815                                 delay: 50,
    1816                                 opacity: opt('dragOpacity'),
    1817                                 revertDuration: opt('dragRevertDuration'),
    1818                                 start: function(ev, ui) {
    1819                                         trigger('eventDragStart', eventElement, event, ev, ui);
    1820                                         hideEvents(event, eventElement);
    1821                                         hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
    1822                                                 eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
    1823                                                 clearOverlays();
    1824                                                 if (cell) {
    1825                                                         dayDelta = rowDelta*7 + colDelta * (opt('isRTL') ? -1 : 1);
    1826                                                         renderDayOverlay(
    1827                                                                 addDays(cloneDate(event.start), dayDelta),
    1828                                                                 addDays(exclEndDay(event), dayDelta)
    1829                                                         );
    1830                                                 }else{
    1831                                                         dayDelta = 0;
    1832                                                 }
    1833                                         }, ev, 'drag');
    1834                                 },
    1835                                 stop: function(ev, ui) {
    1836                                         hoverListener.stop();
     2678                var hoverListener = getHoverListener();
     2679                var dayDelta;
     2680                eventElement.draggable({
     2681                        zIndex: 9,
     2682                        delay: 50,
     2683                        opacity: opt('dragOpacity'),
     2684                        revertDuration: opt('dragRevertDuration'),
     2685                        start: function(ev, ui) {
     2686                                trigger('eventDragStart', eventElement, event, ev, ui);
     2687                                hideEvents(event, eventElement);
     2688                                hoverListener.start(function(cell, origCell, rowDelta, colDelta) {
     2689                                        eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
    18372690                                        clearOverlays();
    1838                                         trigger('eventDragStop', eventElement, event, ev, ui);
    1839                                         if (dayDelta) {
    1840                                                 eventElement.find('a').removeAttr('href'); // prevents safari from visiting the link
    1841                                                 eventDrop(this, event, dayDelta, 0, event.allDay, ev, ui);
     2691                                        if (cell) {
     2692                                                //setOverflowHidden(true);
     2693                                                dayDelta = rowDelta*7 + colDelta * (opt('isRTL') ? -1 : 1);
     2694                                                renderDayOverlay(
     2695                                                        addDays(cloneDate(event.start), dayDelta),
     2696                                                        addDays(exclEndDay(event), dayDelta)
     2697                                                );
    18422698                                        }else{
    1843                                                 if ($.browser.msie) {
    1844                                                         eventElement.css('filter', ''); // clear IE opacity side-effects
    1845                                                 }
    1846                                                 showEvents(event, eventElement);
     2699                                                //setOverflowHidden(false);
     2700                                                dayDelta = 0;
    18472701                                        }
    1848                                 }
    1849                         });
    1850                 }
     2702                                }, ev, 'drag');
     2703                        },
     2704                        stop: function(ev, ui) {
     2705                                hoverListener.stop();
     2706                                clearOverlays();
     2707                                trigger('eventDragStop', eventElement, event, ev, ui);
     2708                                if (dayDelta) {
     2709                                        eventDrop(this, event, dayDelta, 0, event.allDay, ev, ui);
     2710                                }else{
     2711                                        eventElement.css('filter', ''); // clear IE opacity side-effects
     2712                                        showEvents(event, eventElement);
     2713                                }
     2714                                //setOverflowHidden(false);
     2715                        }
     2716                });
    18512717        }
    18522718
     
    19542820
    19552821
     2822// TODO: make it work in quirks mode (event corners, all-day height)
     2823// TODO: test liquid width, especially in IE6
     2824
     2825
    19562826function AgendaView(element, calendar, viewName) {
    19572827        var t = this;
     
    19702840        t.cellDate = cellDate;
    19712841        t.cellIsAllDay = cellIsAllDay;
    1972         t.allDayTR = allDayTR;
     2842        t.allDayRow = getAllDayRow;
    19732843        t.allDayBounds = allDayBounds;
    19742844        t.getHoverListener = function() { return hoverListener };
     
    19792849        t.getMinMinute = function() { return minMinute };
    19802850        t.getMaxMinute = function() { return maxMinute };
    1981         t.getBodyContent = function() { return bodyContent };
     2851        t.getBodyContent = function() { return slotContent }; // !!??
    19822852        t.getRowCnt = function() { return 1 };
    19832853        t.getColCnt = function() { return colCnt };
     
    19882858        t.renderSelection = renderSelection;
    19892859        t.clearSelection = clearSelection;
     2860        t.reportDayClick = reportDayClick; // selection mousedown hack
    19902861        t.dragStart = dragStart;
    19912862        t.dragStop = dragStop;
     
    20102881       
    20112882        // locals
    2012         var head, body, bodyContent, bodyTable, bg;
     2883       
     2884        var dayTable;
     2885        var dayHead;
     2886        var dayHeadCells;
     2887        var dayBody;
     2888        var dayBodyCells;
     2889        var dayBodyCellInners;
     2890        var dayBodyFirstCell;
     2891        var dayBodyFirstCellStretcher;
     2892        var slotLayer;
     2893        var daySegmentContainer;
     2894        var allDayTable;
     2895        var allDayRow;
     2896        var slotScroller;
     2897        var slotContent;
     2898        var slotSegmentContainer;
     2899        var slotTable;
     2900        var slotTableFirstInner;
     2901        var axisFirstCells;
     2902        var gutterCells;
     2903        var selectionHelper;
     2904       
     2905        var viewWidth;
     2906        var viewHeight;
     2907        var axisWidth;
     2908        var colWidth;
     2909        var gutterWidth;
     2910        var slotHeight; // TODO: what if slotHeight changes? (see issue 650)
     2911        var savedScrollTop;
     2912       
    20132913        var colCnt;
    2014         var slotCnt=0; // spanning all the way across
    2015         var axisWidth, colWidth, slotHeight; // TODO: what if slotHeight changes? (see issue 650)
    2016         var viewWidth, viewHeight;
    2017         var savedScrollTop;
    2018         var tm, firstDay;
    2019         var nwe;            // no weekends (int)
    2020         var rtl, dis, dit;  // day index sign / translate
    2021         var minMinute, maxMinute;
     2914        var slotCnt;
    20222915        var coordinateGrid;
    20232916        var hoverListener;
    20242917        var colContentPositions;
    20252918        var slotTopCache = {};
    2026         var selectionHelper;
    2027         var daySegmentContainer;
    2028         var slotSegmentContainer;
     2919       
     2920        var tm;
     2921        var firstDay;
     2922        var nwe;            // no weekends (int)
     2923        var rtl, dis, dit;  // day index sign / translate
     2924        var minMinute, maxMinute;
     2925        var colFormat;
    20292926       
    20302927
     
    20382935       
    20392936        function renderAgenda(c) {
    2040        
    20412937                colCnt = c;
    2042                
    2043                 // update option-derived variables
     2938                updateOptions();
     2939                if (!dayTable) {
     2940                        buildSkeleton();
     2941                }else{
     2942                        clearEvents();
     2943                }
     2944                updateCells();
     2945        }
     2946       
     2947       
     2948       
     2949        function updateOptions() {
    20442950                tm = opt('theme') ? 'ui' : 'fc';
    20452951                nwe = opt('weekends') ? 0 : 1;
     
    20542960                minMinute = parseTime(opt('minTime'));
    20552961                maxMinute = parseTime(opt('maxTime'));
     2962                colFormat = opt('columnFormat');
     2963        }
     2964       
     2965       
     2966       
     2967        function buildSkeleton() {
     2968                var headerClass = tm + "-widget-header";
     2969                var contentClass = tm + "-widget-content";
     2970                var s;
     2971                var i;
     2972                var d;
     2973                var maxd;
     2974                var minutes;
     2975                var slotNormal = opt('slotMinutes') % 15 == 0;
    20562976               
    2057                 var d0 = rtl ? addDays(cloneDate(t.visEnd), -1) : cloneDate(t.visStart),
    2058                         d = cloneDate(d0),
    2059                         today = clearTime(new Date()),
    2060                         colFormat = opt('columnFormat');
     2977                s =
     2978                        "<table style='width:100%' class='fc-agenda-days fc-border-separate' cellspacing='0'>" +
     2979                        "<thead>" +
     2980                        "<tr>" +
     2981                        "<th class='fc-agenda-axis " + headerClass + "'>&nbsp;</th>";
     2982                for (i=0; i<colCnt; i++) {
     2983                        s +=
     2984                                "<th class='fc- fc-col" + i + ' ' + headerClass + "'/>"; // fc- needed for setDayID
     2985                }
     2986                s +=
     2987                        "<th class='fc-agenda-gutter " + headerClass + "'>&nbsp;</th>" +
     2988                        "</tr>" +
     2989                        "</thead>" +
     2990                        "<tbody>" +
     2991                        "<tr>" +
     2992                        "<th class='fc-agenda-axis " + headerClass + "'>&nbsp;</th>";
     2993                for (i=0; i<colCnt; i++) {
     2994                        s +=
     2995                                "<td class='fc- fc-col" + i + ' ' + contentClass + "'>" + // fc- needed for setDayID
     2996                                "<div>" +
     2997                                "<div class='fc-day-content'>" +
     2998                                "<div style='position:relative'>&nbsp;</div>" +
     2999                                "</div>" +
     3000                                "</div>" +
     3001                                "</td>";
     3002                }
     3003                s +=
     3004                        "<td class='fc-agenda-gutter " + contentClass + "'>&nbsp;</td>" +
     3005                        "</tr>" +
     3006                        "</tbody>" +
     3007                        "</table>";
     3008                dayTable = $(s).appendTo(element);
     3009                dayHead = dayTable.find('thead');
     3010                dayHeadCells = dayHead.find('th').slice(1, -1);
     3011                dayBody = dayTable.find('tbody');
     3012                dayBodyCells = dayBody.find('td').slice(0, -1);
     3013                dayBodyCellInners = dayBodyCells.find('div.fc-day-content div');
     3014                dayBodyFirstCell = dayBodyCells.eq(0);
     3015                dayBodyFirstCellStretcher = dayBodyFirstCell.find('> div');
    20613016               
    2062                 if (!head) { // first time rendering, build from scratch
     3017                markFirstLast(dayHead.add(dayHead.find('tr')));
     3018                markFirstLast(dayBody.add(dayBody.find('tr')));
    20633019               
    2064                         var i,
    2065                                 minutes,
    2066                                 slotNormal = opt('slotMinutes') % 15 == 0, //...
     3020                axisFirstCells = dayHead.find('th:first');
     3021                gutterCells = dayTable.find('.fc-agenda-gutter');
     3022               
     3023                slotLayer =
     3024                        $("<div style='position:absolute;z-index:2;left:0;width:100%'/>")
     3025                                .appendTo(element);
     3026                               
     3027                if (opt('allDaySlot')) {
     3028               
     3029                        daySegmentContainer =
     3030                                $("<div style='position:absolute;z-index:8;top:0;left:0'/>")
     3031                                        .appendTo(slotLayer);
     3032               
     3033                        s =
     3034                                "<table style='width:100%' class='fc-agenda-allday' cellspacing='0'>" +
     3035                                "<tr>" +
     3036                                "<th class='" + headerClass + " fc-agenda-axis'>" + opt('allDayText') + "</th>" +
     3037                                "<td>" +
     3038                                "<div class='fc-day-content'><div style='position:relative'/></div>" +
     3039                                "</td>" +
     3040                                "<th class='" + headerClass + " fc-agenda-gutter'>&nbsp;</th>" +
     3041                                "</tr>" +
     3042                                "</table>";
     3043                        allDayTable = $(s).appendTo(slotLayer);
     3044                        allDayRow = allDayTable.find('tr');
    20673045                       
    2068                         // head
    2069                         s = "<div class='fc-agenda-head' style='position:relative;z-index:4'>" +
    2070                                 "<table style='width:100%'>" +
    2071                                 "<tr class='fc-first" + (opt('allDaySlot') ? '' : ' fc-last') + "'>" +
    2072                                 "<th class='fc-leftmost " +
    2073                                         tm + "-state-default'>&nbsp;</th>";
    2074                         for (i=0; i<colCnt; i++) {
    2075                                 s += "<th class='fc-" +
    2076                                         dayIDs[d.getDay()] + ' ' + // needs to be first
    2077                                         tm + '-state-default' +
    2078                                         "'>" + formatDate(d, colFormat) + "</th>";
    2079                                 addDays(d, dis);
    2080                                 if (nwe) {
    2081                                         skipWeekend(d, dis);
    2082                                 }
    2083                         }
    2084                         s += "<th class='" + tm + "-state-default'>&nbsp;</th></tr>";
    2085                         if (opt('allDaySlot')) {
    2086                                 s += "<tr class='fc-all-day'>" +
    2087                                                 "<th class='fc-axis fc-leftmost " + tm + "-state-default'>" + opt('allDayText') + "</th>" +
    2088                                                 "<td colspan='" + colCnt + "' class='" + tm + "-state-default'>" +
    2089                                                         "<div class='fc-day-content'><div style='position:relative'>&nbsp;</div></div></td>" +
    2090                                                 "<th class='" + tm + "-state-default'>&nbsp;</th>" +
    2091                                         "</tr><tr class='fc-divider fc-last'><th colspan='" + (colCnt+2) + "' class='" +
    2092                                                 tm + "-state-default fc-leftmost'><div/></th></tr>";
    2093                         }
    2094                         s+= "</table></div>";
    2095                         head = $(s).appendTo(element);
    2096                         dayBind(head.find('td'));
     3046                        dayBind(allDayRow.find('td'));
    20973047                       
    2098                         // all-day event container
    2099                         daySegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(head);
     3048                        axisFirstCells = axisFirstCells.add(allDayTable.find('th:first'));
     3049                        gutterCells = gutterCells.add(allDayTable.find('th.fc-agenda-gutter'));
    21003050                       
    2101                         // body
    2102                         d = zeroDate();
    2103                         var maxd = addMinutes(cloneDate(d), maxMinute);
    2104                         addMinutes(d, minMinute);
    2105                         s = "<table>";
    2106                         for (i=0; d < maxd; i++) {
    2107                                 minutes = d.getMinutes();
    2108                                 s += "<tr class='" +
    2109                                         (!i ? 'fc-first' : (!minutes ? '' : 'fc-minor')) +
    2110                                         "'><th class='fc-axis fc-leftmost " + tm + "-state-default'>" +
    2111                                         ((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : '&nbsp;') +
    2112                                         "</th><td class='fc-slot" + i + ' ' +
    2113                                                 tm + "-state-default'><div style='position:relative'>&nbsp;</div></td></tr>";
    2114                                 addMinutes(d, opt('slotMinutes'));
    2115                                 slotCnt++;
    2116                         }
    2117                         s += "</table>";
    2118                         body = $("<div class='fc-agenda-body' style='position:relative;z-index:2;overflow:auto'/>")
    2119                                 .append(bodyContent = $("<div style='position:relative;overflow:hidden'>")
    2120                                         .append(bodyTable = $(s)))
    2121                                 .appendTo(element);
    2122                         slotBind(body.find('td'));
     3051                        slotLayer.append(
     3052                                "<div class='fc-agenda-divider " + headerClass + "'>" +
     3053                                "<div class='fc-agenda-divider-inner'/>" +
     3054                                "</div>"
     3055                        );
    21233056                       
    2124                         // slot event container
    2125                         slotSegmentContainer = $("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(bodyContent);
    2126                        
    2127                         // background stripes
    2128                         d = cloneDate(d0);
    2129                         s = "<div class='fc-agenda-bg' style='position:absolute;z-index:1'>" +
    2130                                 "<table style='width:100%;height:100%'><tr class='fc-first'>";
    2131                         for (i=0; i<colCnt; i++) {
    2132                                 s += "<td class='fc-" +
    2133                                         dayIDs[d.getDay()] + ' ' + // needs to be first
    2134                                         tm + '-state-default ' +
    2135                                         (!i ? 'fc-leftmost ' : '') +
    2136                                         (+d == +today ? tm + '-state-highlight fc-today' : 'fc-not-today') +
    2137                                         "'><div class='fc-day-content'><div>&nbsp;</div></div></td>";
    2138                                 addDays(d, dis);
    2139                                 if (nwe) {
    2140                                         skipWeekend(d, dis);
    2141                                 }
    2142                         }
    2143                         s += "</tr></table></div>";
    2144                         bg = $(s).appendTo(element);
    2145                        
    2146                 }else{ // skeleton already built, just modify it
     3057                }else{
    21473058               
    2148                         clearEvents();
    2149                        
    2150                         // redo column header text and class
    2151                         head.find('tr:first th').slice(1, -1).each(function(i, th) {
    2152                                 $(th).text(formatDate(d, colFormat));
    2153                                 th.className = th.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
    2154                                 addDays(d, dis);
    2155                                 if (nwe) {
    2156                                         skipWeekend(d, dis);
    2157                                 }
    2158                         });
    2159                        
    2160                         // change classes of background stripes
    2161                         d = cloneDate(d0);
    2162                         bg.find('td').each(function(i, td) {
    2163                                 td.className = td.className.replace(/^fc-\w+(?= )/, 'fc-' + dayIDs[d.getDay()]);
    2164                                 if (+d == +today) {
    2165                                         $(td)
    2166                                                 .removeClass('fc-not-today')
    2167                                                 .addClass('fc-today')
    2168                                                 .addClass(tm + '-state-highlight');
    2169                                 }else{
    2170                                         $(td)
    2171                                                 .addClass('fc-not-today')
    2172                                                 .removeClass('fc-today')
    2173                                                 .removeClass(tm + '-state-highlight');
    2174                                 }
    2175                                 addDays(d, dis);
    2176                                 if (nwe) {
    2177                                         skipWeekend(d, dis);
    2178                                 }
    2179                         });
     3059                        daySegmentContainer = $([]); // in jQuery 1.4, we can just do $()
    21803060               
    21813061                }
    21823062               
     3063                slotScroller =
     3064                        $("<div style='position:absolute;width:100%;overflow-x:hidden;overflow-y:auto'/>")
     3065                                .appendTo(slotLayer);
     3066                               
     3067                slotContent =
     3068                        $("<div style='position:relative;width:100%;overflow:hidden'/>")
     3069                                .appendTo(slotScroller);
     3070                               
     3071                slotSegmentContainer =
     3072                        $("<div style='position:absolute;z-index:8;top:0;left:0'/>")
     3073                                .appendTo(slotContent);
     3074               
     3075                s =
     3076                        "<table class='fc-agenda-slots' style='width:100%' cellspacing='0'>" +
     3077                        "<tbody>";
     3078                d = zeroDate();
     3079                maxd = addMinutes(cloneDate(d), maxMinute);
     3080                addMinutes(d, minMinute);
     3081                slotCnt = 0;
     3082                for (i=0; d < maxd; i++) {
     3083                        minutes = d.getMinutes();
     3084                        s +=
     3085                                "<tr class='fc-slot" + i + ' ' + (!minutes ? '' : 'fc-minor') + "'>" +
     3086                                "<th class='fc-agenda-axis " + headerClass + "'>" +
     3087                                ((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : '&nbsp;') +
     3088                                "</th>" +
     3089                                "<td class='" + contentClass + "'>" +
     3090                                "<div style='position:relative'>&nbsp;</div>" +
     3091                                "</td>" +
     3092                                "</tr>";
     3093                        addMinutes(d, opt('slotMinutes'));
     3094                        slotCnt++;
     3095                }
     3096                s +=
     3097                        "</tbody>" +
     3098                        "</table>";
     3099                slotTable = $(s).appendTo(slotContent);
     3100                slotTableFirstInner = slotTable.find('div:first');
     3101               
     3102                slotBind(slotTable.find('td'));
     3103               
     3104                axisFirstCells = axisFirstCells.add(slotTable.find('th:first'));
     3105        }
     3106       
     3107       
     3108       
     3109        function updateCells() {
     3110                var i;
     3111                var headCell;
     3112                var bodyCell;
     3113                var date;
     3114                var today = clearTime(new Date());
     3115                for (i=0; i<colCnt; i++) {
     3116                        date = colDate(i);
     3117                        headCell = dayHeadCells.eq(i);
     3118                        headCell.html(formatDate(date, colFormat));
     3119                        bodyCell = dayBodyCells.eq(i);
     3120                        if (+date == +today) {
     3121                                bodyCell.addClass(tm + '-state-highlight fc-today');
     3122                        }else{
     3123                                bodyCell.removeClass(tm + '-state-highlight fc-today');
     3124                        }
     3125                        setDayID(headCell.add(bodyCell), date);
     3126                }
    21833127        }
    21843128       
     
    21863130       
    21873131        function setHeight(height, dateChanged) {
    2188        
    21893132                if (height === undefined) {
    21903133                        height = viewHeight;
    21913134                }
    2192                
    21933135                viewHeight = height;
    21943136                slotTopCache = {};
     3137       
     3138                var headHeight = dayBody.position().top;
     3139                var allDayHeight = slotScroller.position().top; // including divider
     3140                var bodyHeight = Math.min( // total body height, including borders
     3141                        height - headHeight,   // when scrollbars
     3142                        slotTable.height() + allDayHeight + 1 // when no scrollbars. +1 for bottom border
     3143                );
    21953144               
    2196                 var bodyHeight = height - head.height();
    2197                 bodyHeight = Math.min(bodyHeight, bodyTable.height()); // shrink to fit table
    2198                 body.height(bodyHeight);
     3145                dayBodyFirstCellStretcher
     3146                        .height(bodyHeight - vsides(dayBodyFirstCell));
    21993147               
    2200                 slotHeight = body.find('tr:first div').height() + 1;
     3148                slotLayer.css('top', headHeight);
     3149               
     3150                slotScroller.height(bodyHeight - allDayHeight - 1);
     3151               
     3152                slotHeight = slotTableFirstInner.height() + 1; // +1 for border
    22013153               
    22023154                if (dateChanged) {
     
    22113163                colContentPositions.clear();
    22123164               
    2213                 body.width(width).css('overflow', 'auto');
    2214                 bodyTable.width('');
    2215                
    2216                 var topTDs = head.find('tr:first th'),
    2217                         allDayLastTH = head.find('tr.fc-all-day th:last'),
    2218                         stripeTDs = bg.find('td'),
    2219                         clientWidth = body[0].clientWidth;
    2220                        
    2221                 bodyTable.width(clientWidth);
    2222                 clientWidth = body[0].clientWidth; // in ie6, sometimes previous clientWidth was wrongly reported
    2223                 bodyTable.width(clientWidth);
    2224                
    2225                 // time-axis width
    22263165                axisWidth = 0;
    22273166                setOuterWidth(
    2228                         head.find('tr:lt(2) th:first').add(body.find('tr:first th'))
    2229                                 .width(1)
    2230                                 .each(function() {
    2231                                         axisWidth = Math.max(axisWidth, $(this).outerWidth());
     3167                        axisFirstCells
     3168                                .width('')
     3169                                .each(function(i, _cell) {
     3170                                        axisWidth = Math.max(axisWidth, $(_cell).outerWidth());
    22323171                                }),
    22333172                        axisWidth
    22343173                );
    22353174               
    2236                 // column width, except for last column
    2237                 colWidth = Math.floor((clientWidth - axisWidth) / colCnt);
    2238                 setOuterWidth(stripeTDs.slice(0, -1), colWidth);
    2239                 setOuterWidth(topTDs.slice(1, -2), colWidth);
     3175                var slotTableWidth = slotScroller[0].clientWidth; // needs to be done after axisWidth (for IE7)
     3176                //slotTable.width(slotTableWidth);
    22403177               
    2241                 // column width for last column
    2242                 if (width != clientWidth) { // has scrollbar
    2243                         setOuterWidth(topTDs.slice(-2, -1), clientWidth - axisWidth - colWidth*(colCnt-1));
    2244                         topTDs.slice(-1).show();
    2245                         allDayLastTH.show();
     3178                gutterWidth = slotScroller.width() - slotTableWidth;
     3179                if (gutterWidth) {
     3180                        setOuterWidth(gutterCells, gutterWidth);
     3181                        gutterCells
     3182                                .show()
     3183                                .prev()
     3184                                .removeClass('fc-last');
    22463185                }else{
    2247                         body.css('overflow', 'hidden');
    2248                         topTDs.slice(-2, -1).width('');
    2249                         topTDs.slice(-1).hide();
    2250                         allDayLastTH.hide();
     3186                        gutterCells
     3187                                .hide()
     3188                                .prev()
     3189                                .addClass('fc-last');
    22513190                }
    22523191               
    2253                 bg.css({
    2254                         top: head.find('tr').height(),
    2255                         left: axisWidth,
    2256                         width: clientWidth - axisWidth,
    2257                         height: viewHeight
    2258                 });
    2259         }
    2260        
    2261        
     3192                colWidth = Math.floor((slotTableWidth - axisWidth) / colCnt);
     3193                setOuterWidth(dayHeadCells.slice(0, -1), colWidth);
     3194        }
     3195       
     3196
     3197
    22623198        function resetScroll() {
    2263                 var d0 = zeroDate(),
    2264                         scrollDate = cloneDate(d0);
     3199                var d0 = zeroDate();
     3200                var scrollDate = cloneDate(d0);
    22653201                scrollDate.setHours(opt('firstHour'));
    2266                 var top = timePosition(d0, scrollDate) + 1, // +1 for the border
    2267                         scroll = function() {
    2268                                 body.scrollTop(top);
    2269                         };
     3202                var top = timePosition(d0, scrollDate) + 1; // +1 for the border
     3203                function scroll() {
     3204                        slotScroller.scrollTop(top);
     3205                }
    22703206                scroll();
    22713207                setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
     
    22743210       
    22753211        function beforeHide() {
    2276                 savedScrollTop = body.scrollTop();
     3212                savedScrollTop = slotScroller.scrollTop();
    22773213        }
    22783214       
    22793215       
    22803216        function afterShow() {
    2281                 body.scrollTop(savedScrollTop);
     3217                slotScroller.scrollTop(savedScrollTop);
    22823218        }
    22833219       
     
    22883224       
    22893225
    2290         function dayBind(tds) {
    2291                 tds.click(slotClick)
     3226        function dayBind(cells) {
     3227                cells.click(slotClick)
    22923228                        .mousedown(daySelectionMousedown);
    22933229        }
    22943230
    22953231
    2296         function slotBind(tds) {
    2297                 tds.click(slotClick)
     3232        function slotBind(cells) {
     3233                cells.click(slotClick)
    22983234                        .mousedown(slotSelectionMousedown);
    22993235        }
     
    23013237       
    23023238        function slotClick(ev) {
    2303                 if (!opt('selectable')) { // SelectionManager will worry about dayClick
    2304                         var col = Math.min(colCnt-1, Math.floor((ev.pageX - bg.offset().left) / colWidth)),
    2305                                 date = addDays(cloneDate(t.visStart), col*dis+dit),
    2306                                 rowMatch = this.className.match(/fc-slot(\d+)/);
     3239                if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick
     3240                        var col = Math.min(colCnt-1, Math.floor((ev.pageX - dayTable.offset().left - axisWidth) / colWidth));
     3241                        var date = colDate(col);
     3242                        var rowMatch = this.parentNode.className.match(/fc-slot(\d+)/); // TODO: maybe use data
    23073243                        if (rowMatch) {
    2308                                 var mins = parseInt(rowMatch[1]) * opt('slotMinutes'),
    2309                                         hours = Math.floor(mins/60);
     3244                                var mins = parseInt(rowMatch[1]) * opt('slotMinutes');
     3245                                var hours = Math.floor(mins/60);
    23103246                                date.setHours(hours);
    23113247                                date.setMinutes(mins%60 + minMinute);
    2312                                 trigger('dayClick', this, date, false, ev);
     3248                                trigger('dayClick', dayBodyCells[col], date, false, ev);
    23133249                        }else{
    2314                                 trigger('dayClick', this, date, true, ev);
     3250                                trigger('dayClick', dayBodyCells[col], date, true, ev);
    23153251                        }
    23163252                }
     
    23463282       
    23473283       
    2348         function renderCellOverlay(col0, row0, col1, row1) {
    2349                 var rect = coordinateGrid.rect(col0, row0, col1, row1, head);
    2350                 return renderOverlay(rect, head);
     3284        function renderCellOverlay(row0, col0, row1, col1) { // only for all-day?
     3285                var rect = coordinateGrid.rect(row0, col0, row1, col1, slotLayer);
     3286                return renderOverlay(rect, slotLayer);
    23513287        }
    23523288       
     
    23603296                        if (stretchStart < stretchEnd) {
    23613297                                var col = i*dis+dit;
    2362                                 var rect = coordinateGrid.rect(0, col, 0, col, bodyContent); // only use it for horizontal coords
     3298                                var rect = coordinateGrid.rect(0, col, 0, col, slotContent); // only use it for horizontal coords
    23633299                                var top = timePosition(dayStart, stretchStart);
    23643300                                var bottom = timePosition(dayStart, stretchEnd);
     
    23663302                                rect.height = bottom - top;
    23673303                                slotBind(
    2368                                         renderOverlay(rect, bodyContent)
     3304                                        renderOverlay(rect, slotContent)
    23693305                                );
    23703306                        }
     
    23823318        coordinateGrid = new CoordinateGrid(function(rows, cols) {
    23833319                var e, n, p;
    2384                 bg.find('td').each(function(i, _e) {
     3320                dayHeadCells.each(function(i, _e) {
    23853321                        e = $(_e);
    23863322                        n = e.offset().left;
     
    23933329                p[1] = n + e.outerWidth();
    23943330                if (opt('allDaySlot')) {
    2395                         e = head.find('td');
     3331                        e = allDayRow;
    23963332                        n = e.offset().top;
    23973333                        rows[0] = [n, n+e.outerHeight()];
    23983334                }
    2399                 var bodyContentTop = bodyContent.offset().top;
    2400                 var bodyTop = body.offset().top;
    2401                 var bodyBottom = bodyTop + body.outerHeight();
     3335                var slotTableTop = slotContent.offset().top;
     3336                var slotScrollerTop = slotScroller.offset().top;
     3337                var slotScrollerBottom = slotScrollerTop + slotScroller.outerHeight();
    24023338                function constrain(n) {
    2403                         return Math.max(bodyTop, Math.min(bodyBottom, n));
     3339                        return Math.max(slotScrollerTop, Math.min(slotScrollerBottom, n));
    24043340                }
    24053341                for (var i=0; i<slotCnt; i++) {
    24063342                        rows.push([
    2407                                 constrain(bodyContentTop + slotHeight*i),
    2408                                 constrain(bodyContentTop + slotHeight*(i+1))
     3343                                constrain(slotTableTop + slotHeight*i),
     3344                                constrain(slotTableTop + slotHeight*(i+1))
    24093345                        ]);
    24103346                }
     
    24163352       
    24173353        colContentPositions = new HorizontalPositionCache(function(col) {
    2418                 return bg.find('td:eq(' + col + ') div div');
     3354                return dayBodyCellInners.eq(col);
    24193355        });
    24203356       
    24213357       
    24223358        function colContentLeft(col) {
    2423                 return axisWidth + colContentPositions.left(col);
     3359                return colContentPositions.left(col);
    24243360        }
    24253361       
    24263362       
    24273363        function colContentRight(col) {
    2428                 return axisWidth + colContentPositions.right(col);
    2429         }
    2430        
    2431        
    2432         function dayOfWeekCol(dayOfWeek) {