Add greyscale printable calendar mode
Add a black_white URL option for printable calendars and expose it in both printable URL builders. Apply a high-legibility greyscale print style with white day cells, grey event blocks, and dark borders/text. Condense month-cell event typography to fit more matchup text in each calendar day. Cover black_white propagation in the printable URL helper test.
This commit is contained in:
@@ -132,11 +132,12 @@ body.month-pages .day-num {
|
||||
|
||||
body.month-pages .event-name {
|
||||
font-size: calc(13px * var(--month-font-scale));
|
||||
line-height: 0.98;
|
||||
}
|
||||
|
||||
body.month-pages .matchup-name {
|
||||
font-size: calc(13px * var(--month-font-scale));
|
||||
line-height: 1.05;
|
||||
line-height: 0.92;
|
||||
}
|
||||
|
||||
body.month-pages .event-time {
|
||||
@@ -468,6 +469,8 @@ body.month-pages .day .day-num {
|
||||
hyphens: none;
|
||||
line-height: 1.05;
|
||||
font-weight: 700;
|
||||
font-stretch: condensed;
|
||||
font-variation-settings: "wdth" 42, "wght" 700;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
@@ -487,6 +490,7 @@ body.month-pages .day .day-num {
|
||||
padding: 0;
|
||||
font-size: calc(8.5px * var(--month-font-scale));
|
||||
line-height: 0.98;
|
||||
font-variation-settings: "wdth" 36, "wght" 800;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -503,6 +507,7 @@ body.month-pages .day .day-num {
|
||||
text-align: center;
|
||||
text-overflow: clip;
|
||||
white-space: nowrap;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
.ha-flag {
|
||||
@@ -563,6 +568,8 @@ body.month-pages .day .day-num {
|
||||
max-width: 100%;
|
||||
font-size: calc(12px * var(--month-font-scale));
|
||||
font-weight: 800;
|
||||
font-stretch: condensed;
|
||||
font-variation-settings: "wdth" 56, "wght" 800;
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
@@ -584,6 +591,8 @@ body.month-pages .day .day-num {
|
||||
max-width: 100%;
|
||||
font-size: calc(8px * var(--month-font-scale));
|
||||
font-weight: 700;
|
||||
font-stretch: condensed;
|
||||
font-variation-settings: "wdth" 50, "wght" 700;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
@@ -676,6 +685,100 @@ body.month-pages .day .day-num {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
body.black-white .header,
|
||||
body.black-white .month-title,
|
||||
body.black-white .dow span,
|
||||
body.black-white .day,
|
||||
body.black-white .event,
|
||||
body.black-white .empty,
|
||||
body.black-white .footer-meta,
|
||||
body.black-white .footer-qr-image {
|
||||
border-color: #2f3337 !important;
|
||||
}
|
||||
|
||||
body.black-white .month-title,
|
||||
body.black-white .ha-flag {
|
||||
background: #1f2328 !important;
|
||||
color: #fff !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body.black-white .dow span,
|
||||
body.black-white .day,
|
||||
body.black-white .day.muted,
|
||||
body.black-white .day.no-events,
|
||||
body.black-white .day.has-matchups,
|
||||
body.black-white .empty,
|
||||
body.black-white .legend-item,
|
||||
body.black-white .event.a .ha-flag {
|
||||
background: #f7f7f7 !important;
|
||||
color: #111 !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body.black-white .dow span {
|
||||
background: #e4e7eb !important;
|
||||
}
|
||||
|
||||
body.black-white .day,
|
||||
body.black-white .day.has-matchups,
|
||||
body.black-white .legend-item {
|
||||
background: #fff !important;
|
||||
}
|
||||
|
||||
body.black-white .event,
|
||||
body.black-white .event.h,
|
||||
body.black-white .event.a,
|
||||
body.black-white .event.matchup {
|
||||
background: #e4e7eb !important;
|
||||
color: #111 !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body.black-white .day.muted,
|
||||
body.black-white .day.no-events {
|
||||
background: #f2f3f5 !important;
|
||||
color: #4b5563 !important;
|
||||
}
|
||||
|
||||
body.black-white .month-title,
|
||||
body.black-white .dow span,
|
||||
body.black-white .day,
|
||||
body.black-white .event {
|
||||
border: 1px solid #2f3337;
|
||||
}
|
||||
|
||||
body.black-white .day-num,
|
||||
body.black-white .day.has-events .day-num,
|
||||
body.black-white .day.has-matchups .day-num,
|
||||
body.black-white.month-pages .day .day-num {
|
||||
background: #fff !important;
|
||||
color: #111 !important;
|
||||
box-shadow: 0 0 0 1px #2f3337 !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body.black-white .ha-flag,
|
||||
body.black-white .event.a .ha-flag {
|
||||
box-shadow: 0 0 0 1px #2f3337;
|
||||
}
|
||||
|
||||
body.black-white .event-name,
|
||||
body.black-white .event-time,
|
||||
body.black-white .event-venue,
|
||||
body.black-white .matchup-vs,
|
||||
body.black-white .footer-qr-label,
|
||||
body.black-white .footer-qr-link,
|
||||
body.black-white .meta {
|
||||
color: #111 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
body.black-white .meta,
|
||||
body.black-white .footer-qr-label {
|
||||
color: #374151 !important;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body,
|
||||
body.print-preview {
|
||||
|
||||
@@ -153,6 +153,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
$vars[] = 'paper';
|
||||
$vars[] = 'autoprint';
|
||||
$vars[] = 'month_pages';
|
||||
$vars[] = 'black_white';
|
||||
|
||||
return $vars;
|
||||
}
|
||||
@@ -539,6 +540,11 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
echo '<input id="tse-printable-builder-month-pages" type="checkbox" value="1" />';
|
||||
echo esc_html__( 'Print each month on its own page', 'tonys-sportspress-enhancements' );
|
||||
echo '</label>';
|
||||
echo '<br />';
|
||||
echo '<label for="tse-printable-builder-black-white" style="display:inline-flex;align-items:center;gap:6px;margin-top:8px;">';
|
||||
echo '<input id="tse-printable-builder-black-white" type="checkbox" value="1" />';
|
||||
echo esc_html__( 'High-legibility greyscale', 'tonys-sportspress-enhancements' );
|
||||
echo '</label>';
|
||||
echo '</td></tr>';
|
||||
|
||||
echo '</tbody></table>';
|
||||
@@ -585,6 +591,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
var titleFormat = root.querySelector('#tse-printable-builder-title-format');
|
||||
var autoprint = root.querySelector('#tse-printable-builder-autoprint');
|
||||
var monthPages = root.querySelector('#tse-printable-builder-month-pages');
|
||||
var blackWhite = root.querySelector('#tse-printable-builder-black-white');
|
||||
var output = root.querySelector('#tse-printable-builder-output');
|
||||
var copyButton = root.querySelector('#tse-printable-builder-copy');
|
||||
var openLink = root.querySelector('#tse-printable-builder-open');
|
||||
@@ -658,12 +665,18 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
url.searchParams.delete('month_pages');
|
||||
}
|
||||
|
||||
if (blackWhite.checked) {
|
||||
url.searchParams.set('black_white', '1');
|
||||
} else {
|
||||
url.searchParams.delete('black_white');
|
||||
}
|
||||
|
||||
output.value = url.toString();
|
||||
openLink.href = url.toString();
|
||||
openLink.toggleAttribute('disabled', !teamValues.length);
|
||||
}
|
||||
|
||||
[team, season, league, field, paper, teamLabel, fieldLabel, titleFormat, autoprint, monthPages].forEach(function(input){
|
||||
[team, season, league, field, paper, teamLabel, fieldLabel, titleFormat, autoprint, monthPages, blackWhite].forEach(function(input){
|
||||
input.addEventListener('change', buildUrl);
|
||||
});
|
||||
|
||||
@@ -737,6 +750,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
$paper = $this->normalize_paper_size( (string) get_query_var( 'paper' ) );
|
||||
$autoprint = '1' === (string) get_query_var( 'autoprint' );
|
||||
$month_pages = '1' === (string) get_query_var( 'month_pages' );
|
||||
$black_white = '1' === (string) get_query_var( 'black_white' );
|
||||
|
||||
$is_multi_team = count( $team_ids ) > 1;
|
||||
$primary_team_id = isset( $team_ids[0] ) ? (int) $team_ids[0] : 0;
|
||||
@@ -795,7 +809,14 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
echo '<script>window.addEventListener("load",function(){window.print();});</script>';
|
||||
}
|
||||
echo '</head>';
|
||||
echo '<body class="print-preview ' . esc_attr( $paper . ( $month_pages ? ' month-pages' : '' ) ) . '">';
|
||||
$body_classes = array( 'print-preview', $paper );
|
||||
if ( $month_pages ) {
|
||||
$body_classes[] = 'month-pages';
|
||||
}
|
||||
if ( $black_white ) {
|
||||
$body_classes[] = 'black-white';
|
||||
}
|
||||
echo '<body class="' . esc_attr( implode( ' ', $body_classes ) ) . '">';
|
||||
|
||||
$root_vars = array(
|
||||
'--sheet-scale:' . $layout['sheet_scale'],
|
||||
@@ -925,7 +946,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
* @param string $paper Paper size.
|
||||
* @return string
|
||||
*/
|
||||
private function build_url( $team_id, $season_id, $paper, $league_id = 0, $field_id = 0, $month_pages = false, $team_label_mode = 'name', $field_label_mode = '', $title_format = 'selected_first' ) {
|
||||
private function build_url( $team_id, $season_id, $paper, $league_id = 0, $field_id = 0, $month_pages = false, $team_label_mode = 'name', $field_label_mode = '', $title_format = 'selected_first', $black_white = false ) {
|
||||
$paper = $this->normalize_paper_size( $paper );
|
||||
$field_label_mode = '' === $field_label_mode ? $this->get_venue_label_mode() : $field_label_mode;
|
||||
|
||||
@@ -941,6 +962,7 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
'title_format' => $this->sanitize_title_format( $title_format ),
|
||||
'paper' => (string) $paper,
|
||||
'month_pages' => $month_pages ? '1' : '',
|
||||
'black_white' => $black_white ? '1' : '',
|
||||
),
|
||||
home_url( '/' )
|
||||
);
|
||||
@@ -2413,7 +2435,9 @@ if ( ! class_exists( 'Tony_Sportspress_Printable_Calendars' ) ) {
|
||||
$rows = (int) ceil( $count / $columns );
|
||||
|
||||
$font_scale = 1.0;
|
||||
if ( $count >= 3 && $count <= 4 ) {
|
||||
if ( $count == 1 ) {
|
||||
$font_scale = 1.1;
|
||||
} elseif ( $count >= 3 && $count <= 4 ) {
|
||||
$font_scale = 0.9;
|
||||
} elseif ( $count >= 5 && $count <= 6 ) {
|
||||
$font_scale = 0.78;
|
||||
|
||||
@@ -92,6 +92,7 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
$export_type = tse_sp_schedule_exporter_resolve_export_type();
|
||||
$subformat = tse_sp_schedule_exporter_resolve_subformat();
|
||||
$title_format = tse_sp_schedule_exporter_resolve_title_format();
|
||||
$black_white = tse_sp_schedule_exporter_resolve_black_white();
|
||||
|
||||
if ( empty( $teams ) ) {
|
||||
return '<p>' . esc_html__( 'No SportsPress teams match the selected league and season.', 'tonys-sportspress-enhancements' ) . '</p>';
|
||||
@@ -191,6 +192,13 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom:16px;">
|
||||
<label for="tse-public-black-white" style="display:inline-flex;align-items:center;gap:6px;">
|
||||
<input id="tse-public-black-white" type="checkbox" name="black_white" value="1" <?php checked( $black_white ); ?> />
|
||||
<strong><?php esc_html_e( 'High-legibility greyscale printable calendar', 'tonys-sportspress-enhancements' ); ?></strong>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<?php tse_sp_schedule_exporter_render_column_picker( 'matchup', 'public', $subformat ); ?>
|
||||
@@ -206,7 +214,7 @@ function tse_sp_schedule_exporter_render_shortcode() {
|
||||
);
|
||||
$csv_url = tse_sp_event_export_get_feed_url( array_merge( $feed_args, array( 'format' => $subformat ) ), 'csv' );
|
||||
$ics_url = tse_sp_event_export_get_feed_url( $feed_args, 'ics' );
|
||||
$print_url = tse_sp_schedule_exporter_get_printable_url( $team_ids, $season_id, 'letter', $league_id, false, $field_id, false, 'name', 'name', $title_format );
|
||||
$print_url = tse_sp_schedule_exporter_get_printable_url( $team_ids, $season_id, 'letter', $league_id, false, $field_id, false, 'name', 'name', $title_format, $black_white );
|
||||
$current_url = tse_sp_schedule_exporter_get_output_url( $export_type, $csv_url, $ics_url, $print_url );
|
||||
?>
|
||||
<div style="display:flex;align-items:center;gap:8px;max-width:100%;margin-top:16px;">
|
||||
@@ -598,6 +606,15 @@ function tse_sp_schedule_exporter_resolve_title_format_value( $value ) {
|
||||
return in_array( $value, tse_sp_event_export_get_title_formats(), true ) ? $value : 'selected_first';
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve whether printable URLs should use black-and-white styling.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function tse_sp_schedule_exporter_resolve_black_white() {
|
||||
return isset( $_GET['black_white'] ) && '1' === (string) wp_unslash( $_GET['black_white'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current output URL for the selected export type.
|
||||
*
|
||||
@@ -758,9 +775,10 @@ function tse_sp_schedule_exporter_get_primary_venue( $event_id ) {
|
||||
* @param string $team_label_mode Team label mode.
|
||||
* @param string $field_label_mode Field label mode.
|
||||
* @param string $title_format Title format.
|
||||
* @param bool $black_white Whether to use black-and-white printable styling.
|
||||
* @return string
|
||||
*/
|
||||
function tse_sp_schedule_exporter_get_printable_url( $team_id, $season_id, $paper, $league_id = 0, $autoprint = false, $field_id = 0, $month_pages = false, $team_label_mode = 'name', $field_label_mode = 'name', $title_format = 'selected_first' ) {
|
||||
function tse_sp_schedule_exporter_get_printable_url( $team_id, $season_id, $paper, $league_id = 0, $autoprint = false, $field_id = 0, $month_pages = false, $team_label_mode = 'name', $field_label_mode = 'name', $title_format = 'selected_first', $black_white = false ) {
|
||||
$team_ids = is_array( $team_id ) ? array_values( array_filter( array_map( 'absint', $team_id ) ) ) : array( absint( $team_id ) );
|
||||
|
||||
return add_query_arg(
|
||||
@@ -776,6 +794,7 @@ function tse_sp_schedule_exporter_get_printable_url( $team_id, $season_id, $pape
|
||||
'paper' => $paper,
|
||||
'autoprint' => $autoprint ? '1' : '',
|
||||
'month_pages' => $month_pages ? '1' : '',
|
||||
'black_white' => $black_white ? '1' : '',
|
||||
),
|
||||
home_url( '/' )
|
||||
);
|
||||
@@ -829,6 +848,7 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
var titleFormat = form.querySelector('[name="title_format"]');
|
||||
var field = form.querySelector('[name="field_id"]');
|
||||
var monthPages = form.querySelector('[name="month_pages"]');
|
||||
var blackWhite = form.querySelector('[name="black_white"]');
|
||||
var outputUrl = scope.querySelector('.tse-output-url');
|
||||
var openButton = scope.querySelector('.tse-open-link');
|
||||
var iosButton = scope.querySelector('.tse-ics-ios-link');
|
||||
@@ -900,6 +920,11 @@ function tse_sp_schedule_exporter_render_link_sync_script( $echo = false ) {
|
||||
} else {
|
||||
printUrl.searchParams.delete('month_pages');
|
||||
}
|
||||
if (blackWhite && blackWhite.checked) {
|
||||
printUrl.searchParams.set('black_white', '1');
|
||||
} else {
|
||||
printUrl.searchParams.delete('black_white');
|
||||
}
|
||||
printUrl.searchParams.set('paper', 'letter');
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,18 @@ class Test_SP_Schedule_Exporter extends WP_UnitTestCase {
|
||||
$this->assertSame( 'abbreviation', $query['field_label'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Printable URLs should carry black-and-white mode when requested.
|
||||
*/
|
||||
public function test_printable_url_accepts_black_white_mode() {
|
||||
$url = tse_sp_schedule_exporter_get_printable_url( 12, 56, 'letter', 78, false, 90, false, 'name', 'name', 'selected_first', true );
|
||||
$query = array();
|
||||
|
||||
wp_parse_str( (string) wp_parse_url( $url, PHP_URL_QUERY ), $query );
|
||||
|
||||
$this->assertSame( '1', $query['black_white'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Single-team printable entries should keep the existing opponent perspective.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user