100 CMS Items Limit in custom code

Hey gang,

I use mapbox to display all places from my CMS on a map. I used KC’s tutorial (@KC_Kat), and it worked wonderfully.

…Until I hit Webflow’s 100 CMS items limit.

I tried all the AI’s to edit my code (I have very limited knowledge myself), but nothing worked so far.

Any idea on how to edit my code so that it takes into account all items?

CODE:

<script src="https://tools.refokus.com/cms-filter/bundle.v1.5.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>

<script>
//remove map wrapper
$(".locations-map_wrapper").removeClass("is--show");

//-----------MAPBOX SETUP CODE BELOW-----------

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! REPLACE ACCESS TOKEN WITH YOURS HERE !!!
mapboxgl.accessToken = "XXXXXXXXXXXXXXXXXXXXXXXXX";
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

// create empty locations geojson object
let mapLocations = {
	type: "FeatureCollection",
	features: [],
};

let selectedMapLocations = [];

// Initialize map and load in #map wrapper
let map = new mapboxgl.Map({
	container: "map",
	style: "mapbox://styles/ramesquinerie/clzqyzfgr00bu01qtcug8cfaw",
	center: [2.837646, 46.859359],
	zoom: 5.36,
});

// Adjust zoom of map for mobile and desktop
let mq = window.matchMedia("(min-width: 480px)");
if (mq.matches) {
	map.setZoom(5.36); //set map zoom level for desktop size
} else {
	map.setZoom(4); //set map zoom level for mobile size
}

// Add zoom and rotation controls to the map.
map.addControl(new mapboxgl.NavigationControl());

// Get cms items
let listLocations = document.getElementById("location-list").childNodes;

// For each collection item, grab hidden fields and convert to geojson property
function getGeoData() {
	listLocations.forEach(function (location, i) {
		let locationLat = location.querySelector("#locationLatitude").value;
		let locationLong = location.querySelector("#locationLongitude").value;
		let locationInfo = location.querySelector(".locations-map_card").innerHTML;
		let coordinates = [locationLong, locationLat];
		let locationID = location.querySelector("#locationID").value;
    	//add array ID
    	let arrayID = (i + 1) - 1;
		let geoData = {
			type: "Feature",
			geometry: {
				type: "Point",
				coordinates: coordinates,
			},
			properties: {
				id: locationID,
				description: locationInfo,
        		arrayID: arrayID,
			},
		};

		if (mapLocations.features.includes(geoData) === false) {
			mapLocations.features.push(geoData);
		}
	});
}

// Invoke function
getGeoData();

// Define mapping function to be invoked later
function addMapPoints() {
	// Add the data to your map as a layer
	map.addLayer({
		id: "locations",
		type: "circle",
		source: {
			type: "geojson",
			data: mapLocations,
		},
		paint: {
			"circle-radius": 8,
			"circle-stroke-width": 1,
			"circle-color": "#a8c686",
			"circle-opacity": 1,
			"circle-stroke-color": "#303037",
		},
	});
  
	// Function to open a popup with the correct location
	function addPopup(e) {
		const coordinates = e.features[0].geometry.coordinates.slice();
		const description = e.features[0].properties.description;

		while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
			coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
		}

		new mapboxgl.Popup().setLngLat(coordinates).setHTML(description).addTo(map); 
	}
 
	// When a click event occurs on a feature in the places layer, open a popup
	map.on("click", "locations", (e) => {
    	const ID = e.features[0].properties.arrayID;
    	addPopup(e);
    	$(".locations-map_wrapper").addClass("is--show");

    	if ($(".locations-map_item.is--show").length) {
    		$(".locations-map_item").removeClass("is--show");
  		} 
    	$(".locations-map_item").eq(ID).addClass("is--show");
	});

	// Center the map on the coordinates of any clicked circle from the 'locations' layer.
	map.on("click", "locations", (e) => {
		map.flyTo({
			center: e.features[0].geometry.coordinates,
			speed: 0.5,
			curve: 1,
			easing(t) {
				return t;
			},
		});
	});

	// Change the cursor to a pointer when the mouse is over the 'locations' layer.
	map.on("mouseenter", "locations", () => {
		map.getCanvas().style.cursor = "pointer";
	});

	// Change it back to a pointer when it leaves.
	map.on("mouseleave", "locations", () => {
		map.getCanvas().style.cursor = "";
	});
}

// When map is loaded, initialize with data
map.on("load", function (e) {
	addMapPoints();
});

// Close side nav with button
$(".close-block").click(function(){
	$(".locations-map_wrapper").removeClass("is--show");
});

// Hover popup
const popup = new mapboxgl.Popup({
	closeButton: false,
	closeOnClick: false
});

map.on('mouseenter', 'locations', (e) => {
	map.getCanvas().style.cursor = 'pointer';
    const coordinates = e.features[0].geometry.coordinates.slice();
    const description = e.features[0].properties.description;

    while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
    	coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
    }

    popup.setLngLat(coordinates).setHTML(description).addTo(map);
});

map.on('mouseleave', 'locations', () => {
    map.getCanvas().style.cursor = '';
    popup.remove();
});

// ----------- SCROLL BEHAVIOR CONTROL -------------

// Disable zoom via scroll on the map by default
map.scrollZoom.disable();

// Function to check if the map is visible in the viewport
function isMapInView() {
    const mapElement = document.getElementById('map');
    const rect = mapElement.getBoundingClientRect();
    return rect.top >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight);
}

// Variable to store the scrolling state
let isScrolling;

// Event listener for scroll
window.addEventListener('scroll', function () {
	// Clear any ongoing timeout
    window.clearTimeout(isScrolling);

    // Disable scroll zoom while scrolling
    map.scrollZoom.disable();

    // Set a timeout to reactivate scroll zoom after scrolling stops
    isScrolling = setTimeout(function() {
        // If the map is in the viewport, enable scroll zoom
        if (isMapInView()) {
            map.scrollZoom.enable();
        }
    }, 100);  // Wait 300ms after scroll stops
});

</script>

Here is my site Read-Only

How many items do you need to support?

If the collection you’re using is Lieux ( 115 items ) and you will stay under 200, you can use two collection lists. The second will be ranged to show 101-200.

200 will work for now but I’m planning on having much more than 200 “Lieux” ahah — so I’m looking for a more permanent solution, thus in the code

it seems what the AI’s tried to do was:

  1. Activate pagination
  2. Give an ID to the “Next” button
  3. Add some code to ‘load’ the 100-115 items by using the Next button

First, double-check- most mapping solutions have a pin limit anyway, typically around 100. No sense in engineering something if it ends up being useless.

The main approach I use are focused on performance, so #1 is the one I’ve described here. With 20 collection lists you could do up to 2000 items. This is the fastest since it’s a single page fetch and all of the data is integrated in the SSR step.

If you need a lot of collection lists for other purposes on this page, you could create a “data” page which contains nothing but those 20 collection lists, and then fetch that content in script.

If you need more flexibility, and want to try things like filtering, I’d go the route of using FInsweet CMS Filter + CMS Load. They have a JS API that might work with the local all mechanic, so that all of the pins load without pagination, and you can both display cards and map pins at the same time. You’d need to R&D a bit, the API docs are minimal.

You can also build your own version of this, I have some code I somewhere for “de-pagination”- it’s performance-expensive though. The advantage of Finsweet’s is that the caching layer is built in and it directly integrates with FS Filter.

Thanks for all these details! I’ll give it a try and report back if I have more questions :slight_smile: