How to I remove all the child element except the first element? - javascript

It is a BlackJack game. I have a container which the first child element is a template for cloning card purpose. How to I remove all the child elements except the first element? I think the current code which is the "clearContainer" method remove all child elements.
function makeCardPlayer() {
// .card is created in the template card css class
var card = $(".card.templatePlayer").clone();
//card.removeClass("templatePlayer");
card.addClass("newCard");
$("#cardContainerPlayer").append(card);
}
function clearContainer() {
debugger
//$("cardContainerPlayer > *").slice(1).remove();
var myNode = document.getElementById("cardContainerPlayer");
var fc = myNode.firstChild;
var sib = fc && fc.nextSibling;
while (myNode.lastChild && myNode.lastChild !== sib) {
myNode.removeChild(myNode.lastChild);
}
}
makeCardPlayer();
clearContainer();
#cardContainerPlayer {
display: flex;
flex-wrap: wrap;
}
.card {
display: inline-block;
vertical-align: top;
text-align: center;
margin: 5px;
padding: 10px;
width: 70px;
height: 100px;
font-size: 26px;
background-color: black;
border: solid 1px black;
color: white;
border-radius: 10px;
}
.newCard {
display: inline-block;
vertical-align: top;
text-align: center;
margin: 5px;
padding: 10px;
width: 70px;
height: 100px;
font-size: 26px;
background-color: yellow;
border: solid 1px black;
color: white;
border-radius: 10px;
}
.templatePlayer {
/*display: none;*/
}
<!DOCTYPE html>
<html>
<body>
<div id="cardContainerPlayer">
<div class="card templatePlayer">
<span class="playerCardFace"></span>
<span class="playerCardSuit"></span>
</div>
</div>
</body>
</html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Here are the code which I have removed out extra codes for brevity.

YOu seem to be avoiding jQuery in clearContainer. If you want to use it that function, then
function clearContainer() {
$("#cardContainerPlayer > *").slice(1).remove();
}
That selects all child elements of the container and uses slice to get a set of only the ones after the first one, then removes them.
If you want to use the DOM directly:
function clearContainer() {
var myNode = document.getElementById("cardContainerPlayer");
var fc = myNode.firstChild;
var sib = fc && fc.nextSibling;
while (myNode.lastChild && myNode.lastChild !== sib) {
myNode.removeChild(myNode.lastChild);
}
}
Or you might use firstElementChild, nextElementSibling, and lastElementChild, depending on what you want to do and whether you need to handle text nodes in there. More on those various properties in MDN's DOM documentation.

You should use the nextSibling() method to find and delete every sibling of the 1st child :
function clearContainer() {
debugger
var myNode = document.getElementById("cardContainerPlayer");
var fc = myNode.firstChild;
while (fc.nextSibling) {
myNode.removeChild(fc.nextSibling);
}
}

In your clearContainer() method, you can use something like this
function clearContainer() {
debugger
var myNode = document.getElementById("cardContainerPlayer");
var fc = myNode.firstChild;
while (fc.nextSibling) {
myNode.removeChild(fc.nextSibling);
}
}
By removing the next sibling of the child, at the end you will be left just with the firstChild.

Related

Is the child element visible in the parent

I am making a comment system, there is a certain block in which there are others (messages) how, when scrolling through these messages, to find out whether the user sees one particular one (for example, with the identifier x) or not,
HTML:
<div class="parent">
<div class="msg" id="a"></div>
<div class="msg" id="b"></div>
<div class="msg" id="c"></div>
<div class="msg" id="x"></div>
</div>
CSS:
.parent {
width: 100%;
height: 100%;
height: 89%;
overflow: scroll;
padding-top: 10px;
padding-bottom: 70px;
}
.msg {
width: 98%;
height: 500px;
padding: 10px;
position: relative;
margin: 0 auto;
border: 2px hsl(174deg 72% 41%) solid;
color: hsl(174deg 72% 41%);
border-radius: 20px
px
;
margin-top: 10px;
}
JS:
document.querySelector(".parent").onscroll = () => {
//what to write here?
}
That is: if the message has become visible in the general block, then paint it in yellow
I tried different options: getComputedStyle, and getBoundingClientRect, and offset, but none of this helped me, they constantly say that the message is visible
BUT:
getBoundingClientRect doesn't work, I don't need to check if it's visible in the whole window, I need to check if it's ONLY visible in a div element
WHEN SCROLLING A PARENT ELEMENT
As suggested in the comments by other user, what you are looking for is the Intersection Observer API
https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
Here's a demo trying to apply the concept to your scenario. It's not very well factored but clearly shows a document containing both your .msg container (.parent) styled as overflow-y: scroll; and other elements before and after taking space on the viewport.
All .msg elements will be observed for intersection in the visible space of their parent so that every time each one of them will be visible, its id will be printed on console. Plus there's an added trigger callback that will be invoked in the event described above, that will check for a condition (for example if the element currently became visible has id == 'c') to perform an action.
//this will be called everytime a target element being observer became visible,
//and will check a condition before performing an action (if the element.id === c for example)
const trigger = (element)=>{
if (element.id === 'c')
console.log('condition met! element with id == c was reached.');
}
const observerOptions = {
root: null,
rootMargin: '0px',
threshold: 0
};
//gets called everytime any of the targets appears on the viewport
const observerCallback = (entries, observer) => {
//for each of the observed entries
entries.forEach(entry => {
//console logs the element id currently intersecting the viewport
if (entry.isIntersecting){
console.log(entry.target.id);
trigger(entry.target);
}
});
};
//sets up an observer...
//calling the observerCallback when the observed targets will be intersecting the viewport
const observer = new IntersectionObserver(observerCallback, observerOptions);
//the targets the observer will be observing for (each .msg children inside the .parent element)
const observerTargets = document.querySelectorAll('.parent > .msg');
observerTargets.forEach(target => observer.observe(target));
.other-content{
display: block;
outline: dashed 3px gray;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
font-family: arial;
color: gray;
}
.parent {
display: block;
margin: 10px 10px;
height: 120px;
overflow-y: scroll;
outline: solid 1px gray;
}
.msg {
position: relative;
display: block;
width: 100%;
height: 200px;
padding: 0;
margin: 10px 0;
box-sizing: border-box;
border: solid 2px hsl(174deg 72% 41%);
border-radius: 10px;
}
.msg::before {
position: absolute;
content: 'id: ' attr(id);
top: 50%;
left: 50%;
border-radius: 1rem;
padding: 1rem 1rem;
background: gray;
font-size: 2rem;
font-weight: 600;
color: white;
}
<div class="other-content">
before..
</div>
<div class="parent">
<div class="msg" id="a"></div>
<div class="msg" id="b"></div>
<div class="msg" id="c"></div>
<div class="msg" id="x"></div>
</div>
<div class="other-content">
..after
</div>

When to Call JavaScript Toggle Function?

I have a drop down menu I need to make appear and disappear using pure JavaScript (no libraries/jQuery). Thus I am developing a toggle function. However despite trying several approaches, nothing seems to work. My current idea is to create a variable to hold the state of the menu (open or closed). Once the display of the menu changes from "none" to "block", the variable should change from "closed" to "open". Then an event listener would be added to the body element so when anything is clicked, the menu closes (i.e. the display property is changed back to "none").
Unfortunately the above doesn't seem work. When I put the If/else block outside of an event listener it fires when the page loads, but not when the menuToggle variable changes. If I put it or a function inside the menuPlaceholder event listener the menu won't open, probably due to the open and close code being called basically at the same time.
Clearly I am missing something, probably related to program control or function calling. Does anyone have any insights?
The code I am working with is below. Note the alert functions peppered throughout the code are for testing purposes only.
//Puts IDs for search preference selection box into variables
var menuPlaceholder = document.getElementById('searchSelection');
var menuDisplay = document.getElementById('searchOptions');
var boxLabel = document.getElementById('searchLabel');
//Puts IDs for text input box and submission into variables
var searchBoxPlaceholder = document.getElementById('searchInput');
var searchInput = document.getElementById('searchBox');
var submitButton = document.getElementById('submit');
//Adds class to each search option and puts ID of hidde field into variable
var searchPrefSubmission = document.getElementsByClassName('buttonSearch');
var hiddenInput = document.getElementById('searchChoice');
//Global variable to indicate whether searchOptions menu is opened or closed
var menuToggle = "closed";
//Closes element when one clicks outside of it.
function hideOnClickOutside(element) {
const outsideClickListener = event => {
if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
element.style.display = 'none'
removeClickListener()
}
}
const removeClickListener = () => {
document.removeEventListener('click', outsideClickListener)
}
document.addEventListener('click', outsideClickListener)
}
const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length )
//When the placeholder box is clicked, the option menu appears
menuPlaceholder.addEventListener('click', function (event){
menuDisplay.style.display = "block";
menuToggle = "open";
//Add click event to searchPref buttons
for (i = 0; i < searchPrefSubmission.length; i++) {
//Assigns value of the button to both the hidden input field and the placeholder box
searchPrefSubmission[i].addEventListener('click', function(event) {
hiddenInput.value=this.value;
boxLabel.innerHTML = this.value;
menuDisplay.style.display = "none";
menuPlaceholder.style.display = "inline-block";
});
}
});
//This code causes the text input box of the search form to appear when the background box is clicked
searchBoxPlaceholder.addEventListener('click', function(event){
searchInput.style.display = "inline";
submitButton.style.display = "inline";
//hideOnClickOutside(menuDisplay);
});
if (menuToggle == "open"){
document.body.addEventListener('click', function(event){
alert('Foo!');
})
}else{
alert('Boo!');
}
/*function toggleMenu () {
//menuDisplay.style.display = "none";
alert('Boo!');
menuToggle = "closed";
}*/
body {
font-family:Montserrat, sans-serif;
}
#searchOptionPlaceholder {
display: inline-block;
}
#searchSelection {
padding: 10px 20px;
margin-right: 10px;
background-color: #F0F3F5;
display: inline-block;
color: #000000;
width: 140px;
max-width: 200px;
max-height: 35px;
border: 2px solid black;
vertical-align: middle;
}
#searchSelection img {
float: right;
}
#searchLabel {
display: inline-block;
padding-top: 10px;
vertical-align: top;
}
#searchOptions {
display: none;
background-color: #F0F3F5;
position: absolute;
z-index: 2;
}
#searchOptions ul {
background-color: #F0F3F5;
padding: 5px;
}
#searchOptions li {
list-style-type: none;
border-bottom: 2px solid black;
}
#searchOptions li:hover {
background-color: #706868;
color: #ffffff;
}
.buttonSearch {
background-color: transparent;
border: none;
padding: 10px;
font-size: 14px;
}
.searchSubHeading {
font-size: 12px;
}
#searchInput {
display: inline-block;
background-color: #F0F3F5;
padding: 10px 100px;
position: relative;
top: 0px;
max-width: 350px;
border: 2px solid black;
vertical-align: middle;
}
#searchInput img {
position: relative;
left: 80px;
}
#searchBox {
display: none;
width: 80%;
background-color: #F0F3F5;
border: none;
font-size: 1.5em;
position: relative;
right: 50px;
vertical-align: middle;
}
#submit {
border: none;
background-image: url('https://library.domains.skidmore.edu/search/magnifyingGlass.png');
background-repeat: no-repeat;
background-size: contain;
width: 50px;
height: 30px;
position: relative;
right: -80px;
vertical-align: middle;
}
#otherLinks {
margin-top: 10px;
}
#otherLinks a{
color: #000000;
}
#otherLinks a:hover{
color: #006a52;
}
<h1>Library Search</h1>
<form method="post" action="https://library.domains.skidmore.edu/search/searchBox.php" id="librarySearch">
<div id="searchSelection"><span id="searchLabel">Catalog</span><img src="down.png" height="30px" width="30px" /></div>
<div id="searchOptions">
<ul>
<li><button type="button" name="searchPref" value="Catalog" class="buttonSearch">Catalog<br /><br /><span class="searchSubHeading">Search books and DVDs</span></button></li>
<li><button type="button" name="searchPref" value="SearchMore" class="buttonSearch">SearchMore<br /><br /><span class="searchSubHeading">Search everything</span></button></li>
<li><button type="button" name="searchPref" value="Journals" class="buttonSearch">Journals<br /><br /><span class="searchSubHeading">Search journals</span></button></li>
</ul>
</div>
<div id="searchInput">
<input type="hidden" id="searchChoice" name="searchPref" value="catalog" />
<input type="search" id="searchBox" size="60" name="searchText" placeholder="Search our holdings"/><button type="submit" id="submit"></button></div>
<div id="otherLinks">Advanced Catalog Search | WorldCat | eBooks</div>
</form>
Some issues:
Adding event listeners within an event listener is in most cases a code smell: this will add those inner listeners each time the outer event is triggered. Those listeners remain attached, and so they accumulate. So, attach all event handlers in the top-level script, i.e. on page load, and then never again.
The if ... else at the end will execute on page load, and then never again. So the value of menuToggle is guaranteed to be "closed". You need to put that if...else switch inside the handler, so that it executes every time the event triggers, at which time the menuToggle variable will possibly have a modified value.
The body element does not stretch (by default) over the whole window. If you want to detect a click anywhere on the page, you should attach the listener on the document element itself, not on document.body.
When the click on the menu placeholder is handled, you should avoid that this event "bubbles" up the DOM tree up to the document, because there you have the other handler that wants to hide the menu again. You can do this with event.stopPropagation().
The global variable is not absolutely necessary, but if you use it, then I would call it menuVisible and give it a boolean value: false at first, and possibly true later.
For actually toggling the menu, I would create a function, which takes the desired visibility (false or true) as argument, and then performs the toggle.
Do not use undeclared variables, like the for loop variable i. Define it with let.
Here is your code with those changes implemented. Of course, there is still a lot that could be improved, but I believe that goes beyond the scope of this question:
var menuPlaceholder = document.getElementById('searchSelection');
var menuDisplay = document.getElementById('searchOptions');
var boxLabel = document.getElementById('searchLabel');
var searchBoxPlaceholder = document.getElementById('searchInput');
var searchInput = document.getElementById('searchBox');
var submitButton = document.getElementById('submit');
var searchPrefSubmission = document.getElementsByClassName('buttonSearch');
var hiddenInput = document.getElementById('searchChoice');
// Changed name and type of global variable:
var menuVisible = false;
// Removed some functions ...
menuPlaceholder.addEventListener('click', function (event){
// Use new function for actually setting the visibility
toggleMenu(!menuVisible);
// Avoid that click event bubbles up to the document level
event.stopPropagation();
});
// Add these event handlers on page load, not within another handler
// Define loop variable with let
for (let i = 0; i < searchPrefSubmission.length; i++) {
//Assigns value of the button to both the hidden input field and the placeholder box
searchPrefSubmission[i].addEventListener('click', function(event) {
hiddenInput.value = this.value;
boxLabel.innerHTML = this.value;
// Use the new function for setting the visibility
toggleMenu(false);
menuPlaceholder.style.display = "inline-block";
});
}
searchBoxPlaceholder.addEventListener('click', function(event){
searchInput.style.display = "inline";
submitButton.style.display = "inline";
});
// Bind handler on document itself, and call new function
document.addEventListener('click', function(event) {
toggleMenu(false);
});
// new function to perform the toggle
function toggleMenu(show) {
menuDisplay.style.display = show ? "block" : "none";
menuVisible = show;
}
body {
font-family:Montserrat, sans-serif;
}
#searchOptionPlaceholder {
display: inline-block;
}
#searchSelection {
padding: 10px 20px;
margin-right: 10px;
background-color: #F0F3F5;
display: inline-block;
color: #000000;
width: 140px;
max-width: 200px;
max-height: 35px;
border: 2px solid black;
vertical-align: middle;
}
#searchSelection img {
float: right;
}
#searchLabel {
display: inline-block;
padding-top: 10px;
vertical-align: top;
}
#searchOptions {
display: none;
background-color: #F0F3F5;
position: absolute;
z-index: 2;
}
#searchOptions ul {
background-color: #F0F3F5;
padding: 5px;
}
#searchOptions li {
list-style-type: none;
border-bottom: 2px solid black;
}
#searchOptions li:hover {
background-color: #706868;
color: #ffffff;
}
.buttonSearch {
background-color: transparent;
border: none;
padding: 10px;
font-size: 14px;
}
.searchSubHeading {
font-size: 12px;
}
#searchInput {
display: inline-block;
background-color: #F0F3F5;
padding: 10px 100px;
position: relative;
top: 0px;
max-width: 350px;
border: 2px solid black;
vertical-align: middle;
}
#searchInput img {
position: relative;
left: 80px;
}
#searchBox {
display: none;
width: 80%;
background-color: #F0F3F5;
border: none;
font-size: 1.5em;
position: relative;
right: 50px;
vertical-align: middle;
}
#submit {
border: none;
background-image: url('https://library.domains.skidmore.edu/search/magnifyingGlass.png');
background-repeat: no-repeat;
background-size: contain;
width: 50px;
height: 30px;
position: relative;
right: -80px;
vertical-align: middle;
}
#otherLinks {
margin-top: 10px;
}
#otherLinks a{
color: #000000;
}
#otherLinks a:hover{
color: #006a52;
}
<h1>Library Search</h1>
<form method="post" action="https://library.domains.skidmore.edu/search/searchBox.php" id="librarySearch">
<div id="searchSelection">
<span id="searchLabel">Catalog</span>
<img src="down.png" height="30px" width="30px" />
</div>
<div id="searchOptions">
<ul>
<li>
<button type="button" name="searchPref" value="Catalog" class="buttonSearch">
Catalog<br /><br /><span class="searchSubHeading">Search books and DVDs</span>
</button>
</li>
<li>
<button type="button" name="searchPref" value="SearchMore" class="buttonSearch">
SearchMore<br /><br /><span class="searchSubHeading">Search everything</span>
</button>
</li>
<li>
<button type="button" name="searchPref" value="Journals" class="buttonSearch">
Journals<br /><br /><span class="searchSubHeading">Search journals</span>
</button>
</li>
</ul>
</div>
<div id="searchInput">
<input type="hidden" id="searchChoice" name="searchPref" value="catalog" />
<input type="search" id="searchBox" size="60" name="searchText" placeholder="Search our holdings"/>
<button type="submit" id="submit"></button>
</div>
<div id="otherLinks">
Advanced Catalog Search |
WorldCat |
eBooks
</div>
</form>

Reapplying style attributes after dynamically appending elements

On my page, if I change the attributes of an element such as
<div class="showInitially"></div>
by setting
$(".showInitially").hide()
then any elements added dynamically afterwards like
container.append("<div class='showInitially'>text</div>");
do not inherit the changes.
I know I can re-apply all the changes after I add another element but somehow this seems inefficient and hacky, especially if there are a number of changes to styles made. So, is there another way to add elements to the page that will automatically have the inherited style and attribute changes applied to them?
I've tried
container.trigger("create");
but this does nothing. An example is shown in the snippet below:
var container=$("#container");
var buttons = $("button")
var allDivs = $("#container .showInitially")
buttons.on("click", function(){
buttons.addClass("alt");
allDivs.addClass("alt");
allDivs.hide();
addButton();
})
function addButton(){
container.append("<div><button>Change another color</button></div> <div class='showInitially'>text</div>");
}
body {
background: #cccccc;
padding: 20px;
font-family: Helvetica;
}
button {
background: #0084ff;
border: none;
border-radius: 5px;
padding: 8px 14px;
font-size: 15px;
color: #fff;
}
div{
color:black;
}
.alt{
background: red;
}
.showInitially{
color:orange;
display:inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container" >
<button>Change color</button> <div class="showInitially">text</div>
</div>
Modify the CSS rule dynamically.
Blatantly ripped off from How do you read CSS rule values with JavaScript? and modify a css rule object with javascript and then cobbled together.
Part of the issue with your code was that your on click only attached the click handler to buttons that already existed. Any new button would not get a click handler, so I moved the handler to the document and added a selector.
var container=$("#container");
var buttons = $("button")
var allDivs = $("#container .showInitially")
$(document).on("click", "button", function(){
buttons.addClass("alt");
allDivs.addClass("alt");
modStyle('.showInitially', 'display', 'none');
//allDivs.hide();
addButton();
})
function addButton(){
container.append("<div><button>Change another color</button></div> <div class='showInitially'>text</div>");
}
function modStyle(className, foo, bar) {
var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules;
for (var x = 0; x < classes.length; x++) {
if (classes[x].selectorText == className) {
(classes[x].cssText) ? classes[x].style[foo] = bar : classes[x].style[foo] = bar;
}
}
}
body {
background: #cccccc;
padding: 20px;
font-family: Helvetica;
}
button {
background: #0084ff;
border: none;
border-radius: 5px;
padding: 8px 14px;
font-size: 15px;
color: #fff;
}
div{
color:black;
}
.alt{
background: red;
}
.showInitially{
color:orange;
display:inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container" >
<button>Change color</button> <div class="showInitially">text</div>
</div>

Why can I not remove the appended elements that has a class name call building-x?

For some reason I can not remove any of the building-x elements that JavaScript generates. So I'm wondering why?
So I change my code a bit and I ended up adding building-x to the HTML to see if that will do the trick and as soon as I did that, it removed the generated HTML version of building-x but I still can not remove the generated JavaScript version of building-x.
What would I have to do to also be able to remove the JavaScript generated version of building-x?
Here is my code
document.addEventListener('DOMContentLoaded',function(){
/*<Add another building>*/
document.querySelector('#add-another-building').addEventListener('click',addAnotherBuilding);
function addAnotherBuilding(){
if(document.querySelector(".building-x")){
document.querySelector(".building-x").insertAdjacentHTML("afterend","<div class='building-x'></div>");
}
else{
document.querySelector("#first-building").insertAdjacentHTML("afterend","<div class='building-x'></div>");
}
}
/*</Add another building>*/
/*<Remove the targeted buildingX>*/
if(document.querySelector('.building-x')){
var buildingXs= document.querySelectorAll('.building-x');
for(var i=0; i < buildingXs.length; i++){
buildingXs[i].addEventListener('click',removeTheTargetedBuildingX);
}
function removeTheTargetedBuildingX(event){
var removeTheTargetedBuildingX = event.currentTarget;
removeTheTargetedBuildingX.parentNode.removeChild(removeTheTargetedBuildingX);
}
}
/*</Remove the targeted buildingX>*/
});
#buildings{
background-color: gray;
}
#first-building{
background-color: red;
height: 150px;
width: 50px;
display: inline-block;
}
#add-another-building{
margin-bottom: 25px;
display: block;
}
.building-x{
background-color: blue;
display: inline-block;
height: 100px;
width: 50px;
margin-left: 5px;
margin-right: 4px;
margin-bottom: 5px;
}
<button id='add-another-building'>Add another building</button>
<div id='buildings'>
<div id='first-building'></div><!--</first-building>-->
<div class='building-x'></div><!--</building-x>-->
</div><!--</buildings>-->
The original problem was that the part of the code that adds listeners was only run once at the beginning, when there were no building-x. Thus no js-generated building-x ever got a listener.
When you added a starting html building-x, that one got a listener but not subsequent js-generated building-x.
The solution is to call the add-listener code after adding a js-building x. In the below example, I have removed the html-starting building-x.
document.addEventListener('DOMContentLoaded',function(){
/*<Add another building>*/
document.querySelector('#add-another-building').addEventListener('click',addAnotherBuilding);
function addAnotherBuilding(){
if(document.querySelector(".building-x")){
document.querySelector(".building-x").insertAdjacentHTML("afterend","<div class='building-x'></div>");
}
else{
document.querySelector("#first-building").insertAdjacentHTML("afterend","<div class='building-x'></div>");
}
addListener();
}
/*</Add another building>*/
/*<Remove the targeted buildingX>*/
function addListener() {
var buildingXs = document.querySelectorAll('.building-x');
for(var i=0; i < buildingXs.length; i++){
if (buildingXs[i].classList.contains("listening") === false) {
buildingXs[i].addEventListener('click',removeTheTargetedBuildingX);
buildingXs[i].classList.add("listening");
}
}
}
function removeTheTargetedBuildingX(event){
var removeTheTargetedBuildingX = event.currentTarget;
removeTheTargetedBuildingX.parentNode.removeChild(removeTheTargetedBuildingX);
}
});
#buildings{
background-color: gray;
}
#first-building{
background-color: red;
height: 150px;
width: 50px;
display: inline-block;
}
#add-another-building{
margin-bottom: 25px;
display: block;
}
.building-x{
background-color: blue;
display: inline-block;
height: 100px;
width: 50px;
margin-left: 5px;
margin-right: 4px;
margin-bottom: 5px;
}
<button id='add-another-building'>Add another building</button>
<div id='buildings'>
<div id='first-building'></div><!--</first-building>-->
</div><!--</buildings>-->

Unwanted background after repositioned span in Firefox

I want to move a span from one div to another.
My solution works ok in Chrome and Safari but Firefox gives me a problem - when the span is moved it has an unwanted background. The background disappears as soon as I click elsewhere on the page but I need to find a way for it not to appear in the first place. Any help is greatly appreciated.
var clckdEl = null;
var clicked = function(evt) {
var span = null;
if (clckdEl) {
if (clckdEl !== this) {
span = clckdEl.children[0];
clckdEl.removeChild(span);
this.appendChild(span);
}
clckdEl.classList.remove('selected');
clckdEl = null;
} else if (this.children.length) {
clckdEl = this;
clckdEl.classList.add('selected')
}
};
var els = document.getElementsByClassName('rect'),
el,
idx = 0;
for (idx = 0; idx < els.length; idx += 1) {
el = els[idx];
el.onclick = clicked;
}
.holder {
font: 100px Arial Unicode MS, sans-serif;
width: 2em;
height: 1em;
}
.rect {
float: left;
display: flex;
width: 1em;
height: 1em;
align-items: center;
}
.rect-blue {
background-color: blue;
}
.rect-yellow {
background-color: yellow;
}
.letter {
line-height: 1em;
padding-bottom: 15%;
margin: 0 auto;
}
.selected {
background-color: red;
}
<div class='holder'>
<div class='rect rect-blue'>
</div>
<div class='rect rect-yellow'>
<span class='letter'>X</span>
</div>
</div>
All you need is to disable user-select parameter.
Simply add this style to your holder class:
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
JSFiddle

Categories

Resources