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 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