@ -1,37 +1,56 @@
/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http:// ricostacruz . com / nprogress
* @ license MIT * /
/* bjy: NProgress, (c) 2013, 2014 Rico Sta. Cruz - http:// ricostacruz . com / nprogress
* bjy : @ license MIT * /
// bjy: UMD( Universal Module Definition) 模式包装, 使库能在多种模块系统( AMD, CommonJS, 浏览器全局变量)下工作
; ( function ( root , factory ) {
// bjy: 如果环境支持AMD( 如RequireJS) , 则使用define定义模块
if ( typeof define === 'function' && define . amd ) {
define ( factory ) ;
// bjy: 如果环境支持CommonJS( 如Node.js) , 则将模块导出
} else if ( typeof exports === 'object' ) {
module . exports = factory ( ) ;
// bjy: 否则, 将库挂载到全局对象( 浏览器中的window) 上
} else {
root . NProgress = factory ( ) ;
}
// bjy: 传入this( 在浏览器中为window) 作为root, 并调用工厂函数
} ) ( this , function ( ) {
// bjy: 创建NProgress对象, 作为库的命名空间
var NProgress = { } ;
// bjy: 定义NProgress的版本号
NProgress . version = '0.2.0' ;
// bjy: 定义默认配置项, 并挂载到NProgress.settings上
var Settings = NProgress . settings = {
// bjy: 进度条最小值,防止进度条在开始时看起来像没动
minimum : 0.08 ,
// bjy: 动画缓动函数
easing : 'linear' ,
// bjy: 进度条定位方式,由程序自动检测
positionUsing : '' ,
// bjy: 动画速度(毫秒)
speed : 200 ,
// bjy: 是否开启自动递增( trickle) 效果
trickle : true ,
// bjy: 自动递增的频率(毫秒)
trickleSpeed : 200 ,
// bjy: 是否显示右上角的加载旋转图标
showSpinner : true ,
// bjy: 进度条条形的选择器
barSelector : '[role="bar"]' ,
// bjy: 加载旋转图标的选择器
spinnerSelector : '[role="spinner"]' ,
// bjy: 进度条的父容器, 默认为body
parent : 'body' ,
// bjy: 进度条的HTML模板
template : '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'
} ;
/ * *
* Updates configuration .
* bjy: 更新配置 。
*
* NProgress . configure ( {
* minimum : 0.1
@ -39,130 +58,154 @@
* /
NProgress . configure = function ( options ) {
var key , value ;
// bjy: 遍历传入的配置项
for ( key in options ) {
value = options [ key ] ;
// bjy: 将有效的配置项更新到Settings对象中
if ( value !== undefined && options . hasOwnProperty ( key ) ) Settings [ key ] = value ;
}
// bjy: 返回NProgress自身, 支持链式调用
return this ;
} ;
/ * *
* Last number .
* bjy: 存储当前进度状态的变量 。
* /
NProgress . status = null ;
/ * *
* Sets the progress bar status , where ` n ` is a number from ` 0.0 ` to ` 1.0 ` .
* bjy: 设置进度条的状态 , ` n ` 是一个从 ` 0.0 ` 到 ` 1.0 ` 的数字 。
*
* NProgress . set ( 0.4 ) ;
* NProgress . set ( 1.0 ) ;
* /
NProgress . set = function ( n ) {
// bjy: 检查进度条是否已经启动
var started = NProgress . isStarted ( ) ;
// bjy: 将进度值n限制在minimum和1之间
n = clamp ( n , Settings . minimum , 1 ) ;
// bjy: 更新状态, 如果进度为1, 则将status设为null, 表示完成
NProgress . status = ( n === 1 ? null : n ) ;
// bjy: 如果进度条未渲染,则先渲染它
var progress = NProgress . render ( ! started ) ,
bar = progress . querySelector ( Settings . barSelector ) ,
speed = Settings . speed ,
ease = Settings . easing ;
// bjy: 触发重排, 以确保后续的CSS过渡效果能正确应用
progress . offsetWidth ; /* Repaint */
// bjy: 使用队列来管理动画,确保动画按顺序执行
queue ( function ( next ) {
// Set positionUsing if it hasn't already been set
// bjy: 如果定位方式未设置, 则自动检测最佳的CSS定位方式
if ( Settings . positionUsing === '' ) Settings . positionUsing = NProgress . getPositioningCSS ( ) ;
// Add transition
// bjy: 为进度条添加CSS过渡效果, 更新其位置
css ( bar , barPositionCSS ( n , speed , ease ) ) ;
// bjy: 如果进度达到100%
if ( n === 1 ) {
// Fade out
// bjy: 先设置一个无过渡的状态, 并设置opacity为1, 然后触发重排
css ( progress , {
transition : 'none' ,
opacity : 1
} ) ;
progress . offsetWidth ; /* Repaint */
// bjy: 延迟后,添加淡出动画
setTimeout ( function ( ) {
css ( progress , {
transition : 'all ' + speed + 'ms linear' ,
opacity : 0
} ) ;
// bjy: 在淡出动画完成后,移除进度条元素,并执行队列的下一个任务
setTimeout ( function ( ) {
NProgress . remove ( ) ;
next ( ) ;
} , speed ) ;
} , speed ) ;
} else {
// bjy: 如果未完成,则在动画持续时间后执行下一个任务
setTimeout ( next , speed ) ;
}
} ) ;
// bjy: 返回NProgress自身, 支持链式调用
return this ;
} ;
// bjy: 检查进度条是否已经启动( 即status是否为数字)
NProgress . isStarted = function ( ) {
return typeof NProgress . status === 'number' ;
} ;
/ * *
* Shows the progress bar .
* This is the same as setting the status to 0 % , except that it doesn ' t go backwards .
* bjy: 显示进度条 。
* bjy: 这与将状态设置为0 % 相同 , 只是它不会向后退 。
*
* NProgress . start ( ) ;
*
* /
NProgress . start = function ( ) {
// bjy: 如果进度条未启动, 则将其设置为0%
if ( ! NProgress . status ) NProgress . set ( 0 ) ;
// bjy: 定义一个递归函数, 用于实现trickle( 自动递增) 效果
var work = function ( ) {
setTimeout ( function ( ) {
// bjy: 如果进度条已被手动关闭,则停止递增
if ( ! NProgress . status ) return ;
// bjy: 调用trickle方法增加一点进度
NProgress . trickle ( ) ;
// bjy: 递归调用自身
work ( ) ;
} , Settings . trickleSpeed ) ;
} ;
// bjy: 如果配置中开启了trickle, 则开始执行
if ( Settings . trickle ) work ( ) ;
return this ;
} ;
/ * *
* Hides the progress bar .
* This is the * sort of * the same as setting the status to 100 % , with the
* difference being ` done() ` makes some placebo effect of some realistic motion .
* bjy : 隐藏进度条 。
* bjy : 这与将状态设置为100 % 类似 , 但 ` done() ` 会制造一些更逼真的动画效果 。
*
* NProgress . done ( ) ;
*
* If ` true ` is passed , it will show the progress bar even if its hidden .
* bjy: 如果传入 ` true ` , 即使进度条是隐藏的 , 它也会显示并完成 。
*
* NProgress . done ( true ) ;
* /
NProgress . done = function ( force ) {
// bjy: 如果没有强制完成且进度条未启动,则直接返回
if ( ! force && ! NProgress . status ) return this ;
// bjy: 先增加一点随机进度, 然后设置进度为100%
return NProgress . inc ( 0.3 + 0.5 * Math . random ( ) ) . set ( 1 ) ;
} ;
/ * *
* Increments by a random amount .
* bjy: 以一个随机量增加进度 。
* /
NProgress . inc = function ( amount ) {
var n = NProgress . status ;
// bjy: 如果进度条未启动,则启动它
if ( ! n ) {
return NProgress . start ( ) ;
} else if ( n > 1 ) {
// bjy: 如果进度已超过100%,不做任何事
} else {
// bjy: 如果没有指定增加的量,则根据当前进度计算一个合适的增量
if ( typeof amount !== 'number' ) {
if ( n >= 0 && n < 0.2 ) { amount = 0.1 ; }
else if ( n >= 0.2 && n < 0.5 ) { amount = 0.04 ; }
@ -171,18 +214,20 @@
else { amount = 0 ; }
}
// bjy: 计算新的进度值, 并限制在0到0.994之间, 防止达到100%后还有动画
n = clamp ( n + amount , 0 , 0.994 ) ;
return NProgress . set ( n ) ;
}
} ;
// bjy: trickle方法, 内部调用inc
NProgress . trickle = function ( ) {
return NProgress . inc ( ) ;
} ;
/ * *
* Waits for all supplied jQuery promises and
* increases the progress as the promises resolve .
* bjy: 等待所有提供的jQuery promise解决 ,
* bjy: 并在promise解决时增加进度 。
*
* @ param $promise jQUery Promise
* /
@ -190,23 +235,30 @@
var initial = 0 , current = 0 ;
NProgress . promise = function ( $promise ) {
// bjy: 如果promise不存在或已经解决, 则直接返回
if ( ! $promise || $promise . state ( ) === "resolved" ) {
return this ;
}
// bjy: 如果这是第一个promise, 则启动进度条
if ( current === 0 ) {
NProgress . start ( ) ;
}
// bjy: 增加总promise计数和当前计数
initial ++ ;
current ++ ;
// bjy: 为promise添加always回调, 无论成功或失败都会执行
$promise . always ( function ( ) {
// bjy: 当前计数减一
current -- ;
// bjy: 如果所有promise都已完成
if ( current === 0 ) {
initial = 0 ;
NProgress . done ( ) ;
} else {
// bjy: 否则, 根据已完成的promise比例更新进度条
NProgress . set ( ( initial - current ) / initial ) ;
}
} ) ;
@ -217,55 +269,65 @@
} ) ( ) ;
/ * *
* ( Internal ) renders the progress bar markup based on the ` template `
* setting .
* bjy : ( 内部 ) 根据 ` template ` 设置渲染进度条的HTML标记 。
* /
NProgress . render = function ( fromStart ) {
// bjy: 如果进度条已经渲染,则直接返回已存在的元素
if ( NProgress . isRendered ( ) ) return document . getElementById ( 'nprogress' ) ;
// bjy: 给html元素添加'nprogress-busy'类,可用于样式控制
addClass ( document . documentElement , 'nprogress-busy' ) ;
// bjy: 创建进度条的容器div
var progress = document . createElement ( 'div' ) ;
progress . id = 'nprogress' ;
// bjy: 使用模板设置其innerHTML
progress . innerHTML = Settings . template ;
var bar = progress . querySelector ( Settings . barSelector ) ,
// bjy: 如果是从头开始,则初始位置在-100%,否则根据当前状态计算位置
perc = fromStart ? '-100' : toBarPerc ( NProgress . status || 0 ) ,
parent = document . querySelector ( Settings . parent ) ,
spinner ;
// bjy: 设置进度条条的初始位置和过渡效果
css ( bar , {
transition : 'all 0 linear' ,
transform : 'translate3d(' + perc + '%,0,0)'
} ) ;
// bjy: 如果配置中不显示旋转图标,则将其移除
if ( ! Settings . showSpinner ) {
spinner = progress . querySelector ( Settings . spinnerSelector ) ;
spinner && removeElement ( spinner ) ;
}
// bjy: 如果父容器不是body, 则给父容器添加自定义类
if ( parent != document . body ) {
addClass ( parent , 'nprogress-custom-parent' ) ;
}
// bjy: 将进度条元素添加到父容器中
parent . appendChild ( progress ) ;
return progress ;
} ;
/ * *
* Removes the element . Opposite of render ( ) .
* bjy: 移除元素 。 与render ( ) 相反 。
* /
NProgress . remove = function ( ) {
// bjy: 移除html和父容器上的辅助类
removeClass ( document . documentElement , 'nprogress-busy' ) ;
removeClass ( document . querySelector ( Settings . parent ) , 'nprogress-custom-parent' ) ;
// bjy: 从DOM中移除进度条元素
var progress = document . getElementById ( 'nprogress' ) ;
progress && removeElement ( progress ) ;
} ;
/ * *
* Checks if the progress bar is rendered .
* bjy: 检查进度条是否已渲染 。
* /
NProgress . isRendered = function ( ) {
@ -273,35 +335,36 @@
} ;
/ * *
* Determine which positioning CSS rule to use .
* bjy: 确定使用哪种定位CSS规则 。
* /
NProgress . getPositioningCSS = function ( ) {
// Sniff on document.body.style
// bjy: 检查body的style属性以嗅探浏览器支持
var bodyStyle = document . body . style ;
// Sniff prefixes
// bjy: 嗅探浏览器支持的CSS前缀
var vendorPrefix = ( 'WebkitTransform' in bodyStyle ) ? 'Webkit' :
( 'MozTransform' in bodyStyle ) ? 'Moz' :
( 'msTransform' in bodyStyle ) ? 'ms' :
( 'OTransform' in bodyStyle ) ? 'O' : '' ;
// bjy: 如果支持3D变换, 则使用translate3d
if ( vendorPrefix + 'Perspective' in bodyStyle ) {
// Modern browsers with 3D support, e.g. Webkit, IE10
return 'translate3d' ;
// bjy: 如果只支持2D变换, 则使用translate
} else if ( vendorPrefix + 'Transform' in bodyStyle ) {
// Browsers without 3D support, e.g. IE9
return 'translate' ;
// bjy: 否则, 回退到使用margin( 性能较差)
} else {
// Browsers without translate() support, e.g. IE7-8
return 'margin' ;
}
} ;
/ * *
* Helpers
* bjy: 辅助函数
* /
// bjy: 将一个数值限制在最小值和最大值之间
function clamp ( n , min , max ) {
if ( n < min ) return min ;
if ( n > max ) return max ;
@ -309,8 +372,7 @@
}
/ * *
* ( Internal ) converts a percentage ( ` 0..1 ` ) to a bar translateX
* percentage ( ` -100%..0% ` ) .
* bjy : ( 内部 ) 将百分比 ( ` 0..1 ` ) 转换为进度条的translateX百分比 ( ` -100%..0% ` ) 。
* /
function toBarPerc ( n ) {
@ -319,13 +381,14 @@
/ * *
* ( Internal ) returns the correct CSS for changing the bar ' s
* position given an n percentage , and speed and ease from Settings
* bjy : ( 内部 ) 返回用于改变进度条位置的CSS ,
* bjy: 根据给定的百分比n , 以及Settings中的速度和缓动函数 。
* /
function barPositionCSS ( n , speed , ease ) {
var barCSS ;
// bjy: 根据定位方式生成不同的CSS
if ( Settings . positionUsing === 'translate3d' ) {
barCSS = { transform : 'translate3d(' + toBarPerc ( n ) + '%,0,0)' } ;
} else if ( Settings . positionUsing === 'translate' ) {
@ -334,18 +397,20 @@
barCSS = { 'margin-left' : toBarPerc ( n ) + '%' } ;
}
// bjy: 添加过渡效果
barCSS . transition = 'all ' + speed + 'ms ' + ease ;
return barCSS ;
}
/ * *
* ( Internal ) Queues a function to be executed .
* bjy : ( 内部 ) 将一个函数排队等待执行 。
* /
var queue = ( function ( ) {
var pending = [ ] ;
// bjy: 从队列中取出第一个函数并执行
function next ( ) {
var fn = pending . shift ( ) ;
if ( fn ) {
@ -353,30 +418,35 @@
}
}
// bjy: 返回一个函数,用于向队列中添加新任务
return function ( fn ) {
pending . push ( fn ) ;
// bjy: 如果这是队列中唯一的任务,则立即开始执行
if ( pending . length == 1 ) next ( ) ;
} ;
} ) ( ) ;
/ * *
* ( Internal ) Applies css properties to an element , similar to the jQuery
* css method .
* bjy : ( 内部 ) 将CSS属性应用到元素上 , 类似于jQuery的css方法 。
*
* While this helper does assist with vendor prefixed property names , it
* does not perform any manipulation of values prior to setting styles .
* bjy: 虽然这个辅助函数有助于处理带供应商前缀的属性名 ,
* bjy: 但它在设置样式之前不会对值进行任何操作 。
* /
var css = ( function ( ) {
// bjy: 常见的CSS前缀列表
var cssPrefixes = [ 'Webkit' , 'O' , 'Moz' , 'ms' ] ,
// bjy: 缓存已检测的CSS属性名
cssProps = { } ;
// bjy: 将连字符格式的字符串转换为驼峰格式
function camelCase ( string ) {
return string . replace ( /^-ms-/ , 'ms-' ) . replace ( /-([\da-z])/gi , function ( match , letter ) {
return letter . toUpperCase ( ) ;
} ) ;
}
// bjy: 获取带正确前缀的CSS属性名
function getVendorProp ( name ) {
var style = document . body . style ;
if ( name in style ) return name ;
@ -384,6 +454,7 @@
var i = cssPrefixes . length ,
capName = name . charAt ( 0 ) . toUpperCase ( ) + name . slice ( 1 ) ,
vendorName ;
// bjy: 遍历前缀,检查哪个前缀的属性被支持
while ( i -- ) {
vendorName = cssPrefixes [ i ] + capName ;
if ( vendorName in style ) return vendorName ;
@ -392,34 +463,39 @@
return name ;
}
// bjy: 获取最终的样式属性名(带缓存)
function getStyleProp ( name ) {
name = camelCase ( name ) ;
return cssProps [ name ] || ( cssProps [ name ] = getVendorProp ( name ) ) ;
}
// bjy: 应用单个CSS属性到元素
function applyCss ( element , prop , value ) {
prop = getStyleProp ( prop ) ;
element . style [ prop ] = value ;
}
// bjy: 暴露的css函数, 支持单个或多个属性设置
return function ( element , properties ) {
var args = arguments ,
prop ,
value ;
// bjy: 如果传入两个参数( element, properties对象)
if ( args . length == 2 ) {
for ( prop in properties ) {
value = properties [ prop ] ;
if ( value !== undefined && properties . hasOwnProperty ( prop ) ) applyCss ( element , prop , value ) ;
}
} else {
// bjy: 如果传入三个参数( element, prop, value)
applyCss ( element , args [ 1 ] , args [ 2 ] ) ;
}
}
} ) ( ) ;
/ * *
* ( Internal ) Determines if an element or space separated list of class names contains a class name .
* bjy : ( 内部 ) 判断一个元素或空格分隔的类名字符串是否包含某个类名 。
* /
function hasClass ( element , name ) {
@ -428,7 +504,7 @@
}
/ * *
* ( Internal ) Adds a class to an element .
* bjy : ( 内部 ) 给一个元素添加类名 。
* /
function addClass ( element , name ) {
@ -437,12 +513,12 @@
if ( hasClass ( oldList , name ) ) return ;
// Trim the opening space.
// bjy: 去掉开头的空格
element . className = newList . substring ( 1 ) ;
}
/ * *
* ( Internal ) Removes a class from an element .
* bjy : ( 内部 ) 从一个元素移除类名 。
* /
function removeClass ( element , name ) {
@ -451,17 +527,16 @@
if ( ! hasClass ( element , name ) ) return ;
// Replace the class name.
// bjy: 替换掉要移除的类名
newList = oldList . replace ( ' ' + name + ' ' , ' ' ) ;
// Trim the opening and closing spaces.
// bjy: 去掉开头和结尾的空格
element . className = newList . substring ( 1 , newList . length - 1 ) ;
}
/ * *
* ( Internal ) Gets a space separated list of the class names on the element .
* The list is wrapped with a single space on each end to facilitate finding
* matches within the list .
* bjy : ( 内部 ) 获取元素上所有类名的空格分隔列表 。
* bjy : 列表的首尾都包裹一个空格 , 以便于在列表中查找匹配项 。
* /
function classList ( element ) {
@ -469,12 +544,13 @@
}
/ * *
* ( Internal ) Removes an element from the DOM .
* bjy : ( 内部 ) 从DOM中移除一个元素 。
* /
function removeElement ( element ) {
element && element . parentNode && element . parentNode . removeChild ( element ) ;
}
// bjy: 返回NProgress对象
return NProgress ;
} ) ;