govuk_elements_rails 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +13 -7
- data/app/builders/labelling_form_builder.rb +316 -0
- data/lib/govuk_elements_rails/version.rb +1 -1
- data/vendor/assets/javascripts/application.js +134 -0
- data/vendor/assets/javascripts/details.polyfill.js +61 -15
- data/vendor/assets/javascripts/selection-buttons.js +72 -98
- data/vendor/assets/stylesheets/elements-page.scss +48 -3
- data/vendor/assets/stylesheets/elements/_buttons.scss +6 -0
- data/vendor/assets/stylesheets/elements/_details.scss +1 -0
- data/vendor/assets/stylesheets/elements/_forms.scss +6 -2
- data/vendor/assets/stylesheets/elements/_layout.scss +3 -3
- data/vendor/assets/stylesheets/elements/_lists.scss +5 -2
- data/vendor/assets/stylesheets/elements/_tables.scss +12 -1
- data/vendor/assets/stylesheets/elements/forms/_form-block-labels.scss +1 -1
- data/vendor/assets/stylesheets/elements/forms/_form-date.scss +27 -34
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85648682a9e22e34cd2e42af89725178d104b997
|
4
|
+
data.tar.gz: 827a92dcc7d95e073db4e2590bbe28ffbbb4ca22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17519e48bc499d28e907ac48025bb631b06581e87791f3086713ecd9208b69439d9cf8dd4f8a3d390e93e376a465df5faa3c2c8ac8225b0f6ac570ffab48eb87
|
7
|
+
data.tar.gz: e7c7b1fb30e9f189121ff0ea168c694237b3e8354ec007f3c55ed0f3923b2398908666ed73111657095f8a7ca321597c5a297e42278ccd8a6c29997ca8028d5c
|
data/README.md
CHANGED
@@ -15,6 +15,19 @@ If you are installing from git, ensure you enable submodules like so:
|
|
15
15
|
|
16
16
|
gem 'govuk_elements_rails', :git => "https://github.com/ministryofjustice/govuk_elements_rails.git", :submodules => true
|
17
17
|
|
18
|
+
If you are working on the gem itself, clone and download submodules like this:
|
19
|
+
|
20
|
+
git clone https://github.com/ministryofjustice/govuk_elements_rails.git
|
21
|
+
cd govuk_elements_rails
|
22
|
+
git submodule init
|
23
|
+
git submodule update
|
24
|
+
|
25
|
+
To add a javascript file to gem, create new symlink to govuk_elements file like this:
|
26
|
+
|
27
|
+
cd vendor/assets/javascripts/
|
28
|
+
ln -s ../../../govuk_elements/public/javascripts/application.js
|
29
|
+
ls -l
|
30
|
+
|
18
31
|
## Usage
|
19
32
|
|
20
33
|
At the top of a Sass file in your Rails project you should use an `@import` rule
|
@@ -43,13 +56,6 @@ For example here are all the requires possible at present:
|
|
43
56
|
//= require bind
|
44
57
|
//= require selection-buttons
|
45
58
|
|
46
|
-
## Usage of GovukElementsFormBuilder
|
47
|
-
|
48
|
-
To replace the default form builder with a version that generates GOV.UK Elements classed markup, set the following in
|
49
|
-
config/application.rb:
|
50
|
-
|
51
|
-
config.use_govuk_elements_form_builder = true
|
52
|
-
|
53
59
|
## Alternate ways to reuse GOV.UK Elements
|
54
60
|
|
55
61
|
There are other alternate ways to include GOV.UK Elements files in a Rails
|
@@ -0,0 +1,316 @@
|
|
1
|
+
|
2
|
+
class LabellingFormBuilder < ActionView::Helpers::FormBuilder
|
3
|
+
|
4
|
+
include ActionView::Helpers::CaptureHelper
|
5
|
+
include ActionView::Helpers::TagHelper
|
6
|
+
include ActionView::Context
|
7
|
+
|
8
|
+
def text_field_row(attribute, options={})
|
9
|
+
row_input attribute, :text_field, options
|
10
|
+
end
|
11
|
+
|
12
|
+
def text_area_row(attribute, options={})
|
13
|
+
row_input attribute, :text_area, options
|
14
|
+
end
|
15
|
+
|
16
|
+
def moj_date_fieldset attribute, legend, options = {}, example_date = Date.today, explanatory_text = nil
|
17
|
+
df = MojDateFieldset.new(self, attribute, legend, options, example_date, explanatory_text)
|
18
|
+
df.emit
|
19
|
+
end
|
20
|
+
|
21
|
+
# produces an postcode picker widget - this will produce an address/street and postcode attributes for the given object type
|
22
|
+
# @param [String] attribute: the name of the attribute on Claim which is to have the street and postcode attributes (e.g. property, defendant_1)
|
23
|
+
# @param [Hash] options: options to control the way in which the potcode picker is displayed, and what html is generated in the form:
|
24
|
+
# :prefix - the prefix to be applied to each element in the form
|
25
|
+
# :postcode_attr - the name of the postcode attribute if not 'postcode'
|
26
|
+
# :address_attr - the name of the address attribute if not 'street'
|
27
|
+
# :name - the prefix of the name given to the street and postcode attributes if not 'claim['xxxx'] where xxxx is the attribute
|
28
|
+
# :street_hint - and html which is to be inserted as a hint above the street textarea
|
29
|
+
# :vc - list of valid countries: postcodes that return a country not in the supplied list will be marked as invalid.
|
30
|
+
# If not supplied or blank, all countries are valid. Countries should be joined by '+' and spaces in country names should be replaced
|
31
|
+
# by underscores, e.g "england+wales+channel_islands+isle_of_man"
|
32
|
+
# :button_label - the text to use on the Find UK Address button if not 'Find Uk Address'
|
33
|
+
#
|
34
|
+
def moj_postcode_picker attribute, options = {}
|
35
|
+
default_options = {
|
36
|
+
:prefix => "claim_#{attribute}",
|
37
|
+
:postcode_attr => :postcode,
|
38
|
+
:address_attr => :street,
|
39
|
+
:name => "claim[#{attribute}]"
|
40
|
+
}
|
41
|
+
options = default_options.merge(options)
|
42
|
+
mpp = MojPostcodePicker.new(self, options)
|
43
|
+
mpp.emit
|
44
|
+
end
|
45
|
+
|
46
|
+
# Defaults to "Yes" "No" labels on radio inputs
|
47
|
+
def radio_button_fieldset attribute, legend, options={}
|
48
|
+
translation_key = translation_key(attribute)
|
49
|
+
raise "TBD: #{translation_key} #{options[:choice]}" if options[:choice].is_a?(Hash)
|
50
|
+
|
51
|
+
virtual_pageview = options[:data] ? options[:data].delete('virtual-pageview') : nil
|
52
|
+
input_class = options.delete(:input_class)
|
53
|
+
|
54
|
+
set_class_and_id attribute, options
|
55
|
+
|
56
|
+
options[:choice] ||= [ 'Yes', 'No' ]
|
57
|
+
|
58
|
+
options_class = options[:class][/inline/] ? 'inline' : 'options'
|
59
|
+
|
60
|
+
data_reverse = options.delete(:toggle_fieldset) ? ' data-reverse="true"' : ''
|
61
|
+
|
62
|
+
fieldset_tag attribute, legend, options do
|
63
|
+
@template.surround("<div class='#{options_class}'#{data_reverse}>".html_safe, "</div>".html_safe) do
|
64
|
+
options[:choice].map do |choice|
|
65
|
+
radio_button_row(attribute, choice, virtual_pageview, input_class)
|
66
|
+
end.join("\n")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def row attribute, options={}
|
72
|
+
@template.haml_tag haml_tag_text('div option', attribute, options) do
|
73
|
+
yield
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def error_for? attribute
|
78
|
+
# if @object.is_a?(Claim)
|
79
|
+
# subkey = "claim_#{attribute}_error"
|
80
|
+
# base_errors = error_message_for(:base)
|
81
|
+
# base_errors && base_errors.to_h.key?(subkey) && !base_errors.to_h[subkey].empty?
|
82
|
+
# else
|
83
|
+
attribute_errors = error_message_for(attribute)
|
84
|
+
attribute_errors && !attribute_errors.empty?
|
85
|
+
# end
|
86
|
+
end
|
87
|
+
|
88
|
+
def error_span attribute, options={}
|
89
|
+
@template.surround(error_span_open_tag(options), "</span>".html_safe) do
|
90
|
+
error_span_message(attribute)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Creates key for lookup of translation text.
|
95
|
+
# E.g. translation_key(hearing, {:choice=>"No"}) when in possession form
|
96
|
+
# returns "claim.possession.hearing.no"
|
97
|
+
def translation_key attribute, options={}
|
98
|
+
key = "#{ parent_id.gsub('_','.') }.#{attribute}".squeeze('.')
|
99
|
+
key.gsub!(/\.\d+\./, '.')
|
100
|
+
if choice = options[:choice]
|
101
|
+
choice = 'na' if choice == ''
|
102
|
+
key += ".#{choice.downcase}"
|
103
|
+
end
|
104
|
+
key
|
105
|
+
end
|
106
|
+
|
107
|
+
def error_id_for attribute
|
108
|
+
field_id = "#{parent_id}_#{attribute}".squeeze('_')
|
109
|
+
"#{field_id}_error"
|
110
|
+
end
|
111
|
+
|
112
|
+
def parent_id
|
113
|
+
@object_name.to_s.tr('[]','_').squeeze('_')
|
114
|
+
end
|
115
|
+
|
116
|
+
def labelled_check_box attribute, label, yes='Yes', no='No', options={}
|
117
|
+
set_class_and_id attribute, options
|
118
|
+
hidden_input = check_box_input_hidden attribute, options, yes, no
|
119
|
+
|
120
|
+
labeled_input = label(attribute) do
|
121
|
+
check_box_input(attribute, options, yes, no) + label
|
122
|
+
end
|
123
|
+
|
124
|
+
list = [hidden_input]
|
125
|
+
|
126
|
+
if error_for?(attribute)
|
127
|
+
id = error_id_for(attribute)
|
128
|
+
labeled_input.sub!(%Q[id="#{id}"], %Q[id="#{id.sub('_error','')}"])
|
129
|
+
list << hidden_fullstop(options)
|
130
|
+
list << error_span(attribute)
|
131
|
+
end
|
132
|
+
|
133
|
+
list << labeled_input
|
134
|
+
|
135
|
+
list.join("\n").html_safe
|
136
|
+
end
|
137
|
+
|
138
|
+
def set_class_and_id attribute, options
|
139
|
+
options[:class] = css_for(attribute, options)
|
140
|
+
options[:id] = id_for(attribute) unless id_for(attribute).blank?
|
141
|
+
end
|
142
|
+
|
143
|
+
def fieldset_tag(attribute, legend_text, options = {}, &block)
|
144
|
+
fieldset = tag(:fieldset, options_for_fieldset(options), true)
|
145
|
+
|
146
|
+
fieldset.safe_concat legend_for(attribute, legend_text, options) unless legend_text.blank?
|
147
|
+
|
148
|
+
fieldset.concat(capture(&block)) if block_given?
|
149
|
+
fieldset.safe_concat("</fieldset>")
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def fieldset attribute, options={}
|
155
|
+
options.delete(:id) unless options[:id].present?
|
156
|
+
@template.haml_tag haml_tag_text('fieldset', attribute, options) do
|
157
|
+
yield
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def id_for attribute, default=nil
|
162
|
+
error_for?(attribute) ? error_id_for(attribute) : (default || '')
|
163
|
+
end
|
164
|
+
|
165
|
+
def label_content_for attribute, label, options={}
|
166
|
+
label ||= attribute.to_s.humanize
|
167
|
+
label = ["#{label}"]
|
168
|
+
hint = hint_span(options)
|
169
|
+
label << hint if hint
|
170
|
+
if error_for?(attribute)
|
171
|
+
last = label.pop
|
172
|
+
label << ( ends_with_punctuation?(last) ? last : (last + hidden_fullstop(options)) )
|
173
|
+
label << error_span(attribute, options)
|
174
|
+
end
|
175
|
+
label.join(" ").html_safe
|
176
|
+
end
|
177
|
+
|
178
|
+
def hint_span options
|
179
|
+
options[:hint] ? "<span class='hint block'>#{options[:hint]}</span>".html_safe : nil
|
180
|
+
end
|
181
|
+
|
182
|
+
def ends_with_punctuation? span
|
183
|
+
span[/\?<\/span/] || span[/\.<\/span>/] || span[/\.|\?$/]
|
184
|
+
end
|
185
|
+
|
186
|
+
def legend_for attribute, legend_text, options
|
187
|
+
label = label_content_for(attribute, legend_text, hint: options[:hint])
|
188
|
+
content_tag(:legend, label)
|
189
|
+
end
|
190
|
+
|
191
|
+
def hidden_fullstop options
|
192
|
+
'<span class="visuallyhidden">.</span>'.html_safe
|
193
|
+
end
|
194
|
+
|
195
|
+
def error_span_message attribute
|
196
|
+
if @object.is_a? Claim
|
197
|
+
error_message_for(:base).to_h["claim_#{attribute}_error"]
|
198
|
+
else
|
199
|
+
error_message_for(attribute)[0]
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def error_span_open_tag options
|
204
|
+
" <span class='error#{error_classes(options)}'#{error_span_id(options)}>".html_safe
|
205
|
+
end
|
206
|
+
|
207
|
+
def error_span_id options
|
208
|
+
options.has_key?(:id)? " id='#{options[:id]}'" : nil
|
209
|
+
end
|
210
|
+
|
211
|
+
def error_classes options
|
212
|
+
' visuallyhidden' if options[:hidden]
|
213
|
+
end
|
214
|
+
|
215
|
+
def options_for_fieldset options
|
216
|
+
options.delete(:class) if options[:class].blank?
|
217
|
+
options = {}.merge(options)
|
218
|
+
options.delete(:hint)
|
219
|
+
options.delete(:choice)
|
220
|
+
options.delete(:date_select_options)
|
221
|
+
options
|
222
|
+
end
|
223
|
+
|
224
|
+
def error_message_for symbol
|
225
|
+
@object.errors.messages[symbol]
|
226
|
+
end
|
227
|
+
|
228
|
+
def check_box_input attribute, options, yes, no
|
229
|
+
html = check_box(attribute, options, yes, no)
|
230
|
+
html.gsub!(/<[^<]*type="hidden"[^>]*>/,'')
|
231
|
+
html.html_safe
|
232
|
+
end
|
233
|
+
|
234
|
+
def check_box_input_hidden attribute, options, yes, no
|
235
|
+
html = check_box(attribute, options, yes, no)
|
236
|
+
html.gsub!(/.*(<[^<]*type="hidden"[^>]*>).*/, '\1')
|
237
|
+
html.html_safe
|
238
|
+
end
|
239
|
+
|
240
|
+
def radio_button_row attribute, choice, virtual_pageview, input_class
|
241
|
+
translation_key = translation_key(attribute, choice: choice)
|
242
|
+
|
243
|
+
translation = I18n.t(translation_key)
|
244
|
+
raise "translation missing: #{translation_key}" if translation[/translation missing/]
|
245
|
+
label = translation unless translation[/translation missing/]
|
246
|
+
|
247
|
+
options = {}
|
248
|
+
options.merge!(class: input_class) if input_class
|
249
|
+
options.merge!(data: { 'virtual_pageview' => virtual_pageview }) if virtual_pageview
|
250
|
+
|
251
|
+
input = radio_button(attribute, choice, options)
|
252
|
+
|
253
|
+
id = input[/id="([^"]+)"/,1]
|
254
|
+
|
255
|
+
@template.surround("<div class='option'>".html_safe, "</div>".html_safe) do
|
256
|
+
@template.surround("<label for='#{id}'>".html_safe, "</label>".html_safe) do
|
257
|
+
# errors = error_span(attribute, {hidden: true}) if error_for?(attribute)
|
258
|
+
[
|
259
|
+
# errors,
|
260
|
+
input,
|
261
|
+
label
|
262
|
+
].compact.join("\n")
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def css_for attribute, options
|
268
|
+
css = ''
|
269
|
+
css += " #{options[:class]}" if options[:class].present?
|
270
|
+
css += ' error' if error_for?(attribute)
|
271
|
+
css.strip
|
272
|
+
end
|
273
|
+
|
274
|
+
def haml_tag_text tag, attribute, options
|
275
|
+
tag += " #{css_for(attribute, options)}"
|
276
|
+
haml_tag_text = tag.squeeze(' ').strip.gsub(' ','.')
|
277
|
+
end
|
278
|
+
|
279
|
+
def row_input attribute, input_type, options
|
280
|
+
virtual_pageview = options[:data] ? options[:data].delete('virtual-pageview') : nil
|
281
|
+
css = "form-group #{css_for(attribute, options)}".strip
|
282
|
+
id = id_for(attribute).blank? ? '' : "id='#{id_for(attribute)}' "
|
283
|
+
|
284
|
+
@template.surround("<div #{id}class='#{css}'>".html_safe, "</div>".html_safe) do
|
285
|
+
input_options = options.merge(class: "form-control #{options[:input_class]}".strip)
|
286
|
+
input_options.merge!(data: {'virtual_pageview' => virtual_pageview}) if virtual_pageview
|
287
|
+
input_options.delete(:label)
|
288
|
+
input_options.delete(:input_class)
|
289
|
+
|
290
|
+
labelled_input attribute, input_type, input_options, options[:label]
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def labelled_input attribute, input_type, input_options, label=nil
|
295
|
+
label = label(attribute, label_content_for(attribute, label), class: 'form-label')
|
296
|
+
|
297
|
+
if max_length = max_length(attribute)
|
298
|
+
input_options.merge!(maxlength: max_length)
|
299
|
+
end
|
300
|
+
|
301
|
+
value = send(input_type, attribute, input_options)
|
302
|
+
|
303
|
+
[ label, value ].join("\n").html_safe
|
304
|
+
end
|
305
|
+
|
306
|
+
def max_length attribute
|
307
|
+
if validator = validators(attribute).detect{|x| x.is_a?(ActiveModel::Validations::LengthValidator)}
|
308
|
+
validator.options[:maximum]
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def validators attribute
|
313
|
+
@object.class.validators_on(attribute)
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
function ShowHideContent() {
|
2
|
+
var self = this;
|
3
|
+
|
4
|
+
|
5
|
+
self.escapeElementName = function(str) {
|
6
|
+
result = str.replace('[', '\\[').replace(']', '\\]')
|
7
|
+
return(result);
|
8
|
+
};
|
9
|
+
|
10
|
+
self.showHideRadioToggledContent = function () {
|
11
|
+
$(".block-label input[type='radio']").each(function () {
|
12
|
+
|
13
|
+
var $radio = $(this);
|
14
|
+
var $radioGroupName = $radio.attr('name');
|
15
|
+
var $radioLabel = $radio.parent('label');
|
16
|
+
|
17
|
+
var dataTarget = $radioLabel.attr('data-target');
|
18
|
+
|
19
|
+
// Add ARIA attributes
|
20
|
+
|
21
|
+
// If the data-target attribute is defined
|
22
|
+
if (dataTarget) {
|
23
|
+
|
24
|
+
// Set aria-controls
|
25
|
+
$radio.attr('aria-controls', dataTarget);
|
26
|
+
|
27
|
+
$radio.on('click', function () {
|
28
|
+
|
29
|
+
// Select radio buttons in the same group
|
30
|
+
$radio.closest('form').find(".block-label input[name=" + self.escapeElementName($radioGroupName) + "]").each(function () {
|
31
|
+
var $this = $(this);
|
32
|
+
|
33
|
+
var groupDataTarget = $this.parent('label').attr('data-target');
|
34
|
+
var $groupDataTarget = $('#' + groupDataTarget);
|
35
|
+
|
36
|
+
// Hide toggled content
|
37
|
+
$groupDataTarget.hide();
|
38
|
+
// Set aria-expanded and aria-hidden for hidden content
|
39
|
+
$this.attr('aria-expanded', 'false');
|
40
|
+
$groupDataTarget.attr('aria-hidden', 'true');
|
41
|
+
});
|
42
|
+
|
43
|
+
var $dataTarget = $('#' + dataTarget);
|
44
|
+
$dataTarget.show();
|
45
|
+
// Set aria-expanded and aria-hidden for clicked radio
|
46
|
+
$radio.attr('aria-expanded', 'true');
|
47
|
+
$dataTarget.attr('aria-hidden', 'false');
|
48
|
+
|
49
|
+
});
|
50
|
+
|
51
|
+
} else {
|
52
|
+
// If the data-target attribute is undefined for a radio button,
|
53
|
+
// hide visible data-target content for radio buttons in the same group
|
54
|
+
|
55
|
+
$radio.on('click', function () {
|
56
|
+
|
57
|
+
// Select radio buttons in the same group
|
58
|
+
$(".block-label input[name=" + self.escapeElementName($radioGroupName) + "]").each(function () {
|
59
|
+
|
60
|
+
var groupDataTarget = $(this).parent('label').attr('data-target');
|
61
|
+
var $groupDataTarget = $('#' + groupDataTarget);
|
62
|
+
|
63
|
+
// Hide toggled content
|
64
|
+
$groupDataTarget.hide();
|
65
|
+
// Set aria-expanded and aria-hidden for hidden content
|
66
|
+
$(this).attr('aria-expanded', 'false');
|
67
|
+
$groupDataTarget.attr('aria-hidden', 'true');
|
68
|
+
});
|
69
|
+
|
70
|
+
});
|
71
|
+
}
|
72
|
+
|
73
|
+
});
|
74
|
+
}
|
75
|
+
self.showHideCheckboxToggledContent = function () {
|
76
|
+
|
77
|
+
$(".block-label input[type='checkbox']").each(function() {
|
78
|
+
|
79
|
+
var $checkbox = $(this);
|
80
|
+
var $checkboxLabel = $(this).parent();
|
81
|
+
|
82
|
+
var $dataTarget = $checkboxLabel.attr('data-target');
|
83
|
+
|
84
|
+
// Add ARIA attributes
|
85
|
+
|
86
|
+
// If the data-target attribute is defined
|
87
|
+
if (typeof $dataTarget !== 'undefined' && $dataTarget !== false) {
|
88
|
+
|
89
|
+
// Set aria-controls
|
90
|
+
$checkbox.attr('aria-controls', $dataTarget);
|
91
|
+
|
92
|
+
// Set aria-expanded and aria-hidden
|
93
|
+
$checkbox.attr('aria-expanded', 'false');
|
94
|
+
$('#'+$dataTarget).attr('aria-hidden', 'true');
|
95
|
+
|
96
|
+
// For checkboxes revealing hidden content
|
97
|
+
$checkbox.on('click', function() {
|
98
|
+
|
99
|
+
var state = $(this).attr('aria-expanded') === 'false' ? true : false;
|
100
|
+
|
101
|
+
// Toggle hidden content
|
102
|
+
$('#'+$dataTarget).toggle();
|
103
|
+
|
104
|
+
// Update aria-expanded and aria-hidden attributes
|
105
|
+
$(this).attr('aria-expanded', state);
|
106
|
+
$('#'+$dataTarget).attr('aria-hidden', !state);
|
107
|
+
|
108
|
+
});
|
109
|
+
}
|
110
|
+
|
111
|
+
});
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
$(document).ready(function() {
|
116
|
+
|
117
|
+
// Turn off jQuery animation
|
118
|
+
jQuery.fx.off = true;
|
119
|
+
|
120
|
+
// Use GOV.UK selection-buttons.js to set selected
|
121
|
+
// and focused states for block labels
|
122
|
+
var $blockLabels = $(".block-label input[type='radio'], .block-label input[type='checkbox']");
|
123
|
+
new GOVUK.SelectionButtons($blockLabels);
|
124
|
+
|
125
|
+
// Details/summary polyfill
|
126
|
+
// See /javascripts/vendor/details.polyfill.js
|
127
|
+
|
128
|
+
// Where .block-label uses the data-target attribute
|
129
|
+
// to toggle hidden content
|
130
|
+
var toggleContent = new ShowHideContent();
|
131
|
+
toggleContent.showHideRadioToggledContent();
|
132
|
+
toggleContent.showHideCheckboxToggledContent();
|
133
|
+
|
134
|
+
});
|
@@ -24,16 +24,21 @@
|
|
24
24
|
|
25
25
|
// Handle cross-modal click events
|
26
26
|
function addClickEvent(node, callback) {
|
27
|
-
|
28
|
-
addEvent(node, '
|
29
|
-
|
27
|
+
// Prevent space(32) from scrolling the page
|
28
|
+
addEvent(node, 'keypress', function (e, target) {
|
29
|
+
if (e.keyCode === 32) {
|
30
|
+
if (e.preventDefault) {
|
31
|
+
e.preventDefault();
|
32
|
+
}
|
33
|
+
else { e.returnValue = false; }
|
34
|
+
}
|
30
35
|
});
|
36
|
+
// When the key comes up - check if it is enter(13) or space(32)
|
31
37
|
addEvent(node, 'keyup', function (e, target) {
|
32
|
-
|
33
|
-
if (e.keyCode === 13) { callback(e, target); }
|
38
|
+
if (e.keyCode === 13 || e.keyCode === 32) { callback(e, target); }
|
34
39
|
});
|
35
|
-
addEvent(node, '
|
36
|
-
|
40
|
+
addEvent(node, 'mouseup', function (e, target) {
|
41
|
+
callback(e, target);
|
37
42
|
});
|
38
43
|
}
|
39
44
|
|
@@ -86,6 +91,9 @@
|
|
86
91
|
details.__content.id = 'details-content-' + i;
|
87
92
|
}
|
88
93
|
|
94
|
+
// Add ARIA role="group" to details
|
95
|
+
details.setAttribute('role', 'group');
|
96
|
+
|
89
97
|
// Add role=button to summary
|
90
98
|
details.__summary.setAttribute('role', 'button');
|
91
99
|
|
@@ -93,30 +101,69 @@
|
|
93
101
|
details.__summary.setAttribute('aria-controls', details.__content.id);
|
94
102
|
|
95
103
|
// Set tabindex so the summary is keyboard accessible
|
96
|
-
details.__summary.setAttribute('tabindex',
|
104
|
+
// details.__summary.setAttribute('tabindex', 0);
|
105
|
+
// http://www.saliences.com/browserBugs/tabIndex.html
|
106
|
+
details.__summary.tabIndex = 0;
|
97
107
|
|
98
108
|
// Detect initial open/closed state
|
99
|
-
|
100
|
-
|
109
|
+
|
110
|
+
// Native support - has 'open' attribute
|
111
|
+
if (details.open === true) {
|
101
112
|
details.__summary.setAttribute('aria-expanded', 'true');
|
102
113
|
details.__content.setAttribute('aria-hidden', 'false');
|
103
|
-
|
114
|
+
details.__content.style.display = 'block';
|
115
|
+
}
|
116
|
+
|
117
|
+
// Native support - doesn't have 'open' attribute
|
118
|
+
if (details.open === false) {
|
104
119
|
details.__summary.setAttribute('aria-expanded', 'false');
|
105
120
|
details.__content.setAttribute('aria-hidden', 'true');
|
106
121
|
details.__content.style.display = 'none';
|
107
122
|
}
|
108
123
|
|
124
|
+
// If this is not a native implementation
|
125
|
+
if (!details.__native) {
|
126
|
+
|
127
|
+
// Add an arrow
|
128
|
+
var twisty = document.createElement('i');
|
129
|
+
|
130
|
+
// Check for the 'open' attribute
|
131
|
+
// If open exists, but isn't supported it won't have a value
|
132
|
+
if (details.getAttribute('open') === "") {
|
133
|
+
details.__summary.setAttribute('aria-expanded', 'true');
|
134
|
+
details.__content.setAttribute('aria-hidden', 'false');
|
135
|
+
}
|
136
|
+
|
137
|
+
// If open doesn't exist - it will be null or undefined
|
138
|
+
if (details.getAttribute('open') == null || details.getAttribute('open') == "undefined" ) {
|
139
|
+
details.__summary.setAttribute('aria-expanded', 'false');
|
140
|
+
details.__content.setAttribute('aria-hidden', 'true');
|
141
|
+
details.__content.style.display = 'none';
|
142
|
+
}
|
143
|
+
|
144
|
+
}
|
145
|
+
|
109
146
|
// Create a circular reference from the summary back to its
|
110
147
|
// parent details element, for convenience in the click handler
|
111
148
|
details.__summary.__details = details;
|
112
149
|
|
113
150
|
// If this is not a native implementation, create an arrow
|
114
|
-
// inside the summary
|
151
|
+
// inside the summary
|
115
152
|
if (!details.__native) {
|
153
|
+
|
116
154
|
var twisty = document.createElement('i');
|
117
|
-
|
118
|
-
|
155
|
+
|
156
|
+
if (details.getAttribute('open') === "") {
|
157
|
+
twisty.className = 'arrow arrow-open';
|
158
|
+
twisty.appendChild(document.createTextNode('\u25bc'));
|
159
|
+
} else {
|
160
|
+
twisty.className = 'arrow arrow-closed';
|
161
|
+
twisty.appendChild(document.createTextNode('\u25ba'));
|
162
|
+
}
|
163
|
+
|
119
164
|
details.__summary.__twisty = details.__summary.insertBefore(twisty, details.__summary.firstChild);
|
165
|
+
details.__summary.__twisty.setAttribute('aria-hidden', 'true');
|
166
|
+
|
120
167
|
}
|
121
168
|
}
|
122
169
|
|
@@ -124,7 +171,6 @@
|
|
124
171
|
// Also update the arrow position
|
125
172
|
function statechange(summary) {
|
126
173
|
|
127
|
-
// Update aria-expanded attribute on click
|
128
174
|
var expanded = summary.__details.__summary.getAttribute('aria-expanded') == 'true';
|
129
175
|
var hidden = summary.__details.__content.getAttribute('aria-hidden') == 'true';
|
130
176
|
|
@@ -1,12 +1,13 @@
|
|
1
1
|
(function () {
|
2
|
-
"use strict"
|
2
|
+
"use strict";
|
3
3
|
var root = this,
|
4
4
|
$ = root.jQuery;
|
5
5
|
|
6
6
|
if (typeof GOVUK === 'undefined') { root.GOVUK = {}; }
|
7
7
|
|
8
|
-
var
|
9
|
-
|
8
|
+
var SelectionButtons = function (elmsOrSelector, opts) {
|
9
|
+
var $elms;
|
10
|
+
|
10
11
|
this.selectedClass = 'selected';
|
11
12
|
this.focusedClass = 'focused';
|
12
13
|
if (opts !== undefined) {
|
@@ -14,124 +15,97 @@
|
|
14
15
|
this[optionName] = optionObj;
|
15
16
|
}.bind(this));
|
16
17
|
}
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
if (typeof elmsOrSelector === 'string') {
|
19
|
+
$elms = $(elmsOrSelector);
|
20
|
+
this.selector = elmsOrSelector;
|
21
|
+
this.setInitialState($(this.selector));
|
22
|
+
} else {
|
23
|
+
this.$elms = elmsOrSelector;
|
24
|
+
this.setInitialState(this.$elms);
|
25
|
+
}
|
26
|
+
this.addEvents();
|
20
27
|
};
|
21
|
-
|
22
|
-
this
|
23
|
-
|
28
|
+
SelectionButtons.prototype.addEvents = function () {
|
29
|
+
if (typeof this.$elms !== 'undefined') {
|
30
|
+
this.addElementLevelEvents();
|
31
|
+
} else {
|
32
|
+
this.addDocumentLevelEvents();
|
33
|
+
}
|
24
34
|
};
|
25
|
-
|
26
|
-
|
35
|
+
SelectionButtons.prototype.setInitialState = function ($elms) {
|
36
|
+
$elms.each(function (idx, elm) {
|
37
|
+
var $elm = $(elm);
|
27
38
|
|
39
|
+
if ($elm.is(':checked')) {
|
40
|
+
this.markSelected($elm);
|
41
|
+
}
|
42
|
+
}.bind(this));
|
43
|
+
};
|
44
|
+
SelectionButtons.prototype.markFocused = function ($elm, state) {
|
28
45
|
if (state === 'focused') {
|
29
46
|
$elm.parent('label').addClass(this.focusedClass);
|
30
47
|
} else {
|
31
48
|
$elm.parent('label').removeClass(this.focusedClass);
|
32
49
|
}
|
33
50
|
};
|
34
|
-
|
35
|
-
var
|
36
|
-
focusEventHandler = this.markFocused.bind(this);
|
51
|
+
SelectionButtons.prototype.markSelected = function ($elm) {
|
52
|
+
var radioName;
|
37
53
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
}
|
54
|
+
if ($elm.attr('type') === 'radio') {
|
55
|
+
radioName = $elm.attr('name');
|
56
|
+
$($elm[0].form).find('input[name="' + radioName + '"]')
|
57
|
+
.parent('label')
|
58
|
+
.removeClass(this.selectedClass);
|
59
|
+
$elm.parent('label').addClass(this.selectedClass);
|
60
|
+
} else { // checkbox
|
68
61
|
if ($elm.is(':checked')) {
|
69
|
-
|
62
|
+
$elm.parent('label').addClass(this.selectedClass);
|
63
|
+
} else {
|
64
|
+
$elm.parent('label').removeClass(this.selectedClass);
|
70
65
|
}
|
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
66
|
}
|
83
|
-
$elm.parent('label').addClass(this.selectedClass);
|
84
|
-
this.selections[radioName] = $elm;
|
85
67
|
};
|
86
|
-
|
87
|
-
|
68
|
+
SelectionButtons.prototype.addElementLevelEvents = function () {
|
69
|
+
this.clickHandler = this.getClickHandler();
|
70
|
+
this.focusHandler = this.getFocusHandler({ 'level' : 'element' });
|
71
|
+
|
72
|
+
this.$elms
|
73
|
+
.on('click', this.clickHandler)
|
74
|
+
.on('focus blur', this.focusHandler);
|
88
75
|
};
|
76
|
+
SelectionButtons.prototype.addDocumentLevelEvents = function () {
|
77
|
+
this.clickHandler = this.getClickHandler();
|
78
|
+
this.focusHandler = this.getFocusHandler({ 'level' : 'document' });
|
89
79
|
|
90
|
-
|
91
|
-
|
80
|
+
$(document)
|
81
|
+
.on('click', this.selector, this.clickHandler)
|
82
|
+
.on('focus blur', this.selector, this.focusHandler);
|
92
83
|
};
|
93
|
-
|
94
|
-
|
84
|
+
SelectionButtons.prototype.getClickHandler = function () {
|
85
|
+
return function (e) {
|
86
|
+
this.markSelected($(e.target));
|
87
|
+
}.bind(this);
|
95
88
|
};
|
96
|
-
|
97
|
-
var
|
89
|
+
SelectionButtons.prototype.getFocusHandler = function (opts) {
|
90
|
+
var focusEvent = (opts.level === 'document') ? 'focusin' : 'focus';
|
98
91
|
|
99
|
-
|
100
|
-
var
|
92
|
+
return function (e) {
|
93
|
+
var state = (e.type === focusEvent) ? 'focused' : 'blurred';
|
101
94
|
|
102
|
-
|
103
|
-
|
104
|
-
}
|
105
|
-
});
|
95
|
+
this.markFocused($(e.target), state);
|
96
|
+
}.bind(this);
|
106
97
|
};
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
$elm.parent('label').addClass(this.selectedClass);
|
98
|
+
SelectionButtons.prototype.destroy = function () {
|
99
|
+
if (typeof this.selector !== 'undefined') {
|
100
|
+
$(document)
|
101
|
+
.off('click', this.selector, this.clickHandler)
|
102
|
+
.off('focus blur', this.selector, this.focusHandler);
|
113
103
|
} else {
|
114
|
-
|
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);
|
104
|
+
this.$elms
|
105
|
+
.off('click', this.clickHandler)
|
106
|
+
.off('focus blur', this.focusHandler);
|
133
107
|
}
|
134
108
|
};
|
135
109
|
|
136
|
-
root.GOVUK.
|
110
|
+
root.GOVUK.SelectionButtons = SelectionButtons;
|
137
111
|
}).call(this);
|
@@ -94,20 +94,51 @@
|
|
94
94
|
color: $hm-government;
|
95
95
|
}
|
96
96
|
|
97
|
+
// Fix grid layout within example boxes for IE7 and below
|
98
|
+
// where box-sizing isn't supported: http://caniuse.com/#search=box-sizing
|
99
|
+
@mixin example-box-column($width) {
|
100
|
+
width: (($site-width - $gutter) * $width) - $gutter;
|
101
|
+
}
|
102
|
+
|
103
|
+
@include ie-lte(7){
|
104
|
+
|
105
|
+
// Set example box width to 900px (removing left and right padding)
|
106
|
+
$example-box-width: $site-width - ($gutter * 2);
|
107
|
+
width: $example-box-width;
|
108
|
+
|
109
|
+
// Recalculate grid column widths
|
110
|
+
.column-quarter {
|
111
|
+
@include example-box-column( 1/4 );
|
112
|
+
}
|
113
|
+
.column-half {
|
114
|
+
@include example-box-column( 1/2 );
|
115
|
+
}
|
116
|
+
.column-third {
|
117
|
+
@include example-box-column( 1/3 );
|
118
|
+
}
|
119
|
+
.column-two-thirds {
|
120
|
+
@include example-box-column( 2/3 );
|
121
|
+
}
|
122
|
+
|
123
|
+
// Scale images to fit grid columns
|
124
|
+
img {
|
125
|
+
width: 100%;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
97
129
|
}
|
98
130
|
|
99
131
|
|
100
132
|
// 1. Layout
|
101
133
|
// ==========================================================================
|
102
134
|
|
103
|
-
// Grid layout boxes
|
104
135
|
.example-grid p {
|
105
136
|
width: 100%;
|
106
137
|
background: file-url("examples/grid.png") 0 0 repeat;
|
107
|
-
min-height: 30px;
|
108
138
|
margin-bottom: 0;
|
139
|
+
height: 30px;
|
109
140
|
@include media(tablet) {
|
110
|
-
|
141
|
+
height: 60px;
|
111
142
|
}
|
112
143
|
overflow: hidden;
|
113
144
|
text-indent: -999em;
|
@@ -331,3 +362,17 @@ $palette: (
|
|
331
362
|
.example-button ul {
|
332
363
|
padding-bottom: 0;
|
333
364
|
}
|
365
|
+
|
366
|
+
|
367
|
+
// 9. Alpha beta banners
|
368
|
+
// ==========================================================================
|
369
|
+
|
370
|
+
// Alpha
|
371
|
+
.phase-banner-alpha {
|
372
|
+
@include phase-banner($state: alpha);
|
373
|
+
}
|
374
|
+
|
375
|
+
// Beta
|
376
|
+
.phase-banner-beta {
|
377
|
+
@include phase-banner($state: beta);
|
378
|
+
}
|
@@ -45,15 +45,19 @@ fieldset {
|
|
45
45
|
// Labels
|
46
46
|
|
47
47
|
// Form labels, or for legends styled to look like labels
|
48
|
+
.form-label,
|
49
|
+
.form-label-bold {
|
50
|
+
display: block;
|
51
|
+
color: $text-colour;
|
52
|
+
}
|
53
|
+
|
48
54
|
.form-label {
|
49
55
|
@include core-19;
|
50
|
-
display: block;
|
51
56
|
margin-bottom: 5px;
|
52
57
|
}
|
53
58
|
|
54
59
|
.form-label-bold {
|
55
60
|
@include bold-24;
|
56
|
-
display: block;
|
57
61
|
margin-bottom: 0;
|
58
62
|
.form-hint {
|
59
63
|
@include core-19;
|
@@ -9,11 +9,11 @@
|
|
9
9
|
@import "design-patterns/alpha-beta";
|
10
10
|
|
11
11
|
|
12
|
-
//
|
12
|
+
// Content
|
13
13
|
// ==========================================================================
|
14
14
|
|
15
|
-
//
|
16
|
-
#
|
15
|
+
// Content wraps the entire site content block
|
16
|
+
#content {
|
17
17
|
@extend %site-width-container;
|
18
18
|
@extend %contain-floats;
|
19
19
|
padding-bottom: $gutter;
|
@@ -10,13 +10,16 @@ ol {
|
|
10
10
|
// Bulleted lists
|
11
11
|
.list-bullet {
|
12
12
|
list-style-type: disc;
|
13
|
-
|
13
|
+
padding-left: 20px;
|
14
14
|
}
|
15
15
|
|
16
16
|
// Numbered lists
|
17
17
|
.list-number {
|
18
18
|
list-style-type: decimal;
|
19
|
-
|
19
|
+
padding-left: 20px;
|
20
|
+
@include ie-lte(7) {
|
21
|
+
padding-left: 28px;
|
22
|
+
}
|
20
23
|
}
|
21
24
|
|
22
25
|
.list-bullet,
|
@@ -14,7 +14,7 @@ table {
|
|
14
14
|
table th,
|
15
15
|
table td {
|
16
16
|
@include core-16;
|
17
|
-
padding: em(
|
17
|
+
padding: em(12, 16) em(20, 16) em(9, 16) 0;
|
18
18
|
|
19
19
|
text-align: left;
|
20
20
|
color: #0b0c0c;
|
@@ -24,3 +24,14 @@ table td {
|
|
24
24
|
table th {
|
25
25
|
font-weight: 700;
|
26
26
|
}
|
27
|
+
|
28
|
+
// Right align headings for numeric content
|
29
|
+
table th.numeric {
|
30
|
+
text-align: right;
|
31
|
+
}
|
32
|
+
|
33
|
+
// Use tabular numbers for numeric table cells
|
34
|
+
table td.numeric {
|
35
|
+
@include core-16($tabular-numbers: true);
|
36
|
+
text-align: right;
|
37
|
+
}
|
@@ -1,46 +1,39 @@
|
|
1
|
-
// Date
|
1
|
+
// Date pattern
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
// Hide the 'spinner' for webkit
|
4
|
+
// and also for Firefox
|
5
|
+
input::-webkit-outer-spin-button,
|
6
|
+
input::-webkit-inner-spin-button {
|
7
|
+
-webkit-appearance: none;
|
8
|
+
margin: 0
|
6
9
|
}
|
7
|
-
|
8
|
-
|
9
|
-
width: 50px;
|
10
|
-
float: left;
|
11
|
-
margin-right: 20px;
|
12
|
-
margin-bottom: 0;
|
13
|
-
clear: none;
|
10
|
+
input[type=number] {
|
11
|
+
-moz-appearance: textfield
|
14
12
|
}
|
15
13
|
|
16
|
-
.form-date
|
17
|
-
width: 70px;
|
18
|
-
}
|
14
|
+
.form-date {
|
19
15
|
|
20
|
-
.form-
|
21
|
-
|
22
|
-
|
16
|
+
.form-group {
|
17
|
+
float: left;
|
18
|
+
width: 50px;
|
23
19
|
|
20
|
+
margin-right: 20px;
|
21
|
+
margin-bottom: 0;
|
22
|
+
clear: none;
|
24
23
|
|
25
|
-
|
26
|
-
|
24
|
+
label {
|
25
|
+
display: block;
|
26
|
+
margin-bottom: 5px;
|
27
|
+
}
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
}
|
29
|
+
input {
|
30
|
+
width: 100%;
|
31
|
+
}
|
32
32
|
|
33
|
-
|
34
|
-
.no-touch .native-date-picker {
|
35
|
-
display: none;
|
36
|
-
}
|
33
|
+
}
|
37
34
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
}
|
35
|
+
.form-group-year {
|
36
|
+
width: 70px;
|
37
|
+
}
|
42
38
|
|
43
|
-
// Set a minimum height for date inputs
|
44
|
-
.touch input[type="date"] {
|
45
|
-
min-height: 36px;
|
46
39
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govuk_elements_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob McKinnon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -50,8 +50,8 @@ dependencies:
|
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: 3.2.0
|
53
|
-
description: A gem wrapper around SHA
|
54
|
-
(
|
53
|
+
description: A gem wrapper around SHA caadd5a3bf04d58ab61bab5ec8e00afdba818b18 govuk_elements
|
54
|
+
(remotes/origin/HEAD) that pulls stylesheet and javascript files into a Rails app.
|
55
55
|
email: rob.mckinnon ~@nospam@~ digital.justice.gov.uk
|
56
56
|
executables: []
|
57
57
|
extensions: []
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- LICENCE
|
62
62
|
- README.md
|
63
63
|
- app/builders/govuk_elements_form_builder.rb
|
64
|
+
- app/builders/labelling_form_builder.rb
|
64
65
|
- lib/govuk_elements_rails.rb
|
65
66
|
- lib/govuk_elements_rails/engine.rb
|
66
67
|
- lib/govuk_elements_rails/version.rb
|
@@ -89,6 +90,7 @@ files:
|
|
89
90
|
- vendor/assets/images/icons/player-icon-play.png
|
90
91
|
- vendor/assets/images/icons/player-icon-rewind.png
|
91
92
|
- vendor/assets/images/icons/player-icon-volume.png
|
93
|
+
- vendor/assets/javascripts/application.js
|
92
94
|
- vendor/assets/javascripts/bind.js
|
93
95
|
- vendor/assets/javascripts/details.polyfill.js
|
94
96
|
- vendor/assets/javascripts/selection-buttons.js
|
@@ -140,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
142
|
version: '0'
|
141
143
|
requirements: []
|
142
144
|
rubyforge_project:
|
143
|
-
rubygems_version: 2.
|
145
|
+
rubygems_version: 2.4.5
|
144
146
|
signing_key:
|
145
147
|
specification_version: 4
|
146
148
|
summary: A gem wrapper around http://github.com/alphagov/govuk_elements that pulls
|