jquery.inputProgressBar.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. "use strict";
  2. (function ($) {
  3. /**
  4. * 去除单位转换成具体数据
  5. * @param val
  6. * @returns 具体数据
  7. */
  8. function removeUnit(val) {
  9. if (typeof (val) == "number") {
  10. return val
  11. } else {
  12. var reg = /^(-)?\d+/g;
  13. return val.match(reg);
  14. }
  15. }
  16. /**
  17. * 具体数值与占比之间的转换(且限制范围)
  18. * @param val 需转换的数值(若为占比则不包括'%')
  19. * @param max 最大范围
  20. * @param min 最小范围
  21. * @param type 转换类型 "N":占比转换成具体数值 "P":具体数值转换成占比
  22. * @returns "N"具体数值,或者"P"不含百分号的占比 NaN,代表type输入错误
  23. */
  24. function exchange(val, max, min, type) {
  25. // 保存转换数值
  26. var result = NaN;
  27. switch (type) {
  28. // 具体数值
  29. case "N":
  30. var res = Math.round((val / 100) * (max - min) + min);
  31. result = res < min ? min : res > max ? max : res;
  32. break;
  33. // 占比
  34. case "P":
  35. var res = Math.round(((val - min) / (max - min)) * 100);
  36. result = res < 0 ? 0 : res > 100 ? 100 : res;
  37. break;
  38. }
  39. return result;
  40. }
  41. /**
  42. * Input可带单位的input框的点击拖拽进度
  43. * @param Ele 实例this元素对象
  44. * @param config 配置
  45. */
  46. function InputProgressBar(Ele, config) {
  47. //@ts-ignore this
  48. var _this = this;
  49. _this.config = {
  50. dragEle: "",
  51. clickEle: "",
  52. lbEle: "",
  53. lrEle: "",
  54. //scope: 200,
  55. scope: $(config.clickEle).parents(".sp-page").width(),
  56. max: 100,
  57. min: 0,
  58. unit: "",
  59. initVal: "",
  60. isShow: config.isShow,
  61. initValue: config.initValue//initValue为null时,没有限制;initValue不为null时,禁止所有小于initValue的操作(文本框输入,拖拽进度条,点击进度条)
  62. };
  63. // 合并配置
  64. _this.config = $.extend({}, _this.config, config);
  65. // 若拖拽的元素或者点击的元素不存在,则直接退出
  66. if ($(_this.config.dragEle).length == 0 ||
  67. $(_this.config.clickEle).length == 0 ||
  68. $(_this.config.lbEle).length == 0 ||
  69. $(_this.config.lrEle).length == 0)
  70. return;
  71. // 初始化
  72. _this.init(Ele);
  73. // 绑定触发事件
  74. _this.bind();
  75. }
  76. /**
  77. * 初始
  78. * Ele:绑定的input元素
  79. */
  80. InputProgressBar.prototype.init = function (Ele) {
  81. //@ts-ignore this
  82. var _this = this;
  83. // input元素
  84. _this.inputEle = $(Ele);
  85. // 拖拽的元素
  86. _this.dragEle = $(_this.config.dragEle);
  87. // 点击的元素
  88. _this.clickEle = $(_this.config.clickEle);
  89. // 拖拽左侧背景元素
  90. _this.lbEle = $(_this.config.lbEle);
  91. // 左右两侧背景元素
  92. _this.lrEle = $(_this.config.lrEle);
  93. // 最大值显示元素
  94. _this.maxEle = $("<div/>", { class: "maxProgressBar" }).css({
  95. right: 0,
  96. });
  97. // 最小值显示元素
  98. _this.minEle = $("<div/>", { class: "minProgressBar" }).css({
  99. left: 0,
  100. });
  101. _this.lrEle.css({
  102. width: _this.config.scope + 18 + "px",
  103. height: "18px",
  104. position: "relative",
  105. top: "10px",
  106. left: 0,
  107. background: "#4DB64B",
  108. "border-radius": "9px",
  109. "z-index": 0,
  110. })
  111. _this.clickEle.css({
  112. width: _this.config.scope * (1 - _this.config.initValue / 100) + "px",
  113. height: "10px",
  114. position: "absolute",
  115. top: "4px",
  116. left: 9 + _this.config.scope * _this.config.initValue / 100 + "px",
  117. background: "#FDFDFD",
  118. "border-radius": "5px",
  119. cursor: "pointer",
  120. "z-index": 1,
  121. });
  122. _this.dragEle.css({
  123. position: "absolute",
  124. width: "20px",
  125. height: "20px",
  126. border:"1px solid #c3c3c3",
  127. "border-radius": "10px",
  128. background: "#5895C5",
  129. top: "50%",
  130. left: 0,
  131. "z-index": 5,
  132. transform: "translate(-50%, -50%)",
  133. });
  134. _this.lbEle.css({
  135. position: "absolute",
  136. width: 0,
  137. height: "10px",
  138. top: 0,
  139. left: "-1px",
  140. "z-index": 4,
  141. background: "#4DB64B",
  142. "border-radius": "5px",
  143. });
  144. // 是否显示范围
  145. if (_this.config.isShow) {
  146. _this.clickEle.append(_this.maxEle, _this.minEle);
  147. _this.maxEle.add(_this.minEle).css({
  148. height: "20px",
  149. position: "absolute",
  150. top: "-20px",
  151. "line-height": "20px",
  152. "font-size": "12px",
  153. "text-align": "center",
  154. color: "#24211c",
  155. });
  156. _this.minEle.html(_this.config.min + _this.config.unit);
  157. _this.maxEle.html(_this.config.max + _this.config.unit);
  158. }
  159. // 首次绑定数据
  160. // 当前input数值
  161. _this.nowVal =
  162. removeUnit(_this.config.initVal) ||
  163. removeUnit(_this.inputEle.val()) ||
  164. "0";
  165. // 限制范围
  166. _this.nowVal = _this.limits(Number(_this.nowVal));
  167. // input显示
  168. _this.inputEle.val(_this.nowVal + _this.config.unit);
  169. // 保存input初始值,用以后续输入错误处理
  170. _this.initVal = _this.inputEle.val();
  171. // 初次绑定
  172. // 进度条占比
  173. _this.percentage = exchange(_this.nowVal, _this.config.max, _this.config.min, "P");
  174. _this.dragEle.css({
  175. left: _this.config.initValue ? "0px" : (_this.config.scope * _this.percentage) / 100 + "px",
  176. });
  177. _this.lbEle.css({
  178. width: _this.config.initValue ? "0px" : (_this.config.scope * _this.percentage) / 100 + "px",
  179. })
  180. _this.config.cb && _this.config.cb(_this.initVal);
  181. };
  182. /**
  183. * 绑定触发事件
  184. */
  185. InputProgressBar.prototype.bind = function () {
  186. var doc = $(window.document);
  187. // @ts-ignore this
  188. var _this = this;
  189. /**
  190. * input框获取焦点事件 保存input初始值,用以后续输入错误处理
  191. */
  192. _this.bindEvent(_this.inputEle, "focus", function (event) {
  193. var e = event || window.event;
  194. _this.initVal = _this.inputEle.val();
  195. _this.inputEle.select();
  196. });
  197. /**
  198. * input框按enter键
  199. */
  200. _this.bindEvent(_this.inputEle, "keydown", function (event) {
  201. var e = event || window.event;
  202. e.stopPropagation();
  203. if (e.keyCode == 13) {
  204. _this.inputEle.blur();
  205. }
  206. });
  207. /**
  208. * input框失去焦点事件
  209. */
  210. _this.bindEvent(_this.inputEle, "blur", function (event) {
  211. var e = event || window.event;
  212. if (_this.inputEle.val() < _this.config.initValue) {
  213. _this.inputEle.val(_this.config.initValue)
  214. }
  215. var inVal = _this.inputEle.val() - _this.config.initValue;
  216. _this.handleInput(inVal);
  217. _this.config.cb && _this.config.cb(_this.initVal);
  218. });
  219. /**
  220. * 点击的元素上的点击事件
  221. */
  222. _this.bindEvent(_this.clickEle, "click", function (event) {
  223. var e = event || window.event;
  224. e.stopPropagation();
  225. e.preventDefault();
  226. // 计算left值
  227. var left = e.pageX - _this.clickEle.offset().left;
  228. // 限制当前进度范围
  229. left =
  230. left < 0 ? 0 : left > _this.config.scope * (1 - _this.config.initValue / 100) ? _this.config.scope * (1 - _this.config.initValue / 100) : left;
  231. _this.dragEle.css({
  232. left: left + "px",
  233. });
  234. _this.lbEle.css({
  235. width: left + "px",
  236. })
  237. _this.percentage = (left / _this.config.scope) * 100;
  238. _this.nowVal = exchange(_this.percentage, _this.config.max, _this.config.min, "N");
  239. _this.inputEle.val(_this.nowVal + _this.config.unit * 1 + _this.config.initValue);
  240. _this.initVal = _this.inputEle.val();
  241. _this.config.cb && _this.config.cb(_this.initVal);
  242. });
  243. /**
  244. * 拖拽的元素上的拖拽事件
  245. */
  246. _this.bindEvent(_this.dragEle, "mousedown", function () {
  247. /**
  248. * 鼠标移动
  249. */
  250. _this.bindEvent(doc, "mousemove", function (event) {
  251. var e = event || window.event;
  252. e.preventDefault();
  253. //计算元素left值
  254. var left = e.pageX - _this.clickEle.offset().left;
  255. // 限制当前进度范围
  256. left =
  257. left < 0 ? 0 : left > _this.config.scope * (1 - _this.config.initValue / 100) ? _this.config.scope * (1 - _this.config.initValue / 100) : left;
  258. _this.dragEle.css({
  259. left: left + "px",
  260. });
  261. _this.lbEle.css({
  262. width: left + "px",
  263. })
  264. _this.percentage = (left / _this.config.scope) * 100;
  265. _this.nowVal = exchange(_this.percentage, _this.config.max, _this.config.min, "N");
  266. _this.inputEle.val(_this.nowVal + _this.config.unit * 1 + _this.config.initValue);
  267. _this.initVal = _this.inputEle.val();
  268. _this.config.cb && _this.config.cb(_this.initVal);
  269. });
  270. /**
  271. * 鼠标抬起
  272. */
  273. _this.bindEvent(doc, "mouseup", function () {
  274. doc.off("mousemove"); //移除鼠标移动事件
  275. });
  276. });
  277. };
  278. /**
  279. * input框数值处理
  280. * @param val:需处理的数值
  281. */
  282. InputProgressBar.prototype.handleInput = function (val) {
  283. // @ts-ignore this
  284. var _this = this;
  285. var resVal = removeUnit(val);
  286. if (resVal === null) {
  287. _this.inputEle.val(_this.initVal);
  288. }
  289. else {
  290. // input显示
  291. _this.nowVal = _this.limits(Number(resVal));
  292. _this.inputEle.val(_this.nowVal + _this.config.unit * 1 + _this.config.initValue);
  293. _this.initVal = _this.inputEle.val();
  294. // 刷新当前进度
  295. _this.percentage = exchange(_this.nowVal, _this.config.max, _this.config.min, "P");
  296. _this.dragEle.css({
  297. left: (_this.config.scope * _this.percentage) / 100 + "px",
  298. });
  299. _this.lbEle.css({
  300. width: (_this.config.scope * _this.percentage) / 100 + "px",
  301. });
  302. }
  303. };
  304. /**
  305. * 限制范围
  306. * @param val:需限制数值
  307. */
  308. InputProgressBar.prototype.limits = function (val) {
  309. // @ts-ignore this
  310. var _this = this;
  311. var res = val < _this.config.min
  312. ? _this.config.min
  313. : val > _this.config.max
  314. ? _this.config.max
  315. : val;
  316. return res;
  317. };
  318. /**
  319. * 修改绑定事件的回调函数的_this指向
  320. * @param cb 回调函数
  321. */
  322. InputProgressBar.prototype.applyFun = function (cb) {
  323. // @ts-ignore this
  324. var _this = this;
  325. return function () {
  326. cb.apply(_this, Array.prototype.slice.call(arguments));
  327. };
  328. };
  329. /**
  330. * 绑定事件
  331. * @param Ele 绑定事件的元素
  332. * @param event 绑定的事件名称
  333. * @param cb 回调函数
  334. */
  335. InputProgressBar.prototype.bindEvent = function (Ele, event, cb) {
  336. // @ts-ignore this
  337. var _this = this;
  338. return Ele.on(event, _this.applyFun(cb));
  339. };
  340. /**
  341. * 绑定到jq原型链上
  342. * @param config 配置
  343. */
  344. $.fn.inputProgressBar = function (config) {
  345. if (this.length !== 1)
  346. return;
  347. // @ts-ignore 绑定到jq原型链
  348. return new InputProgressBar(this, config);
  349. };
  350. // @ts-ignore 需引入jq
  351. })(jQuery);