From 1e1f3fbb27976a34f53a4e8d250da34dad4e6c20 Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Sat, 4 Jul 2020 23:18:51 +0300
Subject: feat: experimental videos in grid

---
 src/site/components/grid/waterfall/Waterfall.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/site/components/grid/waterfall/Waterfall.vue')

diff --git a/src/site/components/grid/waterfall/Waterfall.vue b/src/site/components/grid/waterfall/Waterfall.vue
index 8631ea5..af1bd72 100644
--- a/src/site/components/grid/waterfall/Waterfall.vue
+++ b/src/site/components/grid/waterfall/Waterfall.vue
@@ -170,7 +170,7 @@ export default {
 					return;
 				}
 				child.el.style.top = `${offsetArr[position]}px`;
-				offsetArr[position] += (child.height + this.gutterHeight);
+				offsetArr[position] += child.height + this.gutterHeight;
 				this.$el.style.height = `${Math.max.apply(Math, offsetArr)}px`;
 			});
 			this.$emit('rendered', this);
-- 
cgit v1.2.3


From 766e74cc51138b32482f65f0f2647eb9d943103e Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Sun, 5 Jul 2020 04:18:08 +0300
Subject: feat: add video preview on hover to dashboard and apply new linter
 rules to some of the files

---
 src/site/components/grid/waterfall/Waterfall.vue | 56 ++++++++++++------------
 1 file changed, 29 insertions(+), 27 deletions(-)

(limited to 'src/site/components/grid/waterfall/Waterfall.vue')

diff --git a/src/site/components/grid/waterfall/Waterfall.vue b/src/site/components/grid/waterfall/Waterfall.vue
index af1bd72..cccc3ac 100644
--- a/src/site/components/grid/waterfall/Waterfall.vue
+++ b/src/site/components/grid/waterfall/Waterfall.vue
@@ -9,8 +9,6 @@
 	</div>
 </template>
 <script>
-// import {quickSort, getMinIndex, _, sum} from './util'
-
 const quickSort = (arr, type) => {
 	const left = [];
 	const right = [];
@@ -25,10 +23,10 @@ const quickSort = (arr, type) => {
 			right.push(arr[i]);
 		}
 	}
-	return quickSort(left, type).concat(povis, quickSort(right, type))
+	return quickSort(left, type).concat(povis, quickSort(right, type));
 };
 
-const getMinIndex = arr => {
+const getMinIndex = (arr) => {
 	let pos = 0;
 	for (let i = 0; i < arr.length; i++) {
 		if (arr[pos] > arr[i]) {
@@ -44,49 +42,53 @@ const _ = {
 	},
 	off(el, type, func, capture = false) {
 		el.removeEventListener(type, func, capture);
-	}
+	},
 };
 
-const sum = arr => arr.reduce((sum, val) => sum + val);
+const sum = (arr) => arr.reduce((acc, val) => acc + val, 0);
+
 export default {
 	name: 'Waterfall',
 	props: {
 		gutterWidth: {
 			type: Number,
-			default: 0
+			default: 0,
 		},
 		gutterHeight: {
 			type: Number,
-			default: 0
+			default: 0,
 		},
 		resizable: {
 			type: Boolean,
-			default: true
+			default: true,
 		},
 		align: {
 			type: String,
-			default: 'center'
+			default: 'center',
 		},
 		fixWidth: {
-			type: Number
+			type: Number,
+			default: 0,
 		},
 		minCol: {
 			type: Number,
-			default: 1
+			default: 1,
 		},
 		maxCol: {
-			type: Number
+			type: Number,
+			default: 0,
 		},
 		percent: {
-			type: Array
-		}
+			type: Array,
+			default: null,
+		},
 	},
 	data() {
 		return {
 			timer: null,
 			colNum: 0,
 			lastWidth: 0,
-			percentWidthArr: []
+			percentWidthArr: [],
 		};
 	},
 	created() {
@@ -105,16 +107,16 @@ export default {
 	},
 	methods: {
 		calulate(arr) {
-			let pageWidth = this.fixWidth ? this.fixWidth : this.$el.offsetWidth;
+			const pageWidth = this.fixWidth ? this.fixWidth : this.$el.offsetWidth;
 			// 百分比布局计算
 			if (this.percent) {
 				this.colNum = this.percent.length;
 				const total = sum(this.percent);
-				this.percentWidthArr = this.percent.map(value => (value / total) * pageWidth);
+				this.percentWidthArr = this.percent.map((value) => (value / total) * pageWidth);
 				this.lastWidth = 0;
 			// 正常布局计算
 			} else {
-				this.colNum = parseInt(pageWidth / (arr.width + this.gutterWidth));
+				this.colNum = parseInt(pageWidth / (arr.width + this.gutterWidth), 10);
 				if (this.minCol && this.colNum < this.minCol) {
 					this.colNum = this.minCol;
 					this.lastWidth = 0;
@@ -136,14 +138,14 @@ export default {
 		render() {
 			// 重新排序
 			let childArr = [];
-			childArr = this.$children.map(child => child.getMeta());
+			childArr = this.$children.map((child) => child.getMeta());
 			childArr = quickSort(childArr, 'order');
 			// 计算列数
-			this.calulate(childArr[0])
-			let offsetArr = Array(this.colNum).fill(0);
+			this.calulate(childArr[0]);
+			const offsetArr = Array(this.colNum).fill(0);
 			// 渲染
-			childArr.forEach(child => {
-				let position = getMinIndex(offsetArr);
+			childArr.forEach((child) => {
+				const position = getMinIndex(offsetArr);
 				// 百分比布局渲染
 				if (this.percent) {
 					let left = 0;
@@ -171,10 +173,10 @@ export default {
 				}
 				child.el.style.top = `${offsetArr[position]}px`;
 				offsetArr[position] += child.height + this.gutterHeight;
-				this.$el.style.height = `${Math.max.apply(Math, offsetArr)}px`;
+				this.$el.style.height = `${Math.max(...offsetArr)}px`;
 			});
 			this.$emit('rendered', this);
-		}
-	}
+		},
+	},
 };
 </script>
-- 
cgit v1.2.3


From fb0bc57542a44dcc94149f393d8a4ff0c2e7902b Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Tue, 7 Jul 2020 02:02:59 +0300
Subject: feat: try fixing THE SHITTY WATERFALL

---
 src/site/components/grid/waterfall/Waterfall.vue | 47 +++++++++++++++++++-----
 1 file changed, 38 insertions(+), 9 deletions(-)

(limited to 'src/site/components/grid/waterfall/Waterfall.vue')

diff --git a/src/site/components/grid/waterfall/Waterfall.vue b/src/site/components/grid/waterfall/Waterfall.vue
index cccc3ac..a83a275 100644
--- a/src/site/components/grid/waterfall/Waterfall.vue
+++ b/src/site/components/grid/waterfall/Waterfall.vue
@@ -1,14 +1,14 @@
-<style>
-	.waterfall {
-		position: relative;
-	}
-</style>
 <template>
 	<div class="waterfall">
-		<slot />
+		<WaterfallItem v-for="(item, index) in items" :key="item.id" :ref="`item-${item.id}`" :width="itemWidth">
+			<slot :item="item" />
+		</WaterfallItem>
 	</div>
 </template>
+
 <script>
+import WaterfallItem from './WaterfallItem.vue';
+
 const quickSort = (arr, type) => {
 	const left = [];
 	const right = [];
@@ -49,6 +49,9 @@ const sum = (arr) => arr.reduce((acc, val) => acc + val, 0);
 
 export default {
 	name: 'Waterfall',
+	components: {
+		WaterfallItem,
+	},
 	props: {
 		gutterWidth: {
 			type: Number,
@@ -82,6 +85,14 @@ export default {
 			type: Array,
 			default: null,
 		},
+		itemWidth: {
+			type: Number,
+			default: 150,
+		},
+		items: {
+			type: Array,
+			default: () => [],
+		},
 	},
 	data() {
 		return {
@@ -89,15 +100,21 @@ export default {
 			colNum: 0,
 			lastWidth: 0,
 			percentWidthArr: [],
+			readyChildCount: 0,
 		};
 	},
+	watch: {
+		items() {
+			this.$nextTick(() => this.render('watch'));
+		},
+	},
 	created() {
 		this.$on('itemRender', () => {
 			if (this.timer) {
 				clearTimeout(this.timer);
 			}
 			this.timer = setTimeout(() => {
-				this.render();
+				this.render('created');
 			}, 0);
 		});
 	},
@@ -105,6 +122,10 @@ export default {
 		this.resizeHandle();
 		this.$watch('resizable', this.resizeHandle);
 	},
+	beforeDestroy() {
+		this.$off('itemRender');
+		_.off(window, 'resize', this.render);
+	},
 	methods: {
 		calulate(arr) {
 			const pageWidth = this.fixWidth ? this.fixWidth : this.$el.offsetWidth;
@@ -135,10 +156,12 @@ export default {
 				_.off(window, 'resize', this.render, false);
 			}
 		},
-		render() {
+		render(context) {
+			console.log(context);
+			if (!this.items) return;
 			// 重新排序
 			let childArr = [];
-			childArr = this.$children.map((child) => child.getMeta());
+			childArr = this.items.map(({ id }) => this.$refs[`item-${id}`][0].getMeta());
 			childArr = quickSort(childArr, 'order');
 			// 计算列数
 			this.calulate(childArr[0]);
@@ -180,3 +203,9 @@ export default {
 	},
 };
 </script>
+
+<style>
+	.waterfall {
+		position: relative;
+	}
+</style>
-- 
cgit v1.2.3


From 5d61b4d000a114857e4519be25c5834f510d450f Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Tue, 7 Jul 2020 02:50:03 +0300
Subject: feat: refactor waterfall to be more efficient

---
 src/site/components/grid/waterfall/Waterfall.vue | 266 ++++++++---------------
 1 file changed, 94 insertions(+), 172 deletions(-)

(limited to 'src/site/components/grid/waterfall/Waterfall.vue')

diff --git a/src/site/components/grid/waterfall/Waterfall.vue b/src/site/components/grid/waterfall/Waterfall.vue
index a83a275..79a330a 100644
--- a/src/site/components/grid/waterfall/Waterfall.vue
+++ b/src/site/components/grid/waterfall/Waterfall.vue
@@ -1,51 +1,20 @@
 <template>
-	<div class="waterfall">
-		<WaterfallItem v-for="(item, index) in items" :key="item.id" :ref="`item-${item.id}`" :width="itemWidth">
+	<div ref="waterfall" class="waterfall">
+		<WaterfallItem
+			v-for="(item, index) in items"
+			:key="item.id"
+			:style="{ width: `${itemWidth}px`, marginBottom: `${gutterHeight}px` }"
+			:width="itemWidth">
 			<slot :item="item" />
 		</WaterfallItem>
 	</div>
 </template>
-
 <script>
 import WaterfallItem from './WaterfallItem.vue';
 
-const quickSort = (arr, type) => {
-	const left = [];
-	const right = [];
-	if (arr.length <= 1) {
-		return arr;
-	}
-	const povis = arr[0];
-	for (let i = 1; i < arr.length; i++) {
-		if (arr[i][type] < povis[type]) {
-			left.push(arr[i]);
-		} else {
-			right.push(arr[i]);
-		}
-	}
-	return quickSort(left, type).concat(povis, quickSort(right, type));
-};
-
-const getMinIndex = (arr) => {
-	let pos = 0;
-	for (let i = 0; i < arr.length; i++) {
-		if (arr[pos] > arr[i]) {
-			pos = i;
-		}
-	}
-	return pos;
-};
-
-const _ = {
-	on(el, type, func, capture = false) {
-		el.addEventListener(type, func, capture);
-	},
-	off(el, type, func, capture = false) {
-		el.removeEventListener(type, func, capture);
-	},
-};
-
-const sum = (arr) => arr.reduce((acc, val) => acc + val, 0);
+const isBrowser = typeof window !== 'undefined';
+const Masonry = isBrowser ? window.Masonry || require('masonry-layout') : null;
+const imagesloaded = isBrowser ? require('imagesloaded') : null;
 
 export default {
 	name: 'Waterfall',
@@ -53,159 +22,112 @@ export default {
 		WaterfallItem,
 	},
 	props: {
-		gutterWidth: {
-			type: Number,
-			default: 0,
-		},
-		gutterHeight: {
-			type: Number,
-			default: 0,
-		},
-		resizable: {
-			type: Boolean,
-			default: true,
-		},
-		align: {
-			type: String,
-			default: 'center',
-		},
-		fixWidth: {
-			type: Number,
-			default: 0,
-		},
-		minCol: {
-			type: Number,
-			default: 1,
-		},
-		maxCol: {
-			type: Number,
-			default: 0,
+		options: {
+			type: Object,
+			default: () => {},
 		},
-		percent: {
+		items: {
 			type: Array,
-			default: null,
+			default: () => [],
 		},
 		itemWidth: {
 			type: Number,
 			default: 150,
 		},
-		items: {
-			type: Array,
-			default: () => [],
+		gutterWidth: {
+			type: Number,
+			default: 10,
 		},
-	},
-	data() {
-		return {
-			timer: null,
-			colNum: 0,
-			lastWidth: 0,
-			percentWidthArr: [],
-			readyChildCount: 0,
-		};
-	},
-	watch: {
-		items() {
-			this.$nextTick(() => this.render('watch'));
+		gutterHeight: {
+			type: Number,
+			default: 4,
 		},
 	},
-	created() {
-		this.$on('itemRender', () => {
-			if (this.timer) {
-				clearTimeout(this.timer);
-			}
-			this.timer = setTimeout(() => {
-				this.render('created');
-			}, 0);
-		});
-	},
 	mounted() {
-		this.resizeHandle();
-		this.$watch('resizable', this.resizeHandle);
+		this.initializeMasonry();
+		this.imagesLoaded();
+	},
+	updated() {
+		this.performLayout();
+		this.imagesLoaded();
 	},
-	beforeDestroy() {
-		this.$off('itemRender');
-		_.off(window, 'resize', this.render);
+	unmounted() {
+		this.masonry.destroy();
 	},
 	methods: {
-		calulate(arr) {
-			const pageWidth = this.fixWidth ? this.fixWidth : this.$el.offsetWidth;
-			// 百分比布局计算
-			if (this.percent) {
-				this.colNum = this.percent.length;
-				const total = sum(this.percent);
-				this.percentWidthArr = this.percent.map((value) => (value / total) * pageWidth);
-				this.lastWidth = 0;
-			// 正常布局计算
-			} else {
-				this.colNum = parseInt(pageWidth / (arr.width + this.gutterWidth), 10);
-				if (this.minCol && this.colNum < this.minCol) {
-					this.colNum = this.minCol;
-					this.lastWidth = 0;
-				} else if (this.maxCol && this.colNum > this.maxCol) {
-					this.colNum = this.maxCol;
-					this.lastWidth = pageWidth - (arr.width + this.gutterWidth) * this.colNum + this.gutterWidth;
-				} else {
-					this.lastWidth = pageWidth - (arr.width + this.gutterWidth) * this.colNum + this.gutterWidth;
-				}
+		imagesLoaded() {
+			const node = this.$refs.waterfall;
+			imagesloaded(
+				node,
+				() => {
+					this.masonry.layout();
+				},
+			);
+		},
+		performLayout() {
+			const diff = this.diffDomChildren();
+			if (diff.removed.length > 0) {
+				this.masonry.remove(diff.removed);
+				this.masonry.reloadItems();
+			}
+			if (diff.appended.length > 0) {
+				this.masonry.appended(diff.appended);
+				this.masonry.reloadItems();
 			}
+			if (diff.prepended.length > 0) {
+				this.masonry.prepended(diff.prepended);
+			}
+			if (diff.moved.length > 0) {
+				this.masonry.reloadItems();
+			}
+			this.masonry.layout();
 		},
-		resizeHandle() {
-			if (this.resizable) {
-				_.on(window, 'resize', this.render, false);
-			} else {
-				_.off(window, 'resize', this.render, false);
+		diffDomChildren() {
+			const oldChildren = this.domChildren.filter((element) => !!element.parentNode);
+			const newChildren = this.getNewDomChildren();
+			const removed = oldChildren.filter((oldChild) => !newChildren.includes(oldChild));
+			const domDiff = newChildren.filter((newChild) => !oldChildren.includes(newChild));
+			const prepended = domDiff.filter((newChild, index) => newChildren[index] === newChild);
+			const appended = domDiff.filter((el) => !prepended.includes(el));
+			let moved = [];
+			if (removed.length === 0) {
+				moved = oldChildren.filter((child, index) => index !== newChildren.indexOf(child));
 			}
+			this.domChildren = newChildren;
+			return {
+				old: oldChildren,
+				new: newChildren,
+				removed,
+				appended,
+				prepended,
+				moved,
+			};
 		},
-		render(context) {
-			console.log(context);
-			if (!this.items) return;
-			// 重新排序
-			let childArr = [];
-			childArr = this.items.map(({ id }) => this.$refs[`item-${id}`][0].getMeta());
-			childArr = quickSort(childArr, 'order');
-			// 计算列数
-			this.calulate(childArr[0]);
-			const offsetArr = Array(this.colNum).fill(0);
-			// 渲染
-			childArr.forEach((child) => {
-				const position = getMinIndex(offsetArr);
-				// 百分比布局渲染
-				if (this.percent) {
-					let left = 0;
-					child.el.style.width = `${this.percentWidthArr[position]}px`;
-					if (position === 0) {
-						left = 0;
-					} else {
-						for (let i = 0; i < position; i++) {
-							left += this.percentWidthArr[i];
-						}
-					}
-					child.el.style.left = `${left}px`;
-				// 正常布局渲染
-				} else {
-					if (this.align === 'left') { // eslint-disable-line no-lonely-if
-						child.el.style.left = `${position * (child.width + this.gutterWidth)}px`;
-					} else if (this.align === 'right') {
-						child.el.style.left = `${position * (child.width + this.gutterWidth) + this.lastWidth}px`;
-					} else {
-						child.el.style.left = `${position * (child.width + this.gutterWidth) + this.lastWidth / 2}px`;
-					}
-				}
-				if (child.height === 0) {
-					return;
-				}
-				child.el.style.top = `${offsetArr[position]}px`;
-				offsetArr[position] += child.height + this.gutterHeight;
-				this.$el.style.height = `${Math.max(...offsetArr)}px`;
-			});
-			this.$emit('rendered', this);
+		initializeMasonry() {
+			if (!this.masonry) {
+				this.masonry = new Masonry(
+					this.$refs.waterfall,
+					{
+						columnWidth: this.itemWidth,
+						gutter: this.gutterWidth,
+						...this.options,
+					},
+				);
+				this.domChildren = this.getNewDomChildren();
+			}
+		},
+		getNewDomChildren() {
+			const node = this.$refs.waterfall;
+			const children = this.options && this.options.itemSelector
+				? node.querySelectorAll(this.options.itemSelector) : node.children;
+			return Array.prototype.slice.call(children);
 		},
 	},
 };
 </script>
 
-<style>
-	.waterfall {
-		position: relative;
-	}
+<style lang="scss" scoped>
+.wfi {
+
+}
 </style>
-- 
cgit v1.2.3

