Skip to content

Commit e553d4a

Browse files
committed
implemented callback feature
1 parent 44b4459 commit e553d4a

File tree

11 files changed

+375
-147
lines changed

11 files changed

+375
-147
lines changed

lazy-transition.d.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export declare class ObserverService {
2929

3030
get observer (): IntersectionObserver
3131

32-
startObserving (el: Element): void
32+
startObserving (el: FunctionalVueElement, callback?: Function, addEvents?: boolean, transitionName?: string): void
3333
stopObserving (el: Element): void
3434
disposeObserver (): void
3535
}
@@ -45,3 +45,13 @@ export interface VueElement extends HTMLElement {
4545
isFromDirective: boolean
4646
binding: DirectiveBinding
4747
}
48+
49+
export interface FunctionalVueElement extends VueElement {
50+
callback?: Function
51+
transition?: string
52+
}
53+
54+
export type FunctionalElementBinding = {
55+
transition?: string
56+
onView: Function
57+
}

notes

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-- TODO(FEATURES)
2+
- Implement feature to play reverse transition when element goes out of viewport.
3+
- Try to implement lazy loading
4+
5+
-- TODO(IDEAS)
6+
- maybe add functionality to provide custom observer
7+
- maybe add functionality to have more than one observer and a way to reference them like an observer factory
8+
[the observer factory will not be seen by the plugin user. to them it will just be add/remove observer]
9+
- maybe change directive syntax to v-lazy then parameters will decide functionality
10+
example <div v-lazy.load> </div> will be for lazy loading on view
11+
example <div v-lazy.transition> </div> will be for lazy transitions [normal behavior]
12+
example <div v-lazy.animate> </div> will be for lazy animations
13+
- maybe add functionality to supply callback to be executed when element is in view
14+
instead of only transitions and animations
15+
- maybe restructure the directive values supplied to allow for more custom transitions and other css changes
16+
example <div v-lazy.transition="{from: '', to: ''}"> </div>
17+
example <div v-lazy.transition.cssClass="'css-class-name'"> </div>
18+
example <div v-lazy.transition.style="'element-style'"> </div>

src/FunctionComponent.vue

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<template>
2+
<section class="animated bg-darkslategray" ref="pageEnd">
3+
This element does not use the v-lazytransition binding or lazy-transition component.
4+
<p> {{ text }} </p>
5+
</section>
6+
</template>
7+
8+
<script lang="ts">
9+
import Vue from 'vue'
10+
import { FunctionalVueElement, VueElement } from '../lazy-transition';
11+
12+
export default Vue.extend({
13+
name: 'function-component',
14+
data () {
15+
return {
16+
text: ''
17+
}
18+
},
19+
methods: {
20+
showThings () {
21+
setTimeout(() => {
22+
this.text = 'But it\'s special'
23+
setTimeout(() => {
24+
this.text = 'It executes a callback using the global variables.'
25+
setTimeout(() => {
26+
this.text = 'This callback keeps cloning nodes as you scroll. ' +
27+
'but there will never be more than 12 nodes at a time' +
28+
'no matter how much you scroll'
29+
this.duplicateAndClone()
30+
}, 1000)
31+
}, 1000)
32+
}, 1000)
33+
},
34+
duplicateAndClone () {
35+
const el = this.$refs.pageEnd as FunctionalVueElement
36+
const newNode = el.cloneNode() as FunctionalVueElement;
37+
const secondNode = el.cloneNode() as FunctionalVueElement; // node to be cloned
38+
secondNode.innerText = 'This is the initial cloned node';
39+
newNode.classList.remove('animated', 'bg-darkslategray');
40+
41+
el.parentElement!.appendChild(newNode)
42+
newNode.appendChild(secondNode)
43+
44+
this.$lazyObserver.startObserving(secondNode, () => {
45+
this.cloneChildNode(secondNode, newNode)
46+
}, true, 'side-fade-right')
47+
},
48+
cloneChildNode (childNode: FunctionalVueElement, parentNode: FunctionalVueElement) {
49+
if (parentNode.children.length > 20) parentNode.firstChild!.remove();
50+
const node = childNode.cloneNode() as VueElement;
51+
node.textContent = 'CLONED NODE'
52+
parentNode.append(node)
53+
this.$lazyObserver.startObserving(node, () => {
54+
this.cloneChildNode(node, parentNode)
55+
}, true, 'side-fade-right')
56+
}
57+
},
58+
mounted (): void {
59+
const el = this.$refs.pageEnd as VueElement
60+
61+
this.$lazyObserver.startObserving(el, this.showThings)
62+
},
63+
beforeDestroy (): void {
64+
const el = this.$refs.pageEnd as VueElement
65+
this.$lazyObserver.stopObserving(el)
66+
}
67+
})
68+
</script>
69+
70+
<style scoped>
71+
72+
</style>

src/component/LazyTransition.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script lang="ts">
22
import Vue from 'vue'
3+
import { VueElement } from '../../lazy-transition';
34
45
interface AnimatedItem {
56
show: boolean;
@@ -23,13 +24,13 @@ export default Vue.extend({
2324
};
2425
},
2526
mounted(): void {
26-
const el = this.$refs.animateditem as Element;
27+
const el = this.$refs.animateditem as VueElement;
2728
this.$lazyObserver.startObserving(el);
2829
},
2930
beforeDestroy(): void {
30-
const el = this.$refs.animateditem as Element;
31+
const el = this.$refs.animateditem as VueElement;
3132
this.$lazyObserver.stopObserving(el);
32-
},
33+
}
3334
});
3435
</script>
3536

src/directive/index.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
1-
import { VueElement } from '../../lazy-transition'
1+
import { VueElement } from '@/../lazy-transition'
22
import _Vue, { VNode } from 'vue'
3-
import { isHtmlElement, isVueComponent } from '@/service/Helpers'
3+
import { getVueInstance, isHtmlElement, isVueComponent } from '@/service/Helpers'
44
import { DirectiveBinding } from 'vue/types/options'
55

66
function prepareAndWatch (el: Element, binding: DirectiveBinding, node: VNode) {
77
const element = el as VueElement
88
element.isFromDirective = true
99
element.binding = binding
1010

11-
if (isHtmlElement(el)) {
12-
node.context!.$lazyObserver.startObserving(element)
11+
if (isHtmlElement(el) && !isVueComponent(el)) {
12+
node.context!.$lazyObserver.startObserving(element, binding.value.onView)
1313
} else if (isVueComponent(el)) {
14-
element.__vue__.$lazyObserver.startObserving(element)
14+
getVueInstance(el).$lazyObserver.startObserving(element, binding.value.onView)
1515
}
1616
}
1717

1818
export const lazyAnimateDirective = (app: typeof _Vue) => app.directive('lazytransition', {
1919
bind: (el, binding, vnode) => {
20-
prepareAndWatch(el, binding, vnode)
20+
if (el.getAttribute('lazy-observing') !== 'true') {
21+
prepareAndWatch(el, binding, vnode)
22+
}
2123
}
2224
})
2325

@@ -27,7 +29,9 @@ export const lazyAnimateGroup = (app: typeof _Vue) => app.directive('lazytransit
2729
const numberOfChildren = el.children.length
2830
for (let i = 0; i < numberOfChildren; i++) {
2931
const elm = el.children.item(i)!;
30-
prepareAndWatch(elm, binding, vnode)
32+
if (elm.getAttribute('lazy-observing') !== 'true') {
33+
prepareAndWatch(elm, binding, vnode)
34+
}
3135
}
3236
}
3337
}

src/dummy-component.vue

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
<template>
2-
<section class="animated mb-5"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur exercitationem
3-
inventore iure, molestias nisi odit praesentium quam, recusandae similique sunt veritatis, voluptas. Asperiores
4-
dolores maxime minima recusandae reprehenderit sed ullam!
2+
<section class="animated mb-5" id="inner"
3+
v-lazytransition.function="{transition: this.transition, onView: this.changeText}">
4+
Dummy component: <slot/>
5+
<p> {{ this.text }} </p>
56
</section>
67
</template>
8+
<script lang="ts">
9+
import Vue from 'vue'
10+
11+
export default Vue.extend({
12+
name: 'dummy-component',
13+
props: {
14+
transition: {
15+
type: String,
16+
required: false
17+
}
18+
},
19+
data () {
20+
return {
21+
text: 'Data property in dummy component'
22+
}
23+
},
24+
methods: {
25+
changeText () {
26+
setTimeout(() => {
27+
this.text = this.text + ' that changed 2 seconds after it got here'
28+
}, 2000)
29+
}
30+
}
31+
})
32+
</script>

src/serve-dev.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ Vue.use(LazyTransition, {
1111
},
1212
intersectionRatio: 0.5
1313
})
14-
1514
new Vue({
1615
render: (h): VNode => h(Dev),
1716
}).$mount('#app');

0 commit comments

Comments
 (0)