Contact & Store Finder
Online Orders:
nzorder@chhl.co.
Club or school quote requests: contact your nearest branch using the Store Locator below.
let map;
let infoWindow;
let markersByName = {};
let lastSearchLatLng = null;
const stores = [
{
name: "Mt Eden Branch (Auckland)",
address: "29 Enfield Street, Mount Eden, Auckland 1024",
phone: "+64 9 558 2463",
email: "ak@justhockey.co.nz",
hours: "Mon-Fri 10:30am - 5:30pm | Sat-Sun 9:00am - 3:00pm",
googleUrl: "https://maps.app.goo.gl/tuvc3Vdmci8im9H8A",
lat:-36.86891352933891, lng: 174.7633514000947
},
{
name: "North Harbour Branch",
address: "5/59 Paul Matthews Road, Albany, Auckland 0632",
phone: "+64 9 415 8444",
email: "nh@justhockey.co.nz",
hours: "Mon-Tue CLOSED | Wed-Fri 10:30am - 5:30pm | Sat-Sun 9:00am - 3:00pm",
googleUrl: "https://maps.app.goo.gl/sUX1PJcWGcni6w9v5",
lat:-36.7508720425155, lng: 174.7129546472372
},
{
name: "Mount Maunganui Branch",
address: "6 Tawa Street, Mount Maunganui, Tauranga 3116",
phone: "+64 7 942 0243",
email: "tauranga@cri6523.e-retailer.co.nz",
hours: "Mon-Tue CLOSED | Wed-Fri 10:30am - 5:30pm | Sat-Sun 9:00am - 3:00pm",
googleUrl: "https://maps.app.goo.gl/R163AGbLh4x7H7f26",
lat: -37.643651048803235, lng: 176.18712702537158
},
{
name: "Hamilton Branch",
address: "558 Anglesea Street, Hamilton 3204",
phone: "+64 7 838 0912",
email: "hamilton@cri6523.e-retailer.co.nz",
hours: "Mon-Fri 10:30am - 5:30pm | Sat-Sun 9:00am - 3:00pm",
googleUrl: "https://maps.app.goo.gl/bwUtPzmTyrWqU86s5",
lat: -37.781375222666895, lng: 175.27449087650587
},
{
name: "Wellington Branch",
address: "218 Riddiford Street, Newtown, Wellington 6021",
phone: "+64 4 389 4384",
email: "well@justhockey.co.nz",
hours: "Mon-Fri 10:30am - 5:30pm | Sat-Sun 9:00am - 3:00pm",
googleUrl: "https://maps.app.goo.gl/TjavjHudZBLf6Jmr8",
lat: -41.31507405035833, lng: 174.78005071447575
},
{
name: "Christchurch Branch",
address: "37 Mandeville Street, Riccarton, Christchurch 8011",
phone: "+64 3 377 3069",
email: "store@justhockey.co.nz",
hours: "Mon-Fri 10:30am - 5:30pm | Sat-Sun 9:00am - 3:00pm",
googleUrl: "https://maps.app.goo.gl/7nZWwd1xcG9dy5pu6",
lat: -43.53478382238378, lng: 172.60611752575437
}
];
function haversineKm(lat1, lon1, lat2, lon2) {
const R = 6371;
const dLat = (lat2-lat1) * Math.PI/180;
const dLon = (lon2-lon1) * Math.PI/180;
const a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1*Math.PI/180) * Math.cos(lat2*Math.PI/180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
}
function directionsUrl(address) {
return "https://www.google.com/maps/dir/?api=1&destination=" + encodeURIComponent(address);
}
function infoHtml(store, distanceKm) {
const dist = (typeof distanceKm === "number")
? `${distanceKm.toFixed(1)} km away
`
: "";
return `
${store.name}
${store.address}
Call: ${store.phone}
Hours: ${store.hours}
Note: Trading hours updates are on the
Google listing.
GET DIRECTIONS
${dist}
`;
}
function renderResults(list) {
const el = document.getElementById("ceResults");
el.innerHTML = "";
list.forEach((s) => {
const card = document.createElement("div");
card.className = "ce-locator__card";
card.setAttribute("data-store", s.name);
const distLine = (typeof s._km === "number")
? `${s._km.toFixed(1)} km
`
: "";
card.innerHTML = `
${s.name}
${s.address}
${s.hours}
GET DIRECTIONS
${distLine}
`;
card.addEventListener("click", (e) => {
if (e.target && e.target.tagName === "A") return;
const marker = markersByName[s.name];
if (!marker) return;
document.querySelectorAll(".ce-locator__card").forEach(x => x.classList.remove("is-active"));
card.classList.add("is-active");
infoWindow.close();
const km = (typeof s._km === "number") ? s._km : undefined;
infoWindow.setContent(infoHtml(s, km));
infoWindow.open(map, marker);
map.setCenter({ lat: s.lat, lng: s.lng });
map.setZoom(12);
});
el.appendChild(card);
});
}
function applyQueryFilter(q) {
const query = (q || "").trim().toLowerCase();
if (!query) return stores.slice();
return stores.filter(s => (`${s.name} ${s.address}`).toLowerCase().includes(query));
}
function sortByDistanceIfKnown(list) {
if (!lastSearchLatLng) return list;
const lat = lastSearchLatLng.lat();
const lng = lastSearchLatLng.lng();
return list
.map(s => ({ ...s, _km: haversineKm(lat, lng, s.lat, s.lng) }))
.sort((a,b) => a._km - b._km);
}
function setResultsFromCurrentState() {
const q = document.getElementById("pac-input").value;
renderResults(sortByDistanceIfKnown(applyQueryFilter(q)));
}
function findClosestTo(latLng) {
const lat = latLng.lat();
const lng = latLng.lng();
let closest = null;
let minKm = Infinity;
stores.forEach(s => {
const km = haversineKm(lat, lng, s.lat, s.lng);
if (km < minKm) { minKm = km; closest = { ...s, _km: km }; }
});
return closest;
}
function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
center: { lat: -40.9006, lng: 174.8860 },
zoom: 5
});
infoWindow = new google.maps.InfoWindow();
markersByName = {};
const bounds = new google.maps.LatLngBounds();
stores.forEach(store => {
const pos = { lat: store.lat, lng: store.lng };
const marker = new google.maps.Marker({
map,
position: pos,
title: store.name
});
marker.addListener("click", () => {
document.querySelectorAll(".ce-locator__card").forEach(x => x.classList.remove("is-active"));
const card = document.querySelector(`.ce-locator__card[data-store="${CSS.escape(store.name)}"]`);
if (card) card.classList.add("is-active");
infoWindow.close();
infoWindow.setContent(infoHtml(store, store._km));
infoWindow.open(map, marker);
});
markersByName[store.name] = marker;
bounds.extend(pos);
});
map.fitBounds(bounds);
// initial list
renderResults(stores.slice());
// Places autocomplete (NZ)
const input = document.getElementById("pac-input");
const ac = new google.maps.places.Autocomplete(input, {
componentRestrictions: { country: "nz" },
fields: ["geometry", "name"]
});
ac.addListener("place_changed", () => {
const place = ac.getPlace();
if (!place.geometry || !place.geometry.location) return;
lastSearchLatLng = place.geometry.location;
// render list sorted by distance
setResultsFromCurrentState();
// auto-open closest store to the searched location
const closest = findClosestTo(lastSearchLatLng);
if (!closest) return;
const marker = markersByName[closest.name];
if (!marker) return;
map.setCenter({ lat: closest.lat, lng: closest.lng });
map.setZoom(12);
infoWindow.close();
infoWindow.setContent(infoHtml(closest, closest._km));
infoWindow.open(map, marker);
const card = document.querySelector(`.ce-locator__card[data-store="${CSS.escape(closest.name)}"]`);
if (card) {
document.querySelectorAll(".ce-locator__card").forEach(x => x.classList.remove("is-active"));
card.classList.add("is-active");
card.scrollIntoView({ behavior: "smooth", block: "nearest" });
}
});
// typing filter (name/suburb/postcode)
input.addEventListener("input", () => setResultsFromCurrentState());
// Optional: support ?q= in URL
try {
const params = new URLSearchParams(window.location.search);
const q = params.get("q");
if (q) {
input.value = q;
setResultsFromCurrentState();
}
} catch(e) {}
}