Reputation: 3628
I am currently creating a codepen, where you can change the color,background-color,text,... of each element on the page when opening the contextmenu.
I store the element, which I right-clicked in a variable:
var x = event.clientX, y = event.clientY,
efp = document.elementFromPoint(x, y);
When I return the value of that variable efp
in the console, it returns me the correct element.
Now the problem:
Changing the color of, for example a text element, works fine. But when I try to do that another time, it not only changes the element, but the element I previously changed aswell.
Something like this:
Change color of p
-> changes p
Change background of section
-> changes section
AND p
Change color of h1
-> changes h1
AND section
AND p
And here's my full code:
$(document).on("contextmenu", function(e){
$('.custom-menu li').show(0);
e.preventDefault();
var el = e.target.nodeName;
var x = event.clientX, y = event.clientY,
efp = document.elementFromPoint(x, y);
console.log(efp);
switch(el){
case "P":
ctxP();
break;
case "CONTENT":
ctxCon();
break;
case "HEADER":
ctxHead();
break;
case "FOOTER":
ctxFoot();
break;
}
$(".custom-menu li").on("click", function(){
switch($(this).attr("data-action")) {
case "color":
colorPick();
break;
case "bgcolor":
bgcolorPick();
break;
case "text":
textChange();
break;
}
$(".custom-menu").fadeOut(100);
});
$(".custom-menu").finish().fadeIn(100).css({
top: e.pageY + "px",
left: e.pageX + "px"
});
function ctxP(){
$('.custom-menu li[data-action=bgcolor]').hide();
}
function ctxCon(){
$('.custom-menu li[data-action=color]').hide();
$('.custom-menu li[data-action=text]').hide();
}
function ctxHead(){
$('.custom-menu li[data-action=color]').hide();
$('.custom-menu li[data-action=text]').hide();
}
function ctxFoot(){
$('.custom-menu li[data-action=color]').hide();
$('.custom-menu li[data-action=text]').hide();
}
function colorPick(){
$(".overlay").fadeIn();
$(".colorpicker").fadeIn().css('display', 'flex');
$(".color").click(function(){
var color = $(this).css('background-color');
$(efp).css('color', color);
$(".colorpicker, .overlay").fadeOut();
});
}
function bgcolorPick(){
$(".overlay").fadeIn();
$(".colorpicker").fadeIn().css('display', 'flex');
$(".color").click(function(){
var color = $(this).css('background-color');
$(efp).css('background-color', color);
$(".colorpicker, .overlay").fadeOut();
});
}
function textChange(){
$(".overlay, .textChange").fadeIn();
$('.textChange input').keypress(function(e) {
var text = $(this).val();
if(e.keyCode == 13){
$(efp).text(text);
$(".overlay, .textChange").fadeOut();
$(this).val("");
}
});
}
});
$(document).click(function(e){
if (!$(e.target).parents(".custom-menu").length > 0) {
$(".custom-menu").fadeOut(100);
}
});
*{
margin:0;
padding:0;
box-sizing:border-box;
}
header,content,footer{
display:block;
width:100%;
height:200px;
padding:50px 20%;
}
header{
background:#efefef;
}
content{
background-color:#cccccc;
}
footer{
background-color:#afafaf
}
.custom-menu {
display: none;
z-index: 1000;
position: absolute;
overflow: hidden;
border: 1px solid #CCC;
white-space: nowrap;
background: #FFF;
color: #333;
}
.custom-menu li {
padding: 8px 12px;
cursor: pointer;
list-style-type: none;
transition: all .3s ease;
user-select: none;
}
.custom-menu li:hover {
background-color: #DEF;
}
.colorpicker{
position:fixed;
z-index:20;
display:flex;
display:none;
flex-wrap:wrap;
top:10%;
left:10%;
height:80%;
width:80%;
background-color:white;
-webkit-box-shadow: 0px 0px 15px 0px rgba(0,0,0,0.5);
-moz-box-shadow: 0px 0px 15px 0px rgba(0,0,0,0.5);
box-shadow: 0px 0px 15px 0px rgba(0,0,0,0.5);
}
.color{
display:block;
flex-grow:1;
transition:.5s ease-in-out;
cursor:pointer;
}
.textChange{
display:none;
position:fixed;
z-index:20;
top:calc(50% - 25px);
width:20%;
height:50px;
left:40%;
}
.textChange input{
height:100%;
width:100%;
padding:10px;
font-size:1.1em;
}
.overlay{
display:none;
position:fixed;
z-index:10;
width:100%;
background-color:black;
height:100%;
opacity:.5;
top:0;
}
.disabled{
pointer-events:none;
color:#a3a3a3;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<header><p>Hello</p></header>
<content><p>Peter</p></content>
<footer><p>Hallo</p></footer>
</div>
<div class="overlay"></div>
<div class="textChange">
<input type="textarea" placeholder="Type new text in here">
</div>
<div class="colorpicker">
<div class="color" style="background-color:#1abc9c"></div>
<div class="color" style="background-color:#16a085"></div>
<div class="color" style="background-color:#2ecc71"></div>
<div class="color" style="background-color:#27ae60"></div>
<div class="color" style="background-color:#3498db"></div>
<div class="color" style="background-color:#2980b9"></div>
<div class="color" style="background-color:#9b59b6"></div>
<div class="color" style="background-color:#8e44ad"></div>
<div class="color" style="background-color:#e74c3c"></div>
<div class="color" style="background-color:#c0392b"></div>
<div class="color" style="background-color:#e67e22"></div>
<div class="color" style="background-color:#d35400"></div>
<div class="color" style="background-color:#f1c40f"></div>
<div class="color" style="background-color:#f39c12"></div>
<div class="color" style="background-color:#ecf0f1"></div>
<div class="color" style="background-color:#bdc3c7"></div>
<div class="color" style="background-color:#95a5a6"></div>
<div class="color" style="background-color:#7f8c8d"></div>
<div class="color" style="background-color:#34495e"></div>
<div class="color" style="background-color:#2c3e50"></div>
</div>
<ul class='custom-menu'>
<li data-action="color">change color</li>
<li data-action="bgcolor">change background-color</li>
<li data-action="text">change text</li>
</ul>
Upvotes: 1
Views: 62
Reputation: 5323
You're creating a closure and attaching a new click
listener on every right click within the on('contextmenu'
event listener, hence this behavior. Simply move all of your declarations out of the event listener like this :
function ctxP() {
$('.custom-menu li[data-action=bgcolor]').hide();
}
function ctxCon() {
$('.custom-menu li[data-action=color]').hide();
$('.custom-menu li[data-action=text]').hide();
}
function ctxHead() {
$('.custom-menu li[data-action=color]').hide();
$('.custom-menu li[data-action=text]').hide();
}
function ctxFoot() {
$('.custom-menu li[data-action=color]').hide();
$('.custom-menu li[data-action=text]').hide();
}
function colorPick() {
$(".overlay").fadeIn();
$(".colorpicker").fadeIn().css('display', 'flex');
$(".color").click(function() {
var color = $(this).css('background-color');
$(efp).css('color', color);
$(".colorpicker, .overlay").fadeOut();
});
}
function bgcolorPick() {
$(".overlay").fadeIn();
$(".colorpicker").fadeIn().css('display', 'flex');
$(".color").click(function() {
var color = $(this).css('background-color');
$(efp).css('background-color', color);
$(".colorpicker, .overlay").fadeOut();
});
}
function textChange() {
$(".overlay, .textChange").fadeIn();
$('.textChange input').keypress(function(e) {
var text = $(this).val();
if (e.keyCode == 13) {
$(emo).text(text);
$(".overlay, .textChange").fadeOut();
$(this).val("");
}
});
}
$(".custom-menu li").on("click", function() {
switch ($(this).attr("data-action")) {
case "color":
colorPick();
break;
case "bgcolor":
bgcolorPick();
break;
case "text":
textChange();
break;
}
$(".custom-menu").fadeOut(100);
});
var efp;
$(document).on("contextmenu", function(e) {
e.preventDefault();
$('.custom-menu li').show(0);
var el = e.target.nodeName,
x = e.clientX,
y = e.clientY;
efp = document.elementFromPoint(x, y);
$(".custom-menu").finish().fadeIn(100).css({
top: e.pageY + "px",
left: e.pageX + "px"
});
switch (el) {
case "P":
ctxP();
break;
case "CONTENT":
ctxCon();
break;
case "HEADER":
ctxHead();
break;
case "FOOTER":
ctxFoot();
break;
}
});
$(document).click(function(e) {
if (!$(e.target).parents(".custom-menu").length > 0) {
$(".custom-menu").fadeOut(100);
}
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
header,
content,
footer {
display: block;
width: 100%;
height: 200px;
padding: 50px 20%;
}
header {
background: #efefef;
}
content {
background-color: #cccccc;
}
footer {
background-color: #afafaf
}
.custom-menu {
display: none;
z-index: 1000;
position: absolute;
overflow: hidden;
border: 1px solid #CCC;
white-space: nowrap;
background: #FFF;
color: #333;
}
.custom-menu li {
padding: 8px 12px;
cursor: pointer;
list-style-type: none;
transition: all .3s ease;
user-select: none;
}
.custom-menu li:hover {
background-color: #DEF;
}
.colorpicker {
position: fixed;
z-index: 20;
display: flex;
display: none;
flex-wrap: wrap;
top: 10%;
left: 10%;
height: 80%;
width: 80%;
background-color: white;
-webkit-box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.5);
-moz-box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.5);
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.5);
}
.color {
display: block;
flex-grow: 1;
transition: .5s ease-in-out;
cursor: pointer;
}
.textChange {
display: none;
position: fixed;
z-index: 20;
top: calc(50% - 25px);
width: 20%;
height: 50px;
left: 40%;
}
.textChange input {
height: 100%;
width: 100%;
padding: 10px;
font-size: 1.1em;
}
.overlay {
display: none;
position: fixed;
z-index: 10;
width: 100%;
background-color: black;
height: 100%;
opacity: .5;
top: 0;
}
.disabled {
pointer-events: none;
color: #a3a3a3;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<header>
<p>Hello</p>
</header>
<content>
<p>Peter</p>
</content>
<footer>
<p>Hallo</p>
</footer>
</div>
<div class="overlay"></div>
<div class="textChange">
<input type="textarea" placeholder="Type new text in here">
</div>
<div class="colorpicker">
<div class="color" style="background-color:#1abc9c"></div>
<div class="color" style="background-color:#16a085"></div>
<div class="color" style="background-color:#2ecc71"></div>
<div class="color" style="background-color:#27ae60"></div>
<div class="color" style="background-color:#3498db"></div>
<div class="color" style="background-color:#2980b9"></div>
<div class="color" style="background-color:#9b59b6"></div>
<div class="color" style="background-color:#8e44ad"></div>
<div class="color" style="background-color:#e74c3c"></div>
<div class="color" style="background-color:#c0392b"></div>
<div class="color" style="background-color:#e67e22"></div>
<div class="color" style="background-color:#d35400"></div>
<div class="color" style="background-color:#f1c40f"></div>
<div class="color" style="background-color:#f39c12"></div>
<div class="color" style="background-color:#ecf0f1"></div>
<div class="color" style="background-color:#bdc3c7"></div>
<div class="color" style="background-color:#95a5a6"></div>
<div class="color" style="background-color:#7f8c8d"></div>
<div class="color" style="background-color:#34495e"></div>
<div class="color" style="background-color:#2c3e50"></div>
</div>
<ul class='custom-menu'>
<li data-action="color">change color</li>
<li data-action="bgcolor">change background-color</li>
<li data-action="text">change text</li>
</ul>
Upvotes: 4
Reputation: 26360
It is because of this line :
$(".color").click( function(){
Every time the bgcolorPick()
function is called, you attach one more click handler. So every time you click, all your click handlers execute on all the elements previously clicked, changing their colour. Detach the click handler before attaching it again to the latest clicked element :
$(".color").off("click").on("click", function(){
Upvotes: 5