Skip to content

Commit 32b7968

Browse files
authored
Merge pull request #696 from craigk5n/fix/695-bottom-date-selectors
fix: render Month/Week/Year date selectors at the bottom when configured
2 parents c8e4060 + 58a64b9 commit 32b7968

7 files changed

Lines changed: 217 additions & 199 deletions

File tree

includes/css/styles.css

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -227,19 +227,10 @@ img.color {
227227
#cat {
228228
font-size:1.125rem;
229229
}
230-
#dateselector,
231230
#trailer {
232231
margin:0;
233232
padding:0;
234233
}
235-
#dateselector form {
236-
float:left;
237-
width:33%;
238-
margin-top:.3125rem;
239-
margin-bottom:1.5625rem;
240-
padding-top:.3125rem;
241-
}
242-
#dateselector label,
243234
#trailer label {
244235
margin:0;
245236
padding:0;

includes/css/styles.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,10 @@
184184
? '10em' : $GLOBALS['MINICALWIDTH']; ?>;
185185
}
186186

187-
<?php if ( $MENU_ENABLED == 'N' ) { ?>
188-
#dateselector form {
187+
/* Only present when the date selectors are rendered below the calendar. */
188+
#dateselector {
189189
border-top: 0.0625em solid var(--tablebg, <?php echo $GLOBALS['TABLEBG'];?>);
190190
}
191-
<?php } ?>
192191

193192
<?php if ( ! empty ( $GLOBALS['BGIMAGE'] ) ) { ?>
194193
body {

includes/date_selectors.php

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
<?php
2+
/**
3+
* Month/Week/Year date selectors.
4+
*
5+
* Shared by the Bootstrap top menu (includes/menu.php) and by print_trailer()
6+
* (includes/init.php) so the selectors can be placed at the top or the bottom
7+
* of the page. Which one is used depends on the MENU_DATE_TOP setting, and on
8+
* MENU_ENABLED: with the top menu switched off there is no navbar to hold the
9+
* selectors, so they always fall through to the trailer.
10+
*
11+
* @author Craig Knudsen <cknudsen@cknudsen.com>
12+
* @copyright Craig Knudsen, <cknudsen@cknudsen.com>, http://www.k5n.us/cknudsen
13+
* @license https://gnu.org/licenses/old-licenses/gpl-2.0.html GNU GPL
14+
* @package WebCalendar
15+
*/
16+
defined('_ISVALID') or die('You cannot access this file directly!');
17+
18+
/**
19+
* Generates the Month, Week and Year dropdowns.
20+
*
21+
* @return string HTML for a navbar list holding the three dropdowns.
22+
*/
23+
function date_selectors_html()
24+
{
25+
global $thisday, $thismonth, $thisyear;
26+
27+
$d = (empty($thisday) ? date('d') : $thisday);
28+
$m = (empty($thismonth) ? date('m') : $thismonth);
29+
$y = (empty($thisyear) ? date('Y') : $thisyear);
30+
31+
return '<ul class="navbar-nav flex-row mxr-auto">' . "\n"
32+
. date_selector_month($m, $y)
33+
. date_selector_week($d, $m, $y)
34+
. date_selector_year($y)
35+
. "</ul>\n";
36+
}
37+
38+
/**
39+
* Generates the Month dropdown: the tail of last year, all of this year and
40+
* the start of next year.
41+
*
42+
* A dropdown-submenu version covering more years was attempted and abandoned
43+
* because Bootstrap v4 does not position the submenu correctly. See the
44+
* commented-out blocks removed from includes/menu.php in the commit that
45+
* created this file, and the related TODO in print_trailer().
46+
*
47+
* @param int $thismonth Month currently being viewed (1-12)
48+
* @param int $thisyear Year currently being viewed
49+
*
50+
* @return string HTML for a single navbar dropdown.
51+
*/
52+
function date_selector_month($thismonth, $thisyear)
53+
{
54+
$ret = date_selector_open('Month', 'dateSelectorMonth');
55+
56+
// Last 4 months of the prior year.
57+
$ret .= '<h6 class="dropdown-header">' . ($thisyear - 1) . "</h6>\n";
58+
for ($i = 9; $i <= 12; $i++) {
59+
$ret .= date_selector_item('month.php',
60+
sprintf('%04d%02d01', $thisyear - 1, $i), month_name($i - 1));
61+
}
62+
// All of this year, with the current month in bold.
63+
$ret .= '<div class="dropdown-divider"></div>' . "\n"
64+
. '<h6 class="dropdown-header">' . $thisyear . "</h6>\n";
65+
for ($i = 1; $i <= 12; $i++) {
66+
$name = month_name($i - 1);
67+
if ($i == $thismonth)
68+
$name = '<b>' . $name . '</b>';
69+
70+
$ret .= date_selector_item('month.php',
71+
sprintf('%04d%02d01', $thisyear, $i), $name);
72+
}
73+
// First 3 months of next year.
74+
$ret .= '<div class="dropdown-divider"></div>' . "\n"
75+
. '<h6 class="dropdown-header">' . ($thisyear + 1) . "</h6>\n";
76+
for ($i = 1; $i <= 3; $i++) {
77+
$ret .= date_selector_item('month.php',
78+
sprintf('%04d%02d01', $thisyear + 1, $i), month_name($i - 1));
79+
}
80+
81+
return $ret . date_selector_close();
82+
}
83+
84+
/**
85+
* Generates the Week dropdown: 5 weeks before and 9 weeks after the week
86+
* currently being viewed.
87+
*
88+
* @param int $d Day currently being viewed
89+
* @param int $m Month currently being viewed
90+
* @param int $y Year currently being viewed
91+
*
92+
* @return string HTML for a single navbar dropdown.
93+
*/
94+
function date_selector_week($d, $m, $y)
95+
{
96+
global $DISPLAY_WEEKENDS;
97+
98+
$ret = date_selector_open('Week', 'dateSelectorWeek');
99+
100+
$lastDay = ($DISPLAY_WEEKENDS == 'N' ? 4 : 6);
101+
$thisdate = date('Ymd', mktime(0, 0, 0, $m, $d, $y));
102+
$wkstart = get_weekday_before($y, $m, $d);
103+
for ($i = -5; $i <= 9; $i++) {
104+
$twkstart = bump_local_timestamp($wkstart, 0, 0, 0, 0, 7 * $i, 0);
105+
$twkend = bump_local_timestamp($twkstart, 0, 0, 0, 0, $lastDay, 0);
106+
// Skip weeks that fall outside the range we can represent.
107+
if ($twkstart <= 0 || $twkend >= 2146021200)
108+
continue;
109+
110+
$dateSYmd = date('Ymd', $twkstart);
111+
$dateEYmd = date('Ymd', $twkend);
112+
$name = (!empty($GLOBALS['PULLDOWN_WEEKNUMBER'])
113+
&& $GLOBALS['PULLDOWN_WEEKNUMBER'] == 'Y'
114+
? '(' . date('W', $twkstart + 86400) . ')&nbsp;&nbsp;' : '')
115+
. sprintf('%s - %s',
116+
date_to_str($dateSYmd, '__mon__ __dd__', false, true),
117+
date_to_str($dateEYmd, '__mon__ __dd__', false, true));
118+
if ($thisdate >= $dateSYmd && $thisdate <= $dateEYmd)
119+
$name = '<b>' . $name . '</b>';
120+
121+
$ret .= date_selector_item('week.php', $dateSYmd, $name);
122+
}
123+
124+
return $ret . date_selector_close();
125+
}
126+
127+
/**
128+
* Generates the Year dropdown: 5 years either side of the year currently
129+
* being viewed.
130+
*
131+
* @param int $thisyear Year currently being viewed
132+
*
133+
* @return string HTML for a single navbar dropdown.
134+
*/
135+
function date_selector_year($thisyear)
136+
{
137+
$ret = date_selector_open('Year', 'dateSelectorYear');
138+
139+
for ($i = -5; $i <= 5; $i++) {
140+
$name = $thisyear + $i;
141+
if ($i == 0)
142+
$name = '<b>' . $name . '</b>';
143+
144+
$ret .= date_selector_item('year.php',
145+
sprintf('%04d0101', $thisyear + $i), $name);
146+
}
147+
148+
return $ret . date_selector_close();
149+
}
150+
151+
/**
152+
* Generates the opening tags of one navbar dropdown.
153+
*
154+
* @param string $label Untranslated dropdown label
155+
* @param string $id Unique element id, used to label the dropdown menu
156+
*
157+
* @return string HTML
158+
*/
159+
function date_selector_open($label, $id)
160+
{
161+
return '<li class="nav-item dropdown">' . "\n"
162+
. '<a class="nav-link dropdown-toggle" href="#" id="' . $id . '"'
163+
. ' data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">'
164+
. translate($label) . "</a>\n"
165+
. '<ul class="dropdown-menu" aria-labelledby="' . $id . '">' . "\n";
166+
}
167+
168+
/**
169+
* Generates the closing tags of one navbar dropdown.
170+
*
171+
* @return string HTML
172+
*/
173+
function date_selector_close()
174+
{
175+
return "</ul>\n</li>\n";
176+
}
177+
178+
/**
179+
* Generates one entry within a date selector dropdown.
180+
*
181+
* @param string $page Page to link to (month.php, week.php or year.php)
182+
* @param string $date Target date in YYYYMMDD format
183+
* @param string $name Text of the link (may contain markup)
184+
*
185+
* @return string HTML
186+
*/
187+
function date_selector_item($page, $date, $name)
188+
{
189+
global $login, $user;
190+
191+
return '<li><a class="dropdown-item" href="' . $page . '?date=' . $date
192+
. (!empty($user) && $user != $login
193+
? '&amp;user=' . htmlspecialchars($user) : '')
194+
. '">' . $name . "</a></li>\n";
195+
}
196+
?>

includes/init.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,17 @@ function print_trailer( $include_nav_links = true, $closeDb = true,
383383
if ($MENU_ENABLED != 'N') {
384384
$ret .= '<script src="./includes/js/menu.js"></script>' . "\n";
385385
}
386+
// The Month/Week/Year selectors live in the top menu by default. Put them
387+
// here instead when the admin asked for that, or when the top menu is
388+
// disabled entirely and so has nowhere to hold them. Installs predating the
389+
// MENU_DATE_TOP setting have no webcal_config row for it, so default to top.
390+
if( $include_nav_links && ! $friendly
391+
&& ( $MENU_ENABLED == 'N' || ( $MENU_DATE_TOP ?? 'Y' ) == 'N' ) ) {
392+
require_once 'date_selectors.php';
393+
$ret .= '<nav id="dateselector"'
394+
. ' class="navbar navbar-expand-lg navbar-light bg-light">' . "\n"
395+
. date_selectors_html() . "</nav>\n";
396+
}
386397
if( $include_nav_links && ! $friendly ) {
387398
if( $MENU_ENABLED == 'N' )
388399
require_once 'includes/trailer.php';

0 commit comments

Comments
 (0)