outro_rails 0.1.5 → 0.1.7
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 +13 -44
- 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: 3985ee600ea177ac1e876651e79887b853620e683a0debfc4bdd24dc234961d6
|
|
4
|
+
data.tar.gz: 858928155568c2b92979dfeae2d84f7f679373a1d0010e16b92e5676a06b20dd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 343d939032844096a9b8440f52936f79d4214a1c55ad132124b3f87e830d27bdbe730d851a3244eba6bbe50e0a34be31dc3ceedfd9d1b01dac1d92eb9b41dd89
|
|
7
|
+
data.tar.gz: 40380f523dc037dde65c1e20d7acc41769a79727cf219c2fbe6e8e8df5b076654450eca28733e32e377db19ce8568b1886fb309357ebba45c1b4bb590bddc5fd
|
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;
|
|
@@ -37,6 +36,7 @@
|
|
|
37
36
|
--outro-focus-ring: #7ab0ff;
|
|
38
37
|
--outro-instrument-bg: #222222;
|
|
39
38
|
--outro-instrument-radius: 12px;
|
|
39
|
+
--outro-field-gap: 0.25rem;
|
|
40
40
|
--outro-fretboard: linear-gradient(180deg, #4a3222, #3a2718);
|
|
41
41
|
--outro-fretboard-edge: #2c1f14;
|
|
42
42
|
--outro-fretboard-ink: #d8c9b8;
|
|
@@ -54,8 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
@supports not (color: color-mix(in srgb, currentColor 50%, transparent)) {
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
.outro-page {
|
|
57
|
+
:root {
|
|
59
58
|
--outro-muted: rgba(128, 128, 128, 0.9);
|
|
60
59
|
--outro-border: rgba(128, 128, 128, 0.3);
|
|
61
60
|
--outro-border-strong: rgba(128, 128, 128, 0.5);
|
|
@@ -129,8 +128,6 @@
|
|
|
129
128
|
align-items: center;
|
|
130
129
|
gap: 0.4rem;
|
|
131
130
|
min-width: 0;
|
|
132
|
-
align-items: center;
|
|
133
|
-
min-width: 0;
|
|
134
131
|
margin: 0;
|
|
135
132
|
padding: 0.3rem clamp(0.6rem, 2vw, 0.95rem);
|
|
136
133
|
border: 1px solid var(--outro-border);
|
|
@@ -307,21 +304,6 @@
|
|
|
307
304
|
font: inherit;
|
|
308
305
|
}
|
|
309
306
|
|
|
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
307
|
.outro-card--link {
|
|
326
308
|
transition: transform 0.16s ease, box-shadow 0.16s ease,
|
|
327
309
|
border-color 0.16s ease;
|
|
@@ -415,13 +397,6 @@
|
|
|
415
397
|
}
|
|
416
398
|
}
|
|
417
399
|
|
|
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
400
|
.outro-empty {
|
|
426
401
|
padding: clamp(1.25rem, 4vw, 2rem);
|
|
427
402
|
border: 1px dashed var(--outro-border-strong);
|
|
@@ -438,17 +413,6 @@
|
|
|
438
413
|
margin-bottom: 0;
|
|
439
414
|
}
|
|
440
415
|
|
|
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
416
|
.outro-button {
|
|
453
417
|
display: inline-flex;
|
|
454
418
|
align-items: center;
|
|
@@ -494,7 +458,7 @@
|
|
|
494
458
|
.outro-picker__field {
|
|
495
459
|
display: flex;
|
|
496
460
|
flex-direction: column;
|
|
497
|
-
gap:
|
|
461
|
+
gap: var(--outro-field-gap);
|
|
498
462
|
}
|
|
499
463
|
|
|
500
464
|
.outro-picker__field .outro-select {
|
|
@@ -727,7 +691,6 @@
|
|
|
727
691
|
.outro-guitar {
|
|
728
692
|
display: flex;
|
|
729
693
|
flex-direction: column;
|
|
730
|
-
align-items: center;
|
|
731
694
|
gap: 14px;
|
|
732
695
|
width: 100%;
|
|
733
696
|
max-width: 100%;
|
|
@@ -735,7 +698,6 @@
|
|
|
735
698
|
border-radius: var(--outro-instrument-radius);
|
|
736
699
|
background-color: var(--outro-instrument-bg);
|
|
737
700
|
overflow-x: auto;
|
|
738
|
-
align-items: center;
|
|
739
701
|
align-items: safe center;
|
|
740
702
|
}
|
|
741
703
|
|
|
@@ -910,7 +872,6 @@
|
|
|
910
872
|
.outro-piano {
|
|
911
873
|
display: flex;
|
|
912
874
|
flex-direction: column;
|
|
913
|
-
align-items: center;
|
|
914
875
|
gap: 14px;
|
|
915
876
|
width: 100%;
|
|
916
877
|
max-width: 100%;
|
|
@@ -918,7 +879,6 @@
|
|
|
918
879
|
border-radius: var(--outro-instrument-radius);
|
|
919
880
|
background-color: var(--outro-instrument-bg);
|
|
920
881
|
overflow-x: auto;
|
|
921
|
-
align-items: center;
|
|
922
882
|
align-items: safe center;
|
|
923
883
|
}
|
|
924
884
|
|
|
@@ -1207,6 +1167,15 @@
|
|
|
1207
1167
|
position: relative;
|
|
1208
1168
|
}
|
|
1209
1169
|
|
|
1170
|
+
.outro-chord-chart-fields__legend {
|
|
1171
|
+
float: none;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
legend.outro-chord-chart-fields__legend {
|
|
1175
|
+
float: none;
|
|
1176
|
+
margin-bottom: 0;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1210
1179
|
.outro-chord-chart__body {
|
|
1211
1180
|
margin: 0;
|
|
1212
1181
|
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.7
|
|
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
|