未解决
上次更新时间:下午4:15
我在哪里
我有三种类别供人们选择:性别,年龄,种族。每个都有自己的一组选项男/女; 35、36-64岁,65岁以上;白人,黑人,原住民,梅蒂斯人和亚洲人。
单击其中一个选项时,该数字应从var total
中减去(这是MLA的数量)。我已经为数字设置了全局变量,该变量将位于我的span.number
文件中的index.html
更改为:“您的人口统计信息中包含X位数的MLA”。
我被困在哪里
a)我正在寻找一种使用Javascript进行数学运算的更有效方法,目前它非常简陋。如果您查看scripts.js
中的“性别”选项,我创建了一个变量var resultMale = total - female
,但是
当生成span.number
依赖于先前选择的选项时,它变得不那么漂亮了。
b)我尝试使用管道布尔值,但是我不清楚第二个类别“年龄”的情况,其中包括var resultLow = resultMale || resultFemale -(middle + high)
如何知道“性别”类别中已单击/选择的内容,以便做适当的数学。
scripts.js
$(function() {
// Numbers
var total = 56
var male = 41;
var female = 15;
var low = {}
var middle = {}
var high = {}
var white = 41
var black = 0;
var aboriginal = null;
var metis = null;
var asian = null;
// MLAs
var MLAs = [
{
"Name": "Nancy Allan",
"Age": 62,
"Constuency": "St. Vital",
"Party": "NDP",
"Gender": "Female",
"Ethnicity": "White"
},
{
"Name": "James Allum",
"Age": null,
"Constuency": "Fort Garry-Riverview",
"Party": "NDP",
"Gender": "Male",
"Ethnicity": "White"
},
{
"Name": "Rob Altemeyer",
"Age": null,
"Constuency": "Wolseley",
"Party": "NDP",
"Gender": "Male",
"Ethnicity": "White"
}]
// Option #1: Gender
$( ".G1" ).click(function() {
$(".G2").toggleClass("disabled");
$(".headshot").not(".Female").toggleClass("opacity");
var resultMale = total - female;
$(".number").html(resultMale);
});
$( ".G2" ).click(function() {
$(".G1").toggleClass("disabled");
$(".headshot").not(".Male").toggleClass("opacity");
var resultFemale = total - male
$(".number").html(resultFemale);
});
// Option #2: Age
$( ".A1" ).click(function() {
$(".A2").toggleClass("disabled");
$(".A3").toggleClass("disabled");
$(".Low").toggleClass("show");
var resultLow = resultMale || resultFemale - (middle + high);
$(".number").html("?");
});
$( ".A2" ).click(function() {
$(".A1").toggleClass("disabled");
$(".A3").toggleClass("disabled");
$(".Medium").toggleClass("show");
var resultMiddle = resultMale || resultFemale - (low + high);
$(".number").html("?");
});
$( ".A3" ).click(function() {
$(".A1").toggleClass("disabled");
$(".A2").toggleClass("disabled");
$(".High").toggleClass("show");
var resultHigh = resultMale || resultFemale - (low + middle);
$(".number").html("?");
});
// OLD
$( ".E1" ).click(function() {
$( ".White" ).toggleClass("show");
var resultWhite = resultLow || resultMiddle || resultHigh - (black + aboriginal + metis + asian);
$(".number").html(resultWhite);
});
$( ".E2" ).click(function() {
$( ".Black" ).toggleClass("show");
var resultBlack = resultLow || resultMiddle || resultHigh - (white + aboriginal + metis + asian);
$(".number").html("0");
});
$( ".E3" ).click(function() {
$( ".Aboriginal" ).toggleClass("show");
var resultAboriginal = resultLow || resultMiddle || resultHigh - (white + black + metis + asian);
$(".number").html(null);
});
$( ".E4" ).click(function() {
$( ".Metis" ).toggleClass("show");
var resultMetis = resultLow || resultMiddle || resultHigh - (white + black + aboriginal + asian);
$(".number").html(null);
});
$( ".E5" ).click(function() {
$( ".Asian" ).toggleClass("show");
var resultAsian = resultLow || resultMiddle || resultHigh - (white + black + aboriginal + metis);
$(".number").html(null);
});
// Option #3: Ethnicity
// $("input[name='ethnicity']").on("change", function() {
// var $checkedbox = $("input[name='ethnicity']:checked");
// if($checkedbox.length >= 2)
// {
// var $uncheckedbox = $("input[name='ethnicity']:not(:checked)");
// $.each($uncheckedbox,function() {
// $(this).attr("disabled", "disabled");
// });
// }
// else
// {
// $("input[name='ethnicity']").removeAttr("disabled");
// }
// });
// Shows a popup with MLA information
$(".headshot").click(function(){
var idx = $(this).index() - 1;
$(".tooltip").fadeIn("slow");
$(".tooltipName").html(MLAs[idx].Name);
$(".tooltipParty").html(MLAs[idx].Party);
$(".tooltipConstuency").html(MLAs[idx].Constuency);
$(".tooltipEthnicity").html(MLAs[idx].Ethnicity) + ",";
$(".tooltipAge").html(MLAs[idx].Age);
});
// Bounce and show result
$(".rect").click(function(){
console.log("Bounce test");
$(".others").fadeIn("slow");
$(".others").effect( "bounce",
{times:3}, 600 );
});
// This hides the footer on click
$(".crossContainer").click(function(){
$("footer").slideUp("slow", function(){
console.log("No feedback makes us sad.");
});
});
// This hides the credits
$(".credits").hide();
});
index.html(包括span.number)
<!-- Three options readers can click -->
<section class="interactive clearfix">
<section class="selection" id="selection">
<div class="gender">
<p class="category">Gender</p>
<div class="options">
<p class="rect G1">Male</p>
<p class="rect G2">Female</p>
</div><!-- /.options -->
</div><!-- /.gender -->
<div class="age">
<p class="category">Age</p>
<div class="options">
<p class="rect A1">Under 35</p>
<p class="rect A2">36-64</p>
<p class="rect A3">65+</p>
</div><!-- /.options -->
</div><!-- /.age -->
<div class="ethnicity">
<p class="category">Ethnicity<span>*<span></p>
<div class="options">
<p class="rect E1 E">White</p>
<p class="rect E2 E">Black</p>
<p class="rect E3 E">Aboriginal</p>
<p class="rect E4 E">Metis</p>
<p class="rect E5 E">Asian</p>
</div><!-- /.options -->
</div><!-- /.ethnicity -->
</section>
<section class="others">
<h2>There are <span class="number">56</span> MLAs that fit in your demographic</h2>
<figcaption class="special">(Does not include the single vacant seat for the Pas.)</figcaption>
</section>
最佳答案
如果我对它的理解正确,则以下演示应按照您的要求进行。您可以在下面和此处的jsFiddle中找到代码。 (旧版本的jsfiddle,新版本请参见下面的编辑。)
基本上是在做Andi建议的事情。对于“计算”,我已使用UnderscoreJS使用where
方法为当前单击的选择找到匹配的键/值对。这样很容易获得带有长度的选择总数。
在演示中,我针对男性,女性和种族进行了演示。它应该与其他选项完全一样。
编辑07.02.2015
我已经改进了代码。现在,您可以在列表中激活多个过滤器。减法也被删除,因为过滤后的列表始终具有length属性的项数。
该代码正在运行,但是仍有一些要改进的地方:
需要更改removeFilter
以轻松删除过滤器,而无需指定过滤器参数setFilter
即兴:实际上并不需要if ( index == -1 ) {
,因为在添加新过滤器之前始终会删除过滤器。
为每个无线电组添加重置按钮。目前,只有一个“全部重置”按钮。
使用AngularJS更新DOM会更好,因为脚本总是在每次过滤器更改时重新创建DOM。
也许使用AngularJS,您可以检查是否存在用于ng-repeat的过滤器以执行类似的行为。
我也可能没有测试过过滤器的任何组合是否正常工作,因为我只有三个列表项。因此,您必须对代码进行更多测试。
我将代码更新为最新版本,这是jsFiddle。
更多代码说明16.02.2015
函数refreshList
和setTotal
用于更新DOM。
应用过滤器后,过滤器功能gender
,ethnicity
和age
返回新数组。
数组activeFilters
存储当前选择的过滤器。它存储过滤器函数,以便可以通过遍历此数组来调用它们。稍后对此有更多详细信息。setFilter
方法正在设置过滤器。它将过滤器添加到activeFilters
数组,然后应用过滤器。applyFilter
函数可能是最难理解的。遍历activeFilters
数组的每个项目。如果您有两个活动的过滤器(此处为性别和种族),则数组activeFilters将如下所示:
activeFilters = [{
method: function(array, gender){...},
param: 'male'
}, {
method: function (array, ethnic){...},
param: 'white'
}];
使用
activeFilters[0].method(MLAs,'male')
,您可以手动调用性别过滤器。这就是$ .each循环在this
循环内所做的就是{method: ..., param: ...}
。因此,对于this.method(filtered, this.param)
,过滤器将应用于变量filtered
。循环之后,每个活动的过滤器都将应用于阵列。
var $total = $('#total');
var $MLA_List = $('#MLA_List');
// MLAs
var MLAs = [{
"Name": "Nancy Allan",
"Age": 62,
"Constuency": "St. Vital",
"Party": "NDP",
"Gender": "Female",
"Ethnicity": "White"
}, {
"Name": "James Allum",
"Age": 34,
"Constuency": "Fort Garry-Riverview",
"Party": "NDP",
"Gender": "Male",
"Ethnicity": "Black"
}, {
"Name": "Rob Altemeyer",
"Age": 36,
"Constuency": "Wolseley",
"Party": "NDP",
"Gender": "Male",
"Ethnicity": "White"
}];
var filteredMLAs = MLAs.slice(0); // copy MLAs
var total = filteredMLAs.length;
var refreshList = function () {
var list = filteredMLAs;
setTotal(list.length);
$MLA_List.empty();
$.each(list, function (index, value) {
$MLA_List.append($('<li/>').text(list[index].Name));
});
};
var setTotal = function (value) {
$total.text(value);
};
// filter methods
var gender = function (array, gender) {
//console.log('gender filter called!', gender);
return _.where(array, {
"Gender": gender
});
};
var ethnicity = function (array, ethnic) {
//console.log('ethnic filter called!', array, ethnic);
return _.where(array, {
"Ethnicity": ethnic
});
};
var age = function(array, ageRange) {
//under 35, 36-64, 65+
return _.filter(array, function(MLA) {
//console.log(MLA.Age);
switch(ageRange) {
case 35:
return ( MLA.Age <= 35 );
case 36:
return ( MLA.Age >= 35 && MLA.Age <= 64);
case 65:
return ( MLA.Age >= 65 );
};
return false;
});
};
var activeFilters = [];
var setFilter = function (method, param) {
var newFilter = {
method: method,
param: param
};
var matchedFilter = _.find(activeFilters, newFilter),
index = activeFilters.indexOf(matchedFilter);
if ( index == -1 ) {
activeFilters.push(newFilter);
}
applyFilter();
};
var removeFilter = function(method, param) {
var filter = {
method: method,
param: param
};
var index = activeFilters.indexOf(_.find(activeFilters, filter));
if (index > -1) {
activeFilters.splice(index, 1);
}
applyFilter(); // re-apply filter to update list
};
var applyFilter = function () {
var filtered = MLAs.slice(0);
$.each(activeFilters, function () {
filtered = this.method(filtered, this.param);
});
filteredMLAs = filtered ? filtered: [];
refreshList();
};
$('#Male, #Female').click(function () {
//console.log(this.id);
removeFilter(gender, this.id=='Male'? 'Female': 'Male'); // remove not active filter
setFilter(gender, this.id);
});
$('#White, #Black').click(function () {
//console.log(this.checked);
if ( this.checked )
setFilter(ethnicity, this.id); //'White');
else
removeFilter(ethnicity, this.id); //'White');
});
$('.Age').click(function() {
removeFilter(age, 35); // improvement of remove filter required, e.g. remove all age filters
removeFilter(age, 36);
removeFilter(age, 65);
setFilter(age, parseInt(this.value));
});
$('#reset').click(function(){
//console.log('reset form');
activeFilters = [];
$(':checkbox, :radio').attr('checked', false);
applyFilter();
});
$(function () {
refreshList();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
There are <span id="total"></span> MLAs matching.
<ul id="MLA_List"></ul>
<hr/>
<p>click to filter:</p>
<input type="radio" id="Male" name="gender">male</input>
<input type="radio" id="Female" name="gender">female</input>
<input type="checkbox" id="White">white</input>
<input type="checkbox" id="Black">black</input>
<input type="radio" class="Age" name="age" value="35">under 35</input>
<input type="radio" class="Age" name="age" value="36">36-64</input>
<input type="radio" class="Age" name="age" value="65">65+</input>
<button id="reset">reset</button>
<!-- <a href="#" id="male">male</a>
<a href="#" id="female">female</a>
<a href="#" id="white">white</a>
-->