body dropdown tweaks

This commit is contained in:
Kyle Spearrin 2017-04-14 23:30:58 -04:00
parent 8d6cbe8e1e
commit c4a3e5c4fd
7 changed files with 48 additions and 74 deletions

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.global') .module('bit.global')
.controller('mainController', function ($scope, $state, authService, appSettings, toastr) { .controller('mainController', function ($scope, $state, authService, appSettings, toastr, $window, $document) {
var vm = this; var vm = this;
vm.bodyClass = ''; vm.bodyClass = '';
vm.searchVaultText = null; vm.searchVaultText = null;
@ -53,83 +53,52 @@ angular
}; };
// Append dropdown menus to body // Append dropdown menus to body
var bodyScrollbarWidth; var bodyScrollbarWidth,
var bodyDropdownMenu; bodyDropdownMenu;
var dropdownHelpers = { var dropdownHelpers = {
scrollParent: function (elem, includeHidden, includeSelf) {
var overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
var documentEl = $(document).documentElement;
var elemStyle = window.getComputedStyle(elem);
if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {
return elem;
}
var excludeStatic = elemStyle.position === 'absolute';
var scrollParent = elem.parentElement || documentEl;
if (scrollParent === documentEl || elemStyle.position === 'fixed') {
return documentEl;
}
while (scrollParent.parentElement && scrollParent !== documentEl) {
var spStyle = window.getComputedStyle(scrollParent);
if (excludeStatic && spStyle.position !== 'static') {
excludeStatic = false;
}
if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {
break;
}
scrollParent = scrollParent.parentElement;
}
return scrollParent;
},
scrollbarWidth: function () { scrollbarWidth: function () {
if (!bodyScrollbarWidth) { if (!bodyScrollbarWidth) {
var bodyElem = $('body'); var bodyElem = $('body');
bodyElem.addClass('bit-position-body-scrollbar-measure'); bodyElem.addClass('bit-position-body-scrollbar-measure');
bodyScrollbarWidth = window.innerWidth - bodyElem[0].clientWidth; bodyScrollbarWidth = $window.innerWidth - bodyElem[0].clientWidth;
bodyScrollbarWidth = isFinite(bodyScrollbarWidth) ? bodyScrollbarWidth : 0; bodyScrollbarWidth = isFinite(bodyScrollbarWidth) ? bodyScrollbarWidth : 0;
bodyElem.removeClass('bit-position-body-scrollbar-measure'); bodyElem.removeClass('bit-position-body-scrollbar-measure');
} }
return bodyScrollbarWidth; return bodyScrollbarWidth;
}, },
scrollbarPadding: function (elem) { scrollbarInfo: function () {
elem = elem[0];
var scrollParent = dropdownHelpers.scrollParent(elem, false, true);
var scrollbarWidth = dropdownHelpers.scrollbarWidth();
return { return {
scrollbarWidth: scrollbarWidth, width: dropdownHelpers.scrollbarWidth(),
widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth, visible: $document.height() > $($window).height()
heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight
}; };
} }
}; };
$('.dropdown-menu-body').on('show.bs.dropdown', function (e) { $(window).on('show.bs.dropdown', function (e) {
bodyScrollbarWidth = $(e.target).find('.dropdown-menu'); var target = $(e.target);
var body = $('body'); if (!target.hasClass('dropdown-to-body')) {
body.append(bodyScrollbarWidth.detach()); return true;
}
var eOffset = $(e.target).offset(); bodyDropdownMenu = target.find('.dropdown-menu');
var body = $('body');
body.append(bodyDropdownMenu.detach());
var eOffset = target.offset();
var css = { var css = {
display: 'block', display: 'block',
top: eOffset.top + $(e.target).outerHeight() top: eOffset.top + target.outerHeight()
}; };
if (bodyScrollbarWidth.hasClass('dropdown-menu-right')) { if (bodyDropdownMenu.hasClass('dropdown-menu-right')) {
var scrollbarPadding = dropdownHelpers.scrollbarPadding(body); var scrollbarInfo = dropdownHelpers.scrollbarInfo();
var scrollbarWidth = 0; var scrollbarWidth = 0;
if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) { if (scrollbarInfo.visible && scrollbarInfo.width) {
scrollbarWidth = scrollbarPadding.scrollbarWidth; scrollbarWidth = scrollbarInfo.width;
} }
css.right = window.innerWidth - scrollbarWidth - css.right = $window.innerWidth - scrollbarWidth - (eOffset.left + target.prop('offsetWidth')) + 'px';
(eOffset.left + $(e.target).prop('offsetWidth')) + 'px';
css.left = 'auto'; css.left = 'auto';
} }
else { else {
@ -137,11 +106,16 @@ angular
css.right = 'auto'; css.right = 'auto';
} }
bodyScrollbarWidth.css(css); bodyDropdownMenu.css(css);
}); });
$('.dropdown-menu-body').on('hide.bs.dropdown', function (e) { $(window).on('hide.bs.dropdown', function (e) {
$(e.target).append(bodyScrollbarWidth.detach()); var target = $(e.target);
bodyScrollbarWidth.hide(); if (!target.hasClass('dropdown-to-body')) {
return true;
}
target.append(bodyDropdownMenu.detach());
bodyDropdownMenu.hide();
}); });
}); });

View File

@ -34,11 +34,11 @@
<tr ng-repeat="user in filteredUsers = (users | filter: (filterSearch || '') | <tr ng-repeat="user in filteredUsers = (users | filter: (filterSearch || '') |
orderBy: ['type', 'name', 'email'])"> orderBy: ['type', 'name', 'email'])">
<td style="width: 70px;"> <td style="width: 70px;">
<div class="btn-group"> <div class="btn-group dropdown-to-body">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i> <span class="caret"></span> <i class="fa fa-cog"></i> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-body"> <ul class="dropdown-menu">
<li> <li>
<a href="javascript:void(0)" ng-click="edit(user.id)"> <a href="javascript:void(0)" ng-click="edit(user.id)">
<i class="fa fa-fw fa-pencil"></i> Edit <i class="fa fa-fw fa-pencil"></i> Edit

View File

@ -38,11 +38,11 @@
<tr ng-repeat="subvault in filteredSubvaults = (subvaults | filter: (filterSearch || '') | <tr ng-repeat="subvault in filteredSubvaults = (subvaults | filter: (filterSearch || '') |
orderBy: ['name'])"> orderBy: ['name'])">
<td style="width: 70px;"> <td style="width: 70px;">
<div class="btn-group"> <div class="btn-group dropdown-to-body">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i> <span class="caret"></span> <i class="fa fa-cog"></i> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-body"> <ul class="dropdown-menu">
<li> <li>
<a href="javascript:void(0)" ng-click="users(subvault)"> <a href="javascript:void(0)" ng-click="users(subvault)">
<i class="fa fa-fw fa-users"></i> Users <i class="fa fa-fw fa-users"></i> Users

View File

@ -14,11 +14,11 @@
<tbody> <tbody>
<tr ng-repeat="user in users | orderBy: ['email']"> <tr ng-repeat="user in users | orderBy: ['email']">
<td style="width: 70px;"> <td style="width: 70px;">
<div class="btn-group"> <div class="btn-group dropdown-to-body">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i> <span class="caret"></span> <i class="fa fa-cog"></i> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-body"> <ul class="dropdown-menu">
<li> <li>
<a href="javascript:void(0)" ng-click="remove(user)" class="text-red"> <a href="javascript:void(0)" ng-click="remove(user)" class="text-red">
<i class="fa fa-fw fa-remove"></i> Remove <i class="fa fa-fw fa-remove"></i> Remove

View File

@ -115,11 +115,11 @@
</div> </div>
<div class="list-group" ng-if="model.organizations && model.organizations.length"> <div class="list-group" ng-if="model.organizations && model.organizations.length">
<div class="list-group-item" ng-repeat="org in model.organizations | orderBy: ['name']"> <div class="list-group-item" ng-repeat="org in model.organizations | orderBy: ['name']">
<div class="btn-group"> <div class="btn-group dropdown-to-body">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i> <span class="caret"></span> <i class="fa fa-cog"></i> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-body"> <ul class="dropdown-menu">
<li> <li>
<a href="javascript:void(0)" ng-click="leaveOrganization(org)" class="text-red"> <a href="javascript:void(0)" ng-click="leaveOrganization(org)" class="text-red">
<i class="fa fa-fw fa-remove"></i> Leave <i class="fa fa-fw fa-remove"></i> Leave

View File

@ -20,7 +20,7 @@
<button type="button" class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i> <span class="caret"></span> <i class="fa fa-cog"></i> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-right dropdown-menu-body"> <ul class="dropdown-menu dropdown-menu-right">
<li> <li>
<a href="#" ng-click="addLogin(null, true)"> <a href="#" ng-click="addLogin(null, true)">
<i class="fa fa-fw fa-plus-circle"></i> Add Login <i class="fa fa-fw fa-plus-circle"></i> Add Login
@ -45,11 +45,11 @@
<tr ng-repeat="login in favoriteLogins = (logins | filter: { favorite: true } | <tr ng-repeat="login in favoriteLogins = (logins | filter: { favorite: true } |
filter: (main.searchVaultText || '')) track by login.id"> filter: (main.searchVaultText || '')) track by login.id">
<td style="width: 70px;"> <td style="width: 70px;">
<div class="btn-group"> <div class="btn-group dropdown-to-body">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i> <span class="caret"></span> <i class="fa fa-cog"></i> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-body"> <ul class="dropdown-menu">
<li> <li>
<a href="javascript:void(0)" ng-click="editLogin(login)"> <a href="javascript:void(0)" ng-click="editLogin(login)">
<i class="fa fa-fw fa-pencil"></i> Edit <i class="fa fa-fw fa-pencil"></i> Edit
@ -96,7 +96,7 @@
<button type="button" class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i> <span class="caret"></span> <i class="fa fa-cog"></i> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-right dropdown-menu-body"> <ul class="dropdown-menu dropdown-menu-right">
<li> <li>
<a href="#" ng-click="addLogin(folder)"> <a href="#" ng-click="addLogin(folder)">
<i class="fa fa-fw fa-plus-circle"></i> Add Login <i class="fa fa-fw fa-plus-circle"></i> Add Login
@ -131,11 +131,11 @@
<tr ng-repeat="login in folderLogins = (logins | filter: { folderId: folder.id } | <tr ng-repeat="login in folderLogins = (logins | filter: { folderId: folder.id } |
filter: (main.searchVaultText || '')) track by login.id"> filter: (main.searchVaultText || '')) track by login.id">
<td style="width: 70px;"> <td style="width: 70px;">
<div class="btn-group"> <div class="btn-group dropdown-to-body">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i> <span class="caret"></span> <i class="fa fa-cog"></i> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-body"> <ul class="dropdown-menu">
<li> <li>
<a href="javascript:void(0)" ng-click="editLogin(login)"> <a href="javascript:void(0)" ng-click="editLogin(login)">
<i class="fa fa-fw fa-pencil"></i> Edit <i class="fa fa-fw fa-pencil"></i> Edit

View File

@ -49,11 +49,11 @@
<tr ng-repeat="login in subvaultLogins = (logins | filter: filterBySubvault(subvault) | <tr ng-repeat="login in subvaultLogins = (logins | filter: filterBySubvault(subvault) |
filter: (main.searchVaultText || '') | orderBy: ['name', 'username'])"> filter: (main.searchVaultText || '') | orderBy: ['name', 'username'])">
<td style="width: 70px;"> <td style="width: 70px;">
<div class="btn-group"> <div class="btn-group dropdown-to-body">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i> <span class="caret"></span> <i class="fa fa-cog"></i> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-body"> <ul class="dropdown-menu">
<li> <li>
<a href="javascript:void(0)" ng-click="editLogin(login)"> <a href="javascript:void(0)" ng-click="editLogin(login)">
<i class="fa fa-fw fa-pencil"></i> Edit <i class="fa fa-fw fa-pencil"></i> Edit