abracadabra 1.0.5 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7cb45804338fe71758c94d2b1d99dc80ab717d8a
4
- data.tar.gz: 530aeb3bae6e383a2b38e80eebc69b244506882a
3
+ metadata.gz: 213cf8616712fda20832054f530234d2026ee52a
4
+ data.tar.gz: 8a14ef87204cb4ba575ce6902b0a280518fe940f
5
5
  SHA512:
6
- metadata.gz: 73fecc08bc118c530dc84389865f346ece46b5ef6ab3faa8dcfda9f80fb2a1c04111d75ef763e44b956b09dc16389330fa4ee9a297874df5f58ddb6bfad9db7f
7
- data.tar.gz: 14995d84dff4f4369643cecbd528e46218fad781381090c06ea1bb2054cfa3a720f3621941b515edc0b37d35916d2c143115971d57c28cf7808e9278a9ab9491
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 "abracadabra" is added either way.
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 types (:js and :script can both be used to respond with Javascript).
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
- function closeAbracadabra(element) {
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
- value = container.find(".abracadabra-input").val();
10
- container.siblings(".abracadabra").text(value).show();
11
- container.remove();
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
- closeAbracadabra(this);
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
- closeAbracadabra(this);
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
- // Press Tab to submit (same function as Enter key)
102
+ /* Press Tab to submit (same function as Enter key) */
24
103
  if (e.keyCode == 9)
25
104
  {
26
105
  e.preventDefault();
27
- $(this.form).submit();
106
+ if(abracadabraSubmissionInProgress == false) {
107
+ $(this.form).submit();
108
+ }
28
109
  }
110
+ /* /Press Tab to submit (same function as Enter key) */
29
111
 
30
- // Press Escape to cancel
112
+ /* Press Escape to cancel */
31
113
  if (e.keyCode == 27)
32
114
  {
33
115
  e.preventDefault();
34
- closeAbracadabra(this);
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, "&quot;");
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=\"&#10003;\"><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 abracadabra-inline\">" + openFormTag + hiddenMethodTags;
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 value, "javascript:void(0)", class: link_class, method: method.to_sym, data: { path: options[:path], attribute: options[:attribute], class: instance_class, type: data_type.to_sym }, remote: remote
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
@@ -1,5 +1,5 @@
1
1
  module Abracadabra
2
2
  module Rails
3
- VERSION = "1.0.5"
3
+ VERSION = "1.0.6"
4
4
  end
5
5
  end
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.5
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-08 00:00:00.000000000 Z
11
+ date: 2014-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails