1- /* [email protected] .5 2015-10-03 */ 1+ /* [email protected] .6 2015-10-12 */ 22// shim layer with setTimeout fallback
33// credit Erik Möller and http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
44'use strict' ;
@@ -46,7 +46,8 @@ angular.module('angular-svg-round-progress').constant('roundProgressConfig', {
4646 bgcolor : "#eaeaea" ,
4747 stroke : 15 ,
4848 duration : 800 ,
49- animation : "easeOutCubic"
49+ animation : "easeOutCubic" ,
50+ offset : 0
5051} ) ;
5152
5253'use strict' ;
@@ -73,6 +74,26 @@ angular.module('angular-svg-round-progress').service('roundProgressService', [fu
7374 return isNumber ( value ) ? value : parseFloat ( ( value + '' ) . replace ( ',' , '.' ) ) ;
7475 } ;
7576
77+ service . getOffset = function ( element , options ) {
78+ var value = + options . offset || 0 ;
79+
80+ if ( options . offset === 'inherit' ) {
81+ var parent = element ;
82+ var parentScope ;
83+
84+ while ( ! parent . hasClass ( 'round-progress-wrapper' ) ) {
85+ if ( service . isDirective ( parent ) ) {
86+ parentScope = parent . scope ( ) . $parent ;
87+ value += ( ( + parentScope . offset || 0 ) + ( + parentScope . stroke || 0 ) ) ;
88+ }
89+
90+ parent = parent . parent ( ) ;
91+ }
92+ }
93+
94+ return value ;
95+ } ;
96+
7697 // credit to http://stackoverflow.com/questions/5736398/how-to-calculate-the-svg-path-for-an-arc-of-a-circle
7798 service . updateState = function ( val , total , R , ring , size , isSemicircle ) {
7899
@@ -93,6 +114,14 @@ angular.module('angular-svg-round-progress').service('roundProgressService', [fu
93114 return ring . attr ( 'd' , d ) ;
94115 } ;
95116
117+ service . isDirective = function ( el ) {
118+ if ( el && el . length ) {
119+ return ( typeof el . attr ( 'round-progress' ) !== 'undefined' || el [ 0 ] . nodeName . toLowerCase ( ) === 'round-progress' ) ;
120+ }
121+
122+ return false ;
123+ } ;
124+
96125 // Easing functions by Robert Penner
97126 // Source: http://www.robertpenner.com/easing/
98127 // License: http://www.robertpenner.com/easing_terms_of_use.html
@@ -292,7 +321,8 @@ angular.module('angular-svg-round-progress')
292321 bgcolor : "@" ,
293322 stroke : "@" ,
294323 duration : "@" ,
295- animation : "@"
324+ animation : "@" ,
325+ offset : "@"
296326 }
297327 } ;
298328
@@ -305,19 +335,21 @@ angular.module('angular-svg-round-progress')
305335
306336 return angular . extend ( base , {
307337 link : function ( scope , element ) {
308- var svg = element . find ( 'svg' ) . eq ( 0 ) ;
338+ var isNested = ! element . hasClass ( 'round-progress-wrapper' ) ;
339+ var svg = isNested ? element : element . find ( 'svg' ) . eq ( 0 ) ;
309340 var ring = svg . find ( 'path' ) . eq ( 0 ) ;
310341 var background = svg . find ( 'circle' ) . eq ( 0 ) ;
311342 var options = angular . copy ( roundProgressConfig ) ;
312343 var lastAnimationId ;
344+ var parentChangedListener ;
313345
314346 var renderCircle = function ( ) {
315347 var isSemicircle = options . semi ;
316348 var responsive = options . responsive ;
317- var radius = parseInt ( options . radius ) || 0 ;
318- var stroke = parseInt ( options . stroke ) ;
349+ var radius = + options . radius || 0 ;
350+ var stroke = + options . stroke ;
319351 var diameter = radius * 2 ;
320- var backgroundSize = radius - ( stroke / 2 ) ;
352+ var backgroundSize = radius - ( stroke / 2 ) - service . getOffset ( element , options ) ;
321353
322354 svg . css ( {
323355 "top" : 0 ,
@@ -328,9 +360,18 @@ angular.module('angular-svg-round-progress')
328360 "overflow" : "hidden" // on some browsers the background overflows, if in semicircle mode
329361 } ) ;
330362
331- // note that we can't use .attr, because if jQuery is loaded, it lowercases all attributes
332- // and viewBox is case-sensitive
333- svg [ 0 ] . setAttribute ( 'viewBox' , '0 0 ' + diameter + ' ' + ( isSemicircle ? radius : diameter ) ) ;
363+ // when nested, the element shouldn't define its own viewBox
364+ if ( ! isNested ) {
365+ // note that we can't use .attr, because if jQuery is loaded,
366+ // it lowercases all attributes and viewBox is case-sensitive
367+ svg [ 0 ] . setAttribute ( 'viewBox' , '0 0 ' + diameter + ' ' + ( isSemicircle ? radius : diameter ) ) ;
368+
369+ element . css ( {
370+ "width" : responsive ? "100%" : "auto" ,
371+ "position" : "relative" ,
372+ "padding-bottom" : responsive ? ( isSemicircle ? "50%" : "100%" ) : 0
373+ } ) ;
374+ }
334375
335376 element . css ( {
336377 "width" : responsive ? "100%" : "auto" ,
@@ -360,19 +401,19 @@ angular.module('angular-svg-round-progress')
360401 } ) ;
361402 } ;
362403
363- var renderState = function ( newValue , oldValue ) {
404+ var renderState = function ( newValue , oldValue , preventAnimationOverride ) {
364405 var max = service . toNumber ( options . max || 0 ) ;
365406 var end = newValue > 0 ? $window . Math . min ( newValue , max ) : 0 ;
366407 var start = ( oldValue === end || oldValue < 0 ) ? 0 : ( oldValue || 0 ) ; // fixes the initial animation
367408 var changeInValue = end - start ;
368409
369410 var easingAnimation = service . animations [ options . animation ] ;
370411 var startTime = new $window . Date ( ) ;
371- var duration = parseInt ( options . duration ) || 0 ;
372- var preventAnimation = ( newValue > max && oldValue > max ) || ( newValue < 0 && oldValue < 0 ) || duration < 25 ;
412+ var duration = + options . duration || 0 ;
413+ var preventAnimation = preventAnimationOverride || ( newValue > max && oldValue > max ) || ( newValue < 0 && oldValue < 0 ) || duration < 25 ;
373414
374415 var radius = options . radius ;
375- var circleSize = radius - ( options . stroke / 2 ) ;
416+ var circleSize = radius - ( options . stroke / 2 ) - service . getOffset ( element , options ) ;
376417 var elementSize = radius * 2 ;
377418 var isSemicircle = options . semi ;
378419
@@ -406,30 +447,53 @@ angular.module('angular-svg-round-progress')
406447
407448 // properties that are used only for presentation
408449 scope . $watchGroup ( keys , function ( newValue ) {
409- for ( var i = 0 ; i < newValue . length ; i ++ ) {
450+ for ( var i = 0 ; i < newValue . length ; i ++ ) {
410451 if ( typeof newValue [ i ] !== 'undefined' ) {
411452 options [ keys [ i ] ] = newValue [ i ] ;
412453 }
413454 }
414455
415456 renderCircle ( ) ;
457+ scope . $broadcast ( '$parentOffsetChanged' ) ;
458+
459+ // it doesn't have to listen for changes on the parent unless it inherits
460+ if ( options . offset === 'inherit' && ! parentChangedListener ) {
461+ parentChangedListener = scope . $on ( '$parentOffsetChanged' , function ( ) {
462+ renderState ( scope . current , scope . current , true ) ;
463+ renderCircle ( ) ;
464+ } ) ;
465+ } else if ( options . offset !== 'inherit' && parentChangedListener ) {
466+ parentChangedListener ( ) ;
467+ }
416468 } ) ;
417469
418470 // properties that are used during animation. some of these overlap with
419471 // the ones that are used for presentation
420- scope . $watchGroup ( [ 'current' , 'max' , 'animation' , 'duration' , 'radius' , 'stroke' , 'semi' ] , function ( newValue , oldValue ) {
472+ scope . $watchGroup ( [ 'current' , 'max' , 'animation' , 'duration' , 'radius' , 'stroke' , 'semi' , 'offset' ] , function ( newValue , oldValue ) {
421473 renderState ( service . toNumber ( newValue [ 0 ] ) , service . toNumber ( oldValue [ 0 ] ) ) ;
422474 } ) ;
423475 } ,
424- template :[
425- '<div class="round-progress-wrapper">' ,
426- '<svg class="round-progress" xmlns="http://www.w3.org/2000/svg">' ,
476+ template : function ( element ) {
477+ var parent = element . parent ( ) ;
478+ var directiveName = 'round-progress' ;
479+ var template = [
480+ '<svg class="' + directiveName + '" xmlns="http://www.w3.org/2000/svg">' ,
427481 '<circle fill="none"/>' ,
428482 '<path fill="none"/>' ,
429- '<g ng-transclude></g>' ,
430- '</svg>' ,
431- '</div>'
432- ] . join ( '\n' )
433- } ) ;
483+ '<g ng-transclude width></g>' ,
484+ '</svg>'
485+ ] ;
486+
487+ while ( parent . length && ! service . isDirective ( parent ) ) {
488+ parent = parent . parent ( ) ;
489+ }
490+
491+ if ( ! parent || ! parent . length ) {
492+ template . unshift ( '<div class="round-progress-wrapper">' ) ;
493+ template . push ( '</div>' ) ;
494+ }
434495
496+ return template . join ( '\n' ) ;
497+ }
498+ } ) ;
435499 } ] ) ;
0 commit comments