Skip to content

Commit 43d8357

Browse files
authored
Merge pull request #19 from TheCodeRaccoons/Develop
Updating scripts
2 parents e609745 + 46ef20c commit 43d8357

6 files changed

Lines changed: 163 additions & 76 deletions

File tree

Dist/Functional/CMSFilter.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,8 @@ class CMSFilter {
337337
}
338338

339339
SetActiveTags() {
340+
if(!this.tagTemplateContainer) return;
340341
this.InitializeTagTemplate();
341-
// Clear existing tags before adding new ones
342-
this.tagTemplateContainer.innerHTML = "";
343342

344343
const filterTags = Object.keys(this.activeFilters);
345344
filterTags.forEach(tag => {

Dist/Functional/FormatNumbers.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,13 @@ class NumberFormatter {
6767

6868
const InitializeFormatNumbers = () => {
6969
try {
70+
window.trickeries = window.trickeries || [];
7071
const numbersToFormat = document.querySelectorAll('[wt-formatnumber-element="number"]');
7172
if (!numbersToFormat || numbersToFormat.length === 0) throw new Error("No elements found to format.");
7273

7374
numbersToFormat.forEach((numberContainer) => {
74-
new NumberFormatter(numberContainer);
75+
let instance = new NumberFormatter(numberContainer);
76+
window.trickeries.push({'FormatNumber': instance});
7577
});
7678
} catch (err) {
7779
console.error(`Format Number found an Error while initializing: ${err.message}`);

Dist/Functional/Marquee.js

Lines changed: 61 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,27 @@ class Marquee {
66
this.container = _container;
77
this.elements = Array.from(this.container.children);
88
if (this.elements.length === 0) throw new Error("No elements found inside the marquee container.");
9-
this.speed =_container.getAttribute('wt-marquee-speed') || 50;
10-
this.direction = _container.getAttribute('wt-marquee-direction') || 'left'
11-
this.viewportWidth = window.innerWidth;
12-
this.parentWidth = this.container.parentElement.offsetWidth;
13-
this.totalWidth = this.calculateTotalWidth();
14-
this.scrollPosition = 0;
9+
10+
this.speed = _container.getAttribute('wt-marquee-speed') || 50;
11+
this.direction = _container.getAttribute('wt-marquee-direction') || 'left'; // 'left', 'right', 'top', 'bottom'
12+
this.isVertical = this.direction === 'top' || this.direction === 'bottom';
13+
this.parentSize = this.isVertical ? this.container.parentElement.offsetHeight : this.container.parentElement.offsetWidth;
1514
this.gapSize = this.getGapSize();
1615

16+
this.scrollPosition = 0;
17+
this.totalSize = this.calculateTotalSize();
1718
this.fillContainer();
19+
this.setMarqueeStyles();
1820
this.startMarquee();
1921
this.handleResize();
2022
} catch (err) {
2123
console.error(`Error initializing Marquee: ${err.message}`);
2224
}
2325
}
2426

25-
calculateTotalWidth() {
27+
calculateTotalSize() {
2628
const gapTotal = (this.elements.length - 1) * this.gapSize;
27-
return this.elements.reduce((total, el) => total + el.offsetWidth, 0) + gapTotal;
29+
return this.elements.reduce((total, el) => total + (this.isVertical ? el.offsetHeight : el.offsetWidth), 0) + gapTotal;
2830
}
2931

3032
getGapSize() {
@@ -33,57 +35,76 @@ class Marquee {
3335
}
3436

3537
fillContainer() {
36-
let totalWidth = this.calculateTotalWidth();
37-
const targetWidth = this.parentWidth * 1.5;
38-
39-
while (totalWidth < targetWidth) {
38+
let totalSize = this.calculateTotalSize();
39+
const targetSize = this.parentSize * 1.5;
40+
41+
while (totalSize < targetSize) {
4042
this.elements.forEach(el => {
4143
const clone = el.cloneNode(true);
4244
this.container.appendChild(clone);
4345
});
4446
this.elements = Array.from(this.container.children);
45-
totalWidth = this.calculateTotalWidth();
47+
totalSize = this.calculateTotalSize();
4648
}
4749
}
4850

51+
setMarqueeStyles() {
52+
this.container.style.display = 'flex';
53+
this.container.style.flexDirection = this.isVertical ? 'column' : 'row';
54+
this.container.style.whiteSpace = 'nowrap';
55+
this.container.style.position = 'relative';
56+
}
57+
4958
startMarquee() {
5059
this.marqueeInterval = setInterval(() => {
51-
this.scrollPosition += this.direction === 'left' ? -1 : 1;
52-
60+
this.scrollPosition += (this.direction === 'left' || this.direction === 'top') ? -1 : 1;
5361
this.moveOffscreenElement();
5462

55-
this.container.style.transform = `translateX(${this.scrollPosition}px)`;
63+
if (this.isVertical) {
64+
this.container.style.transform = `translate3d(0, ${this.scrollPosition}px, 0)`;
65+
} else {
66+
this.container.style.transform = `translate3d(${this.scrollPosition}px, 0, 0)`;
67+
}
5668
}, this.speed);
5769
}
5870

5971
moveOffscreenElement() {
6072
const firstElement = this.container.firstElementChild;
61-
const firstElementWidth = firstElement.offsetWidth + this.gapSize;
62-
63-
if (this.direction === 'left' && this.scrollPosition <= -firstElementWidth) {
64-
this.container.style.transition = 'none';
65-
this.container.appendChild(firstElement);
66-
this.scrollPosition += firstElementWidth;
67-
requestAnimationFrame(() => {
68-
this.container.style.transition = '';
69-
});
70-
} else if (this.direction === 'right' && this.scrollPosition >= -firstElementWidth / 2) {
71-
const lastElement = this.container.lastElementChild;
72-
this.container.style.transition = 'none';
73-
this.container.insertBefore(lastElement, firstElement);
74-
this.scrollPosition -= firstElementWidth;
75-
requestAnimationFrame(() => {
76-
this.container.style.transition = '';
77-
});
73+
const lastElement = this.container.lastElementChild;
74+
75+
const firstElementSize = this.isVertical ? firstElement.offsetHeight : firstElement.offsetWidth;
76+
const firstElementTotalSize = firstElementSize + this.gapSize;
77+
78+
const lastElementSize = this.isVertical ? lastElement.offsetHeight : lastElement.offsetWidth;
79+
const lastElementTotalSize = lastElementSize + this.gapSize;
80+
81+
if (this.direction === 'left' || this.direction === 'top') {
82+
if (this.scrollPosition <= -firstElementTotalSize) {
83+
this.container.style.transition = 'none';
84+
this.container.appendChild(firstElement);
85+
this.scrollPosition += firstElementTotalSize;
86+
requestAnimationFrame(() => {
87+
this.container.style.transition = '';
88+
});
89+
}
90+
} else if (this.direction === 'right' || this.direction === 'bottom') {
91+
if (this.scrollPosition >= -firstElementTotalSize / 2) {
92+
this.container.style.transition = 'none';
93+
this.container.insertBefore(lastElement, firstElement);
94+
this.scrollPosition -= lastElementTotalSize;
95+
requestAnimationFrame(() => {
96+
this.container.style.transition = '';
97+
});
98+
}
7899
}
79100
}
80101

102+
81103
handleResize() {
82104
window.addEventListener('resize', () => {
83105
clearInterval(this.marqueeInterval);
84-
this.viewportWidth = window.innerWidth;
85-
this.parentWidth = this.container.parentElement.offsetWidth;
86-
this.totalWidth = this.calculateTotalWidth();
106+
this.parentSize = this.isVertical ? this.container.parentElement.offsetHeight : this.container.parentElement.offsetWidth;
107+
this.totalSize = this.calculateTotalSize();
87108
this.fillContainer();
88109
this.startMarquee();
89110
});
@@ -96,11 +117,13 @@ class Marquee {
96117

97118
const InitializeMarquee = () => {
98119
try {
120+
window.trickeries = window.trickeries || [];
99121
const marqueeContainers = document.querySelectorAll('[wt-marquee-element="container"]');
100122
if (!marqueeContainers || marqueeContainers.length === 0) throw new Error("No marquee containers found.");
101123

102124
marqueeContainers.forEach(container => {
103-
new Marquee(container);
125+
let instance = new Marquee(container);
126+
window.trickeries.push({'Marquee': instance});
104127
});
105128
} catch (err) {
106129
console.error(`Error in InitializeMarquee: ${err.message}`);
@@ -111,4 +134,4 @@ if (/complete|interactive|loaded/.test(document.readyState)) {
111134
InitializeMarquee();
112135
} else {
113136
window.addEventListener('DOMContentLoaded', InitializeMarquee);
114-
}
137+
};

Dist/WebflowOnly/CMSSelect.js

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,59 @@
1-
'use strict'
1+
'use strict';
22

3-
const InitializeCMSSelect = () => {
4-
5-
const selectElements = document.querySelectorAll('[wt-cmsselect-element^="select-"], [wt-cmsselect-element="select"]');
6-
7-
if(!selectElements || selectElements.length === 0) return;
3+
class CMSSelect {
4+
constructor(selectElement) {
5+
try {
6+
this.selectElement = selectElement;
7+
this.attributeValue = this.selectElement.getAttribute('wt-cmsselect-element');
8+
this.index = this.attributeValue.replace('select', '');
9+
10+
// Fetch the corresponding options
11+
this.options = document.querySelectorAll(`[wt-cmsselect-element="target${this.index}"]`);
12+
if (!this.options || this.options.length === 0) throw new Error(`No options found for select ${this.index}`);
813

9-
for(let select of selectElements){
10-
const _sel = select.getAttribute('wt-cmsselect-element');
11-
let index = _sel.replace('select','');
12-
let _opts = document.querySelectorAll(`[wt-cmsselect-element="target${index}"]`);
14+
// Populate the select element
15+
this.populateSelect();
16+
} catch (err) {
17+
console.error(`Error initializing CMSSelect: ${err.message}`);
18+
}
19+
}
1320

14-
for(let opt of _opts) {
15-
let val = opt.getAttribute('wt-cmsselect-value');
16-
let text = opt.innerText;
17-
18-
if(text && text !== "")
19-
select.add( new Option(text, (val ? val : text)))
21+
populateSelect() {
22+
try {
23+
this.options.forEach(opt => {
24+
const value = opt.getAttribute('wt-cmsselect-value');
25+
const text = opt.innerText;
26+
27+
if (text && text.trim() !== "") {
28+
const option = new Option(text, value || text);
29+
this.selectElement.add(option);
30+
}
31+
});
32+
} catch (err) {
33+
console.error(`Error populating select: ${err.message}`);
2034
}
2135
}
2236
}
2337

24-
window.addEventListener('DOMContentLoaded', InitializeCMSSelect());
38+
const InitializeCMSSelect = () => {
39+
try {
40+
window.trickeries = window.trickeries || [];
41+
const selectElements = document.querySelectorAll('[wt-cmsselect-element^="select-"], [wt-cmsselect-element="select"]');
42+
43+
if (!selectElements || selectElements.length === 0) throw new Error("No select elements found.");
44+
45+
selectElements.forEach(selectElement => {
46+
const instance = new CMSSelect(selectElement);
47+
window.trickeries.push({ 'CMSSelect': instance });
48+
});
49+
} catch (err) {
50+
console.error(`Error during CMSSelect initialization: ${err.message}`);
51+
}
52+
};
53+
54+
// Ensure the script runs when the DOM is fully loaded
55+
if (/complete|interactive|loaded/.test(document.readyState)) {
56+
InitializeCMSSelect();
57+
} else {
58+
window.addEventListener('DOMContentLoaded', InitializeCMSSelect);
59+
}

Dist/WebflowOnly/MirrorClick.js

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,50 @@
1-
'use strict'
21

3-
const InitializeMirrorClick = () => {
2+
'use strict';
3+
4+
class MirrorClick {
5+
constructor(triggerElement) {
6+
try {
7+
this.triggerElement = triggerElement;
8+
this.triggerAttr = triggerElement.getAttribute('wt-mirrorclick-element');
9+
this.index = this.triggerAttr.replace('trigger', '');
10+
this.targetElement = document.querySelector(`[wt-mirrorclick-element="target${this.index}"]`);
411

5-
let triggers = document.querySelectorAll('[wt-mirrorclick-element^="trigger-"], [wt-mirrorclick-element="trigger"]');
6-
7-
if(!triggers || triggers.length === 0) return;
12+
if (!this.targetElement) throw new Error(`Target element not found for trigger: ${this.index}`);
813

9-
for(let trigger of triggers) {
10-
let _triggerAttr = trigger.getAttribute('wt-mirrorclick-element');
11-
let _index = _triggerAttr.replace('trigger','');
12-
let _target = document.querySelector(`[wt-mirrorclick-element="target${_index}"]`);
14+
this.bindClickEvent();
15+
} catch (err) {
16+
console.error(`Error initializing MirrorClick: ${err.message}`);
17+
}
18+
}
1319

14-
if(_target) {
15-
trigger.addEventListener('click', () => {
16-
_target.click();
17-
})
20+
bindClickEvent() {
21+
try {
22+
this.triggerElement.addEventListener('click', () => {
23+
this.targetElement.click();
24+
});
25+
} catch (err) {
26+
console.error(`Error binding click event for MirrorClick: ${err.message}`);
1827
}
1928
}
2029
}
2130

22-
window.addEventListener('DOMContentLoaded', InitializeMirrorClick());
31+
const InitializeMirrorClick = () => {
32+
try {
33+
window.trickeries = window.trickeries || [];
34+
const triggers = document.querySelectorAll('[wt-mirrorclick-element^="trigger-"], [wt-mirrorclick-element="trigger"]');
35+
if (!triggers || triggers.length === 0) throw new Error("No trigger elements found.");
36+
37+
triggers.forEach((triggerElement) => {
38+
let instance = new MirrorClick(triggerElement);
39+
window.trickeries.push({'MirrorClick': instance});
40+
});
41+
} catch (err) {
42+
console.error(`MirrorClick found an error during initialization: ${err.message}`);
43+
}
44+
};
45+
46+
if (/complete|interactive|loaded/.test(document.readyState)) {
47+
InitializeMirrorClick();
48+
} else {
49+
window.addEventListener('DOMContentLoaded', InitializeMirrorClick);
50+
};

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
<br />
2525
<div align="center">
2626
<a href="https://github.com/TheCodeRaccoons/WebflowTrickery">
27-
<img src="https://raw.githubusercontent.com/TheCodeRaccoons/Imagery/16a395115ab598a94a7d1ab93f182218d8bbb751/wt-logo.svg" alt="Webflow Trickery Logo" height="140" />
27+
<img src="https://raw.githubusercontent.com/TheCodeRaccoons/Imagery/16a395115ab598a94a7d1ab93f182218d8bbb751/wt-logo.svg" alt="WebTricks Logo" height="140" />
2828
</a>
2929
<h5 align="center">
30-
Webflow Trickery aims to create easy to implement, reusable functionalities for the web. As it's name implies, the main platform this project targets is <a href="https://webflow.com/">Webflow</a>, but the majority of the scripts are made with general web development in mind. Meaning that most of this scripts should work without an issue on any website unless it is a CMS functionality or a Webflow specific script.
30+
WebTricks aims to create easy to implement, reusable functionalities for the web. As it's name implies, the main platform this project targets is <a href="https://webflow.com/">Webflow</a>, but the majority of the scripts are made with general web development in mind. Meaning that most of this scripts should work without an issue on any website unless it is a CMS functionality or a Webflow specific script.
3131
</h5>
3232
<p align="center">
3333
<a target="_blank" href="https://github.com/TheCodeRaccoons/WebflowTrickery/issues/new/choose">Request a functionality</a>
@@ -54,12 +54,12 @@ All of the documentation is explained by functionality in <a href="https://coder
5454
<p>
5555
As any other developer using no-code web design tools I've struggled with the ability to bring specific, more complex functionalities to platforms like Webflow.
5656
<br/><br/>
57-
Over the past couple of years I started noticing some of this functionalities are not only commonly used but also requested by many in the community. Webflow trickery aims to empower developers and designers alike, provinding both simple and complex functionalities that could, in other cases, take longer to develop from scratch.
57+
Over the past couple of years I started noticing some of this functionalities are not only commonly used but also requested by many in the community. WebTricks aims to empower developers and designers alike, provinding both simple and complex functionalities that could, in other cases, take longer to develop from scratch.
5858
<br/><br/>
5959
This being said even though most of this functionalities are built for Webflow, there's many that can be used in any other web project and platform. Feel free to see the full <a href="https://coderacoons.webflow.io/tools/webflow-trickery">documentation</a> in our site for the complete list of functionalities and scripts available.
6060
</p>
6161
<sub>
62-
Webflow Trickery might have been started as a personal project, but I'm a believer that a project for the comunity by the comunity can offer way more value than any single dev could provide so feel free to contribute to this project and use any solution here.
62+
WebTricks might have been started as a personal project, but I'm a believer that a project for the comunity by the comunity can offer way more value than any single dev could provide so feel free to contribute to this project and use any solution here.
6363
</sub>
6464

6565
<h2 id="getting-started">Getting Started</h2>

0 commit comments

Comments
 (0)