jquery-asSpinner.es.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /**
  2. * jQuery asSpinner v0.4.3
  3. * https://github.com/amazingSurge/jquery-asSpinner
  4. *
  5. * Copyright (c) amazingSurge
  6. * Released under the LGPL-3.0 license
  7. */
  8. import $ from 'jquery';
  9. var DEFAULTS = {
  10. namespace: 'asSpinner',
  11. skin: null,
  12. disabled: false,
  13. min: -10,
  14. max: 10,
  15. step: 1,
  16. name: null,
  17. precision: 0,
  18. rule: null, //string, shortcut define max min step precision
  19. looping: true, // if cycling the value when it is outofbound
  20. mousewheel: false, // support mouse wheel
  21. format(value) { // function, define custom format
  22. return value;
  23. },
  24. parse(value) { // function, parse custom format value
  25. return parseFloat(value);
  26. }
  27. };
  28. var RULES = {
  29. defaults: {
  30. min: null,
  31. max: null,
  32. step: 1,
  33. precision: 0
  34. },
  35. currency: {
  36. min: 0.00,
  37. max: 99999,
  38. step: 0.01,
  39. precision: 2
  40. },
  41. quantity: {
  42. min: 1,
  43. max: 999,
  44. step: 1,
  45. precision: 0
  46. },
  47. percent: {
  48. min: 1,
  49. max: 100,
  50. step: 1,
  51. precision: 0
  52. },
  53. month: {
  54. min: 1,
  55. max: 12,
  56. step: 1,
  57. precision: 0
  58. },
  59. day: {
  60. min: 1,
  61. max: 31,
  62. step: 1,
  63. precision: 0
  64. },
  65. hour: {
  66. min: 0,
  67. max: 23,
  68. step: 1,
  69. precision: 0
  70. },
  71. minute: {
  72. min: 1,
  73. max: 59,
  74. step: 1,
  75. precision: 0
  76. },
  77. second: {
  78. min: 1,
  79. max: 59,
  80. step: 1,
  81. precision: 0
  82. }
  83. };
  84. const NAMESPACE$1 = 'asSpinner';
  85. class asSpinner {
  86. constructor(element, options) {
  87. this.element = element;
  88. this.$element = $(element);
  89. this.options = $.extend({}, DEFAULTS, options, this.$element.data());
  90. this.namespace = this.options.namespace;
  91. if (this.options.rule) {
  92. const that = this;
  93. const array = ['min', 'max', 'step', 'precision'];
  94. $.each(array, (key, value) => {
  95. that[value] = RULES[that.options.rule][value];
  96. });
  97. } else {
  98. this.min = this.options.min;
  99. this.max = this.options.max;
  100. this.step = this.options.step;
  101. this.precision = this.options.precision;
  102. }
  103. this.disabled = this.options.disabled;
  104. if (this.$element.prop('disabled')) {
  105. this.disabled = true;
  106. }
  107. this.value = this.options.parse(this.$element.val());
  108. this.mousewheel = this.options.mousewheel;
  109. if (this.mousewheel && !$.event.special.mousewheel) {
  110. this.mousewheel = false;
  111. }
  112. this.eventBinded = false;
  113. this.spinTimeout = null;
  114. this.isFocused = false;
  115. this.classes = {
  116. disabled: `${this.namespace}_disabled`,
  117. skin: `${this.namespace}_${this.options.skin}`,
  118. focus: `${this.namespace}_focus`,
  119. control: `${this.namespace}-control`,
  120. down: `${this.namespace}-down`,
  121. up: `${this.namespace}-up`,
  122. wrap: this.namespace
  123. };
  124. this._trigger('init');
  125. this.init();
  126. }
  127. init() {
  128. this.$control = $(`<div class="${this.namespace}-control"><span class="${this.classes.up}"></span><span class="${this.classes.down}"></span></div>`);
  129. this.$wrap = this.$element.wrap(`<div tabindex="0" class="${this.classes.wrap}"></div>`).parent();
  130. this.$down = this.$control.find(`.${this.classes.down}`);
  131. this.$up = this.$control.find(`.${this.classes.up}`);
  132. if (this.options.skin) {
  133. this.$wrap.addClass(this.classes.skin);
  134. }
  135. this.$control.appendTo(this.$wrap);
  136. if (this.disabled === false) {
  137. // attach event
  138. this.bindEvent();
  139. } else {
  140. this.disable();
  141. }
  142. // inital
  143. this._trigger('ready');
  144. }
  145. _trigger(eventType, ...params) {
  146. let data = [this].concat(params);
  147. // event
  148. this.$element.trigger(`${NAMESPACE$1}::${eventType}`, data);
  149. // callback
  150. eventType = eventType.replace(/\b\w+\b/g, (word) => {
  151. return word.substring(0, 1).toUpperCase() + word.substring(1);
  152. });
  153. let onFunction = `on${eventType}`;
  154. if (typeof this.options[onFunction] === 'function') {
  155. this.options[onFunction].apply(this, params);
  156. }
  157. }
  158. // 500ms to detect if it is a click event
  159. // 60ms interval execute if it if long pressdown
  160. spin(fn, timeout) {
  161. const that = this;
  162. const spinFn = timeout => {
  163. clearTimeout(that.spinTimeout);
  164. that.spinTimeout = setTimeout(() => {
  165. fn.call(that);
  166. spinFn(60);
  167. }, timeout);
  168. };
  169. spinFn(timeout || 500);
  170. }
  171. bindEvent() {
  172. const that = this;
  173. this.eventBinded = true;
  174. this.$wrap.on('focus.asSpinner', () => {
  175. that.$wrap.addClass(that.classes.focus);
  176. }).on('blur.asSpinner', () => {
  177. if (!that.isFocused) {
  178. that.$wrap.removeClass(that.classes.focus);
  179. }
  180. });
  181. this.$down.on('mousedown.asSpinner', () => {
  182. $(document).one('mouseup.asSpinner', () => {
  183. clearTimeout(that.spinTimeout);
  184. });
  185. that.spin(that.spinDown);
  186. }).on('mouseup.asSpinner', () => {
  187. clearTimeout(that.spinTimeout);
  188. $(document).off('mouseup.asSpinner');
  189. }).on('click.asSpinner', () => {
  190. that.spinDown();
  191. });
  192. this.$up.on('mousedown.asSpinner', () => {
  193. $(document).one('mouseup.asSpinner', () => {
  194. clearTimeout(that.spinTimeout);
  195. });
  196. that.spin(that.spinUp);
  197. }).on('mouseup.asSpinner', () => {
  198. clearTimeout(that.spinTimeout);
  199. $(document).off('mouseup.asSpinner');
  200. }).on('click.asSpinner', () => {
  201. that.spinUp();
  202. });
  203. this.$element.on('focus.asSpinner', function() {
  204. that.isFocused = true;
  205. that.$wrap.addClass(that.classes.focus);
  206. // keyboard support
  207. $(this).on('keydown.asSpinner', e => {
  208. /*eslint consistent-return: "off"*/
  209. const key = e.keyCode || e.which;
  210. if (key === 38) {
  211. that.applyValue();
  212. that.spinUp();
  213. return false;
  214. }
  215. if (key === 40) {
  216. that.applyValue();
  217. that.spinDown();
  218. return false;
  219. }
  220. if (key <= 57 && key >= 48) {
  221. setTimeout(() => {
  222. //that.set(parseFloat(it.value));
  223. }, 0);
  224. }
  225. });
  226. // mousewheel support
  227. if (that.mousewheel === true) {
  228. $(this).mousewheel((event, delta) => {
  229. if (delta > 0) {
  230. that.spinUp();
  231. } else {
  232. that.spinDown();
  233. }
  234. return false;
  235. });
  236. }
  237. }).on('blur.asSpinner', function() {
  238. that.isFocused = false;
  239. that.$wrap.removeClass(that.classes.focus);
  240. $(this).off('keydown.asSpinner');
  241. if (that.mousewheel === true) {
  242. $(this).unmousewheel();
  243. }
  244. that.applyValue();
  245. });
  246. }
  247. unbindEvent() {
  248. this.eventBinded = false;
  249. this.$element.off('.asSpinner');
  250. this.$down.off('.asSpinner');
  251. this.$up.off('.asSpinner');
  252. this.$wrap.off('.asSpinner');
  253. }
  254. isNumber(value) {
  255. if (typeof value === 'number' && $.isNumeric(value)) {
  256. return true;
  257. }
  258. return false;
  259. }
  260. isOutOfBounds(value) {
  261. if (value < this.min) {
  262. return -1;
  263. }
  264. if (value > this.max) {
  265. return 1;
  266. }
  267. return 0;
  268. }
  269. applyValue() {
  270. if (this.options.format(this.value) !== this.$element.val()) {
  271. this.set(this.options.parse(this.$element.val()));
  272. }
  273. }
  274. _set(value) {
  275. if (isNaN(value)) {
  276. value = this.min;
  277. }
  278. const valid = this.isOutOfBounds(value);
  279. if (valid !== 0) {
  280. if (this.options.looping === true) {
  281. value = (valid === 1) ? this.min : this.max;
  282. } else {
  283. value = (valid === -1) ? this.min : this.max;
  284. }
  285. }
  286. this.value = value = Number(value).toFixed(this.precision);
  287. this.$element.val(this.options.format(this.value));
  288. }
  289. set(value) {
  290. this._set(value);
  291. this._trigger('change', this.value);
  292. }
  293. get() {
  294. return this.value;
  295. }
  296. /* Public methods */
  297. update(obj) {
  298. const that = this;
  299. ['min', 'max', 'precision', 'step'].forEach(value => {
  300. if (obj[value]) {
  301. that[value] = obj[value];
  302. }
  303. });
  304. if (obj.value) {
  305. this.set(obj.value);
  306. }
  307. return this;
  308. }
  309. val(value) {
  310. if (value) {
  311. this.set(this.options.parse(value));
  312. } else {
  313. return this.get();
  314. }
  315. }
  316. spinDown() {
  317. if (!$.isNumeric(this.value)) {
  318. this.value = 0;
  319. }
  320. this.value = parseFloat(this.value) - parseFloat(this.step);
  321. this.set(this.value);
  322. return this;
  323. }
  324. spinUp() {
  325. if (!$.isNumeric(this.value)) {
  326. this.value = 0;
  327. }
  328. this.value = parseFloat(this.value) + parseFloat(this.step);
  329. this.set(this.value);
  330. return this;
  331. }
  332. enable() {
  333. this.disabled = false;
  334. this.$wrap.removeClass(this.classes.disabled);
  335. this.$element.prop('disabled', false);
  336. if (this.eventBinded === false) {
  337. this.bindEvent();
  338. }
  339. this._trigger('enable');
  340. return this;
  341. }
  342. disable() {
  343. this.disabled = true;
  344. this.$element.prop('disabled', true);
  345. this.$wrap.addClass(this.classes.disabled);
  346. this.unbindEvent();
  347. this._trigger('disable');
  348. return this;
  349. }
  350. destroy() {
  351. this.unbindEvent();
  352. this.$control.remove();
  353. this.$element.unwrap();
  354. this._trigger('destroy');
  355. return this;
  356. }
  357. static setDefaults(options) {
  358. $.extend(DEFAULTS, $.isPlainObject(options) && options);
  359. }
  360. }
  361. var info = {
  362. version:'0.4.3'
  363. };
  364. const NAMESPACE = 'asSpinner';
  365. const OtherAsSpinner = $.fn.asSpinner;
  366. const jQueryAsSpinner = function(options, ...args) {
  367. if (typeof options === 'string') {
  368. const method = options;
  369. if (/^_/.test(method)) {
  370. return false;
  371. } else if ((/^(get)$/.test(method)) || (method === 'val' && args.length === 0)) {
  372. const instance = this.first().data(NAMESPACE);
  373. if (instance && typeof instance[method] === 'function') {
  374. return instance[method](...args);
  375. }
  376. } else {
  377. return this.each(function() {
  378. const instance = $.data(this, NAMESPACE);
  379. if (instance && typeof instance[method] === 'function') {
  380. instance[method](...args);
  381. }
  382. });
  383. }
  384. }
  385. return this.each(function() {
  386. if (!$(this).data(NAMESPACE)) {
  387. $(this).data(NAMESPACE, new asSpinner(this, options));
  388. }
  389. });
  390. };
  391. $.fn.asSpinner = jQueryAsSpinner;
  392. $.asSpinner = $.extend({
  393. setDefaults: asSpinner.setDefaults,
  394. noConflict: function() {
  395. $.fn.asSpinner = OtherAsSpinner;
  396. return jQueryAsSpinner;
  397. }
  398. }, info);