单击元素时,Javascript中的数学问题

时间:2015-02-05 21:21:51

标签: javascript jquery html

未解

上次更新时间:下午4:15

我在

的地方

我有三个类别供人们选择:性别,年龄,种族。每个都有自己的选项男/女; 35岁以下,36-64岁,65岁以上;白色,黑色,原住民,梅蒂斯人和亚洲人。

单击其中一个选项时,该数字应从var total中减去(这是MLA的数量)。我为这些数字设置了全局变量,这会更改位于我的span.number文件中的index.html来说明,"有多个适合您人口统计数据的x-MLAs。&& #34;

我被困的地方

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>

2 个答案:

答案 0 :(得分:1)

如果我理解正确,下面的演示应该做你想要的。您可以在jsFiddle找到下面和此处的代码。 (旧版本的jsfiddle,新版本见下面的编辑。)

它基本上是在做什么和我建议的。对于“计算”,我使用UnderscoreJS使用where方法查找当前点击的选择的匹配键/值对。然后很容易得到长度选择的总和。

在演示中,我为男性,女性和少数民族做过。它应该与其他选项完全相同。


编辑07.02.2015

我改进了代码。现在,您可以在列表中激活多个过滤器。此外,删除减法因为过滤后的列表始终包含具有length属性的项目数。

代码正在运行,但仍有一些要改进的地方:

    需要更改
  • removeFilter以轻松删除过滤器而不指定过滤器参数
  • setFilter改进:if ( index == -1 ) {并非真正需要,因为在添加新过滤器之前始终会删除过滤器。
  • 为每个广播组添加重置按钮。目前,只有一个“全部重置”按钮。
  • 使用AngularJS更新DOM会更好,因为脚本总是在每次更换过滤器时重新创建DOM。
  • 也许使用AngularJS,你可以检查是否有ng-repeat的过滤器来做类似的行为。

我可能还没有测试过滤器的任何组合是否正常工作,因为我只有三个列表项。所以你必须用代码做更多的测试。

我在这里将代码更新为最新版本,这里是jsFiddle


更多代码说明16.02.2015

函数refreshListsetTotal用于更新DOM。

过滤器函数genderethnicityage在应用过滤器后返回新数组。

数组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>
-->

答案 1 :(得分:0)

如果通过循环每个MLA并递增计数器,每次点击一个类别时重新计算number怎么样?我认为你通过尝试使用以前的计算作为起点使你复杂化,但每次重新开始都更容易。