@@ -343,7 +343,7 @@ function merge(src, dst) {
343
343
}
344
344
345
345
function compile ( element , parentScope , overrides ) {
346
- var compiler = new Compiler ( angularTextMarkup , angularAttrMarkup , angularDirective , angularWidget ) ;
346
+ var compiler = new Compiler ( angularTextMarkup , angularAttrMarkup , angularDirective , angularWidget ) ,
347
347
$element = jqLite ( element ) ,
348
348
parent = extend ( { } , parentScope ) ;
349
349
parent . $element = $element ;
@@ -641,30 +641,30 @@ Compiler.prototype = {
641
641
} ;
642
642
643
643
function eachTextNode ( element , fn ) {
644
- var i , chldNodes = element [ 0 ] . childNodes || [ ] , size = chldNodes . length , chld ;
645
- for ( i = 0 ; i < size ; i ++ ) {
644
+ var i , chldNodes = element [ 0 ] . childNodes || [ ] , chld ;
645
+ for ( i = 0 ; i < chldNodes . length ; i ++ ) {
646
646
if ( isTextNode ( chld = chldNodes [ i ] ) ) {
647
647
fn ( jqLite ( chld ) , i ) ;
648
648
}
649
649
}
650
650
}
651
651
652
652
function eachNode ( element , fn ) {
653
- var i , chldNodes = element [ 0 ] . childNodes || [ ] , size = chldNodes . length , chld ;
654
- for ( i = 0 ; i < size ; i ++ ) {
653
+ var i , chldNodes = element [ 0 ] . childNodes || [ ] , chld ;
654
+ for ( i = 0 ; i < chldNodes . length ; i ++ ) {
655
655
if ( ! isTextNode ( chld = chldNodes [ i ] ) ) {
656
656
fn ( jqLite ( chld ) , i ) ;
657
657
}
658
658
}
659
659
}
660
660
661
661
function eachAttribute ( element , fn ) {
662
- var i , attrs = element [ 0 ] . attributes || [ ] , size = attrs . length , chld , attr , attrValue = { } ;
663
- for ( i = 0 ; i < size ; i ++ ) {
662
+ var i , attrs = element [ 0 ] . attributes || [ ] , chld , attr , attrValue = { } ;
663
+ for ( i = 0 ; i < attrs . length ; i ++ ) {
664
664
attr = attrs [ i ] ;
665
665
attrValue [ attr . name ] = attr . value ;
666
666
}
667
- foreach ( attrValue , fn ) ;
667
+ foreachSorted ( attrValue , fn ) ;
668
668
}
669
669
670
670
function getter ( instance , path , unboundFn ) {
@@ -848,7 +848,10 @@ function createScope(parent, services, existing) {
848
848
}
849
849
850
850
foreach ( services , function ( _ , name ) {
851
- instance [ name ] = inject ( name ) ;
851
+ var service = inject ( name ) ;
852
+ if ( service ) {
853
+ instance [ name ] = service ;
854
+ }
852
855
} ) ;
853
856
854
857
return instance ;
@@ -2026,7 +2029,9 @@ var angularGlobal = {
2026
2029
var angularCollection = {
2027
2030
'size' : size
2028
2031
} ;
2029
- var angularObject = { } ;
2032
+ var angularObject = {
2033
+ 'extend' : extend
2034
+ } ;
2030
2035
var angularArray = {
2031
2036
'indexOf' : indexOf ,
2032
2037
'include' : includes ,
@@ -3135,9 +3140,11 @@ function valueAccessor(scope, element) {
3135
3140
required = required || required === '' ;
3136
3141
if ( ! validator ) throw "Validator named '" + validatorName + "' not found." ;
3137
3142
function validate ( value ) {
3138
- var error = required && ! trim ( value ) ?
3139
- "Required" :
3140
- validator ( { state :scope , scope :{ get :scope . $get , set :scope . $set } } , value ) ;
3143
+ var error ,
3144
+ validateScope = extend ( new ( extend ( function ( ) { } , { prototype :scope } ) ) ( ) , { $element :element } ) ;
3145
+ error = required && ! trim ( value ) ?
3146
+ "Required" :
3147
+ validator ( { state :validateScope , scope :{ get :validateScope . $get , set :validateScope . $set } } , value ) ;
3141
3148
if ( error !== lastError ) {
3142
3149
elementError ( element , NG_VALIDATION_ERROR , error ) ;
3143
3150
lastError = error ;
@@ -3298,7 +3305,8 @@ angularWidget('NG:INCLUDE', function(element){
3298
3305
angularWidget ( 'NG:SWITCH' , function ngSwitch ( element ) {
3299
3306
var compiler = this ,
3300
3307
watchExpr = element . attr ( "on" ) ,
3301
- whenFn = ngSwitch [ element . attr ( "using" ) || 'equals' ] ;
3308
+ whenExpr = ( element . attr ( "using" ) || 'equals' ) . split ( ":" ) ;
3309
+ whenFn = ngSwitch [ whenExpr . shift ( ) ] ;
3302
3310
changeExpr = element . attr ( 'change' ) || '' ,
3303
3311
cases = [ ] ;
3304
3312
if ( ! whenFn ) throw "Using expression '" + usingExpr + "' unknown." ;
@@ -3307,7 +3315,11 @@ angularWidget('NG:SWITCH', function ngSwitch(element){
3307
3315
if ( when ) {
3308
3316
cases . push ( {
3309
3317
when : function ( scope , value ) {
3310
- return whenFn . call ( scope , value , when ) ;
3318
+ var args = [ value , when ] ;
3319
+ foreach ( whenExpr , function ( arg ) {
3320
+ args . push ( arg ) ;
3321
+ } ) ;
3322
+ return whenFn . apply ( scope , args ) ;
3311
3323
} ,
3312
3324
change : changeExpr ,
3313
3325
element : caseElement ,
@@ -3320,13 +3332,10 @@ angularWidget('NG:SWITCH', function ngSwitch(element){
3320
3332
var scope = this , childScope ;
3321
3333
this . $watch ( watchExpr , function ( value ) {
3322
3334
element . html ( '' ) ;
3323
- childScope = null ;
3324
- var params = { } ;
3335
+ childScope = createScope ( scope ) ;
3325
3336
foreach ( cases , function ( switchCase ) {
3326
- if ( switchCase . when ( params , value ) ) {
3337
+ if ( switchCase . when ( childScope , value ) ) {
3327
3338
element . append ( switchCase . element ) ;
3328
- childScope = createScope ( scope ) ;
3329
- extend ( childScope , params ) ;
3330
3339
childScope . $tryEval ( switchCase . change , element ) ;
3331
3340
switchCase . template ( switchCase . element , childScope ) ;
3332
3341
childScope . $init ( ) ;
@@ -3341,22 +3350,25 @@ angularWidget('NG:SWITCH', function ngSwitch(element){
3341
3350
equals : function ( on , when ) {
3342
3351
return on == when ;
3343
3352
} ,
3344
- route : function ( on , when ) {
3345
- var regex = '^' + when . replace ( / [ \. \\ \( \) \^ \$ ] / g, "\$1" ) + '$' , params = [ ] , self = this ;
3353
+ route : function ( on , when , dstName ) {
3354
+ var regex = '^' + when . replace ( / [ \. \\ \( \) \^ \$ ] / g, "\$1" ) + '$' ,
3355
+ params = [ ] ,
3356
+ dst = { } ;
3346
3357
foreach ( when . split ( / \W / ) , function ( param ) {
3347
3358
if ( param ) {
3348
3359
var paramRegExp = new RegExp ( ":" + param + "([\\W])" ) ;
3349
3360
if ( regex . match ( paramRegExp ) ) {
3350
- regex = regex . replace ( paramRegExp , "(. *)$1" ) ;
3361
+ regex = regex . replace ( paramRegExp , "([^\/] *)$1" ) ;
3351
3362
params . push ( param ) ;
3352
3363
}
3353
3364
}
3354
3365
} ) ;
3355
3366
var match = on . match ( new RegExp ( regex ) ) ;
3356
3367
if ( match ) {
3357
3368
foreach ( params , function ( name , index ) {
3358
- self [ name ] = match [ index + 1 ] ;
3369
+ dst [ name ] = match [ index + 1 ] ;
3359
3370
} ) ;
3371
+ if ( dstName ) this . $set ( dstName , dst ) ;
3360
3372
}
3361
3373
return match ;
3362
3374
}
@@ -3370,6 +3382,7 @@ var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.]*)(:([0-9]+))
3370
3382
var DEFAULT_PORTS = { 'http' : 80 , 'https' : 443 , 'ftp' :21 } ;
3371
3383
angularService ( "$location" , function ( browser ) {
3372
3384
var scope = this , location = { parse :parse , toString :toString } ;
3385
+ var lastHash ;
3373
3386
function parse ( url ) {
3374
3387
if ( isDefined ( url ) ) {
3375
3388
var match = URL_MATCH . exec ( url ) ;
@@ -3381,28 +3394,33 @@ angularService("$location", function(browser){
3381
3394
location . path = match [ 6 ] ;
3382
3395
location . search = parseKeyValue ( match [ 8 ] ) ;
3383
3396
location . hash = match [ 9 ] ;
3384
- if ( location . hash ) location . hash = location . hash . substr ( 1 ) ;
3397
+ if ( location . hash )
3398
+ location . hash = location . hash . substr ( 1 ) ;
3399
+ lastHash = location . hash ;
3385
3400
location . hashPath = match [ 11 ] || '' ;
3386
3401
location . hashSearch = parseKeyValue ( match [ 13 ] ) ;
3387
3402
}
3388
3403
}
3389
3404
}
3390
3405
function toString ( ) {
3391
- var hashKeyValue = toKeyValue ( location . hashSearch ) ,
3392
- hash = ( location . hashPath ? location . hashPath : '' ) + ( hashKeyValue ? '?' + hashKeyValue : '' ) ;
3393
- return location . href . split ( '#' ) [ 0 ] + '#' + ( hash ? hash : '' ) ;
3406
+ if ( lastHash === location . hash ) {
3407
+ var hashKeyValue = toKeyValue ( location . hashSearch ) ,
3408
+ hash = ( location . hashPath ? location . hashPath : '' ) + ( hashKeyValue ? '?' + hashKeyValue : '' ) ,
3409
+ url = location . href . split ( '#' ) [ 0 ] + '#' + ( hash ? hash : '' ) ;
3410
+ if ( url !== location . href ) parse ( url ) ;
3411
+ return url ;
3412
+ } else {
3413
+ parse ( location . href . split ( '#' ) [ 0 ] + '#' + location . hash ) ;
3414
+ return toString ( ) ;
3415
+ }
3394
3416
}
3395
3417
browser . watchUrl ( function ( url ) {
3396
3418
parse ( url ) ;
3397
3419
scope . $root . $eval ( ) ;
3398
3420
} ) ;
3399
3421
parse ( browser . getUrl ( ) ) ;
3400
3422
this . $onEval ( PRIORITY_LAST , function ( ) {
3401
- var href = toString ( ) ;
3402
- if ( href != location . href ) {
3403
- browser . setUrl ( href ) ;
3404
- location . href = href ;
3405
- }
3423
+ browser . setUrl ( toString ( ) ) ;
3406
3424
} ) ;
3407
3425
return location ;
3408
3426
} , { inject : [ '$browser' ] } ) ;
@@ -3432,13 +3450,15 @@ angularService("$hover", function(browser) {
3432
3450
tooltip . arrow . addClass ( 'ng-arrow-right' ) ;
3433
3451
tooltip . arrow . css ( { left : ( width + 1 ) + 'px' } ) ;
3434
3452
tooltip . callout . css ( {
3453
+ position : 'fixed' ,
3435
3454
left : ( elementRect . left - arrowWidth - width - 4 ) + "px" ,
3436
3455
top : ( elementRect . top - 3 ) + "px" ,
3437
3456
width : width + "px"
3438
3457
} ) ;
3439
3458
} else {
3440
3459
tooltip . arrow . addClass ( 'ng-arrow-left' ) ;
3441
3460
tooltip . callout . css ( {
3461
+ position : 'fixed' ,
3442
3462
left : ( elementRect . right + arrowWidth ) + "px" ,
3443
3463
top : ( elementRect . top - 3 ) + "px" ,
3444
3464
width : width + "px"
0 commit comments