From dc8055c0a45abe252724543711ec14780a69a36b Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Tue, 8 Apr 2014 15:10:20 +0100 Subject: Move the indoor code to an external library --- .gitmodules | 3 + examples/full.html | 1 + examples/indoor.html | 1 + examples/zepler.html | 1 + resources/leaflet-indoor | 1 + src/leaflet-soton.css | 129 ------------ src/leaflet-soton.js | 498 ++++++++++++++--------------------------------- 7 files changed, 151 insertions(+), 483 deletions(-) create mode 160000 resources/leaflet-indoor diff --git a/.gitmodules b/.gitmodules index d6ad98a..662791d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "resources/leaflet-hash"] path = resources/leaflet-hash url = https://github.com/mlevans/leaflet-hash.git +[submodule "resources/leaflet-indoor"] + path = resources/leaflet-indoor + url = git@github.com:cbaines/leaflet-indoor.git diff --git a/examples/full.html b/examples/full.html index ed80cd5..cae1e87 100644 --- a/examples/full.html +++ b/examples/full.html @@ -27,6 +27,7 @@ + diff --git a/examples/indoor.html b/examples/indoor.html index f94c252..47de9a2 100644 --- a/examples/indoor.html +++ b/examples/indoor.html @@ -22,6 +22,7 @@
+ diff --git a/examples/zepler.html b/examples/zepler.html index 4caf762..0900992 100644 --- a/examples/zepler.html +++ b/examples/zepler.html @@ -24,6 +24,7 @@ + diff --git a/resources/leaflet-indoor b/resources/leaflet-indoor new file mode 160000 index 0000000..cb980fc --- /dev/null +++ b/resources/leaflet-indoor @@ -0,0 +1 @@ +Subproject commit cb980fc85685334ac88d6cc8d2224d219b80006b diff --git a/src/leaflet-soton.css b/src/leaflet-soton.css index a464a5f..af1ecda 100644 --- a/src/leaflet-soton.css +++ b/src/leaflet-soton.css @@ -56,135 +56,6 @@ } -.ls-btn { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - - *zoom: 1; - padding: 4px 10px 4px; - margin-bottom: 0; - font-size: 13px; - line-height: 18px; - color: #333333; - text-align: center; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - vertical-align: middle; - background-color: #f5f5f5; - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(top, #ffffff, #e6e6e6); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); - border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - border: 1px solid #cccccc; - border-bottom-color: #b3b3b3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - cursor: pointer; - *margin-left: .3em; -} -.ls-btn:hover, -.ls-btn:active, -.ls-btn.active, -.ls-btn.disabled, -.ls-btn[disabled] { - background-color: #e6e6e6; -} -.ls-btn:active, -.ls-btn.active { - background-color: #cccccc \9; -} -.ls-btn:first-child { - *margin-left: 0; -} -.ls-btn:hover { - color: #333333; - text-decoration: none; - background-color: #e6e6e6; - background-position: 0 -15px; - -webkit-transition: background-position 0.1s linear; - -moz-transition: background-position 0.1s linear; - -ms-transition: background-position 0.1s linear; - -o-transition: background-position 0.1s linear; - transition: background-position 0.1s linear; -} -.ls-btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.ls-btn.active, -.ls-btn:active { - background-image: none; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - background-color: #e6e6e6; - background-color: #d9d9d9 \9; - outline: 0; -} - -.ls-btn-group .ls-btn { - position: relative; - float: left; - margin-left: -1px; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.ls-btn-group .ls-btn:first-child { - margin-left: 0; - -webkit-border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; - border-top-left-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - border-bottom-left-radius: 4px; -} -.ls-btn-group .ls-btn:last-child, -.ls-btn-group .dropdown-toggle { - -webkit-border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; - border-bottom-right-radius: 4px; -} -.ls-btn-group .ls-btn.large:first-child { - margin-left: 0; - -webkit-border-top-left-radius: 6px; - -moz-border-radius-topleft: 6px; - border-top-left-radius: 6px; - -webkit-border-bottom-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - border-bottom-left-radius: 6px; -} -.ls-btn-group .ls-btn.large:last-child, -.ls-btn-group .large.dropdown-toggle { - -webkit-border-top-right-radius: 6px; - -moz-border-radius-topright: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - -moz-border-radius-bottomright: 6px; - border-bottom-right-radius: 6px; -} -.ls-btn-group .ls-btn:hover, -.ls-btn-group .ls-btn:focus, -.ls-btn-group .ls-btn:active, -.ls-btn-group .ls-btn.active { - z-index: 2; -} - .ls-nav { margin-left: 0; padding: 0; diff --git a/src/leaflet-soton.js b/src/leaflet-soton.js index f6ce069..7f84154 100644 --- a/src/leaflet-soton.js +++ b/src/leaflet-soton.js @@ -418,179 +418,182 @@ SELECT * WHERE {\ LS.getWorkstationData(function(workstationData) { - // Adding .features means leaflet will - // ignore those without a geometry - map.indoorLayer = L.indoorLayer(data.buildingParts.features, { - level: map._startLevel, - style: function(feature) { - var fill = 'white'; - if (feature.properties.buildingpart === 'corridor') { - fill = '#169EC6'; - } else if (feature.properties.buildingpart === 'verticalpassage') { - fill = '#0A485B'; - } - - return { - fillColor: fill, - weight: 1, - color: '#666', - fillOpacity: 1 - }; - }, - markerForFeature: function(part) { - if (part.properties.buildingpart === "room") { - - var iconCoords = part.properties.center; - - if (part.properties.name === "The Bridge") { - return L.marker(iconCoords, {icon: icons.theBridge}); - } else if (part.properties.name === "SUSU Shop") { - return L.marker(iconCoords, {icon: icons.theSUSUShop}); - } else if (part.properties.name === "The Stag's") { - return L.marker(iconCoords, {icon: icons.theStags}); - } else if (part.properties.name === "SUSU Cafe") { - return L.marker(iconCoords, {icon: icons.theSUSUCafe}); + if (options.indoor) { + // Adding .features means leaflet will + // ignore those without a geometry + map.indoorLayer = L.indoor(data.buildingParts.features, { + level: map._startLevel, + style: function(feature) { + var fill = 'white'; + if (feature.properties.buildingpart === 'corridor') { + fill = '#169EC6'; + } else if (feature.properties.buildingpart === 'verticalpassage') { + fill = '#0A485B'; } - var partWorkstation = null; + return { + fillColor: fill, + weight: 1, + color: '#666', + fillOpacity: 1 + }; + }, + markerForFeature: function(part) { + if (part.properties.buildingpart === "room") { + + var iconCoords = part.properties.center; + + if (part.properties.name === "The Bridge") { + return L.marker(iconCoords, {icon: icons.theBridge}); + } else if (part.properties.name === "SUSU Shop") { + return L.marker(iconCoords, {icon: icons.theSUSUShop}); + } else if (part.properties.name === "The Stag's") { + return L.marker(iconCoords, {icon: icons.theStags}); + } else if (part.properties.name === "SUSU Cafe") { + return L.marker(iconCoords, {icon: icons.theSUSUCafe}); + } - if ('contents' in part.properties) { - part.properties.contents.forEach(function(feature) { - if (feature.subject === "http://id.southampton.ac.uk/point-of-interest-category/iSolutions-Workstations") { - partWorkstation = feature; - } - }); - } + var partWorkstation = null; - if (part.properties.amenity === "toilets") { - if ("male" in part.properties) { - return L.marker(iconCoords, {icon: icons.toiletsMale}); - } else if ("female" in part.properties) { - return L.marker(iconCoords, {icon: icons.toiletsFemale}); - } else if ("unisex" in part.properties) { - return L.marker(iconCoords, {icon: icons.toiletsUnisex}); - } // TODO: Disabled - } + if ('contents' in part.properties) { + part.properties.contents.forEach(function(feature) { + if (feature.subject === "http://id.southampton.ac.uk/point-of-interest-category/iSolutions-Workstations") { + partWorkstation = feature; + } + }); + } - var content; + if (part.properties.amenity === "toilets") { + if ("male" in part.properties) { + return L.marker(iconCoords, {icon: icons.toiletsMale}); + } else if ("female" in part.properties) { + return L.marker(iconCoords, {icon: icons.toiletsFemale}); + } else if ("unisex" in part.properties) { + return L.marker(iconCoords, {icon: icons.toiletsUnisex}); + } // TODO: Disabled + } - if ("name" in part.properties && "ref" in part.properties) { - content = part.properties.name + " (" + part.properties.ref + ")"; - } else if ("ref" in part.properties) { - content = "Room " + part.properties.ref; - } else if ("name" in part.properties) { - content = part.properties.name; - } else { - return; - } + var content; - if (partWorkstation) { - if (partWorkstation.feature in workstationData) { - var state = workstationData[partWorkstation.feature]; + if ("name" in part.properties && "ref" in part.properties) { + content = part.properties.name + " (" + part.properties.ref + ")"; + } else if ("ref" in part.properties) { + content = "Room " + part.properties.ref; + } else if ("name" in part.properties) { + content = part.properties.name; + } else { + return; + } - var closed = (state.status.indexOf("closed") !== -1) + if (partWorkstation) { + if (partWorkstation.feature in workstationData) { + var state = workstationData[partWorkstation.feature]; - var image; - var workstationIcon; + var closed = (state.status.indexOf("closed") !== -1) - if (!closed) { - image = 'workstation-group.png'; - workstationIcon = '
'; - } else { - image = 'workstation-closed.png'; - workstationIcon = '
'; - } + var image; + var workstationIcon; - if (!closed) { - workstationIcon += '
'; + if (!closed) { + image = 'workstation-group.png'; + workstationIcon = '
'; + } else { + image = 'workstation-closed.png'; + workstationIcon = '
'; + } - var freeSeats = state.free_seats; - workstationIcon += freeSeats + "
"; - } + if (!closed) { + workstationIcon += '
'; - workstationIcon += '
'; + var freeSeats = state.free_seats; + workstationIcon += freeSeats + "
"; + } - content = workstationIcon + content; - } else { - var workstationIcon = '
'; + workstationIcon += '
'; + + content = workstationIcon + content; + } else { + var workstationIcon = '
'; - content = workstationIcon + content; + content = workstationIcon + content; + } } - } - var myIcon = L.divIcon({ - className: 'ls-room-marker', - html: content, - iconSize: new L.Point(100, 30), - iconAnchor: new L.Point(50, 15) - }); + var myIcon = L.divIcon({ + className: 'ls-room-marker', + html: content, + iconSize: new L.Point(100, 30), + iconAnchor: new L.Point(50, 15) + }); - var marker = L.marker(iconCoords, {icon: myIcon}); + var marker = L.marker(iconCoords, {icon: myIcon}); - return marker; - } - }, - onEachFeature: function(feature, layer) { - if (feature.properties.buildingpart === "corridor") { - return; // No popup for corridors yet - } + return marker; + } + }, + onEachFeature: function(feature, layer) { + if (feature.properties.buildingpart === "corridor") { + return; // No popup for corridors yet + } - layer.on('click', function(e) { - var content; - var popupOptions = {}; + layer.on('click', function(e) { + var content; + var popupOptions = {}; - // When the feature is clicked on - if ("buildingpart" in feature.properties) { - if (feature.properties.buildingpart === "room") { - content = roomPopupTemplate(feature.properties); - } else if (feature.properties.buildingpart === "verticalpassage") { - content = verticalPassagePopupTemplate(feature.properties); + // When the feature is clicked on + if ("buildingpart" in feature.properties) { + if (feature.properties.buildingpart === "room") { + content = roomPopupTemplate(feature.properties); + } else if (feature.properties.buildingpart === "verticalpassage") { + content = verticalPassagePopupTemplate(feature.properties); + } + } else { // Assume that it is a printer + // TODO: Use different icons where appropriate + popupOptions.offset = icons.vendingHotDrinks.options.popupAnchor; + + if ('vending' in feature.properties) { + content = vendingPopupTemplate(feature.properties); + } else { + content = printerPopupTemplate(feature.properties); + } } - } else { // Assume that it is a printer - // TODO: Use different icons where appropriate - popupOptions.offset = icons.vendingHotDrinks.options.popupAnchor; - if ('vending' in feature.properties) { - content = vendingPopupTemplate(feature.properties); + showPopup(map, content, e.latlng, popupOptions); + }); + }, + pointToLayer: function (feature, latlng) { + var icon; + + if ('vending' in feature.properties) { + if (feature.properties.vending === 'drinks') { + icon = icons.vendingHotDrinks; + } else if (feature.properties.vending === 'sweets') { + icon = icons.vendingSweets; } else { - content = printerPopupTemplate(feature.properties); + console.warn("Unrecognired vending " + feature.properties.vending); } - } - - showPopup(map, content, e.latlng, popupOptions); - }); - }, - pointToLayer: function (feature, latlng) { - var icon; - - if ('vending' in feature.properties) { - if (feature.properties.vending === 'drinks') { - icon = icons.vendingHotDrinks; - } else if (feature.properties.vending === 'sweets') { - icon = icons.vendingSweets; } else { - console.warn("Unrecognired vending " + feature.properties.vending); + icon = icons.printer; } - } else { - icon = icons.printer; + + return L.marker(latlng, {icon: icon}); } + }); - return L.marker(latlng, {icon: icon}); - } - }); + map.indoorLayer.addData(data.buildingFeatures); - map.indoorLayer.addData(data.buildingFeatures); + map.levelControl = L.Control.level({ + levels: map.indoorLayer.getLevels(), + level: map._startLevel + }); - map.levelControl = L.Control.level({ - levels: map.indoorLayer.getLevels(), - level: map._startLevel - }); + map.levelControl.addEventListener("levelchange", map.indoorLayer.setLevel, map.indoorLayer); - map.levelControl.addEventListener("levelchange", map.indoorLayer.setLevel, map.indoorLayer); + map.levelControl.on("levelchange", function(e) { + map.fireEvent("levelchange", e); + }); - map.levelControl.on("levelchange", function(e) { - map.fireEvent("levelchange", e); - }); + } var workstationMarkerLayer; if (options.workstations) { @@ -1642,219 +1645,6 @@ SELECT * WHERE {\ } })(); -L.Control.Level = L.Control.extend({ - includes: L.Mixin.Events, - - options: { - position: 'bottomright', - parseLevel: function(level) { - return parseInt(level, 10); - } - }, - - initialize: function(options) { - L.setOptions(this, options); - - this._map = null; - this._buttons = {}; - this._listeners = []; - this._level = options.level; - - this.addEventListener("levelchange", this._levelChange, this); - }, - onAdd: function(map) { - var div = L.DomUtil.create('div', 'ls-levelselector'); - - var btnGroup = L.DomUtil.create('div', 'ls-btn-group', div); - - var buttons = this._buttons; - var activeLevel = this._level; - var self = this; - - this.options.levels.forEach(function(level) { - var cls = 'ls-btn'; - - var levelNum = self.options.parseLevel(level); - - if (level === activeLevel || levelNum === activeLevel) - cls += ' active'; - - var levelBtn = L.DomUtil.create('button', cls, btnGroup); - - levelBtn.appendChild(levelBtn.ownerDocument.createTextNode(level)); - - levelBtn.onclick = function() { - self.setLevel(level); - }; - - buttons[level] = levelBtn; - }); - - return div; - }, - _levelChange: function(e) { - // Probably won't work in some browsers, see - // https://developer.mozilla.org/en-US/docs/Web/API/element.classList - - if (this._map !== null) { - this._buttons[e.oldLevel].classList.remove('active'); - this._buttons[e.newLevel].classList.add('active'); - } - }, - setLevel: function(level) { - - if (level === this._level) - return; - - var oldLevel = this._level; - this._level = level; - - this.fireEvent("levelchange", { - oldLevel: oldLevel, - newLevel: level - }); - }, - getLevel: function() { - return this._level; - } -}); - -L.Control.level = function (options) { - return new L.Control.Level(options); -}; - -/** - * A layer that will display indoor data - * - * addData takes a GeoJSON feature collection, each feature must have a level - * property that indicates the level. If the level is a string, some function - * will be used to rank the levels. - * - * getLevels can be called to get the array of levels that are present. - * - * - */ - -L.IndoorLayer = L.Class.extend({ - - initialize: function(data, options) { - L.setOptions(this, options); - - var onEachFeature = options.onEachFeature; - var layers = this._layers = {}; - this._map = null; - if ("level" in options) { - this._level = options.level; - } else { - this._level = null; - } - - this.options.onEachFeature = function(feature, layer) { - - onEachFeature(feature, layer); - - var marker = options.markerForFeature(feature); - if (typeof(marker) !== 'undefined') { - marker.on('click', function(e) { - layer.fire('click', e); - }); - - layers[feature.properties.level].addLayer(marker); - } - }; - - this.addData(data); - }, - addTo: function (map) { - map.addLayer(this); - return this; - }, - onAdd: function (map) { - this._map = map; - - if (this._level === null) { - var levels = this.getLevels(); - - if (levels.length !== 0) { - this._level = levels[0]; - } - } - - this._map.addLayer(this._layers[this._level]); - }, - onRemove: function (map) { - this._map.removeLayer(this._layers[this._level]); - this._map = null; - }, - addData: function(data) { - var layers = this._layers; - - var options = this.options; - - var features = L.Util.isArray(data) ? data : data.features; - - features.forEach(function (part) { - var level = part.properties.level; - var layer; - - if (typeof level === 'undefined') - return; - - if (!("geometry" in part)) { - return; - } - - if (L.Util.isArray(level)) { - level.forEach(function(level) { - if (level in layers) { - layer = layers[level]; - } else { - layer = layers[level] = L.geoJson({ type: "FeatureCollection", features: [] }, options); - } - - layer.addData(part); - }); - } else { - if (level in layers) { - layer = layers[level]; - } else { - layer = layers[level] = L.geoJson({ type: "FeatureCollection", features: [] }, options); - } - - layer.addData(part); - } - }); - }, - getLevels: function() { - return Object.keys(this._layers); - }, - getLevel: function() { - return this._level; - }, - setLevel: function(level) { - if (typeof(level) === 'object') { - level = level.newLevel; - } - - if (this._level === level) - return; - - var oldLayer = this._layers[this._level]; - var layer = this._layers[level]; - - if (this._map !== null) { - this._map.removeLayer(oldLayer); - this._map.addLayer(layer); - } - - this._level = level; - } -}); - -L.indoorLayer = function(data, options) { - return new L.IndoorLayer(data, options); -}; - L.SelectiveVisibilityLayer = L.Class.extend({ _layers: {}, @@ -1901,7 +1691,7 @@ L.SelectiveVisibilityLayer = L.Class.extend({ }); L.SelectiveVisibilityLayer = function(data, options) { - return new L.IndoorLayer(data, options); + return new L.Indoor(data, options); }; // forEach compatability if (!Array.prototype.forEach) { -- cgit v1.2.3