2

我需要创建一个button循环通过3 个状态。出于某种原因,很难找到。每个状态下的功能都是简单的样式变化,例如:

click 1: hide div
click 2: show hidden div, change bg-color
click 3: reset bg-color, change font
click 1: reset font, hide div

有任何想法吗?我不能使用jquery(课堂作业,不允许)

4

2 回答 2

3

Cou 可以使用一个数组,每个状态变化都有一个函数,以及一个循环遍历可能状态的计数器变量。

然后只需通过按钮的单击处理程序调用当前状态函数。

像这样的东西可以做到

var toggle = (function (el) {
    var div = document.getElementById(el); //Get the div you want to change
    var states = []; //The Array to hold the functions
    var style = {} //Will be used to save the current style
    for (var att in div.style) //Saves the style of the div *I was just lazy and did a for loop*
    style[att] = div.style[att]

    var current = 0; //The Counter

    states[0] = function () { //The first state function
        div.style["font-family"] = style["font-family"]
        div.style.display = "none";
    };
    states[1] = function () {
        div.style.display = "block";
        div.style["background-color"] = "rgb(" + [rand(), rand(), rand()] + ")"; // [1,2,3] toString is "1,2,3"
    };
    states[2] = function () {
        div.style["background-color"] = style["background-color"];
        div.style["font-family"] = "Courier New";
    }

    function rand() { //ONly to return a random number for a random bgcolor
        return ~~(Math.random() * 255)
    }
    return function () {  //The function which cycles through the states
        states[current]() //Invokes the current statechange function
        current = (current + 1) % (states.length); //Increments the counter and uses modulo to cycle
    }
})("div");

document.getElementById("click")
    .addEventListener("click", toggle);

这是一个关于JSFiddle的例子

更新:

我对其进行了一些修改并注释了更改的代码,这应该能够更改页面上多个元素的状态

    function rand() {
        return~~ (Math.random() * 255);
    }


    var makeToggle = function (states, elements) { // I Changed it to makeToggle, The first argument accepts an array of states to cycle through, the second either an array of elements, or an array of objects with the element property (and an optional state function)
        var current = 0; //Sets the counter to zero

        for (var i = 0, ilen = elements.length; i < ilen; i++) {
            if (!elements[i].element) { //check if you passed an Object with the `element` Property
                elements[i] = {
                    element: elements[i] //If it was an array, the arrays element will be set to an object
                }; //to support arrays only
            }
            elements[i].style = {}; //to save the original style in the object
            for (var att in elements[i].element.style) {
                elements[i].style[att] = div.style[att]; // saves it
            }
        }

        function doForElements() { //Invokes either the state function passed with an element, or the general statefunction
            for (var i = 0, ilen = elements.length; i < ilen; i++) {
                var state = elements[i].states;
                if (state && typeof state[current] === "function") state = state[current];
                else state = states[current];
                state(elements[i].element, elements[i].style); //Invokes the function with the element as first parameter and the original style as second
            }

        }
        return function () { //Returns the function for the click handler
            doForElements();
            current = (current + 1) % (states.length); //cycles the current state counter
        };
    };

    var states = []; //Here the General State change functions get defined
    states[0] = function (div, style) {
        div.style["font-family"] = style["font-family"];
        div.style.display = "none";
    };
    states[1] = function (div, style) {
        div.style.display = "block";
        div.style["background-color"] = "rgb(" + [rand(), rand(), rand()] + ")";
    };
    states[2] = function (div, style) {
        div.style["background-color"] = style["background-color"];
        div.style["font-family"] = "Courier New";
    };


    var elements = [].slice.call(document.getElementsByTagName("div")); //To actually get an Array of the NodeList (all divs on the page)

    elements[4] = { //changes the 5th element (which should receive a special statechange function)
        element: elements[4],
        states: {
            1: function (div, style) { //Use an Objects property to pass an single state change instead of an array with functions
                div.style.display = "block";
                div.style["background-color"] = "yellow";
            }
        }
    };


    var toggle = makeToggle(states, elements); //sets the function for the click handler to toggle
    //Pass an Object with the Elements and an optional st

    document.getElementById("click")
        .addEventListener("click", toggle); //binds the function

这是一个JSBin来尝试一下

于 2013-02-13T09:25:22.987 回答
2
<div id="mydiv" data-state="0"></div>
<input type="button" id="mybutton" value="Change State" />

var states = {
    1: [{ name: 'display', value: 'none'}],
    2: [{ name: 'display', value: 'block'}],
    3: [{ name: 'background-color', value: 'white'}, { name: 'prop', value: 'val' }]
}

window.onload = function(){
     var mydiv = document.getElementById('mydiv');
     var mybutton = document.getElementById('mybutton');
     mybutton.onclick = function (){
         var num = parseInt(mydiv.getAttribute('data-state'));
         num = num < 3 ? ++num : 1;
         var nameValues = states[num];
         for(var i = 0; i < nameValues.length; i++)
              mydiv.style[nameValues[i].name] = nameValues[i].value;
     }
}
于 2013-02-13T09:06:11.323 回答