@@ -14,7 +14,9 @@ import {
1414 SchedulerInterface ,
1515 ElementSchedulerInterface ,
1616 FrameInterface ,
17- QueueInterface
17+ QueueInterface ,
18+ MetaInterface ,
19+ SpanielClientRectInterface
1820} from './interfaces' ;
1921import W from './window-proxy' ;
2022
@@ -29,45 +31,88 @@ const TOKEN_SEED = 'xxxx'.replace(/[xy]/g, function(c) {
2931} ) ;
3032let tokenCounter = 0 ;
3133
32- function generateRandomToken ( ) {
33- return Math . floor ( Math . random ( ) * ( 9999999 - 0o0 ) ) . toString ( 16 ) ;
34- }
35-
3634export class Frame implements FrameInterface {
3735 constructor (
3836 public timestamp : number ,
3937 public scrollTop : number ,
4038 public scrollLeft : number ,
4139 public width : number ,
42- public height : number
40+ public height : number ,
41+ public x : number ,
42+ public y : number ,
43+ public top : number ,
44+ public left : number
4345 ) { }
44- static generate ( ) : Frame {
46+ static generate ( root : Element | Window = window ) : Frame {
47+ const rootMeta = this . revalidateRootMeta ( root ) ;
4548 return new Frame (
4649 Date . now ( ) ,
47- W . meta . scrollTop ,
48- W . meta . scrollLeft ,
49- W . meta . width ,
50- W . meta . height
50+ rootMeta . scrollTop ,
51+ rootMeta . scrollLeft ,
52+ rootMeta . width ,
53+ rootMeta . height ,
54+ rootMeta . x ,
55+ rootMeta . y ,
56+ rootMeta . top ,
57+ rootMeta . left
5158 ) ;
5259 }
60+ static revalidateRootMeta ( root : any = window ) : MetaInterface {
61+ let _rootMeta : MetaInterface = {
62+ width : 0 ,
63+ height : 0 ,
64+ scrollTop : 0 ,
65+ scrollLeft : 0 ,
66+ x : 0 ,
67+ y : 0 ,
68+ top : 0 ,
69+ left : 0
70+ } ;
71+
72+ // if root is dirty update the cached values
73+ if ( W . isDirty ) { W . updateMeta ( ) ; }
74+
75+ if ( root === window ) {
76+ _rootMeta . height = W . meta . height ;
77+ _rootMeta . width = W . meta . width ;
78+ _rootMeta . scrollLeft = W . meta . scrollLeft ;
79+ _rootMeta . scrollTop = W . meta . scrollTop ;
80+ } else if ( root ) {
81+ let _clientRect = getBoundingClientRect ( root ) ;
82+ _rootMeta . scrollTop = root . scrollTop ;
83+ _rootMeta . scrollLeft = root . scrollLeft ;
84+ _rootMeta . width = _clientRect . width ;
85+ _rootMeta . height = _clientRect . height ;
86+ _rootMeta . x = _clientRect . x ;
87+ _rootMeta . y = _clientRect . y ;
88+ _rootMeta . top = _clientRect . top ;
89+ _rootMeta . left = _clientRect . left ;
90+ }
91+
92+ return _rootMeta ;
93+ }
5394}
5495
5596export function generateToken ( ) {
5697 return tokenCounter ++ + TOKEN_SEED ;
5798}
5899
59100export abstract class BaseScheduler {
101+ protected root : Element | Window ;
60102 protected engine : EngineInterface ;
61103 protected queue : QueueInterface ;
62104 protected isTicking : Boolean = false ;
63105 protected toRemove : Array < string | Element | Function > = [ ] ;
106+ protected id ?: string ;
64107
65- constructor ( customEngine ?: EngineInterface ) {
108+ constructor ( customEngine ?: EngineInterface , root : Element | Window = window ) {
66109 if ( customEngine ) {
67110 this . engine = customEngine ;
68111 } else {
69112 this . engine = getGlobalEngine ( ) ;
70113 }
114+
115+ this . root = root ;
71116 }
72117 protected abstract applyQueue ( frame : Frame ) : void ;
73118
@@ -81,8 +126,7 @@ export abstract class BaseScheduler {
81126 }
82127 this . toRemove = [ ] ;
83128 }
84-
85- this . applyQueue ( Frame . generate ( ) ) ;
129+ this . applyQueue ( Frame . generate ( this . root ) ) ;
86130 this . engine . scheduleRead ( this . tick . bind ( this ) ) ;
87131 }
88132 }
@@ -97,7 +141,7 @@ export abstract class BaseScheduler {
97141 let frame : Frame = null ;
98142 this . engine . scheduleRead ( ( ) => {
99143 clientRect = getBoundingClientRect ( el ) ;
100- frame = Frame . generate ( ) ;
144+ frame = Frame . generate ( this . root ) ;
101145 } ) ;
102146 this . engine . scheduleWork ( ( ) => {
103147 callback ( clientRect , frame ) ;
@@ -108,14 +152,16 @@ export abstract class BaseScheduler {
108152 }
109153 unwatchAll ( ) {
110154 this . queue . clear ( ) ;
111- W . __destroy__ ( ) ;
112155 }
113156 startTicking ( ) {
114157 if ( ! this . isTicking ) {
115158 this . isTicking = true ;
116159 this . engine . scheduleRead ( this . tick . bind ( this ) ) ;
117160 }
118161 }
162+ validateState ( ) {
163+ ++ W . version ;
164+ }
119165}
120166
121167export class Scheduler extends BaseScheduler implements SchedulerInterface {
@@ -140,7 +186,7 @@ export class Scheduler extends BaseScheduler implements SchedulerInterface {
140186export class PredicatedScheduler extends Scheduler implements SchedulerInterface {
141187 predicate : ( frame : Frame ) => Boolean ;
142188 constructor ( predicate : ( frame : Frame ) => Boolean ) {
143- super ( null ) ;
189+ super ( null , window ) ;
144190 this . predicate = predicate ;
145191 }
146192 applyQueue ( frame : Frame ) {
@@ -152,13 +198,15 @@ export class PredicatedScheduler extends Scheduler implements SchedulerInterface
152198
153199export class ElementScheduler extends BaseScheduler implements ElementSchedulerInterface {
154200 protected queue : DOMQueue ;
155- protected isDirty : boolean = false ;
156- protected id : string = '' ;
201+ protected lastVersion : number = W . version ;
157202
158- constructor ( customEngine ?: EngineInterface ) {
159- super ( customEngine ) ;
203+ constructor ( customEngine ?: EngineInterface , root ?: Element | Window ) {
204+ super ( customEngine , root ) ;
160205 this . queue = new DOMQueue ( ) ;
161- this . id = generateRandomToken ( ) ;
206+ }
207+
208+ get isDirty ( ) : boolean {
209+ return W . version !== this . lastVersion ;
162210 }
163211
164212 applyQueue ( frame : Frame ) {
@@ -172,11 +220,10 @@ export class ElementScheduler extends BaseScheduler implements ElementSchedulerI
172220 callback ( frame , id , clientRect ) ;
173221 }
174222
175- this . isDirty = false ;
223+ this . lastVersion = W . version ;
176224 }
177225
178226 watch ( el : Element , callback : ( frame : FrameInterface , id : string , clientRect ?: ClientRect | null ) => void , id ?: string ) : string {
179- this . initWindowIsDirtyListeners ( ) ;
180227 this . startTicking ( ) ;
181228 id = id || generateToken ( ) ;
182229 let clientRect = null ;
@@ -189,14 +236,6 @@ export class ElementScheduler extends BaseScheduler implements ElementSchedulerI
189236 } ) ;
190237 return id ;
191238 }
192-
193- initWindowIsDirtyListeners ( ) {
194- W . onWindowIsDirtyListeners . push ( { fn : this . windowIsDirtyHandler , scope : this , id : this . id } ) ;
195- }
196-
197- windowIsDirtyHandler ( ) {
198- this . isDirty = true ;
199- }
200239}
201240
202241let globalScheduler : Scheduler = null ;
0 commit comments