govuk_elements_rails 0.1.0

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 (36) hide show
  1. checksums.yaml +7 -0
  2. data/LICENCE +20 -0
  3. data/README.md +54 -0
  4. data/lib/govuk_elements_rails.rb +4 -0
  5. data/lib/govuk_elements_rails/engine.rb +4 -0
  6. data/lib/govuk_elements_rails/version.rb +5 -0
  7. data/vendor/assets/javascripts/bind.js +40 -0
  8. data/vendor/assets/javascripts/details.polyfill.js +158 -0
  9. data/vendor/assets/javascripts/selection-buttons.js +137 -0
  10. data/vendor/assets/stylesheets/elements-page-ie6.scss +5 -0
  11. data/vendor/assets/stylesheets/elements-page-ie7.scss +4 -0
  12. data/vendor/assets/stylesheets/elements-page-ie8.scss +4 -0
  13. data/vendor/assets/stylesheets/elements-page.scss +333 -0
  14. data/vendor/assets/stylesheets/elements/_buttons.scss +44 -0
  15. data/vendor/assets/stylesheets/elements/_details.scss +39 -0
  16. data/vendor/assets/stylesheets/elements/_elements-typography.scss +179 -0
  17. data/vendor/assets/stylesheets/elements/_forms.scss +166 -0
  18. data/vendor/assets/stylesheets/elements/_helpers.scss +46 -0
  19. data/vendor/assets/stylesheets/elements/_icons.scss +224 -0
  20. data/vendor/assets/stylesheets/elements/_layout.scss +67 -0
  21. data/vendor/assets/stylesheets/elements/_lists.scss +32 -0
  22. data/vendor/assets/stylesheets/elements/_panels.scss +29 -0
  23. data/vendor/assets/stylesheets/elements/_reset.scss +33 -0
  24. data/vendor/assets/stylesheets/elements/_tables.scss +26 -0
  25. data/vendor/assets/stylesheets/elements/forms/_form-block-labels.scss +67 -0
  26. data/vendor/assets/stylesheets/elements/forms/_form-date.scss +46 -0
  27. data/vendor/assets/stylesheets/elements/forms/_form-validation.scss +68 -0
  28. data/vendor/assets/stylesheets/main-ie6.scss +5 -0
  29. data/vendor/assets/stylesheets/main-ie7.scss +4 -0
  30. data/vendor/assets/stylesheets/main-ie8.scss +4 -0
  31. data/vendor/assets/stylesheets/main.scss +36 -0
  32. data/vendor/assets/stylesheets/prism.scss +144 -0
  33. data/vendor/assets/stylesheets/service-design-manual/helpers/_breadcrumbs.scss +81 -0
  34. data/vendor/assets/stylesheets/service-design-manual/helpers/_page-header.scss +28 -0
  35. data/vendor/assets/stylesheets/service-design-manual/styleguide/_colours.scss +3 -0
  36. metadata +122 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0e4507b35a48b80125447d05206cad3cfe6f39f0
4
+ data.tar.gz: 98b68bd115ef63a93316504d741f4130c486f493
5
+ SHA512:
6
+ metadata.gz: 10ecd7e53790c3d74e3853f4d40b0f83d786a8d6af4e222d7c0ebd4c27c95ffad1780d0a4615a138aa2b2f58a649c847f15dca8aa95014c30e234c2574e27429
7
+ data.tar.gz: ff14ffac1525b39272214c70e6e6c408377de2365fbff171f6386bb3a221169dd3d561fe88f41aae4f7fd51324133776e199a5805a9ab3928052c687f916b27a
data/LICENCE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 HM Government
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # GOV.UK Elements Rails gem
2
+
3
+ A gem wrapper around [govuk_elements](http://github.com/alphagov/govuk_elements)
4
+ that pulls stylesheet and javascript files into a Rails app.
5
+
6
+ ## Installing
7
+
8
+ Just include `govuk_elements_rails` in your `Gemfile`. It
9
+ automatically attaches itself to your asset path so the static/SCSS
10
+ files will be available to the asset pipeline.
11
+
12
+ ### Development
13
+
14
+ If you are installing from git, ensure you enable submodules like so:
15
+
16
+ gem 'govuk_elements_rails', :git => "https://github.com/ministryofjustice/govuk_elements_rails.git", :submodules => true
17
+
18
+ ## Usage
19
+
20
+ At the top of a Sass file in your Rails project you should use an `@import` rule
21
+ to include the file for the mixins you require. For example here are all the
22
+ imports possible:
23
+
24
+ @import 'elements/helpers';
25
+ @import 'elements/reset';
26
+ @import 'elements/elements-typography';
27
+ @import 'elements/layout';
28
+
29
+ @import 'elements/forms';
30
+ @import 'elements/tables';
31
+ @import 'elements/buttons';
32
+ @import 'elements/details';
33
+ @import 'elements/lists';
34
+ @import 'elements/panels';
35
+ @import "elements/icons";
36
+
37
+ In the `app/assets/javascripts/application.js` file in your Rails project use
38
+ `require` rule to include the files for the javascript enhancements you require.
39
+ For example here are all the requires possible at present:
40
+
41
+ // from govuk_elements gem
42
+ //= require details.polyfill
43
+ //= require bind
44
+ //= require selection-buttons
45
+
46
+ ## Alternate ways to reuse GOV.UK Elements
47
+
48
+ There are other alternate ways to include GOV.UK Elements files in a Rails
49
+ project, for example via `Bower`. Feel free to use an alternate approach if it
50
+ is more appropriate for your team.
51
+
52
+ ## Feedback
53
+
54
+ Please provide feedback via [GitHub issues](https://github.com/ministryofjustice/govuk_elements_rails/issues).
@@ -0,0 +1,4 @@
1
+ module GovUKElementsRails
2
+ require 'govuk_elements_rails/engine'
3
+ autoload 'Version', 'govuk_elements_rails/version'
4
+ end
@@ -0,0 +1,4 @@
1
+ module GovUKElementsRails
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ module GovUKElementsRails
2
+ def self.elements_version
3
+ '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,40 @@
1
+ // Function.prototype.bind
2
+ //
3
+ // A polyfill for Function.prototype.bind. Which lets you bind a defined
4
+ // value to the `this` keyword in a function call.
5
+ //
6
+ // Bind is natively supported in:
7
+ // IE9+
8
+ // Chrome 7+
9
+ // Firefox 4+
10
+ // Safari 5.1.4+
11
+ // iOS 6+
12
+ // Android Browser 4+
13
+ // Chrome for Android 0.16+
14
+ //
15
+ // Originally from:
16
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
17
+ if (!Function.prototype.bind) {
18
+ Function.prototype.bind = function (oThis) {
19
+ if (typeof this !== "function") {
20
+ // closest thing possible to the ECMAScript 5
21
+ // internal IsCallable function
22
+ throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
23
+ }
24
+
25
+ var aArgs = Array.prototype.slice.call(arguments, 1),
26
+ fToBind = this,
27
+ fNOP = function () {},
28
+ fBound = function () {
29
+ return fToBind.apply(this instanceof fNOP && oThis
30
+ ? this
31
+ : oThis,
32
+ aArgs.concat(Array.prototype.slice.call(arguments)));
33
+ };
34
+
35
+ fNOP.prototype = this.prototype;
36
+ fBound.prototype = new fNOP();
37
+
38
+ return fBound;
39
+ };
40
+ }
@@ -0,0 +1,158 @@
1
+ // <details> polyfill
2
+ // http://caniuse.com/#feat=details
3
+
4
+ // FF Support for HTML5's <details> and <summary>
5
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=591737
6
+
7
+ // http://www.sitepoint.com/fixing-the-details-element/
8
+
9
+ (function () {
10
+
11
+ // Add event construct for modern browsers or IE
12
+ // which fires the callback with a pre-converted target reference
13
+ function addEvent(node, type, callback) {
14
+ if (node.addEventListener) {
15
+ node.addEventListener(type, function (e) {
16
+ callback(e, e.target);
17
+ }, false);
18
+ } else if (node.attachEvent) {
19
+ node.attachEvent('on' + type, function (e) {
20
+ callback(e, e.srcElement);
21
+ });
22
+ }
23
+ }
24
+
25
+ // Handle cross-modal click events
26
+ function addClickEvent(node, callback) {
27
+ var keydown = false;
28
+ addEvent(node, 'keydown', function () {
29
+ keydown = true;
30
+ });
31
+ addEvent(node, 'keyup', function (e, target) {
32
+ keydown = false;
33
+ if (e.keyCode === 13) { callback(e, target); }
34
+ });
35
+ addEvent(node, 'click', function (e, target) {
36
+ if (!keydown) { callback(e, target); }
37
+ });
38
+ }
39
+
40
+ // Get the nearest ancestor element of a node that matches a given tag name
41
+ function getAncestor(node, match) {
42
+ do {
43
+ if (!node || node.nodeName.toLowerCase() === match) {
44
+ break;
45
+ }
46
+ } while (node = node.parentNode);
47
+
48
+ return node;
49
+ }
50
+
51
+ // Create a started flag so we can prevent the initialisation
52
+ // function firing from both DOMContentLoaded and window.onload
53
+ var started = false;
54
+
55
+ // Initialisation function
56
+ function addDetailsPolyfill(list) {
57
+
58
+ // If this has already happened, just return
59
+ // else set the flag so it doesn't happen again
60
+ if (started) {
61
+ return;
62
+ }
63
+ started = true;
64
+
65
+ // Get the collection of details elements, but if that's empty
66
+ // then we don't need to bother with the rest of the scripting
67
+ if ((list = document.getElementsByTagName('details')).length === 0) {
68
+ return;
69
+ }
70
+
71
+ // else iterate through them to apply their initial state
72
+ var n = list.length, i = 0;
73
+ for (n; i < n; i++) {
74
+ var details = list[i];
75
+
76
+ // Detect native implementations
77
+ details.__native = typeof(details.open) == 'boolean';
78
+
79
+ // Save shortcuts to the inner summary and content elements
80
+ details.__summary = details.getElementsByTagName('summary').item(0);
81
+ details.__content = details.getElementsByTagName('div').item(0);
82
+
83
+ // If the content doesn't have an ID, assign it one now
84
+ // which we'll need for the summary's aria-controls assignment
85
+ if (!details.__content.id) {
86
+ details.__content.id = 'details-content-' + i;
87
+ }
88
+
89
+ // Add role=button to summary
90
+ details.__summary.setAttribute('role', 'button');
91
+
92
+ // Add aria-controls
93
+ details.__summary.setAttribute('aria-controls', details.__content.id);
94
+
95
+ // Set tabindex so the summary is keyboard accessible
96
+ details.__summary.setAttribute('tabindex', '0');
97
+
98
+ // Detect initial open/closed state
99
+ var detailsAttr = details.hasAttribute('open');
100
+ if (typeof detailsAttr !== 'undefined' && detailsAttr !== false) {
101
+ details.__summary.setAttribute('aria-expanded', 'true');
102
+ details.__content.setAttribute('aria-hidden', 'false');
103
+ } else {
104
+ details.__summary.setAttribute('aria-expanded', 'false');
105
+ details.__content.setAttribute('aria-hidden', 'true');
106
+ details.__content.style.display = 'none';
107
+ }
108
+
109
+ // Create a circular reference from the summary back to its
110
+ // parent details element, for convenience in the click handler
111
+ details.__summary.__details = details;
112
+
113
+ // If this is not a native implementation, create an arrow
114
+ // inside the summary, saving its reference as a summary property
115
+ if (!details.__native) {
116
+ var twisty = document.createElement('i');
117
+ twisty.className = 'arrow arrow-closed';
118
+ twisty.appendChild(document.createTextNode('\u25ba'));
119
+ details.__summary.__twisty = details.__summary.insertBefore(twisty, details.__summary.firstChild);
120
+ }
121
+ }
122
+
123
+ // Define a statechange function that updates aria-expanded and style.display
124
+ // Also update the arrow position
125
+ function statechange(summary) {
126
+
127
+ // Update aria-expanded attribute on click
128
+ var expanded = summary.__details.__summary.getAttribute('aria-expanded') == 'true';
129
+ var hidden = summary.__details.__content.getAttribute('aria-hidden') == 'true';
130
+
131
+ summary.__details.__summary.setAttribute('aria-expanded', (expanded ? 'false' : 'true'));
132
+ summary.__details.__content.setAttribute('aria-hidden', (hidden ? 'false' : 'true'));
133
+ summary.__details.__content.style.display = (expanded ? 'none' : 'block');
134
+
135
+ if (summary.__twisty) {
136
+ summary.__twisty.firstChild.nodeValue = (expanded ? '\u25ba' : '\u25bc');
137
+ summary.__twisty.setAttribute('class', (expanded ? 'arrow arrow-closed' : 'arrow arrow-open'));
138
+ }
139
+
140
+ return true;
141
+ }
142
+
143
+ // Bind a click event to handle summary elements
144
+ addClickEvent(document, function(e, summary) {
145
+ if (!(summary = getAncestor(summary, 'summary'))) {
146
+ return true;
147
+ }
148
+ return statechange(summary);
149
+ });
150
+ }
151
+
152
+ // Bind two load events for modern and older browsers
153
+ // If the first one fires it will set a flag to block the second one
154
+ // but if it's not supported then the second one will fire
155
+ addEvent(document, 'DOMContentLoaded', addDetailsPolyfill);
156
+ addEvent(window, 'load', addDetailsPolyfill);
157
+
158
+ })();
@@ -0,0 +1,137 @@
1
+ (function () {
2
+ "use strict"
3
+ var root = this,
4
+ $ = root.jQuery;
5
+
6
+ if (typeof GOVUK === 'undefined') { root.GOVUK = {}; }
7
+
8
+ var BaseButtons = function ($elms, opts) {
9
+ this.$elms = $elms;
10
+ this.selectedClass = 'selected';
11
+ this.focusedClass = 'focused';
12
+ if (opts !== undefined) {
13
+ $.each(opts, function (optionName, optionObj) {
14
+ this[optionName] = optionObj;
15
+ }.bind(this));
16
+ }
17
+ this.setEventNames();
18
+ this.getSelections();
19
+ this.bindEvents();
20
+ };
21
+ BaseButtons.prototype.setEventNames = function () {
22
+ this.selectionEvents = 'click';
23
+ this.focusEvents = 'focus blur';
24
+ };
25
+ BaseButtons.prototype.markFocused = function ($elm, state) {
26
+ var elmId = $elm.attr('id');
27
+
28
+ if (state === 'focused') {
29
+ $elm.parent('label').addClass(this.focusedClass);
30
+ } else {
31
+ $elm.parent('label').removeClass(this.focusedClass);
32
+ }
33
+ };
34
+ BaseButtons.prototype.bindEvents = function () {
35
+ var selectionEventHandler = this.markSelected.bind(this),
36
+ focusEventHandler = this.markFocused.bind(this);
37
+
38
+ this.$elms
39
+ .on(this.selectionEvents, function (e) {
40
+ selectionEventHandler($(e.target));
41
+ })
42
+ .on(this.focusEvents, function (e) {
43
+ var state = (e.type === 'focus') ? 'focused' : 'blurred';
44
+
45
+ focusEventHandler($(e.target), state);
46
+ });
47
+ };
48
+
49
+ var RadioButtons = function ($elms, opts) {
50
+ BaseButtons.apply(this, arguments);
51
+ };
52
+ RadioButtons.prototype.setEventNames = function () {
53
+ // some browsers fire the 'click' when the selected radio changes by keyboard
54
+ this.selectionEvents = 'click change';
55
+ this.focusEvents = 'focus blur';
56
+ };
57
+ RadioButtons.prototype.getSelections = function () {
58
+ var selectionEventHandler = this.markSelected.bind(this);
59
+
60
+ this.selections = {};
61
+ $.each(this.$elms, function (index, elm) {
62
+ var $elm = $(elm),
63
+ radioName = $elm.attr('name');
64
+
65
+ if (typeof this.selections[radioName] === 'undefined') {
66
+ this.selections[radioName] = false;
67
+ }
68
+ if ($elm.is(':checked')) {
69
+ selectionEventHandler($elm);
70
+ }
71
+ }.bind(this));
72
+ };
73
+ RadioButtons.prototype.bindEvents = function () {
74
+ BaseButtons.prototype.bindEvents.call(this);
75
+ };
76
+ RadioButtons.prototype.markSelected = function ($elm) {
77
+ var radioName = $elm.attr('name'),
78
+ $previousSelection = this.selections[radioName];
79
+
80
+ if ($previousSelection) {
81
+ $previousSelection.parent('label').removeClass(this.selectedClass);
82
+ }
83
+ $elm.parent('label').addClass(this.selectedClass);
84
+ this.selections[radioName] = $elm;
85
+ };
86
+ RadioButtons.prototype.markFocused = function ($elm) {
87
+ BaseButtons.prototype.markFocused.apply(this, arguments);
88
+ };
89
+
90
+ var CheckboxButtons = function ($elms, opts) {
91
+ BaseButtons.apply(this, arguments);
92
+ };
93
+ CheckboxButtons.prototype.setEventNames = function () {
94
+ BaseButtons.prototype.setEventNames.call(this);
95
+ };
96
+ CheckboxButtons.prototype.getSelections = function () {
97
+ var selectionEventHandler = this.markSelected.bind(this);
98
+
99
+ this.$elms.each(function (idx, elm) {
100
+ var $elm = $(elm);
101
+
102
+ if ($elm.is(':checked')) {
103
+ selectionEventHandler($elm);
104
+ }
105
+ });
106
+ };
107
+ CheckboxButtons.prototype.bindEvents = function () {
108
+ BaseButtons.prototype.bindEvents.call(this);
109
+ };
110
+ CheckboxButtons.prototype.markSelected = function ($elm) {
111
+ if ($elm.is(':checked')) {
112
+ $elm.parent('label').addClass(this.selectedClass);
113
+ } else {
114
+ $elm.parent('label').removeClass(this.selectedClass);
115
+ }
116
+ };
117
+ CheckboxButtons.prototype.markFocused = function ($elm) {
118
+ BaseButtons.prototype.markFocused.apply(this, arguments);
119
+ };
120
+
121
+ root.GOVUK.RadioButtons = RadioButtons;
122
+ root.GOVUK.CheckboxButtons = CheckboxButtons;
123
+
124
+ var selectionButtons = function ($elms, opts) {
125
+ var $radios = $elms.filter('[type=radio]'),
126
+ $checkboxes = $elms.filter('[type=checkbox]');
127
+
128
+ if ($radios) {
129
+ new GOVUK.RadioButtons($radios, opts);
130
+ }
131
+ if ($checkboxes) {
132
+ new GOVUK.CheckboxButtons($checkboxes, opts);
133
+ }
134
+ };
135
+
136
+ root.GOVUK.selectionButtons = selectionButtons;
137
+ }).call(this);
@@ -0,0 +1,5 @@
1
+ $is-ie: true;
2
+ $ie-version: 6;
3
+ $mobile-ie6: false;
4
+
5
+ @import "elements-page";