@widelab-nc/widelab 1.1.27 → 1.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@widelab-nc/widelab",
3
- "version": "1.1.27",
3
+ "version": "1.1.28",
4
4
  "description": "Widelab starter template based on Finsweet template + add-ons.",
5
5
  "homepage": "https://widelab.co",
6
6
  "license": "ISC",
package/src/index.js CHANGED
@@ -968,36 +968,250 @@ window.badgeColorChange = function(e) {
968
968
  }
969
969
 
970
970
 
971
+ // Filtering logic on Client's page
972
+ window.clientFilters = function() {
973
+ function updateCheckboxCounts(excludeField) {
971
974
 
972
- // GSAP Counter Up Animation
975
+ const fields = ['industry', 'country', 'services'];
976
+
977
+ fields.forEach(function(field) {
978
+ if (field === excludeField) return;
979
+
980
+ const checkboxes = document.querySelectorAll(`span[fs-cmsfilter-field="${field}"]`);
981
+
982
+ checkboxes.forEach(function(checkbox) {
983
+ const originalText = checkbox.dataset.originalText || checkbox.textContent.trim();
984
+ checkbox.dataset.originalText = originalText;
985
+
986
+ let matchedCount = 0;
987
+
988
+ document.querySelectorAll(`div[fs-cmsfilter-field="${field}"]`).forEach(function(div) {
989
+ if (div.textContent.trim() === originalText) {
990
+ matchedCount++;
991
+ }
992
+ });
993
+
994
+ let countSpan = checkbox.nextElementSibling;
995
+ if (!countSpan || !countSpan.classList.contains('count')) {
996
+ countSpan = document.createElement('span');
997
+ countSpan.className = 'count';
998
+ checkbox.insertAdjacentElement('afterend', countSpan);
999
+ }
1000
+ countSpan.textContent = `(${matchedCount})`;
1001
+
1002
+ const parentDiv = checkbox.closest('div.w-dyn-item');
1003
+ if (matchedCount === 0) {
1004
+ parentDiv.classList.add('empty-category');
1005
+ } else {
1006
+ parentDiv.classList.remove('empty-category');
1007
+ }
1008
+ });
1009
+
1010
+ sortCheckboxes(field);
1011
+ });
1012
+ }
1013
+
1014
+ function sortCheckboxes(field) {
1015
+
1016
+ const parentList = document.querySelector(`span[fs-cmsfilter-field="${field}"]`).closest('.collection-list');
1017
+ const items = Array.from(parentList.children);
1018
+
1019
+ items.sort(function(a, b) {
1020
+ const countA = parseInt((a.querySelector('.count')?.textContent || '').replace(/[()]/g, '')) || 0;
1021
+ const countB = parseInt((b.querySelector('.count')?.textContent || '').replace(/[()]/g, '')) || 0;
1022
+ return countB - countA;
1023
+ });
1024
+
1025
+ items.forEach(function(item) {
1026
+ parentList.appendChild(item);
1027
+ });
1028
+ }
1029
+
1030
+ updateCheckboxCounts();
1031
+
1032
+ function delayedUpdate(excludeField) {
1033
+ setTimeout(function() {
1034
+ updateCheckboxCounts(excludeField);
1035
+ }, 200);
1036
+ }
1037
+
1038
+ document.querySelectorAll('.w-checkbox').forEach(function(checkbox) {
1039
+ checkbox.addEventListener('click', function() {
1040
+ const spanElement = checkbox.closest('label').querySelector('span[fs-cmsfilter-field]');
1041
+ if (spanElement) {
1042
+ const field = spanElement.getAttribute('fs-cmsfilter-field');
1043
+ delayedUpdate(field);
1044
+ }
1045
+ });
1046
+ });
1047
+
1048
+ document.querySelectorAll('.cross-icon').forEach(function(icon) {
1049
+ icon.addEventListener('click', function() {
1050
+ delayedUpdate(null); // Update all fields with 200ms delay
1051
+ });
1052
+ });
1053
+
1054
+ document.querySelectorAll('.filters-clients_dropdown-field').forEach(function(dropdownField) {
1055
+ dropdownField.addEventListener('click', function() {
1056
+ delayedUpdate(null); // Update all fields with 200ms delay
1057
+ });
1058
+ });
1059
+
1060
+ function toggleClearButton() {
1061
+ if (document.querySelectorAll('.active-dropdown').length > 0) {
1062
+ document.querySelector('.clear-button').style.display = 'block';
1063
+ } else {
1064
+ document.querySelector('.clear-button').style.display = 'none';
1065
+ }
1066
+ }
1067
+ toggleClearButton();
1068
+ const observer = new MutationObserver(toggleClearButton);
1069
+
1070
+ observer.observe(document.body, {
1071
+ childList: true,
1072
+ subtree: true,
1073
+ attributes: true,
1074
+ attributeFilter: ['class']
1075
+ });
1076
+
1077
+ document.querySelectorAll('[fs-cmsfilter-element="dropdown"]').forEach(function(dropdown) {
1078
+ const originalText = dropdown.querySelector('[filters-clients_dropdown-field="tag-name-title"]').textContent;
1079
+ let firstCheckedText = null;
1080
+
1081
+ dropdown.querySelectorAll('input[type="checkbox"]').forEach(function(checkbox) {
1082
+ checkbox.addEventListener('change', function() {
1083
+ const checkedBoxes = dropdown.querySelectorAll('input[type="checkbox"]:checked');
1084
+ const titleField = dropdown.querySelector('[filters-clients_dropdown-field="tag-name-title"]');
1085
+ const dropdownHolder = dropdown.closest('.dropdown-holder');
1086
+ const tagNumber = dropdown.querySelector('[fs-cmsfilter-element="tag-number"]');
1087
+
1088
+ if (checkedBoxes.length > 0) {
1089
+ // Check if firstCheckedText is still checked
1090
+ if (![...checkedBoxes].some(cb => cb.nextElementSibling.textContent.split('(')[0].trim() === firstCheckedText)) {
1091
+ // If not, set it to the current checkbox text without the count
1092
+ firstCheckedText = checkedBoxes[0].nextElementSibling.textContent.split('(')[0].trim();
1093
+ }
1094
+ titleField.textContent = firstCheckedText;
1095
+ dropdownHolder.classList.add('active-dropdown');
1096
+ } else {
1097
+ titleField.textContent = originalText;
1098
+ dropdownHolder.classList.remove('active-dropdown');
1099
+ firstCheckedText = null;
1100
+ }
1101
+
1102
+ if (checkedBoxes.length > 1) {
1103
+ const numberText = `+${checkedBoxes.length - 1}`;
1104
+ tagNumber.textContent = numberText;
1105
+ } else {
1106
+ tagNumber.textContent = '';
1107
+ }
1108
+ });
1109
+ });
1110
+ });
1111
+ }
1112
+
1113
+ // Filtering logic on Client's page
1114
+ window.formatCounter = function() {
1115
+ function format_number(x) {
1116
+ let parts = x.toFixed(1).split(".");
1117
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
1118
+ let formattedNumber = parts.join(".");
1119
+ let digits = formattedNumber.split('').map(char => {
1120
+ if (char === '.') {
1121
+ return char;
1122
+ } else {
1123
+ return `<span class="single-number">${char}</span>`;
1124
+ }
1125
+ }).join('');
1126
+ return digits;
1127
+ }
1128
+
1129
+ function easeOutQuad(t) {
1130
+ return t * (2 - t);
1131
+ }
1132
+
1133
+ function animateValue(start, end, duration) {
1134
+ const counter = document.getElementById('counter');
1135
+ let startTimestamp = null;
1136
+ const step = (timestamp) => {
1137
+ if (!startTimestamp) startTimestamp = timestamp;
1138
+ const progress = Math.min((timestamp - startTimestamp) / duration, 1);
1139
+ const easedProgress = easeOutQuad(progress);
1140
+ const currentValue = start + (end - start) * easedProgress;
1141
+ counter.innerHTML = format_number(currentValue);
1142
+ if (progress < 1) {
1143
+ window.requestAnimationFrame(step);
1144
+ }
1145
+ };
1146
+ window.requestAnimationFrame(step);
1147
+ }
1148
+
1149
+ animateValue(52.0, 56.2, 3500);
1150
+ }
1151
+
1152
+ // GSAP Counter Up Animation onc Client's Page
973
1153
  window.counterUpAnimation = function() {
1154
+
1155
+
1156
+ function format_number(x) {
1157
+ let parts = x.toFixed(1).split(".");
1158
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
1159
+ let formattedNumber = parts.join(".");
1160
+ let digits = formattedNumber.split('').map(char => {
1161
+ if (char === '.') {
1162
+ return char;
1163
+ } else {
1164
+ return `<span class="single-number">${char}</span>`;
1165
+ }
1166
+ }).join('');
1167
+ return digits;
1168
+ }
1169
+
1170
+ function easeOutQuad(t) {
1171
+ return t * (2 - t);
1172
+ }
1173
+
1174
+ function animateValue(start, end, duration) {
1175
+ const counter = document.getElementById('counter');
1176
+ let startTimestamp = null;
1177
+ const step = (timestamp) => {
1178
+ if (!startTimestamp) startTimestamp = timestamp;
1179
+ const progress = Math.min((timestamp - startTimestamp) / duration, 1);
1180
+ const easedProgress = easeOutQuad(progress);
1181
+ const currentValue = start + (end - start) * easedProgress;
1182
+ counter.innerHTML = format_number(currentValue);
1183
+ if (progress < 1) {
1184
+ window.requestAnimationFrame(step);
1185
+ }
1186
+ };
1187
+ window.requestAnimationFrame(step);
1188
+ }
1189
+
1190
+ animateValue(52.0, 56.2, 3500);
1191
+
1192
+
974
1193
  const counters = document.querySelectorAll('#counter');
975
1194
 
976
1195
  counters.forEach(counter => {
977
- // Get the final value from the element's text content and parse it as a float
978
1196
  const finalValue = parseFloat(counter.textContent.replace(/,/g, '')); // Handle comma-separated numbers
979
1197
 
980
- // Create a GSAP animation for the counter
981
1198
  gsap.fromTo(counter,
982
1199
  { innerHTML: 0 },
983
1200
  {
984
1201
  innerHTML: finalValue,
985
- duration: 2, // Animation duration in seconds
1202
+ duration: 2,
986
1203
  ease: 'power1.inOut',
987
- snap: { innerHTML: 1 }, // Ensure whole numbers
1204
+ snap: { innerHTML: 1 },
988
1205
  onUpdate: function() {
989
- // Update the element's text content with the current value
990
- counter.textContent = this.targets()[0].innerHTML.toLocaleString(); // Format with commas if needed
1206
+
1207
+ counter.textContent = this.targets()[0].innerHTML.toLocaleString();
991
1208
  }
992
1209
  }
993
1210
  );
994
1211
  });
995
1212
  }
996
1213
 
997
-
998
-
999
-
1000
-
1214
+ // Slider on Client's page
1001
1215
  window.heroSliders = function(e) {
1002
1216
  console.log("Initializing Splide on element:", e);
1003
1217
 
@@ -1023,7 +1237,6 @@ window.heroSliders = function(e) {
1023
1237
 
1024
1238
  const descriptions = e.querySelectorAll('.slider-description');
1025
1239
 
1026
- // Set the initial state: Hide descriptions except the one in the active slide
1027
1240
  descriptions.forEach(desc => {
1028
1241
  if (!desc.closest('.splide__slide').classList.contains('is-active')) {
1029
1242
  gsap.set(desc, { opacity: 0 });
@@ -1036,12 +1249,10 @@ window.heroSliders = function(e) {
1036
1249
  });
1037
1250
  }
1038
1251
 
1039
- // Hide descriptions instantly on slide change
1040
1252
  slider.on('move', function() {
1041
1253
  gsap.set(descriptions, { opacity: 0 });
1042
1254
  });
1043
1255
 
1044
- // Show description on new active slide
1045
1256
  slider.on('active', function (slide) {
1046
1257
  gsap.to(slide.slide.querySelectorAll('.slider-description'), { opacity: 1, duration: 0.15, ease: 'linear' });
1047
1258
  });