diff --git a/LICENSE.MD b/LICENSE.md similarity index 100% rename from LICENSE.MD rename to LICENSE.md diff --git a/README.md b/README.md index 2f6bc75..7c585e7 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,23 @@ multiple-emails.js Enter multiple emails in a single input field with jQuery. -This is an improved version of the original work of Jamie Bradley http://t2a.co/blog/index.php/multiple-value-input-field-with-jquery/. +This project is forked from Pierre Clavequin's project at https://github.com/pierresh/multiple-emails.js. + +Pierre's project is an improved version of the original work of Jamie Bradley http://t2a.co/blog/index.php/multiple-value-input-field-with-jquery/. + +## New features added to Pierre's work by John: + +- "Basic" theme is now the default theme +- "Basic" theme now displays a "heavy multiplication x" (`✖` ✖) for the Remove icon +- renamed old "Basic" theme to "Text" (shows the word "Remove") for clarity +- renamed "Bootstrap" theme to "Bootstrap3" for clarity +- added new "FontAwesome" theme +- added option to "checkForEmail" formatting or not (default is true); + this allows the input field to be used for any generic text +- update border styling of widget and input field + +## New features added to Jamie's work by Pierre (and others): -## New features are: - can display emails once the page is loaded - check integrity of inputted email address - emails are encapsulated in json @@ -14,8 +28,12 @@ This is an improved version of the original work of Jamie Bradley http://t2a.co/ ## Options - $(selector).multiple_emails({ - position: 'top', // Display the added emails above the input - theme: 'bootstrap', // Bootstrap is the default theme - checkDupEmail: true // Should check for duplicate emails added - }); \ No newline at end of file +```javascript +$(selector).multiple_emails({ + position: 'top', // Display the added emails above the input + theme: 'FontAwesome', // Basic is the default theme + checkForDuplicates: true, // Should check for duplicate emails added + checkForEmail: false, // Should not check for valid email address format + placeholder: 'Email' // Use placeholder text +}); +``` diff --git a/example.html b/example.html index 64951fa..75c17ce 100644 --- a/example.html +++ b/example.html @@ -1,44 +1,45 @@ - + Multiple Emails - + - - + + - - + + - - - + + + + + - - + + +
-

Bootstrap Example

+

Bootstrap3 Example

Input email addresses

@@ -78,39 +108,73 @@

Current email addresses


- +
-
-
-

SemanticUI Example

+
+

SemanticUI Example

+
+
+

Input email addresses

+
- -
-
-

Input email addresses

- -
-
-

Current email addresses

-

-					
+
+

Current email addresses

+

 				
+

- + +
+
+

FontAwesome Example

+
+
+

Input email addresses

+ +
+
+

Current email addresses

+

+				
+
+
+
+
+ +
+
+

Text Example

+
+
+

Input email addresses

+ +
+
+

Current email addresses

+

+				
+
+
+
+
+
- +

Basic Example

-
+
+

Input email addresses

-
+

Current email addresses


 				
+
+
- + diff --git a/multiple-emails.css b/multiple-emails.css index ded0b80..4cc813e 100644 --- a/multiple-emails.css +++ b/multiple-emails.css @@ -1,43 +1,59 @@ -.multiple_emails-container { - border:1px #ccc solid; - border-radius: 4px; - box-shadow: inset 0 1px 1px rgba(0,0,0,.075); - padding:0; margin: 0; cursor:text; width:100%; +.multiple_emails-container { + padding: 0; + margin: 0; + margin-left: -5px; + cursor: text; + width: 100%; } -.multiple_emails-container input { - clear:both; - width:100%; - border:0; - outline: none; - margin-bottom:3px; - padding-left: 5px; - box-sizing: border-box; +.multiple_emails-container input { + clear: both; + width: 100%; + border: 0; + outline: none; + margin-bottom: 3px; + padding-left: 5px; + box-sizing: border-box; } -.multiple_emails-container input{ - border: 0 !important; +.multiple_emails-container input { + border: 0 !important; } -.multiple_emails-container input.multiple_emails-error { - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px red !important; - outline: thin auto red !important; +.multiple_emails-container input.multiple_emails-error { + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px red !important; + outline: thin auto red !important; } -.multiple_emails-container ul { - list-style-type:none; - padding-left: 0; +.multiple_emails-container ul { + list-style-type: none; + padding-left: 0; } -.multiple_emails-email { - margin: 3px 5px 3px 5px; - padding: 3px 5px 3px 5px; - border:1px #BBD8FB solid; - border-radius: 3px; - background: #F3F7FD; +.multiple_emails-email { + margin: 3px 5px 3px 5px; + padding: 3px 5px 3px 5px; + border: 1px #BBD8FB solid; + border-radius: 3px; + background: #F3F7FD; + width: 100%; } -.multiple_emails-close { - float:left; - margin:0 3px; +input.multiple_emails-input { + background-color: #ffffff; + border: 1px solid #ced4da !important; + border-radius: 0.25rem; + padding: 0.25rem 0.75rem; + color: #495057; + margin-left: 5px; +} + +.multiple_emails-close { + float: left; + margin: 0 3px; + text-decoration: none; +} + +a.multiple_emails-close:hover { + text-decoration: none; } diff --git a/multiple-emails.js b/multiple-emails.js index f9d4bb0..78d8c72 100644 --- a/multiple-emails.js +++ b/multiple-emails.js @@ -1,33 +1,40 @@ (function( $ ){ - + $.fn.multiple_emails = function(options) { - + // Default options var defaults = { - checkDupEmail: true, - theme: "Bootstrap", + checkForDuplicates: true, + checkForEmail: true, + theme: "Basic", position: "top", placeholder: "" }; - + // Merge send options with defaults var settings = $.extend( {}, defaults, options ); - + var deleteIconHTML = ""; - if (settings.theme.toLowerCase() == "Bootstrap".toLowerCase()) - { + if (settings.theme.toLowerCase() == "Bootstrap3".toLowerCase() || settings.theme.toLowerCase() == "Bootstrap 3".toLowerCase()) { deleteIconHTML = ''; } else if (settings.theme.toLowerCase() == "SemanticUI".toLowerCase() || settings.theme.toLowerCase() == "Semantic-UI".toLowerCase() || settings.theme.toLowerCase() == "Semantic UI".toLowerCase()) { deleteIconHTML = ''; } - else if (settings.theme.toLowerCase() == "Basic".toLowerCase()) { - //Default which you should use if you don't use Bootstrap, SemanticUI, or other CSS frameworks - deleteIconHTML = 'Remove'; + else if (settings.theme.toLowerCase() == "FontAwesome".toLowerCase() || settings.theme.toLowerCase() == "Font Awesome".toLowerCase()) { + deleteIconHTML = ''; } - + else if (settings.theme.toLowerCase() == "Text".toLowerCase()) { + deleteIconHTML = '[Remove]'; + } + else { // if (settings.theme.toLowerCase() == "Basic".toLowerCase()) { + // Default which you should use if you don't use Bootstrap, SemanticUI, or other CSS frameworks + // uses the 'heavy multiplication x' HTML entity; https://www.fileformat.info/info/unicode/char/2716/index.htm + deleteIconHTML = ''; + } + return this.each(function() { - //$orig refers to the input HTML node + // $orig refers to the input HTML node var $orig = $(this); var $list = $('
    '); // create html elements - list of email addresses as unordered list @@ -40,39 +47,39 @@ ); }); } - + var $input = $('').on('keyup', function(e) { // input $(this).removeClass('multiple_emails-error'); var input_length = $(this).val().length; - + var keynum; - if(window.event){ // IE + if(window.event){ // IE keynum = e.keyCode; } - else if(e.which){ // Netscape/Firefox/Opera + else if(e.which){ // Netscape/Firefox/Opera keynum = e.which; - } - - //if(event.which == 8 && input_length == 0) { $list.find('li').last().remove(); } //Removes last item on backspace with no input - - // Supported key press is tab, enter, space or comma, there is no support for semi-colon since the keyCode differs in various browsers - if(keynum == 9 || keynum == 32 || keynum == 188) { - display_email($(this), settings.checkDupEmail); + } + + // if(event.which == 8 && input_length == 0) { $list.find('li').last().remove(); } //Removes last item on backspace with no input + + // For email addresses, supported key press is tab, enter, space or comma, there is no support for semi-colon since the keyCode differs in various browsers + if (settings.checkForEmail === true && (keynum == 9 || keynum == 32 || keynum == 188)) { + display_email($(this), settings.checkForDuplicates, settings.checkForEmail); } else if (keynum == 13) { - display_email($(this), settings.checkDupEmail); - //Prevents enter key default - //This is to prevent the form from submitting with the submit button - //when you press enter in the email textbox + display_email($(this), settings.checkForDuplicates, settings.checkForEmail); + // Prevents enter key default + // This is to prevent the form from submitting with the submit button + // when you press enter in the email textbox e.preventDefault(); } - }).on('blur', function(event){ - if ($(this).val() != '') { display_email($(this), settings.checkDupEmail); } + }).on('blur', function(event){ + if ($(this).val() != '') { display_email($(this), settings.checkForDuplicates, settings.checkForEmail); } }); var $container = $('
    ').click(function() { $input.focus(); } ); // container div - + // insert elements into DOM if (settings.position.toLowerCase() === "top") $container.append($list).append($input).insertAfter($(this)); @@ -82,37 +89,51 @@ /* t is the text input device. Value of the input could be a long line of copy-pasted emails, not just a single email. - As such, the string is tokenized, with each token validated individually. - - If the dupEmailCheck variable is set to true, scans for duplicate emails, and invalidates input if found. - Otherwise allows emails to have duplicated values if false. + As such, the string is tokenized, with each token validated individually if checkForEmail + variable is set to true. + + If the checkForDuplicates variable is set to true, scans for duplicate emails, and + invalidates input if found. Otherwise allows emails to have duplicated values if false. */ - function display_email(t, dupEmailCheck) { - - //Remove space, comma and semi-colon from beginning and end of string - //Does not remove inside the string as the email will need to be tokenized using space, comma and semi-colon + function display_email(t, checkForDuplicates, checkForEmail) { + + // Remove space, comma and semi-colon from beginning and end of string + // Does not remove inside the string as the email will need to be tokenized using space, comma and semi-colon var arr = t.val().trim().replace(/^,|,$/g , '').replace(/^;|;$/g , ''); - //Remove the double quote - arr = arr.replace(/"/g,""); - //Split the string into an array, with the space, comma, and semi-colon as the separator - arr = arr.split(/[\s,;]+/); - - var errorEmails = new Array(); //New array to contain the errors - + if (checkForEmail) { + // Remove the double quote + arr = arr.replace(/"/g,""); + // Split the string into an array, with the space, comma, and semi-colon as the separator + arr = arr.split(/[\s,;]+/); + } + else { + arr = arr.split(); + } + + var errorEmails = new Array(); // New array to contain the errors + var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i); - - for (var i = 0; i < arr.length; i++) { - //Check if the email is already added, only if dupEmailCheck is set to true - if ( dupEmailCheck === true && $orig.val().indexOf(arr[i]) != -1 ) { - if (arr[i] && arr[i].length > 0) { + + for (var i = 0; i < arr.length; i++) { + // Check if the email is already added, only if checkForDuplicates is set to true + if ( checkForDuplicates === true && $orig.val().indexOf(arr[i]) != -1 ) { + if (arr[i] && arr[i].length > 0) { new function () { - var existingElement = $list.find('.email_name[data-email=' + arr[i].toLowerCase().replace('.', '\\.').replace('@', '\\@') + ']'); + var existingElement = $list.find('.email_name[data-email="' + arr[i].toLowerCase().replace('.', '\\.').replace('@', '\\@') + '"]'); existingElement.css('font-weight', 'bold'); setTimeout(function() { existingElement.css('font-weight', ''); }, 1500); }(); // Use a IIFE function to create a new scope so existingElement won't be overriden } } - else if (pattern.test(arr[i]) == true) { + // Check if the email is a valid address, only if checkForEmail is set to true + else if (checkForEmail === true && pattern.test(arr[i]) == true) { + $list.append($('
  • ') + .prepend($(deleteIconHTML) + .click(function(e) { $(this).parent().remove(); refresh_emails(); e.preventDefault(); }) + ) + ); + } + else if (checkForEmail === false) { $list.append($('
  • ') .prepend($(deleteIconHTML) .click(function(e) { $(this).parent().remove(); refresh_emails(); e.preventDefault(); }) @@ -129,24 +150,24 @@ t.val(""); refresh_emails (); } - + function refresh_emails () { var emails = new Array(); var container = $orig.siblings('.multiple_emails-container'); container.find('.multiple_emails-email span.email_name').each(function() { emails.push($(this).html()); }); $orig.val(JSON.stringify(emails)).trigger('change'); } - + function IsJsonString(str) { try { JSON.parse(str); } catch (e) { return false; } return true; } - + return $(this).hide(); - + }); - + }; - + })(jQuery);