idsk_frontend_toolkit 7.4.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ }