how to dynamically remove css in Angular? - javascript

.items {
color: black;
background-color: white;
-webkit-transition:all cubic-bezier(0.250,0.460,0.450,0.940) 0.5s;
transition:all cubic-bezier(0.250,0.460,0.450,0.940) 0.5s;
}
.items.currentlySelected {
color: orange;
background-color: yellow;
font-size: 3em;
}
<div ng-repeat="returnedUser in returnedUsers" value="set" ng-click="myVar='currentlySelected'">
<span class="items" ng-class="myVar">
{{returnedUser.login}}
</span>
</div>
$scope.getRepoData = function(singleUser) {
$scope.selectedUser = singleUser;
$http.get(singleUser.repos_url).
success(function(data,status) {
if(status===200) {
$scope.returnedRepos = data;
}
}).
error(function(data,status){
alert("something happened in single user");
});
}
When I click the link, it works beautifully. However when I want to select another link, I want to restore the link back to items (from items.currentlySelected) before applying my css on the newly selected link
How do I do this using Angular (no jquery please)

First remove the ng-click from the div that has ng-repeat. Next in your getRepoData function, do something where you set the currently clicked item to some $scope-bound variable. Let's say that variable is $scope.selectedRepo.
Now, to set the class dynamically for your span, you'd have:
<span ng-class="{active: selectedRepo.id === returnedUser.id}">

You are using a global scope variable for all items (myVar). Instead, conditionally apply the class if the id is equal to the selected:
<div ng-repeat="returnedUser in returnedUsers" value="set"
ng-click="selected=returnedUser"> <!-- Assign current to selected variable -->
<span class="items"
ng-class="{ 'currentlySelected': returnedUser.id == selected.id }"> <!-- Apply class 'currentlySelected' if selected.id is equal to returnedUser.id -->
<a href="#"
ng-click="getRepoData(returnedUser);">
{{returnedUser.login}}
</a>
</span>
</div>

Related

How to display none if div tag doesn't exist?

If the "slick-initialized" div tag doesn't exist within a parent, then I want the parent ID (product recommender-recipe) to display none. Right now this is what I have set up:
HTML is set up like this:
<div id="product-recommender-recipe">
<div class="slick-initialized">
</div>
</div>
My JS so far. If length is 0, then have the parent ID display none. :
var productTemplate = document.getElementsByClassName("#product-recommender-recipe > .slick-initialized")
if (productTemplate.length === 0){
document.getElementById("product-recommender-recipe").style.display = "none";
}
Do I have this set up properly?
You can hide #product-recommender-recipe and check if .slick-initialized exists than show using just CSS.
it is working perfectly.
#product-recommender-recipe {
padding: 50px;
background-color: red;
display: none;
}
#product-recommender-recipe:has(.slick-initialized) {
display: block;
}
<!-- hidden if slick-initialized not exist -->
<div id="product-recommender-recipe">
<!-- <div class="slick-initialized"></div> -->
</div>
<br/>
<!-- visible if slick-initialized exist -->
<div id="product-recommender-recipe">
<div class="slick-initialized"></div>
</div>
You are pretty close. You have two mistakes in your implementation.
The first one is that you used getElementByClassName when in fact you are using an ID as your selector. Thus you should have used querySelector.
The second one is that you overused your selector. You have selected your parent div and placed it in a var so that you can reference it again.
Here is my implementation:
var productTemplate = document.querySelector("#product-recommender-recipe")
if (!productTemplate.querySelector('.slick-initialized')) {
productTemplate.style.display = none;
}
#product-recommender-recipe {
background: red;
width: 50px;
height: 50px;
}
<div id="product-recommender-recipe">
<div class="slick-initialized"></div>
</div>
getElementsByClassName expects a single class name – not a selector. If you want to use a selector, use querySelector or querySelectorAll. querySelector returns null if the element doesn't exists in the DOM.
const element = document.querySelector(".slick-initialized");
if(element === null) {
document.querySelector("#product-recommender-recipe").style.display = "none";
}

How can I add a CSS class to the button that is clicked among multiple buttons using jQuery?

My motive is when someone will click on a particular button then will show the particular cards and will add a class named category_btn_active that clicked. Suppose Services will be clicked then the service cards will be shown. Here the filtering is working well, the problem is here $(this).addClass('category_btn_active').siblings().removeClass('category_btn_active'). The category_btn_active class adds when clicked but when I clicked another button it stays in both buttons. I want the class will be added to just the last clicked button. Where is the problem? give a relevant solution...
index.html:
<li>Services</li>
<li>Static Website</li>
<div class="Services service_itembox">
<img src="Assets/pic-1.jpg" alt="service image">
</div>
<div class="Static service_itembox">
<img src="Assets/pic-2.jpg" alt="service image">
</div>
index.js:
$(function () {
$(".category_btn").click(function () {
$(this).addClass('category_btn_active').siblings().removeClass('category_btn_active')
const value = $(this).attr('data-filter');
if(value == "Services"){
$('.service_itembox').show('slow');
}else{
$('.service_itembox').not('.'+value).hide('slow');
$('.service_itembox').filter('.'+value).show('slow');
}
});
});
style.css:
.category_btn_active{
color: white;
border-color:gray;
border-style:solid ;
border-width:0px 0px 1px 0px;
background-color: #019587;
padding: 8px;
font-size: 14px;
text-transform: uppercase;
}
This is not the most elegant way to do this, but it illustrates use of parent() and sibling(), which you were struggling with:
https://jsfiddle.net/v5fg3qwh/2/
$(function () {
$(".category_btn").click(function () {
$(this).addClass('category_btn_active').parent().siblings().find("a.category_btn").removeClass('category_btn_active')
const value = $(this).attr('data-filter');
$(`.${value}.service_itembox`).show('slow');
$(`.service_itembox`).not('.'+value).hide('slow');
$(`.service_itembox`).filter('.'+value).show('slow');
});
});
Note that I removed your if/else because you don't need it. Your classes and JS logic are defined in such a way that you can specify your intent w/out those conditionals.
I also defaulted one of your images to be hidden at initialization, which I assume is what you'd want:
div.Static.service_itembox {
display: none;
}

Tricky toggle active onmouseover with Vanilla JavaScript

I have a structure like below and I want to toggle active the currently hovered .item element.
I'm using a simple Vanilla JavaScript function that I usually use for click-like situations and it works.
function myFunction(e) {
var elems = document.querySelectorAll(".hover");
[].forEach.call(elems, function(el) {
el.classList.remove("hover");
});
e.target.classList.add("hover");
}
<div class="main-container">
<div class="item hover" onmouseover="myFunction(event)">
item 1
</div>
<div class="item" onmouseover="myFunction(event)">
item 2
</div>
<div class="item" onmouseover="myFunction(event)">
item 3
</div>
</div>
So far so good, but here comes the tricky part. When the mouse goes to a sibling element the hover correctly is changing to the inner one.
I tried some CSS ticks but I can't manage to make it work, any thoughts would be much appreciated
P.S. I prefer Vanilla JavaScript than jQuery
You can use CSS to add and remove the hover. Basic code showing that and added code to toggle active so it can move around.
const menu = document.querySelector(".main-container")
menu.addEventListener("click", function (evt) {
const item = evt.target.closest(".item")
if (item) {
menu.querySelector(".item.active").classList.remove("active")
item.classList.add("active")
}
});
.main-container .item.active {
background-color: green;
}
.item,
.main-container:hover .item.active {
background-color: yellow;
transition: background-color .3s;
}
.main-container:hover .item:hover {
background-color: lime;
transition: background-color .3s;
}
<div class="main-container">
<div class="item active">
item 1
</div>
<div class="item">
item 2
</div>
<div class="item">
item 3
</div>
</div>
You don't need JS for that.
Just overwrite style when the container is hovered
.main-container:hover .item.hover {
background-color: transparent;
}
.item.hover {
background-color: red;
}
.item:hover {
background-color: red !important;
}
<div class="main-container" >
<div class="item hover">
item 1
</div>
<div class="item">
item 2
</div>
<div class="item">
item 3
</div>
</div>
See jsfiddle: https://jsfiddle.net/hs2yfxm1/
If you're trying to style this based on a hover event you should be utilizing the proper pseudo-class. You mentioned that you always want the first item to be "active", why not set an .active class that matches the format styling of :hover? For example:
SCSS
.item {
border-color: red;
&.active,
&:hover {
border-color: blue;
}
}
CSS
.item {
border-color: red;
}
.item.active,
.item:hover {
border-color: blue;
}
Note: In general, it's best practice to limit your use of JS whenever possible. If something is attainable simply with HTML and CSS, that should be the preferred implementation in most cases.
Other than the stylistic portion, just one comment on your JS. In your example, you're utilizing e.target this can be dangerous if the element has children in that the target could be the child. Since you're targeting each element individually (a lot of event listeners that you may want to consider re-working) you can make use of e.currentTarget for other JS needs.
Is this what you are after?
.active { background-color:grey; }
.item:hover { background-color:yellow; }
<div class="main-container" >
<div class="item active">
item 1
</div>
<div class="item">
item 2
</div>
<div class="item">
item 3
</div>
</div>

I want to remove only the parent tag I clicked

There are 3 buttons in my code.
One is to add more files. (.btn-plus)
One is to remove the one added. (.btn-minus)
One is to reset the file. (.btn-reset)
I could add more input with (.btn-plus) button.
How could I delete only the one I click among every input I add with (.btn-plus)?
$(".btn-plus").click(function(){
$('.board-box__attachments').prepend('<li><div class="th">files</div><div class="td"><input type="file"><button class="btn btn-minus"> - </button></div></li>');
return false;
})
$(".btn-minus").click(function(){
$(this).nextUntil('li').remove()
})
$(".btn-reset").click(function(){
$(".board-box__attachments input").value = "";
})
li {
width : 60%;
background : lightblue;
list-style : none;
padding : 0.5em;
border-bottom : 1px solid white;
}
.th {
width : 100px;
float: left;
}
.td {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="board-box__attachments">
<li>
<div class="th">files</div>
<div class="td">
<input type="file">
<button class="btn btn-plus"> + </button>
<button class="btn-reset">Reset</button>
</div>
</li>
</ul>
You have to use on() to attach event to dynamically added element. Then use closest() to find currently clicked element's parent.
$("body").on("click", ".btn-minus", function(){
$(this).closest('li').remove();
})
$(this).nextUntil("li") doesn't match anything. It only searches siblings of this, and the button doesn't have any li siblings. If you want to select the li containing the button, use $(this).closest("li").
You also need to use event delegation to bind an event handler to dynamically-created elements.
$(".btn-plus").click(function(){
$('.board-box__attachments').prepend('<li><div class="th">files</div><div class="td"><input type="file"><button class="btn btn-minus"> - </button></div></li>');
return false;
})
$(".board-box__attachments").on("click", ".btn-minus", function(){
$(this).closest("li").remove()
})
li {
width : 50%;
background : lightblue;
list-style : none;
padding : 1em;
border-bottom : 1px solid white;
}
.th {
width : 100px;
float: left;
}
.td {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="board-box__attachments">
<li>
<div class="th">files</div>
<div class="td">
<input type="file">
<button class="btn btn-plus"> + </button>
</div>
</li>
</ul>
There are 2 issues with you code:
Your element which contains btn-minus is being created dynamically. So the click event would not work instead you need to use on event.
$(".btn-minus").click(function(){
So instead of this you need to use
$(document).on('click', '.btn-minus', function() {
Also you need to use following code to remove element.
$(this).closest('li').remove();
Please see the updated JSFiddle
Here you can creating elements dynamically so once the page is loaded, browser has no knowledge of '.btn-minus'
Try this:
$(document).on('click', '.btn-minus', function(){
$(this).closest('li').remove()
})
Hope this helps!

Removing an element added by ::before pseudo selector

I have the following case: (styling is done in SASS and unnecessary stylings are omitted.)
.header {
...
&::before {
...
position: absolute;
height: 0.5rem;
...
}
}
This creates a bar on top of the application's menu bar. In certain cases this bar has to be removed. I have read questions like these, but with no success. What would be the best way to remove this bar added by the ::before selector?
Only CSS can remove pseudo element, so you need to have an other class that display:none; the before. First declare that class in the CSS :
.header {
...
&::before {
...
position: absolute;
height: 0.5rem;
...
}
&.no-before::before{
display:none;
}
}
Then, when you want to remove it :
$('.header').addClass('no-before'); //Remove before
$('.header').removeClass('no-before'); //Re-add before
The usual way is to create a more specific rule that applies to the element(s) in question (or a later rule with the same specificity), and specify display: none to hide the pseudo in that case.
For example: Here, I want to have an X in front of <span class="foo">, but not if they're in .header:
span.foo::before {
content: 'X ';
}
.header span.foo::before {
display: none;
}
<div>
These have the X:
<span class="foo">span.foo 1</span>
<span class="foo">span.foo 2</span>
<span class="foo">span.foo 3</span>
</div>
<div class="header">
These don't:
<span class="foo">span.foo 4</span>
<span class="foo">span.foo 5</span>
<span class="foo">span.foo 6</span>
</div>
If you are manipulating the DOM by using JavaScript, you can add a class name - for instance .remove-bar - to the element having .header in order to remove the pseudo-element (generated content):
.remove-bar {
&::before { content: none; }
}
Also make sure that it is placed after the previous styles, or use a more specific selector if needed.
For remove special element use this method.
<button onclick="myFunction()">Remove</button>
<div id="myList">
<div> Coffee </div>
<div id="child2" > Tea </div>
<div> Milk </div>
</div>
your JavaScript :
<script>
function myFunction() {
const list = document.getElementById("myList");
if (list.hasChildNodes()) {
list.removeChild(list.children[0]);
}
}
</script>
you can combine above function with this code:
const parent = document.getElementById('myList');
const children = parent.children;
let index = -1;
for (let i = 0; i < children.length; i++) {
if (children[i].id === 'child3') {
index = i;
break;
}
}
alert(index); // 👉️ 2

Categories