angular.module('demo', []).controller('ctrl' ,function ($scope){
$scope.btn1Func = function(){
$scope.text.push("Button1");
};
$scope.btn2Func = function(){
$scope.text.push("Button2");
};
$scope.btn3Func = function(){
$scope.text.push("Button3");
};
$scope.text = [];
$scope.options1= {isExpanded:false};
$scope.options2 = {isExpanded:false, display:"ClickMe"};
}).directive('flyOut', ['$window', function($window){
var template = "<div class='flyoutContainer' tabindex='0' ng-click='click();' ng-blur='lostFocus();' ng-class='{\"expanded\": options.isExpanded}'>" +
"<div class='expanderContainer' >" +
"{{options.display || 'Expand'}}" +
"" +
"</div>" +
"<div class='flyout' ng-transclude ></div>" +
"</div>";
function link(scope, element){
scope.lostFocus = function lostFocus(){
scope.options.isExpanded = false;
clearFlyoutPosition();
};
scope.click = function click(){
updateFlyoutPosition();
scope.options.isExpanded = !scope.options.isExpanded;
if (!scope.options.isExpanded){
clearFlyoutPosition();
}
};
function clearFlyoutPosition(){
var $flyoutElement = angular.element(element[0].querySelector('.flyout'));
$flyoutElement.css('top', 'auto');
$flyoutElement.css('left', 'auto');
// $flyoutElement.css('right', 'auto');
}
function updateFlyoutPosition(){
var flyoutElement = element[0].querySelector('.flyout'),
$flyoutElement = angular.element(flyoutElement);
if ($window.innerHeight < flyoutElement.getBoundingClientRect().bottom){
$flyoutElement.css('top', '-' +
(flyoutElement.getBoundingClientRect().height ) + "px");
}
else{
// set the top to the flyout container so it starts right at the bottom.
$flyoutElement.css('top',
'auto');
}
if ($window.innerWidth < flyoutElement.getBoundingClientRect().right){
// angular.element(flyoutElement).css('right', 0);
$flyoutElement.css('left', "-" +
(flyoutElement.getBoundingClientRect().right - $window.innerWidth + 10) + "px");
}
else{
// angular.element(flyoutElement).css('right', 'auto');
$flyoutElement.css('left', 'auto');
}
}
}
return {
restrict: 'E',
transclude: true,
template: template,
scope:{
options : '='
},
link: link
};
}]);
<div ng-controller='ctrl'>
<fly-out options='options1'>
<ul>
<li ng-click='btn1Func()'>Print1</li>
<li ng-click='btn2Func()'>Print2</li>
<li ng-click='btn3Func()'>Print3</li>
</ul>
</fly-out>
<div ng-repeat='line in text track by $index'>{{line}}</div>
<div class='bottomContainer'>
<fly-out options='options2'>
<ul>
<li ng-click='btn1Func()'>Print1</li>
<li ng-click='btn2Func()'>Print2 </li>
<li ng-click='btn3Func()'>Print3 </li>
</ul>
</fly-out>
</div>
</div>
.flyoutContainer{
outline:none;
position: relative;
}
.expanderContainer{
cursor:pointer;
}
.expanderContainer::after{
content:'';
height:0;
width:0;
border-top: 10px solid black;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
position:relative;
right:0;
top: 15px;
}
.flyout{
position:absolute;
top:auto;
left:auto;
z-index:1;
visibility:hidden;
background-color:yellow;
}
.expanded .flyout{
visibility:visible;
}
.bottomContainer{
position:fixed;
bottom:0;
right:0;
}