dom-scripts.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* expandable sections */
  2. (function () {
  3. function toggle (button, target) {
  4. var expanded = button.getAttribute('aria-expanded') === 'true';
  5. button.setAttribute('aria-expanded', !expanded);
  6. target.hidden = !target.hidden;
  7. }
  8. var expanders = document.querySelectorAll('[data-expands]');
  9. Array.prototype.forEach.call(expanders, function (expander) {
  10. var target = document.getElementById(expander.getAttribute('data-expands'));
  11. expander.addEventListener('click', function () {
  12. toggle(expander, target);
  13. })
  14. })
  15. }());
  16. /* menu button */
  17. (function () {
  18. var button = document.getElementById('menu-button');
  19. if (button) {
  20. var menu = document.getElementById('patterns-list');
  21. button.addEventListener('click', function() {
  22. var expanded = this.getAttribute('aria-expanded') === 'true';
  23. this.setAttribute('aria-expanded', !expanded);
  24. })
  25. }
  26. }());
  27. /* persist navigation scroll point */
  28. (function () {
  29. window.onbeforeunload = function () {
  30. var patternsNav = document.getElementById('patterns-nav');
  31. if (patternsNav) {
  32. var scrollPoint = patternsNav.scrollTop;
  33. localStorage.setItem('scrollPoint', scrollPoint);
  34. }
  35. }
  36. window.addEventListener('DOMContentLoaded', function () {
  37. if (document.getElementById('patterns-nav')) {
  38. if (window.location.href.indexOf('patterns/') !== -1) {
  39. document.getElementById('patterns-nav').scrollTop = parseInt(localStorage.getItem('scrollPoint'));
  40. } else {
  41. document.getElementById('patterns-nav').scrollTop = 0;
  42. }
  43. }
  44. })
  45. }());
  46. /* Add "link here" links to <h2> headings */
  47. (function () {
  48. var headings = document.querySelectorAll('main > h2');
  49. Array.prototype.forEach.call(headings, function (heading) {
  50. var id = heading.getAttribute('id');
  51. if (id) {
  52. var newHeading = heading.cloneNode(true);
  53. var container = document.createElement('div');
  54. container.setAttribute('class', 'h2-container');
  55. container.appendChild(newHeading);
  56. heading.parentNode.insertBefore(container, heading);
  57. var link = document.createElement('a');
  58. link.setAttribute('href', '#' + id);
  59. var headingText = heading.textContent;
  60. link.setAttribute('aria-label', 'To this ' + headingText + ' section');
  61. link.innerHTML = '<svg aria-hidden="true" viewBox="0 0 50 50" focusable="false"> <use xlink:href="#link"></use> </svg>';
  62. container.appendChild(link);
  63. heading.parentNode.removeChild(heading);
  64. }
  65. })
  66. }());
  67. /* SVG scaling fix for IE10-11 */
  68. (function () {
  69. if (window.matchMedia('(-ms-high-contrast: none), (-ms-high-contrast: active)').matches) {
  70. // Get all the SVGs on the page except the symbol defs
  71. var svgs = document.querySelectorAll('a svg, button svg, h1 svg, .tags svg');
  72. // ... iterate over SVGs
  73. Array.prototype.forEach.call(svgs, function(svg) {
  74. // Set preserveAspectRatio to 'XMidYMin slice'
  75. svg.setAttribute('preserveAspectRatio', 'xMidYMin slice');
  76. // Turn the viewBox values into an array
  77. var viewBox = svg.getAttribute('viewBox').split(' ');
  78. // Calculate padding value needed (width/height x 100)
  79. var padding = (viewBox[2] / viewBox[3]) * 100;
  80. // Set inline styles
  81. svg.setAttribute('style', 'width: 100%; height: 1px; padding-bottom: ' + padding + '%; overflow: visible');
  82. // Create span wrapper
  83. var span = document.createElement('span');
  84. span.setAttribute('class', 'svg-outer');
  85. span.style.width = '0.75em';
  86. svg.parentNode.insertBefore(span, svg);
  87. span.appendChild(svg);
  88. })
  89. }
  90. }());
  91. /* Contrast calculation */
  92. function hexToRgb(hex) {
  93. var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  94. return result ? [
  95. parseInt(result[1], 16),
  96. parseInt(result[2], 16),
  97. parseInt(result[3], 16)
  98. ] : null;
  99. }
  100. function luminance(r, g, b) {
  101. var a = [r, g, b].map(function (v) {
  102. v /= 255;
  103. return v <= 0.03928
  104. ? v / 12.92
  105. : Math.pow( (v + 0.055) / 1.055, 2.4 );
  106. });
  107. return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
  108. }
  109. function ratio(hex1, hex2) {
  110. var rgb1 = hexToRgb(hex1);
  111. var rgb2 = hexToRgb(hex2);
  112. var luminance1 = luminance(rgb1[0], rgb1[1], rgb1[2]) + 0.05;
  113. var luminance2 = luminance(rgb2[0], rgb2[1], rgb2[2]) + 0.05;
  114. var ratio = luminance1 > luminance2 ? luminance1 / luminance2 : luminance2 / luminance1;
  115. var level;
  116. if (ratio > 4.5) {
  117. level = ratio > 7 ? "AAA" : "AA";
  118. } else {
  119. level = "Fails";
  120. }
  121. return {
  122. ratio: ratio.toFixed(2)+':1',
  123. level: level
  124. }
  125. }