Angular-Kendo TreeView - working with div and span templates - javascript

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);
}
}
}
}]);

Related

Add/Remove element-binding in Bindinghandler - knockout

Hello I have created a list and sliced it up and added pagingnation.
All works good but I would like the user to be able to disable pagingnation and just use regular scroll.
My html mark-up looks somewhat like this atm.
<div data-bind="event: { mousewheel: ScrolledPagingnation }">
</div>
Im thinking a custom handler is the right tool for the job? but havent really have any succes adding/removing the event..
<div data-bind="toggleScroll: EnablePagingnation">
</div>
EnablePagingnation is just an observable toggeling a boolen.
How can I implement adding/removing of the 'event object on my element?
Any other suitable approach is welcome aswell.. :)
ko.bindingHandlers.toggleScroll = {
update: function (element, valueAccessor, allBindings) {
var value = valueAccessor();
if (ko.unwrap(value) === true) {
//Pseudo Code
element add "event: { mousewheel: ScrolledPagination }"
} else {
//Clean the Binding
ko.cleanNode(element);
}
}
};
Don't use cleanNode. Ever.
You don't even need a bindingHandler. Just use an expression for the event handler. I used the click event in the snippet below.
vm = {
active: ko.observable(false),
v: ko.observable(1),
addToV: function() {
vm.v(vm.v() + 1);
}
};
ko.applyBindings(vm);
#area {
height: 10rem;
width: 10rem;
background-color: lightgreen;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="area" data-bind="event: {click: active() ? addToV : null}"></div>
Activate:
<input type="checkbox" data-bind="checked: active" />
<div data-bind="text: v"></div>

ng-click to undo event AngularJs

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"
}
};

Moving a hidden <div> inside a scrollable <div> as the container scrolls

I have an Angular page with the below HTML:
<div style="overflow-y:scroll; height:700px;" data-ng-if="ctrl.items.length">
<table class="table table-striped">
<tbody>
<tr bindonce data-ng-repeat="i in ctrl.items">
<td class="note-row">
<div my-tooltip-template="nav-fo-to-bo-compare/comments-hover-template.html" my-tooltip-scope="i.navSummary">
<div break-notes nav-summary="i.navSummary" item="i" note-disable="!ctrl.allowChanges"></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
The page displays a custom tooltip for each record in the table. Below is the custom tooltip directive.
angular.module('app').directive("myTooltipTemplate", function ($compile) {
var contentContainer;
return {
restrict: "A",
scope: {
myTooltipScope: "="
},
link: function (scope, element, attrs) {
var templateUrl = attrs.myTooltipTemplate;
scope.hidden = true;
var tooltipElement = angular.element("<div class='customTooltip' ng-hide='hidden'>");
tooltipElement.append("<div ng-include='\"" + templateUrl + "\"'></div>");
element.parent().append(tooltipElement);
element
.on('mouseenter', function () { scope.hidden = false; scope.$digest(); })
.on('mouseleave', function () { scope.hidden = true; scope.$digest(); });
var toolTipScope = scope.$new(true);
angular.extend(toolTipScope, scope.myTooltipScope);
$compile(tooltipElement.contents())(toolTipScope);
$compile(tooltipElement)(scope);
}
};
});
Custom tooltip CSS class:
.customTooltip{
position:absolute;
background-color:#00adee;
z-index:2;
display:block;
right: 25px;
}
The tooltip appear properly positioned for the records that show up on the screen. It shows up on mousehover. However, when I scroll the page to view the records towards end of the table, the custom tooltip appears to be still showing up at a position where the that table record was originally present. How can I ensure that even when the user scrolls the table, the tooltips from the bottom rows will appear just as the tooltips at the top of the grid ?
Add
position:relative
to the parent container of the absolutley positioned div. That is, add position:relative to the div with class note-row.
More details can be found in this tutorial

get parent div id onclick of icon

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>

set focus on span on tab using angular js

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.

Categories