// add tile layer from OSM var baseMap = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox', maxZoom: 18, id: 'mapbox/dark-v10', tileSize: 512, zoomOffset: -1, accessToken: 'pk.eyJ1IjoiaHVnaHIiLCJhIjoiY2lxenRqMGQyMDJvdWZwbWd0d2JxeGswNiJ9.vfUQRJDzbJhaG_865TSkPA' }); var baseRules = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox
Incorporates Administrative Boundaries ©PSMA Australia Limited licensed by the Commonwealth of Australia under Creative Commons Attribution 4.0 International licence (CC BY 4.0).', maxZoom: 18, id: 'mapbox/light-v10', tileSize: 512, zoomOffset: -1, accessToken: 'pk.eyJ1IjoiaHVnaHIiLCJhIjoiY2lxenRqMGQyMDJvdWZwbWd0d2JxeGswNiJ9.vfUQRJDzbJhaG_865TSkPA' }); // attach map to #mapid div above and centre var map = L.map('mapid', { center: [-27.00, 133.000], zoom: 5, layers: [baseMap] }); // Use TopoJSON // ----------------------------------------------------------------- L.TopoJSON = L.GeoJSON.extend({ addData: function (jsonData) { if (jsonData.type === 'Topology') { for (let key in jsonData.objects) { geojson = topojson.feature(jsonData, jsonData.objects[key]); L.GeoJSON.prototype.addData.call(this, geojson); } } else { L.GeoJSON.prototype.addData.call(this, jsonData); } }, }); // // Copyright (c) 2013 Ryan Clark (MIT) // ----------------------------------------------------------------- // library services fines overlay var fines = new L.TopoJSON(libraryServices, { style: function(feature){ return { fillColor: getFinesColor(feature.properties.fines), weight: 3, color: "white", dashArray: "4", fillOpacity: 0.4 } }, onEachFeature: function onEachFeature(feature, layer) { layer.on({ mouseover: e => highlightFeature(e), mouseout: e => resetHighlight(e, fines), click: zoomToFeature }) } }); // fill patterns for loan period overlay var circles = new L.PatternCircle({ color: '#000', weight: 1, radius: 2, x: 4, y: 4, fill: true, fillOpacity: 1 }); var loanTwo = new L.Pattern({ width: 8, height: 8 }) loanTwo.addShape(circles); loanTwo.addTo(map); var loanThree = new L.StripePattern({ color: '#000' }); loanThree.addTo(map); var loanFour = new L.StripePattern({ color: '#000', weight: 6, spaceWeight: 2, angle: 45 }); loanFour.addTo(map); var loanSix = new L.StripePattern({ color: '#000', weight: 2, spaceWeight: 6, angle: 135 }); loanSix.addTo(map); function getLoanFillPattern(w) { return w == '2' ? loanTwo : w == '3' ? loanThree : w == '4' ? loanFour : w == '6' ? loanSix : null } // loan period overlay var loanPeriod = new L.TopoJSON(libraryServices, { style: function(feature){ return { weight: 3, color: "#fff", dashArray: "4", fillOpacity: 0.6, fillColor: "#bbb", fillPattern: getLoanFillPattern(feature.properties.standard_loan_weeks) } }, onEachFeature: function onEachFeature(feature, layer) { layer.on({ mouseover: e => highlightFeature(e), mouseout: e => resetHighlight(e, loanPeriod), click: zoomToFeature }) } }); // TODO: const branches = L.layerGroup([ L.geoCsv(branchesCsv, { firstLineTitles: true, fieldSeparator: ',', onEachFeature: function (feature, layer) { layer.bindPopup("" + feature.properties.town + "
" + feature.properties.address) }, pointToLayer: function (feature, latlng) { return L.circle(latlng, {color: "#FF3961", radius: 800}) // this is an 800m radius around the library } }), L.geoCsv(branchesCsv, { firstLineTitles: true, fieldSeparator: ',', pointToLayer: function (feature, latlng) { return L.circleMarker(latlng, {color: "#FF3961", radius: 2, fill: true}) } }) ]).addTo(map) // add this to the initial map on load // Indigenous Knowledge Centre locations from csv file var ikcs = L.layerGroup([ L.geoCsv(ikcCsv, { firstLineTitles: true, fieldSeparator: ',', onEachFeature: function (feature, layer) { layer.bindPopup("" + feature.properties.town + "
" + feature.properties.address) }, pointToLayer: function (feature, latlng) { return L.circle(latlng, {color: "#76DBA7", radius: 800}) } }), L.geoCsv(ikcCsv, { firstLineTitles: true, fieldSeparator: ',', pointToLayer: function (feature, latlng) { return L.circleMarker(latlng, {color: "#76DBA7", radius: 2, fill: true}) } }) ]).addTo(map) // add this to the initial map on load // mechanics institutes (Vic) & schools of arts (NSW) locations from csv file var mechsAndSoA = L.layerGroup([ L.geoCsv(mechanics, { firstLineTitles: true, fieldSeparator: ',', onEachFeature: function (feature, layer) { layer.bindPopup("" + feature.properties.town + "
" + feature.properties.address) }, pointToLayer: function (feature, latlng) { return L.circle(latlng, {color: "rgb(255,165,0)", radius: 800}) } }), L.geoCsv(mechanics, { firstLineTitles: true, fieldSeparator: ',', pointToLayer: function (feature, latlng) { return L.circleMarker(latlng, {color: "rgb(255,165,0)", radius: 2, fill: true}) } }) ]).addTo(map) // add this to the initial map on load // NSLA locations from csv file var otherLibs = L.layerGroup([ L.geoCsv(nslaBranches, { firstLineTitles: true, fieldSeparator: ',', onEachFeature: function (feature, layer) { layer.bindPopup("" + feature.properties.town + "
" + feature.properties.address) }, pointToLayer: function (feature, latlng) { return L.circle(latlng, {color: "#75f857", radius: 800}) } }), L.geoCsv(nslaBranches, { firstLineTitles: true, fieldSeparator: ',', pointToLayer: function (feature, latlng) { return L.circleMarker(latlng, {color: "#75f857", radius: 2, fill: true}) } }) ]).addTo(map) // add this to the initial map on load // ++++++++++++++ // control layers // ++++++++++++++ var baseMaps = { "Libraries" : baseMap, // "Languages" : baseLang, "Rules" : baseRules, } // change the overlay name depending on the mode. var modeButton = document.getElementById('mode-button'); var overlayMaps = { "Settler Knowledge Centres" : branches, "Indigenous Knowledge Centres": ikcs, "Worker Pacification Centres" : mechsAndSoA, "Imperial Knowledge Centres": otherLibs } function setGeneral() { overlayMaps = { "Settler Knowledge Centres" : branches, "Indigenous Knowledge Centres": ikcs, "Worker Pacification Centres" : mechsAndSoA, "Imperial Knowledge Centres": otherLibs } modeButton.innerText = "View in White Fragility mode"; } function setFragile() { overlayMaps = { "Public Libraries" : branches, "Indigenous Knowledge Centres": ikcs, "Mechanics Institutes" : mechsAndSoA, "National & State Libraries" : otherLibs }; modeButton.innerText = "View in General mode"; } if (sessionStorage.getItem('mapMode') === 'fragile') { setFragile() } else { setGeneral() } // switching mode between standard and fragile function switchMode() { if (sessionStorage.getItem('mapMode') === 'fragile') { sessionStorage.setItem('mapMode', 'general'); setGeneral() mapControl.remove(); infoBoxes.branches.remove() mapControl = L.control.layers(baseMaps, overlayMaps, {"collapsed": false}).addTo(map); infoBoxes.branches.addTo(map) } else { sessionStorage.setItem('mapMode', 'fragile'); setFragile() mapControl.remove(); infoBoxes.branches.remove() mapControl = L.control.layers(baseMaps, overlayMaps, {"collapsed": false}).addTo(map); infoBoxes.branches.addTo(map) } } modeButton.addEventListener('click', switchMode, false); // add control layers var mapControl = L.control.layers( baseMaps, overlayMaps, { "collapsed" : false } ).addTo(map); // scale L.control.scale().addTo(map); // info boxes var infoBoxes = { branches: L.control(), fines: L.control(), loanPeriod: L.control(), serviceInfo: L.control({position: 'topleft'}) } function getFinesColor(f) { return f == 'no' ? '#4dac26' : f == 'yes' ? '#d01c8b' : f == 'adults' ? '#f1b6da' : f == 'by_lga' ? '#abd9e9' : f == 'no_unconfirmed' ? '#b8e186' : '#bbb'; } // highlight feature on mouse hover function highlightFeature(e) { var layer = e.target; layer.setStyle({ weight: 6, color: '#FF3961', dashArray: "0", fillOpacity: 0 }); if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) { layer.bringToFront(); } infoBoxes.serviceInfo.addTo(map) infoBoxes.serviceInfo.update(layer.feature.properties); } // clear on mouseout function zoomToFeature(e) { map.fitBounds(e.target.getBounds()); } function resetHighlight(e, layer) { layer.resetStyle(e.target); infoBoxes.serviceInfo.remove() } // this is used to add general info when each layer is added function addLegend() { this._div = L.DomUtil.create('div', 'info') this.update(); return this._div; } // FINES LEGEND infoBoxes.fines.onAdd = addLegend; infoBoxes.fines.update = function (props) { this._div.innerHTML = `

Hover over an area for more information

Fine free
Fine free (unconfirmed)
Fine free for children
Fine policy varies
Fines for all users
Unknown (help me find out!)
` }; // BRANCH LOCATIONS LEGEND infoBoxes.branches.onAdd = addLegend; infoBoxes.branches.update = function (props) { this._div.innerHTML = `

Library Branches

Circles represent an 800 metre radius from the library location. This is the distance generally used by urban planners to represent "conceptually within walking distance" for most people.

`}; infoBoxes.branches.addTo(map) // add by default // STANDARD LOAN PERIOD LEGEND infoBoxes.loanPeriod.onAdd = addLegend; infoBoxes.loanPeriod.update = function (props) { this._div.innerHTML = `
2 weeks
3 weeks
4 weeks
6 weeks
Unknown (help me find out!)
` }; // FOCUSSED AREA INFOBOX infoBoxes.serviceInfo.onAdd = addLegend; infoBoxes.serviceInfo.update = function(props) { if (props) { this._div.innerHTML = `

${props.name}

` + '

' + ( props.fines === "no" ? "Fine free for overdue items" : props.fines == "no_unconfirmed" ? "Probably no overdue fines" : props.fines === "yes" ? "Overdue fines for all users" : props.fines == "adults" ? "No overdue fines for children" : props.fines == "by_lga" ? "Fine policy varies" : "No fines data" ) + '

' + ( !props.standard_loan_weeks || props.standard_loan_weeks == "?" ? `No loan period data` : `${props.standard_loan_weeks} week loans` + '

' )} } // remove info boxes & markers when relevant layer is removed map.on('overlayremove', l => { if (l.name == "Fines") { infoBoxes.fines.remove() } if (l.name == "Loan Period") { infoBoxes.loanPeriod.remove() } }) // add info boxes & markers when relevant layer is added map.on('overlayadd', l => { if (l.name == "Fines") { infoBoxes.fines.addTo(map) } if (l.name == "Loan Period") { infoBoxes.loanPeriod.addTo(map) loanPeriod.bringToBack() } }) // change overlays depending on base layer // we remove info boxes before adding them again where relevant // this is so we don't accidentally stack up multiple copies dependng on user // navigation journey map.on('baselayerchange', l => { for (let k in infoBoxes) { infoBoxes[k].remove() } if (l.name == "Rules") { mapControl.addOverlay(fines, "Fines") mapControl.addOverlay(loanPeriod, "Loan Period") loanPeriod.addTo(map) fines.addTo(map) for (let i in overlayMaps ) { mapControl.removeLayer(overlayMaps[i]) overlayMaps[i].remove() } modeButton.setAttribute('class', 'hidden'); // hide the mode button when it's not relevant } else { mapControl.removeLayer(fines) mapControl.removeLayer(loanPeriod) fines.remove() loanPeriod.remove() branches.addTo(map) for (let k in overlayMaps ) { mapControl.addOverlay(overlayMaps[k], k) } infoBoxes.branches.addTo(map); modeButton.setAttribute('class', 'visible'); } })