var options = { valueNames: ["name", "town", "cuisine", "description"], item: '<li class="restaurant-item"><div class="restaurant-container"><div class="restaurant-info"><h3 class="name"></h3><div class="town"></div><div class="cuisine"></div><summary class="description"></summary></div><a target="_blank" class="url"><button class="more-info">more info</button></a><div class="clear"></div></div></li>' }; var values = [{ name: "Aki Japanese Restaurant", town: "Bloomfield", cuisine: "Japanese", description: "A sleek and stylish restaurant that offers healthy and flavorful food that is served fresh.", url: "http://www.akisushius.com/" }, { name: "Cloverleaf", town: "Caldwell", cuisine: "Bar/Pub", description: "Offering a menu consisting of American cuisine in a family-casual dining atmosphere.", url: "http://www.cloverleaftavern.com/" }, { name: "LuNello", town: "Cedar Grove", cuisine: "Italian", description: "Offers a classic Italian menu with special homemade and signature dishes that exude quality.", url: "http://www.lunello.com/" }, { name: "Calandra's Mediterranean Grill", town: "Fairfield", cuisine: "Mediterranean", description: "A family friendly restaurant featuring an open kitchen with a wood burning grill and stone pizza oven.", url: "http://www.calandrasmedgrill.com/home.html" }, { name: "Stamna Greek Taverna", town: "Little Falls", cuisine: "Greek", description: "Enjoy home cooked traditional Greek fare with ambiance that portraits the feel of Greece.", url: "http://www.stamnataverna.com/" }, { name: "Strip House", town: "Livingston", cuisine: "Steakhouse", description: "Serving cuts of meat primed to perfection, an extensive wine list, and their famed 24-layer chocolate cake.", url: "http://www.striphousenewjersey.com/" }, { name: "Fricasse French Bistro", town: "Montclair", cuisine: "French", description: "Specializing in high quality daily specials and fine French cuisine served in a bistro setting.", url: "http://www.fricasseebistro.com/" }, { name: "Samurai Sushi", town: "Livingston", cuisine: "Japanese", description: "A relaxing ambiance combining the Zen-like calm of a Japanese garden with a modern, NY sushi bar style.", url: "http://www.usasamurai.com/" }]; var restaurantList = window.restaurantList = new List('restaurant-list', options, values); function filterByValues(filterItems) { //this really needs to be refactored filterItems.towns = filterItems.towns === null ? [] : filterItems.towns; filterItems.cuisines = filterItems.cuisines === null ? [] : filterItems.cuisines; if (filterItems.towns.length === 0 && filterItems.cuisines.length === 0) { restaurantList.filter(); } else if (filterItems.towns.length > 0 && filterItems.cuisines.length === 0) { restaurantList.filter(function (item) { var values = item.values(); for (var i in filterItems.towns) { if (values.town === filterItems.towns[i]) { return true; } } return false; }); } else if (filterItems.cuisines.length > 0 && filterItems.towns.length === 0) { restaurantList.filter(function (item) { var values = item.values(); for (var i in filterItems.cuisines) { if (values.cuisine === filterItems.cuisines[i]) { return true; } } return false; }); } else { restaurantList.filter(function (item) { var values = item.values(); for (var town in filterItems.towns) { for (var cuisine in filterItems.cuisines) { //TODO I need to think about how to best filter by the union of the two if (values.town === filterItems.towns[town] && values.cuisine === filterItems.cuisines[cuisine]) { return true; } } } return false; }); } } var selected = { towns: [], cuisines: [] }; function townUpdate(e, obj) { if (obj === undefined) { selected.towns = $(e.target).val(); filterByValues(selected); } else if (obj.selected !== undefined) { selected.towns.push(obj.selected); filterByValues(selected); } else if (obj.deselected !== undefined) { selected.towns = _.without(selected.towns, obj.deselected); filterByValues(selected); } } function cuisineUpdate(e, obj) { if (obj === undefined) { selected.cuisines = $(e.target).val(); filterByValues(selected); } else if (obj.selected !== undefined) { selected.cuisines.push(obj.selected); filterByValues(selected); } else if (obj.deselected !== undefined) { selected.cuisines = _.without(selected.cuisines, obj.deselected); filterByValues(selected); } } $(".chosen-select.cuisines").on("chosen:ready", function (e, obj) { this.removeChild(this.firstElementChild); }).chosen({ display_disabled_options: false }).change(cuisineUpdate).trigger("chosen:updated"); $(".chosen-select.towns").on("chosen:ready", function (e, obj) { this.removeChild(this.firstElementChild); }).chosen({ display_disabled_options: false }).change(townUpdate).trigger("chosen:updated"); // Some underscore methods to make my life easier var ArrayProto = Array.prototype, concat = ArrayProto.concat, slice = ArrayProto.slice, each = ArrayProto.each, nativeFilter = ArrayProto.filter, nativeIndexOf = ArrayProto.indexOf, _ = {}; _.without = function (array) { return _.difference(array, slice.call(arguments, 1)); }; _.difference = function (array) { var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); return _.filter(array, function (value) { return !_.contains(rest, value); }); }; _.filter = function (obj, iterator, context) { var results = []; if (obj == null) return results; if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); each(obj, function (value, index, list) { if (iterator.call(context, value, index, list)) results.push(value); }); return results; }; _.contains = function (obj, target) { if (obj == null) return false; if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; return any(obj, function (value) { return value === target; }); };
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <div class="container"> <select data-placeholder="Choose a town..." multiple class="chosen-select towns"> <option value='' disabled selected style='display:none;'>Choose a town...</option> <option>Belleville</option> <option>Bloomfield</option> <optgroup label="The Caldwells"> <option>Caldwell</option> <option>North Caldwell</option> <option>West Caldwell</option> </optgroup> <option>Cedar Grove</option> <option>Essex Fells</option> <option>Fairfield</option> <option>Glen Ridge</option> <option>Irvington</option> <option>Livingston</option> <option>Maplewood</option> <option>Millburn</option> <option>Montclair</option> <option>Newark</option> <option>Nutley</option> <optgroup label="The Oranges"> <option>East Orange</option> <option>Orange</option> <option>West Orange</option> <option>South Orange</option> </optgroup> <option>Roseland</option> <option>Verona</option> </select> <select data-placeholder="Choose a cuisine..." multiple class="chosen-select cuisines"> <option value='' disabled selected style='display:none;'>Choose a cuisine...</option> <option>Japanese</option> <option>Bar/Pub</option> <option>Italian</option> <option>Mediterranean</option> <option>Greek</option> <option>Steakhouse</option> <option>French</option> </select> <div id="restaurant-list"> <ul class="list"></ul> </div> </div>
body { margin: 10px; font-family: sans-serif; background-color: white; font-size: 18px; min-width: 320px; } .container { position: relative; width: 590px; width: 33em; margin: 0 auto; } .chosen-select, .chosen-container { width: 49.5% !important; } /* #restaurant-list { width: 590px; width: 33em; } */ .name { margin: 0.2em 0; color: #007dc5; font-weight: 300; } .clear { clear: both; } .restaurant-item { padding: 0.35em 1em 0.65em; margin: 1em 0; list-style: none; background-color: #e6e7e8; color: #231f20; font-weight: 100; } .list { padding-left: 0; } .restaurant-info { float: left; width: 75%; } .more-info { font-size: 24px; font-weight: 600; text-align: center; margin-top: 4px; width: 4.1em; float: right; border: 0; line-height: normal; padding: 9px 14px 9px; /* This seems to be jittery when the page reflows */ padding: 0.375em 0.583em; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; background-color: hsl(201, 100%, 30%) !important; background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#00a5ff", endColorstr="#006399"); background-image: -khtml-gradient(linear, left top, left bottom, from(#00a5ff), to(#006399)); background-image: -moz-linear-gradient(top, #00a5ff, #006399); background-image: -ms-linear-gradient(top, #00a5ff, #006399); background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #00a5ff), color-stop(100%, #006399)); background-image: -webkit-linear-gradient(top, #00a5ff, #006399); background-image: -o-linear-gradient(top, #00a5ff, #006399); background-image: linear-gradient(#00a5ff, #006399); border-color: #006399 #006399 hsl(201, 100%, 25%); color: #fff !important; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.33); -webkit-font-smoothing: antialiased; } @media only screen and (max-width : 620px) { .container { width: 98%; font-size: 15px; } .more-info { font-size: 18px; } .chosen-select, .chosen-container { width: 49.4% !important; } } @media only screen and (max-width : 365px) { .more-info { font-size: 16px; width: 4.1em; padding: 0.5em 0.6em; } .chosen-select, .chosen-container { width: 49.3% !important; } }