1"use strict"; 2 3(function ($, window, document, undefined) { 4 5 var pluginName = "emailautocomplete"; 6 var defaults = { 7 suggClass: "eac-sugg", 8 domains: ["yahoo.com" ,"hotmail.com" ,"gmail.com" ,"me.com" ,"aol.com" ,"mac.com" ,"live.com" ,"comcast.net" ,"googlemail.com" ,"msn.com" ,"hotmail.co.uk" ,"yahoo.co.uk" ,"facebook.com" ,"verizon.net" ,"sbcglobal.net" ,"att.net" ,"gmx.com" ,"outlook.com" ,"icloud.com"] 9 }; 10 11 function EmailAutocomplete(elem, options) { 12 this.$field = $(elem); 13 this.options = $.extend(true, {}, defaults, options); //we want deep extend 14 this._defaults = defaults; 15 this._domains = this.options.domains; 16 this.init(); 17 } 18 19 EmailAutocomplete.prototype = { 20 init: function () { 21 22 //shim indexOf 23 if (!Array.prototype.indexOf) { 24 this.doIndexOf(); 25 } 26 27 //this will be calculated upon keyup 28 this.fieldLeftOffset = null; 29 30 //wrap our field 31 var $wrap = $("<div class='eac-input-wrap' />").css({ 32 display: this.$field.css("display"), 33 position: this.$field.css("position") === 'static' ? 'relative' : this.$field.css("position"), 34 fontSize: this.$field.css("fontSize") 35 }); 36 this.$field.wrap($wrap); 37 38 //create container to test width of current val 39 this.$cval = $("<span class='eac-cval' />").css({ 40 visibility: "hidden", 41 position: "absolute", 42 display: "inline-block", 43 fontFamily: this.$field.css("fontFamily"), 44 fontWeight: this.$field.css("fontWeight"), 45 letterSpacing: this.$field.css("letterSpacing") 46 }).insertAfter(this.$field); 47 48 //create the suggestion overlay 49 /* touchstart jquery 1.7+ */ 50 var heightPad = (this.$field.outerHeight(true) - this.$field.height()) / 2; //padding+border 51 this.$suggOverlay = $("<span class='"+this.options.suggClass+"' />").css({ 52 display: "block", 53 "box-sizing": "content-box", //standardize 54 lineHeight: this.$field.css('lineHeight'), 55 paddingTop: heightPad + "px", 56 paddingBottom: heightPad + "px", 57 fontFamily: this.$field.css("fontFamily"), 58 fontWeight: this.$field.css("fontWeight"), 59 letterSpacing: this.$field.css("letterSpacing"), 60 position: "absolute", 61 top: 0, 62 left: 0 63 }).insertAfter(this.$field); 64 65 //bind events and handlers 66 this.$field.on("keyup.eac", $.proxy(this.displaySuggestion, this)); 67 68 this.$field.on("blur.eac", $.proxy(this.autocomplete, this)); 69 70 this.$field.on("keydown.eac", $.proxy(function(e){ 71 if(e.which === 39 || e.which === 9){ 72 this.autocomplete(); 73 } 74 }, this)); 75 76 this.$suggOverlay.on("mousedown.eac touchstart.eac", $.proxy(this.autocomplete, this)); 77 }, 78 79 suggest: function (str) { 80 var str_arr = str.split("@"); 81 if (str_arr.length > 1) { 82 str = str_arr.pop(); 83 if (!str.length) { 84 return ""; 85 } 86 } else { 87 return ""; 88 } 89 90 var match = this._domains.filter(function (domain) { 91 return domain.indexOf(str) === 0; 92 }).shift() || ""; 93 94 return match.replace(str, ""); 95 }, 96 97 autocomplete: function () { 98 if(typeof this.suggestion === "undefined" || this.suggestion.length < 1){ 99 return false; 100 } 101 this.$field.val(this.val + this.suggestion); 102 this.$suggOverlay.text(""); 103 this.$cval.text(""); 104 }, 105 106 /** 107 * Displays the suggestion, handler for field keyup event 108 */ 109 displaySuggestion: function (e) { 110 this.val = this.$field.val(); 111 this.suggestion = this.suggest(this.val); 112 113 if (!this.suggestion.length) { 114 this.$suggOverlay.text(""); 115 } else { 116 e.preventDefault(); 117 } 118 119 //update with new suggestion 120 this.$suggOverlay.text(this.suggestion); 121 this.$cval.text(this.val); 122 123 // get input padding, border and margin to offset text 124 if(this.fieldLeftOffset === null){ 125 this.fieldLeftOffset = (this.$field.outerWidth(true) - this.$field.width()) / 2; 126 } 127 128 //find width of current input val so we can offset the suggestion text 129 var cvalWidth = this.$cval.width(); 130 131 if(this.$field.outerWidth() > cvalWidth){ 132 //offset our suggestion container 133 this.$suggOverlay.css('left', this.fieldLeftOffset + cvalWidth + "px"); 134 } 135 }, 136 137 /** 138 * indexof polyfill 139 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill 140 */ 141 doIndexOf: function(){ 142 143 Array.prototype.indexOf = function (searchElement, fromIndex) { 144 if ( this === undefined || this === null ) { 145 throw new TypeError( '"this" is null or not defined' ); 146 } 147 148 var length = this.length >>> 0; // Hack to convert object.length to a UInt32 149 150 fromIndex = +fromIndex || 0; 151 152 if (Math.abs(fromIndex) === Infinity) { 153 fromIndex = 0; 154 } 155 156 if (fromIndex < 0) { 157 fromIndex += length; 158 if (fromIndex < 0) { 159 fromIndex = 0; 160 } 161 } 162 163 for (;fromIndex < length; fromIndex++) { 164 if (this[fromIndex] === searchElement) { 165 return fromIndex; 166 } 167 } 168 169 return -1; 170 }; 171 } 172 }; 173 174 $.fn[pluginName] = function (options) { 175 return this.each(function () { 176 if (!$.data(this, "yz_" + pluginName)) { 177 $.data(this, "yz_" + pluginName, new EmailAutocomplete(this, options)); 178 } 179 }); 180 }; 181 182})(jQuery, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.