1
- export default function Adapter ( $parse , $attr , viewport , buffer , adjustBuffer ) {
2
- const viewportScope = viewport . scope ( ) || $rootScope ;
3
- const setTopVisible = $attr . topVisible ? $parse ( $attr . topVisible ) . assign : angular . noop ;
4
- const setTopVisibleElement = $attr . topVisibleElement ? $parse ( $attr . topVisibleElement ) . assign : angular . noop ;
5
- const setTopVisibleScope = $attr . topVisibleScope ? $parse ( $attr . topVisibleScope ) . assign : angular . noop ;
6
- const setIsLoading = $attr . isLoading ? $parse ( $attr . isLoading ) . assign : angular . noop ;
7
-
8
- this . isLoading = false ;
9
-
10
- function applyUpdate ( wrapper , newItems ) {
11
- if ( ! angular . isArray ( newItems ) ) {
12
- return ;
13
- }
14
-
15
- let keepIt ;
16
- let pos = ( buffer . indexOf ( wrapper ) ) + 1 ;
17
-
18
- newItems . reverse ( ) . forEach ( ( newItem ) => {
19
- if ( newItem === wrapper . item ) {
20
- keepIt = true ;
21
- pos -- ;
22
- } else {
23
- buffer . insert ( pos , newItem ) ;
24
- }
25
- } ) ;
26
-
27
- if ( ! keepIt ) {
28
- wrapper . op = 'remove' ;
29
- }
30
- }
31
-
32
- this . applyUpdates = ( arg1 , arg2 ) => {
33
- if ( angular . isFunction ( arg1 ) ) {
34
- // arg1 is the updater function, arg2 is ignored
35
- buffer . slice ( 0 ) . forEach ( ( wrapper ) => {
36
- // we need to do it on the buffer clone, because buffer content
37
- // may change as we iterate through
38
- applyUpdate ( wrapper , arg1 ( wrapper . item , wrapper . scope , wrapper . element ) ) ;
39
- } ) ;
40
- } else {
41
- // arg1 is item index, arg2 is the newItems array
42
- if ( arg1 % 1 !== 0 ) { // checking if it is an integer
43
- throw new Error ( 'applyUpdates - ' + arg1 + ' is not a valid index' ) ;
44
- }
45
-
46
- const index = arg1 - buffer . first ;
47
- if ( ( index >= 0 && index < buffer . length ) ) {
48
- applyUpdate ( buffer [ index ] , arg2 ) ;
49
- }
50
- }
51
-
52
- adjustBuffer ( ) ;
53
- } ;
54
-
55
- this . append = ( newItems ) => {
56
- buffer . append ( newItems ) ;
57
- adjustBuffer ( ) ;
58
- } ;
59
-
60
- this . prepend = ( newItems ) => {
61
- buffer . prepend ( newItems ) ;
62
- adjustBuffer ( ) ;
63
- } ;
64
-
65
- this . loading = function ( value ) {
66
- this . isLoading = value ;
67
- setIsLoading ( viewportScope , value ) ;
68
- } ;
69
-
70
- this . calculateProperties = function ( ) {
71
- let i , item , itemHeight , itemTop , isNewRow , rowTop ;
72
- let topHeight = 0 ;
73
- for ( i = 0 ; i < buffer . length ; i ++ ) {
74
- item = buffer [ i ] ;
75
- itemTop = item . element . offset ( ) . top ;
76
- isNewRow = rowTop !== itemTop ;
77
- rowTop = itemTop ;
78
- if ( isNewRow ) {
79
- itemHeight = item . element . outerHeight ( true ) ;
80
- }
81
- if ( isNewRow && ( viewport . topDataPos ( ) + topHeight + itemHeight <= viewport . topVisiblePos ( ) ) ) {
82
- topHeight += itemHeight ;
83
- } else {
84
- if ( isNewRow ) {
85
- this . topVisible = item . item ;
86
- this . topVisibleElement = item . element ;
87
- this . topVisibleScope = item . scope ;
88
- setTopVisible ( viewportScope , item . item ) ;
89
- setTopVisibleElement ( viewportScope , item . element ) ;
90
- setTopVisibleScope ( viewportScope , item . scope ) ;
91
- }
92
- break ;
93
-
94
- }
95
- }
96
- } ;
1
+ export default function Adapter ( $rootScope , $parse , $attr , viewport , buffer , adjustBuffer , element ) {
2
+ const viewportScope = viewport . scope ( ) || $rootScope ;
3
+ let disabled = false ;
4
+ let self = this ;
5
+
6
+ createValueInjector ( 'adapter' ) ( self ) ;
7
+ let topVisibleInjector = createValueInjector ( 'topVisible' ) ;
8
+ let topVisibleElementInjector = createValueInjector ( 'topVisibleElement' ) ;
9
+ let topVisibleScopeInjector = createValueInjector ( 'topVisibleScope' ) ;
10
+ let isLoadingInjector = createValueInjector ( 'isLoading' ) ;
11
+
12
+ // Adapter API definition
13
+
14
+ Object . defineProperty ( this , 'disabled' , {
15
+ get : ( ) => disabled ,
16
+ set : ( value ) => ( ! ( disabled = value ) ) ? adjustBuffer ( ) : null
17
+ } ) ;
18
+
19
+ this . isLoading = false ;
20
+ this . isBOF = ( ) => buffer . bof ;
21
+ this . isEOF = ( ) => buffer . eof ;
22
+
23
+ this . applyUpdates = ( arg1 , arg2 ) => {
24
+ if ( angular . isFunction ( arg1 ) ) {
25
+ // arg1 is the updater function, arg2 is ignored
26
+ buffer . slice ( 0 ) . forEach ( ( wrapper ) => {
27
+ // we need to do it on the buffer clone, because buffer content
28
+ // may change as we iterate through
29
+ applyUpdate ( wrapper , arg1 ( wrapper . item , wrapper . scope , wrapper . element ) ) ;
30
+ } ) ;
31
+ } else {
32
+ // arg1 is item index, arg2 is the newItems array
33
+ if ( arg1 % 1 !== 0 ) { // checking if it is an integer
34
+ throw new Error ( 'applyUpdates - ' + arg1 + ' is not a valid index' ) ;
35
+ }
36
+
37
+ const index = arg1 - buffer . first ;
38
+ if ( ( index >= 0 && index < buffer . length ) ) {
39
+ applyUpdate ( buffer [ index ] , arg2 ) ;
40
+ }
41
+ }
42
+
43
+ adjustBuffer ( ) ;
44
+ } ;
45
+
46
+ this . append = ( newItems ) => {
47
+ buffer . append ( newItems ) ;
48
+ adjustBuffer ( ) ;
49
+ } ;
50
+
51
+ this . prepend = ( newItems ) => {
52
+ buffer . prepend ( newItems ) ;
53
+ adjustBuffer ( ) ;
54
+ } ;
55
+
56
+ this . loading = ( value ) => {
57
+ isLoadingInjector ( value ) ;
58
+ } ;
59
+
60
+ this . calculateProperties = ( ) => {
61
+ let item , itemHeight , itemTop , isNewRow , rowTop = null ;
62
+ let topHeight = 0 ;
63
+ for ( let i = 0 ; i < buffer . length ; i ++ ) {
64
+ item = buffer [ i ] ;
65
+ itemTop = item . element . offset ( ) . top ;
66
+ isNewRow = rowTop !== itemTop ;
67
+ rowTop = itemTop ;
68
+ if ( isNewRow ) {
69
+ itemHeight = item . element . outerHeight ( true ) ;
70
+ }
71
+ if ( isNewRow && ( viewport . topDataPos ( ) + topHeight + itemHeight <= viewport . topVisiblePos ( ) ) ) {
72
+ topHeight += itemHeight ;
73
+ } else {
74
+ if ( isNewRow ) {
75
+ topVisibleInjector ( item . item ) ;
76
+ topVisibleElementInjector ( item . element ) ;
77
+ topVisibleScopeInjector ( item . scope ) ;
78
+ }
79
+ break ;
80
+ }
81
+ }
82
+ } ;
83
+
84
+ // private function definitions
85
+
86
+ function createValueInjector ( attribute ) {
87
+ let expression = $attr [ attribute ] ;
88
+ let scope = viewportScope ;
89
+ let assign ;
90
+ if ( expression ) {
91
+ // it is ok to have relaxed validation for the first part of the 'on' expression.
92
+ // additional validation will be done by the $parse service below
93
+ let match = expression . match ( / ^ ( \S + ) (?: \s + o n \s + ( \w (?: \w | \d ) * ) ) ? / ) ;
94
+ if ( ! match )
95
+ throw new Error ( 'Expected injection expression in form of \'target\' or \'target on controller\' but got \'' + expression + '\'' ) ;
96
+ let target = match [ 1 ] ;
97
+ let onControllerName = match [ 2 ] ;
98
+
99
+ let parseController = ( controllerName , on ) => {
100
+ let candidate = element ;
101
+ while ( candidate . length ) {
102
+ let candidateScope = candidate . scope ( ) ;
103
+ // ng-controller's "Controller As" parsing
104
+ let candidateName = ( candidate . attr ( 'ng-controller' ) || '' ) . match ( / ( \w (?: \w | \d ) * ) (?: \s + a s \s + ( \w (?: \w | \d ) * ) ) ? / ) ;
105
+ if ( candidateName && candidateName [ on ? 1 : 2 ] === controllerName ) {
106
+ scope = candidateScope ;
107
+ return true ;
108
+ }
109
+ // directive's/component's "Controller As" parsing
110
+ if ( ! on && candidateScope && candidateScope . hasOwnProperty ( controllerName ) && Object . getPrototypeOf ( candidateScope [ controllerName ] ) . constructor . hasOwnProperty ( '$inject' ) ) {
111
+ scope = candidateScope ;
112
+ return true ;
113
+ }
114
+ candidate = candidate . parent ( ) ;
115
+ }
116
+ } ;
117
+
118
+ if ( onControllerName ) { // 'on' syntax DOM parsing (adapter="adapter on ctrl")
119
+ scope = null ;
120
+ parseController ( onControllerName , true ) ;
121
+ if ( ! scope ) {
122
+ throw new Error ( 'Failed to locate target controller \'' + onControllerName + '\' to inject \'' + target + '\'' ) ;
123
+ }
124
+ }
125
+ else { // try to parse DOM with 'Controller As' syntax (adapter="ctrl.adapter")
126
+ let controllerAsName ;
127
+ let dotIndex = target . indexOf ( '.' ) ;
128
+ if ( dotIndex > 0 ) {
129
+ controllerAsName = target . substr ( 0 , dotIndex ) ;
130
+ parseController ( controllerAsName , false ) ;
131
+ }
132
+ }
133
+
134
+ assign = $parse ( target ) . assign ;
135
+ }
136
+ return ( value ) => {
137
+ if ( self !== value ) // just to avoid injecting adapter reference in the adapter itself. Kludgy, I know.
138
+ self [ attribute ] = value ;
139
+ if ( assign )
140
+ assign ( scope , value ) ;
141
+ } ;
142
+ }
143
+
144
+ function applyUpdate ( wrapper , newItems ) {
145
+ if ( ! angular . isArray ( newItems ) ) {
146
+ return ;
147
+ }
148
+
149
+ let keepIt ;
150
+ let pos = ( buffer . indexOf ( wrapper ) ) + 1 ;
151
+
152
+ newItems . reverse ( ) . forEach ( ( newItem ) => {
153
+ if ( newItem === wrapper . item ) {
154
+ keepIt = true ;
155
+ pos -- ;
156
+ } else {
157
+ buffer . insert ( pos , newItem ) ;
158
+ }
159
+ } ) ;
160
+
161
+ if ( ! keepIt ) {
162
+ wrapper . op = 'remove' ;
163
+ }
164
+ }
165
+
97
166
}
0 commit comments