Skip to content

Instantly share code, notes, and snippets.

@zackad
Forked from dsiebel/calendar.html.twig
Last active April 6, 2022 11:37
Show Gist options
  • Save zackad/02666165983f6f6e5ac5bef469596fff to your computer and use it in GitHub Desktop.
Save zackad/02666165983f6f6e5ac5bef469596fff to your computer and use it in GitHub Desktop.
A Twig template rendering a calendar/datepicker.
{#
time can be any string acceptable by http://www.php.net/strtotime, the
template will output that time's month.
If you don't want to pass in a date you can set time like this:
{% set time = "now"|date("U") %}
{% set time = "December 2012"|date("U") %}
How ever you want to output items onto the calendar is a different issue,
but I'd assume pushing everything into an array numerically indexed by that day:
$days = array(1=>array('Something on the first'),31=>array('Halloween'));
#}
{% set data = data|default([]) %}
{% set today = date("today") %}
{% set time = date(time|default(today)) %}
{% set numberOfMonth = numberOfMonth|default(1) %}
{% set spanOtherMonth = spanOtherMonth|default(false) %}
{% set firstDay = firstDay|default(1) %}
{% set dateStringToday = time|date('Y-m-d') %}
{% set disableNavigation = disableNavigation|default(false) %}
{% set prevText %}<i class="cal-icon-prev">&laquo;</i>{% endset %}
{% set nextText %}<i class="cal-icon-next">&raquo;</i>{% endset %}
{% set daynames = daynames|default({
0: { short: 'sun' | trans, full: 'sunday' | trans },
1: { short: 'mon' | trans, full: 'monday' | trans },
2: { short: 'tue' | trans, full: 'tuesday' | trans },
3: { short: 'wed' | trans, full: 'wednesday' | trans },
4: { short: 'thu' | trans, full: 'thursday' | trans },
5: { short: 'fri' | trans, full: 'friday' | trans },
6: { short: 'sat' | trans, full: 'saturday' | trans }
}) %}
{% set monthnames = monthnames|default({
1: { short: 'january' | trans, full: 'january' | trans},
2: { short: 'february' | trans, full: 'february' | trans},
3: { short: 'march' | trans, full: 'march' | trans},
4: { short: 'april' | trans, full: 'april' | trans},
5: { short: 'may' | trans, full: 'may' | trans},
6: { short: 'june' | trans, full: 'june' | trans},
7: { short: 'july' | trans, full: 'july' | trans},
8: { short: 'august' | trans, full: 'august' | trans},
9: { short: 'september' | trans, full: 'september' | trans},
10: { short: 'october' | trans, full: 'october' | trans},
11: { short: 'november' | trans, full: 'november' | trans},
12: { short: 'december' | trans, full: 'december' | trans}
}) %}
{% if app.debug %}
<!-- // DEBUG
data: {{ data|json_encode }}
today: {{ today.format('Y-m-d H:i:s') }}
time: {{ time.format('Y-m-d H:i:s') }}
numberOfMonth: {{ numberOfMonth }}
spanOtherMonth: {{ spanOtherMonth }}
firstDay: {{ firstDay }}
disableNavigation: {{ disableNavigation }}
-->
{% endif %}
<div class="cal-calendar{% if numberOfMonth > 1 %} cal-group{% endif %}">
{% if not disableNavigation -%}
<div class="cal-btn">
<a class="cal-prev" title="">
<span class="cal-prev-btn">{{ prevText | raw }}</span>
</a>
</div>
{%- endif %}
{% for i in range(0, numberOfMonth-1) -%}
{% if not loop.first %}
{% set time = time|date_modify('+1 month') %}
{% endif %}
{% set year = time.format('Y') %}
{% set month = time.format('n') %}
{% if app.debug %}
<!-- // DEBUG
loop.index: {{ loop.index }}
time: {{ time.format('Y-m-d H:i:s') }}
year: {{ year }}
month: {{ month }}
-->
{% endif %}
<div class="cal-month{% if loop.first %} cal-group-first{% endif %}{% if loop.last %} cal-group-last{% endif %}" data-year="{{ year }}" data-month="{{ month }}">
<table>
<thead>
<tr>
<th colspan="7" class="center cal-month-title">
{{ monthnames[month].full }}
</th>
</tr>
<tr>
{% for dow in range(0, 6) %}
{% set day = (dow + firstDay) % 7 %}
<th><span title="{{ daynames[day].full }}">{{ daynames[day].short }}</span></th>
{% endfor %}
</tr>
</thead>
<tbody>
{% set daysInMonth = time.format('t') %}
{% set startDow = (time.format('F 1\\s\\t Y')|date('w')) %}
{% set dow = startDow %}
{% set pos = (7 + (startDow - firstDay)) % 7 %}
<tr class="cal-week">
{% for dom in range(1,daysInMonth) -%}
{#
TODO
- disable days before today in calendar
-
#}
{% set dom_date_s = "%d-%02d-%02d"|format(year, month, dom) %}
{% set dom_date = date(dom_date_s) %}
{% set dom_id = "cal_" ~ ("%d%02d%02d"|format(year, month, dom)) %}
{% set cal_day_classes = (
'cal-day'
~ (dom_date < today ? ' cal-unselectable' : '')
~ ((pos + firstDay + 6) % 7 >= 5 ? ' cal-weekend' : '')
~ (data[dom_date_s] is defined ? ' cal-day-data' : '')
) %}
{% if loop.first and pos > 0 -%}
{% if not spanOtherMonth %}
{% for _dom in range(1, pos) -%}
<td class="cal-day"><span>&nbsp;</span></td>
{%- endfor %}
{% else %}
<td colspan="{{ pos }}"><span>&nbsp;</span></td>
{% endif %}
{%- endif %}
<td id="{{ dom_id }}" class="{{ cal_day_classes }}" data-date="{{ dom_date_s }}" data-handler="selectDay" data-event="click">
<a{% if data[dom_date_s] is defined %} title="{{ data[dom_date_s] }}"{% endif %}>
{{- dom -}}
</a>
</td>
{% if loop.last and pos != 6 -%}
{% if not spanOtherMonth %}
{% for _dom in range(1, 6 - pos) -%}
<td class="cal-day"><span>&nbsp;</span></td>
{%- endfor %}
{% else %}
<td colspan="{{ 6 - pos }}"><span>&nbsp;</span></td>
{% endif %}
{%- endif %}
{% if pos == 6 and not loop.last %}
{% set pos = 0 %}
{% set dow = firstDay %}
</tr>
<tr class="cal-week">
{% else %}
{% set dow = (dow + 1) % 7 %}
{% set pos = pos + 1 %}
{% endif %}
{%- endfor %}
</tr>
</tbody>
</table>
</div>
{%- endfor %}
{% if not disableNavigation -%}
<div class="cal-btn">
<a class="cal-next" title="">
<span class="cal-next-btn">{{ nextText | raw }}</span>
</a>
</div>
{%- endif %}
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment