From 58130e4c6ab0577b0343e2115e3106e9b962efb0 Mon Sep 17 00:00:00 2001 From: Cody Reichert Date: Fri, 4 Sep 2026 14:21:30 -0500 Subject: [PATCH 1/5] Improve accessibility compliance for links, form labels, and headings - Add property address context to "More details" and "View Details" links using aria-label and .screen-reader-text. - Add programmatically associated labels and matching IDs to all search and contact form inputs. - Connect the "Sort by" label to the select dropdown with matching ID. - Correct heading hierarchy across search results and open house archives to eliminate skipped heading levels. - Introduce filters (simplyrets_search_heading_tag, simplyrets_listing_heading_tag, simplyrets_results_heading_tag) for configurable heading levels. - Define .screen-reader-text utility class and expand heading selectors in simply-rets-client.css to maintain visual consistency. --- src/assets/css/simply-rets-client.css | 23 ++++ src/assets/js/simply-rets-client.js | 2 +- src/simply-rets-maps.php | 5 +- src/simply-rets-openhouses.php | 24 +++- src/simply-rets-renderer.php | 190 ++++++++++++++++++-------- 5 files changed, 179 insertions(+), 65 deletions(-) diff --git a/src/assets/css/simply-rets-client.css b/src/assets/css/simply-rets-client.css index fae3731..4bdc54b 100644 --- a/src/assets/css/simply-rets-client.css +++ b/src/assets/css/simply-rets-client.css @@ -36,6 +36,24 @@ sizes with this class. ``` */ +/* +Accessibility: Text meant only for screen readers. +Matches the standard WordPress screen-reader-text class. +*/ +.screen-reader-text { + border: 0; + clip: rect(1px, 1px, 1px, 1px); + -webkit-clip-path: inset(50%); + clip-path: inset(50%); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + word-wrap: normal !important; +} + .sr-listing { position: relative; display: block; @@ -187,6 +205,8 @@ div#sr-contact-form-error { background-color: #eee; } +.sr-primary-data h2, +.sr-primary-data h3, .sr-primary-data h4 { padding-left: 15px; margin-top: 10px !important; @@ -615,6 +635,7 @@ Most of these elements also have id's for you to use specifically. clear: both; } +#sr-search-wrapper h2, #sr-search-wrapper h3 { margin-top: 0px; } @@ -938,6 +959,8 @@ elsewhere, this should be a breeze. clear: both; } + .sr-primary-data h2, + .sr-primary-data h3, .sr-primary-data h4 { padding-right: 15px; } diff --git a/src/assets/js/simply-rets-client.js b/src/assets/js/simply-rets-client.js index 615f1c9..1663e91 100644 --- a/src/assets/js/simply-rets-client.js +++ b/src/assets/js/simply-rets-client.js @@ -194,7 +194,7 @@ var genMarkerPopup = function ( ' ' + '
' + '
' + - ' View Details' + + ' View Details for ' + addr + '' + '
' + ''; diff --git a/src/simply-rets-maps.php b/src/simply-rets-maps.php index 6cd23f1..601da53 100644 --- a/src/simply-rets-maps.php +++ b/src/simply-rets-maps.php @@ -164,8 +164,9 @@ public static function infoWindowMarkup(
- View Details + class='sr-iw-inner__details-link' + aria-label=""> + View Details
diff --git a/src/simply-rets-openhouses.php b/src/simply-rets-openhouses.php index 5343029..5ce8cb2 100644 --- a/src/simply-rets-openhouses.php +++ b/src/simply-rets-openhouses.php @@ -105,6 +105,18 @@ public static function openHousesSearchResults($search_response, $settings) { return SrMessages::noResultsMsg($res); } else { + $results_heading_raw = apply_filters('simplyrets_results_heading_tag', 'h2'); + $results_heading = tag_escape($results_heading_raw); + if (empty($results_heading)) { + $results_heading = 'h2'; + } + $show_results_heading = apply_filters('simplyrets_show_results_heading', true); + $results_heading_text = apply_filters('simplyrets_openhouses_heading_text', 'Open Houses'); + + if ($show_results_heading && !empty($res)) { + $markup .= "<{$results_heading} class='sr-listings-heading screen-reader-text'>" . esc_html($results_heading_text) . ""; + } + // Generate markup for each open house result foreach ($res as $idx => $oh) { $markup .= SimplyRetsOpenHouses::openHouseSearchResultMarkup( @@ -191,6 +203,12 @@ public static function openHouseSearchResultMarkup($openhouse, $settings) { $sqft = !empty($living_area) ? "SqFt: {$living_area} sqft
" : ""; + $listing_heading_raw = apply_filters('simplyrets_listing_heading_tag', 'h3'); + $listing_heading = tag_escape($listing_heading_raw); + if (empty($listing_heading)) { + $listing_heading = 'h3'; + } + ob_start(); ?>
@@ -207,12 +225,12 @@ class="sr-photo"
@@ -231,7 +249,7 @@ class="sr-photo"
clearfix - More details + More details diff --git a/src/simply-rets-renderer.php b/src/simply-rets-renderer.php index 31443f9..554265d 100644 --- a/src/simply-rets-renderer.php +++ b/src/simply-rets-renderer.php @@ -1052,6 +1052,20 @@ public static function srResidentialResultsGenerator($request_response, $setting $map->setAutoZoom(true); } + $listing_heading_raw = apply_filters('simplyrets_listing_heading_tag', 'h3'); + $listing_heading = tag_escape($listing_heading_raw); + if (empty($listing_heading)) { + $listing_heading = 'h3'; + } + + $results_heading_raw = apply_filters('simplyrets_results_heading_tag', 'h2'); + $results_heading = tag_escape($results_heading_raw); + if (empty($results_heading)) { + $results_heading = 'h2'; + } + $show_results_heading = apply_filters('simplyrets_show_results_heading', true); + $results_heading_text = apply_filters('simplyrets_results_heading_text', 'Listings'); + $resultsMarkup = ""; foreach ($response as $listing) { $listing_uid = $listing->mlsId; @@ -1258,11 +1272,11 @@ public static function srResidentialResultsGenerator($request_response, $setting . '
' . ' ' . '
' @@ -1280,7 +1294,7 @@ public static function srResidentialResultsGenerator($request_response, $setting . '
' . '
' . ' ' - . ' More details' + . ' More details ' . esc_html('for ' . $full_address) . '' . ' ' . ' ' . $compliance_markup @@ -1304,11 +1318,11 @@ public static function srResidentialResultsGenerator($request_response, $setting . '
' . ' ' . '
' @@ -1326,7 +1340,7 @@ public static function srResidentialResultsGenerator($request_response, $setting . '
' . '
' . ' ' - . ' More details' + . ' More details ' . esc_html('for ' . $full_address) . '' . ' ' . ' ' . $compliance_markup @@ -1336,8 +1350,12 @@ public static function srResidentialResultsGenerator($request_response, $setting } } + $results_heading_markup = ($show_results_heading && !empty($response)) + ? "<{$results_heading} class='sr-listings-heading screen-reader-text'>" . esc_html($results_heading_text) . "" + : ""; $markupGridViewClass = $grid_view == true ? "sr-listings-grid-view" : ""; $resultsMarkup = "
" + . $results_heading_markup . "{$resultsMarkup}" . "
"; $markerCount > 0 ? $mapMarkup = $mapHelper->render($map) : $mapMarkup = ''; @@ -1485,36 +1503,42 @@ public static function srContactFormMarkup($listing) { // Process any form submissions $submission_message = SimplyRetsContactForm::srContactFormDeliver(); + $contact_heading_raw = apply_filters('simplyrets_contact_heading_tag', 'h3'); + $contact_heading = tag_escape($contact_heading_raw); + if (empty($contact_heading)) { + $contact_heading = 'h3'; + } + // Default lead capture form $markup = ''; $markup .= '
'; $markup .= '
'; $markup .= $submission_message; - $markup .= '

Contact us about this listing

'; + $markup .= '<' . $contact_heading . '>Contact us about this listing'; $markup .= '
'; $markup .= wp_nonce_field('sr_contact_action', 'sr_contact_nonce', true, false); $markup .= '

'; $markup .= ''; - $markup .= 'Your Name (required)
'; - $markup .= 'Your Name (required)
'; + $markup .= ''; $markup .= '

'; $markup .= '

'; - $markup .= 'Your Email (required)
'; - $markup .= 'Your Email (required)
'; + $markup .= ''; $markup .= '

'; $markup .= '

'; - $markup .= 'Subject (required)
'; - $markup .= 'Subject (required)
'; + $markup .= ''; $markup .= '

'; $markup .= '

'; - $markup .= 'Your Message (required)
'; - $markup .= ''; $markup .= '

'; @@ -1678,21 +1702,31 @@ public static function renderMapSearchForm($atts) { } } + $search_heading_raw = apply_filters('simplyrets_search_heading_tag', 'h2'); + $search_heading = tag_escape($search_heading_raw); + if (empty($search_heading)) { + $search_heading = 'h2'; + } + $search_form = '
' . '
' - . '

Search Listings

' + . ' <' . $search_heading . ' class="sr-search-heading">Search Listings' . ' ' . ' ' . '
' . '
' - . ' Search keywords' + . ' ' . '
' . '
' - . ' ' . ' ' . $type_options . ' ' @@ -1700,22 +1734,28 @@ public static function renderMapSearchForm($atts) { . '
' . '
' . '
' - . ' ' + . ' ' + . ' ' . '
' . '
' - . ' ' + . ' ' + . ' ' . '
' . '
' - . ' ' + . ' ' + . ' ' . '
' . '
' - . ' ' + . ' ' + . ' ' . '
' . '
' - . ' ' + . ' ' + . ' ' . '
' . '
' - . ' ' + . ' ' + . ' ' . '
' . '
' . ' ' @@ -1726,8 +1766,8 @@ public static function renderMapSearchForm($atts) { . '
' . ' ' . '
' - . ' ' - . ' ' . ' ' . ' ' . ' ' @@ -1935,6 +1975,12 @@ public static function renderSearchForm($atts) { $q_placeholder = "Subdivision, Zipcode, " . $MLS_text . " area, " . $MLS_text . " #, etc"; + $search_heading_raw = apply_filters('simplyrets_search_heading_tag', 'h2'); + $search_heading = tag_escape($search_heading_raw); + if (empty($search_heading)) { + $search_heading = 'h2'; + } + if (array_key_exists('advanced', $attributes) && ($attributes['advanced'] == 'true' || $attributes['advanced'] == 'True')) { ?> @@ -1942,21 +1988,25 @@ public static function renderSearchForm($atts) { -

Advanced Listings Search

+ < class="sr-search-heading">Advanced Listings Search>
- Search keywords +
-
- - + + + +
-