1/*! 2 * JavaScript Custom Forms : Number Module 3 * 4 * Copyright 2014-2015 PSD2HTML - http://psd2html.com/jcf 5 * Released under the MIT license (LICENSE.txt) 6 * 7 * Version: 1.2.3 8 */ 9 10(function(jcf) { 11 12jcf.addModule(function($) { 13 'use strict'; 14 15 return { 16 name: 'Number', 17 selector: 'input[type="number"]', 18 options: { 19 realElementClass: 'jcf-real-element', 20 fakeStructure: '<span class="jcf-number"><span class="jcf-btn-inc"></span><span class="jcf-btn-dec"></span></span>', 21 btnIncSelector: '.jcf-btn-inc', 22 btnDecSelector: '.jcf-btn-dec', 23 pressInterval: 150 24 }, 25 matchElement: function(element) { 26 return element.is(this.selector); 27 }, 28 init: function() { 29 this.initStructure(); 30 this.attachEvents(); 31 this.refresh(); 32 }, 33 initStructure: function() { 34 this.page = $('html'); 35 this.realElement = $(this.options.element).addClass(this.options.realElementClass); 36 this.fakeElement = $(this.options.fakeStructure).insertBefore(this.realElement).prepend(this.realElement); 37 this.btnDec = this.fakeElement.find(this.options.btnDecSelector); 38 this.btnInc = this.fakeElement.find(this.options.btnIncSelector); 39 40 // set initial values 41 this.initialValue = parseFloat(this.realElement.val()) || 0; 42 this.minValue = parseFloat(this.realElement.attr('min')); 43 this.maxValue = parseFloat(this.realElement.attr('max')); 44 this.stepValue = parseFloat(this.realElement.attr('step')) || 1; 45 46 // check attribute values 47 this.minValue = isNaN(this.minValue) ? -Infinity : this.minValue; 48 this.maxValue = isNaN(this.maxValue) ? Infinity : this.maxValue; 49 50 // handle range 51 if (isFinite(this.maxValue)) { 52 this.maxValue -= (this.maxValue - this.minValue) % this.stepValue; 53 } 54 }, 55 attachEvents: function() { 56 this.realElement.on({ 57 focus: this.onFocus 58 }); 59 this.btnDec.add(this.btnInc).on('jcf-pointerdown', this.onBtnPress); 60 }, 61 onBtnPress: function(e) { 62 var self = this, 63 increment; 64 65 if (!this.realElement.is(':disabled')) { 66 increment = this.btnInc.is(e.currentTarget); 67 68 self.step(increment); 69 clearInterval(this.stepTimer); 70 this.stepTimer = setInterval(function() { 71 self.step(increment); 72 }, this.options.pressInterval); 73 74 this.page.on('jcf-pointerup', this.onBtnRelease); 75 } 76 }, 77 onBtnRelease: function() { 78 clearInterval(this.stepTimer); 79 this.page.off('jcf-pointerup', this.onBtnRelease); 80 }, 81 onFocus: function() { 82 this.fakeElement.addClass(this.options.focusClass); 83 this.realElement.on({ 84 blur: this.onBlur, 85 keydown: this.onKeyPress 86 }); 87 }, 88 onBlur: function() { 89 this.fakeElement.removeClass(this.options.focusClass); 90 this.realElement.off({ 91 blur: this.onBlur, 92 keydown: this.onKeyPress 93 }); 94 }, 95 onKeyPress: function(e) { 96 if (e.which === 38 || e.which === 40) { 97 e.preventDefault(); 98 this.step(e.which === 38); 99 } 100 }, 101 step: function(increment) { 102 var originalValue = parseFloat(this.realElement.val()), 103 newValue = originalValue || 0, 104 addValue = this.stepValue * (increment ? 1 : -1), 105 edgeNumber = isFinite(this.minValue) ? this.minValue : this.initialValue - Math.abs(newValue * this.stepValue), 106 diff = Math.abs(edgeNumber - newValue) % this.stepValue; 107 108 // handle step diff
109 if (diff) { 110 if (increment) { 111 newValue += addValue - diff; 112 } else { 113 newValue -= diff; 114 } 115 } else { 116 newValue += addValue; 117 } 118 119 // handle min/max limits 120 if (newValue < this.minValue) { 121 newValue = this.minValue; 122 } else if (newValue > this.maxValue) { 123 newValue = this.maxValue; 124 } 125 126 // update value in real input if its changed 127 if (newValue !== originalValue) { 128 this.realElement.val(newValue).trigger('change'); 129 this.refresh(); 130 } 131 }, 132 refresh: function() { 133 var isDisabled = this.realElement.is(':disabled'), 134 currentValue = parseFloat(this.realElement.val()); 135 136 // handle disabled state 137 this.fakeElement.toggleClass(this.options.disabledClass, isDisabled); 138 139 // refresh button classes 140 this.btnDec.toggleClass(this.options.disabledClass, currentValue === this.minValue); 141 this.btnInc.toggleClass(this.options.disabledClass, currentValue === this.maxValue); 142 }, 143 destroy: function() { 144 // restore original structure 145 this.realElement.removeClass(this.options.realElementClass).insertBefore(this.fakeElement); 146 this.fakeElement.remove(); 147 clearInterval(this.stepTimer); 148 149 // remove event handlers 150 this.page.off('jcf-pointerup', this.onBtnRelease); 151 this.realElement.off({ 152 keydown: this.onKeyPress, 153 focus: this.onFocus, 154 blur: this.onBlur 155 }); 156 } 157 }; 158}); 159 160}(jcf));
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.