The idea is to create a checklist. When the user clicks on a circle it changes its background color. If he clicks it again it should reset the color.
I managed to change the background to green when the user checks his progress like this:
<i class="circle1"
ng-style="myStyle1"
ng-click="myStyle1={'background-color':'green'}">1</i>
Now my problem is how to reset the color to white when the user clicks again?
Thank you for your help.
One option would be to introduce a css class which is toggled when you click the element. You can do this with a combination of ng-class and using ng-click to toggle a variable.
<i class="circle1" ng-class="{'green-circle': isToggled === true}" ng-click="isToggled = !isToggled">1 - {{isToggled}}</i>
angular.module("app", []);
.circle1 {
background: red;
}
.green-circle {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<i class="circle1" ng-class="{'green-circle': isToggled === true}" ng-click="isToggled = !isToggled">1 - {{isToggled}}</i>
</div>
The downfall of this solution is that you would need a different isToggled variable for each circle. A better and more re-usable solution would be to create a directive that handles this:
var app = angular.module("app", []);
app.directive('toggleClass', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.on('click', function() {
element.toggleClass(attrs.toggleClass);
});
}
};
});
.circle1 {
background: red;
}
.green-circle {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<i class="circle1" toggle-class="green-circle">One</i>
<i class="circle1" toggle-class="green-circle">Two</i>
<i class="circle1" toggle-class="green-circle">Three</i>
</div>
Why don't you follow this algorithm and write some code,
write a common function to reset color
Call that function via ng-click and get currently clicked element
and reset color of that elements plus all elements next to it by changing it's class
Remember resetting color of all nodes next to current code is must, else it will not look like Progress. It will just look like on-off buttons
You can post code again if you are getting some errors
HTML
<i class="circle1" id ="circle1" ng-click="changeColor()">1</i>
JS code:
$scope.changeColor= function() {
var i=0
if(i%2 ==0)
{
document.getElementbyID('circle1').style.background ="original color"
}
else
{
document.getElementbyID('circle1').style.background ="green"
}
};
Related
I am trying to use JQuery to update a data attribute after clicking on a button.
Please take a look at what I have tried below.
When I click on the div with class previous-wrapper, the whole block is well updated, and the data-nb-attribute get the correct value.
But, when I click on this div for the second time, data-nb-attribute gets the value NaN..
Is there another way to dynamically update and retrieve the value of this attribute?
$(function(){
$(document).on('click','.previous-wrapper',function(){
var get_nb = $(this).find('.previous');
get_nb = get_nb.data("nb");
get_nb = parseInt(get_nb)
//Dom to update
arr_left = $('<i/>', {
className: 'fa-solid fa-arrow-left'
});
previous = $('<div/>', {
className: 'previous',
'data-nb': get_nb-5,
html: "Previous"
});
//Question 2. How to append previous to arrow_left
$(".previous-wrapper").html(previous);
});
});
.previous-wrapper{
cursor: pointer;
background:red;
width:100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="previous-wrapper">
<i class="fa-solid fa-arrow-left"></i>
<span class="previous" data-nb="100">Previous</span>
</div>
I would also like to know how to add multiple DOM created by JQuery.
You're overwriting the HTML with an invalid attribute of "classname" instead of "class", which means on the second interation $('.previous') won't match anything.
Corrected version of your code:
$(document).on('click', '.previous-wrapper', function() {
var get_nb = $(this).find('.previous');
get_nb = get_nb.data("nb");
get_nb = parseInt(get_nb)
//Dom to update
arr_left = $('<i/>', {
class: 'fa-solid fa-arrow-left'
});
previous = $('<div/>', {
class: 'previous',
'data-nb': get_nb - 5,
html: "Previous"
});
// including both elements at once:
$(".previous-wrapper").html([arr_left, previous]);
console.log($('.previous-wrapper').html())
});
.previous-wrapper {
cursor: pointer;
background: red;
width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="previous-wrapper">
<i class="fa-solid fa-arrow-left"></i>
<span class="previous" data-nb="100">Previous</span>
</div>
It would be much, much simpler, however, to simply update the one attribute you want to update, instead of rewriting all the HTML every click:
$(document).on('click', '.previous-wrapper', function() {
let el = $(this).find('.previous')
// update the data attribute using .attr() instead of .data() because jQuery handles .data internally; it's not reflected in the DOM
el.attr('data-nb', Number(el.attr('data-nb')) - 5);
console.log($('.previous-wrapper').html())
});
.previous-wrapper {
cursor: pointer;
background: red;
width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="previous-wrapper">
<i class="fa-solid fa-arrow-left"></i>
<span class="previous" data-nb="100">Previous</span>
</div>
On click of fa-eye icon I want to focus/highlight only that div.
Html:
<i style="float: right; margin: 8px; cursor: pointer;" class="fa fa-eye" ng-click="focus()"></i>
JS:
$scope.focus = function($element) {
$('#focus-overlay').toggleClass("focus-overlay");
$('#last').toggleClass("widget-focus-enabled");
};
In place of id="last" I have to find the id on click of icon and then need to add class..
I tried : $($event.target).parent() but not able to get the result.
Demo : http://plnkr.co/edit/HvTRdjNVdmHjnyG41O4F?p=preview
Please help.
You can use this for getting the current object,
ng-click="focus(this)"
Then in the function,
$scope.focus = function($element) {
var parent= $($element).closest("div");
$('#focus-overlay').toggleClass("focus-overlay");
$('#last').toggleClass("widget-focus-enabled");
};
.closest("div") will get the parent div. Advantage of closest() over parent() is it can traverse multiple level.
Just pass $event property of angularjs in ng-click method.
ng-click="focus($event)"
In your method do so.
$scope.focus = function($element) {
var parent= $($element.target).closest("div");
$('#focus-overlay').toggleClass("focus-overlay");
$('#last').toggleClass("widget-focus-enabled");
};
if you read this thread:
Automatically pass $event with ng-click?
you will see the comment by zeroflagL, which i just upvoted,
you are trying to modify a visual component in a controller,
which is not what is the intention of this handler
it is further supported by the angular documentation:
'Controllers should contain only business logic. Putting any presentation logic into Controllers significantly affects its testability. '
https://docs.angularjs.org/guide/controller
there is nothing stopping you from using plain old javascript here
i have added a script block that applies a style, not to the direct
parent but a few up
here is your modified plunker,
http://plnkr.co/edit/0x4ZqKoQcQLHXMMWtLJD
but in essence here are the additions:
index.html:
<script>
var _handleclick = function(ele) {
ele.parentElement.parentElement.parentElement.style.backgroundColor = 'red';
}
</script>
template.html:
<i style="float: right; margin: 8px; cursor: pointer;" class="fa fa-eye" onclick="_handleclick(this)" ng-click="focus()"></i>
I have below structure for my span tag,
<span class="spanclass" ng-click="clickfunction()">
</span>
It is said that we need to add tabindex=-1 to the span
and then set focus to the span element.
Initially I thought like on ng-blur of anchor tag, I can call a function where I can set the focus as below
$('.spanclass').attr("tabIndex", -1).focus();
Then Im able to get focus on it however, when I press enter ng-click is not getting called, which is happening if I do by clicking directly.Also here I mixed both angular js and jquery which might not be correct.
May I know how we can implement above two steps using angular js and on what event.
Thanks,
Balaji
As mentioned in other answers, changing to a button would make the most sense.
If you MUST use a span element, then you can add a directive to perform a function on Enter keypress, like found here: How to use a keypress event in AngularJS?
Javascript:
app.directive('ngEnter', function () {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if(event.which === 13) {
scope.$apply(function (){
scope.$eval(attrs.ngEnter);
});
event.preventDefault();
}
});
};
});
HTML:
<div ng-app="" ng-controller="MainCtrl">
<input type="text" ng-enter="doSomething()">
</div>
It will be more semantic to change the span to a button (you can still style it as you wish)
...
<style>
.span {
border: none;
background: none;
}
</style>
</head>
<body ng-app="app">
<div ng-controller="ctrlr">
First
<button class="span" ng-click="clickfunction()" tabindex="1">
Second
</button>
</div>
<script>
angular.module('app', []);
angular.module('app').controller('ctrlr', function ($scope) {
$scope.clickfunction = function () {
alert('a')
}
});
</script>
</body>
angular.module('app', []);
angular.module('app').controller('ctrlr', function ($scope) {
$scope.clickfunction = function () {
alert('a')
}
});
.span {
border: none;
background: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="ctrlr">
First
<button class="span" ng-click="clickfunction()" tabindex="1">
Second
</button>
</div>
</div>
Although the above answer by #mofojed has been accepted.
But here are some more clarification that will make this post complete.
You can set focus on a focusable HTML element which includes anchor tags, HTML inputs, selects, text areas, buttons, any embedded elements as well as any element with a tabindex
Note that tabindex should not be -1 if you want to focus on the span by adding a tabindex. Make the tabindex a positive number.
I have to toggle between two icons based on some criteria. How do I do this in jQuery?
<a href='' id="home" onclick="myfunction(this)" data-toggle="toggle">
<span class="fa fa-train"></span>
</a>
myfunction($this) {
// ...
if ($($this).hasClass("fa fa-train")) {
$($this).removeClass("fa fa-train");
$($this).addClass("fa fa-car");
}
else {
$($this).addClass("fa fa-car");
$($this).addClass("fa fa-train");
}
// ...
}
clicked anchor element do not have class added, its child span does :
function myfunction($this) {
$($this).find('span').toggleClass('fa-train fa-car');
}
Do something like this
$('a#home').on('click', function(){
var childSpan = $(this).find('span');
if(childSpan.hasClass('fa-train')){
childSpan.removeClass('fa-train');
childSpan.addClass('fa-car');
}
else if(childSpan.hasClass('fa-car')){
childSpan.removeClass('fa-car');
childSpan.addClass('fa-train');
}});
you are using this which will check the a tag if has class . while you should check in the span next to a tag .you should use like this
myfunction($this) {
// ...
if ($($this).next('span').hasClass("fa fa-train")) {
$($this).next('span').removeClass("fa fa-train");
$($this).next('span').addClass("fa fa-car");
}
else {
$($this).next('span').addClass("fa fa-car");
$($this).next('span').addClass("fa fa-train");
}
// ...
}
With a condition in one line:
$($this)
.addClass((condition=(Math.random() > .5)) ? 'fa-car' : 'fa-train')
.removeClass(condition ? 'fa-train': 'fa-car')
Note: This will not work if you "use strict" and of course your code will be less readable.
Thanks everyone, yes i had to search for 'span' and add toggle class. hasClass is also good way to check beforehand that the class exist or not.
This is a concept that I came with which is a bit logical. Instead of using complicated language, what this does is it hides the add button and makes a times button while showing the message that was hidden. It is fairly simple JQuery.
$(document).ready(function() {
$("#addCross").click(function() {
document.getElementById("addCross").style.display = "none";
document.getElementById("addAdd").style.display = "inline-block";
document.getElementById("hello").style.display = "block";
});
$("#addAdd").click(function() {
document.getElementById("addCross").style.display = "inline-block";
document.getElementById("addAdd").style.display = "none";
document.getElementById("hello").style.display = "none";
});
});
/*
Unoptional CSS
Just to make the buttons look better in the snippet.
*/
button {
background: transparent;
border: none;
}
button:focus {
outline: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/9b271ce18a.js" crossorigin="anonymous"></script>
<div>
<label>Press the Button: </label>
<button id="addCross"><i class="fas fa-plus"></i>
<button id="addAdd" style="display: none;"><i class="fas fa-times"></i></button>
<div style="display: none;" id="hello">
<p>Hello. I was hidden by the Magic of JQuery.</p>
<label>This design also makes a cool rotating add sign if you look closely. Ha Ha!!</label>
</div>
Within a Angular-Kendo treeview <div>, I'm having a bit of trouble styling a <div> element which I want to show on a hover event.
Here is an image of the treeview without the icon options to the right of each node:
However I'd like to show some icons to the right once I hover on a node, as follows :
your advice is appreciated...
Here's the HTML (please notice the Kendo k-template directive used here):
<div id="treeview" kendo-tree-view
k-options="nav.treeOptions"
k-data-source="nav.reportsTreeDataSource"
k-on-change="nav.onTreeSelect(dataItem)">
<span k-template>{{dataItem.text}}
<span class="templ-icons">
<a title="add new folder" ng-click="nav.addAfter(nav.selectedItem)"><i class="fa fa-folder-open"></i></a>
<a title="add report here" ng-click="nav.addBelow(nav.selectedItem)"><i class="fa fa-plus"></i></a>
<a title="remove" ng-click="nav.remove(nav.selectedItem)"><i class="fa fa-remove"></i></a>
</span>
</span>
</div>
and of course, I want ONLY want to show the icon options when a user hovers over any particular node (i.e. could be at the folder level, or at the leaf level).
and the CSS :
<style scoped>
.templ-icons {
text-align: center;
font-size:smaller;
font-style: italic;
color: white;
}
#treeview:hover > .templ-icons {
opacity:1.0;
display:none;
}
What if you make a small directive for this? Check out this example I put together with my toggle-preview directive. I'm not including any kendo controls, but you should be able to add something like this to your custom template. You might need to make some small changes, and you can of course make it more robust, but this seems like a good situation to use something like this, and you can use whichever element you would like be it <span> <div> etc.
JSFiddle Link
<span toggle-preview>item a</span>
.active::after {
content: url(~/icon.gif);
}
app.directive('togglePreview', [function () {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
elem.on('mouseenter', function() {
elem.addClass('active');
});
elem.on('mouseleave', function() {
elem.removeClass('active');
});
}
}
}]);
Edit
Per discussion we want to attach all three pre-defined icons, and attach a ng-click handler to the icon with some sort of sense of knowing which icon we clicked. Here is a solution that is driven on a naming convention and utilizing the $compile service for directive injection based on the icon values we provide in the parent attr
Updated JSFiddle
<div toggle-preview ico="plus delete folder" >item a</div>
.add::after {
content: url(~/iconA.gif);
}
.delete::after {
content: url(~/iconB.gif);
}
.folder::after {
content: url(~/iconC.gif);
}
app.directive('togglePreview', ['$compile', function ($compile) {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
var classes = attrs.ico.split(' ');
elem.on('mouseenter', function(){
angular.forEach(classes, function(e, i) {
var node = $compile('<span ng-click="clickIco($event)"><img src="//~' + e + '.gif" ico="'+ e +'"/><span>')(scope);
elem.append(node);
})
});
elem.on('mouseleave', function(){
elem.children().remove();
});
scope.clickIco = function($event){
console.log($event.target.attributes.ico.value);
}
}
}
}]);