微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 CSS/JavaScript 实现双击控件

如何解决使用 CSS/JavaScript 实现双击控件

我正在尝试实现一个双击控件,该控件在第一次单击时显示操作,并允许在可选的第二次单击时启动该操作。这部分很简单,我已经完成了(见下面的代码)。照原样,第一次点击后第一个动作被删除,第二个动作被附加。但是,如果用户不想在第一个操作后继续,我希望小部件恢复到初始状态,以便他们可以在稍后执行显示优先,第二操作的序列。我想不出一种优雅的方式来做到这一点。欢迎提出建议(甚至替代的实施方式)。

const first = (e) => {
    e.stopImmediatePropagation()
    e.target.removeEventListener('click',first)
    e.target.addEventListener('click',second)
}

const second = (e) => {
    console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`)
}

const btns = document.querySelectorAll('.semafore')

btns.forEach(b => { b.addEventListener('click',first) })
.semafores { display: block; width: auto; height: 40px; }
.r { background: red; }
.g { background: green; }
.b { background: blue; }

.semafore {
    float: left;
    width: 30px;
    height: 30px;
    border: 1px solid black;
    border-radius: 15px;
    display: block;
    text-align: center;
    font-family: sans-serif;
    color: white;
    transition: width 0.5s ease-in-out,color 0.2s;
}
.semafore.r:focus,.semafore.g:focus,.semafore.b:focus { width: auto; padding: 0 10px; }
.semafore.r:focus::after,.semafore.g:focus::after,.semafore.b:focus::after { content: attr(data-val); }
<div class="semafores">
    <button id="1r" data-val='remove' class="r semafore"></button>
    <button id="1g" data-val='change' class="g semafore"></button>
    <button id="1b" data-val='report' class="b semafore"></button>
</div>

<div class="semafores">
    <button id="2r" data-val='remove' class="r semafore"></button>
    <button id="2g" data-val='change' class="g semafore"></button>
    <button id="2b" data-val='report' class="b semafore"></button>
</div>

解决方法

这样弄怎么样?我们可以用状态创建一个,而不是两个事件:

const event = (e) => {
    e.stopImmediatePropagation()
    var state = e.target.dataset['state']
    if(state === 'first') {
      e.target.dataset['state'] = 'second'
      first(e)
    } else {
      second(e)
    }
}

const first = (e) => {
    console.log(`first ${e.target.getAttribute('data-val')} ${e.target.id}`)
}

const second = (e) => {
    console.log(`second ${e.target.getAttribute('data-val')} ${e.target.id}`)
}

const btns = document.querySelectorAll('.semafore')

btns.forEach(b => { b.addEventListener('click',event) })
.semafores { display: block; width: auto; height: 40px; }
.r { background: red; }
.g { background: green; }
.b { background: blue; }

.semafore {
    float: left;
    width: 30px;
    height: 30px;
    border: 1px solid black;
    border-radius: 15px;
    display: block;
    text-align: center;
    font-family: sans-serif;
    color: white;
    transition: width 0.5s ease-in-out,color 0.2s;
}
.semafore.r:focus,.semafore.g:focus,.semafore.b:focus { width: auto; padding: 0 10px; }
.semafore.r:focus::after,.semafore.g:focus::after,.semafore.b:focus::after { content: attr(data-val); }
<div class="semafores">
<button id="1r" data-state="first" data-val='remove' class="r semafore"></button>
<button id="1g" data-state="first" data-val='change' class="g semafore"></button>
<button id="1b" data-state="first" data-val='report' class="b semafore"></button>
</div>

<div class="semafores">
<button id="2r" data-state="first" data-val='remove' class="r semafore"></button>
<button id="2g" data-state="first" data-val='change' class="g semafore"></button>
<button id="2b" data-state="first" data-val='report' class="b semafore"></button>
</div>

,

您可以使用 reset() 函数。


使用两个不同的事件侦听器:

就像你的例子

const reset = () => {
    btns.forEach(btn => {
        btn.removeEventListener('click',second);
        btn.addEventListener('click',first);
    });
};

您可以在更改 first() 中的事件侦听器之前或在 console.log() 中的 second() 之前调用它,

const first = (e) => {
    e.stopImmediatePropagation();
    reset();
    e.target.removeEventListener('click',first);
    e.target.addEventListener('click',second);
};

const second = (e) => {
    e.stopImmediatePropagation();
    reset();
    console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`);
};

或者如果您在 button.semafore 之外点击。

document.addEventListener('click',reset);

工作示例:

const btns = document.querySelectorAll('.semafore');

const reset = () => {
    btns.forEach(btn => {
        btn.removeEventListener('click',first);
    });
};

const first = (e) => {
    e.stopImmediatePropagation();
    reset();
    e.target.removeEventListener('click',second);
};

const second = (e) => {
    e.stopImmediatePropagation();
    reset();
    console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`);
};

btns.forEach(b => { b.addEventListener('click',first); });

document.addEventListener('click',reset);
.semafores { display: block; width: auto; height: 40px; }

.r { background: red; }
.g { background: green; }
.b { background: blue; }

.semafore {
    float: left;
    width: 30px;
    height: 30px;
    border: 1px solid black;
    border-radius: 15px;
    display: block;
    text-align: center;
    font-family: sans-serif;
    color: white;
    transition: width 0.5s ease-in-out,color 0.2s;
}

.semafore.r:focus,.semafore.b:focus { width: auto; padding: 0 10px; }

.semafore.r:focus::after,.semafore.b:focus::after { content: attr(data-val); }
<div class="semafores">
    <button id="1r" data-val='remove' class="r semafore"></button>
    <button id="1g" data-val='change' class="g semafore"></button>
    <button id="1b" data-val='report' class="b semafore"></button>
</div>

<div class="semafores">
    <button id="2r" data-val='remove' class="r semafore"></button>
    <button id="2g" data-val='change' class="g semafore"></button>
    <button id="2b" data-val='report' class="b semafore"></button>
</div>


有数据属性:

const reset = () => {
    const active_btn = document.querySelector('[data-active="true"]');
    if (active_btn) {
        active_btn.dataset.active = 'false';
    }
};

您可以在一个处理程序中处理两次点击:

const handleClick = (e) => {
    e.stopImmediatePropagation();
    if (e.target.dataset.active == 'true') {
        reset();
        console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`);
    }
    else { 
        reset();
        e.target.dataset.active = 'true';
    }
};

工作示例:

const btns = document.querySelectorAll('.semafore');

const reset = () => {
    const active_btn = document.querySelector('[data-active="true"]');
    if (active_btn) {
        active_btn.dataset.active = 'false';
    }
};

const handleClick = (e) => {
    e.stopImmediatePropagation();
    if (e.target.dataset.active == 'true') {
        reset();
        console.log(`${e.target.getAttribute('data-val')} ${e.target.id}`);
    }
    else { 
        reset();
        e.target.dataset.active = 'true';
    }
};

btns.forEach(b => { b.addEventListener('click',handleClick); });

document.addEventListener('click',.semafore.b:focus::after { content: attr(data-val); }
<div class="semafores">
    <button id="1r" data-val='remove' data-active="false" class="r semafore"></button>
    <button id="1g" data-val='change' data-active="false" class="g semafore"></button>
    <button id="1b" data-val='report' data-active="false" class="b semafore"></button>
</div>

<div class="semafores">
    <button id="2r" data-val='remove' data-active="false" class="r semafore"></button>
    <button id="2g" data-val='change' data-active="false" class="g semafore"></button>
    <button id="2b" data-val='report' data-active="false" class="b semafore"></button>
</div>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。