JAVASCRIPT   5

nprogress.js

Guest on 14th September 2021 08:43:00 PM

  1. /* NProgress, (c) Rico Sta. Cruz - http://ricostacruz.com/nprogress
  2.  
  3.  * @license MIT */
  4.  
  5.  
  6.  
  7. ;(function(root, factory) {
  8.  
  9.  
  10.  
  11.   if (typeof define === 'function' && define.amd) {
  12.  
  13.     define(factory);
  14.  
  15.   } else if (typeof exports === 'object') {
  16.  
  17.     module.exports = factory();
  18.  
  19.   } else {
  20.  
  21.     root.NProgress = factory();
  22.  
  23.   }
  24.  
  25.  
  26.  
  27. })(this, function() {
  28.  
  29.   var NProgress = {};
  30.  
  31.  
  32.  
  33.   NProgress.version = '0.1.6';
  34.  
  35.  
  36.  
  37.   var Settings = NProgress.settings = {
  38.  
  39.     minimum: 0.08,
  40.  
  41.     easing: 'ease',
  42.  
  43.     positionUsing: '',
  44.  
  45.     speed: 200,
  46.  
  47.     trickle: true,
  48.  
  49.     trickleRate: 0.02,
  50.  
  51.     trickleSpeed: 800,
  52.  
  53.     showSpinner: true,
  54.  
  55.     barSelector: '[role="bar"]',
  56.  
  57.     spinnerSelector: '[role="spinner"]',
  58.  
  59.     parent: 'body',
  60.  
  61.     template: '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'
  62.  
  63.   };
  64.  
  65.  
  66.  
  67.   /**
  68.  
  69.    * Updates configuration.
  70.  
  71.    *
  72.  
  73.    *     NProgress.configure({
  74.  
  75.    *       minimum: 0.1
  76.  
  77.    *     });
  78.  
  79.    */
  80.  
  81.   NProgress.configure = function(options) {
  82.  
  83.     var key, value;
  84.  
  85.     for (key in options) {
  86.  
  87.       value = options[key];
  88.  
  89.       if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;
  90.  
  91.     }
  92.  
  93.  
  94.  
  95.     return this;
  96.  
  97.   };
  98.  
  99.  
  100.  
  101.   /**
  102.  
  103.    * Last number.
  104.  
  105.    */
  106.  
  107.  
  108.  
  109.   NProgress.status = null;
  110.  
  111.  
  112.  
  113.   /**
  114.  
  115.    * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
  116.  
  117.    *
  118.  
  119.    *     NProgress.set(0.4);
  120.  
  121.    *     NProgress.set(1.0);
  122.  
  123.    */
  124.  
  125.  
  126.  
  127.   NProgress.set = function(n) {
  128.  
  129.     var started = NProgress.isStarted();
  130.  
  131.  
  132.  
  133.     n = clamp(n, Settings.minimum, 1);
  134.  
  135.     NProgress.status = (n === 1 ? null : n);
  136.  
  137.  
  138.  
  139.     var progress = NProgress.render(!started),
  140.  
  141.         bar      = progress.querySelector(Settings.barSelector),
  142.  
  143.         speed    = Settings.speed,
  144.  
  145.         ease     = Settings.easing;
  146.  
  147.  
  148.  
  149.     progress.offsetWidth; /* Repaint */
  150.  
  151.  
  152.  
  153.     queue(function(next) {
  154.  
  155.       // Set positionUsing if it hasn't already been set
  156.  
  157.       if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();
  158.  
  159.  
  160.  
  161.       // Add transition
  162.  
  163.       css(bar, barPositionCSS(n, speed, ease));
  164.  
  165.  
  166.  
  167.       if (n === 1) {
  168.  
  169.         // Fade out
  170.  
  171.         css(progress, {
  172.  
  173.           transition: 'none',
  174.  
  175.           opacity: 1
  176.  
  177.         });
  178.  
  179.         progress.offsetWidth; /* Repaint */
  180.  
  181.  
  182.  
  183.         setTimeout(function() {
  184.  
  185.           css(progress, {
  186.  
  187.             transition: 'all ' + speed + 'ms linear',
  188.  
  189.             opacity: 0
  190.  
  191.           });
  192.  
  193.           setTimeout(function() {
  194.  
  195.             NProgress.remove();
  196.  
  197.             next();
  198.  
  199.           }, speed);
  200.  
  201.         }, speed);
  202.  
  203.       } else {
  204.  
  205.         setTimeout(next, speed);
  206.  
  207.       }
  208.  
  209.     });
  210.  
  211.  
  212.  
  213.     return this;
  214.  
  215.   };
  216.  
  217.  
  218.  
  219.   NProgress.isStarted = function() {
  220.  
  221.     return typeof NProgress.status === 'number';
  222.  
  223.   };
  224.  
  225.  
  226.  
  227.   /**
  228.  
  229.    * Shows the progress bar.
  230.  
  231.    * This is the same as setting the status to 0%, except that it doesn't go backwards.
  232.  
  233.    *
  234.  
  235.    *     NProgress.start();
  236.  
  237.    *
  238.  
  239.    */
  240.  
  241.   NProgress.start = function() {
  242.  
  243.     if (!NProgress.status) NProgress.set(0);
  244.  
  245.  
  246.  
  247.     var work = function() {
  248.  
  249.       setTimeout(function() {
  250.  
  251.         if (!NProgress.status) return;
  252.  
  253.         NProgress.trickle();
  254.  
  255.         work();
  256.  
  257.       }, Settings.trickleSpeed);
  258.  
  259.     };
  260.  
  261.  
  262.  
  263.     if (Settings.trickle) work();
  264.  
  265.  
  266.  
  267.     return this;
  268.  
  269.   };
  270.  
  271.  
  272.  
  273.   /**
  274.  
  275.    * Hides the progress bar.
  276.  
  277.    * This is the *sort of* the same as setting the status to 100%, with the
  278.  
  279.    * difference being `done()` makes some placebo effect of some realistic motion.
  280.  
  281.    *
  282.  
  283.    *     NProgress.done();
  284.  
  285.    *
  286.  
  287.    * If `true` is passed, it will show the progress bar even if its hidden.
  288.  
  289.    *
  290.  
  291.    *     NProgress.done(true);
  292.  
  293.    */
  294.  
  295.  
  296.  
  297.   NProgress.done = function(force) {
  298.  
  299.     if (!force && !NProgress.status) return this;
  300.  
  301.  
  302.  
  303.     return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
  304.  
  305.   };
  306.  
  307.  
  308.  
  309.   /**
  310.  
  311.    * Increments by a random amount.
  312.  
  313.    */
  314.  
  315.  
  316.  
  317.   NProgress.inc = function(amount) {
  318.  
  319.     var n = NProgress.status;
  320.  
  321.  
  322.  
  323.     if (!n) {
  324.  
  325.       return NProgress.start();
  326.  
  327.     } else {
  328.  
  329.       if (typeof amount !== 'number') {
  330.  
  331.         amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);
  332.  
  333.       }
  334.  
  335.  
  336.  
  337.       n = clamp(n + amount, 0, 0.994);
  338.  
  339.       return NProgress.set(n);
  340.  
  341.     }
  342.  
  343.   };
  344.  
  345.  
  346.  
  347.   NProgress.trickle = function() {
  348.  
  349.     return NProgress.inc(Math.random() * Settings.trickleRate);
  350.  
  351.   };
  352.  
  353.  
  354.  
  355.   /**
  356.  
  357.    * Waits for all supplied jQuery promises and
  358.  
  359.    * increases the progress as the promises resolve.
  360.  
  361.    *
  362.  
  363.    * @param $promise jQUery Promise
  364.  
  365.    */
  366.  
  367.   (function() {
  368.  
  369.     var initial = 0, current = 0;
  370.  
  371.    
  372.  
  373.     NProgress.promise = function($promise) {
  374.  
  375.       if (!$promise || $promise.state() == "resolved") {
  376.  
  377.         return this;
  378.  
  379.       }
  380.  
  381.      
  382.  
  383.       if (current == 0) {
  384.  
  385.         NProgress.start();
  386.  
  387.       }
  388.  
  389.      
  390.  
  391.       initial++;
  392.  
  393.       current++;
  394.  
  395.      
  396.  
  397.       $promise.always(function() {
  398.  
  399.         current--;
  400.  
  401.         if (current == 0) {
  402.  
  403.             initial = 0;
  404.  
  405.             NProgress.done();
  406.  
  407.         } else {
  408.  
  409.             NProgress.set((initial - current) / initial);
  410.  
  411.         }
  412.  
  413.       });
  414.  
  415.      
  416.  
  417.       return this;
  418.  
  419.     };
  420.  
  421.    
  422.  
  423.   })();
  424.  
  425.  
  426.  
  427.   /**
  428.  
  429.    * (Internal) renders the progress bar markup based on the `template`
  430.  
  431.    * setting.
  432.  
  433.    */
  434.  
  435.  
  436.  
  437.   NProgress.render = function(fromStart) {
  438.  
  439.     if (NProgress.isRendered()) return document.getElementById('nprogress');
  440.  
  441.  
  442.  
  443.     addClass(document.documentElement, 'nprogress-busy');
  444.  
  445.    
  446.  
  447.     var progress = document.createElement('div');
  448.  
  449.     progress.id = 'nprogress';
  450.  
  451.     progress.innerHTML = Settings.template;
  452.  
  453.  
  454.  
  455.     var bar      = progress.querySelector(Settings.barSelector),
  456.  
  457.         perc     = fromStart ? '-100' : toBarPerc(NProgress.status || 0),
  458.  
  459.         parent   = document.querySelector(Settings.parent),
  460.  
  461.         spinner;
  462.  
  463.    
  464.  
  465.     css(bar, {
  466.  
  467.       transition: 'all 0 linear',
  468.  
  469.       transform: 'translate3d(' + perc + '%,0,0)'
  470.  
  471.     });
  472.  
  473.  
  474.  
  475.     if (!Settings.showSpinner) {
  476.  
  477.       spinner = progress.querySelector(Settings.spinnerSelector);
  478.  
  479.       spinner && removeElement(spinner);
  480.  
  481.     }
  482.  
  483.  
  484.  
  485.     if (parent != document.body) {
  486.  
  487.       addClass(parent, 'nprogress-custom-parent');
  488.  
  489.     }
  490.  
  491.  
  492.  
  493.     parent.appendChild(progress);
  494.  
  495.     return progress;
  496.  
  497.   };
  498.  
  499.  
  500.  
  501.   /**
  502.  
  503.    * Removes the element. Opposite of render().
  504.  
  505.    */
  506.  
  507.  
  508.  
  509.   NProgress.remove = function() {
  510.  
  511.     removeClass(document.documentElement, 'nprogress-busy');
  512.  
  513.     removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent')
  514.  
  515.     var progress = document.getElementById('nprogress');
  516.  
  517.     progress && removeElement(progress);
  518.  
  519.   };
  520.  
  521.  
  522.  
  523.   /**
  524.  
  525.    * Checks if the progress bar is rendered.
  526.  
  527.    */
  528.  
  529.  
  530.  
  531.   NProgress.isRendered = function() {
  532.  
  533.     return !!document.getElementById('nprogress');
  534.  
  535.   };
  536.  
  537.  
  538.  
  539.   /**
  540.  
  541.    * Determine which positioning CSS rule to use.
  542.  
  543.    */
  544.  
  545.  
  546.  
  547.   NProgress.getPositioningCSS = function() {
  548.  
  549.     // Sniff on document.body.style
  550.  
  551.     var bodyStyle = document.body.style;
  552.  
  553.  
  554.  
  555.     // Sniff prefixes
  556.  
  557.     var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :
  558.  
  559.                        ('MozTransform' in bodyStyle) ? 'Moz' :
  560.  
  561.                        ('msTransform' in bodyStyle) ? 'ms' :
  562.  
  563.                        ('OTransform' in bodyStyle) ? 'O' : '';
  564.  
  565.  
  566.  
  567.     if (vendorPrefix + 'Perspective' in bodyStyle) {
  568.  
  569.       // Modern browsers with 3D support, e.g. Webkit, IE10
  570.  
  571.       return 'translate3d';
  572.  
  573.     } else if (vendorPrefix + 'Transform' in bodyStyle) {
  574.  
  575.       // Browsers without 3D support, e.g. IE9
  576.  
  577.       return 'translate';
  578.  
  579.     } else {
  580.  
  581.       // Browsers without translate() support, e.g. IE7-8
  582.  
  583.       return 'margin';
  584.  
  585.     }
  586.  
  587.   };
  588.  
  589.  
  590.  
  591.   /**
  592.  
  593.    * Helpers
  594.  
  595.    */
  596.  
  597.  
  598.  
  599.   function clamp(n, min, max) {
  600.  
  601.     if (n < min) return min;
  602.  
  603.     if (n > max) return max;
  604.  
  605.     return n;
  606.  
  607.   }
  608.  
  609.  
  610.  
  611.   /**
  612.  
  613.    * (Internal) converts a percentage (`0..1`) to a bar translateX
  614.  
  615.    * percentage (`-100%..0%`).
  616.  
  617.    */
  618.  
  619.  
  620.  
  621.   function toBarPerc(n) {
  622.  
  623.     return (-1 + n) * 100;
  624.  
  625.   }
  626.  
  627.  
  628.  
  629.  
  630.  
  631.   /**
  632.  
  633.    * (Internal) returns the correct CSS for changing the bar's
  634.  
  635.    * position given an n percentage, and speed and ease from Settings
  636.  
  637.    */
  638.  
  639.  
  640.  
  641.   function barPositionCSS(n, speed, ease) {
  642.  
  643.     var barCSS;
  644.  
  645.  
  646.  
  647.     if (Settings.positionUsing === 'translate3d') {
  648.  
  649.       barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };
  650.  
  651.     } else if (Settings.positionUsing === 'translate') {
  652.  
  653.       barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };
  654.  
  655.     } else {
  656.  
  657.       barCSS = { 'margin-left': toBarPerc(n)+'%' };
  658.  
  659.     }
  660.  
  661.  
  662.  
  663.     barCSS.transition = 'all '+speed+'ms '+ease;
  664.  
  665.  
  666.  
  667.     return barCSS;
  668.  
  669.   }
  670.  
  671.  
  672.  
  673.   /**
  674.  
  675.    * (Internal) Queues a function to be executed.
  676.  
  677.    */
  678.  
  679.  
  680.  
  681.   var queue = (function() {
  682.  
  683.     var pending = [];
  684.  
  685.    
  686.  
  687.     function next() {
  688.  
  689.       var fn = pending.shift();
  690.  
  691.       if (fn) {
  692.  
  693.         fn(next);
  694.  
  695.       }
  696.  
  697.     }
  698.  
  699.  
  700.  
  701.     return function(fn) {
  702.  
  703.       pending.push(fn);
  704.  
  705.       if (pending.length == 1) next();
  706.  
  707.     };
  708.  
  709.   })();
  710.  
  711.  
  712.  
  713.   /**
  714.  
  715.    * (Internal) Applies css properties to an element, similar to the jQuery
  716.  
  717.    * css method.
  718.  
  719.    *
  720.  
  721.    * While this helper does assist with vendor prefixed property names, it
  722.  
  723.    * does not perform any manipulation of values prior to setting styles.
  724.  
  725.    */
  726.  
  727.  
  728.  
  729.   var css = (function() {
  730.  
  731.     var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],
  732.  
  733.         cssProps    = {};
  734.  
  735.  
  736.  
  737.     function camelCase(string) {
  738.  
  739.       return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) {
  740.  
  741.         return letter.toUpperCase();
  742.  
  743.       });
  744.  
  745.     }
  746.  
  747.  
  748.  
  749.     function getVendorProp(name) {
  750.  
  751.       var style = document.body.style;
  752.  
  753.       if (name in style) return name;
  754.  
  755.  
  756.  
  757.       var i = cssPrefixes.length,
  758.  
  759.           capName = name.charAt(0).toUpperCase() + name.slice(1),
  760.  
  761.           vendorName;
  762.  
  763.       while (i--) {
  764.  
  765.         vendorName = cssPrefixes[i] + capName;
  766.  
  767.         if (vendorName in style) return vendorName;
  768.  
  769.       }
  770.  
  771.  
  772.  
  773.       return name;
  774.  
  775.     }
  776.  
  777.  
  778.  
  779.     function getStyleProp(name) {
  780.  
  781.       name = camelCase(name);
  782.  
  783.       return cssProps[name] || (cssProps[name] = getVendorProp(name));
  784.  
  785.     }
  786.  
  787.  
  788.  
  789.     function applyCss(element, prop, value) {
  790.  
  791.       prop = getStyleProp(prop);
  792.  
  793.       element.style[prop] = value;
  794.  
  795.     }
  796.  
  797.  
  798.  
  799.     return function(element, properties) {
  800.  
  801.       var args = arguments,
  802.  
  803.           prop,
  804.  
  805.           value;
  806.  
  807.  
  808.  
  809.       if (args.length == 2) {
  810.  
  811.         for (prop in properties) {
  812.  
  813.           value = properties[prop];
  814.  
  815.           if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);
  816.  
  817.         }
  818.  
  819.       } else {
  820.  
  821.         applyCss(element, args[1], args[2]);
  822.  
  823.       }
  824.  
  825.     }
  826.  
  827.   })();
  828.  
  829.  
  830.  
  831.   /**
  832.  
  833.    * (Internal) Determines if an element or space separated list of class names contains a class name.
  834.  
  835.    */
  836.  
  837.  
  838.  
  839.   function hasClass(element, name) {
  840.  
  841.     var list = typeof element == 'string' ? element : classList(element);
  842.  
  843.     return list.indexOf(' ' + name + ' ') >= 0;
  844.  
  845.   }
  846.  
  847.  
  848.  
  849.   /**
  850.  
  851.    * (Internal) Adds a class to an element.
  852.  
  853.    */
  854.  
  855.  
  856.  
  857.   function addClass(element, name) {
  858.  
  859.     var oldList = classList(element),
  860.  
  861.         newList = oldList + name;
  862.  
  863.  
  864.  
  865.     if (hasClass(oldList, name)) return;
  866.  
  867.  
  868.  
  869.     // Trim the opening space.
  870.  
  871.     element.className = newList.substring(1);
  872.  
  873.   }
  874.  
  875.  
  876.  
  877.   /**
  878.  
  879.    * (Internal) Removes a class from an element.
  880.  
  881.    */
  882.  
  883.  
  884.  
  885.   function removeClass(element, name) {
  886.  
  887.     var oldList = classList(element),
  888.  
  889.         newList;
  890.  
  891.  
  892.  
  893.     if (!hasClass(element, name)) return;
  894.  
  895.  
  896.  
  897.     // Replace the class name.
  898.  
  899.     newList = oldList.replace(' ' + name + ' ', ' ');
  900.  
  901.  
  902.  
  903.     // Trim the opening and closing spaces.
  904.  
  905.     element.className = newList.substring(1, newList.length - 1);
  906.  
  907.   }
  908.  
  909.  
  910.  
  911.   /**
  912.  
  913.    * (Internal) Gets a space separated list of the class names on the element.
  914.  
  915.    * The list is wrapped with a single space on each end to facilitate finding
  916.  
  917.    * matches within the list.
  918.  
  919.    */
  920.  
  921.  
  922.  
  923.   function classList(element) {
  924.  
  925.     return (' ' + (element.className || '') + ' ').replace(/\s+/gi, ' ');
  926.  
  927.   }
  928.  
  929.  
  930.  
  931.   /**
  932.  
  933.    * (Internal) Removes an element from the DOM.
  934.  
  935.    */
  936.  
  937.  
  938.  
  939.   function removeElement(element) {
  940.  
  941.     element && element.parentNode && element.parentNode.removeChild(element);
  942.  
  943.   }
  944.  
  945.  
  946.  
  947.   return NProgress;
  948.  
  949. });

Raw Paste


Login or Register to edit or fork this paste. It's free.