* Simplify css for click animation
* Refactor to transfer responsibility for casting multiple synchronous to index.ts from machine.ts (so they can be dealt with in bulk)
* During synchronous application of a batch of events, move the mouse to the last position so that it's in the correct place when the timer starts
- previous `needCastInSyncMode` added in 4bf533a675 meant that the isSync versions of MouseMove/TouchMove were being accidentally ignored
- each synchronous MouseMove would have resulted in a separate mouse position update
- the Click/TouchStart/TouchEnd events didn't have an async version
* The desktop pointer cursor is not representative of what is happening on a mobile device.
Instead, check a recording for any presence of a Touch event, and switch to a touch visualisation mode for the entire recording.
(for now, we use this mode even for mixed touch/mouse devices - this could be improved upon in future)
Show a round circle representing the users' finger which is visible only between TouchStart and TouchEnd events
Again this can be evolved upon, but this change should be a good start in the right direction.
* It's more correct to not have a transition for repositioning of touch as user can lift finger off screen and place elsewhere; however we can now have much smoother touch movement during the .touch-active phase as we know the finger is on the screen. This has a .25s delaying effect on the touch position which IMO is acceptable; e.g. scroll position can lag behind a touch movement and this seems to bring them more in sync
* Ensure we end up with the correct touch-active state after a series of synchronous events
* Important to discontinue tail animations and position transitions when user has lifted their finger and placed it into a new position. This is apparent in a replay session where the user is scrolling the page using repeated TouchMove bottom-to-top movements
* Simplify by unwrapping `mouseState.touchActive` and `mouseState.pos` into their own global vars
- encountered inconsistent html with multiple <option> elements with the same value attribute
- due to check `attributes.selected = (n as HTMLOptionElement).selected;` the extra ones were being stored as `selected: false`; furthermore, the `false` value was being ignored upon replay, and so the last of the extra ones was being chosen as the 'selected' option
* Add test for event ordering utilizing final html testing method added by Justin (with thanks)
* Found an error where two mutation events had the same timestamp, but one removed a node added in the other. The `actions.splice` method was reversing their order and triggering a 'Node with id [...] not found' error
* Show whether a node was not found because it was never there, or because some other mutation already removed it
* Be more careful applying mutations as replay-stopping things can go wrong, e.g. node removal parent belongs to a different FullSnapshot and has e.g. a text nodeType
* Don't warn when a modified node has been removed in the same mutation - or the parent node for a removed node has been already removed
* My best interpretation of what the typings should look like after merge of #464
* Apply variable name changes as per Juice10 review
Co-authored-by: Justin Halsall <Juice10@users.noreply.github.com>
* fix types
Co-authored-by: Eoghan Murray <eoghan@getthere.ie>
* Don't store the full style attribute change, as small mutations to single style properties result in storage of a rewrite for the full style attribute, which may be very large.
Had an example of a website using http://schillmania.com/projects/snowstorm/ where many direct style changes were happening every second across many 'snowflake' elements, with each attribute change looking like:
"style":"color: rgb(255, 255, 255); position: absolute; width: 8px; height: 8px; font-family: arial, verdana; overflow: hidden; font-weight: normal; z-index: 0; display: block; bottom: auto; opacity: 1; padding: 0px; margin: 0px; font-size: 10px; line-height: 10px; text-align: center; vertical-align: baseline; left: 242.807px; top: 85.7332px;"
even though maybe just the left/top position had been changed
* More compact storage for the much more common attribute value without an `!important` flag - saves 6 chars per style attr in the json :)
* Fix bug: attributes weren't getting removed after changes to treatment of 'style' attributes
* Fix sheet insertion
Restore skip duration
Use virtualStyleRulesMap to re-populate stylesheet on Flush event
Clear virtualStyleRulesMap after flush applied
* Support rule deletion in virtual processing
* Simply restoreNodeSheet with early aborts
* Encountered a bug where firstFullSnapshot was played twice because timer was immediately started and reached the snapshot before the setTimeout returned
* Ignoring a FullSnapshot needs to be a one-time only thing, as otherwise we'll ignore it after scrubbing (restarting play head at a particular time). This is a problem if mutations have altered the player state, and we try to replay those mutations, so we e.g. try to remove an element that has already been removed because we haven't reset the FullSnapshot state
* Some `npm run typings` related fixups
* add basic html snapshot functionality
* move restoreNodeSheet to it's own module
* Refactor virtual style rules to buffer changes.
Only applies changes on flush.
`virtualStyleRulesMap` now works with strings instead of CSSRules.
CSSRules can only be via made `.insertRule` on CSSStyleSheet in most browsers.
And `new CSSStyleSheet()` only works in Chrome currently.
* remove unused code
* move VirtualStyleRules from CSSRule to string in tests
* correct paths for tests
* naming
* create and restore style snapshots for virtual nodes
* update replayer snapshot
* move storeCSSRules to virtual-styles.ts
* try/catch access to .sheet in case of access errors
* clean up tests
Co-authored-by: Vladimir Milenko <vladimir.milenko@uber.com>
Co-authored-by: Eoghan Murray <eoghan@getthere.ie>
* add `userTriggered`
* update snapshots to add userTriggered
* add `userTriggered`
* update snapshots to add userTriggered
* update snapshot to include userTrigger
* only set userTriggered on `userTriggeredOnInput: true`
* What is user triggered?
* correct snapshot
* add second radio to demonstrate userTriggered