使用纯Javascript进行CSS转换

时间:2014-02-01 12:13:36

标签: javascript javascript-events onclick

我正在做一个移动页面/广告,在图片上方有4-5个小信息框。触摸时,框将展开并显示有关图像部分的文本。当触摸下一个框时,它将展开,另一个当前展开的框将返回默认值。我需要保持它非常轻的重量,所以我一直在玩使用:target伪类的CSS-only版本。除了预期的页面跳转到顶部之外,它的效果非常好。

<body>
<div class="page">
    <a id="button1" href="#button1">
        btn1
    </a>
    <a id="button2" href="#button2">
        btn2
    </a>
    <a id="button3" href="#button3">
        btn3
    </a>
    <a id="button4" href="#button4">
        btn3
    </a>

</div>
</body>

Fiddle

为了避免不必要的页面跳转,我得出结论,我需要使用Javascript通过点击事件来控制它。虽然它很小jQuery lib会占用我的可用kB,所以不是一个选项。我花了几天时间浏览网络寻求实现某种删除/添加类功能的解决方案,但无济于事。我设法单独扩展和关闭盒子,但是当所有盒子同时打开时,它会留下混乱的混乱。我意识到我必须得到它来删除扩展类的任何当前实例,但是如何?

<body>
<div class="page">
    <div class="box1">
    </div>

    <div class="box2">
    </div>
</div>
</body>

JS:

var hasClass = function (elem, className) {
    return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
}

var addClass = function (elem, className) {
    if (!hasClass(elem, className)) {
        elem.className += ' ' + className;
    }
}

var removeClass = function (elem, className) {
    var newClass = ' ' + elem.className.replace( /[\t\r\n]/g, ' ') + ' ';
    if (hasClass(elem, className)) {
        while (newClass.indexOf(' ' + className + ' ') >= 0 ) {
            newClass = newClass.replace(' ' + className + ' ', ' ');
        }
        elem.className = newClass.replace(/^\s+|\s+$/g, '');
    }
}

// Boxes Functions
if ( 'querySelector' in document && 'addEventListener' in window ) {

    var box1items = document.querySelectorAll('.box1');
    var box2items = document.querySelectorAll('.box2');


    [].forEach.call(box1items, function (box1) {

        box1.addEventListener('click', function(e) {

            if ( hasClass(box1, 'box1stage2') ) {
                removeClass(box1, 'box1stage2');
            }

            else {
                addClass(box1, 'box1stage2');
            }



        }

    )

    });

    [].forEach.call(box2items, function (box2) {

        box2.addEventListener('click', function(e) {

            if ( hasClass(box2, 'box2stage2') ) {
                removeClass(box2, 'box2stage2');
            }

            else {
                addClass(box2, 'box2stage2');
            }



        }

    )

    });

}

非常感谢任何帮助! http://jsfiddle.net/negativebyte/BE4BJ/1/

1 个答案:

答案 0 :(得分:0)

我在你的帖子里玩了最后一个小提琴,把它和我的一些样板代码结合起来。它将允许任意特定类的任意数量的框,并且在打开新类时将关闭具有相同类的任何框。

我注意到你的css对于box1stage2和box2stage2是相同的 - 除非你希望能够专门定位项目,你可以使用一个boxStage2类 - 但是,这将删除控制哪些框属于组的能力和最终它会影响同时打开的盒子的数量。在我的演示中,您可以从每个box1和box2一次打开1。尝试打开第3个框将关闭具有已打开的同一个类的框。 此外,请注意,为了方便起见,我已经评论了绝对定位 - 我不想制定更多的css规则来定位和定位额外的盒子。 我还删掉了你的一些代码,发现它过于冗长而且不清楚。特别注意我使用forEachNode函数 - 它基本上为你提供了nodeLists上的每个功能 - 而不仅仅是数组。也许这是个人偏好,也许它比这更有价值,你不得不问别人。

<强>代码:

<!DOCTYPE html>
<html>
<head>
<script>
/////////////////////////////////////////////////////////////
////    U n u s e d   i n   t h i s   s a m p l e
/////////////////////////////////////////////////////////////
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}

/////////////////////////////////////////////////////////////
////    R e q u i r e d   b y   t h i s   s a m p l e
/////////////////////////////////////////////////////////////
function toggleClass(element, newStr)
{
    var index=element.className.indexOf(newStr);
    if ( index == -1)
        element.className += ' '+newStr;
    else
    {
        if (index != 0)
            newStr = ' '+newStr;
        element.className = element.className.replace(newStr, '');
    }
}
function forEachNode(nodeList, func)
{
    var i, n = nodeList.length;
    for (i=0; i<n; i++)
    {
        func(nodeList[i], i, nodeList);
    }
}

window.addEventListener('load', mInit, false);

function mInit()
{
    // Boxes Functions
    if ( 'querySelector' in document && 'addEventListener' in window ) 
    {
        var box1Items = document.querySelectorAll('.box1');
        var box2Items = document.querySelectorAll('.box2');
        forEachNode(box1Items, addBox1EvtListeners);
        forEachNode(box2Items, addBox2EvtListeners);
    }

    function addBox1EvtListeners(elem, index, list)
    {
        elem.addEventListener('click', onBox1_click, false);
    }

    function addBox2EvtListeners(elem, index, list)
    {
        elem.addEventListener('click', onBox2_click, false);
    }
}

var hasClass = function (elem, className) {
    return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
}

var addClass = function (elem, className) {
    if (!hasClass(elem, className)) {
        elem.className += ' ' + className;
    }
}

var removeClass = function (elem, className) {
    var newClass = ' ' + elem.className.replace( /[\t\r\n]/g, ' ') + ' ';
    if (hasClass(elem, className)) {
        while (newClass.indexOf(' ' + className + ' ') >= 0 ) {
            newClass = newClass.replace(' ' + className + ' ', ' ');
        }
        elem.className = newClass.replace(/^\s+|\s+$/g, '');
    }
}

function onBox1_click(e)
{
    var box1Elems = document.getElementsByClassName('box1');
    var clickedBox = this;
    forEachNode(box1Elems, remClass1);
    toggleClass(this, 'box1stage2');
    function remClass1(elem, index, nodeList)
    {
        if (elem != clickedBox)
            removeClass(elem, 'box1stage2');
    }
}

function onBox2_click(e)
{
    var box2Elems = document.getElementsByClassName('box2');
    var clickedBox = this;
    forEachNode(box2Elems, remClass2);
    toggleClass(this, 'box2stage2');
    function remClass2(elem, index, nodeList)
    {
        if (elem != clickedBox)
            removeClass(elem, 'box2stage2');
    }
}

</script>
<style>
.page {
    position:relative;
    top:0px;
    left:0px;
    width:580px;
    height:500px;
    background:#CCCCCC;
}

.box1 {
/*
    position:absolute;
    top:250px;
    left:85px;
*/
    width:40px;
    height:40px;
    border-radius:5px;
    background:rgba(0,0,0,0.5);
    -webkit-transition: All 0.4s ease;
}

.box1stage2 {
    width:200px;
    height:100px;
    background:rgba(0,0,0,0.85);
    -webkit-transition: All 0.4s ease;
}

.box2 {
/*
    position:absolute;
    top:200px;
    left:230px;
*/ 
 width:40px;
    height:40px;
    border-radius:5px;
    background:rgba(0,0,0,0.5);
    -webkit-transition: All 0.4s ease;
}

.box2stage2 {
    width:200px;
    height:100px;
    background:rgba(0,0,0,0.85);
    -webkit-transition: All 0.4s ease;
}
</style>
</head>
<body>
<div class="page">
    <div class="box1">
    </div>

    <div class="box2">
    </div>

    <div class="box1">
    </div>

    <div class="box2">
    </div>
</div>
</body>
</html>