outro_rails 0.1.5 → 0.1.6
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.
- checksums.yaml +4 -4
- data/README.md +63 -2
- data/app/assets/stylesheets/outro_rails/outro_rails.css +11 -43
- data/app/helpers/outro_rails/chord_charts_helper.rb +1 -0
- data/app/helpers/outro_rails/class_names_helper.rb +34 -0
- data/app/views/outro_rails/caged/show.html.erb +5 -5
- data/app/views/outro_rails/capo/show.html.erb +2 -1
- data/app/views/outro_rails/chord_charts/_chart.html.erb +240 -249
- data/app/views/outro_rails/chord_charts/_fields.html.erb +13 -12
- data/app/views/outro_rails/chords/_filter.html.erb +14 -14
- data/app/views/outro_rails/chords/index.html.erb +1 -1
- data/app/views/outro_rails/circle_of_fifths/show.html.erb +2 -3
- data/app/views/outro_rails/instruments/_guitar.html.erb +3 -3
- data/app/views/outro_rails/scales/_picker.html.erb +7 -7
- data/app/views/outro_rails/scales/show.html.erb +2 -3
- data/app/views/outro_rails/transposer/show.html.erb +9 -9
- data/lib/outro_rails/version.rb +1 -1
- data/lib/outro_rails.rb +31 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b9a61b44de4d831dd78c2ef49903677777792cfe812a6f77211dbf4e846ffb35
|
|
4
|
+
data.tar.gz: 60ee9af6996b28da00252dc296e40d5869c0f877ed8335e126d8650ae6b8d462
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 153b0d96d98f43b44c323a06fa7b3106b2ea06d0e92ca2c4a9e33f74bb3a6555b109bffbb880c3969d5147ca0aa3e43ba573060111b073c36e80f7958911c4ac
|
|
7
|
+
data.tar.gz: 91a29abfb552a60757fcdc0ded4883d921000fa9fb2c2a31e4a855e5cca628689b9def02844da3f88f736fba6c44ac4b9ff4e5280d50bb736b532bd6b5d67096
|
data/README.md
CHANGED
|
@@ -50,7 +50,8 @@ quickest version is to add two tags to your layout:
|
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
If you'd rather fold the engine's assets into your existing bundles, see
|
|
53
|
-
[Assets](#assets) below.
|
|
53
|
+
[Assets](#assets) below. If you'd rather style the form controls with your
|
|
54
|
+
own CSS framework, see [Control classes](#control-classes).
|
|
54
55
|
|
|
55
56
|
## Assets
|
|
56
57
|
|
|
@@ -161,6 +162,61 @@ yarn build
|
|
|
161
162
|
yarn build:css
|
|
162
163
|
```
|
|
163
164
|
|
|
165
|
+
### Form Control Classes
|
|
166
|
+
|
|
167
|
+
Out of the box the engine's text fields, textareas, selects, and labels
|
|
168
|
+
carry its own classes, styled by the stylesheet above:
|
|
169
|
+
|
|
170
|
+
| Element | Setting | Default |
|
|
171
|
+
| ---------- | -------------------------- | ---------------- |
|
|
172
|
+
| `button` | `OutroRails.button_class` | `outro-button` |
|
|
173
|
+
| `input` | `OutroRails.input_class` | `outro-input` |
|
|
174
|
+
| `label` | `OutroRails.label_class` | `outro-label` |
|
|
175
|
+
| `select` | `OutroRails.select_class` | `outro-select` |
|
|
176
|
+
| `textarea` | `OutroRails.textarea_class` | `outro-textarea` |
|
|
177
|
+
|
|
178
|
+
If your app already has a form style (Bootstrap, Tailwind, your own classes)
|
|
179
|
+
point these at it in an initializer and the engine will render your classes
|
|
180
|
+
instead:
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
# config/initializers/outro_rails.rb
|
|
184
|
+
OutroRails.configure do |config|
|
|
185
|
+
config.button_class = "btn btn-sm"
|
|
186
|
+
config.input_class = "form-control"
|
|
187
|
+
config.label_class = "form-label"
|
|
188
|
+
config.select_class = "form-select"
|
|
189
|
+
config.textarea_class = "form-control"
|
|
190
|
+
end
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Each setting is a plain string and can also be assigned on its own
|
|
194
|
+
(`OutroRails.select_class = "form-select"`).
|
|
195
|
+
|
|
196
|
+
These apply everywhere the engine renders a form control.
|
|
197
|
+
|
|
198
|
+
#### Per render
|
|
199
|
+
|
|
200
|
+
The same four names are accepted as locals on the chart partial and as
|
|
201
|
+
options on `chord_chart_area` for a page that needs something other than
|
|
202
|
+
the application-wide setting:
|
|
203
|
+
|
|
204
|
+
```erb
|
|
205
|
+
<%= form.chord_chart_area :chord_sheet,
|
|
206
|
+
button_class: "btn-primary",
|
|
207
|
+
input_class: "form-control",
|
|
208
|
+
label_class: "form-label",
|
|
209
|
+
select_class: "form-select",
|
|
210
|
+
textarea_class: "form-control font-monospace" %>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
```erb
|
|
214
|
+
<%= render "outro_rails/chord_charts/chart",
|
|
215
|
+
chord_chart: @song.chord_sheet,
|
|
216
|
+
select_class: "form-select",
|
|
217
|
+
label_class: "form-label" %>
|
|
218
|
+
```
|
|
219
|
+
|
|
164
220
|
## Usage
|
|
165
221
|
To view the chord library and music theory tools, mount the engine in your
|
|
166
222
|
routes.rb:
|
|
@@ -258,6 +314,12 @@ When the model declares the chart with `required: false`, the fieldset is
|
|
|
258
314
|
labeled "Optional" and tells the user to leave the fields blank if there's
|
|
259
315
|
no chord chart.
|
|
260
316
|
|
|
317
|
+
The fields inside the fieldset use the engine's own control classes. Pass
|
|
318
|
+
`input_class:`, `textarea_class:`, `select_class:`, or `label_class:` to
|
|
319
|
+
render them with your app's classes for this form, or set them once
|
|
320
|
+
application-wide — see [Control classes](#control-classes). Any other
|
|
321
|
+
option is passed through to `fields_for`, as before.
|
|
322
|
+
|
|
261
323
|
### Controller: Permitting the Parameters
|
|
262
324
|
|
|
263
325
|
`chord_chart_area` submits the chart as nested attributes, so your
|
|
@@ -471,7 +533,6 @@ It seeds the chord library and four example songs (`spec/dummy/db/seeds.rb`).
|
|
|
471
533
|
The example songs are listed on the home page. To illustrate permissions,
|
|
472
534
|
the dummy app sets even record ids as editable and odd ones as view-only.
|
|
473
535
|
|
|
474
|
-
|
|
475
536
|
## Publishing a New Version
|
|
476
537
|
|
|
477
538
|
**1. Bump the version.** Edit `lib/outro_rails/version.rb`
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
from `currentColor`, so they adapt to light and dark host themes.
|
|
12
12
|
========================================================================== */
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
.outro-page {
|
|
14
|
+
:root {
|
|
16
15
|
--outro-container-width: 66rem;
|
|
17
16
|
--outro-radius: 14px;
|
|
18
17
|
--outro-radius-sm: 6px;
|
|
@@ -54,8 +53,7 @@
|
|
|
54
53
|
|
|
55
54
|
@supports not (color: color-mix(in srgb, currentColor 50%, transparent)) {
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
.outro-page {
|
|
56
|
+
:root {
|
|
59
57
|
--outro-muted: rgba(128, 128, 128, 0.9);
|
|
60
58
|
--outro-border: rgba(128, 128, 128, 0.3);
|
|
61
59
|
--outro-border-strong: rgba(128, 128, 128, 0.5);
|
|
@@ -129,8 +127,6 @@
|
|
|
129
127
|
align-items: center;
|
|
130
128
|
gap: 0.4rem;
|
|
131
129
|
min-width: 0;
|
|
132
|
-
align-items: center;
|
|
133
|
-
min-width: 0;
|
|
134
130
|
margin: 0;
|
|
135
131
|
padding: 0.3rem clamp(0.6rem, 2vw, 0.95rem);
|
|
136
132
|
border: 1px solid var(--outro-border);
|
|
@@ -307,21 +303,6 @@
|
|
|
307
303
|
font: inherit;
|
|
308
304
|
}
|
|
309
305
|
|
|
310
|
-
.outro-button {
|
|
311
|
-
display: inline-flex;
|
|
312
|
-
align-items: center;
|
|
313
|
-
gap: 0.45rem;
|
|
314
|
-
padding: 0.4rem 0.9rem;
|
|
315
|
-
border: 1px solid var(--outro-border-strong);
|
|
316
|
-
border-radius: var(--outro-radius-sm);
|
|
317
|
-
background-color: var(--outro-surface, transparent);
|
|
318
|
-
color: inherit;
|
|
319
|
-
font: inherit;
|
|
320
|
-
line-height: 1.2;
|
|
321
|
-
text-decoration: none;
|
|
322
|
-
cursor: pointer;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
306
|
.outro-card--link {
|
|
326
307
|
transition: transform 0.16s ease, box-shadow 0.16s ease,
|
|
327
308
|
border-color 0.16s ease;
|
|
@@ -415,13 +396,6 @@
|
|
|
415
396
|
}
|
|
416
397
|
}
|
|
417
398
|
|
|
418
|
-
.outro-panel {
|
|
419
|
-
padding: var(--outro-card-padding);
|
|
420
|
-
border: 1px solid var(--outro-border);
|
|
421
|
-
border-radius: var(--outro-radius);
|
|
422
|
-
background-color: var(--outro-surface, transparent);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
399
|
.outro-empty {
|
|
426
400
|
padding: clamp(1.25rem, 4vw, 2rem);
|
|
427
401
|
border: 1px dashed var(--outro-border-strong);
|
|
@@ -438,17 +412,6 @@
|
|
|
438
412
|
margin-bottom: 0;
|
|
439
413
|
}
|
|
440
414
|
|
|
441
|
-
.outro-select,
|
|
442
|
-
.outro-input,
|
|
443
|
-
.outro-textarea {
|
|
444
|
-
padding: var(--outro-control-padding);
|
|
445
|
-
border: 1px solid var(--outro-border-strong);
|
|
446
|
-
border-radius: var(--outro-radius-sm);
|
|
447
|
-
background-color: var(--outro-surface, transparent);
|
|
448
|
-
color: inherit;
|
|
449
|
-
font: inherit;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
415
|
.outro-button {
|
|
453
416
|
display: inline-flex;
|
|
454
417
|
align-items: center;
|
|
@@ -727,7 +690,6 @@
|
|
|
727
690
|
.outro-guitar {
|
|
728
691
|
display: flex;
|
|
729
692
|
flex-direction: column;
|
|
730
|
-
align-items: center;
|
|
731
693
|
gap: 14px;
|
|
732
694
|
width: 100%;
|
|
733
695
|
max-width: 100%;
|
|
@@ -735,7 +697,6 @@
|
|
|
735
697
|
border-radius: var(--outro-instrument-radius);
|
|
736
698
|
background-color: var(--outro-instrument-bg);
|
|
737
699
|
overflow-x: auto;
|
|
738
|
-
align-items: center;
|
|
739
700
|
align-items: safe center;
|
|
740
701
|
}
|
|
741
702
|
|
|
@@ -910,7 +871,6 @@
|
|
|
910
871
|
.outro-piano {
|
|
911
872
|
display: flex;
|
|
912
873
|
flex-direction: column;
|
|
913
|
-
align-items: center;
|
|
914
874
|
gap: 14px;
|
|
915
875
|
width: 100%;
|
|
916
876
|
max-width: 100%;
|
|
@@ -918,7 +878,6 @@
|
|
|
918
878
|
border-radius: var(--outro-instrument-radius);
|
|
919
879
|
background-color: var(--outro-instrument-bg);
|
|
920
880
|
overflow-x: auto;
|
|
921
|
-
align-items: center;
|
|
922
881
|
align-items: safe center;
|
|
923
882
|
}
|
|
924
883
|
|
|
@@ -1207,6 +1166,15 @@
|
|
|
1207
1166
|
position: relative;
|
|
1208
1167
|
}
|
|
1209
1168
|
|
|
1169
|
+
.outro-chord-chart-fields__legend {
|
|
1170
|
+
float: none;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
legend.outro-chord-chart-fields__legend {
|
|
1174
|
+
float: none;
|
|
1175
|
+
margin-bottom: 0;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1210
1178
|
.outro-chord-chart__body {
|
|
1211
1179
|
margin: 0;
|
|
1212
1180
|
padding: 0.85rem;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OutroRails
|
|
4
|
+
module ClassNamesHelper
|
|
5
|
+
def outro_button_class(*modifiers)
|
|
6
|
+
outro_element_class(:button, *modifiers)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def outro_input_class(*modifiers)
|
|
10
|
+
outro_element_class(:input, *modifiers)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def outro_label_class(*modifiers)
|
|
14
|
+
outro_element_class(:label, *modifiers)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def outro_select_class(*modifiers)
|
|
18
|
+
outro_element_class(:select, *modifiers)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def outro_textarea_class(*modifiers)
|
|
22
|
+
outro_element_class(:textarea, *modifiers)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def outro_element_class(element, *modifiers)
|
|
26
|
+
tokens = [ OutroRails.class_for(element), *modifiers ]
|
|
27
|
+
.flat_map { |token| token.to_s.split(/\s+/) }
|
|
28
|
+
.reject(&:empty?)
|
|
29
|
+
.uniq
|
|
30
|
+
|
|
31
|
+
tokens.join(" ").presence
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -16,27 +16,27 @@
|
|
|
16
16
|
<%= form_with url: caged_picker_path, method: :get,
|
|
17
17
|
class: "outro-picker" do %>
|
|
18
18
|
<label class="outro-picker__field">
|
|
19
|
-
|
|
19
|
+
<%= tag.span "Root", class: outro_label_class %>
|
|
20
20
|
<%= select_tag :root,
|
|
21
21
|
options_for_select(scale_root_options, @root.path_slug),
|
|
22
|
-
class:
|
|
22
|
+
class: outro_select_class,
|
|
23
23
|
onchange: "this.form.requestSubmit()" %>
|
|
24
24
|
</label>
|
|
25
25
|
|
|
26
26
|
<label class="outro-picker__field">
|
|
27
|
-
|
|
27
|
+
<%= tag.span "Shape", class: outro_label_class %>
|
|
28
28
|
<%= select_tag :shape,
|
|
29
29
|
options_for_select(
|
|
30
30
|
OutroRails::Instruments::Guitar::ChordShapes::CAGED_LETTERS
|
|
31
31
|
.map { |l| [ "#{l} shape", l.downcase ] },
|
|
32
32
|
@letter.downcase
|
|
33
33
|
),
|
|
34
|
-
class:
|
|
34
|
+
class: outro_select_class,
|
|
35
35
|
onchange: "this.form.requestSubmit()" %>
|
|
36
36
|
</label>
|
|
37
37
|
|
|
38
38
|
<%= button_tag type: :submit, name: nil,
|
|
39
|
-
class:
|
|
39
|
+
class: outro_button_class,
|
|
40
40
|
"aria-label": "Show Shapes" do %>
|
|
41
41
|
<%= image_tag "outro_rails/shapes.svg", class: 'outro-button__icon' %>
|
|
42
42
|
Show Shapes
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
] %>
|
|
15
15
|
|
|
16
16
|
<div class="outro-panel outro-filters">
|
|
17
|
-
|
|
17
|
+
<%= tag.span "Capo position", id: "capo-position-label",
|
|
18
|
+
class: outro_label_class %>
|
|
18
19
|
<nav class="outro-chip-row outro-capo-frets"
|
|
19
20
|
aria-labelledby="capo-position-label">
|
|
20
21
|
<% OutroRails::Instruments::Guitar::Capo::FRETS.each do |fret| %>
|
|
@@ -8,10 +8,7 @@
|
|
|
8
8
|
render "outro_rails/chord_charts/chart", chord_chart: @song.chord_sheet
|
|
9
9
|
|
|
10
10
|
Locals:
|
|
11
|
-
chord_chart - required, an OutroRails::ChordChart
|
|
12
|
-
optional `has_chord_chart ..., required: false` reader
|
|
13
|
-
returns before anyone fills it in) to render a short
|
|
14
|
-
"no chord chart" placeholder instead.
|
|
11
|
+
chord_chart - required, an OutroRails::ChordChart
|
|
15
12
|
instrument - "guitar" or "piano", default "guitar"
|
|
16
13
|
to_key - preview the chart transposed into this key, default none
|
|
17
14
|
editable - let the viewer change which voicing shows for each
|
|
@@ -22,277 +19,271 @@
|
|
|
22
19
|
|
|
23
20
|
%>
|
|
24
21
|
|
|
25
|
-
<%
|
|
22
|
+
<%
|
|
23
|
+
chord_chart = local_assigns.fetch(:chord_chart)
|
|
24
|
+
valid_instruments = chord_chart_instrument_options.map(&:last)
|
|
25
|
+
requested = local_assigns[:instrument]
|
|
26
|
+
instrument = valid_instruments.include?(requested) ? requested : "guitar"
|
|
27
|
+
to_key = local_assigns[:to_key].presence
|
|
28
|
+
editable = local_assigns[:editable] || false
|
|
29
|
+
transposed = to_key.present? && to_key != chord_chart.key
|
|
30
|
+
chords = chord_chart.display_chords(to_key: to_key)
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<% else %>
|
|
34
|
-
|
|
35
|
-
<%
|
|
36
|
-
valid_instruments = chord_chart_instrument_options.map(&:last)
|
|
37
|
-
requested = local_assigns[:instrument]
|
|
38
|
-
instrument = valid_instruments.include?(requested) ? requested : "guitar"
|
|
39
|
-
to_key = local_assigns[:to_key].presence
|
|
40
|
-
editable = local_assigns[:editable] || false
|
|
41
|
-
transposed = to_key.present? && to_key != chord_chart.key
|
|
42
|
-
chords = chord_chart.display_chords(to_key: to_key)
|
|
32
|
+
voicings = chords.to_h do |symbol, chord|
|
|
33
|
+
bass = OutroRails::Theory::Transposer.split_bass(symbol).last
|
|
34
|
+
[ symbol,
|
|
35
|
+
chord_chart.voicing_for(chord, instrument,
|
|
36
|
+
transposed: transposed, bass: bass) ]
|
|
37
|
+
end
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
editing = editable && !transposed
|
|
40
|
+
selections =
|
|
41
|
+
if editing
|
|
42
|
+
chord_chart.voicings.where(instrument: instrument)
|
|
43
|
+
.index_by { |s| [ s.chord_id, s.bass ] }
|
|
44
|
+
else
|
|
45
|
+
{}
|
|
49
46
|
end
|
|
47
|
+
%>
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
<%# The container is keyed by chart id so the voicing cycler's
|
|
50
|
+
fetch-based refresh (see outro_rails.js) can swap in the updated
|
|
51
|
+
chart from the redirected response without reloading the page. %>
|
|
52
|
+
<div class="outro-chord-chart" data-outro-chord-chart="<%= chord_chart.id %>">
|
|
53
|
+
<section class="outro-card">
|
|
54
|
+
<h2 class="outro-section-heading">
|
|
55
|
+
<%= chord_chart.song %>
|
|
56
|
+
<span class="outro-symbol-list__detail"><%= chord_chart.artist %></span>
|
|
57
|
+
</h2>
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<
|
|
64
|
-
<%= chord_chart.song %>
|
|
65
|
-
<span class="outro-symbol-list__detail"><%= chord_chart.artist %></span>
|
|
66
|
-
</h2>
|
|
59
|
+
<dl class="outro-spec">
|
|
60
|
+
<dt class="outro-spec__term">Tuning</dt>
|
|
61
|
+
<dd class="outro-spec__detail"><%= chord_chart.to_tuning.label %></dd>
|
|
67
62
|
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
<dt class="outro-spec__term">Capo</dt>
|
|
64
|
+
<dd class="outro-spec__detail">
|
|
65
|
+
<% if chord_chart.capo.present? %>
|
|
66
|
+
<%= capo_fret_label(chord_chart.capo) %>
|
|
67
|
+
<% else %>
|
|
68
|
+
None
|
|
69
|
+
<% end %>
|
|
70
|
+
</dd>
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
<dt class="outro-spec__term">Key</dt>
|
|
73
|
+
<dd class="outro-spec__detail">
|
|
74
|
+
<% if transposed %>
|
|
75
|
+
<%= to_key %>
|
|
76
|
+
<span class="outro-symbol-list__detail">
|
|
77
|
+
originally <%= chord_chart.key %>
|
|
78
|
+
</span>
|
|
79
|
+
<% else %>
|
|
80
|
+
<%= chord_chart.key %>
|
|
81
|
+
<% end %>
|
|
82
|
+
</dd>
|
|
83
|
+
</dl>
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
</dd>
|
|
92
|
-
</dl>
|
|
85
|
+
<div class="outro-picker outro-picker--flush">
|
|
86
|
+
<%= form_with url: request.path, method: :get,
|
|
87
|
+
class: "outro-picker__field" do %>
|
|
88
|
+
<span class="outro-label">Instrument</span>
|
|
89
|
+
<%= select_tag :instrument,
|
|
90
|
+
options_for_select(chord_chart_instrument_options, instrument),
|
|
91
|
+
class: outro_select_class,
|
|
92
|
+
onchange: "this.form.requestSubmit()" %>
|
|
93
|
+
<%= hidden_field_tag :to_key, to_key if to_key %>
|
|
94
|
+
<% end %>
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
<% end %>
|
|
96
|
+
<%= form_with url: request.path, method: :get,
|
|
97
|
+
class: "outro-picker__field" do %>
|
|
98
|
+
<span class="outro-label">Transpose to</span>
|
|
99
|
+
<%= select_tag :to_key,
|
|
100
|
+
grouped_options_for_select(chord_chart_key_options,
|
|
101
|
+
to_key || chord_chart.key),
|
|
102
|
+
class: outro_select_class,
|
|
103
|
+
onchange: "this.form.requestSubmit()" %>
|
|
104
|
+
<%= hidden_field_tag :instrument, instrument %>
|
|
105
|
+
<% end %>
|
|
105
106
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
<% if transposed %>
|
|
108
|
+
<%= link_to url_for(request.query_parameters.except("to_key")),
|
|
109
|
+
class: outro_button_class do %>
|
|
110
|
+
<%= image_tag "outro_rails/undo.svg",
|
|
111
|
+
class: "outro-button__icon" %>
|
|
112
|
+
<%= "Reset to #{chord_chart.key}" %>
|
|
113
|
+
<% end %>
|
|
114
|
+
<% end %>
|
|
115
|
+
</div>
|
|
116
|
+
</section>
|
|
117
|
+
|
|
118
|
+
<section class="outro-card">
|
|
119
|
+
<h2 class="outro-section-heading">Chart</h2>
|
|
120
|
+
<pre class="outro-chord-chart__body"><%=
|
|
121
|
+
chord_chart_body(chord_chart, to_key: to_key)
|
|
122
|
+
%></pre>
|
|
116
123
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
<%# Hover-popup figures, one per distinct chord in the body. <template>
|
|
125
|
+
contents are inert; outro_rails.js clones the matching one into a
|
|
126
|
+
floating popup when a chord in the chart text is hovered. %>
|
|
127
|
+
<% voicings.each do |symbol, voicing| %>
|
|
128
|
+
<% next unless voicing %>
|
|
129
|
+
<template data-outro-chord-popup="<%= symbol %>">
|
|
130
|
+
<p class="outro-chord-chart__popup-title"><%= voicing.symbol %></p>
|
|
131
|
+
<%= render "outro_rails/chord_voicings/figure", voicing: voicing %>
|
|
132
|
+
</template>
|
|
133
|
+
<% end %>
|
|
134
|
+
</section>
|
|
125
135
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
136
|
+
<section class="outro-card">
|
|
137
|
+
<h2 class="outro-section-heading">
|
|
138
|
+
Chords
|
|
139
|
+
<% if editing %>
|
|
140
|
+
<span class="outro-symbol-list__detail">
|
|
141
|
+
Use the arrows to browse each chord's voicings and pick
|
|
142
|
+
which one shows.
|
|
143
|
+
</span>
|
|
144
|
+
<% end %>
|
|
145
|
+
</h2>
|
|
132
146
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
147
|
+
<% if chords.any? %>
|
|
148
|
+
<ul class="outro-grid outro-grid--figures">
|
|
149
|
+
<% chords.each do |symbol, chord| %>
|
|
150
|
+
<% voicing = voicings[symbol] %>
|
|
151
|
+
<li class="outro-grid__item">
|
|
152
|
+
<div class="outro-card">
|
|
153
|
+
<h3 class="outro-section-heading">
|
|
154
|
+
<%= link_to symbol, outro_rails.chord_path(chord) %>
|
|
155
|
+
<% if voicing && voicing.symbol != symbol %>
|
|
156
|
+
<span class="outro-symbol-list__detail">
|
|
157
|
+
<%= voicing.symbol %> voicing
|
|
158
|
+
</span>
|
|
159
|
+
<% end %>
|
|
160
|
+
</h3>
|
|
141
161
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
162
|
+
<% if !voicing %>
|
|
163
|
+
<div class="outro-empty">
|
|
164
|
+
<p>No <%= instrument %> voicing yet.</p>
|
|
165
|
+
</div>
|
|
166
|
+
<% elsif editing %>
|
|
167
|
+
<%
|
|
168
|
+
bass = OutroRails::Theory::Transposer
|
|
169
|
+
.split_bass(symbol).last
|
|
170
|
+
all_voicings = chord.voicings
|
|
171
|
+
.where(instrument: instrument)
|
|
172
|
+
.order(:position).to_a
|
|
173
|
+
normalized = OutroRails::ChordChart::Voicing
|
|
174
|
+
.normalize_bass(bass)
|
|
175
|
+
selection = selections[[ chord.id, normalized ]]
|
|
176
|
+
default_voicing =
|
|
177
|
+
chord_chart.default_voicing_for(chord, instrument,
|
|
178
|
+
bass: bass)
|
|
152
179
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
<%= link_to symbol, outro_rails.chord_path(chord) %>
|
|
161
|
-
<% if voicing && voicing.symbol != symbol %>
|
|
162
|
-
<span class="outro-symbol-list__detail">
|
|
163
|
-
<%= voicing.symbol %> voicing
|
|
164
|
-
</span>
|
|
165
|
-
<% end %>
|
|
166
|
-
</h3>
|
|
180
|
+
form_params = {
|
|
181
|
+
chord_id: chord.id,
|
|
182
|
+
instrument: instrument,
|
|
183
|
+
bass: bass,
|
|
184
|
+
return_to: request.fullpath
|
|
185
|
+
}
|
|
186
|
+
%>
|
|
167
187
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
188
|
+
<div class="outro-voicing-cycler" data-outro-voicing-cycler>
|
|
189
|
+
<% if all_voicings.many? %>
|
|
190
|
+
<div class="outro-voicing-cycler__nav">
|
|
191
|
+
<button type="button" data-voicing-prev
|
|
192
|
+
class="<%= outro_button_class %>
|
|
193
|
+
outro-voicing-cycler__arrow"
|
|
194
|
+
aria-label=
|
|
195
|
+
"Previous voicing for <%= symbol %>">
|
|
196
|
+
◀
|
|
197
|
+
</button>
|
|
198
|
+
<span class="outro-voicing-cycler__counter"
|
|
199
|
+
data-voicing-counter aria-live="polite"></span>
|
|
200
|
+
<button type="button" data-voicing-next
|
|
201
|
+
class="<%= outro_button_class %>
|
|
202
|
+
outro-voicing-cycler__arrow"
|
|
203
|
+
aria-label=
|
|
204
|
+
"Next voicing for <%= symbol %>">
|
|
205
|
+
▶
|
|
206
|
+
</button>
|
|
171
207
|
</div>
|
|
172
|
-
<%
|
|
173
|
-
<%
|
|
174
|
-
bass = OutroRails::Theory::Transposer
|
|
175
|
-
.split_bass(symbol).last
|
|
176
|
-
all_voicings = chord.voicings
|
|
177
|
-
.where(instrument: instrument)
|
|
178
|
-
.order(:position).to_a
|
|
179
|
-
normalized = OutroRails::ChordChart::Voicing
|
|
180
|
-
.normalize_bass(bass)
|
|
181
|
-
selection = selections[[ chord.id, normalized ]]
|
|
182
|
-
default_voicing =
|
|
183
|
-
chord_chart.default_voicing_for(chord, instrument,
|
|
184
|
-
bass: bass)
|
|
208
|
+
<% end %>
|
|
185
209
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
210
|
+
<% all_voicings.each do |candidate| %>
|
|
211
|
+
<%
|
|
212
|
+
showing = candidate.id == voicing.id
|
|
213
|
+
is_pick = selection&.chord_voicing_id == candidate.id
|
|
214
|
+
is_default = default_voicing&.id == candidate.id
|
|
215
|
+
caption = "#{candidate.symbol} - " \
|
|
216
|
+
"position #{candidate.position}"
|
|
192
217
|
%>
|
|
218
|
+
<div class="outro-voicing-cycler__slide"
|
|
219
|
+
data-voicing-slide
|
|
220
|
+
<%= "hidden" unless showing %>>
|
|
221
|
+
<p class="outro-spec__detail">
|
|
222
|
+
<%= render "outro_rails/chord_voicings/figure",
|
|
223
|
+
voicing: candidate,
|
|
224
|
+
caption: caption %>
|
|
193
225
|
|
|
194
|
-
|
|
195
|
-
<% if all_voicings.many? %>
|
|
196
|
-
<div class="outro-voicing-cycler__nav">
|
|
197
|
-
<button type="button" data-voicing-prev
|
|
198
|
-
class="outro-button
|
|
199
|
-
outro-voicing-cycler__arrow"
|
|
200
|
-
aria-label=
|
|
201
|
-
"Previous voicing for <%= symbol %>">
|
|
202
|
-
◀
|
|
203
|
-
</button>
|
|
204
|
-
<span class="outro-voicing-cycler__counter"
|
|
205
|
-
data-voicing-counter aria-live="polite"></span>
|
|
206
|
-
<button type="button" data-voicing-next
|
|
207
|
-
class="outro-button
|
|
208
|
-
outro-voicing-cycler__arrow"
|
|
209
|
-
aria-label=
|
|
210
|
-
"Next voicing for <%= symbol %>">
|
|
211
|
-
▶
|
|
212
|
-
</button>
|
|
213
|
-
</div>
|
|
214
|
-
<% end %>
|
|
226
|
+
</p>
|
|
215
227
|
|
|
216
|
-
<%
|
|
228
|
+
<% if is_default && selection %>
|
|
229
|
+
<%# Not currently on the default: navigating here
|
|
230
|
+
offers the revert, same as the pick's slide. %>
|
|
217
231
|
<%
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
caption = "#{candidate.symbol} - " \
|
|
222
|
-
"position #{candidate.position}"
|
|
232
|
+
revert_path = outro_rails.chord_chart_voicing_path(
|
|
233
|
+
chord_chart, selection, **form_params
|
|
234
|
+
)
|
|
223
235
|
%>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
form_class: "outro-inline-form" do %>
|
|
260
|
-
<%= image_tag "outro_rails/check.svg",
|
|
261
|
-
class: "outro-button__icon" %>
|
|
262
|
-
Select Voicing
|
|
263
|
-
<% end %>
|
|
264
|
-
<% elsif is_pick %>
|
|
265
|
-
<%
|
|
266
|
-
revert_path = outro_rails.chord_chart_voicing_path(
|
|
267
|
-
chord_chart, selection, **form_params
|
|
268
|
-
)
|
|
269
|
-
%>
|
|
270
|
-
<%= button_to revert_path,
|
|
271
|
-
method: :delete, class: "outro-button",
|
|
272
|
-
form_class: "outro-inline-form" do %>
|
|
273
|
-
<%= image_tag "outro_rails/undo.svg",
|
|
274
|
-
class: "outro-button__icon" %>
|
|
275
|
-
Revert to default
|
|
276
|
-
<% end %>
|
|
277
|
-
<% end %>
|
|
278
|
-
</div>
|
|
236
|
+
<%= button_to revert_path,
|
|
237
|
+
method: :delete, class: outro_button_class,
|
|
238
|
+
form_class: "outro-inline-form" do %>
|
|
239
|
+
<%= image_tag "outro_rails/undo.svg",
|
|
240
|
+
class: "outro-button__icon" %>
|
|
241
|
+
Revert to default
|
|
242
|
+
<% end %>
|
|
243
|
+
<% elsif !showing %>
|
|
244
|
+
<%
|
|
245
|
+
pick_path = outro_rails.chord_chart_voicings_path(
|
|
246
|
+
chord_chart, **form_params
|
|
247
|
+
)
|
|
248
|
+
%>
|
|
249
|
+
<%= button_to pick_path,
|
|
250
|
+
method: :post,
|
|
251
|
+
params: { chord_voicing_id: candidate.id },
|
|
252
|
+
class: "outro-button",
|
|
253
|
+
form_class: "outro-inline-form" do %>
|
|
254
|
+
<%= image_tag "outro_rails/check.svg",
|
|
255
|
+
class: "outro-button__icon" %>
|
|
256
|
+
Select Voicing
|
|
257
|
+
<% end %>
|
|
258
|
+
<% elsif is_pick %>
|
|
259
|
+
<%
|
|
260
|
+
revert_path = outro_rails.chord_chart_voicing_path(
|
|
261
|
+
chord_chart, selection, **form_params
|
|
262
|
+
)
|
|
263
|
+
%>
|
|
264
|
+
<%= button_to revert_path,
|
|
265
|
+
method: :delete, class: outro_button_class,
|
|
266
|
+
form_class: "outro-inline-form" do %>
|
|
267
|
+
<%= image_tag "outro_rails/undo.svg",
|
|
268
|
+
class: "outro-button__icon" %>
|
|
269
|
+
Revert to default
|
|
270
|
+
<% end %>
|
|
279
271
|
<% end %>
|
|
280
272
|
</div>
|
|
281
|
-
<% else %>
|
|
282
|
-
<%= render "outro_rails/chord_voicings/figure",
|
|
283
|
-
voicing: voicing %>
|
|
284
273
|
<% end %>
|
|
285
274
|
</div>
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
</div>
|
|
275
|
+
<% else %>
|
|
276
|
+
<%= render "outro_rails/chord_voicings/figure",
|
|
277
|
+
voicing: voicing %>
|
|
278
|
+
<% end %>
|
|
279
|
+
</div>
|
|
280
|
+
</li>
|
|
293
281
|
<% end %>
|
|
294
|
-
</
|
|
282
|
+
</ul>
|
|
283
|
+
<% else %>
|
|
284
|
+
<div class="outro-empty">
|
|
285
|
+
<p>No recognized chords yet.</p>
|
|
286
|
+
</div>
|
|
295
287
|
<% end %>
|
|
296
|
-
</
|
|
297
|
-
|
|
298
|
-
<% end %>
|
|
288
|
+
</section>
|
|
289
|
+
</div>
|
|
@@ -44,40 +44,41 @@
|
|
|
44
44
|
|
|
45
45
|
<div class="outro-picker outro-picker--grid outro-picker--cols-2">
|
|
46
46
|
<label class="outro-picker__field">
|
|
47
|
-
|
|
48
|
-
<%= f.text_field :artist, class:
|
|
47
|
+
<%= tag.span "Artist", class: outro_label_class %>
|
|
48
|
+
<%= f.text_field :artist, class: outro_input_class %>
|
|
49
49
|
</label>
|
|
50
50
|
|
|
51
51
|
<label class="outro-picker__field">
|
|
52
|
-
|
|
53
|
-
<%= f.text_field :song, class:
|
|
52
|
+
<%= tag.span "Song", class: outro_label_class %>
|
|
53
|
+
<%= f.text_field :song, class: outro_input_class %>
|
|
54
54
|
</label>
|
|
55
55
|
</div>
|
|
56
56
|
|
|
57
57
|
<div class="outro-picker outro-picker--grid outro-picker--cols-3">
|
|
58
58
|
<label class="outro-picker__field">
|
|
59
|
-
|
|
59
|
+
<%= tag.span "Tuning", class: outro_label_class %>
|
|
60
60
|
<%= f.select :tuning, chord_chart_tuning_options, {},
|
|
61
|
-
class:
|
|
61
|
+
class: outro_select_class %>
|
|
62
62
|
</label>
|
|
63
63
|
|
|
64
64
|
<label class="outro-picker__field">
|
|
65
|
-
|
|
65
|
+
<%= tag.span "Capo", class: outro_label_class %>
|
|
66
66
|
<%= f.select :capo, chord_chart_capo_options,
|
|
67
|
-
{ include_blank: "None" }, class:
|
|
67
|
+
{ include_blank: "None" }, class: outro_select_class %>
|
|
68
68
|
</label>
|
|
69
69
|
|
|
70
70
|
<label class="outro-picker__field">
|
|
71
|
-
|
|
72
|
-
<%= f.select :key, chord_chart_key_options, {},
|
|
71
|
+
<%= tag.span "Key", class: outro_label_class %>
|
|
72
|
+
<%= f.select :key, chord_chart_key_options, {},
|
|
73
|
+
class: outro_select_class %>
|
|
73
74
|
</label>
|
|
74
75
|
</div>
|
|
75
76
|
|
|
76
77
|
<label class="outro-transposer__field">
|
|
77
|
-
|
|
78
|
+
<%= tag.span "Chords & lyrics (Optional)", class: outro_label_class %>
|
|
78
79
|
<%= f.text_area :body,
|
|
79
80
|
rows: 16,
|
|
80
81
|
placeholder: "Paste or type a chord chart here.",
|
|
81
|
-
class: "outro-
|
|
82
|
+
class: outro_textarea_class("outro-transposer__textarea") %>
|
|
82
83
|
</label>
|
|
83
84
|
</fieldset>
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
<%= search_field_tag :q, params[:missing],
|
|
6
6
|
placeholder: "F#m7b5 or fsharpm7flat5",
|
|
7
7
|
"aria-label": "Go to chord by symbol or slug",
|
|
8
|
-
class: "outro-
|
|
8
|
+
class: outro_input_class("outro-filters__search-input") %>
|
|
9
9
|
<%= button_tag type: :submit, name: nil,
|
|
10
|
-
class:
|
|
10
|
+
class: outro_button_class,
|
|
11
11
|
"aria-label": "Search" do %>
|
|
12
12
|
<%= image_tag "outro_rails/search.svg", class: 'outro-button__icon' %>
|
|
13
13
|
Search
|
|
@@ -18,52 +18,52 @@
|
|
|
18
18
|
<%= form_with url: chords_path, method: :get,
|
|
19
19
|
class: "outro-picker outro-filters__facets" do %>
|
|
20
20
|
<label class="outro-picker__field">
|
|
21
|
-
|
|
21
|
+
<%= tag.span "Root", class: outro_label_class %>
|
|
22
22
|
<%= select_tag :root,
|
|
23
23
|
options_for_select(chord_root_options, @filters[:root]),
|
|
24
24
|
include_blank: "Any",
|
|
25
|
-
class:
|
|
25
|
+
class: outro_select_class,
|
|
26
26
|
onchange: "this.form.requestSubmit()" %>
|
|
27
27
|
</label>
|
|
28
28
|
|
|
29
29
|
<label class="outro-picker__field">
|
|
30
|
-
|
|
30
|
+
<%= tag.span "Quality", class: outro_label_class %>
|
|
31
31
|
<%= select_tag :quality,
|
|
32
32
|
options_for_select(chord_quality_options, @filters[:quality]),
|
|
33
33
|
include_blank: "Any",
|
|
34
|
-
class:
|
|
34
|
+
class: outro_select_class,
|
|
35
35
|
onchange: "this.form.requestSubmit()" %>
|
|
36
36
|
</label>
|
|
37
37
|
|
|
38
38
|
<label class="outro-picker__field">
|
|
39
|
-
|
|
39
|
+
<%= tag.span "Extension", class: outro_label_class %>
|
|
40
40
|
<%= select_tag :extension,
|
|
41
41
|
options_for_select(chord_extension_options, @filters[:extension]),
|
|
42
42
|
include_blank: "Any",
|
|
43
|
-
class:
|
|
43
|
+
class: outro_select_class,
|
|
44
44
|
onchange: "this.form.requestSubmit()" %>
|
|
45
45
|
</label>
|
|
46
46
|
|
|
47
47
|
<label class="outro-picker__field">
|
|
48
|
-
|
|
48
|
+
<%= tag.span "Alteration", class: outro_label_class %>
|
|
49
49
|
<%= select_tag :alteration,
|
|
50
50
|
options_for_select(chord_alteration_options, @filters[:alteration]),
|
|
51
51
|
include_blank: "Any",
|
|
52
|
-
class:
|
|
52
|
+
class: outro_select_class,
|
|
53
53
|
onchange: "this.form.requestSubmit()" %>
|
|
54
54
|
</label>
|
|
55
55
|
|
|
56
56
|
<label class="outro-picker__field">
|
|
57
|
-
|
|
57
|
+
<%= tag.span "Added tone", class: outro_label_class %>
|
|
58
58
|
<%= select_tag :added_tone,
|
|
59
59
|
options_for_select(chord_added_tone_options, @filters[:added_tone]),
|
|
60
60
|
include_blank: "Any",
|
|
61
|
-
class:
|
|
61
|
+
class: outro_select_class,
|
|
62
62
|
onchange: "this.form.requestSubmit()" %>
|
|
63
63
|
</label>
|
|
64
64
|
|
|
65
65
|
<%= button_tag type: :submit, name: nil,
|
|
66
|
-
class:
|
|
66
|
+
class: outro_button_class,
|
|
67
67
|
"aria-label": "Filter" do %>
|
|
68
68
|
<%= image_tag "outro_rails/filter.svg", class: 'outro-button__icon' %>
|
|
69
69
|
Filter
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
|
|
72
72
|
<% if filters_active? %>
|
|
73
73
|
<%= link_to chords_path,
|
|
74
|
-
class:
|
|
74
|
+
class: outro_button_class,
|
|
75
75
|
"aria-label": "Clear" do %>
|
|
76
76
|
<%= image_tag "outro_rails/clear.svg", class: 'outro-button__icon' %>
|
|
77
77
|
Clear
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<div class="outro-empty">
|
|
20
20
|
<p>No chords match those filters.</p>
|
|
21
21
|
<%= link_to chords_path,
|
|
22
|
-
class:
|
|
22
|
+
class: outro_button_class,
|
|
23
23
|
"aria-label": "Clear Filters" do %>
|
|
24
24
|
<%= image_tag "outro_rails/clear.svg", class: 'outro-button__icon' %>
|
|
25
25
|
Clear Filters
|
|
@@ -63,9 +63,8 @@
|
|
|
63
63
|
</dl>
|
|
64
64
|
|
|
65
65
|
<div class="outro-card__footer">
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
</span>
|
|
66
|
+
<%= tag.span "See this scale on", id: "scale-instruments-label",
|
|
67
|
+
class: outro_label_class %>
|
|
69
68
|
<div class="outro-chip-row" role="group"
|
|
70
69
|
aria-labelledby="scale-instruments-label">
|
|
71
70
|
<% OutroRails::ScalesController::INSTRUMENTS.each do |instrument| %>
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
<%= hidden_field_tag :instrument, @instrument %>
|
|
13
13
|
|
|
14
14
|
<label class="outro-picker__field">
|
|
15
|
-
|
|
15
|
+
<%= tag.span "Tuning", class: outro_label_class %>
|
|
16
16
|
<%= select_tag :tuning,
|
|
17
17
|
options_for_select(guitar_tuning_options, tuning.slug),
|
|
18
|
-
class:
|
|
18
|
+
class: outro_select_class,
|
|
19
19
|
onchange: "this.form.requestSubmit()" %>
|
|
20
20
|
</label>
|
|
21
21
|
|
|
22
22
|
<%# Fallback for keyboard users / no JS; the select auto-submits
|
|
23
23
|
on change. %>
|
|
24
24
|
<%= button_tag type: :submit, name: nil,
|
|
25
|
-
class:
|
|
25
|
+
class: outro_button_class,
|
|
26
26
|
"aria-label": "Show Tuning" do %>
|
|
27
27
|
<%= image_tag "outro_rails/guitar.svg", class: 'outro-button__icon' %>
|
|
28
28
|
Show Tuning
|
|
@@ -3,33 +3,33 @@
|
|
|
3
3
|
<%= hidden_field_tag :instrument, @instrument %>
|
|
4
4
|
|
|
5
5
|
<label class="outro-picker__field">
|
|
6
|
-
|
|
6
|
+
<%= tag.span "Root", class: outro_label_class %>
|
|
7
7
|
<%= select_tag :root,
|
|
8
8
|
options_for_select(scale_root_options, @scale.root.path_slug),
|
|
9
|
-
class:
|
|
9
|
+
class: outro_select_class,
|
|
10
10
|
onchange: "this.form.requestSubmit()" %>
|
|
11
11
|
</label>
|
|
12
12
|
|
|
13
13
|
<label class="outro-picker__field">
|
|
14
|
-
|
|
14
|
+
<%= tag.span "Scale", class: outro_label_class %>
|
|
15
15
|
<%= select_tag :type,
|
|
16
16
|
options_for_select(scale_type_options, @scale.slug),
|
|
17
|
-
class:
|
|
17
|
+
class: outro_select_class,
|
|
18
18
|
onchange: "this.form.requestSubmit()" %>
|
|
19
19
|
</label>
|
|
20
20
|
|
|
21
21
|
<% if @instrument == "guitar" %>
|
|
22
22
|
<label class="outro-picker__field">
|
|
23
|
-
|
|
23
|
+
<%= tag.span "Tuning", class: outro_label_class %>
|
|
24
24
|
<%= select_tag :tuning,
|
|
25
25
|
options_for_select(guitar_tuning_options, @tuning&.slug),
|
|
26
|
-
class:
|
|
26
|
+
class: outro_select_class,
|
|
27
27
|
onchange: "this.form.requestSubmit()" %>
|
|
28
28
|
</label>
|
|
29
29
|
<% end %>
|
|
30
30
|
|
|
31
31
|
<%= button_tag type: :submit, name: nil,
|
|
32
|
-
class:
|
|
32
|
+
class: outro_button_class,
|
|
33
33
|
"aria-label": "Show Scale" do %>
|
|
34
34
|
<%= image_tag "outro_rails/scales.svg", class: 'outro-button__icon' %>
|
|
35
35
|
Show Scale
|
|
@@ -77,9 +77,8 @@
|
|
|
77
77
|
<% others = OutroRails::ScalesController::INSTRUMENTS - [ @instrument ] %>
|
|
78
78
|
<% if others.any? %>
|
|
79
79
|
<div class="outro-switch">
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
</span>
|
|
80
|
+
<%= tag.span "View this scale on", id: "scale-switch-label",
|
|
81
|
+
class: outro_label_class %>
|
|
83
82
|
<div class="outro-chip-row" role="group"
|
|
84
83
|
aria-labelledby="scale-switch-label">
|
|
85
84
|
<% others.each do |other| %>
|
|
@@ -21,39 +21,39 @@
|
|
|
21
21
|
class: "outro-transposer" do %>
|
|
22
22
|
<div class="outro-picker outro-picker--flush">
|
|
23
23
|
<label class="outro-picker__field">
|
|
24
|
-
|
|
24
|
+
<%= tag.span "Convert", class: outro_label_class %>
|
|
25
25
|
<%= select_tag :mode,
|
|
26
26
|
options_for_select(transposer_mode_options, @mode),
|
|
27
|
-
class:
|
|
27
|
+
class: outro_select_class %>
|
|
28
28
|
</label>
|
|
29
29
|
|
|
30
30
|
<label class="outro-picker__field">
|
|
31
|
-
|
|
31
|
+
<%= tag.span "Original key", class: outro_label_class %>
|
|
32
32
|
<%= select_tag :from_key,
|
|
33
33
|
grouped_options_for_select(transposer_key_options,
|
|
34
34
|
@from_key.to_s),
|
|
35
|
-
class:
|
|
35
|
+
class: outro_select_class %>
|
|
36
36
|
</label>
|
|
37
37
|
|
|
38
38
|
<label class="outro-picker__field">
|
|
39
|
-
|
|
39
|
+
<%= tag.span "New key", class: outro_label_class %>
|
|
40
40
|
<%= select_tag :to_key,
|
|
41
41
|
grouped_options_for_select(transposer_key_options,
|
|
42
42
|
@to_key.to_s),
|
|
43
|
-
class:
|
|
43
|
+
class: outro_select_class %>
|
|
44
44
|
</label>
|
|
45
45
|
</div>
|
|
46
46
|
|
|
47
47
|
<label class="outro-transposer__field">
|
|
48
|
-
|
|
48
|
+
<%= tag.span "Chords and lyrics", class: outro_label_class %>
|
|
49
49
|
<%= text_area_tag :text, @text,
|
|
50
50
|
rows: 8,
|
|
51
51
|
placeholder: "Paste a chord chart here.",
|
|
52
|
-
class: "outro-
|
|
52
|
+
class: outro_textarea_class("outro-transposer__textarea") %>
|
|
53
53
|
</label>
|
|
54
54
|
|
|
55
55
|
<%= button_tag type: :submit, name: nil,
|
|
56
|
-
class:
|
|
56
|
+
class: outro_button_class,
|
|
57
57
|
"aria-label": "Transpose" do %>
|
|
58
58
|
<%= image_tag "outro_rails/transposer.svg",
|
|
59
59
|
class: 'outro-button__icon' %>
|
data/lib/outro_rails/version.rb
CHANGED
data/lib/outro_rails.rb
CHANGED
|
@@ -18,4 +18,35 @@ module OutroRails
|
|
|
18
18
|
!!chord_chart_voicing_authorization.call(chord_chart: chord_chart,
|
|
19
19
|
controller: controller)
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
ELEMENT_CLASS_DEFAULTS = {
|
|
23
|
+
button: "outro-button",
|
|
24
|
+
input: "outro-input",
|
|
25
|
+
label: "outro-label",
|
|
26
|
+
select: "outro-select",
|
|
27
|
+
textarea: "outro-textarea"
|
|
28
|
+
}.freeze
|
|
29
|
+
|
|
30
|
+
mattr_accessor :button_class, default: ELEMENT_CLASS_DEFAULTS[:button]
|
|
31
|
+
mattr_accessor :input_class, default: ELEMENT_CLASS_DEFAULTS[:input]
|
|
32
|
+
mattr_accessor :label_class, default: ELEMENT_CLASS_DEFAULTS[:label]
|
|
33
|
+
mattr_accessor :select_class, default: ELEMENT_CLASS_DEFAULTS[:select]
|
|
34
|
+
mattr_accessor :textarea_class, default: ELEMENT_CLASS_DEFAULTS[:textarea]
|
|
35
|
+
|
|
36
|
+
def self.configure
|
|
37
|
+
yield self
|
|
38
|
+
self
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.class_for(element)
|
|
42
|
+
key = element.to_sym
|
|
43
|
+
|
|
44
|
+
unless ELEMENT_CLASS_DEFAULTS.key?(key)
|
|
45
|
+
raise ArgumentError,
|
|
46
|
+
"unknown element #{element.inspect}; expected one of " \
|
|
47
|
+
"#{ELEMENT_CLASS_DEFAULTS.keys.map(&:inspect).join(', ')}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
public_send(:"#{key}_class")
|
|
51
|
+
end
|
|
21
52
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: outro_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- endtoendpaper
|
|
@@ -79,6 +79,7 @@ files:
|
|
|
79
79
|
- app/helpers/outro_rails/chord_charts_helper.rb
|
|
80
80
|
- app/helpers/outro_rails/chords_helper.rb
|
|
81
81
|
- app/helpers/outro_rails/circle_of_fifths_helper.rb
|
|
82
|
+
- app/helpers/outro_rails/class_names_helper.rb
|
|
82
83
|
- app/helpers/outro_rails/instruments_helper.rb
|
|
83
84
|
- app/helpers/outro_rails/scales_helper.rb
|
|
84
85
|
- app/helpers/outro_rails/transposer_helper.rb
|