jquery-asProgress.es.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /**
  2. * jQuery asProgress v0.2.4
  3. * https://github.com/amazingSurge/jquery-asProgress
  4. *
  5. * Copyright (c) amazingSurge
  6. * Released under the LGPL-3.0 license
  7. */
  8. import $ from 'jquery';
  9. var DEFAULTS = {
  10. namespace: 'progress',
  11. bootstrap: false,
  12. min: 0,
  13. max: 100,
  14. goal: 100,
  15. speed: 20, // speed of 1/100
  16. easing: 'ease',
  17. labelCallback(n) {
  18. const percentage = this.getPercentage(n);
  19. return `${percentage}%`;
  20. }
  21. };
  22. let easingBezier = (mX1, mY1, mX2, mY2) => {
  23. 'use strict';
  24. let a = (aA1, aA2) => {
  25. return 1.0 - 3.0 * aA2 + 3.0 * aA1;
  26. };
  27. let b = (aA1, aA2) => {
  28. return 3.0 * aA2 - 6.0 * aA1;
  29. };
  30. let c = (aA1) => {
  31. return 3.0 * aA1;
  32. };
  33. // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
  34. let calcBezier = (aT, aA1, aA2) => {
  35. return ((a(aA1, aA2) * aT + b(aA1, aA2)) * aT + c(aA1)) * aT;
  36. };
  37. // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
  38. let getSlope = (aT, aA1, aA2) => {
  39. return 3.0 * a(aA1, aA2) * aT * aT + 2.0 * b(aA1, aA2) * aT + c(aA1);
  40. };
  41. let getTForX = (aX) => {
  42. // Newton raphson iteration
  43. let aGuessT = aX;
  44. for (let i = 0; i < 4; ++i) {
  45. let currentSlope = getSlope(aGuessT, mX1, mX2);
  46. if (currentSlope === 0.0) {
  47. return aGuessT;
  48. }
  49. let currentX = calcBezier(aGuessT, mX1, mX2) - aX;
  50. aGuessT -= currentX / currentSlope;
  51. }
  52. return aGuessT;
  53. };
  54. if (mX1 === mY1 && mX2 === mY2) {
  55. return {
  56. css: 'linear',
  57. fn(aX) {
  58. return aX;
  59. }
  60. };
  61. }
  62. return {
  63. css: `cubic-bezier(${mX1},${mY1},${mX2},${mY2})`,
  64. fn(aX) {
  65. return calcBezier(getTForX(aX), mY1, mY2);
  66. }
  67. };
  68. };
  69. var EASING = {
  70. ease: easingBezier(0.25, 0.1, 0.25, 1.0),
  71. linear: easingBezier(0.00, 0.0, 1.00, 1.0),
  72. 'ease-in': easingBezier(0.42, 0.0, 1.00, 1.0),
  73. 'ease-out': easingBezier(0.00, 0.0, 0.58, 1.0),
  74. 'ease-in-out': easingBezier(0.42, 0.0, 0.58, 1.0)
  75. };
  76. if (!Date.now){
  77. Date.now = () => new Date().getTime();
  78. }
  79. const vendors = ['webkit', 'moz'];
  80. for (let i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
  81. const vp = vendors[i];
  82. window.requestAnimationFrame = window[`${vp}RequestAnimationFrame`];
  83. window.cancelAnimationFrame = (window[`${vp}CancelAnimationFrame`]
  84. || window[`${vp}CancelRequestAnimationFrame`]);
  85. }
  86. if (/iP(ad|hone|od).*OS (6|7)/.test(window.navigator.userAgent) // iOS6 is buggy
  87. || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
  88. let lastTime = 0;
  89. window.requestAnimationFrame = callback => {
  90. const now = Date.now();
  91. const nextTime = Math.max(lastTime + 16, now);
  92. return setTimeout(() => {
  93. callback(lastTime = nextTime);
  94. },
  95. nextTime - now);
  96. };
  97. window.cancelAnimationFrame = clearTimeout;
  98. }
  99. function isPercentage(n) {
  100. return typeof n === 'string' && n.includes('%');
  101. }
  102. function getTime(){
  103. if (typeof window.performance !== 'undefined' && window.performance.now) {
  104. return window.performance.now();
  105. }
  106. return Date.now();
  107. }
  108. const NAMESPACE$1 = 'asProgress';
  109. /**
  110. * Plugin constructor
  111. **/
  112. class asProgress {
  113. constructor(element, options) {
  114. this.element = element;
  115. this.$element = $(element);
  116. this.options = $.extend({}, DEFAULTS, options, this.$element.data());
  117. if(this.options.bootstrap){
  118. this.namespace = 'progress';
  119. this.$target = this.$element.find('.progress-bar');
  120. this.classes = {
  121. label: `${this.namespace}-label`,
  122. bar: `${this.namespace}-bar`,
  123. disabled: 'is-disabled'
  124. };
  125. } else {
  126. this.namespace = this.options.namespace;
  127. this.classes = {
  128. label: `${this.namespace}__label`,
  129. bar: `${this.namespace}__bar`,
  130. disabled: 'is-disabled'
  131. };
  132. this.$target = this.$element;
  133. this.$element.addClass(this.namespace);
  134. }
  135. this.easing = EASING[this.options.easing] || EASING.ease;
  136. this.min = this.$target.attr('aria-valuemin');
  137. this.max = this.$target.attr('aria-valuemax');
  138. this.min = this.min? parseInt(this.min, 10): this.options.min;
  139. this.max = this.max? parseInt(this.max, 10): this.options.max;
  140. this.first = this.$target.attr('aria-valuenow');
  141. this.first = this.first? parseInt(this.first, 10): this.min;
  142. this.now = this.first;
  143. this.goal = this.options.goal;
  144. this._frameId = null;
  145. // Current state information.
  146. this._states = {};
  147. this.initialized = false;
  148. this._trigger('init');
  149. this.init();
  150. }
  151. init() {
  152. this.$bar = this.$element.find(`.${this.classes.bar}`);
  153. this.$label = this.$element.find(`.${this.classes.label}`);
  154. this.reset();
  155. this.initialized = true;
  156. this._trigger('ready');
  157. }
  158. _trigger(eventType, ...params) {
  159. let data = [this].concat(params);
  160. // event
  161. this.$element.trigger(`${NAMESPACE$1}::${eventType}`, data);
  162. // callback
  163. eventType = eventType.replace(/\b\w+\b/g, (word) => {
  164. return word.substring(0, 1).toUpperCase() + word.substring(1);
  165. });
  166. let onFunction = `on${eventType}`;
  167. if (typeof this.options[onFunction] === 'function') {
  168. this.options[onFunction].apply(this, params);
  169. }
  170. }
  171. /**
  172. * Checks whether the carousel is in a specific state or not.
  173. */
  174. is(state) {
  175. return this._states[state] && this._states[state] > 0;
  176. }
  177. getPercentage(n) {
  178. return Math.round(100 * (n - this.min) / (this.max - this.min));
  179. }
  180. go(goal) {
  181. if(!this.is('disabled')) {
  182. const that = this;
  183. this._clear();
  184. if (isPercentage(goal)) {
  185. goal = parseInt(goal.replace('%', ''), 10);
  186. goal = Math.round(this.min + (goal / 100) * (this.max - this.min));
  187. }
  188. if (typeof goal === 'undefined') {
  189. goal = this.goal;
  190. }
  191. if (goal > this.max) {
  192. goal = this.max;
  193. } else if (goal < this.min) {
  194. goal = this.min;
  195. }
  196. const start = that.now;
  197. const startTime = getTime();
  198. const animation = time => {
  199. const distance = (time - startTime)/that.options.speed;
  200. let next = Math.round(that.easing.fn(distance/100) * (that.max - that.min));
  201. if(goal > start){
  202. next = start + next;
  203. if(next > goal){
  204. next = goal;
  205. }
  206. } else{
  207. next = start - next;
  208. if(next < goal){
  209. next = goal;
  210. }
  211. }
  212. that._update(next);
  213. if (next === goal) {
  214. window.cancelAnimationFrame(that._frameId);
  215. that._frameId = null;
  216. if (that.now === that.goal) {
  217. that._trigger('finish');
  218. }
  219. } else {
  220. that._frameId = window.requestAnimationFrame(animation);
  221. }
  222. };
  223. that._frameId = window.requestAnimationFrame(animation);
  224. }
  225. }
  226. _update(n) {
  227. this.now = n;
  228. const percenage = this.getPercentage(this.now);
  229. this.$bar.css('width', `${percenage}%`);
  230. this.$target.attr('aria-valuenow', this.now);
  231. if (this.$label.length > 0 && typeof this.options.labelCallback === 'function') {
  232. this.$label.html(this.options.labelCallback.call(this, [this.now]));
  233. }
  234. this._trigger('update', n);
  235. }
  236. _clear() {
  237. if (this._frameId) {
  238. window.cancelAnimationFrame(this._frameId);
  239. this._frameId = null;
  240. }
  241. }
  242. get() {
  243. return this.now;
  244. }
  245. start() {
  246. if(!this.is('disabled')) {
  247. this._clear();
  248. this._trigger('start');
  249. this.go(this.goal);
  250. }
  251. }
  252. reset() {
  253. if(!this.is('disabled')) {
  254. this._clear();
  255. this._update(this.first);
  256. this._trigger('reset');
  257. }
  258. }
  259. stop() {
  260. this._clear();
  261. this._trigger('stop');
  262. }
  263. finish() {
  264. if(!this.is('disabled')) {
  265. this._clear();
  266. this._update(this.goal);
  267. this._trigger('finish');
  268. }
  269. }
  270. destroy() {
  271. this.$element.data(NAMESPACE$1, null);
  272. this._trigger('destroy');
  273. }
  274. enable() {
  275. this._states.disabled = 0;
  276. this.$element.removeClass(this.classes.disabled);
  277. }
  278. disable() {
  279. this._states.disabled = 1;
  280. this.$element.addClass(this.classes.disabled);
  281. }
  282. static registerEasing(name, ...args) {
  283. EASING[name] = easingBezier(...args);
  284. }
  285. static getEasing(name) {
  286. return EASING[name];
  287. }
  288. static setDefaults(options) {
  289. $.extend(DEFAULTS, $.isPlainObject(options) && options);
  290. }
  291. }
  292. var info = {
  293. version:'0.2.4'
  294. };
  295. const NAMESPACE = 'asProgress';
  296. const OtherAsProgress = $.fn.asProgress;
  297. const jQueryAsProgress = function(options, ...args) {
  298. if (typeof options === 'string') {
  299. const method = options;
  300. if (/^_/.test(method)) {
  301. return false;
  302. } else if ((/^(get)/.test(method))) {
  303. const instance = this.first().data(NAMESPACE);
  304. if (instance && typeof instance[method] === 'function') {
  305. return instance[method](...args);
  306. }
  307. } else {
  308. return this.each(function() {
  309. const instance = $.data(this, NAMESPACE);
  310. if (instance && typeof instance[method] === 'function') {
  311. instance[method](...args);
  312. }
  313. });
  314. }
  315. }
  316. return this.each(function() {
  317. if (!$(this).data(NAMESPACE)) {
  318. $(this).data(NAMESPACE, new asProgress(this, options));
  319. }
  320. });
  321. };
  322. $.fn.asProgress = jQueryAsProgress;
  323. $.asProgress = $.extend({
  324. setDefaults: asProgress.setDefaults,
  325. registerEasing: asProgress.registerEasing,
  326. getEasing: asProgress.getEasing,
  327. noConflict: function() {
  328. $.fn.asProgress = OtherAsProgress;
  329. return jQueryAsProgress;
  330. }
  331. }, info);