1/* https://github.com/cloudfour/hideShowPassword */ 2(function (factory, global) { 3 if (typeof define === 'function' && define.amd) { 4 // AMD. Register as an anonymous module. 5 // To use Zepto, map Zepto to the the name 'jquery' in your paths config 6 define(['jquery'], factory); 7 } else { 8 // Browser globals 9 factory(global.jQuery || global.Zepto); 10 } 11}(function ($, undef) { 12 13 var dataKey = 'plugin_hideShowPassword' // Where to store instances 14 , defaults = { 15 // Visibility of the password text. Can be true, false, 'toggle' 16 // or 'infer'. If 'toggle', it will be the opposite of whatever 17 // it currently is. If 'infer', it will be based on the input 18 // type (false if 'password', otherwise true). 19 show: 'infer', 20 21 // Set to true to create an inner toggle for this input. 22 innerToggle: false, 23 24 // Specify an event for the input that should make the innerToggle 25 // visible. If false, the toggle will be immediately visible. 26 // Example: 'focus' 27 hideToggleUntil: false, 28 29 // By default, the innerToggle will work like any old clickable 30 // element. If this is set to true, it will use touch-optimized 31 // events so you can tap it on a touch device without losing 32 // your input focus. 33 touchSupport: false, 34 35 // Event to use for inner toggle when touchSupport is false. 36 toggleEvent: 'click', 37 38 // ...and when touchSupport is true. 39 toggleTouchEvent: 'touchstart mousedown', 40 41 // When innerToggle is true, the input needs to be wrapped in 42 // a containing element. You can specify the class name of this 43 // element here. Useful for custom styles. 44 wrapperClass: 'hideShowPassword-wrapper', 45 46 // Class name for the inner toggle. 47 toggleClass: 'hideShowPassword-toggle', 48 49 // The states object includes settings specific to the "shown" 50 // or "hidden" states of the input field. 51 states: { 52 53 // These settings are applied when the password text is 54 // visible (show: true). 55 shown: { 56 57 // Class to apply to the input element. 58 inputClass: 'hideShowPassword-shown', 59 60 // Event to trigger on the input. 61 eventName: 'passwordShown', 62 63 // Class to apply to the toggle. 64 toggleClass: 'hideShowPassword-toggle-hide', 65 66 // Text of the toggle element. 67 toggleText: '', 68 69 // Property values to apply to the input element. 70 attr: { 71 'type': 'text', 72 'autocapitalize': 'off', 73 'autocomplete': 'off', 74 'autocorrect': 'off', 75 'spellcheck': 'false' 76 } 77 }, 78 79 // Settings when text is hidden (show: false). 80 hidden: { 81 inputClass: 'hideShowPassword-hidden', 82 eventName: 'passwordHidden', 83 toggleClass: 'hideShowPassword-toggle-show', 84 toggleText: '', 85 attr: { 'type': 'password' } 86 } 87 }, 88 89 // When innerToggle is true, some elements are styled based 90 // on their width. Unless box-sizing is set to border-box, 91 // outerWidth() is a more reliable method than width(), but it is 92 // not included with Zepto. If you plan to include your own plugin 93 // for determining width, you can specify its key as a string to 94 // override these defaults. 95 widthMethod: ($.fn.outerWidth === undef) ? 'width' : 'outerWidth', 96 heightMethod: ($.fn.outerHeight === undef) ? 'height' : 'outerHeight' 97 }; 98 99 // Constructor 100 function HideShowPassword(element, options) { 101 this.element = $(element); 102 this.init(options); 103 } 104 105 HideShowPassword.prototype = { 106 107 // Initialization logic (only runs first time) 108 init: function (options) { 109 this.update(options, defaults, (this.element.prop('type') === 'password')); 110 if (this.options.innerToggle) { 111 this.initInnerToggle(this.element, this.options); 112 } 113 }, 114 115 // Processes fresh options and updates the input state 116 update: function (options, base, toggleFallback) { 117 base = base || this.options; 118 toggleFallback = toggleFallback || !this.options.show; 119 // Allow show/hide shorthand 120 if (typeof options !== 'object') { 121 options = { show: options }; 122 } 123 // Update the options 124 this.options = $.extend(true, {}, base, options); 125 // Interpret strings 126 if (this.options.show === 'toggle') { 127 this.options.show = toggleFallback; 128 }
129 if (this.options.show === 'infer') { 130 this.options.show = (this.element.prop('type') !== 'password'); 131 } 132 // Apply and remove attributes based on the new state 133 this.ifCurrentOrNot($.proxy(function (state) { 134 // This is a loop because Zepto's prop method does not 135 // support an object of key/value pairs. 136 $.each(state.attr, $.proxy(function (key, value) { 137 this.element.prop(key, value); 138 }, this)); 139 this.element.addClass(state.inputClass).trigger(state.eventName); 140 }, this), $.proxy(function (state) { 141 this.element.removeClass(state.inputClass); 142 }, this)); 143 }, 144 145 // Toggle shorthand 146 toggle: function () { 147 this.update('toggle'); 148 }, 149 150 // Return the current state key 151 currentStateKey: function () { 152 return this.options.show ? 'shown' : 'hidden'; 153 }, 154 155 // Loop through all states, perform one action for 156 // the current state and another for others. 157 ifCurrentOrNot: function (ifCurrent, ifNot) { 158 var currentKey = this.currentStateKey(); 159 $.each(this.options.states, function (thisKey, state) { 160 ((currentKey === thisKey) ? ifCurrent : ifNot)(state); 161 }); 162 }, 163 164 // Build the inner toggle, wrapper, and associated events 165 initInnerToggle: function (el, options) { 166 167 var attachment = (el.css('direction') === 'rtl') ? 'left' : 'right' 168 , elWidth = el[options.widthMethod]() 169 , wrapperCSS = { 170 position: 'relative', 171 display: el.css('display'), 172 verticalAlign: el.css('verticalAlign'), 173 marginTop: el.css('marginTop'), 174 marginRight: el.css('marginRight'), 175 marginBottom: el.css('marginBottom'), 176 marginLeft: el.css('marginLeft') 177 } 178 , toggleCSS = { 179 position: 'absolute', 180 top: '50%', 181 mozUserSelect: 'none', 182 webkitUserSelect: 'none', 183 msUserSelect: 'none', 184 userSelect: 'none' 185 } 186 , elCSS = { 187 marginTop: 0, 188 marginRight: 0, 189 marginBottom: 0, 190 marginLeft: 0 191 } 192 , eventName = '' 193 , elWidth 194 , wrapper 195 , toggle; 196 197 el.wrap($('<div />').addClass(options.wrapperClass).css(wrapperCSS)); 198 wrapper = el.parent(); 199 if (wrapper[options.widthMethod]() !== elWidth) { 200 wrapper.css('width', elWidth); 201 } 202 203 toggle = $('<div />').addClass(options.toggleClass); 204 this.updateInnerToggle(toggle, this.currentStateKey(), options.states); 205 toggleCSS[attachment] = 0; 206 toggle.css(toggleCSS); 207 toggle.appendTo(wrapper); 208 toggle.css('marginTop', (toggle[options.heightMethod]() / -2)); 209 210 elCSS['padding' + attachment.replace(/./, function(m) { return m[0].toUpperCase() })] = toggle[options.widthMethod](); 211 el.css(elCSS); 212 213 if (options.touchSupport) {
214 toggle.css('pointerEvents', 'none'); 215 el.on(options.toggleTouchEvent, $.proxy(function (event) { 216 var toggleX = toggle.offset().left 217 , eventX 218 , lesser 219 , greater; 220 if (toggleX) { 221 eventX = event.pageX || event.originalEvent.pageX; 222 if (attachment === 'left') { 223 toggleX+= toggle[options.widthMethod](); 224 lesser = eventX; 225 greater = toggleX; 226 } else { 227 lesser = toggleX; 228 greater = eventX; 229 } 230 if (greater >= lesser) { 231 event.preventDefault(); 232 this.toggle(); 233 } 234 } 235 }, this)); 236 } else { 237 toggle.on(options.toggleEvent, $.proxy(function () { 238 this.toggle(); 239 }, this)); 240 } 241 242 $.each(options.states, function (key, state) { 243 eventName += state.eventName + ' '; 244 }); 245 el.on(eventName, $.proxy(function () { 246 this.updateInnerToggle(toggle, this.currentStateKey(), options.states); 247 }, this)); 248 249 250 if (options.hideToggleUntil) { 251 toggle.hide(); 252 el.one(options.hideToggleUntil, function () { 253 toggle.show(); 254 }); 255 } 256 257 }, 258 259 // Update the inner toggle (text, class, etc.) 260 updateInnerToggle: function (el, currentKey, states) { 261 this.ifCurrentOrNot(function (state) { 262 el.addClass(state.toggleClass).text(state.toggleText); 263 }, function (state) { 264 el.removeClass(state.toggleClass); 265 }); 266 } 267 268 }; 269 270 // The main function, reuses previous instance if it exists 271 $.fn.hideShowPassword = function (options) { 272 return this.each(function () { 273 var $this = $(this) 274 , data = $this.data(dataKey); 275 if (data) { 276 data.update(options); 277 } else { 278 $this.data(dataKey, new HideShowPassword(this, options)); 279 } 280 }); 281 }; 282 283 // Shorthand plugins 284 $.each({ 'show':true, 'hide':false, 'toggle':'toggle' }, function (verb, showVal) { 285 $.fn[verb + 'Password'] = function (options) { 286 return this.hideShowPassword($.extend({}, options, { show: showVal })); 287 }; 288 }); 289 290}, this));
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.