abracadabra 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +64 -8
- data/app/assets/javascripts/abracadabra.js +169 -15
- data/app/assets/stylesheets/abracadabra.css +9 -8
- data/app/helpers/abracadabra/rails/view_helper.rb +32 -1
- data/lib/abracadabra/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 213cf8616712fda20832054f530234d2026ee52a
|
4
|
+
data.tar.gz: 8a14ef87204cb4ba575ce6902b0a280518fe940f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62807428994753c30a7287ff7f6d541963778d5a5b526d16ae5dc7d6b4e2185b783841b4ab2ba0611c1e53ad5edec2d49e365399c2655e8c9e04d3059dd6f657
|
7
|
+
data.tar.gz: 593595d4f1e71c4b3b435d9a3d05841bc65cc1798ed39535a8bb25dc25d75564023d96ab9fb0b1f798d51444c6df3c1af9a572e541a2d977a169d1195cb2b02e
|
data/README.md
CHANGED
@@ -53,41 +53,97 @@ It accepts the following parameters:
|
|
53
53
|
```ruby
|
54
54
|
### REQUIRED ###
|
55
55
|
path: user_path(@user)
|
56
|
-
# Specifies where the form will be submitted.
|
56
|
+
# Description: Specifies where the form will be submitted.
|
57
57
|
|
58
58
|
attribute: :name
|
59
|
-
# Specifies what attribute your text field will be updating.
|
59
|
+
# Description: Specifies what attribute your text field will be updating.
|
60
60
|
|
61
61
|
|
62
62
|
### OPTIONAL ###
|
63
63
|
class: "my-class"
|
64
|
-
# Class(es) to be added to the text input of the form. The class
|
64
|
+
# Description: Class(es) to be added to the text input of the form. The class
|
65
|
+
# "abracadabra" is added # either way.
|
65
66
|
# Default: only "abracadabra"
|
66
67
|
|
67
68
|
value: "blah"
|
68
|
-
# An alternate value, other than what object.attribute would return.
|
69
|
+
# Description: An alternate value, other than what object.attribute would return.
|
69
70
|
# Default: object.attribute
|
70
71
|
|
71
72
|
method: "patch"
|
72
|
-
# HTTP REST method to use. Use anything but "get".
|
73
|
+
# Description: HTTP REST method to use. Use anything but "get".
|
73
74
|
# Default: "patch"
|
74
75
|
|
76
|
+
buttonless: true
|
77
|
+
# Description: Removes submit and cancel buttons, submission and cancellation is then
|
78
|
+
# done through the Enter/Tab and Escape keys, respectively.
|
79
|
+
# Default: false
|
80
|
+
|
75
81
|
remote: true
|
76
|
-
# Same as link_to's `remote: true`, form submits via AJAX.
|
82
|
+
# Description: Same as link_to's `remote: true`, form submits via AJAX.
|
77
83
|
# Default: true
|
78
84
|
|
79
85
|
# IMPORTANT: `type` will be ignored if `remote = false` is used. HTML is the default
|
80
86
|
# in Rails for standard form submissions.
|
81
87
|
type: :js
|
82
|
-
# Content type -- responds to any content
|
88
|
+
# Description: Content type -- responds to any content type (:js and :script can both be
|
89
|
+
# used to respond with Javascript).
|
83
90
|
# Default: :script (:js)
|
91
|
+
|
92
|
+
# IMPORTANT: On ajax:success, this will remove the specific abracadabra instance from
|
93
|
+
# the DOM entirely.
|
94
|
+
deletable: true
|
95
|
+
# Boolean: DELETE will be submitted without a confirmation dialog
|
96
|
+
# OR
|
97
|
+
deletable: "Are you sure?"
|
98
|
+
# String: Confirmation dialog, with the string as the message, will be displayed after
|
99
|
+
# clicking the DELETE link
|
100
|
+
# Description: Puts a link to DELETE the object (obviously, it always uses DELETE as
|
101
|
+
# the HTTP verb).
|
102
|
+
# Default: false
|
103
|
+
|
104
|
+
deletable_path: user_path(@user)
|
105
|
+
# Description: Specifies where the form will be submitted.
|
106
|
+
# Default: path (uses the same path as the main form if `deletable_path` isn't declared).
|
107
|
+
|
108
|
+
# Boolean: Open the next abracadabra instance after successful form submission (main
|
109
|
+
# form, not the DELETE link's submission) by using `.abracadabra` as the selector.
|
110
|
+
tab_to_next: true
|
111
|
+
# OR
|
112
|
+
tab_to_next: ".my-class"
|
113
|
+
# IMPORTANT: If this is a class, this abracadabra instance MUST have the same class
|
114
|
+
# as well.
|
115
|
+
# String: The class or ID of the next abracadabra instance to open on succesful form
|
116
|
+
# submission. Use `.` before a class selector or `#` before a an ID selector just as you
|
117
|
+
# would when finding an element in Javascript.
|
118
|
+
# Description: Puts a link to DELETE the object (obviously, it always uses DELETE as the
|
119
|
+
# HTTP verb).
|
120
|
+
# Default: false
|
121
|
+
|
122
|
+
submit_on_blur: true
|
123
|
+
# Description: Submit form when focus leaves the input, rather than simply closing it
|
124
|
+
# out.
|
125
|
+
# Default: false
|
126
|
+
```
|
127
|
+
|
128
|
+
## Configuration
|
129
|
+
|
130
|
+
Abracadabra allows some customization. If you would like to change what icon classes are used for the `submit`, `cancel`, and `delete` icons, you can change them globally.
|
131
|
+
|
132
|
+
In any Javascript file that loads **BEFORE** abracadabra's Javascript file that you required above, change any/all of the following variables to suit your project's needs:
|
133
|
+
|
134
|
+
```javascript
|
135
|
+
abracadabraSubmitIcon = "fa fa-check"; // default
|
136
|
+
|
137
|
+
abracadabraCancelIcon = "fa fa-times"; // default
|
138
|
+
|
139
|
+
abracadabraDeleteIcon = "fa fa-times-circle-o"; // default
|
84
140
|
```
|
85
141
|
|
86
142
|
## Future & Contributing
|
87
143
|
|
88
144
|
1. I would love anyone to add date pickers and other alternate field types to this.
|
89
145
|
|
90
|
-
2. I would love the different Bootstrap classes to be overridable with an initializer (config/abracadabra.rb) so that any framework could be used. Same with the Font-Awesome button classes.
|
146
|
+
2. I would love the different Bootstrap classes to be overridable with an initializer (config/abracadabra.rb), rather than Javascript (not sure if this is even possible), so that any framework could be used. Same with the Font-Awesome button classes.
|
91
147
|
|
92
148
|
3. I would love for a `buttons: false` option to be offered that would allow only `Tab`, `Enter` and `Escape` to submit or cancel the form submission.
|
93
149
|
|
@@ -1,38 +1,134 @@
|
|
1
1
|
$(function() {
|
2
|
-
|
2
|
+
abracadabraSubmissionInProgress = false;
|
3
|
+
abracadabraDeleteMousedown = false;
|
4
|
+
|
5
|
+
function closeAbracadabra(element, destroy) {
|
3
6
|
$element = $(element);
|
4
7
|
if($element.hasClass("abracadabra-container")) {
|
5
8
|
container = $element;
|
6
9
|
} else {
|
7
10
|
container = $element.parents(".abracadabra-container");
|
8
11
|
}
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
+
|
13
|
+
if(destroy) {
|
14
|
+
container.siblings(".abracadabra").remove();
|
15
|
+
} else {
|
16
|
+
value = container.find(".abracadabra-input").val();
|
17
|
+
container.siblings(".abracadabra").text(value).show();
|
18
|
+
}
|
19
|
+
|
20
|
+
try {
|
21
|
+
container.remove();
|
22
|
+
} catch (error) {
|
23
|
+
if(error.name != "NotFoundError") {
|
24
|
+
throw error;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
function tabToNextAbracadabra(element, selector) {
|
30
|
+
if(selector != undefined) {
|
31
|
+
nextAbracadabra = $(selector);
|
32
|
+
|
33
|
+
/* If selector isn't an ID, find the element with the class AFTER the current element */
|
34
|
+
if (selector.indexOf("#") == -1) {
|
35
|
+
abracadabra = $(element).parents(".abracadabra-container").siblings(".abracadabra");
|
36
|
+
indexOfAbracadabra = $(selector).index(abracadabra);
|
37
|
+
nextAbracadabra = $($(selector)[indexOfAbracadabra + 1]);
|
38
|
+
}
|
39
|
+
/* /If selector isn't an ID, find the element with the class AFTER the current element */
|
40
|
+
|
41
|
+
closeAbracadabra(element, false);
|
42
|
+
nextAbracadabra.click();
|
43
|
+
} else {
|
44
|
+
closeAbracadabra(element, false);
|
45
|
+
}
|
12
46
|
}
|
13
47
|
|
48
|
+
$("body").on("submit", ".abracadabra-form", function(e) {
|
49
|
+
if(abracadabraSubmissionInProgress == true) {
|
50
|
+
e.preventDefault();
|
51
|
+
return false;
|
52
|
+
}
|
53
|
+
abracadabraSubmissionInProgress = true;
|
54
|
+
});
|
55
|
+
|
56
|
+
$("body").on("ajax:before", ".abracadabra-delete", function() {
|
57
|
+
if(abracadabraSubmissionInProgress == true) {
|
58
|
+
e.preventDefault();
|
59
|
+
return false;
|
60
|
+
}
|
61
|
+
abracadabraSubmissionInProgress = true;
|
62
|
+
});
|
63
|
+
|
64
|
+
$("body").on("mousedown", ".abracadabra-delete", function() {
|
65
|
+
abracadabraDeleteMousedown = true;
|
66
|
+
});
|
67
|
+
|
14
68
|
$("body").on("ajax:success", ".abracadabra-form", function(e) {
|
15
|
-
|
16
|
-
|
69
|
+
target = $(e.target);
|
70
|
+
|
71
|
+
/* If form is a DELETE, remove abracadabra instance, if not, call tabToNextSelector */
|
72
|
+
if(target.hasClass("abracadabra-delete")) {
|
73
|
+
closeAbracadabra(target, true);
|
74
|
+
abracadabraDeleteMousedown = false;
|
75
|
+
} else {
|
76
|
+
input = $(target).find(".abracadabra-input");
|
77
|
+
tabToNextSelector = input.data("tab-to-next-selector");
|
78
|
+
tabToNextAbracadabra(target, tabToNextSelector);
|
79
|
+
}
|
80
|
+
/* /If form is a DELETE, remove abracadabra instance, if not, call tabToNextSelector */
|
81
|
+
|
82
|
+
abracadabraSubmissionInProgress = false;
|
83
|
+
});
|
17
84
|
|
18
85
|
$("body").on("click", ".abracadabra-cancel", function() {
|
19
|
-
|
86
|
+
if(abracadabraSubmissionInProgress == false) {
|
87
|
+
closeAbracadabra(this, false);
|
88
|
+
}
|
89
|
+
});
|
90
|
+
|
91
|
+
$("body").on("blur", ".abracadabra-input", function() {
|
92
|
+
if(abracadabraSubmissionInProgress == false && abracadabraDeleteMousedown == false) {
|
93
|
+
if($(this).data("submit-on-blur") == true) {
|
94
|
+
$(this.form).submit();
|
95
|
+
} else {
|
96
|
+
closeAbracadabra(this, false);
|
97
|
+
}
|
98
|
+
}
|
20
99
|
});
|
21
100
|
|
22
101
|
$("body").on("keydown", ".abracadabra-input", function(e) {
|
23
|
-
|
102
|
+
/* Press Tab to submit (same function as Enter key) */
|
24
103
|
if (e.keyCode == 9)
|
25
104
|
{
|
26
105
|
e.preventDefault();
|
27
|
-
|
106
|
+
if(abracadabraSubmissionInProgress == false) {
|
107
|
+
$(this.form).submit();
|
108
|
+
}
|
28
109
|
}
|
110
|
+
/* /Press Tab to submit (same function as Enter key) */
|
29
111
|
|
30
|
-
|
112
|
+
/* Press Escape to cancel */
|
31
113
|
if (e.keyCode == 27)
|
32
114
|
{
|
33
115
|
e.preventDefault();
|
34
|
-
|
116
|
+
if(abracadabraSubmissionInProgress == false) {
|
117
|
+
closeAbracadabra(this, false);
|
118
|
+
}
|
35
119
|
}
|
120
|
+
/* /Press Escape to cancel */
|
121
|
+
});
|
122
|
+
|
123
|
+
|
124
|
+
$("body").on("confirm:complete", ".abracadabra-delete", function(e, response) {
|
125
|
+
/* If cancel is clicked in the deletable_confirm dialog, focus on the input */
|
126
|
+
if(response == false) {
|
127
|
+
input = $(this).parents(".abracadabra-delete-container").siblings();
|
128
|
+
inputValue = input.val();
|
129
|
+
input.focus().val("").val(inputValue);
|
130
|
+
}
|
131
|
+
/* /If cancel is clicked in the deletable_confirm dialog, focus on the input */
|
36
132
|
});
|
37
133
|
|
38
134
|
$(".abracadabra").on("click", function() {
|
@@ -43,6 +139,55 @@ $(function() {
|
|
43
139
|
formMethod = link.data("method");
|
44
140
|
remote = ((link.data("remote") == true) ? " data-remote=\"true\"" : "");
|
45
141
|
|
142
|
+
/* Check if button classes have been manually overridden elsewhere */
|
143
|
+
if(typeof abracadabraSubmitIcon == "undefined") {
|
144
|
+
abracadabraSubmitIcon = "fa fa-check";
|
145
|
+
}
|
146
|
+
|
147
|
+
if(typeof abracadabraCancelIcon == "undefined") {
|
148
|
+
abracadabraCancelIcon = "fa fa-times";
|
149
|
+
}
|
150
|
+
|
151
|
+
if(typeof abracadabraDeleteIcon == "undefined") {
|
152
|
+
abracadabraDeleteIcon = "fa fa-times-circle-o";
|
153
|
+
}
|
154
|
+
/* /Check if button classes have been manually overridden elsewhere */
|
155
|
+
|
156
|
+
/* Deletable? */
|
157
|
+
if(link.data("deletable") !== false) {
|
158
|
+
deletablePath = link.data("deletable-path");
|
159
|
+
deletableConfirm = link.data("deletable");
|
160
|
+
if(deletableConfirm === true) {
|
161
|
+
deletableConfirm = "";
|
162
|
+
} else {
|
163
|
+
deletableConfirm = " data-confirm=\"" + deletableConfirm + "\"";
|
164
|
+
}
|
165
|
+
deletable = "<span class=\"abracadabra-delete-container\"><a href=\"" + deletablePath + "\" class=\"abracadabra-delete\" data-method=\"delete\"" + deletableConfirm + remote + " rel=\"nofollow\"><i class=\"" + abracadabraDeleteIcon + "\"></i></a></span>";
|
166
|
+
} else {
|
167
|
+
deletable = "";
|
168
|
+
}
|
169
|
+
/* /Deletable? */
|
170
|
+
|
171
|
+
/* Tab to next? */
|
172
|
+
tabToNextSelector = link.data("tab-to-next");
|
173
|
+
if(tabToNextSelector !== false) {
|
174
|
+
tabToNextSelector = link.data("tab-to-next");
|
175
|
+
tabToNextSelector = " data-tab-to-next-selector=\"" + tabToNextSelector + "\"";
|
176
|
+
} else {
|
177
|
+
tabToNextSelector = "";
|
178
|
+
}
|
179
|
+
/* /Tab to next? */
|
180
|
+
|
181
|
+
/* Submit on blur? */
|
182
|
+
submitOnBlur = link.data("submit-on-blur");
|
183
|
+
if(submitOnBlur == true) {
|
184
|
+
submitOnBlur = " data-submit-on-blur=\"true\"";
|
185
|
+
} else {
|
186
|
+
submitOnBlur = "";
|
187
|
+
}
|
188
|
+
/* /Submit on blur? */
|
189
|
+
|
190
|
+
/* AJAX? */
|
46
191
|
if(remote == "") {
|
47
192
|
authToken = "<input name=\"authenticity_token\" type=\"hidden\" value=\"" + $("meta[name=\"csrf-token\"]").attr("content") + "\">";
|
48
193
|
type = "";
|
@@ -50,21 +195,30 @@ $(function() {
|
|
50
195
|
authToken = "";
|
51
196
|
type = " data-type=\"" + link.data("type") + "\"";
|
52
197
|
}
|
198
|
+
/* /AJAX? */
|
199
|
+
|
200
|
+
/* Show buttons? */
|
201
|
+
if(link.data("buttonless") == true) {
|
202
|
+
buttons = "";
|
203
|
+
} else {
|
204
|
+
buttons = "<button type=\"submit\" class=\"btn btn-primary abracadabra-submit\"><i class=\"" + abracadabraSubmitIcon + "\"></i></button><button type=\"button\" class=\"btn abracadabra-cancel\"><i class=\"" + abracadabraCancelIcon + "\"></i></button>";
|
205
|
+
}
|
206
|
+
/* /Show buttons? */
|
53
207
|
|
54
208
|
instanceClass = link.data("class");
|
55
209
|
inputValue = link.text().replace(/"|\\"/g, """);
|
56
210
|
inputId = instanceClass + "_" + attribute;
|
57
211
|
inputName = instanceClass + "[" + attribute + "]";
|
58
212
|
|
59
|
-
buttons = "<button type=\"submit\" class=\"btn btn-primary abracadabra-submit\"><i class=\"fa fa-check\"></i></button><button type=\"button\" class=\"btn abracadabra-cancel\"><i class=\"fa fa-times\"></i></button>";
|
60
213
|
openFormTag = "<form accept-charset=\"UTF-8\" action=\"" + path + "\"" + remote + type + " class=\"form-inline abracadabra-form\" method=\"post\">";
|
61
214
|
hiddenMethodTags = "<div style=\"display:none;\"><input name=\"utf8\" type=\"hidden\" value=\"✓\"><input name=\"_method\" type=\"hidden\" value=\"" + formMethod + "\">" + authToken + "</div>";
|
62
|
-
input = "<input type=\"text\" class=\"form-control abracadabra-input\" id=\"" + inputId + "\" name=\"" + inputName + "\" value=\"" + inputValue + "\">";
|
215
|
+
input = "<input type=\"text\" class=\"form-control abracadabra-input\" id=\"" + inputId + "\" name=\"" + inputName + "\" value=\"" + inputValue + "\"" + tabToNextSelector + submitOnBlur + ">";
|
63
216
|
|
64
|
-
html = "<span class=\"abracadabra-container
|
65
|
-
html += "<div class=\"control-group\"><div class=\"abracadabra-input-and-button-wrapper\"><div class=\"abracadabra-input-container\">" + input + "</div>";
|
217
|
+
html = "<span class=\"abracadabra-container\">" + openFormTag + hiddenMethodTags;
|
218
|
+
html += "<div class=\"control-group\"><div class=\"abracadabra-input-and-button-wrapper\"><div class=\"abracadabra-input-container\">" + input + deletable + "</div>";
|
66
219
|
html += "<div class=\"abracadabra-buttons\">" + buttons + "</div></div></form></span>";
|
67
220
|
|
68
221
|
link.after(html);
|
222
|
+
link.siblings(".abracadabra-container").find(".abracadabra-input").focus().val("").val(inputValue);
|
69
223
|
});
|
70
224
|
});
|
@@ -1,21 +1,22 @@
|
|
1
|
-
.abracadabra {
|
2
|
-
border-bottom: 1px dashed;
|
3
|
-
color: #428bca;
|
4
|
-
}
|
1
|
+
.abracadabra { border-bottom: 1px dashed; }
|
5
2
|
|
6
|
-
.abracadabra:hover {
|
7
|
-
text-decoration: none;
|
8
|
-
color: darken(#428bca, 10%);
|
9
|
-
}
|
3
|
+
.abracadabra:hover { text-decoration: none; }
|
10
4
|
|
11
5
|
.abracadabra-container { display: block; }
|
12
6
|
|
13
7
|
.abracadabra-container > .abracadabra-form > .control-group > .abracadabra-input-and-button-wrapper > .abracadabra-input-container {
|
14
8
|
width: 60%;
|
15
9
|
display: inline-block;
|
10
|
+
position: relative;
|
16
11
|
}
|
17
12
|
|
18
13
|
.abracadabra-container > .abracadabra-form > .control-group > .abracadabra-input-and-button-wrapper > .abracadabra-buttons {
|
19
14
|
width: 40%;
|
20
15
|
display: inline-block;
|
16
|
+
}
|
17
|
+
|
18
|
+
.abracadabra-container > .abracadabra-form > .control-group > .abracadabra-input-and-button-wrapper > .abracadabra-input-container > .abracadabra-delete-container {
|
19
|
+
position: absolute;
|
20
|
+
top: 50%;
|
21
|
+
right: 6px;
|
21
22
|
}
|
@@ -6,6 +6,21 @@ module Abracadabra
|
|
6
6
|
link_class = "#{options[:class]} abracadabra".strip
|
7
7
|
value = options[:value] || instance.send(options[:attribute])
|
8
8
|
method = options[:method] || "patch"
|
9
|
+
path = options[:path]
|
10
|
+
buttonless = options[:buttonless] || false
|
11
|
+
deletable = options[:deletable] || false
|
12
|
+
deletable_path = options[:deletable_path] || path
|
13
|
+
submit_on_blur = options[:submit_on_blur] || false
|
14
|
+
|
15
|
+
if options[:tab_to_next] || options[:tab_to_next] != false
|
16
|
+
if options[:tab_to_next] == true
|
17
|
+
tab_to_next = ".abracadabra"
|
18
|
+
else
|
19
|
+
tab_to_next = options[:tab_to_next]
|
20
|
+
end
|
21
|
+
else
|
22
|
+
tab_to_next = false
|
23
|
+
end
|
9
24
|
|
10
25
|
if !options[:remote].nil? && options[:remote] == false
|
11
26
|
remote = false
|
@@ -15,7 +30,23 @@ module Abracadabra
|
|
15
30
|
|
16
31
|
data_type = options[:type].to_s.gsub(/^j+s+$/, "script") || "script"
|
17
32
|
|
18
|
-
link_to
|
33
|
+
link_to(
|
34
|
+
value,
|
35
|
+
"javascript:void(0)",
|
36
|
+
class: link_class, method: method.to_sym,
|
37
|
+
data: {
|
38
|
+
path: path,
|
39
|
+
attribute: options[:attribute],
|
40
|
+
class: instance_class,
|
41
|
+
type: data_type.to_sym,
|
42
|
+
buttonless: buttonless,
|
43
|
+
deletable: deletable,
|
44
|
+
deletable_path: deletable_path,
|
45
|
+
tab_to_next: tab_to_next,
|
46
|
+
submit_on_blur: submit_on_blur
|
47
|
+
},
|
48
|
+
remote: remote
|
49
|
+
)
|
19
50
|
end
|
20
51
|
end
|
21
52
|
end
|
data/lib/abracadabra/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abracadabra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Trevor Hinesley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|