effective_bootstrap 0.9.19 → 0.9.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/effective_bootstrap.js +1 -0
- data/app/assets/javascripts/effective_bootstrap/form.js.coffee +7 -1
- data/app/assets/javascripts/effective_has_many/initialize.js.coffee +2 -2
- data/app/assets/javascripts/effective_rich_text_area/extensions.js +171 -0
- data/app/assets/javascripts/effective_rich_text_area/initialize.js +20 -0
- data/app/assets/javascripts/effective_rich_text_area/input.js +2 -0
- data/app/assets/stylesheets/effective_rich_text_area/extensions.scss +90 -0
- data/app/assets/stylesheets/effective_rich_text_area/input.scss +2 -25
- data/app/assets/stylesheets/effective_rich_text_area/rich_text_area.scss +30 -0
- data/app/helpers/effective_bootstrap_helper.rb +26 -1
- data/app/models/effective/form_inputs/has_many.rb +1 -1
- data/app/views/action_text/attachables/_content_attachment.html.erb +3 -0
- data/app/views/action_text/attachables/content_attachments/_horizontal_rule.html.erb +1 -0
- data/lib/effective_bootstrap/engine.rb +6 -0
- data/lib/effective_bootstrap/version.rb +1 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e3b9c4a0be1d9efbe01b7cc9d4fbd40cc9c2b5be9b069e4ed38603bdf650316
|
4
|
+
data.tar.gz: 013a278ce24f5a45c44be26d57943ae5c263a97182175964b47adb6ad8705fc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8be225273013f47a0cb79e8d5849d494c13005393db8128bbe935b7f3c9d3d35b1b1d430239770f97bdb13b4e109386996c8c99a0e0b167c5160daaaff1cbc57
|
7
|
+
data.tar.gz: '08db95e5b85da09ffe4db682d0936f571ad2ffa8253eb21fd7f00e41880b54a7c56c900ff218a7cdf162b7c72c2f804aed3a6e3bc2b58bd43f46b687dc3bd166'
|
@@ -4,6 +4,7 @@ this.EffectiveForm ||= new class
|
|
4
4
|
remote_form_commit: '' # String containing the last params[:commit]
|
5
5
|
remote_form_payload: '' # String containing html from server side render of this form
|
6
6
|
remote_form_flash: '' # Array of Arrays
|
7
|
+
remote_form_redirect: '' # String containing the redirect path (optional)
|
7
8
|
|
8
9
|
validate: (form) ->
|
9
10
|
valid = form.checkValidity()
|
@@ -73,6 +74,11 @@ this.EffectiveForm ||= new class
|
|
73
74
|
$target = $target.closest('form') unless $target.is('form')
|
74
75
|
$form = ''
|
75
76
|
|
77
|
+
if @remote_form_redirect.length > 0
|
78
|
+
window.location.href = @remote_form_redirect
|
79
|
+
@remote_form_redirect = ''
|
80
|
+
return
|
81
|
+
|
76
82
|
if @remote_form_payload.length > 0
|
77
83
|
$payload = $("<div>#{@remote_form_payload}</div>")
|
78
84
|
$form = $payload.find("form[data-remote-index='#{$target.data('remote-index')}']")
|
@@ -160,7 +166,7 @@ this.EffectiveForm ||= new class
|
|
160
166
|
# This displays the spinner here, and directs any flash messages before and after loadRemoteForm
|
161
167
|
$(document).on 'click', '.form-actions a[data-remote],.form-actions button[type=submit]', (event) ->
|
162
168
|
EffectiveForm.setCurrentSubmit($(@).parent())
|
163
|
-
EffectiveForm.spin()
|
169
|
+
EffectiveForm.spin() unless $(@).attr('data-confirm')
|
164
170
|
|
165
171
|
# This actually attached the handlers to a remote ajax form when it or an action inside it triggers a remote thing.
|
166
172
|
$(document).on 'ajax:beforeSend', 'form[data-remote]', (event) ->
|
@@ -3,7 +3,7 @@ assignPositions = (target) ->
|
|
3
3
|
return unless $hasMany.length > 0
|
4
4
|
|
5
5
|
$fields = $hasMany.children('.has-many-fields:not(.marked-for-destruction)')
|
6
|
-
positions = $fields.find("input[name$='[position]']").map(-> this.value).get()
|
6
|
+
positions = $fields.find("input[name$='[position]'][type=hidden]").map(-> this.value).get()
|
7
7
|
|
8
8
|
if positions.length > 0
|
9
9
|
index = Math.min.apply(Math, positions) || 0
|
@@ -35,7 +35,7 @@ $(document).on 'click', '[data-effective-form-has-many-add]', (event) ->
|
|
35
35
|
return unless $hasMany.length > 0
|
36
36
|
|
37
37
|
uid = (new Date).valueOf()
|
38
|
-
template = $obj.data('effective-form-has-many-template').replace(/HASMANYINDEX/g, uid)
|
38
|
+
template = atob($obj.data('effective-form-has-many-template')).replace(/HASMANYINDEX/g, uid)
|
39
39
|
|
40
40
|
$fields = $(template).hide().fadeIn('fast')
|
41
41
|
EffectiveBootstrap.initialize($fields)
|
@@ -0,0 +1,171 @@
|
|
1
|
+
// https://github.com/lazaronixon/trix-extensions/blob/master/app/javascript/richtext.js
|
2
|
+
|
3
|
+
if(window.Trix) {
|
4
|
+
|
5
|
+
addHeadingAttributes()
|
6
|
+
addForegroundColorAttributes()
|
7
|
+
addBackgroundColorAttributes()
|
8
|
+
|
9
|
+
addEventListener('trix-initialize', function (event) { new RichText(event.target) })
|
10
|
+
|
11
|
+
addEventListener('trix-action-invoke', function (event) {
|
12
|
+
if (event.actionName == 'x-horizontal-rule') insertHorizontalRule()
|
13
|
+
|
14
|
+
function insertHorizontalRule() {
|
15
|
+
event.target.editor.insertAttachment(buildHorizontalRule())
|
16
|
+
}
|
17
|
+
|
18
|
+
function buildHorizontalRule() {
|
19
|
+
return new Trix.Attachment({ content: '<hr>', contentType: 'vnd.rubyonrails.horizontal-rule.html' })
|
20
|
+
}
|
21
|
+
})
|
22
|
+
|
23
|
+
class RichText {
|
24
|
+
constructor(element) {
|
25
|
+
this.element = element
|
26
|
+
|
27
|
+
this.insertHeadingElements()
|
28
|
+
this.insertDividerElements()
|
29
|
+
this.insertColorElements()
|
30
|
+
}
|
31
|
+
|
32
|
+
insertHeadingElements() {
|
33
|
+
this.removeOriginalHeadingButton()
|
34
|
+
this.insertNewHeadingButton()
|
35
|
+
this.insertHeadingDialog()
|
36
|
+
}
|
37
|
+
|
38
|
+
removeOriginalHeadingButton() {
|
39
|
+
this.buttonGroupBlockTools.removeChild(this.originalHeadingButton)
|
40
|
+
}
|
41
|
+
|
42
|
+
insertNewHeadingButton() {
|
43
|
+
this.buttonGroupBlockTools.insertAdjacentHTML("afterbegin", this.headingButtonTemplate)
|
44
|
+
}
|
45
|
+
|
46
|
+
insertHeadingDialog() {
|
47
|
+
this.dialogsElement.insertAdjacentHTML("beforeend", this.dialogHeadingTemplate)
|
48
|
+
}
|
49
|
+
|
50
|
+
insertDividerElements() {
|
51
|
+
this.quoteButton.insertAdjacentHTML("afterend", this.horizontalButtonTemplate)
|
52
|
+
}
|
53
|
+
|
54
|
+
insertColorElements() {
|
55
|
+
this.insertColorButton()
|
56
|
+
this.insertDialogColor()
|
57
|
+
}
|
58
|
+
|
59
|
+
insertColorButton() {
|
60
|
+
this.buttonGroupTextTools.insertAdjacentHTML("beforeend", this.colorButtonTemplate)
|
61
|
+
}
|
62
|
+
|
63
|
+
insertDialogColor() {
|
64
|
+
this.dialogsElement.insertAdjacentHTML("beforeend", this.dialogColorTemplate)
|
65
|
+
}
|
66
|
+
|
67
|
+
get buttonGroupBlockTools() {
|
68
|
+
return this.toolbarElement.querySelector("[data-trix-button-group=block-tools]")
|
69
|
+
}
|
70
|
+
|
71
|
+
get buttonGroupTextTools() {
|
72
|
+
return this.toolbarElement.querySelector("[data-trix-button-group=text-tools]")
|
73
|
+
}
|
74
|
+
|
75
|
+
get dialogsElement() {
|
76
|
+
return this.toolbarElement.querySelector("[data-trix-dialogs]")
|
77
|
+
}
|
78
|
+
|
79
|
+
get originalHeadingButton() {
|
80
|
+
return this.toolbarElement.querySelector("[data-trix-attribute=heading1]")
|
81
|
+
}
|
82
|
+
|
83
|
+
get quoteButton() {
|
84
|
+
return this.toolbarElement.querySelector("[data-trix-attribute=quote]")
|
85
|
+
}
|
86
|
+
|
87
|
+
get toolbarElement() {
|
88
|
+
return this.element.toolbarElement
|
89
|
+
}
|
90
|
+
|
91
|
+
get horizontalButtonTemplate() {
|
92
|
+
return '<button type="button" class="trix-button trix-button--icon trix-button--icon-horizontal-rule" data-trix-action="x-horizontal-rule" tabindex="-1" title="Divider">Divider</button>'
|
93
|
+
}
|
94
|
+
|
95
|
+
get headingButtonTemplate() {
|
96
|
+
return '<button type="button" class="trix-button trix-button--icon trix-button--icon-heading-1" data-trix-action="x-heading" title="Heading" tabindex="-1">Heading</button>'
|
97
|
+
}
|
98
|
+
|
99
|
+
get colorButtonTemplate() {
|
100
|
+
return '<button type="button" class="trix-button trix-button--icon trix-button--icon-color" data-trix-action="x-color" title="Color" tabindex="-1">Color</button>'
|
101
|
+
}
|
102
|
+
|
103
|
+
get dialogHeadingTemplate() {
|
104
|
+
return `
|
105
|
+
<div class="trix-dialog trix-dialog--heading" data-trix-dialog="x-heading" data-trix-dialog-attribute="x-heading">
|
106
|
+
<div class="trix-dialog__link-fields">
|
107
|
+
<input type="text" name="x-heading" class="trix-dialog-hidden__input" data-trix-input>
|
108
|
+
<div class="trix-button-group">
|
109
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="heading1">H1</button>
|
110
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="heading2">H2</button>
|
111
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="heading3">H3</button>
|
112
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="heading4">H4</button>
|
113
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="heading5">H5</button>
|
114
|
+
</div>
|
115
|
+
</div>
|
116
|
+
</div>
|
117
|
+
`
|
118
|
+
}
|
119
|
+
|
120
|
+
get dialogColorTemplate() {
|
121
|
+
return `
|
122
|
+
<div class="trix-dialog trix-dialog--color" data-trix-dialog="x-color" data-trix-dialog-attribute="x-color">
|
123
|
+
<div class="trix-dialog__link-fields">
|
124
|
+
<input type="text" name="x-color" class="trix-dialog-hidden__input" data-trix-input>
|
125
|
+
<div class="trix-button-group">
|
126
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="fgColor1" data-trix-method="hideDialog"></button>
|
127
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="fgColor2" data-trix-method="hideDialog"></button>
|
128
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="fgColor3" data-trix-method="hideDialog"></button>
|
129
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="fgColor4" data-trix-method="hideDialog"></button>
|
130
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="fgColor5" data-trix-method="hideDialog"></button>
|
131
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="fgColor6" data-trix-method="hideDialog"></button>
|
132
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="fgColor7" data-trix-method="hideDialog"></button>
|
133
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="fgColor8" data-trix-method="hideDialog"></button>
|
134
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="fgColor9" data-trix-method="hideDialog"></button>
|
135
|
+
</div>
|
136
|
+
<div class="trix-button-group">
|
137
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="bgColor1" data-trix-method="hideDialog"></button>
|
138
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="bgColor2" data-trix-method="hideDialog"></button>
|
139
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="bgColor3" data-trix-method="hideDialog"></button>
|
140
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="bgColor4" data-trix-method="hideDialog"></button>
|
141
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="bgColor5" data-trix-method="hideDialog"></button>
|
142
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="bgColor6" data-trix-method="hideDialog"></button>
|
143
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="bgColor7" data-trix-method="hideDialog"></button>
|
144
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="bgColor8" data-trix-method="hideDialog"></button>
|
145
|
+
<button type="button" class="trix-button trix-button--dialog" data-trix-attribute="bgColor9" data-trix-method="hideDialog"></button>
|
146
|
+
</div>
|
147
|
+
</div>
|
148
|
+
</div>
|
149
|
+
`
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
function addHeadingAttributes() {
|
154
|
+
Array.from(["h1", "h2", "h3", "h4", "h5"]).forEach((tagName, i) => {
|
155
|
+
Trix.config.blockAttributes[`heading${(i + 1)}`] = { tagName: tagName, terminal: true, breakOnReturn: true, group: false }
|
156
|
+
})
|
157
|
+
}
|
158
|
+
|
159
|
+
function addForegroundColorAttributes() {
|
160
|
+
Array.from(["rgb(136, 118, 38)", "rgb(185, 94, 6)", "rgb(207, 0, 0)", "rgb(216, 28, 170)", "rgb(144, 19, 254)", "rgb(5, 98, 185)", "rgb(17, 138, 15)", "rgb(148, 82, 22)", "rgb(102, 102, 102)"]).forEach((color, i) => {
|
161
|
+
Trix.config.textAttributes[`fgColor${(i + 1)}`] = { style: { color: color }, inheritable: true, parser: e => e.style.color == color }
|
162
|
+
})
|
163
|
+
}
|
164
|
+
|
165
|
+
function addBackgroundColorAttributes() {
|
166
|
+
Array.from(["rgb(250, 247, 133)", "rgb(255, 240, 219)", "rgb(255, 229, 229)", "rgb(255, 228, 247)", "rgb(242, 237, 255)", "rgb(225, 239, 252)", "rgb(228, 248, 226)", "rgb(238, 226, 215)", "rgb(242, 242, 242)"]).forEach((color, i) => {
|
167
|
+
Trix.config.textAttributes[`bgColor${(i + 1)}`] = { style: { backgroundColor: color }, inheritable: true, parser: e => e.style.backgroundColor == color }
|
168
|
+
})
|
169
|
+
}
|
170
|
+
|
171
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
if(window.Trix) {
|
2
|
+
|
3
|
+
window.Trix.config.blockAttributes.default.tagName = 'p';
|
4
|
+
window.Trix.config.blockAttributes.default.breakOnReturn = true;
|
5
|
+
|
6
|
+
window.Trix.Block.prototype.breaksOnReturn = function() {
|
7
|
+
const attr = this.getLastAttribute();
|
8
|
+
const config = Trix.getBlockConfig(attr ? attr : 'default');
|
9
|
+
return config ? config.breakOnReturn : false;
|
10
|
+
};
|
11
|
+
|
12
|
+
window.Trix.LineBreakInsertion.prototype.shouldInsertBlockBreak = function() {
|
13
|
+
if(this.block.hasAttributes() && this.block.isListItem() && !this.block.isEmpty()) {
|
14
|
+
return this.startLocation.offset > 0
|
15
|
+
} else {
|
16
|
+
return !this.shouldBreakFormattedBlock() ? this.breaksOnReturn : false;
|
17
|
+
}
|
18
|
+
};
|
19
|
+
|
20
|
+
}
|
@@ -0,0 +1,90 @@
|
|
1
|
+
trix-toolbar {
|
2
|
+
// http://www.asiteaboutnothing.net/c_decode-url.html
|
3
|
+
// background-image: url("data:image/svg+xml,***encoded data***");
|
4
|
+
|
5
|
+
.trix-button--icon-horizontal-rule::before { background-image: url("data:image/svg+xml,%3Csvg%20enable-background%3D%22new%200%200%2024%2024%22%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22%23000%22%3E%3Cpath%20d%3D%22m0%2013h24v-2h-24z%22%2F%3E%3Cpath%20d%3D%22m5%208.5h14v-3h-14z%22%2F%3E%3Cpath%20d%3D%22m5%2018.5h14v-3h-14z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); }
|
6
|
+
.trix-button--icon-color::before { background-image: url("data:image/svg+xml,%3Csvg%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22m16.56%2011.94-8.94-8.94-1.41%201.41%202.38%202.38-5.15%205.15c-.59.59-.59%201.54%200%202.12l5.5%205.5c.29.29.68.44%201.06.44s.77-.15%201.06-.44l5.5-5.5c.59-.58.59-1.53%200-2.12zm-11.35%201.06%204.79-4.79%204.79%204.79zm13.79%202.5s-2%202.17-2%203.5c0%201.1.9%202%202%202s2-.9%202-2c0-1.33-2-3.5-2-3.5z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E%0A"); }
|
7
|
+
|
8
|
+
.trix-dialog--heading { max-width: 160px; }
|
9
|
+
|
10
|
+
.trix-dialog--color {
|
11
|
+
max-width: 265px;
|
12
|
+
|
13
|
+
.trix-dialog__link-fields { flex-direction: column; }
|
14
|
+
|
15
|
+
.trix-button-group {
|
16
|
+
margin: 1px;
|
17
|
+
|
18
|
+
button {
|
19
|
+
width: 28px;
|
20
|
+
&:after { content: "Ab"; }
|
21
|
+
&.trix-active::after { content: "✓"; }
|
22
|
+
}
|
23
|
+
|
24
|
+
[data-trix-attribute=fgColor1] { color: rgb(136, 118, 38) }
|
25
|
+
[data-trix-attribute=fgColor2] { color: rgb(136, 118, 38) }
|
26
|
+
[data-trix-attribute=fgColor3] { color: rgb(207, 0, 0) }
|
27
|
+
[data-trix-attribute=fgColor4] { color: rgb(216, 28, 170) }
|
28
|
+
[data-trix-attribute=fgColor5] { color: rgb(144, 19, 254) }
|
29
|
+
[data-trix-attribute=fgColor6] { color: rgb(5, 98, 185) }
|
30
|
+
[data-trix-attribute=fgColor7] { color: rgb(17, 138, 15) }
|
31
|
+
[data-trix-attribute=fgColor8] { color: rgb(148, 82, 22) }
|
32
|
+
[data-trix-attribute=fgColor9] { color: rgb(102, 102, 102) }
|
33
|
+
|
34
|
+
[data-trix-attribute=bgColor1] { background-color: rgb(250, 247, 133) }
|
35
|
+
[data-trix-attribute=bgColor2] { background-color: rgb(255, 240, 219) }
|
36
|
+
[data-trix-attribute=bgColor3] { background-color: rgb(255, 229, 229) }
|
37
|
+
[data-trix-attribute=bgColor4] { background-color: rgb(255, 228, 247) }
|
38
|
+
[data-trix-attribute=bgColor5] { background-color: rgb(242, 237, 255) }
|
39
|
+
[data-trix-attribute=bgColor6] { background-color: rgb(225, 239, 252) }
|
40
|
+
[data-trix-attribute=bgColor7] { background-color: rgb(228, 248, 226) }
|
41
|
+
[data-trix-attribute=bgColor8] { background-color: rgb(238, 226, 215) }
|
42
|
+
[data-trix-attribute=bgColor9] { background-color: rgb(242, 242, 242) }
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
.trix-dialog {
|
47
|
+
padding: 5px;
|
48
|
+
|
49
|
+
.trix-dialog-hidden__input {
|
50
|
+
position: absolute;
|
51
|
+
z-index: -1;
|
52
|
+
opacity: 0;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
trix-editor {
|
58
|
+
[data-trix-mutable].attachment[data-trix-content-type~="vnd.rubyonrails.horizontal-rule.html"] {
|
59
|
+
box-shadow: 0 0 0 2px highlight;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
.trix-content {
|
64
|
+
h1, h2, h3, h4, h5, h6 {
|
65
|
+
line-height: 1.2;
|
66
|
+
margin: 0;
|
67
|
+
}
|
68
|
+
|
69
|
+
h1 { font-size: 36px; }
|
70
|
+
h2 { font-size: 26px; }
|
71
|
+
h3 { font-size: 18px; }
|
72
|
+
h4 { font-size: 18px; }
|
73
|
+
h5 { font-size: 14px; }
|
74
|
+
h6 { font-size: 12px; }
|
75
|
+
|
76
|
+
.attachment { width: 100%; }
|
77
|
+
|
78
|
+
.attachment--content.attachment--horizontal-rule,
|
79
|
+
.attachment--content[data-trix-content-type~='vnd.rubyonrails.horizontal-rule.html'] {
|
80
|
+
padding: 1.5em 0 0.5em !important;
|
81
|
+
margin-bottom: 0.5em
|
82
|
+
}
|
83
|
+
|
84
|
+
.attachment--content.attachment--horizontal-rule hr,
|
85
|
+
.attachment--content[data-trix-content-type~='vnd.rubyonrails.horizontal-rule.html'] hr {
|
86
|
+
margin: 0;
|
87
|
+
width: 20%;
|
88
|
+
border-color: currentColor
|
89
|
+
}
|
90
|
+
}
|
@@ -1,25 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
border-color: #ccc;
|
4
|
-
|
5
|
-
&:hover,
|
6
|
-
&:active,
|
7
|
-
&:focus, {
|
8
|
-
border-color: #ccc;
|
9
|
-
outline: 0px !important;
|
10
|
-
-webkit-appearance: none;
|
11
|
-
box-shadow: none !important;
|
12
|
-
}
|
13
|
-
}
|
14
|
-
|
15
|
-
// Bootstrap 4 Feedback client side
|
16
|
-
.was-validated .form-control:invalid ~ .trix-content, { border-color: #dc3545 !important; }
|
17
|
-
.was-validated .form-control:valid ~ .trix-content { border-color: #28a745 !important; }
|
18
|
-
.was-validated .form-control:invalid ~ trix-toolbar, { border-color: #dc3545 !important; }
|
19
|
-
.was-validated .form-control:valid ~ trix-toolbar { border-color: #28a745 !important; }
|
20
|
-
|
21
|
-
// Bootstrap 4 Server side feedback
|
22
|
-
.form-control.is-invalid ~ .trix-content { border-color: #dc3545 !important; }
|
23
|
-
.form-control.is-invalid ~ trix-toolbar { border-color: #dc3545 !important; }
|
24
|
-
.form-control.is-valid ~ .trix-content { border-color: #28a745 !important; }
|
25
|
-
.form-control.is-valid ~ trix-toolbar { border-color: #28a745 !important; }
|
1
|
+
@import 'rich_text_area';
|
2
|
+
@import 'extensions';
|
@@ -0,0 +1,30 @@
|
|
1
|
+
.effective_rich_text_area {
|
2
|
+
height: 100%;
|
3
|
+
border-color: #ccc;
|
4
|
+
|
5
|
+
&:hover,
|
6
|
+
&:active,
|
7
|
+
&:focus, {
|
8
|
+
border-color: #ccc;
|
9
|
+
outline: 0px !important;
|
10
|
+
-webkit-appearance: none;
|
11
|
+
box-shadow: none !important;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
// Trix image caption
|
16
|
+
.trix-content {
|
17
|
+
figcaption.attachment__caption { display: none; }
|
18
|
+
}
|
19
|
+
|
20
|
+
// Bootstrap 4 Feedback client side
|
21
|
+
.was-validated .form-control:invalid ~ .trix-content, { border-color: #dc3545 !important; }
|
22
|
+
.was-validated .form-control:valid ~ .trix-content { border-color: #28a745 !important; }
|
23
|
+
.was-validated .form-control:invalid ~ trix-toolbar, { border-color: #dc3545 !important; }
|
24
|
+
.was-validated .form-control:valid ~ trix-toolbar { border-color: #28a745 !important; }
|
25
|
+
|
26
|
+
// Bootstrap 4 Server side feedback
|
27
|
+
.form-control.is-invalid ~ .trix-content { border-color: #dc3545 !important; }
|
28
|
+
.form-control.is-invalid ~ trix-toolbar { border-color: #dc3545 !important; }
|
29
|
+
.form-control.is-valid ~ .trix-content { border-color: #28a745 !important; }
|
30
|
+
.form-control.is-valid ~ trix-toolbar { border-color: #28a745 !important; }
|
@@ -411,7 +411,9 @@ module EffectiveBootstrapHelper
|
|
411
411
|
|
412
412
|
@_tab_active = nil if @_tab_active == :first
|
413
413
|
|
414
|
-
if @_tab_mode == :
|
414
|
+
if @_tab_mode == :tablist_vertical
|
415
|
+
content_tag(:a, label, id: ('tab-' + controls), class: ['nav-link', ('active' if active)].compact.join(' '), href: '#' + controls, 'aria-controls': controls, 'aria-selected': active.to_s, 'data-toggle': 'tab', role: 'tab')
|
416
|
+
elsif @_tab_mode == :tablist # Inserting the label into the tablist top
|
415
417
|
content_tag(:li, class: 'nav-item') do
|
416
418
|
content_tag(:a, label, id: ('tab-' + controls), class: ['nav-link', ('active' if active)].compact.join(' '), href: '#' + controls, 'aria-controls': controls, 'aria-selected': active.to_s, 'data-toggle': 'tab', role: 'tab')
|
417
419
|
end
|
@@ -423,6 +425,29 @@ module EffectiveBootstrapHelper
|
|
423
425
|
end
|
424
426
|
end
|
425
427
|
|
428
|
+
def vertical_tabs(active: nil, unique: false, list: {}, content: {}, &block)
|
429
|
+
raise 'expected a block' unless block_given?
|
430
|
+
|
431
|
+
@_tab_mode = :tablist_vertical
|
432
|
+
@_tab_active = (active || :first)
|
433
|
+
@_tab_unique = ''.object_id if unique
|
434
|
+
|
435
|
+
content_tag(:div, class: 'row border') do
|
436
|
+
content_tag(:div, class: 'col-3 border-right') do
|
437
|
+
content_tag(:div, {class: 'nav flex-column nav-pills my-2', role: 'tablist', 'aria-orientation': :vertical}.merge(list)) do
|
438
|
+
yield # Yield to tab the first time
|
439
|
+
end
|
440
|
+
end +
|
441
|
+
content_tag(:div, class: 'col-9') do
|
442
|
+
content_tag(:div, {class: 'tab-content my-2'}.merge(content)) do
|
443
|
+
@_tab_mode = :content
|
444
|
+
@_tab_active = (active || :first)
|
445
|
+
yield # Yield to tab the second time
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
426
451
|
def merge_class_key(hash, value)
|
427
452
|
return { :class => value } unless hash.kind_of?(Hash)
|
428
453
|
|
@@ -150,7 +150,7 @@ module Effective
|
|
150
150
|
html.gsub!("#{name}_attributes][#{index}]", "#{name}_attributes][HASMANYINDEX]")
|
151
151
|
html.gsub!("#{name}_attributes_#{index}_", "#{name}_attributes_HASMANYINDEX_")
|
152
152
|
|
153
|
-
html
|
153
|
+
Base64.encode64(html)
|
154
154
|
end
|
155
155
|
|
156
156
|
def link_to_add(block)
|
@@ -0,0 +1 @@
|
|
1
|
+
<hr>
|
@@ -11,5 +11,11 @@ module EffectiveBootstrap
|
|
11
11
|
app.config.assets.precompile += ['effective_bootstrap_manifest.js', 'icons/*']
|
12
12
|
end
|
13
13
|
|
14
|
+
initializer 'effective_bootstrap.action_text' do |app|
|
15
|
+
if defined?(ActionText)
|
16
|
+
ActionText::ContentHelper.allowed_attributes << 'style'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
14
20
|
end
|
15
21
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_bootstrap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -451,6 +451,9 @@ files:
|
|
451
451
|
- app/assets/javascripts/effective_price/input.js
|
452
452
|
- app/assets/javascripts/effective_radio/initialize.js.coffee
|
453
453
|
- app/assets/javascripts/effective_radio/input.js
|
454
|
+
- app/assets/javascripts/effective_rich_text_area/extensions.js
|
455
|
+
- app/assets/javascripts/effective_rich_text_area/initialize.js
|
456
|
+
- app/assets/javascripts/effective_rich_text_area/input.js
|
454
457
|
- app/assets/javascripts/effective_select/initialize.js.coffee
|
455
458
|
- app/assets/javascripts/effective_select/input.js
|
456
459
|
- app/assets/javascripts/effective_select/overrides.js.coffee
|
@@ -605,7 +608,9 @@ files:
|
|
605
608
|
- app/assets/stylesheets/effective_file/input.scss
|
606
609
|
- app/assets/stylesheets/effective_has_many/input.scss
|
607
610
|
- app/assets/stylesheets/effective_radio/input.scss
|
611
|
+
- app/assets/stylesheets/effective_rich_text_area/extensions.scss
|
608
612
|
- app/assets/stylesheets/effective_rich_text_area/input.scss
|
613
|
+
- app/assets/stylesheets/effective_rich_text_area/rich_text_area.scss
|
609
614
|
- app/assets/stylesheets/effective_select/bootstrap-theme.css
|
610
615
|
- app/assets/stylesheets/effective_select/input.scss
|
611
616
|
- app/assets/stylesheets/effective_select/overrides.scss
|
@@ -660,6 +665,8 @@ files:
|
|
660
665
|
- app/models/effective/form_logics/hide_if.rb
|
661
666
|
- app/models/effective/form_logics/show_if.rb
|
662
667
|
- app/models/effective/form_logics/show_if_any.rb
|
668
|
+
- app/views/action_text/attachables/_content_attachment.html.erb
|
669
|
+
- app/views/action_text/attachables/content_attachments/_horizontal_rule.html.erb
|
663
670
|
- app/views/effective/style_guide/__fields.html.haml
|
664
671
|
- app/views/effective/style_guide/__inline_fields.html.haml
|
665
672
|
- app/views/effective/style_guide/_effective_form_with.html.haml
|