PageSourceSearch

https://ashmolean.org/sites/all/themes/custom/oxtheme/js/accessibility.js?tle9wb

js ashmolean.org collected 2026-09-24 08:37:16 UTC 12,202 bytes, 283 lines download raw bytes

1jQuery(document).ready(function() {
2    setTimeout( function () {
3      // Foreach date component.
4      jQuery(".webform-calendar").each(function(){
5        //
6        var thisElement = jQuery(this).parents('.webform-component-date');
7        var thisLabel = jQuery(thisElement).find('.control-label');
8        var thisId = jQuery(this).attr('id');
9        jQuery(thisLabel).attr("for", thisId);
10
11        // add aria-label to date select boxes
12        jQuery(thisElement).find('select.form-select').each(function () {
13            jQuery(this).attr('aria-label', jQuery(jQuery(this).find('option')[0]).html())
14        })
15      });
16      // Add fieldset to grid componenet table.
17      jQuery('.webform-component-grid').each(function(){
18        var thisGrid = jQuery(this).find('table.webform-grid');
19        var thisLabel = jQuery(this).find('.control-label');
20        var thisId = jQuery(thisLabel).attr('for');
21        if (jQuery("#"+thisId).length < 1) {
22          jQuery(thisGrid).wrap('<fieldset id="' + thisId + '"></fieldset>');
23        }
24
25        // add radiogroup role to the radio buttons in a grid
26        var thisTr = jQuery(this).find('tr')
27        var firstTd = jQuery(thisTr).find('td')[0]
28        // disable adding radiogroup to webform grid's "tr" elements
29        // radiogroup makes NVDA miscount rows and columns, it always reads 0 rows, 0 columns
30        // jQuery(thisTr).attr('role', "radiogroup")
31        jQuery(thisTr).attr('aria-label', jQuery(firstTd).html())
32      });
33
34      // add description to the top-left cell of a grid if it's empty
35      jQuery('.webform-component-grid thead th.webform-grid-question').each(function(){
36          if (this.innerHTML.length == 0) {
37              jQuery(this).append( "<span class='screen-reader-only'>table header</span>" )
38          }
39      });
40
41      // add radiogroup role to the radio buttons in redios component
42      jQuery('.webform-component-radios').each(function () {
43          jQuery(this).attr('role', "radiogroup")
44          var thisLabel = jQuery(this).find('label')
45          jQuery(this).attr('aria-label', jQuery(thisLabel).text())
46          jQuery(this).find('input[type="radio"]').attr('role', "radio")
47      })
48
49      // if a label points (with its for attribute) to a div or fieldset convert the label to a div
50      jQuery('label.control-label').each(function () {
51          var forAttr = jQuery(this).attr('for')
52          if (jQuery('#' + forAttr).is("div") || jQuery('#' + forAttr).is("fieldset") || jQuery('#' + forAttr).length == 0) {
53              jQuery(this).replaceWith("<div class='"+ this.className +" label_replace'>"+ this.innerHTML +"</div>");
54          }
55      })
56
57      // convert Time labels to divs
58      jQuery('.webform-component-time label.element-invisible').each(function () {
59          jQuery(this).replaceWith("<div class='"+ this.className +"'>"+ this.innerHTML +"</div>");
60      })
61
62      // add 'for' attribute to time component
63      jQuery('.webform-component-time').each(function (idx) {
64          var thisLabel = jQuery(this).find('label')
65          var thisInputs = jQuery(this).find('.webform-container-inline')
66          jQuery(thisInputs).attr('id', "time-" + idx)
67          if (!jQuery(thisLabel).attr('for')) {
68              jQuery(thisLabel).attr('for', "time-" + idx)
69          }
70
71          // add aria-label time component to select boxes
72          var thisSelect = jQuery(this).find('select')
73          jQuery(thisSelect).attr('aria-label', jQuery(jQuery(thisSelect).find('option')[0]).html())
74      })
75
76      // Add ARIA label to recaptcha response textarea.
77      jQuery('.g-recaptcha-response').each(function(){
78        jQuery(this).attr('aria-label', 'Recaptcha response');
79      });
80      //
81      jQuery('.ui-datepicker').each(function(){
82        jQuery(this).attr('role','dialog').attr('aria-modal','true').attr('aria-label', "Select a date");
83        jQuery('.powered-by-wrapper').append(jQuery(this));
84      });
85
86      jQuery(".flatpickr").each(function() {
87        var prevId = jQuery(this).prev().attr('id');
88        if (prevId) {
89          var labelId = 'label-' + prevId
90          jQuery('label[for="' + prevId + '"]').attr('id', labelId);
91          jQuery(this).attr('aria-labelledby', labelId);
92        }
93
94        // aria-labelledby
95      })
96      // Add ARIA label to webform progress bar.
97      jQuery('.webform-progressbar').each(function(){
98          var progressPages = jQuery(this).find('.webform-progressbar-page')
99          var currentPage = 0
100          progressPages.each(function(idx){
101              if (jQuery(this).hasClass('current')) {
102                  currentPage = idx
103                  return false;
104              }
105          })
106          jQuery(this).append( "<div class='screen-reader-only'>Webform progress: "+ currentPage +" of "+ progressPages.length +" steps completed</div>" )
107      });
108
109      // give focus and read the error message when page loads
110      var errorMessages = jQuery('.alert.alert-danger.error')
111      if (errorMessages.length) {
112          jQuery(errorMessages[0]).attr('tabIndex','-1')
113          jQuery(errorMessages[0]).focus()
114      }
115
116      // slideshow/carousel add scread reader labels to pagination dots
117      /*jQuery('.swiper-pagination').each(function(idx){
118          jQuery(this).append( "<span class='screen-reader-only'>Slideshow pagination bullets</span>" )
119      })*/
120
121      // slideshow/carousel add scread reader labels to previous, next slide buttons
122            jQuery('.swiper-button-next').each(function(idx){
123          jQuery(this).append( "<span class='screen-reader-only'>Next slide</span>" )
124      })
125      jQuery('.swiper-button-prev').each(function(idx){
126          jQuery(this).append( "<span class='screen-reader-only'>Previous slide</span>" )
127      })
128
129      // cookie control
130      // move the about icon next to the header dom element where its real position is
131      jQuery('.ccc-inner h2').prepend(jQuery('a.ccc-icon'))
132      // remove the "About Cookie Control" text, add aria-label
133      jQuery('a.ccc-icon').text('')
134      jQuery('a.ccc-icon').attr('aria-label','About Cookie Control')
135
136      // chosen fixes, suggested in: https://github.com/harvesthq/chosen/issues/264#issuecomment-232286392 (css disabled)
137      // With css disabed the selected option is now visible
138      jQuery("select.oxdrupal_dropdown").chosen().change(function (ev, el, asd) {
139          var parentEl = jQuery(ev.target).parent()
140          var idx = parentEl.find('option').index(parentEl.find('option[value="'+el.selected+'"]')[0])
141          parentEl.find('.chosen-results').find("li").each(function () {
142              if (jQuery(this).data('option-array-index') == idx) {
143                  jQuery(this).html("<strong>" + jQuery(this).text() + "</strong>")
144              } else {
145                  jQuery(this).html(jQuery(this).text())
146              }
147          })
148      })
149
150      // add popover to feedback form radio buttons to explain that keyboard
151      // navigation works with the arrow kays
152      jQuery('#edit-submitted-was-this-page-useful').popover({
153          trigger: 'manual', placement: 'top', animation: false,
154          content: 'Use arrow keys'
155      })
156      jQuery('#oxdrupal_feedback_form_wrapper input[type="radio"]').keyup(function(ev) {
157          jQuery('#edit-submitted-was-this-page-useful').popover('show')
158      })
159      jQuery('#oxdrupal_feedback_form_wrapper input[type="radio"]').blur(function (ev) {
160          setTimeout(function () {
161              // only hide the popover if we moved outside of the radiogroup
162              var isLabelActive = jQuery('#oxdrupal_feedback_form_wrapper label.active').length
163              if (!isLabelActive) {
164                  jQuery('#edit-submitted-was-this-page-useful').popover('hide')
165              }
166          }, 100)
167      })
168
169      jQuery(".pause-animated-content").on('click', pauseAnimatedContent);
170
171    }, 500)
172
173    // On focus of a Webform Grid radio, highlight row.
174  jQuery(document).on("focusin", '.webform-grid-option input[type="radio"]', function(e) {
175  	var thisRadio = jQuery(this);
176  	jQuery(thisRadio).parents('tr[role="radiogroup"]').addClass('active');
177  });
178  // On focus out of a Webform Grid radio, un-highlight row.
179  jQuery(document).on("focusout", '.webform-grid-option input[type="radio"]', function(e){
180    var thisRadio = jQuery(this);
181    jQuery(thisRadio).parents('tr[role="radiogroup"]').removeClass('active');
182  });
183
184  jQuery(document).on("focusin", '.oxdrupal_feedback_form input[type="radio"]', function(e) {
185    var thisRadio = jQuery(this);
186    jQuery(thisRadio).parent('label').addClass('active');
187  });
188
189  jQuery(document).on("focusout", '.oxdrupal_feedback_form input[type="radio"]', function(e){
190    var thisRadio = jQuery(this);
191    jQuery(thisRadio).parent('label').removeClass('active');
192  });
193
194  /**/
195  //
196  jQuery(document).on("click", '.publication-source-modal-trigger', function(){
197    activateModal(jQuery(this).siblings(".modal"));
198  });
199  //
200  jQuery(document).on("keyup", '.publication-source-modal-trigger', function(e){
201    if (e.keyCode === 13) {
202      activateModal(jQuery(this).siblings(".modal"));
203    }
204  });
205  /**/
206  //
207  jQuery(document).on("click", '.publication-source-modal-trigger ~ .modal button.close', function(){
208    deactivateModal(jQuery(this).parents(".modal"))
209  });
210  //
211  jQuery(document).on("keyup", '.publication-source-modal-trigger ~ .modal button.close', function(e){
212    if (e.keyCode === 13 || e.keyCode === 32) {
213      deactivateModal(jQuery(this).siblings(".modal"));
214    }
215  });
216  //
217  jQuery(document).on("click", '.publication-source-modal-trigger ~ .modal', function(e){
218      deactivateModal(jQuery(this));
219  });
220  //
221  jQuery(document).on("click", '.publication-source-modal-trigger ~ .modal *', function(e){
222    e.stopPropagation();
223  });
224
225  jQuery('.oxdrupal_dropdown_container').each(function(){
226    var dropdownOption = jQuery(this).find('a.chosen-single');
227    jQuery(dropdownOption).find("div").attr("aria-hidden", "true");
228    jQuery(".chosen-search-input").attr("placeholder", jQuery(".chosen-search-input").attr("aria-label"));
229  });
230
231  // Add more information to tabs.
232  jQuery(document).on("click", ".nav-tabs li", function (e) {
233    var thisTab = jQuery(this);
234    jQuery(thisTab).attr("aria-selected", "true");
235    jQuery(thisTab).siblings().attr("aria-selected", "false");
236    // jQuery UI incorrectly adds the aria-expanded attribute to the tab controls.
237    // They are unlikely to fix it so we need to hack around it.
238    // see https://github.com/jquery/jquery-ui/issues/2094
239    jQuery(thisTab).parent().find("a").removeAttr("aria-expanded");
240
241  });
242
243  // If a tab is pre-selected with a URL hash, set aria-selected attribute to true.
244  if (window.location.hash && jQuery(this).find('nav-tabs a[href="' + window.location.hash + '"]')) {
245    var tabFromUrlHash = jQuery('a[href="' + window.location.hash + '"]').parent();
246    jQuery(tabFromUrlHash).attr("aria-selected", "true");
247    jQuery(tabFromUrlHash).siblings().attr("aria-selected", "false");
248    // See comment in function above - hack to fix jQuery UI accessibility issue.
249    jQuery(tabFromUrlHash).parent().find("a").removeAttr("aria-expanded");
250  }
251
252});
253
254function pauseAnimatedContent(e){
255  e.preventDefault();
256  console.log("pausing slideshows / carousels");
257  //Find all animated elements and click their pause buttons
258  jQuery('.paragraphs-item .swiper-pause-button').each(function(index, el) {
259    console.log(el);
260    el.click();
261  });
262  console.log("pausing background videos");
263  jQuery('.youtube-play-pause-button').each(function(index, el) {
264    //Had to use jQuery on the dom object as I couldnt't get the attribute selector [aria-label*="Pause"] to work
265    if(jQuery(el)[0].ariaLabel.includes("Pause")) {
266      el.click();
267    }
268  });
269
270}
271
272function activateModal(element) {
273  jQuery(element).attr('aria-hidden', false);
274}
275
276function deactivateModal(element) {
277  jQuery(element).attr('aria-hidden', true);
278}
279
280jQuery(document).on('focus', '.item-style-tile_text_rollover a.listing-item-link', function(){
281  jQuery('.item-style-tile_text_rollover').removeClass('active');
282  jQuery(this).closest('.item-style-tile_text_rollover').addClass('active');
283});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.