email_list_field 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fa1ee5984c8e2c9c1f39aa7fcef50df89d5ac91c
4
+ data.tar.gz: 4adfebbaf27ebdbe9c4d4b9a238167ffa8b28478
5
+ SHA512:
6
+ metadata.gz: 7511f8e37fcd9e2fd727446db0529977370c1779baf0d74e08f52a7feb844bfbe9e9232b0c8c0db80cb64b22cd8872a3263ec8faed136c82b78d82df54e0fb9a
7
+ data.tar.gz: 60427fea02ee47cf27ce49e48c881cc4f64f989a805ee95b5de7502cf0a2f3355ad6d2ad483c69f935853c97899c89d6734ce905b7ede0bc9f633624e1070ab9
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ email_list_field
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.3.1
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.4
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in email_list_field.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Henrique Gubert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # EmailListField
2
+
3
+ Creates editable form field for email lists using jquery and jquery-ui.
4
+
5
+ This gem is a wrapper of the [jquery-email_list_field.js](https://github.com/hsgubert/jquery-email_list_field) project, that allows you to include jquery-email_list_field.js in your Rails app, using the asset pipeline. The gem currently includes v1.1.0 of jquery-email_list_field.js.
6
+
7
+ ![](https://github.com/hsgubert/email_list_field/raw/master/preview.gif)
8
+ ```html
9
+ <div id="mailing_list_container"></div>
10
+ <script>
11
+ $('#mailing_list_container').emailListField();
12
+ </script>
13
+ ```
14
+
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'email_list_field'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ Or install it yourself as:
29
+
30
+ $ gem install email_list_field
31
+
32
+ ## Usage
33
+
34
+ Include the jquery-email_list_field.js javascript in your `app/assets/javascripts/application.js` or `app/assets/javascripts/vendor.js`:
35
+ ```
36
+ //= require email_list_field
37
+ ```
38
+ And include stylesheets in your `app/assets/stylesheets/application.js` or `app/assets/stylesheets/vendor.js`::
39
+ ```
40
+ *= require email_list_field
41
+ ```
42
+
43
+ In your view, create an empty div and call the `emailListField()` JQuery method:
44
+ ```html
45
+ <div id="mailing_list_container"></div>
46
+ <script>
47
+ $('#mailing_list_container').emailListField();
48
+ </script>
49
+ ```
50
+
51
+ For a full reference on all the options available, see the [jquery-email_list_field.js page](https://github.com/hsgubert/jquery-email_list_field)
52
+
53
+ ## Params Handling Method
54
+ When the user submits the form containing the email list field, an array of strings will be submitted to your controller (by default at `params[:emails]`). The problem is that these string might be either an email or a string in the format "Name <email>". There is a helper to help you treat these parameters:
55
+ ```ruby
56
+ params[:emails] = [
57
+ 'Name <email1@address.com>',
58
+ 'email2@address.com.br',
59
+ 'Compound Name <EMAIL3@Address.com.de>'
60
+ ]
61
+
62
+ EmailListField.parse_email_list_params(params[:emails])
63
+ # => [
64
+ # ['Name', 'email1@address.com'],
65
+ # [nil, 'email2@address.com.br'],
66
+ # ['Compound Name', 'email3@address.com.de']
67
+ # ]
68
+ ```
69
+
70
+ This helper will identify the name and the email part of the string. It will also downcase all the emails. If you don't want the emails to be downcased you can pass the `lower_email_address_case: false` option as a second parameter.
71
+
72
+ ## Feature/Integration Tests
73
+ For you to be able to test the email list field behavior, you will need an integration test with javascripts enabled. We recommend the RSpec + Capybara + PhantomJS tools. To make those tests easier, the gem packages helpers to be used during testing.
74
+
75
+ To include these helpers add to your `spec/spec_helper.rb` or to you `spec/rails_helper.rb`:
76
+ ```ruby
77
+ RSpec.configure do |config|
78
+ config.include EmailListField::TestHelpers, type: :feature
79
+ end
80
+ ```
81
+
82
+ Then you can use these helpers:
83
+ ```ruby
84
+ fill_in_email_list_field 'mailing_list_container', with: 'some@email.com'
85
+ remove_from_email_list_field 'mailing_list_container', 'some@email.com'
86
+ ```
87
+ ## License
88
+
89
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ // This is a manifest file that'll be compiled into vendor.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require taggle-full
14
+ //= require_tree ./jquery-email_list_field
@@ -0,0 +1,374 @@
1
+ ////////////////////////////////////////////////////////////////////////////////
2
+ // jquery-email_list_field.js
3
+ // Author: @hsgubert - Henrique Gubert
4
+ ////////////////////////////////////////////////////////////////////////////////
5
+
6
+ // JQuery plugin. Examples:
7
+ // $('#email-list-field').emailListField();
8
+ // $('#email-list-field').emailListField({ lowerEmailAddressCase: false });
9
+ //
10
+ // For reference of available options see DEFAULT_OPTIONS definition
11
+ //
12
+ $.fn.emailListField = function(options) {
13
+ var containerId = this.attr('id');
14
+
15
+ if (!containerId) {
16
+ containerId = 'email-list-field-container';
17
+ this.attr('id', containerId);
18
+ }
19
+
20
+ return new EmailListField(containerId, options);
21
+ };
22
+
23
+
24
+ // Class definition
25
+ var EmailListField = function() {
26
+ //////////////////////////////////////////////////////////////////////////////
27
+ // Static constants
28
+ //////////////////////////////////////////////////////////////////////////////
29
+
30
+ var DEFAULT_OPTIONS = {
31
+
32
+ /**
33
+ * List of known emails for autocomplete purposes. Emails can be provided
34
+ * as is or in the "Name Lastname <email>" format
35
+ * @type {Array[String]}
36
+ */
37
+ knownFormattedEmails: [],
38
+
39
+ /**
40
+ * List of emails that are initialized in the field. Emails can be provided
41
+ * as is or in the "Name Lastname <email>" format
42
+ * @type {Array[String]}
43
+ */
44
+ initialEmails: [],
45
+
46
+ /**
47
+ * Name of the input fields. One hidden input is generated for each email in list
48
+ * @type {String}
49
+ */
50
+ inputName: 'emails[]',
51
+
52
+ /**
53
+ * If true email addresses will be downcased when added. This does not affect
54
+ * name when email is added in the "Name <email>" format.
55
+ * @type {Boolean}
56
+ */
57
+ lowerEmailAddressCase: true,
58
+
59
+ /**
60
+ * If false emails already in list will not be added
61
+ * @type {Boolean}
62
+ */
63
+ allowDuplicateEmails: false,
64
+
65
+ /**
66
+ * If defined, a message tooltip appears when user tries to add duplicate emails
67
+ * The message is in the format "%{email} %{duplicatedEmailMessage}"
68
+ * @type {Boolean}
69
+ */
70
+ duplicatedEmailMessage: 'is already on this email list',
71
+
72
+ /**
73
+ * If defined, a message tooltip appears when user tries to add invalid emails
74
+ * The message is in the format "%{email} %{duplicatedEmailMessage}"
75
+ * @type {String}
76
+ */
77
+ invalidEmailMessage: 'is not a valid email address',
78
+
79
+ /**
80
+ * The message shown as placeholder in the field when there are no emails
81
+ * @type {String}
82
+ */
83
+ placeholderMessage: 'Insert email list here',
84
+
85
+ /**
86
+ * Function that receives both the complete tag text and only the email and
87
+ * optionally returns a string with css classes to be added to the specific
88
+ * tag. If the option lowerEmailAddressCase is set, the function will receive
89
+ * the email already downcased.
90
+ * @type {function returning String}
91
+ */
92
+ extraTagClassFunction: function(text, email) {},
93
+
94
+ /**
95
+ * Function called after each adition or removal of email. It is passed an
96
+ * array of emails (strings) exactly as shown to the user. This callback is
97
+ * designed to do actions that depend on the current state os the email list field
98
+ * @type {function}
99
+ */
100
+ afterChangeCallback: function(formatted_emails) {}
101
+ };
102
+
103
+ // Email validation and extraction
104
+ // Email validation regexp: not the most restrictive regexp, but it does the trick
105
+ // Obs: it allows up case characters on email because we downcase them later, depending on option lowerEmailAddressCase
106
+ var emailRegexpString = "[-a-z0-9~!$%^&*_=+}{\\'?]+(\\.[-a-z0-9~!$%^&*_=+}{\\'?]+)*@([a-z0-9_][-a-z0-9_]*(\\.[-a-z0-9_]+)*\\.([a-z][a-z]+)|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,5})?";
107
+ var EMAIL_REGEXP = new RegExp('^' + emailRegexpString + '$', 'i');
108
+ var NAME_AND_EMAIL_REGEXP = new RegExp('^[^<>]*<' + emailRegexpString + '>$', 'i');
109
+ var EMAIL_EXTRACTION_REGEXP = new RegExp('^([^<>]*)<(.+)>$');
110
+
111
+ //////////////////////////////////////////////////////////////////////////////
112
+ // Constructor
113
+ //////////////////////////////////////////////////////////////////////////////
114
+
115
+ var emailListFieldConstructor = function(containerId, options) {
116
+ this.containerId = containerId;
117
+ this.options = $.extend(DEFAULT_OPTIONS, options);
118
+ this._initAttributes();
119
+
120
+ // Taggle is the ui lib used to implement the "tagging effect" when you
121
+ // finish writting an email
122
+ this._initTaggle();
123
+
124
+ this._prepopulateTaggle();
125
+ }
126
+
127
+ //////////////////////////////////////////////////////////////////////////////
128
+ // Object public functions
129
+ //////////////////////////////////////////////////////////////////////////////
130
+
131
+ emailListFieldConstructor.prototype.addEmail = function(email_or_emails) {
132
+ this.taggleObject.add(email_or_emails);
133
+ }
134
+
135
+ emailListFieldConstructor.prototype.removeEmail = function(email) {
136
+ this.taggleObject.remove(email, true);
137
+ }
138
+
139
+ emailListFieldConstructor.prototype.clear = function() {
140
+ this.taggleObject.removeAll();
141
+ }
142
+
143
+ emailListFieldConstructor.prototype.getEmails = function() {
144
+ return this.taggleObject.getTags().values;
145
+ }
146
+
147
+ //////////////////////////////////////////////////////////////////////////////
148
+ // Object private functions
149
+ //////////////////////////////////////////////////////////////////////////////
150
+
151
+
152
+ // Initialization of necessary attributes
153
+ emailListFieldConstructor.prototype._initAttributes = function() {
154
+ // Creates array to keep track of current emails on taggle, for purposes of detecting duplicates
155
+ // We create this list to keep track of just the emails (without names)
156
+ this.emailsOnTaggle = [];
157
+ };
158
+
159
+ // Runs when user tries to add email with invalid format
160
+ // It will show a message tooltip if invalidEmailMessage is defined, otherwise does nothing
161
+ // Needs to receive taggle so it can show tooltip anchored to it
162
+ emailListFieldConstructor.prototype._onInvalidEmailCallback = function(invalidEmail) {
163
+ if (this.options.invalidEmailMessage) {
164
+ var input = this.taggleObject.getInput();
165
+
166
+ // shows tooltip for 3 seconds
167
+ $(input).
168
+ attr("title", "\"" + invalidEmail + "\" " + this.options.invalidEmailMessage).
169
+ tooltip("open");
170
+
171
+ setTimeout(function() {
172
+ $(input).
173
+ tooltip("close").
174
+ attr( "title", "" );
175
+ }, 3000);
176
+ }
177
+ }
178
+
179
+ // Runs when user tries to add duplicated email to list, and allowDuplicateEmails is false
180
+ // It will show a message tooltip if duplicatedEmailMessage is defined, otherwise does nothing
181
+ emailListFieldConstructor.prototype._onDuplicatedEmailsCallback = function(email) {
182
+ if (this.options.duplicatedEmailMessage) {
183
+ var input = this.taggleObject.getInput();
184
+
185
+ // shows tooltip for 3 seconds
186
+ $(input).
187
+ attr("title", "\"" + email + "\" " + this.options.duplicatedEmailMessage).
188
+ tooltip("open");
189
+
190
+ setTimeout(function() {
191
+ $(input).
192
+ tooltip("close").
193
+ attr( "title", "" );
194
+ }, 3000);
195
+ }
196
+ };
197
+
198
+ // Extracts email from either a string with an email or a string with a name
199
+ // and an email, like: Compound Name <email@domain.com>
200
+ // Returns null if format is invalid
201
+ emailListFieldConstructor.prototype._extractEmail = function(text) {
202
+ var trimmedText = text.trim();
203
+ if (EMAIL_REGEXP.test(trimmedText)) {
204
+ var email = trimmedText;
205
+ } else if (NAME_AND_EMAIL_REGEXP.test(text)) {
206
+ var email = trimmedText.match(EMAIL_EXTRACTION_REGEXP)[2];
207
+ } else {
208
+ return null;
209
+ }
210
+
211
+ return (this.options.lowerEmailAddressCase ? email.toLowerCase(): email);
212
+ };
213
+
214
+ // Pre-processes email or name + email, downcasing email address if necessary
215
+ emailListFieldConstructor.prototype._normalizeEmail = function(text) {
216
+ var newText = text.trim();
217
+
218
+ if (this.options.lowerEmailAddressCase) {
219
+ if (EMAIL_REGEXP.test(newText)) {
220
+ newText = newText.toLowerCase();
221
+ }
222
+ else {
223
+ var matchdata = newText.match(EMAIL_EXTRACTION_REGEXP);
224
+ var name = matchdata[1].trim();
225
+ var email = matchdata[2].toLowerCase().trim();
226
+ newText = name + ' <' + email + '>'
227
+ }
228
+ }
229
+
230
+ return newText;
231
+ };
232
+
233
+ // Checks if email is authorized to be added. It checks if email is valid and if not duplicated
234
+ emailListFieldConstructor.prototype._isEmailValidAndUnique = function(text) {
235
+ var email = this._extractEmail(text);
236
+
237
+ // prevents invalid email format
238
+ if (email == null) {
239
+ this._onInvalidEmailCallback(text);
240
+ return false;
241
+ }
242
+
243
+ // prevents duplicated email
244
+ if (this.options.allowDuplicateEmails || !this._includesEmail(email)) {
245
+ return true;
246
+ }
247
+ else {
248
+ this._onDuplicatedEmailsCallback(email);
249
+ return false;
250
+ };
251
+ }
252
+
253
+ // Checks wether email is currently in the list
254
+ emailListFieldConstructor.prototype._includesEmail = function(email) {
255
+ return this.emailsOnTaggle.indexOf(email) > -1
256
+ }
257
+
258
+ // Adds email to the list used to detect duplicates. It accepts text in the format "Name <email>" too
259
+ emailListFieldConstructor.prototype._recordEmailAdded = function(text) {
260
+ var email = this._extractEmail(text);
261
+ this.emailsOnTaggle.push(email);
262
+ }
263
+
264
+ // Removes email from the list used to detect duplicates. It accepts text in the format "Name <email>" too
265
+ emailListFieldConstructor.prototype._recordEmailRemoved = function(text) {
266
+ var email = this._extractEmail(text);
267
+ var emailIndex = this.emailsOnTaggle.indexOf(email);
268
+ if (emailIndex > -1) {
269
+ this.emailsOnTaggle.splice(emailIndex, 1);
270
+ }
271
+ }
272
+
273
+ // if add extra classes to tags, depending on the return of the options.extraTagClassFunction
274
+ emailListFieldConstructor.prototype._addExtraTagClassIfNecessary = function(text, li) {
275
+ var email = this._extractEmail(text);
276
+ var extraClasses = this.options.extraTagClassFunction(text, email);
277
+ if (extraClasses && extraClasses.length > 0) {
278
+ $(li).addClass(extraClasses);
279
+ }
280
+ }
281
+
282
+ // Checks wether email is known
283
+ emailListFieldConstructor.prototype._knowsEmail = function(email) {
284
+ return this.knownEmails.indexOf(email) > -1
285
+ }
286
+
287
+ // Initializes taggle, the lib that implements the tagging effect on the email
288
+ // list field.
289
+ emailListFieldConstructor.prototype._initTaggle = function() {
290
+ // creates scoped variable so we can acccess emailListField inside the taggle callbacks
291
+ var emailListField = this;
292
+
293
+ // adds taggle class to container
294
+ $('#' + this.containerId).addClass('taggle');
295
+
296
+ this.taggleObject = new Taggle(this.containerId, {
297
+ delimeter: new RegExp('[,;]'), // splits emails on commas and semicolons (passing regexps here is not documented on taggle, but works)
298
+ submitKeys: [44, 9, 13, 27, 186], // keycodes: 9 (tab), 13 (enter), 27 (esc), 35 (end), 186 (semicolon). Ons: cannot use 188 (comma) because it is also de key of '<', which is a necessary character for emails with name
299
+ saveOnBlur: true, // tries to save the tag when user clicks away
300
+ hiddenInputName: this.options.inputName, // how the parameters are going to be submitted
301
+ placeholder: this.options.placeholderMessage, // message to show when there are no emails on list
302
+ allowDuplicates: true, // we implement our own duplicate detection, based on the email address only
303
+ preserveCase: true, // we deal with the case separately
304
+ tabIndex: 0, // makes tab select field in form
305
+
306
+ // prepares input element to show tooltip (for validation or duplicate messages)
307
+ inputFormatter: function(input) {
308
+ $(input).tooltip({position: {my:'left top', at: 'left bottom'}});
309
+ },
310
+
311
+ // prevents invalid or duplicated emails from being added to the list
312
+ onBeforeTagAdd: function(event, tag) {
313
+ return emailListField._isEmailValidAndUnique(tag);
314
+ },
315
+
316
+ // Formats the tag, normalizing email address and adding extra classes
317
+ tagFormatter: function(li) {
318
+ var text = $(li).find('.taggle_text').text();
319
+
320
+ // trims and downcases email (even when in format Name <email>)
321
+ text = emailListField._normalizeEmail(text);
322
+
323
+ // changes li and hidden input with new text
324
+ $(li).find('.taggle_text').text(text);
325
+ $(li).find('input[type="hidden"]').val(text);
326
+
327
+ emailListField._addExtraTagClassIfNecessary(text, li);
328
+
329
+ return li;
330
+ },
331
+
332
+ // records tags that are added, so to know if new candidate tags are duplicate
333
+ onTagAdd: function(event, tag) {
334
+ emailListField._recordEmailAdded(tag);
335
+ emailListField.options.afterChangeCallback(emailListField.getEmails());
336
+ },
337
+
338
+ // remove emails from list, so we don't think it is a duplicate if added again
339
+ onTagRemove: function(event, tag) {
340
+ emailListField._recordEmailRemoved(tag);
341
+ emailListField.options.afterChangeCallback(emailListField.getEmails());
342
+ }
343
+ });
344
+
345
+ // If knownFormattedEmails has elements, activate JQueryUI autocomplete
346
+ if (this.options.knownFormattedEmails.length > 0) {
347
+ var taggle = this.taggleObject;
348
+ $(this.taggleObject.getInput()).autocomplete({
349
+ source: this.options.knownFormattedEmails,
350
+ appendTo: this.taggleObject.getContainer(),
351
+ position: { at: "left bottom", of: this.taggleObject.getContainer() },
352
+ select: function(event, data) {
353
+ event.preventDefault();
354
+
355
+ // Add the tag only when the user clicks on autocomplete. If user selects
356
+ // another way (E.g.: down + enter/tab) the text will already be added as it
357
+ // is autocompleted on the input and added by taggle automatically
358
+ if (data && data.item && event.which == 1) {
359
+ taggle.add(data.item.value);
360
+ }
361
+ }
362
+ });
363
+ }
364
+ }
365
+
366
+ emailListFieldConstructor.prototype._prepopulateTaggle = function() {
367
+ for (var i=0; i<this.options.initialEmails.length; i++) {
368
+ this.addEmail(this.options.initialEmails[i]);
369
+ }
370
+ }
371
+
372
+ // returns contructor and calls the function so EmailListField is defined immediately
373
+ return emailListFieldConstructor;
374
+ }();
@@ -0,0 +1,12 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require taggle
12
+ */
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "email_list_field"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'email_list_field/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "email_list_field"
8
+ spec.version = EmailListField::VERSION
9
+ spec.date = '2016-09-29'
10
+ spec.authors = ["Henrique Gubert"]
11
+ spec.email = ["guberthenrique@hotmail.com"]
12
+
13
+ spec.summary = %q{Produces email list fields for rails forms}
14
+ spec.description = %q{This gem provides helper functions that allows you to add email list fields to your forms in a rails app. It also provides helper functions to process the submitted data on the controllers.}
15
+ spec.homepage = "https://github.com/hsgubert/email_list_field"
16
+ spec.license = "MIT"
17
+
18
+ # # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ # if spec.respond_to?(:metadata)
21
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
22
+ # else
23
+ # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
24
+ # end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.add_runtime_dependency 'rails', '>= 3.2', '< 5.0'
32
+ spec.add_runtime_dependency 'taggle', '0.1.2'
33
+ spec.add_runtime_dependency 'jquery-rails', '~>4'
34
+ spec.add_runtime_dependency 'jquery-ui-rails', '~>5.0'
35
+
36
+ spec.add_development_dependency "bundler", "~> 1.12"
37
+ spec.add_development_dependency "rake", "~> 10.0"
38
+ spec.add_development_dependency "rspec", "~> 3.0"
39
+ end
@@ -0,0 +1,8 @@
1
+ require "email_list_field/version"
2
+ require "email_list_field/engine"
3
+ require "email_list_field/static_helpers"
4
+ require "email_list_field/test_helpers"
5
+
6
+ module EmailListField
7
+ extend EmailListField::StaticHelpers
8
+ end
@@ -0,0 +1,6 @@
1
+ require 'taggle'
2
+
3
+ module EmailListField
4
+ class Engine < Rails::Engine
5
+ end
6
+ end
@@ -0,0 +1,34 @@
1
+ module EmailListField::StaticHelpers
2
+ EMAIL_EXTRACTION_REGEXP = /^([^<>]*)<(.+)>$/
3
+
4
+ # Inputs
5
+ # => emails: an array of strings, where each string may be either an email or a "Name <email>" string
6
+ # => options:
7
+ # :lower_email_address_case [true|false] default=true
8
+ #
9
+ # Output:
10
+ # => an array of pairs [name, email], where name might be nil
11
+ #
12
+ def parse_email_list_params(emails, options={})
13
+ return [] unless emails
14
+
15
+ lower_email_address_case = (!options[:lower_email_address_case].nil? ? options[:lower_email_address_case] : true)
16
+
17
+ emails.map do |formatted_email|
18
+ stripped_formatted_email = formatted_email.strip
19
+
20
+ if matchdata = stripped_formatted_email.match(EmailListField::StaticHelpers::EMAIL_EXTRACTION_REGEXP)
21
+ parsed_email = [matchdata[1].strip, matchdata[2].strip]
22
+ else
23
+ parsed_email = [nil, stripped_formatted_email]
24
+ end
25
+
26
+ if lower_email_address_case
27
+ parsed_email[1].downcase!
28
+ end
29
+
30
+ parsed_email
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,23 @@
1
+ # Defines helpers to be used in feature/integration tests in the target app.
2
+ # These helpers work for a RSpec + Capybara + PhantomJS test suite (javascript
3
+ # must be enabled)
4
+ #
5
+ # To include these helpers add to your spec/spec_helper.rb or to you spec/rails_helper.rb:
6
+ #
7
+ # RSpec.configure do |config|
8
+ # config.include EmailListField::TestHelpers, type: :feature
9
+ # end
10
+ #
11
+ module EmailListField::TestHelpers
12
+
13
+ def fill_in_email_list_field(wrapper_id, options={})
14
+ with = options.delete(:with)
15
+ fill_options = options.delete(:fill_options)
16
+ find('#' + wrapper_id + ' input.taggle_input').set(with, fill_options)
17
+ end
18
+
19
+ def remove_from_email_list_field(wrapper_id, formatted_email)
20
+ find('#' + wrapper_id + ' li', text: formatted_email).find('button', visible: false).trigger('click')
21
+ end
22
+
23
+ end
@@ -0,0 +1,3 @@
1
+ module EmailListField
2
+ VERSION = "1.1.0"
3
+ end
data/preview.gif ADDED
Binary file
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: email_list_field
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Henrique Gubert
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-09-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: taggle
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '='
38
+ - !ruby/object:Gem::Version
39
+ version: 0.1.2
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '='
45
+ - !ruby/object:Gem::Version
46
+ version: 0.1.2
47
+ - !ruby/object:Gem::Dependency
48
+ name: jquery-rails
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '4'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '4'
61
+ - !ruby/object:Gem::Dependency
62
+ name: jquery-ui-rails
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '5.0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '5.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: bundler
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.12'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.12'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rake
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '10.0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '10.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rspec
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.0'
117
+ description: This gem provides helper functions that allows you to add email list
118
+ fields to your forms in a rails app. It also provides helper functions to process
119
+ the submitted data on the controllers.
120
+ email:
121
+ - guberthenrique@hotmail.com
122
+ executables: []
123
+ extensions: []
124
+ extra_rdoc_files: []
125
+ files:
126
+ - ".gitignore"
127
+ - ".rspec"
128
+ - ".ruby-gemset"
129
+ - ".ruby-version"
130
+ - ".travis.yml"
131
+ - Gemfile
132
+ - LICENSE.txt
133
+ - README.md
134
+ - Rakefile
135
+ - app/assets/javascripts/email_list_field.js
136
+ - app/assets/javascripts/jquery-email_list_field/email_list_field.js
137
+ - app/assets/stylesheets/email_list_field.scss
138
+ - bin/console
139
+ - bin/setup
140
+ - email_list_field.gemspec
141
+ - lib/email_list_field.rb
142
+ - lib/email_list_field/engine.rb
143
+ - lib/email_list_field/static_helpers.rb
144
+ - lib/email_list_field/test_helpers.rb
145
+ - lib/email_list_field/version.rb
146
+ - preview.gif
147
+ homepage: https://github.com/hsgubert/email_list_field
148
+ licenses:
149
+ - MIT
150
+ metadata: {}
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ requirements: []
166
+ rubyforge_project:
167
+ rubygems_version: 2.5.1
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: Produces email list fields for rails forms
171
+ test_files: []