idsk_frontend_toolkit 7.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.gitmodules +3 -0
  4. data/.ruby-version +1 -0
  5. data/.travis/govuk_frontend_toolkit_gem_push.enc +0 -0
  6. data/.travis/govuk_frontend_toolkit_gem_push.pub +1 -0
  7. data/.travis.yml +23 -0
  8. data/CONTRIBUTING.md +13 -0
  9. data/Gemfile +3 -0
  10. data/LICENCE +20 -0
  11. data/README.md +61 -0
  12. data/Rakefile +10 -0
  13. data/app/assets/.gitignore +5 -0
  14. data/app/assets/.ruby-version +1 -0
  15. data/app/assets/.travis/README.md +23 -0
  16. data/app/assets/.travis/govuk_frontend_toolkit_push.enc +0 -0
  17. data/app/assets/.travis/govuk_frontend_toolkit_push.pub +1 -0
  18. data/app/assets/.travis.yml +18 -0
  19. data/app/assets/CHANGELOG.md +381 -0
  20. data/app/assets/CONTRIBUTING.md +23 -0
  21. data/app/assets/Gemfile +4 -0
  22. data/app/assets/Gemfile.lock +48 -0
  23. data/app/assets/Gruntfile.js +68 -0
  24. data/app/assets/LICENCE +20 -0
  25. data/app/assets/README.md +170 -0
  26. data/app/assets/VERSION.txt +1 -0
  27. data/app/assets/create-release.sh +38 -0
  28. data/app/assets/docs/analytics.md +270 -0
  29. data/app/assets/docs/functions.md +62 -0
  30. data/app/assets/docs/javascript.md +337 -0
  31. data/app/assets/docs/mixins.md +617 -0
  32. data/app/assets/images/accordion-arrow-2x.png +0 -0
  33. data/app/assets/images/accordion-arrow.png +0 -0
  34. data/app/assets/images/arrow-sprite.png +0 -0
  35. data/app/assets/images/crests/bis_crest_13px.png +0 -0
  36. data/app/assets/images/crests/bis_crest_13px_x2.png +0 -0
  37. data/app/assets/images/crests/bis_crest_18px.png +0 -0
  38. data/app/assets/images/crests/bis_crest_18px_x2.png +0 -0
  39. data/app/assets/images/crests/bis_crest_27px.png +0 -0
  40. data/app/assets/images/crests/bis_crest_27px_x2.png +0 -0
  41. data/app/assets/images/crests/coastguard_13px.png +0 -0
  42. data/app/assets/images/crests/coastguard_13px_x2.png +0 -0
  43. data/app/assets/images/crests/coastguard_18px.png +0 -0
  44. data/app/assets/images/crests/coastguard_18px_x2.png +0 -0
  45. data/app/assets/images/crests/coastguard_27px.png +0 -0
  46. data/app/assets/images/crests/coastguard_27px_x2.png +0 -0
  47. data/app/assets/images/crests/dit_crest_13px.png +0 -0
  48. data/app/assets/images/crests/dit_crest_13px_x2.png +0 -0
  49. data/app/assets/images/crests/dit_crest_18px.png +0 -0
  50. data/app/assets/images/crests/dit_crest_18px_x2.png +0 -0
  51. data/app/assets/images/crests/dit_crest_27px.png +0 -0
  52. data/app/assets/images/crests/dit_crest_27px_x2.png +0 -0
  53. data/app/assets/images/crests/hmrc_crest_13px.png +0 -0
  54. data/app/assets/images/crests/hmrc_crest_13px_x2.png +0 -0
  55. data/app/assets/images/crests/hmrc_crest_18px.png +0 -0
  56. data/app/assets/images/crests/hmrc_crest_18px_x2.png +0 -0
  57. data/app/assets/images/crests/hmrc_crest_27px.png +0 -0
  58. data/app/assets/images/crests/hmrc_crest_27px_x2.png +0 -0
  59. data/app/assets/images/crests/ho_crest_13px.png +0 -0
  60. data/app/assets/images/crests/ho_crest_13px_x2.png +0 -0
  61. data/app/assets/images/crests/ho_crest_18px.png +0 -0
  62. data/app/assets/images/crests/ho_crest_18px_x2.png +0 -0
  63. data/app/assets/images/crests/ho_crest_27px.png +0 -0
  64. data/app/assets/images/crests/ho_crest_27px_x2.png +0 -0
  65. data/app/assets/images/crests/mod_crest_13px.png +0 -0
  66. data/app/assets/images/crests/mod_crest_13px_x2.png +0 -0
  67. data/app/assets/images/crests/mod_crest_18px.png +0 -0
  68. data/app/assets/images/crests/mod_crest_18px_x2.png +0 -0
  69. data/app/assets/images/crests/mod_crest_27px.png +0 -0
  70. data/app/assets/images/crests/mod_crest_27px_x2.png +0 -0
  71. data/app/assets/images/crests/org_crest_13px.png +0 -0
  72. data/app/assets/images/crests/org_crest_13px_x2.png +0 -0
  73. data/app/assets/images/crests/org_crest_18px.png +0 -0
  74. data/app/assets/images/crests/org_crest_18px_x2.png +0 -0
  75. data/app/assets/images/crests/org_crest_27px.png +0 -0
  76. data/app/assets/images/crests/org_crest_27px_x2.png +0 -0
  77. data/app/assets/images/crests/portcullis_13px.png +0 -0
  78. data/app/assets/images/crests/portcullis_13px_x2.png +0 -0
  79. data/app/assets/images/crests/portcullis_18px.png +0 -0
  80. data/app/assets/images/crests/portcullis_18px_x2.png +0 -0
  81. data/app/assets/images/crests/portcullis_27px.png +0 -0
  82. data/app/assets/images/crests/portcullis_27px_x2.png +0 -0
  83. data/app/assets/images/crests/so_crest_13px.png +0 -0
  84. data/app/assets/images/crests/so_crest_13px_x2.png +0 -0
  85. data/app/assets/images/crests/so_crest_18px.png +0 -0
  86. data/app/assets/images/crests/so_crest_18px_x2.png +0 -0
  87. data/app/assets/images/crests/so_crest_27px.png +0 -0
  88. data/app/assets/images/crests/so_crest_27px_x2.png +0 -0
  89. data/app/assets/images/crests/ukaea_crest_13px.png +0 -0
  90. data/app/assets/images/crests/ukaea_crest_13px_x2.png +0 -0
  91. data/app/assets/images/crests/ukaea_crest_18px.png +0 -0
  92. data/app/assets/images/crests/ukaea_crest_18px_x2.png +0 -0
  93. data/app/assets/images/crests/ukaea_crest_27px.png +0 -0
  94. data/app/assets/images/crests/ukaea_crest_27px_x2.png +0 -0
  95. data/app/assets/images/crests/ukho_13px.png +0 -0
  96. data/app/assets/images/crests/ukho_13px_x2.png +0 -0
  97. data/app/assets/images/crests/ukho_18px.png +0 -0
  98. data/app/assets/images/crests/ukho_18px_x2.png +0 -0
  99. data/app/assets/images/crests/ukho_27px.png +0 -0
  100. data/app/assets/images/crests/ukho_27px_x2.png +0 -0
  101. data/app/assets/images/crests/wales_crest_13px.png +0 -0
  102. data/app/assets/images/crests/wales_crest_13px_x2.png +0 -0
  103. data/app/assets/images/crests/wales_crest_18px.png +0 -0
  104. data/app/assets/images/crests/wales_crest_18px_x2.png +0 -0
  105. data/app/assets/images/crests/wales_crest_27px.png +0 -0
  106. data/app/assets/images/crests/wales_crest_27px_x2.png +0 -0
  107. data/app/assets/images/icon-arrow-left.png +0 -0
  108. data/app/assets/images/icon-calendar-2x.png +0 -0
  109. data/app/assets/images/icon-calendar.png +0 -0
  110. data/app/assets/images/icon-file-download-2x.png +0 -0
  111. data/app/assets/images/icon-file-download.png +0 -0
  112. data/app/assets/images/icon-important-2x.png +0 -0
  113. data/app/assets/images/icon-important.png +0 -0
  114. data/app/assets/images/icon-information-2x.png +0 -0
  115. data/app/assets/images/icon-information.png +0 -0
  116. data/app/assets/images/icon-locator-2x.png +0 -0
  117. data/app/assets/images/icon-locator.png +0 -0
  118. data/app/assets/images/icon-pointer-2x.png +0 -0
  119. data/app/assets/images/icon-pointer-black-2x.png +0 -0
  120. data/app/assets/images/icon-pointer-black.png +0 -0
  121. data/app/assets/images/icon-pointer-indexed.png +0 -0
  122. data/app/assets/images/icon-pointer.png +0 -0
  123. data/app/assets/images/icon-search-2x.png +0 -0
  124. data/app/assets/images/icon-search.png +0 -0
  125. data/app/assets/images/icon-steps/icon-step-1-2x.png +0 -0
  126. data/app/assets/images/icon-steps/icon-step-1.png +0 -0
  127. data/app/assets/images/icon-steps/icon-step-10-2x.png +0 -0
  128. data/app/assets/images/icon-steps/icon-step-10.png +0 -0
  129. data/app/assets/images/icon-steps/icon-step-11-2x.png +0 -0
  130. data/app/assets/images/icon-steps/icon-step-11.png +0 -0
  131. data/app/assets/images/icon-steps/icon-step-12-2x.png +0 -0
  132. data/app/assets/images/icon-steps/icon-step-12.png +0 -0
  133. data/app/assets/images/icon-steps/icon-step-13-2x.png +0 -0
  134. data/app/assets/images/icon-steps/icon-step-13.png +0 -0
  135. data/app/assets/images/icon-steps/icon-step-14-2x.png +0 -0
  136. data/app/assets/images/icon-steps/icon-step-14.png +0 -0
  137. data/app/assets/images/icon-steps/icon-step-2-2x.png +0 -0
  138. data/app/assets/images/icon-steps/icon-step-2.png +0 -0
  139. data/app/assets/images/icon-steps/icon-step-3-2x.png +0 -0
  140. data/app/assets/images/icon-steps/icon-step-3.png +0 -0
  141. data/app/assets/images/icon-steps/icon-step-4-2x.png +0 -0
  142. data/app/assets/images/icon-steps/icon-step-4.png +0 -0
  143. data/app/assets/images/icon-steps/icon-step-5-2x.png +0 -0
  144. data/app/assets/images/icon-steps/icon-step-5.png +0 -0
  145. data/app/assets/images/icon-steps/icon-step-6-2x.png +0 -0
  146. data/app/assets/images/icon-steps/icon-step-6.png +0 -0
  147. data/app/assets/images/icon-steps/icon-step-7-2x.png +0 -0
  148. data/app/assets/images/icon-steps/icon-step-7.png +0 -0
  149. data/app/assets/images/icon-steps/icon-step-8-2x.png +0 -0
  150. data/app/assets/images/icon-steps/icon-step-8.png +0 -0
  151. data/app/assets/images/icon-steps/icon-step-9-2x.png +0 -0
  152. data/app/assets/images/icon-steps/icon-step-9.png +0 -0
  153. data/app/assets/images/player-icon-forward.png +0 -0
  154. data/app/assets/images/player-icon-pause.png +0 -0
  155. data/app/assets/images/player-icon-play.png +0 -0
  156. data/app/assets/images/player-icon-rewind.png +0 -0
  157. data/app/assets/images/player-icon-volume.png +0 -0
  158. data/app/assets/images/separator-2x.png +0 -0
  159. data/app/assets/images/separator.png +0 -0
  160. data/app/assets/javascripts/govuk/analytics/analytics.js +143 -0
  161. data/app/assets/javascripts/govuk/analytics/download-link-tracker.js +41 -0
  162. data/app/assets/javascripts/govuk/analytics/error-tracking.js +51 -0
  163. data/app/assets/javascripts/govuk/analytics/external-link-tracker.js +56 -0
  164. data/app/assets/javascripts/govuk/analytics/google-analytics-universal-tracker.js +166 -0
  165. data/app/assets/javascripts/govuk/analytics/govuk-tracker.js +134 -0
  166. data/app/assets/javascripts/govuk/analytics/mailto-link-tracker.js +38 -0
  167. data/app/assets/javascripts/govuk/analytics/print-intent.js +39 -0
  168. data/app/assets/javascripts/govuk/details.polyfill.js +240 -0
  169. data/app/assets/javascripts/govuk/modules/auto-track-event.js +30 -0
  170. data/app/assets/javascripts/govuk/modules.js +61 -0
  171. data/app/assets/javascripts/govuk/primary-links.js +57 -0
  172. data/app/assets/javascripts/govuk/selection-buttons.js +116 -0
  173. data/app/assets/javascripts/govuk/shim-links-with-button-role.js +34 -0
  174. data/app/assets/javascripts/govuk/show-hide-content.js +172 -0
  175. data/app/assets/javascripts/govuk/stick-at-top-when-scrolling.js +128 -0
  176. data/app/assets/javascripts/govuk/stop-scrolling-at-footer.js +139 -0
  177. data/app/assets/javascripts/govuk_toolkit.js +1 -0
  178. data/app/assets/javascripts/stageprompt.js +69 -0
  179. data/app/assets/javascripts/vendor/jquery/jquery.player.min.js +25 -0
  180. data/app/assets/javascripts/vendor/polyfills/bind.js +40 -0
  181. data/app/assets/package.json +25 -0
  182. data/app/assets/spec/manifest.js +41 -0
  183. data/app/assets/spec/stylesheets/_colour_contrast_spec.scss +12 -0
  184. data/app/assets/spec/support/LocalTestRunner.html +21 -0
  185. data/app/assets/spec/support/console-runner.js +102 -0
  186. data/app/assets/spec/support/load.js +47 -0
  187. data/app/assets/spec/support/run_jasmine_test.js +62 -0
  188. data/app/assets/spec/unit/analytics/analytics.spec.js +315 -0
  189. data/app/assets/spec/unit/analytics/download-link-tracker.spec.js +72 -0
  190. data/app/assets/spec/unit/analytics/error-tracking.spec.js +65 -0
  191. data/app/assets/spec/unit/analytics/external-link-tracker.spec.js +109 -0
  192. data/app/assets/spec/unit/analytics/google-analytics-universal-tracker.spec.js +180 -0
  193. data/app/assets/spec/unit/analytics/govuk-tracker.spec.js +171 -0
  194. data/app/assets/spec/unit/analytics/mailto-link-tracker.spec.js +62 -0
  195. data/app/assets/spec/unit/details.polyfill.spec.js +91 -0
  196. data/app/assets/spec/unit/modules/auto-track-event.spec.js +54 -0
  197. data/app/assets/spec/unit/modules.spec.js +93 -0
  198. data/app/assets/spec/unit/primary-links.spec.js +55 -0
  199. data/app/assets/spec/unit/selection-button.spec.js +761 -0
  200. data/app/assets/spec/unit/shim-links-with-button-role.spec.js +41 -0
  201. data/app/assets/spec/unit/show-hide-content.spec.js +306 -0
  202. data/app/assets/spec/unit/stick-at-top-when-scrolling.spec.js +137 -0
  203. data/app/assets/stylesheets/.gitkeep +0 -0
  204. data/app/assets/stylesheets/_colours.scss +2 -0
  205. data/app/assets/stylesheets/_conditionals.scss +81 -0
  206. data/app/assets/stylesheets/_css3.scss +90 -0
  207. data/app/assets/stylesheets/_device-pixels.scss +10 -0
  208. data/app/assets/stylesheets/_font_stack.scss +25 -0
  209. data/app/assets/stylesheets/_grid_layout.scss +136 -0
  210. data/app/assets/stylesheets/_helpers.scss +16 -0
  211. data/app/assets/stylesheets/_measurements.scss +14 -0
  212. data/app/assets/stylesheets/_shims.scss +55 -0
  213. data/app/assets/stylesheets/_typography.scss +249 -0
  214. data/app/assets/stylesheets/_url-helpers.scss +16 -0
  215. data/app/assets/stylesheets/colours/_organisation.scss +104 -0
  216. data/app/assets/stylesheets/colours/_palette.scss +77 -0
  217. data/app/assets/stylesheets/design-patterns/_alpha-beta.scss +67 -0
  218. data/app/assets/stylesheets/design-patterns/_breadcrumbs.scss +53 -0
  219. data/app/assets/stylesheets/design-patterns/_buttons.scss +145 -0
  220. data/app/assets/stylesheets/design-patterns/_media-player.scss +264 -0
  221. data/app/assets/trigger.sh +24 -0
  222. data/idsk_frontend_toolkit.gemspec +49 -0
  223. data/lib/idsk_frontend_toolkit/engine.rb +4 -0
  224. data/lib/idsk_frontend_toolkit/version.rb +5 -0
  225. data/lib/idsk_frontend_toolkit.rb +4 -0
  226. data/publish.sh +30 -0
  227. metadata +314 -0
@@ -0,0 +1,41 @@
1
+ /* global describe it expect beforeEach afterEach */
2
+
3
+ var $ = window.jQuery
4
+
5
+ describe('shim-links-with-button-role', function () {
6
+ 'use strict'
7
+ var GOVUK = window.GOVUK
8
+
9
+ var $buttonLink
10
+ var keyDownEvent
11
+
12
+ beforeEach(function () {
13
+ $buttonLink = $('<a role="button">Button</a>')
14
+ $buttonLink.on('click', function () {
15
+ $buttonLink.addClass('clicked')
16
+ })
17
+ $(document.body).append($buttonLink)
18
+ keyDownEvent = $.Event('keydown')
19
+ keyDownEvent.target = $buttonLink.get(0)
20
+ GOVUK.shimLinksWithButtonRole.init()
21
+ })
22
+
23
+ afterEach(function () {
24
+ $buttonLink.remove()
25
+ $(document).off('keyup')
26
+ })
27
+
28
+ it('should trigger event on space', function () {
29
+ // Ideally we’d test the page loading functionality but that seems hard to
30
+ // do within a Jasmine context. Settle for checking a bound event trigger.
31
+ keyDownEvent.which = 32 // Space character
32
+ $(document).trigger(keyDownEvent)
33
+ expect($buttonLink.hasClass('clicked')).toBe(true)
34
+ })
35
+
36
+ it('should not trigger event on tab', function () {
37
+ keyDownEvent.which = 9 // Tab character
38
+ $(document).trigger(keyDownEvent)
39
+ expect($buttonLink.hasClass('clicked')).toBe(false)
40
+ })
41
+ })
@@ -0,0 +1,306 @@
1
+ /* global describe it expect beforeEach afterEach jasmine */
2
+
3
+ var $ = window.jQuery
4
+
5
+ describe('show-hide-content', function () {
6
+ 'use strict'
7
+ var GOVUK = window.GOVUK
8
+
9
+ afterEach(function () {
10
+ if (this.showHideContent) {
11
+ this.showHideContent.destroy()
12
+ }
13
+
14
+ this.$content.remove()
15
+ })
16
+
17
+ describe('when the radios are inside a form', function () {
18
+ beforeEach(function () {
19
+ // Sample markup
20
+ this.$content = $(
21
+
22
+ // Radio buttons (yes/no)
23
+ '<form>' +
24
+ '<div class="multiple-choice" data-target="show-hide-radios">' +
25
+ '<input type="radio" name="single" value="yes">' +
26
+ '<label>Yes</label>' +
27
+ '</div>' +
28
+ '<div class="multiple-choice">' +
29
+ '<input type="radio" name="single" value="no">' +
30
+ '<label>No</label>' +
31
+ '</div>' +
32
+ '<div id="show-hide-radios" class="panel js-hidden" />' +
33
+ '</form>' +
34
+
35
+ // Checkboxes (multiple values)
36
+ '<form>' +
37
+ '<div class="multiple-choice" data-target="show-hide-checkboxes">' +
38
+ '<input type="checkbox" name="multiple[option1]">' +
39
+ '<label>Option 1</label>' +
40
+ '</div>' +
41
+ '<div class="multiple-choice">' +
42
+ '<input type="checkbox" name="multiple[option2]">' +
43
+ '<label>Option 2</label>' +
44
+ '</div>' +
45
+ '<div class="multiple-choice">' +
46
+ '<input type="checkbox" name="multiple[option3]">' +
47
+ '<label>Option 3</label>' +
48
+ '</div>' +
49
+ '<div id="show-hide-checkboxes" class="panel js-hidden" />' +
50
+ '</form>'
51
+ )
52
+
53
+ // Find radios/checkboxes
54
+ var $radios = this.$content.find('input[type=radio]')
55
+ var $checkboxes = this.$content.find('input[type=checkbox]')
56
+
57
+ // Two radios
58
+ this.$radio1 = $radios.eq(0)
59
+ this.$radio2 = $radios.eq(1)
60
+
61
+ // Three checkboxes
62
+ this.$checkbox1 = $checkboxes.eq(0)
63
+ this.$checkbox2 = $checkboxes.eq(1)
64
+ this.$checkbox3 = $checkboxes.eq(2)
65
+
66
+ // Add to page
67
+ $(document.body).append(this.$content)
68
+
69
+ // Show/Hide content
70
+ this.$radioShowHide = $('#show-hide-radios')
71
+ this.$checkboxShowHide = $('#show-hide-checkboxes')
72
+
73
+ // Add show/hide content support
74
+ this.showHideContent = new GOVUK.ShowHideContent()
75
+ this.showHideContent.init()
76
+ })
77
+
78
+ describe('and when this.showHideContent = new GOVUK.ShowHideContent() is called', function () {
79
+ it('should add the aria attributes to inputs with show/hide content', function () {
80
+ expect(this.$radio1.attr('aria-expanded')).toBe('false')
81
+ expect(this.$radio1.attr('aria-controls')).toBe('show-hide-radios')
82
+ })
83
+
84
+ it('should add the aria attributes to show/hide content', function () {
85
+ expect(this.$radioShowHide.attr('aria-hidden')).toBe('true')
86
+ expect(this.$radioShowHide.hasClass('js-hidden')).toEqual(true)
87
+ })
88
+
89
+ it('should hide the show/hide content visually', function () {
90
+ expect(this.$radioShowHide.hasClass('js-hidden')).toEqual(true)
91
+ })
92
+
93
+ it('should do nothing if no radios are checked', function () {
94
+ expect(this.$radio1.attr('aria-expanded')).toBe('false')
95
+ expect(this.$radio2.attr('aria-expanded')).toBe(undefined)
96
+ })
97
+
98
+ it('should do nothing if no checkboxes are checked', function () {
99
+ expect(this.$radio1.attr('aria-expanded')).toBe('false')
100
+ expect(this.$radio2.attr('aria-expanded')).toBe(undefined)
101
+ })
102
+
103
+ describe('with non-default markup', function () {
104
+ beforeEach(function () {
105
+ this.showHideContent.destroy()
106
+ })
107
+
108
+ it('should do nothing if a radio without show/hide content is checked', function () {
109
+ this.$radio2.prop('checked', true)
110
+
111
+ // Defaults changed, initialise again
112
+ this.showHideContent = new GOVUK.ShowHideContent().init()
113
+ expect(this.$radio1.attr('aria-expanded')).toBe('false')
114
+ expect(this.$radioShowHide.attr('aria-hidden')).toBe('true')
115
+ expect(this.$radioShowHide.hasClass('js-hidden')).toEqual(true)
116
+ })
117
+
118
+ it('should do nothing if a checkbox without show/hide content is checked', function () {
119
+ this.$checkbox2.prop('checked', true)
120
+
121
+ // Defaults changed, initialise again
122
+ this.showHideContent = new GOVUK.ShowHideContent().init()
123
+ expect(this.$checkbox1.attr('aria-expanded')).toBe('false')
124
+ expect(this.$checkboxShowHide.attr('aria-hidden')).toBe('true')
125
+ expect(this.$checkboxShowHide.hasClass('js-hidden')).toEqual(true)
126
+ })
127
+
128
+ it('should do nothing if checkboxes without show/hide content is checked', function () {
129
+ this.$checkbox2.prop('checked', true)
130
+ this.$checkbox3.prop('checked', true)
131
+
132
+ // Defaults changed, initialise again
133
+ this.showHideContent = new GOVUK.ShowHideContent().init()
134
+ expect(this.$checkbox1.attr('aria-expanded')).toBe('false')
135
+ expect(this.$checkboxShowHide.attr('aria-hidden')).toBe('true')
136
+ expect(this.$checkboxShowHide.hasClass('js-hidden')).toEqual(true)
137
+ })
138
+
139
+ it('should make the show/hide content visible if its radio is checked', function () {
140
+ this.$radio1.prop('checked', true)
141
+
142
+ // Defaults changed, initialise again
143
+ this.showHideContent = new GOVUK.ShowHideContent().init()
144
+ expect(this.$radio1.attr('aria-expanded')).toBe('true')
145
+ expect(this.$radioShowHide.attr('aria-hidden')).toBe('false')
146
+ expect(this.$radioShowHide.hasClass('js-hidden')).toEqual(false)
147
+ })
148
+
149
+ it('should make the show/hide content visible if its checkbox is checked', function () {
150
+ this.$checkbox1.prop('checked', true)
151
+
152
+ // Defaults changed, initialise again
153
+ this.showHideContent = new GOVUK.ShowHideContent().init()
154
+ expect(this.$checkbox1.attr('aria-expanded')).toBe('true')
155
+ expect(this.$checkboxShowHide.attr('aria-hidden')).toBe('false')
156
+ expect(this.$checkboxShowHide.hasClass('js-hidden')).toEqual(false)
157
+ })
158
+ })
159
+
160
+ describe('and a show/hide radio receives a click', function () {
161
+ it('should make the show/hide content visible', function () {
162
+ this.$radio1.click()
163
+ expect(this.$radioShowHide.hasClass('js-hidden')).toEqual(false)
164
+ })
165
+
166
+ it('should add the aria attributes to show/hide content', function () {
167
+ this.$radio1.click()
168
+ expect(this.$radio1.attr('aria-expanded')).toBe('true')
169
+ expect(this.$radioShowHide.attr('aria-hidden')).toBe('false')
170
+ expect(this.$radioShowHide.hasClass('js-hidden')).toEqual(false)
171
+ })
172
+ })
173
+
174
+ describe('and a show/hide checkbox receives a click', function () {
175
+ it('should make the show/hide content visible', function () {
176
+ this.$checkbox1.click()
177
+ expect(this.$checkboxShowHide.hasClass('js-hidden')).toEqual(false)
178
+ })
179
+
180
+ it('should add the aria attributes to show/hide content', function () {
181
+ this.$checkbox1.click()
182
+ expect(this.$checkbox1.attr('aria-expanded')).toBe('true')
183
+ expect(this.$checkboxShowHide.attr('aria-hidden')).toBe('false')
184
+ expect(this.$checkboxShowHide.hasClass('js-hidden')).toEqual(false)
185
+ })
186
+ })
187
+
188
+ describe('and a show/hide radio receives a click, but another group radio is clicked afterwards', function () {
189
+ it('should make the show/hide content hidden', function () {
190
+ this.$radio1.click()
191
+ this.$radio2.click()
192
+ expect(this.$radioShowHide.hasClass('js-hidden')).toEqual(true)
193
+ })
194
+
195
+ it('should add the aria attributes to show/hide content', function () {
196
+ this.$radio1.click()
197
+ this.$radio2.click()
198
+ expect(this.$radio1.attr('aria-expanded')).toBe('false')
199
+ expect(this.$radioShowHide.attr('aria-hidden')).toBe('true')
200
+ })
201
+ })
202
+
203
+ describe('and a show/hide checkbox receives a click, but another checkbox is clicked afterwards', function () {
204
+ it('should keep the show/hide content visible', function () {
205
+ this.$checkbox1.click()
206
+ this.$checkbox2.click()
207
+ expect(this.$checkboxShowHide.hasClass('js-hidden')).toEqual(false)
208
+ })
209
+
210
+ it('should keep the aria attributes to show/hide content', function () {
211
+ this.$checkbox1.click()
212
+ this.$checkbox2.click()
213
+ expect(this.$checkbox1.attr('aria-expanded')).toBe('true')
214
+ expect(this.$checkboxShowHide.attr('aria-hidden')).toBe('false')
215
+ })
216
+ })
217
+ })
218
+
219
+ describe('before this.showHideContent.destroy() is called', function () {
220
+ it('document.body should have show/hide event handlers', function () {
221
+ var events = $._data(document.body, 'events')
222
+ expect(events && events.click).toContain(jasmine.objectContaining({
223
+ namespace: 'ShowHideContent',
224
+ selector: 'input[type="radio"][name="single"]'
225
+ }))
226
+ expect(events && events.click).toContain(jasmine.objectContaining({
227
+ namespace: 'ShowHideContent',
228
+ selector: '[data-target] > input[type="checkbox"]'
229
+ }))
230
+ })
231
+ })
232
+
233
+ describe('and when this.showHideContent.destroy() is called', function () {
234
+ beforeEach(function () {
235
+ this.showHideContent.destroy()
236
+ })
237
+
238
+ it('should have no show/hide event handlers', function () {
239
+ var events = $._data(document.body, 'events')
240
+ expect(events && events.click).not.toContain(jasmine.objectContaining({
241
+ namespace: 'ShowHideContent',
242
+ selector: 'input[type="radio"][name="single"]'
243
+ }))
244
+ expect(events && events.click).not.toContain(jasmine.objectContaining({
245
+ namespace: 'ShowHideContent',
246
+ selector: '[data-target] > input[type="checkbox"]'
247
+ }))
248
+ })
249
+ })
250
+ })
251
+
252
+ describe('when the radios are outside of a form', function () {
253
+ beforeEach(function () {
254
+ // Sample markup
255
+ this.$content = $(
256
+ // Radio buttons (yes/no)
257
+ '<div class="multiple-choice" data-target="show-hide-radios">' +
258
+ '<input type="radio" name="single" value="yes">' +
259
+ '<label>Yes</label>' +
260
+ '</div>' +
261
+ '<div class="multiple-choice">' +
262
+ '<input type="radio" name="single" value="no">' +
263
+ '<label>No</label>' +
264
+ '</div>' +
265
+ '<div id="show-hide-radios" class="panel js-hidden" />'
266
+ )
267
+
268
+ // Find radios/checkboxes
269
+ var $radios = this.$content.find('input[type=radio]')
270
+
271
+ // Two radios
272
+ this.$radio1 = $radios.eq(0)
273
+ this.$radio2 = $radios.eq(1)
274
+
275
+ // Add to page
276
+ $(document.body).append(this.$content)
277
+
278
+ // Show/Hide content
279
+ this.$radioShowHide = $('#show-hide-radios')
280
+
281
+ // Add show/hide content support
282
+ this.showHideContent = new GOVUK.ShowHideContent()
283
+ this.showHideContent.init()
284
+ })
285
+
286
+ it('should make the show/hide content visible if its radio is checked', function () {
287
+ this.$radio1.click()
288
+
289
+ // Defaults changed, initialise again
290
+ this.showHideContent = new GOVUK.ShowHideContent().init()
291
+ expect(this.$radio1.attr('aria-expanded')).toBe('true')
292
+ expect(this.$radioShowHide.attr('aria-hidden')).toBe('false')
293
+ expect(this.$radioShowHide.hasClass('js-hidden')).toEqual(false)
294
+ })
295
+
296
+ it('should do nothing if a radio without show/hide content is checked', function () {
297
+ this.$radio2.click()
298
+
299
+ // Defaults changed, initialise again
300
+ this.showHideContent = new GOVUK.ShowHideContent().init()
301
+ expect(this.$radio1.attr('aria-expanded')).toBe('false')
302
+ expect(this.$radioShowHide.attr('aria-hidden')).toBe('true')
303
+ expect(this.$radioShowHide.hasClass('js-hidden')).toEqual(true)
304
+ })
305
+ })
306
+ })
@@ -0,0 +1,137 @@
1
+ /* global describe it expect beforeEach afterEach */
2
+
3
+ var $ = window.jQuery
4
+
5
+ describe('stick-at-top-when-scrolling', function () {
6
+ 'use strict'
7
+ var GOVUK = window.GOVUK
8
+
9
+ var $stickyElement
10
+ var $stickyWrapper
11
+
12
+ beforeEach(function () {
13
+ $stickyElement = $('<div class="stick-at-top-when-scrolling"></div>')
14
+ $stickyWrapper = $('<div>').append($stickyElement)
15
+
16
+ $('body').append($stickyWrapper)
17
+ })
18
+
19
+ afterEach(function () {
20
+ $stickyWrapper.remove()
21
+ })
22
+
23
+ describe('when stick is called', function () {
24
+ it('should add fixed class on stick', function () {
25
+ expect(!$stickyElement.hasClass('content-fixed')).toBe(true)
26
+ GOVUK.stickAtTopWhenScrolling.stick($stickyElement)
27
+ expect($stickyElement.hasClass('content-fixed')).toBe(true)
28
+ })
29
+
30
+ it('should insert shim when sticking the element', function () {
31
+ expect($('.shim').length).toBe(0)
32
+ GOVUK.stickAtTopWhenScrolling.stick($stickyElement)
33
+ expect($('.shim').length).toBe(1)
34
+ })
35
+
36
+ it('should insert shim with minimum height', function () {
37
+ GOVUK.stickAtTopWhenScrolling.stick($stickyElement)
38
+ expect($('.shim').height()).toBe(1)
39
+ })
40
+ })
41
+
42
+ describe('when release is called', function () {
43
+ it('should remove fixed class', function () {
44
+ $stickyElement.addClass('content-fixed')
45
+ GOVUK.stickAtTopWhenScrolling.release($stickyElement)
46
+ expect($stickyElement.hasClass('content-fixed')).toBe(false)
47
+ })
48
+
49
+ it('should remove the shim', function () {
50
+ $stickyElement = $('<div class="stick-at-top-when-scrolling content-fixed"></div>')
51
+ GOVUK.stickAtTopWhenScrolling.release($stickyElement)
52
+ expect($('.shim').length).toBe(0)
53
+ })
54
+ })
55
+
56
+ describe('for larger screens (>768px)', function () {
57
+ beforeEach(function () {
58
+ GOVUK.stickAtTopWhenScrolling.getWindowPositions = function () {
59
+ return {
60
+ scrollTop: 300
61
+ }
62
+ }
63
+ GOVUK.stickAtTopWhenScrolling.getElementOffset = function () {
64
+ return {
65
+ top: 300
66
+ }
67
+ }
68
+ GOVUK.stickAtTopWhenScrolling.getWindowDimensions = function () {
69
+ return {
70
+ height: 768,
71
+ width: 769
72
+ }
73
+ }
74
+ GOVUK.stickAtTopWhenScrolling.$els = $stickyElement
75
+ GOVUK.stickAtTopWhenScrolling._hasScrolled = true
76
+ GOVUK.stickAtTopWhenScrolling.checkScroll()
77
+ })
78
+
79
+ it('should stick, if the scroll position is past the element position', function () {
80
+ expect($stickyElement.hasClass('content-fixed')).toBe(true)
81
+ })
82
+
83
+ it('should check the width of the parent, and make the width of the element and the shim the same on resize', function () {
84
+ var $stickyResizeElement = $('<div class="stick-at-top-when-scrolling js-sticky-resize"></div>')
85
+ var $stickyResizeWrapper = $('<div class="column-third" style="width:300px;">').append($stickyResizeElement)
86
+ $('body').append($stickyResizeWrapper)
87
+
88
+ GOVUK.stickAtTopWhenScrolling.$els = $stickyResizeElement
89
+ GOVUK.stickAtTopWhenScrolling._hasResized = true
90
+ GOVUK.stickAtTopWhenScrolling.checkResize()
91
+
92
+ var stickyElementParentWidth = $stickyResizeElement.parent('div').width()
93
+ expect(stickyElementParentWidth).toBe(300)
94
+
95
+ var stickyElementWidth = $stickyResizeElement.width()
96
+ expect(stickyElementWidth).toBe(300)
97
+
98
+ var stickElementShimWidth = $('.shim').width()
99
+ expect(stickElementShimWidth).toBe(300)
100
+ })
101
+
102
+ it('should unstick, if the scroll position is less than the point at which scrolling started', function () {
103
+ GOVUK.stickAtTopWhenScrolling.getWindowPositions = function () {
104
+ return {
105
+ scrollTop: 0
106
+ }
107
+ }
108
+ GOVUK.stickAtTopWhenScrolling.$els = $stickyElement
109
+ GOVUK.stickAtTopWhenScrolling._hasScrolled = true
110
+ GOVUK.stickAtTopWhenScrolling.checkScroll()
111
+ expect($stickyElement.hasClass('content-fixed')).toBe(false)
112
+ })
113
+ })
114
+
115
+ describe('for smaller screens (<=768px)', function () {
116
+ beforeEach(function () {
117
+ GOVUK.stickAtTopWhenScrolling.getWindowDimensions = function () {
118
+ return {
119
+ height: 768,
120
+ width: 767
121
+ }
122
+ }
123
+ GOVUK.stickAtTopWhenScrolling.getElementOffset = function () {
124
+ return {
125
+ top: 300
126
+ }
127
+ }
128
+ GOVUK.stickAtTopWhenScrolling.$els = $stickyElement
129
+ GOVUK.stickAtTopWhenScrolling._hasScrolled = true
130
+ GOVUK.stickAtTopWhenScrolling.checkScroll()
131
+ })
132
+
133
+ it('should unstick the element', function () {
134
+ expect($stickyElement.hasClass('content-fixed')).toBe(false)
135
+ })
136
+ })
137
+ })
File without changes
@@ -0,0 +1,2 @@
1
+ @import "colours/palette";
2
+ @import "colours/organisation";
@@ -0,0 +1,81 @@
1
+ // Media query helpers. These make producing IE layouts
2
+ // super easy.
3
+
4
+ // The base css you write should be for mobile. You can
5
+ // then add desktop styles on top.
6
+ //
7
+ // Usage:
8
+ //
9
+ // div.columns {
10
+ // border: 1px solid;
11
+ //
12
+ // @include media(desktop){
13
+ // width: 30%;
14
+ // float: left;
15
+ // }
16
+ // @include ie-lte(8) {
17
+ // something to fix visual bugs in old IE
18
+ // }
19
+ // @include ie(6) {
20
+ // padding: 0;
21
+ // }
22
+ // }
23
+
24
+
25
+ $is-ie: false !default;
26
+ $mobile-ie6: true !default;
27
+
28
+ $tablet-breakpoint: 641px !default;
29
+ $desktop-breakpoint: 769px !default;
30
+
31
+ @mixin media($size: false, $max-width: false, $min-width: false, $ignore-for-ie: false) {
32
+ @if $is-ie and ($ignore-for-ie == false) {
33
+ @if $size != mobile {
34
+ @if ($ie-version == 6 and $mobile-ie6 == false) or $ie-version > 6 {
35
+ @content;
36
+ }
37
+ }
38
+ } @else {
39
+ @if $size == desktop {
40
+ @media (min-width: $desktop-breakpoint){
41
+ @content;
42
+ }
43
+ } @else if $size == tablet {
44
+ @media (min-width: $tablet-breakpoint){
45
+ @content;
46
+ }
47
+ } @else if $size == mobile {
48
+ @media (max-width: $tablet-breakpoint - 1px){
49
+ @content;
50
+ }
51
+ } @else if $max-width != false {
52
+ @media (max-width: $max-width){
53
+ @content;
54
+ }
55
+ } @else if $min-width != false {
56
+ @media (min-width: $min-width){
57
+ @content;
58
+ }
59
+ } @else {
60
+ @media (min-width: $size){
61
+ @content
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ @mixin ie-lte($version) {
68
+ @if $is-ie {
69
+ @if $ie-version <= $version {
70
+ @content;
71
+ }
72
+ }
73
+ }
74
+
75
+ @mixin ie($version) {
76
+ @if $is-ie {
77
+ @if $ie-version == $version {
78
+ @content;
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,90 @@
1
+ // CSS 3 mixins
2
+
3
+ // This file includes mixins for CSS properties that require vendor prefixes.
4
+
5
+ // Please add more mixins here as you need them, rather than adding them to
6
+ // your application - this lets us manage them in one place.
7
+
8
+ // You can use the @warn directive to deprecate a mixin where the property
9
+ // no longer needs prefixes.
10
+
11
+ // This style of indentation is preferred as it is easier to scan
12
+ // Allow more than two spaces per indentation level and don't require a space after a colon
13
+ // scss-lint:disable Indentation SpaceAfterPropertyColon
14
+
15
+ @mixin border-radius($radius) {
16
+ -webkit-border-radius: $radius; // Chrome 4.0, Safari 3.1 to 4.0, Mobile Safari 3.2, Android Browser 2.1
17
+ -moz-border-radius: $radius; // Firefox 2.0 to 3.6
18
+ border-radius: $radius;
19
+ }
20
+
21
+ @mixin box-shadow($shadow) {
22
+ -webkit-box-shadow: $shadow; // Chrome 4.0 to 9.0, Safari 3.1 to 5.0, Mobile Safari 3.2 to 4.3, Android Browser 2.1 to 3.0
23
+ -moz-box-shadow: $shadow; // Firefox 3.5 to 3.6
24
+ box-shadow: $shadow;
25
+ }
26
+
27
+ @mixin scale($x, $y, $transform-origin: 50% 50% 0) {
28
+ // $x and $y should be numeric values without units
29
+ -webkit-transform: scale($x, $y); // Still in use now, started at: Chrome 4.0, Safari 3.1, Mobile Safari 3.2, Android 2.1
30
+ -moz-transform: scale($x, $y); // Firefox 3.5 to 15.0
31
+ -ms-transform: scale($x, $y); // IE9 only
32
+ transform: scale($x, $y);
33
+
34
+ -webkit-transform-origin: $transform-origin; // Chrome, Safari 3.1
35
+ -moz-transform-origin: $transform-origin; // Firefox 10 to 15.0
36
+ -ms-transform-origin: $transform-origin; // IE9
37
+ transform-origin: $transform-origin;
38
+ }
39
+
40
+ @mixin translate($x, $y) {
41
+ -webkit-transform: translate($x, $y); // Still in use now, started at: Chrome 4.0, Safari 3.1, Mobile Safari 3.2, Android 2.1
42
+ -moz-transform: translate($x, $y); // Firefox 3.5 to 15.0
43
+ -ms-transform: translate($x, $y); // IE9 only
44
+ -o-transform: translate($x, $y); // Opera 10.5 to 12.0
45
+ transform: translate($x, $y);
46
+ }
47
+
48
+ @mixin gradient($from, $to) {
49
+ // Creates a vertical gradient where $from is the colour at the top of the element
50
+ // and $to is the colour at the bottom. The top colour is used as a background-color
51
+ // for browsers that don't support gradients.
52
+ background-color: $from;
53
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from($from), to($to)); // Safari 4.0 to 5.1, Chrome 1.0 to 10.0, old deprecated syntax
54
+ background-image: -webkit-linear-gradient($from, $to); // Chrome 10.0 to 25.0, Safari 5.1 to 6.0, Mobile Safari 5.0 to 6.1, Android Browser 4.0 to 4.3
55
+ background-image: -moz-linear-gradient($from, $to); // Firefox 3.6 to 15.0
56
+ background-image: -o-linear-gradient($from, $to); // Opera 11.1 to 12.0
57
+ background-image: linear-gradient($from, $to);
58
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#{$from}', endColorstr='#{$to}',GradientType=0 ); // IE6 to IE9
59
+ }
60
+
61
+ @mixin transition($property, $duration, $function, $delay: 0s) {
62
+ -webkit-transition: ($property $duration $function $delay); // Chrome 4.0 to 25.0, Safari 3.1 to 6.0, Mobile Safari 3.2 to 6.1, Android Browser 2.1 to 4.3
63
+ -moz-transition: ($property $duration $function $delay); // Firefox 4.0 to 15.0
64
+ -o-transition: ($property $duration $function $delay); // Opera 10.5 to 12.0
65
+ transition: ($property $duration $function $delay);
66
+ }
67
+
68
+ @mixin box-sizing($type) {
69
+ // http://www.w3.org/TR/css3-ui/#box-sizing
70
+ // $type can be one of: content-box | padding-box | border-box | inherit
71
+ -webkit-box-sizing: $type; // Chrome 4.0 to 9.0, Safari 3.1 to 5.0, Mobile Safari 3.2 to 4.3, Android Browser 2.1 to 3.0
72
+ -moz-box-sizing: $type; // Firefox 2.0 to 28.0, Firefox for Android 26.0 onwards
73
+ box-sizing: $type;
74
+ }
75
+
76
+ @mixin appearance($appearance) {
77
+ -webkit-appearance: $appearance;
78
+ -moz-appearance: $appearance;
79
+ }
80
+
81
+ @mixin calc($property, $calc) {
82
+ #{$property}: -webkit-calc(#{$calc}); // Chrome 19.0 to 25.0, Safari 6.0, Mobile Safari 6.0 to 6.1
83
+ #{$property}: calc(#{$calc});
84
+ }
85
+
86
+ @mixin opacity($trans) {
87
+ zoom: 1;
88
+ filter: unquote('alpha(opacity=' + ($trans * 100) + ')'); // IE6 to IE8
89
+ opacity: $trans;
90
+ }
@@ -0,0 +1,10 @@
1
+ @mixin device-pixel-ratio($ratio: 2) {
2
+ @media only screen and (-webkit-min-device-pixel-ratio: $ratio),
3
+ only screen and (min--moz-device-pixel-ratio: $ratio),
4
+ only screen and ( -o-min-device-pixel-ratio: #{($ratio*10)}/10),
5
+ only screen and ( min-device-pixel-ratio: $ratio),
6
+ only screen and ( min-resolution: #{($ratio*96)}dpi),
7
+ only screen and ( min-resolution: #{$ratio}dppx) {
8
+ @content;
9
+ }
10
+ }