diff --git a/README.md b/README.md index fe71eb2..e8453c8 100644 --- a/README.md +++ b/README.md @@ -114,8 +114,8 @@ Each of these files should define a single array containing zero or more "marker ### FAQs -- **How were the community and census tract Fusion tables created?** The City of Chicago Data Portal (HERE) provides this information in KML format (keyhole markup language, an XML schema used to represent geo-spacial data). Unfortunately, KML isn't particularly friendly for applications like ours. The metadata associated with each area (for example, the neighborhood name or census tract id) is stored in an HTML fragment that CDATA'd in the XML. In order to create a more useable representation, we wrote a small Groovy script to export the useful bits into CSV format, which was then uploaded to Fusion. +- How were the community and census tract Fusion tables created? The City of Chicago Data Portal (HERE) provides this information in KML format (keyhole markup language, an XML schema used to represent geo-spacial data). Unfortunately, KML isn't particularly friendly for applications like ours. The metadata associated with each area (for example, the neighborhood name or census tract id) is stored in an HTML fragment that CDATA'd in the XML. In order to create a more useable representation, we wrote a small Groovy script to export the useful bits into CSV format, which was then uploaded to Fusion. -- **Why is the boundary data in a Fusion Table?** It shouldn't be. There's no good reason for this other than legacy: When we started development the notion was that we'd use Fusion Tables as our primary database. We eventually migrated the other data away from Fusion, but haven't gotten around to moving the polygons out. +- Why is the boundary data in a Fusion Table? It shouldn't be. There's no good reason for this other than legacy: When we started development the notion was that we'd use Fusion Tables as our primary database. We eventually migrated the other data away from Fusion, but haven't gotten around to moving the polygons out. -- **How are the polygons shaded?** +- How are the polygons shaded? diff --git a/public/index.html b/public/index.html index a0cafc4..c855220 100644 --- a/public/index.html +++ b/public/index.html @@ -74,7 +74,7 @@

For calendar year

-
diff --git a/public/js/index.js b/public/js/index.js index e19d45f..43c99c8 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1,5 +1,7 @@ (function (index, $) { + var multiselectData = undefined; + /* Initialize the area/geography type radio selection (census tracts vs. neighborhoods) */ function initGeoRadio() { @@ -26,6 +28,7 @@ // Fetch license list from server and update the multiselect accordingly json.fetch("licenses.json", function (data) { + multiselectData = data; $("#business-multiselect").multiselect('dataprovider', data); }); @@ -83,19 +86,47 @@ } function getAreaType() { - return $('#neighborhood-radio').is(":checked") ? "neighborhood" : "census"; + return $('#neighborhood-radio').is(":checked") ? "commareas" : "tracts"; } - + + function updateSliderRange () { + var selectedBusiness = getSelectedBusiness(); + var min = 0; + var max = 0; + + multiselectData.forEach(function (record) { + if (record.value == selectedBusiness) { + min = record["min-year"]; + max = record["max-year"]; + } + }); + + var selectedYear = $("#year-slider").slider("getValue"); + + $("#year-slider").slider("setAttribute", "min", min); + $("#year-slider").slider("setAttribute", "max", max); + + if (selectedYear > max) + $("#year-slider").slider("setValue", max); + + if (selectedYear < min) + $("#year-slider").slider("setValue", min); + + $("#year-value").text($("#year-slider").slider("getValue")); + } + /* * Invoked when a user makes a UI selection that affects map rendering */ index.update = function () { - var dataset = getAreaType() + "-" + getSelectedBusiness() + "-" + getSelectedYear() + ".json"; - console.log(dataset); + updateSliderRange(); + + var dataset = getAreaType() + "/" + getSelectedBusiness() + "-" + getSelectedYear() + ".json"; + // Update polygons and shading // TODO: Cache this result and only fetch/update when required - if (getAreaType() == "census") { + if (getAreaType() == "tracts") { maps.showCensusTracts(); maps.setCensusData(dataset); } else { diff --git a/public/js/maps.js b/public/js/maps.js index 4f2fc31..88f6cce 100644 --- a/public/js/maps.js +++ b/public/js/maps.js @@ -15,7 +15,7 @@ var censusData = []; // current census desertification data // When true, polygons are shaded relative only to other visible polygons - var relativeShadingEnabled = false; + var relativeShadingEnabled = false; var map = null; // Google map object @@ -170,7 +170,7 @@ } /* Filter a given set of polygons returning an array containing only those currently visible - * on the map. + * on the map. */ function getVisiblePolygons(polys) { var visiblePolys = []; @@ -197,10 +197,9 @@ function getMaxIndex(polys, data) { var max = 0; - polys.forEach(function (thisPoly) { - if (data[thisPoly.areaId] && data[thisPoly.areaId].ACCESS_INDEX > max) { - max = data[thisPoly.areaId].ACCESS_INDEX; - }; + polys.forEach(function (poly) { + var index = getIndexForArea(poly.areaId, data); + if (index > max) max = index; }); return max; @@ -208,10 +207,9 @@ function getMinIndex(polys, data) { var min = Number.MAX_VALUE; - polys.forEach(function (thisPoly) { - if (data[thisPoly.areaId] && data[thisPoly.areaId].ACCESS_INDEX < min) { - min = data[thisPoly.areaId].ACCESS_INDEX; - }; + polys.forEach(function (poly) { + var index = getIndexForArea(poly.areaId, data); + if (index < min) min = index; }); return min; @@ -220,42 +218,67 @@ /* Re-shade visible polygons (may change opacity on when relative shading is enabled). */ function refreshPolygonShading() { - + var activePolygons = (activeGeography == "census") ? censusPolys : communityPolys; var activeDataset = (activeGeography == "census") ? censusData : communityData; - + if (relativeShadingEnabled) { + + // Blank polygons that are not visible + activePolygons.forEach(function (thisPoly) { + thisPoly.setOptions({ + fillOpacity: 0 + }); + }); + activePolygons = getVisiblePolygons(activePolygons); } shadePolygons(activePolygons, activeDataset); } + function getIndexForArea(areaId, data) { + var areaProperty = (activeGeography == "census") ? "TRACT" : "COMMUNITY_AREA"; + var index = undefined; + + data.forEach(function (record) { + if (record[areaProperty] == areaId) { + index = record.ACCESS1; + } + }); + + return index; + } + function shadePolygons(polys, data) { // Get min and max access index values for polygons var max = getMaxIndex(polys, data); var min = getMinIndex(polys, data); - // Blank polygons that are not visible polys.forEach(function (thisPoly) { - thisPoly.setOptions({ - fillOpacity: 0 - }); - }); + var index = getIndexForArea(thisPoly.areaId, data); - // Shade visible polys relative to others - getVisiblePolygons(polys).forEach(function (thisPoly) { - var index = data[thisPoly.areaId] && data[thisPoly.areaId].ACCESS_INDEX; - thisPoly.setOptions({ - fillOpacity: getOpacityBucket((index - min) / (max - min)) - }); + // No data available--color polygon in red + if (index == undefined) { + thisPoly.setOptions({ + fillOpacity: 0.4, + fillColor: "#ff0000" + }); + } + + // Shade polygon based on bucket value + else { + thisPoly.setOptions({ + fillOpacity: getOpacityBucket((index - min) / (max - min)) + }); + } }); } function getOpacityBucket(value) { var bucketCount = 5; - return Math.round(value / (1 / bucketCount)) * (1 / bucketCount); + return 1 - Math.round(value / (1 / bucketCount)) * (1 / bucketCount); } function renderMarkers(places) { @@ -339,25 +362,17 @@ maps.setRelativePolygonShading = function (isRelativeShadingEnabled) { relativeShadingEnabled = isRelativeShadingEnabled; + refreshPolygonShading(); }; maps.setCommunityData = function (datafile) { communityData = {}; - // Generate fake data - communityPolys.forEach(function (thisPoly) { - communityData[thisPoly.areaId] = { - "ACCESS_INDEX": Math.random() - }; + json.fetch(datafile, function (data) { + communityData = data; + shadePolygons(communityPolys, data); }); - shadePolygons(communityPolys, communityData); - - // TODO: Uncomment to fetch real data - // json.fetch(datafile, function (data) { - // communityData = data; - // shadePolygons(communityPolys, data); - // }); activeGeography = "communities"; }; @@ -365,19 +380,10 @@ maps.setCensusData = function (datafile) { censusData = {}; - // Generate fake data - censusPolys.forEach(function (thisPoly) { - censusData[thisPoly.areaId] = { - "ACCESS_INDEX": Math.random() - }; + json.fetch(datafile, function (data) { + censusData = data; + shadePolygons(censusPolys, data); }); - shadePolygons(censusPolys, censusData); - - // TODO: Uncomment to fetch real data - // json.fetch(datafile, function (data) { - // censusData = data; - // shadePolygons(censusPolys, data); - // }); activeGeography = "census"; }; diff --git a/public/json/licenses.json b/public/json/licenses.json index d30b432..3d96e04 100644 --- a/public/json/licenses.json +++ b/public/json/licenses.json @@ -1,80 +1,799 @@ [{ - "title": "Animal Care", - "label": "Animal Care", - "value": "animal-care" + "title": "Accessory Garage", + "label": "Accessory Garage", + "value": "accessory-garage", + "min-year": 2002, + "max-year": 2015 }, { - "title": "Bike Messenger", - "label": "Bike Messenger", - "value": "bicycle-messenger" + "title": "Affiliation", + "label": "Affiliation", + "value": "affiliation", + "min-year": 2012, + "max-year": 2014 + }, + { + "title": "Animal Care Facility", + "label": "Animal Care Facility", + "value": "animal-care-facility", + "min-year": 2007, + "max-year": 2015 + }, + { + "title": "Animal Exhibition", + "label": "Animal Exhibition", + "value": "animal-exhibition", + "min-year": 2005, + "max-year": 2014 + }, + { + "title": "Assisted Living Shared Housing", + "label": "Assisted Living Shared Housing", + "value": "assisted-livingshared-housing-establishment", + "min-year": 2009, + "max-year": 2013 + }, + { + "title": "Auctioneer", + "label": "Auctioneer", + "value": "auctioneer", + "min-year": 2004, + "max-year": 2013 + }, + { + "title": "Automatic Amusement Device Operator", + "label": "Automatic Amusement Device Operator", + "value": "automatic-amusement-device-operator", + "min-year": 2005, + "max-year": 2013 + }, + { + "title": "Bed and Breakfast", + "label": "Bed and Breakfast", + "value": "bed-and-breakfast-establishment", + "min-year": 2005, + "max-year": 2014 + + }, + { + "title": "Bike Messenger Service", + "label": "Bike Messenger Service", + "value": "bicycle-messenger-service", + "min-year": 2008, + "max-year": 2014 + }, + { + "title": "Board-up Work", + "label": "Board-up Work", + "value": "board-up-work", + "min-year": 2005, + "max-year": 2013 + }, + { + "title": "Body Piercing", + "label": "Body Piercing", + "value": "body-piercing", + "min-year": 2005, + "max-year": 2014 + }, + { + "title": "Broker", + "label": "Broker", + "value": "broker", + "min-year": 1995, + "max-year": 2013 + }, + { + "title": "Caterers Liquor License", + "label": "Caterers Liquor License", + "value": "caterers-liquor-license", + "min-year": 2005, + "max-year": 2015 + }, + { + "title": "Childrens Activities Facilities", + "label": "Childrens Activities Facilities", + "value": "childrens-activities-facilities", + "min-year": 2010, + "max-year": 2015 + }, + { + "title": "Childrens Services Facility", + "label": "Childrens Services Facility", + "value": "childrens-services-facility-license", + "min-year": 2010, + "max-year": 2015 + }, + { + "title": "Consumption on Premises - Incidental Activity", + "label": "Consumption on Premises - Incidental Activity", + "value": "consumption-on-premises---incidental-activity", + "min-year": 1998, + "max-year": 2015 + }, + { + "title": "Day Care Center (ages 2-6)", + "label": "Day Care Center (ages 2-6)", + "value": "day-care-center-2---6-years", + "min-year": 2004, + "max-year": 2013 + }, + { + "title": "Day Care Center (ages 0-6)", + "label": "Day Care Center (ages 0-6)", + "value": "day-care-center-under-2-and-2---6-years", + "min-year": 2005, + "max-year": 2014 + }, + { + "title": "Day Care Center (ages 0-2)", + "label": "Day Care Center (ages 0-2)", + "value": "day-care-center-under-2-years", + "min-year": 2004, + "max-year": 2013 + }, + { + "title": "Day Labor Agency", + "label": "Day Labor Agency", + "value": "day-labor-agency", + "min-year": 2005, + "max-year": 2014 + }, + { + "title": "Electronic Equipment Repair", + "label": "Electronic Equipment Repair", + "value": "electronic-equipment-repair", + "min-year": 1997, + "max-year": 2014 + }, + { + "title": "Emerging Business", + "label": "Emerging Business", + "value": "emerging-business", + "min-year": 2014, + "max-year": 2015 + }, + { + "title": "Expediter (Class A)", + "label": "Expediter (Class A)", + "value": "expediter---class-a", + "min-year": 2008, + "max-year": 2013 + }, + { + "title": "Expediter (Class B)", + "label": "Expediter (Class B)", + "value": "expediter---class-b", + "min-year": 2009, + "max-year": 2013 + }, + { + "title": "Expediter Employee (Class B)", + "label": "Expediter Employee (Class B)", + "value": "expediter---class-b-employee", + "min-year": 2009, + "max-year": 2013 + }, + { + "title": "Explosives", + "label": "Explosives", + "value": "explosives", + "min-year": 2006, + "max-year": 2014 + }, + { + "title": "Explosives (Certificate of Fitness)", + "label": "Explosives (Certificate of Fitness)", + "value": "explosives-certificate-of-fitness", + "min-year": 2004, + "max-year": 2014 + }, + { + "title": "Filling / Gas Station", + "label": "Filling / Gas Station", + "value": "filling-station", + "min-year": 1996, + "max-year": 2015 + }, + { + "title": "Shared Kitchen (Supplemental)", + "label": "Shared Kitchen (Supplemental)", + "value": "food---shared-kitchen---supplemental", + "min-year": 2011, + "max-year": 2015 + }, + { + "title": "Shared Kitchen", + "label": "Shared Kitchen", + "value": "food---shared-kitchen", + "min-year": 2011, + "max-year": 2014 + }, + { + "title": "Shared Kitchen (Long-Term User)", + "label": "Shared Kitchen (Long-Term User)", + "value": "food---shared-kitchen-long-term-user", + "min-year": 2011, + "max-year": 2015 + }, + { + "title": "Shared Kitchen (Short-Term User)", + "label": "Shared Kitchen (Short-Term User)", + "value": "food---shared-kitchen-short-term-user", + "min-year": 2011, + "max-year": 2014 }, { "title": "Grocery", "label": "Grocery", - "value": "grocery" + "value": "grocery", + "min-year": 2006, + "max-year": 2015 + }, + { + "title": "Grooming Facility", + "label": "Grooming Facility", + "value": "grooming-facility", + "min-year": 2007, + "max-year": 2013 + }, + { + "title": "Guard Dog Service", + "label": "Guard Dog Service", + "value": "guard-dog-service", + "min-year": 2007, + "max-year": 2008 + }, + { + "title": "Hazardous Materials", + "label": "Hazardous Materials", + "value": "hazardous-materials", + "min-year": 1997, + "max-year": 2015 + }, + { + "title": "Heliport", + "label": "Heliport", + "value": "heliports", + "min-year": 2006, + "max-year": 2015 + }, + { + "title": "Home Occupation", + "label": "Home Occupation", + "value": "home-occupation", + "min-year": 1997, + "max-year": 2014 + }, + { + "title": "Home Repair", + "label": "Home Repair", + "value": "home-repair", + "min-year": 1996, + "max-year": 2014 + }, + { + "title": "Hospital", + "label": "Hospital", + "value": "hospital", + "min-year": 2006, + "max-year": 2014 + }, + { + "title": "Hotel", + "label": "Hotel", + "value": "hotel", + "min-year": 2003, + "max-year": 2014 + }, + { + "title": "Humane Society", + "label": "Humane Society", + "value": "humane-society", + "min-year": 2006, + "max-year": 2013 + }, + { + "title": "Itinerant Merchant", + "label": "Itinerant Merchant", + "value": "itinerant-merchant", + "min-year": 2013, + "max-year": 2013 + }, + { + "title": "Itinerant Merchant (Class I)", + "label": "Itinerant Merchant (Class I)", + "value": "itinerant-merchant-class-i", + "min-year": 2007, + "max-year": 2011 + }, + { + "title": "Itinerant Merchant (Class II)", + "label": "Itinerant Merchant (Class II)", + "value": "itinerant-merchant-class-ii", + "min-year": 2008, + "max-year": 2012 + }, + { + "title": "Junk Peddler", + "label": "Junk Peddler", + "value": "junk-peddler", + "min-year": 1996, + "max-year": 2014 + }, + { + "title": "Kennels and Catteries", + "label": "Kennels and Catteries", + "value": "kennels-and-catteries", + "min-year": 2005, + "max-year": 2008 + }, + { + "title": "Laboratories", + "label": "Laboratories", + "value": "laboratories", + "min-year": 1998, + "max-year": 2013 + }, + { + "title": "Late Hour", + "label": "Late Hour", + "value": "late-hour", + "min-year": 2005, + "max-year": 2015 + }, + { + "title": "Laundry (Late Hour)", + "label": "Laundry (Late Hour)", + "value": "laundry-late-hour", + "min-year": 2002, + "max-year": 2013 + }, + { + "title": "License Broker", + "label": "License Broker", + "value": "license-broker", + "min-year": 2011, + "max-year": 2014 + }, + { + "title": "License Manager", + "label": "License Manager", + "value": "license-manager", + "min-year": 2012, + "max-year": 2014 }, { - "title": "Manufacturing", - "label": "Manufacturing", - "value": "manufacturing" + "title": "Limited Business License", + "label": "Limited Business License", + "value": "limited-business-license", + "min-year": 1995, + "max-year": 2015 + }, + { + "title": "Liquor Airport Pushcart", + "label": "Liquor Airport Pushcart", + "value": "liquor-airport-pushcart-license", + "min-year": 2012, + "max-year": 2015 + }, + { + "title": "Long-Term Care Facility", + "label": "Long-Term Care Facility", + "value": "long-term-care-facility", + "min-year": 2005, + "max-year": 2014 + }, + { + "title": "Manufacturing Establishment", + "label": "Manufacturing Establishment", + "value": "manufacturing-establishments", + "min-year": 1996, + "max-year": 2015 }, { "title": "Massage", "label": "Massage", - "value": "massage" + "value": "massage-establishment", + "min-year": 1995, + "max-year": 2015 + }, + { + "title": "Mobile Food Dispenser", + "label": "Mobile Food Dispenser", + "value": "mobile-food-dispenser", + "min-year": 1997, + "max-year": 2013 + }, + { + "title": "Mobile Food License", + "label": "Mobile Food License", + "value": "mobile-food-license", + "min-year": 2012, + "max-year": 2015 + }, + { + "title": "Mobile Frozen Desserts Dispenser (Non-Motorized)", + "label": "Mobile Frozen Desserts Dispenser (Non-Motorized)", + "value": "mobile-frozen-desserts-dispenser---non-motorized", + "min-year": 2006, + "max-year": 2013 + }, + { + "title": "Motor Vehicle Repair (Engine Only, Class II)", + "label": "Motor Vehicle Repair (Engine Only, Class II)", + "value": "motor-vehicle-repair--engine-only-class-ii", + "min-year": 1995, + "max-year": 2014 + }, + { + "title": "Motor Vehicle Repair (Engine & Body, Class III)", + "label": "Motor Vehicle Repair (Engine & Body, Class III)", + "value": "motor-vehicle-repair-enginebodyclass-iii", + "min-year": 1995, + "max-year": 2015 + }, + { + "title": "Motor Vehicle Repair (Specialty, Class I)", + "label": "Motor Vehicle Repair (Specialty, Class I)", + "value": "motor-vehicle-repair-specialtyclass-i", + "min-year": 1995, + "max-year": 2015 + }, + { + "title": "Motor Vehicle Services", + "label": "Motor Vehicle Services", + "value": "motor-vehicle-services-license", + "min-year": 2012, + "max-year": 2015 + }, + { + "title": "Music and Dance", + "label": "Music and Dance", + "value": "music-and-dance", + "min-year": 2005, + "max-year": 2015 + }, + { + "title": "Night Care Privilege", + "label": "Night Care Privilege", + "value": "night-care-privilege", + "min-year": 2005, + "max-year": 2013 + }, + { + "title": "Not-for-Profit Club", + "label": "Not-for-Profit Club", + "value": "not-for-profit-club", + "min-year": 2004, + "max-year": 2015 }, { - "title": "Not-for-Profit", - "label": "Not-for-Profit", - "value": "not-for-profit-club" + "title": "Outdoor Patio", + "label": "Outdoor Patio", + "value": "outdoor-patio", + "min-year": 1998, + "max-year": 2015 }, { - "title": "Parking Garage", - "label": "Parking Garage", - "value": "public-garage" + "title": "Package Goods", + "label": "Package Goods", + "value": "package-goods", + "min-year": 2005, + "max-year": 2015 }, { "title": "Pawnbroker", "label": "Pawnbroker", - "value": "pawnbroker" + "value": "pawnbroker", + "min-year": 1995, + "max-year": 2015 + }, + { + "title": "Peddler (Fruits and Vegetables)", + "label": "Peddler (Fruits and Vegetables)", + "value": "peddler-food-fruits-and-vegtables-only", + "min-year": 2000, + "max-year": 2013 + }, + { + "title": "Peddler (Fruits and Vegetables, Special)", + "label": "Peddler (Fruits and Vegetables, Special)", + "value": "peddlerfood---fruits-and-vegetables-only---special", + "min-year": 2005, + "max-year": 2013 }, { "title": "Peddler", "label": "Peddler", - "value": "peddler" + "value": "peddler-license", + "min-year": 2012, + "max-year": 2015 + }, + { + "title": "Peddler (Non-Food)", + "label": "Peddler (Non-Food)", + "value": "peddler-non-food", + "min-year": 1999, + "max-year": 2014 + }, + { + "title": "Peddler (Non-Food, Special)", + "label": "Peddler (Non-Food, Special)", + "value": "peddler-non-food-special", + "min-year": 2001, + "max-year": 2014 + }, + { + "title": "Performing Arts Venue", + "label": "Performing Arts Venue", + "value": "performing-arts-venue", + "min-year": 2006, + "max-year": 2015 + }, + { + "title": "Pet Shop", + "label": "Pet Shop", + "value": "pet-shop", + "min-year": 2000, + "max-year": 2013 + }, + { + "title": "Private Booting Operation", + "label": "Private Booting Operation", + "value": "private-booting-operation", + "min-year": 2006, + "max-year": 2012 + }, + { + "title": "Produce Merchant", + "label": "Produce Merchant", + "value": "produce-merchant", + "min-year": 2012, + "max-year": 2013 + }, + { + "title": "Public Garage", + "label": "Public Garage", + "value": "public-garage", + "min-year": 1996, + "max-year": 2015 + }, + { + "title": "Amusement", + "label": "Amusement", + "value": "public-place-of-amusement", + "min-year": 1997, + "max-year": 2015 }, { "title": "Raffle", "label": "Raffle", - "value": "raffles" + "value": "raffles", + "min-year": 2003, + "max-year": 2015 }, { - "title": "Restaurant & Grocery", - "label": "Restaurant & Grocery", - "value": "retail-food" + "title": "Regulated Business", + "label": "Regulated Business", + "value": "regulated-business-license", + "min-year": 2012, + "max-year": 2015 }, { - "title": "Shared Kitchen", - "label": "Shared Kitchen", - "value": "shared-kitchen" + "title": "Repossessor (Class A)", + "label": "Repossessor (Class A)", + "value": "repossessor-class-a", + "min-year": 2009, + "max-year": 2012 + }, + { + "title": "Repossessor (Class B)", + "label": "Repossessor (Class B)", + "value": "repossessor-class-b", + "min-year": 2009, + "max-year": 2012 + }, + { + "title": "Repossessor Employee (Class B)", + "label": "Repossessor Employee (Class B)", + "value": "repossessor-class-b-employee", + "min-year": 2009, + "max-year": 2012 + }, + { + "title": "Residential Real Estate Developer", + "label": "Residential Real Estate Developer", + "value": "residential-real-estate-developer", + "min-year": 2004, + "max-year": 2015 + }, + { + "title": "Retail Computing Center", + "label": "Retail Computing Center", + "value": "retail-computing-center", + "min-year": 2002, + "max-year": 2013 + }, + { + "title": "Retail Food License for Dog Friendly Area", + "label": "Retail Food License for Dog Friendly Area", + "value": "retail-food-est.-supplemental-license-for-dog-friendly-areas", + "min-year": 2008, + "max-year": 2013 + }, + { + "title": "Retail Food Establishment", + "label": "Retail Food Establishment", + "value": "retail-food-establishment", + "min-year": 1996, + "max-year": 2015 + }, + { + "title": "Riverwalk Venue Liquor License", + "label": "Riverwalk Venue Liquor License", + "value": "riverwalk-venue-liquor-license", + "min-year": 2008, + "max-year": 2013 + }, + { + "title": "Scavenger", + "label": "Scavenger", + "value": "scavenger-private", + "min-year": 2003, + "max-year": 2013 + }, + { + "title": "Secondhand Dealer (Childrens Products)", + "label": "Secondhand Dealer (Childrens Products)", + "value": "secondhand-dealer---childrens-products", + "min-year": 2006, + "max-year": 2013 + }, + { + "title": "Secondhand Dealer (Incl. Valuables)", + "label": "Secondhand Dealer (Incl. Valuables)", + "value": "secondhand-dealer-includes-valuable-objects", + "min-year": 2005, + "max-year": 2015 + }, + { + "title": "Secondhand Dealer (No Valuables)", + "label": "Secondhand Dealer (No Valuables)", + "value": "secondhand-dealer-no-valuable-objects", + "min-year": 2011, + "max-year": 2015 + }, + { + "title": "Single Room Occupancy (Class I)", + "label": "Single Room Occupancy (Class I)", + "value": "single-room-occupancy-class-i", + "min-year": 2003, + "max-year": 2013 + }, + { + "title": "Single Room Occupancy (Class II)", + "label": "Single Room Occupancy (Class II)", + "value": "single-room-occupancy-class-ii", + "min-year": 2005, + "max-year": 2013 + }, + { + "title": "Special Event (Beer & Wine)", + "label": "Special Event (Beer & Wine)", + "value": "special-event-beer-and-wine", + "min-year": 2008, + "max-year": 2010 + }, + { + "title": "Special Event (Food)", + "label": "Special Event (Food)", + "value": "special-event-food", + "min-year": 2008, + "max-year": 2010 + }, + { + "title": "Street Performer", + "label": "Street Performer", + "value": "street-performer", + "min-year": 2000, + "max-year": 2014 }, { "title": "Tavern", "label": "Tavern", - "value": "tavern" + "value": "tavern", + "min-year": 2002, + "max-year": 2015 + }, + { + "title": "Taxicab Dispatch", + "label": "Taxicab Dispatch", + "value": "taxicab-two-way-dispatch-service-license", + "min-year": 2012, + "max-year": 2014 + }, + { + "title": "Tire Facility (100-1000 Tires)", + "label": "Tire Facility (100-1000 Tires)", + "value": "tire-facilty-class-i-100---1000-tires", + "min-year": 2002, + "max-year": 2015 + }, + { + "title": "Tire Facility (1000-5000 tires)", + "label": "Tire Facility (1000-5000 tires)", + "value": "tire-facility-class-ii-1001---5000-tires", + "min-year": 2005, + "max-year": 2014 + }, + { + "title": "Tire Facility (5000 or more tires)", + "label": "Tire Facility (5000 or more tires)", + "value": "tire-facility-class-iii-5001---more-tires", + "min-year": 2004, + "max-year": 2013 + }, + { + "title": "Tobacco Dealer (Wholesale)", + "label": "Tobacco Dealer (Wholesale)", + "value": "tobacco-dealer-wholesale", + "min-year": 2004, + "max-year": 2015 + }, + { + "title": "Tobacco Dealer (Retail)", + "label": "Tobacco Dealer (Retail)", + "value": "tobacco-retail-over-counter", + "min-year": 1995, + "max-year": 2015 + }, + { + "title": "Tobacco Sampler", + "label": "Tobacco Sampler", + "value": "tobacco-sampler", + "min-year": 2006, + "max-year": 2015 + }, + { + "title": "Tobacco Vending Machine", + "label": "Tobacco Vending Machine", + "value": "tobacco-vending-machine-operator", + "min-year": 2006, + "max-year": 2011 + }, + { + "title": "Vacation Rental", + "label": "Vacation Rental", + "value": "vacation-rental", + "min-year": 2011, + "max-year": 2013 + }, + { + "title": "Valet Parking Operator", + "label": "Valet Parking Operator", + "value": "valet-parking-operator", + "min-year": 2011, + "max-year": 2014 }, { - "title": "Tobacco", - "label": "Tobacco", - "value": "tobacco" + "title": "Veterinary Hospital", + "label": "Veterinary Hospital", + "value": "veterinary-hospital", + "min-year": 2000, + "max-year": 2013 }, { - "title": "Valet Parking", - "label": "Valet Parking", - "value": "valet-parking-operator" + "title": "Weapons Dealer", + "label": "Weapons Dealer", + "value": "weapons-dealer", + "min-year": 2006, + "max-year": 2013 }, { - "title": "Weapons & Explosives", - "label": "Weapons & Explosives", - "value": "weapons" + "title": "Wholesale Food Establishment", + "label": "Wholesale Food Establishment", + "value": "wholesale-food-establishment", + "min-year": 1996, + "max-year": 2015 }] \ No newline at end of file