Skip to content

Instantly share code, notes, and snippets.

@MartinMuzatko
Last active July 10, 2016 20:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MartinMuzatko/4bfc559a0158c4652c2c to your computer and use it in GitHub Desktop.
Save MartinMuzatko/4bfc559a0158c4652c2c to your computer and use it in GitHub Desktop.
Riot Mixin - Smooth exit animation for your data - interact.js

Junp to the file: https://gist.github.com/MartinMuzatko/4bfc559a0158c4652c2c#file-interact-js

How to set it up:

In your tag:

<my-tag>
	<div name="items" each={set in data}>{set}</div>
	<script>
		this.mixin(interact)
		
		this.data = {your:'data', is:'an', object : ['or', 'an', 'array']}
		
		this.on(
			'mount',
			function()
			{
				// Important! You don't insert the data in the function, 
				// but the element/DOM node it affects (hence name="items" and this.items)
				this.dataFade = new this.interaction(this.items)
			}
		)
	</script>
</my-tag>

Arguments for new this.interaction:

Element

The DOM node you define with name="example" or id="example" - this.example

Classes

The animation classes, this example works with animate.css - but you can add your own animations if you want to. Just add the classes as array

Default: ['animated', 'fadeOut']

Interaction Class Methods

When creating the Interaction Object, you'll retrieve an Object with these methods

setup()

Gets called when setting up the interaction. Creates the MutationObserver and the underlying logic

observe()

Gets called after successful Setup, you need this if you want to reconnect to the observer

disconnect()

Disconnecting the observer - no more mutations get observed and reacted upon.

_doAnimate()

The method that is called whenever a mutation is made (no matter if element added or removed or changed) You can overwrite this if you want to. The first argument are the mutations, retrieved by the MutationObserver the second argument is the observer (so you can disconnect and reconnect if you want to avoid having the listener to listen to your own changes

e.g.:

	observer.disconnect()
	node.remove()
	observer.observe()

Thats it! Have fun with it.

License: MIT

var interact = {
interaction : function(element, classes)
{
classes = classes || ['animated','fadeOut']
this.element = element
this.classes = ' ' + classes.join(' ')
this.observer = {}
this.setup = function()
{
if (JSON.stringify(this.observer) != '{}')
{
this.observe()
return this
}
this.observer = new MutationObserver(
function (mutations)
{
this._doAnimate(mutations, this)
}.bind(this)
)
this.observe()
return this.observer
}
this.observe = function()
{
this.observer.observe(
this.element,
{
childList: true,
attributes: false,
characterData: false,
}
)
}
this.disconnect = function()
{
this.observer.disconnect()
}
this._doAnimate = function(mutations, observer)
{
for (var mutation in mutations)
{
mutation = mutations[mutation]
if (mutation.removedNodes.length)
{
var nodes = Array.prototype.slice.call(mutation.removedNodes)
for (var node in nodes)
{
node = nodes[node]
node.className += observer.classes
if (node.className.length > 120)
{
window.document.body.innerHTML = 'STOP!!'
// This is just added for security, in case the observer
// does not fire the disconnect and is trapped in the loop
}
var next = mutation.nextSibling
var prev = mutation.previousSibling
if (!next)
{
mutation.target.appendChild(node)
}
else if (next)
{
mutation.target.insertBefore(node, mutation.nextSibling)
}
node.addEventListener(
"animationend",
function(e)
{
observer.disconnect()
e.target.remove()
observer.observe()
}.bind(this)
)
//node.target.appendChild()
}
}
}
}
this.setup()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment