My message display out of my DIV HTML
How do I resolve this?
I need to display this message within the div. If I repeat this code, it appears in the same place every time, I just want to display it in its own div and not invade others. My big problem it's the display message. Does anyone know how to resolve this?
<html>
<head>
</head>
<body>
jhadfjadfjasf
ajdfhkhasdjfas
ajdfhjadfa
ajdfhkajsdfh
<div class="sidney">
<img src="https://eitrawmaterials.eu/wp-content/uploads/2016/09/person-icon.png" width="220px" height="220px">
<div id="baselayer">
<input type="button" class="testx" value="SubLevel" onclick="showFrontLayer();" />
<input type="button" value="Job Description" onclick="showFrontLayers();"/>
<div id="bg_mask">
<div id="frontlayer">
<div class="containers">
<input type="button" value="X" onclick="hideFrontLayer();" style="position: absolute;top:5%;right:5%;"/>
O Product Owner é a pessoa que define os itens que compõem o Product Backlog e os prioriza nas Sprint Planning Meetings.
</div>
</div>
</div>
<div id="bg_masks">
<div id="frontlayers">
<input type="button" value="X" onclick="hideFrontLayers();" style="position: absolute;top:5%;right:5%;"/>
O Product Owner.
</div>
</div>
</div>
</div>
<style>
.sidney{
width: 250px;
height: 250px;
background-color: black;
border:20px;
}
</style>
<img src="https://eitrawmaterials.eu/wp-content/uploads/2016/09/person-icon.png" width="170px" height="150px">
<style>
#testx{
position: absolute;
top: 0px;
left: 0px%;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
background-color: #555;
color: white;
font-size: 16px;
padding: 12px 24px;
border: none;
cursor: pointer;
border-radius: 5px;
text-align: center;}
#bg_mask{
position: absolute;
top: 0px;
right: 0;
bottom: 0;
left: 0;
margin: auto;
margin-top: 0px;
width: 981px;
height: 610px;
background : url("img_dot_white.jpg") center;
z-index: 0;
visibility: hidden;
}
#frontlayer{
position: absolute;
top: 0px;
right: 0;
bottom: 0;
left: 0;
margin: 10px 10px 10px 10px;
padding : 30px;
width: 180px;
height: 100px;
background-color: orange;
visibility: hidden;
border: 1px solid black;
z-index: 1;
}
#bg_masks {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
margin-top: 0px;
width: 981px;
height: 610px;
background : url("img_dot_white.jpg") center;
z-index: 0;
visibility: hidden;
}
#frontlayers {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: 10px 10px 10px 10px;
padding : 30px;
width: 180px;
height: 100px;
background-color: orange;
visibility: hidden;
border: 1px solid black;
z-index: 1;
}
</style>
<script>
function showFrontLayer() {
document.getElementById('bg_mask').style.visibility='visible';
document.getElementById('frontlayer').style.visibility='visible';
}
function hideFrontLayer() {
document.getElementById('bg_mask').style.visibility='hidden';
document.getElementById('frontlayer').style.visibility='hidden';
}
</script>
<script>
function showFrontLayers() {
document.getElementById('bg_masks').style.visibility='visible';
document.getElementById('frontlayers').style.visibility='visible';
}
function hideFrontLayers() {
document.getElementById('bg_masks').style.visibility='hidden';
document.getElementById('frontlayers').style.visibility='hidden';
}
</script>
</body>
</html>
How do I resolve this?
add position: relative; to this class .sidney (you can find it on line 31)
Related
I was trying to make a dice random, and I created different faces of it by using HTML and CSS. Now I cannot hide them. I want to show only one face of the die at a time. How can I call a single face on random numbers from 1 to 6 and in javascript I tried onclicking a button to change the border color. How can I link CSS, HTML and javascript so that on clicking it shows one of the face designed through CSS?
HTML
function roll() {
var die = Math.floor(Math.random() * 6) + 1;
$('#die').removeAttr('class').addClass('die' + die);
}
#die {
width: 30px;
border: 5px solid black;
padding: 25px;
margin: 25px;
}
#die.die1 {
width: 30px;
border: 5px solid green;
padding: 25px;
margin: 25px;
}
#die.die2 {
width: 30px;
border: 5px solid pink;
padding: 25px;
margin: 25px;
}
#die.die3 {
width: 30px;
border: 5px solid violet;
padding: 25px;
margin: 25px;
}
#die.die4 {
width: 30px;
border: 5px solid yellow;
padding: 25px;
margin: 25px;
}
#die.die5 {
width: 30px;
border: 5px solid red;
padding: 25px;
margin: 25px;
}
#die.die6 {
width: 30px;
border: 5px solid blue;
padding: 25px;
margin: 25px;
}
.dice {
border: solid 3px #aaa;
border-radius: 3px;
display: block;
width: 100px;
height: 100px;
margin: 7px auto;
box-sizing: border-box;
padding: 10px;
position: relative;
}
.dice .dot {
border-radius: 50%;
position: absolute;
width: 15px;
height: 15px;
background: #000;
}
.dice:first-child .dot {
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
.dice:nth-child(2) .dot:first-child {
top: 20px;
left: 20px;
}
.dice:nth-child(2) .dot:last-child {
bottom: 20px;
right: 20px;
}
.dice:nth-child(3) .dot:first-child {
top: 15px;
left: 15px;
}
.dice:nth-child(3) .dot:nth-child(2) {
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
.dice:nth-child(3) .dot:last-child {
bottom: 15px;
right: 15px;
}
.dice:nth-child(4) .dot:first-child {
top: 15px;
left: 15px;
}
.dice:nth-child(4) .dot:nth-child(2) {
top: 15px;
right: 15px;
}
.dice:nth-child(4) .dot:nth-child(3) {
bottom: 15px;
left: 15px;
}
.dice:nth-child(4) .dot:last-child {
bottom: 15px;
right: 15px;
}
.dice:nth-child(5) .dot:first-child {
top: 15px;
left: 15px;
}
.dice:nth-child(5) .dot:nth-child(2) {
top: 15px;
right: 15px;
}
.dice:nth-child(5) .dot:nth-child(3) {
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
.dice:nth-child(5) .dot:nth-child(4) {
bottom: 15px;
left: 15px;
}
.dice:nth-child(5) .dot:last-child {
bottom: 15px;
right: 15px;
}
.dice:nth-child(6) .dot:first-child {
top: 15px;
left: 15px;
}
.dice:nth-child(6) .dot:nth-child(2) {
top: 15px;
right: 15px;
}
.dice:nth-child(6) .dot:nth-child(3) {
top: 0;
bottom: 0;
left: 15px;
margin: auto;
}
.dice:nth-child(6) .dot:nth-child(4) {
top: 0;
right: 15px;
bottom: 0;
margin: auto;
}
.dice:nth-child(6) .dot:nth-child(5) {
bottom: 15px;
left: 15px;
}
.dice:nth-child(6) .dot:last-child {
bottom: 15px;
right: 15px;
}
.content {
left: 80%;
}
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" href="dice.css" type="text/css" />
<script src="dice.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div id="die">
</div>
<button type="button" onclick="roll()">Click me!</button>
<div class="container">
<div class="dice">
<div class="dot"></div>
</div>
<div class="dice">
<div class="dot"></div>
<div class="dot"></div>
</div>
<div class="dice">
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
<div class="dice">
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
<div class="dice">
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
<div class="dice">
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
</div>
</body>
</html>
Rather than hiding, showing, and repositioning the dice elements you have created, you could just create the element you need on click (with some css modifications to take advantage of the random number generation to help position the dots). As an aside, there is no real need for jQuery here, but it is used in the example since you were using it in your original approach.
The js creates a click event listener on the #roll button. Each time the button is clicked, the num variable is set to a random number between 1 and 6. The cls variable sets the prefix for the various classes that determine the positioning of the dots on the die - it assumes the roll is an odd number and then adjusts if it is even. Then, we remove any child elements from #die with empty() (so any dots from a previous roll are removed before we add new ones). Finally, we use a loop to append the same number of dots to #die as generated in our num variable. At the same time, we append the numbered class for each dot (which is why we named our classes odd-1, even-1, etc). For example:
$('#roll').click(() => {
const num = Math.floor(Math.random() * 6) + 1;
let cls = 'odd-'
if (num % 2 === 0) {
cls = 'even-'
}
$('#die').empty();
for (let i = 1; i <= num; i++) {
$('#die').append(`<div class="dot ${cls}${i}"></div>`);
}
});
.dice {
position: relative;
margin: 8px;
border: solid 3px #aaa;
border-radius: 3px;
width: 100px;
height: 100px;
}
.dice .dot {
position: absolute;
background: #000;
border-radius: 50%;
width: 16px;
height: 16px;
transform: translate(-8px, -8px);
}
.odd-1 {
top: 50%;
left: 50%;
}
.even-1,
.odd-2 {
top: 25%;
left: 25%;
}
.even-2,
.odd-3 {
top: 75%;
left: 75%;
}
.even-3,
.odd-4 {
top: 75%;
left: 25%;
}
.even-4,
.odd-5 {
top: 25%;
left: 75%;
}
.even-5 {
top: 50%;
left: 75%;
}
.even-6 {
top: 50%;
left: 25%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<button id="roll" type="button">Click to roll</button>
<div id="die" class="dice">
</div>
</div>
Something possessed me to create a Vanilla JS version of #benvc's excellent answer (upvoted).
This uses the exact same strategy, but of course without the jQuery conveniences like .empty() and .append()
I also chose to use const in place of let where possible, collapsed the determination of the class name "cls" into a ternary ?: in place of an if, and I'm displaying the random number to visually confirm that the rendered die matches the number which makes for minor changes in the HTML.
The CSS is completely unchanged.
const die = document.getElementById('die');
const val = document.getElementById('value');
document.getElementById('roll')
.addEventListener('click', () => {
const num = Math.floor(Math.random() * 6) + 1;
const cls = num % 2 === 0 ? 'even-' : 'odd-';
val.innerText = num;
die.innerHTML = '';
for (let i = 1; i <= num; i++) {
die.innerHTML += `<div class="dot ${cls}${i}"></div>`;
}
});
.dice {
position: relative;
margin: 8px;
border: solid 3px #aaa;
border-radius: 3px;
width: 100px;
height: 100px;
}
.dice .dot {
position: absolute;
background: #000;
border-radius: 50%;
width: 16px;
height: 16px;
transform: translate(-8px, -8px);
}
.odd-1 {
top: 50%;
left: 50%;
}
.even-1,
.odd-2 {
top: 25%;
left: 25%;
}
.even-2,
.odd-3 {
top: 75%;
left: 75%;
}
.even-3,
.odd-4 {
top: 75%;
left: 25%;
}
.even-4,
.odd-5 {
top: 25%;
left: 75%;
}
.even-5 {
top: 50%;
left: 75%;
}
.even-6 {
top: 50%;
left: 25%;
}
<div>
<button id="roll" type="button">Click to roll</button>
<span id="value">0</span>
<div id="die" class="dice"></div>
</div>
I am trying to make an on click image overlay, where you click the left icon and an image fades or slides in, but when you click the right icon a different image fades or slides in. Also, when you click either icon, the associated images fade or slide out.
I've been trying to use
function on() {
document.getElementById("overlay").style.display = "block";
}
function off() {
document.getElementById("overlay").style.display = "none";
}
to make the display go from none to block when you click the icon, but there is no way to use this function with two separate links. I am not very great with javascript so any help would be greatly appreciated. Thanks.
https://jsfiddle.net/hzfw00L7/
Are you looking for something like this? I have used Jquery to speed up the coding!
$(document).ready(function() {
$(".left").click(function() {
$("#overlay").fadeIn(3000);
});
$(".right").click(function() {
$("#overlay2").fadeIn(3000);
});
$("#overlay").click(function() {
$("#overlay").fadeOut(2000);
});
$("#overlay2").click(function() {
$("#overlay2").fadeOut(2000);
});
});
#overlay {
position: fixed;
z-index: 4;
display: none;
width: 100%;
height: 350px;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 2;
cursor: pointer;
}
#overlay2 {
position: fixed;
z-index: 4;
display: none;
width: 100%;
height: 350px;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: red;
z-index: 2;
cursor: pointer;
}
#text {
position: absolute;
top: 50%;
left: 50%;
font-size: 50px;
color: white;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
}
#content {
padding: 20px;
}
a.left {
display: block;
position: absolute;
top: 320px;
left: 80px;
z-index: 6;
height: 20px;
background-color: purple;
color: white;
font-family: Arial;
padding: 10px;
}
a.right {
display: block;
position: absolute;
top: 320px;
right: 80px;
z-index: 7;
height: 20px;
background-color: magenta;
color: white;
font-family: Arial;
padding: 10px;
}
#buttons {
height: 50px;
width: 300px;
margin: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<body>
<div id="overlay">
<div id="text">Overlay Text</div>
</div>
<div id="overlay2">
<div id="text">Overlay Text 2</div>
</div>
<div id="content">
<div id="buttons">
<a class="left">Turn on overlay effect</a>
</div>
<div id="content">
<a class="right">Turn on overlay effect 2</a>
</div>
</div>
</body>
</html>
Added Fade in and fade out animations!
For More Reference Go here
I stack two circles over an image, using the position and overflow properties.
It works fine but I have the circle running over the image on left and right (not top and left.
Here is the image : Circle overflowing
Here is the CSS.
.mainContainer {
background-color: #A6A4AA
}
.targetImage {
margin: 0;
width: 100%;
height: auto;
border: solid medium #2C3756;
border-radius: 0 0 8px 8px;
background-color: #A6A4AA;
position: relative;
}
#targetCol {
overflow: hidden;
position: absolute;
}
.impact, .ajustement {
position: absolute;
background-color: #dc022e;
border-radius: 100%;
opacity: 0.75;
margin: 0;
width: 100%;
height: auto;
border: solid medium #2C3756;
}
.ajustement {
opacity: 0.5;
}
The code source (ejs+bootstrap) : the row is a child of mainContainer
<div class="row"> <!-- Row : target -->
<div class= "col-xs-12" id="targetCol">
<img id="target" class="targetImage"></img>
<div id="ajustement" class="ajustement"></div>
<div id="impact" class="impact"></div>
</div>
</div>
How can I draw my circles into the images only, without running out the border ?
Here is what I would like :
Do you looking something like this:
body{
margin: 0;
background-color: #A6A4AA
}
.mainContainer {
background-color: #A6A4AA;
margin: 15px auto;
width: 98%;
}
.targetImage {
margin: 0;
width: 100%;
height: auto;
border-radius: 0 0 8px 8px;
background: #A6A4AA;
position: relative;
}
#targetCol {
overflow: hidden;
position: absolute;
border: 3px solid #2C3756;
line-height: 0;
border-radius: 12px;
}
.impact, .ajustement {
position: absolute;
background-color: #dc022e;
border-radius: 100%;
opacity: 0.75;
margin: 0;
width: 100%;
height: auto;
border: 3px solid #2C3756;
left: -45%;
top: -78px;
height: calc(100% + 78px);
}
.impact{
width: 20px;
height: 20px;
border-color: #000;
left: 10%;
top: 10%;
}
.ajustement {
opacity: 0.5;
}
<div class="mainContainer">
<div class="row"> <!-- Row : target -->
<div class= "col-xs-12" id="targetCol">
<img id="target" class="targetImage" src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Papageitaucher_Fratercula_arctica.jpg/800px-Papageitaucher_Fratercula_arctica.jpg">
<div id="ajustement" class="ajustement"></div>
<div id="impact" class="impact"></div>
</div>
</div>
</div>
I have a map where I am toggling a class when you click on a dot/location that pops up a tooltip. The issue I'm running into is that when I click on another dot the other siblings tooltips are not going away. I tried to solve this by removing the class of the siblings on click, but when I do this the toggle stops working and I cannot click the dot again to get rid of the active tooltip.
I need the toggle on the currently active tooltip to still work but I also need the sibling tooltips to disappear as well.
I hope I explained that right. Here is a codepen: http://codepen.io/anon/pen/BzQrLV
$('.dot').click(function() {
$('div.toggle-active').removeClass('toggle-active');
$(this).next().toggleClass('toggle-active');
});
#map {
position: relative;
width: 100%;
max-width: 580px;
}
#map img {
max-width: 100%;
}
/** DOTS **/
.dot {
background-color: #fff;
border: 1px solid #fff;
border-radius: 50%;
cursor: pointer;
display: inline-block;
height: 10px;
position: absolute;
width: 10px;
}
.dot:hover {
background-color: #00A24B;
}
.dot-oregon-greshman {
top: 15%;
left: 11%;
}
.dot-oregon-oregon-city {
top: 16.5%;
left: 11%;
}
/** TOOLTIPS **/
.tooltip::before {
content: "";
height: 0;
width: 0;
border-style: solid;
border-width: 12.5px 21.7px 12.5px 0;
border-color: transparent #01872B transparent transparent;
position: absolute;
top: 50%;
left: -6%;
transform: translateY(-50%);
}
.tooltip {
opacity: 0;
background-color: #01872B;
color: #fff;
padding: 10px 10px 10px 20px;
font-size: 12px;
width: 186px;
position: absolute;
line-height: 14px;
transition: all 300ms ease-in-out;
}
.tooltip.toggle-active {
opacity: 1;
}
.tooltip p {
margin: 3px 0;
}
.tooltip a {
color: #fff;
}
.tooltip a:hover {
color: #c3ecff;
text-decoration: none;
}
.tooltip strong {
color: #fff;
font-size: 14px;
}
.tooltip-oregon-greshman {
top: 10%;
left: 16%;
}
.tooltip-oregon-oregon-city {
top: 11.5%;
left: 17%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="map-section">
<div class="map-container">
<div id="map">
<img src="http://openpathinvestments.com/wp-content/themes/boilerplate/images/map-blue.png" alt="">
<div class="locations">
<div class="dot dot-oregon-greshman"></div>
<div class="tooltip tooltip-oregon-greshman">
<strong>Stark Street Crossings</strong>
<p>Greshman, Oregon 97030</p>
<p>Property Profile | Website
</p>
</div>
<div class="dot dot-oregon-oregon-city"></div>
<div class="tooltip tooltip-oregon-oregon-city">
<strong>The Preserve</strong>
<p>Oregon City, Oregon 97045</p>
<p>Property Profile | Website
</p>
</div>
</div>
</div>
</div>
</div>
Add .not($(this).next()) to your removeClass statement so you don't remove the active class from all the dots, just the dots not being clicked on.
$('.dot').click(function() {
$('div.toggle-active').not($(this).next()).removeClass('toggle-active');
$(this).next().toggleClass('toggle-active');
});
#map {
position: relative;
width: 100%;
max-width: 580px;
}
#map img {
max-width: 100%;
}
/** DOTS **/
.dot {
background-color: #fff;
border: 1px solid #fff;
border-radius: 50%;
cursor: pointer;
display: inline-block;
height: 10px;
position: absolute;
width: 10px;
}
.dot:hover {
background-color: #00A24B;
}
.dot-oregon-greshman {
top: 15%;
left: 11%;
}
.dot-oregon-oregon-city {
top: 16.5%;
left: 11%;
}
/** TOOLTIPS **/
.tooltip::before {
content: "";
height: 0;
width: 0;
border-style: solid;
border-width: 12.5px 21.7px 12.5px 0;
border-color: transparent #01872B transparent transparent;
position: absolute;
top: 50%;
left: -6%;
transform: translateY(-50%);
}
.tooltip {
opacity: 0;
background-color: #01872B;
color: #fff;
padding: 10px 10px 10px 20px;
font-size: 12px;
width: 186px;
position: absolute;
line-height: 14px;
transition: all 300ms ease-in-out;
}
.tooltip.toggle-active {
opacity: 1;
}
.tooltip p {
margin: 3px 0;
}
.tooltip a {
color: #fff;
}
.tooltip a:hover {
color: #c3ecff;
text-decoration: none;
}
.tooltip strong {
color: #fff;
font-size: 14px;
}
.tooltip-oregon-greshman {
top: 10%;
left: 16%;
}
.tooltip-oregon-oregon-city {
top: 11.5%;
left: 17%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
HTML
<div class="map-section">
<div class="map-container">
<div id="map">
<img src="http://openpathinvestments.com/wp-content/themes/boilerplate/images/map-blue.png" alt="">
<div class="locations">
<div class="dot dot-oregon-greshman"></div>
<div class="tooltip tooltip-oregon-greshman">
<strong>Stark Street Crossings</strong>
<p>Greshman, Oregon 97030</p>
<p>Property Profile | Website
</p>
</div>
<div class="dot dot-oregon-oregon-city"></div>
<div class="tooltip tooltip-oregon-oregon-city">
<strong>The Preserve</strong>
<p>Oregon City, Oregon 97045</p>
<p>Property Profile | Website
</p>
</div>
</div>
</div>
</div>
</div>
Updated to check whether the tooltip was already being displayed before displaying it.
$('.dot').click(function() {
var displayed = $(this).next().attr('class').match('toggle-active');
$('div.toggle-active').removeClass('toggle-active');
if(!displayed){
$(this).next().toggleClass('toggle-active');
}
});
I have a recursive ng-repeat for creating a branching mind map tree which may have child nodes indefinitely (run the code snippet below to get a better idea of what I mean).
I've got a remove() function in my $scope, which intends to remove itself. However, to do this, I need access to the parent. I tried achieving this by using ng-init to set the parent node in a variable called parent. The problem is, the parent variable seems to be referring to the node itself instead of its parent. How do I inject the parent into the loop instead?
Everything but the fore-mentioned $scope.remove() works in the snippet below:
(function(){
angular
.module('createTree',[])
.controller('CreateTreeController', function($scope){
$scope.tree=[{
title:'node 1',
subNodes:[
{
title:'node 1.1',
subNodes:[]
},
{
title:'node 1.2',
subNodes:[
{
title:'node 1.2.1',
subNodes:[]
},
{
title:'node 1.2.2',
subNodes:[]
}
]
},
{
title:'node 1.3',
subNodes:[]
}
]
}];
$scope.addTo=function(node){
node.subNodes.push({
title: node.title+"."+(node.subNodes.length+1),
subNodes:[]
});
}
$scope.remove=function(node,parent){
var index=parent.subNodes.indexOf(node)
if(index>-1) parent.subNodes.splice(index,1);
}
});
})();
*{
position: relative;
box-sizing: border-box;
}
.node{
padding: 1px 0;
}
.node>.subNodes{
margin-left: 10px;
}
.node>.subNodes::before{
content: '';
display: block;
width: 5px;
height: 1px;
background-color: black;
position: absolute;
top: 50%;
left: -10px;
}
.node>.subNodes::after{
content:'';
display: block;
width: 1px;
height: 100%;
background-color: black;
position: absolute;
top: 0;
left: -5px;
z-index: 1;
}
.node>.subNodes>.node::before{
content:'';
display: block;
width: 5px;
height: 1px;
background-color: black;
position: absolute;
top: 50%;
left:-5px;
z-index: 3;
}
.node>.subNodes>.node:first-child::after{
content:'';
display: block;
width: 1px;
height: 50%;
background-color: white;
position: absolute;
top: 0;
left:-5px;
z-index: 2;
}
.node>.subNodes>.node:last-child:not(:first-child)::after{
content:'';
display: block;
width: 1px;
height: calc(50% - 1px);
background-color: white;
position: absolute;
bottom: 0;
left:-5px;
z-index: 2;
}
.node>.subNodes>.node:only-child::after{
height: 100%;
}
.node>*{
display: inline-block;
vertical-align: middle;
}
.node [type=text]{
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<div ng-app="createTree" ng-controller="CreateTreeController as createTree">
<script type="text/ng-template" id="treeNode.html">
<span>
<input
type="button"
value="x"
ng-click="remove(node,parent)"
>
{{node.title}}, parent: {{parent.title}}
<input
type="button"
value="+"
ng-click="addTo(node)"
>
</span><div class="subNodes" ng-show="node.subNodes.length>0">
<div
class="node"
ng-init="parent=node"
ng-repeat="node in node.subNodes"
ng-include="'treeNode.html'"
></div>
</div>
</script>
<div
class="node"
ng-init="parent=tree"
ng-repeat="node in tree"
ng-include="'treeNode.html'"
></div>
</div>
There is an issue with the way you are updating your parent in every loop. Basically what is happening is that after the first level you parent's value is becoming same as that of node. This is actually an angular feature where the ng-init gets called again to update the value of parent because it sees that the value of node has changes in the ng-repeat. So the end result that the value of parent will always be the last element in node.subNodes. Hence when you call remove the parent of the node is not really being passed. To overcome this I have added a third variable which will hold the value of the parent (or rather the next parent). I have created a fiddler here.
I have only changed your HTML as below (the ng-init expression has been changed):
<div ng-controller="CreateTreeController">
<script type="text/ng-template" id="treeNode.html">
<span>
<input
type="button"
value="x"
ng-click="remove(node,parent)"
>
{{node.title}}, parent: {{parent.title}}
<input
type="button"
value="+"
ng-click="addTo(node)"
>
</span>
<div class="subNodes" ng-show="node.subNodes.length>0">
<div class="node" ng-init="parent=oldParent;oldParent=node;" ng-repeat="node in node.subNodes" ng-include="'treeNode.html'"></div>
</div>
</script>
<div class="node" ng-init="parent=tree;oldParent=parent[0];" ng-repeat="node in tree" ng-include="'treeNode.html'"></div>
</div>
The parent can't be the node, You need to set true parent for every node.
I made a solution
(function(){
angular
.module('createTree',[])
.controller('CreateTreeController', function($scope){
$scope.tree=[{
title:'node 1',
parent: null,
subNodes:[]
}];
$scope.addTo=function(node){
node.subNodes.push({
title: node.title+"."+(node.subNodes.length+1),
parent: node,
subNodes:[]
});
}
$scope.remove=function(node,parent){
var index=node.parent.subNodes.indexOf(node)
if(index>-1 && node.parent != null) node.parent.subNodes.splice(index,1);
}
});
})();
*{
position: relative;
box-sizing: border-box;
}
.node{
padding: 1px 0;
}
.node>.subNodes{
margin-left: 10px;
}
.node>.subNodes::before{
content: '';
display: block;
width: 5px;
height: 1px;
background-color: black;
position: absolute;
top: 50%;
left: -10px;
}
.node>.subNodes::after{
content:'';
display: block;
width: 1px;
height: 100%;
background-color: black;
position: absolute;
top: 0;
left: -5px;
z-index: 1;
}
.node>.subNodes>.node::before{
content:'';
display: block;
width: 5px;
height: 1px;
background-color: black;
position: absolute;
top: 50%;
left:-5px;
z-index: 3;
}
.node>.subNodes>.node:first-child::after{
content:'';
display: block;
width: 1px;
height: 50%;
background-color: white;
position: absolute;
top: 0;
left:-5px;
z-index: 2;
}
.node>.subNodes>.node:last-child:not(:first-child)::after{
content:'';
display: block;
width: 1px;
height: calc(50% - 1px);
background-color: white;
position: absolute;
bottom: 0;
left:-5px;
z-index: 2;
}
.node>.subNodes>.node:only-child::after{
height: 100%;
}
.node>*{
display: inline-block;
vertical-align: middle;
}
.node [type=text]{
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<div ng-app="createTree" ng-controller="CreateTreeController as createTree">
<script type="text/ng-template" id="treeNode.html">
<span>
<input
type="button"
value="x"
ng-click="remove(node)"
>
{{node.title}}, parent: {{node.parent.title}}
<input
type="button"
value="+"
ng-click="addTo(node)"
>
</span><div class="subNodes" ng-show="node.subNodes.length>0">
<div
class="node"
ng-repeat="node in node.subNodes"
ng-include="'treeNode.html'"
></div>
</div>
</script>
<div
class="node"
ng-repeat="node in tree"
ng-include="'treeNode.html'"
></div>
</div>