Css псевдо-элемент (треугольник за пределами tr) позиция смещена, когда появляется полоса прокрутки
У меня есть панель, высота которой фиксирована, и overflow-y:auto;
в этой панели я показываю таблицу, и когда пользователь нажимает на одну из строк, появляется треугольник в правой части строки, который работает нормально, пока полоса прокрутки не появится список таблиц. если на панели появляется панель прокрутки, то справа появляется панель. как решить эту проблему?
Вот Working Fiddle, а также я добавил полный фрагмент кода ниже, а изображение с проблемой ![соответствующее изображение]()
(function() {
'use strict';
angular
.module('app', [])
.controller('TableController', function($log, $scope) {
$scope.tables = [{
"name": "one_table",
"purpose": "test"
},
{
"name": "one_",
"purpose": "test"
}, {
"name": "two_",
"purpose": "test"
}, {
"name": "three_",
"purpose": "test"
}, {
"name": "four_",
"purpose": "test"
}, {
"name": "five_",
"purpose": "test"
}, {
"name": "six_",
"purpose": "test"
}, {
"name": "seven_",
"purpose": "test"
}, {
"name": "eight_",
"purpose": "test"
}, {
"name": "nine_",
"purpose": "test"
}, {
"name": "ten_",
"purpose": "test"
}
];
$scope.tindex = -1;
$scope.rowClicked = function(idx) {
$scope.tindex = idx;
}
});
})();
.panel-body {
display: block;
height: 230px;
overflow-x: hidden;
overflow-y: auto;
}
table {
width: 100%;
max-width: 100%;
}
.arrow-left:after {
border-bottom: 20px solid transparent;
border-left: 20px solid #eee;
border-right: 20px solid transparent;
border-top: 20px solid transparent;
clear: both;
content: '';
float: right;
height: 0px;
margin: 1px auto;
position: absolute;
right: 8px;
width: 0px;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="#" onclick="location.href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'; return false;" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<body ng-controller="TableController">
<div class="row col-md-12">
<div class="col-md-4" data-define="tables">
<div class="panel panel-default">
<div class="panel-heading">
<span>Tables</span>
</div>
<div class="panel-body no-padding">
<table class="table table-striped">
<tbody>
<tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)" ng-class="tindex === $index ? 'arrow-left' : ''">
<td>{{table.name}}</td>
<td>{{table.purpose}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
Ответы
Ответ 1
Наконец, я решил это по специальной директиве и немного CSS и с помощью моего коллеги.
добавьте настраиваемую директиву в панели и вычислите положение щелкнутой строки и высоты панели и переместите класс стрелки (без псевдоэлемента). Ниже приведен полный код
(function() {
'use strict';
angular
.module('app',[])
.controller('TableController', function($log, $scope) {
$scope.tables = [
{
"name": "one_table",
"columns": [
{"name": "id"},{"name": "f_name"}
]
},
{
"name": "one_",
"columns": []
}, {
"name": "two_",
"columns": []
}, {
"name": "three_",
"columns": []
}, {
"name": "four_",
"columns": []
}, {
"name": "five_",
"columns": []
}, {
"name": "six_",
"columns": []
}, {
"name": "seven_",
"columns": []
}, {
"name": "eight_",
"columns": []
}, {
"name": "nine_",
"columns": []
}, {
"name": "ten_",
"columns": []
}
];
$scope.tindex = -1;
$scope.rowClicked = function (idx) {
$scope.tblRowClicked = idx;
$scope.tindex = idx;
}
}).directive('showArrow', function($window, $timeout) {
return {
restrict: 'A',
link: function(scope, element) {
// change the arrow position
var minHeight, maxHeight, maxWidth, tableHeight, style;
var row, rowPos, arrow;
var changeArrowPosition = function() {
$timeout(function() {
row = element.find('.hover');
rowPos = row.position(); // get position of clicked row
//console.log("rowPos:minHeight:maxHeight:tableHeight", rowPos, minHeight, maxHeight,tableHeight);
arrow = element.children('.dir-right');
arrow.hide();
if (rowPos) {
if (rowPos.top >= minHeight && rowPos.top <= maxHeight) {
style = {"top": rowPos.top + "px"};
arrow.css(style);
// if table height is lesser than panel height
if (tableHeight <= maxHeight && maxWidth > 435) {
style = {"margin": "auto 5px"};
arrow.css(style);
}
arrow.addClass('arrow-right').show();
}
}
});
};
element.on("click scroll", function() {
var elem = angular.element(this);
maxHeight = elem.height(); // panel height
maxWidth = elem.width(); //panel width
tableHeight = elem.children('table').height(); // table height
minHeight = elem.children('table').find('tr').eq(0).height(); // firt row height
changeArrowPosition();
});
}
};
});
})();
.panel-body {
display: block;
height: 230px;
padding: 0px !important;
overflow-x: hidden;
overflow-y: auto;
}
table {
width:100%;
max-width: 100%;
}
tr {
cursor: pointer;
}
tr.hover {
background-color: #e5ee4f!important;
}
.arrow-right {
border-bottom: 20px solid transparent;
border-left: 20px solid #e5ee4f;
border-right: 20px solid transparent;
border-top: 20px solid transparent;
clear: both;
content: '';
float: right;
height: 0px;
left: 96%;
margin: 0px auto;
position: absolute;
width: 0px;
}
.dir-right {
display: none;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<body ng-controller="TableController">
<div class="row">
<div class="col-md-12">
<div class="col-md-4" data-define="tables">
<div class="panel panel-default">
<div class="panel-heading">
<span>Tables</span>
</div>
<div class="panel-body" show-arrow>
<table class="table table-striped">
<tbody >
<tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)" ng-class="tindex === $index ? 'hover' : ''">
<td>{{table.name}}</td>
</tr>
</tbody>
</table>
<i ng-if="vm.tblRowClicked === vm.tindex" class="dir-right"></i>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Ответ 2
Похоже, что псевдоэлемент неправильно расположен, даже если tr
задан position: relative
Эта проблема может быть исправлена добавлением псевдоэлемента в td.
<tr ng-repeat="table in tables track by $index" >
<td ng-click="rowClicked($index)" ng-class="tindex === $index ? 'arrow-left' : ''">{{table.name}}</td>
</tr>
и слегка измените CSS:
table tbody tr td {
position: relative;
}
.arrow-left:after {
border-bottom: 20px solid transparent;
border-left: 20px solid #eee;
border-right: 20px solid transparent;
border-top: 20px solid transparent;
clear: both;
content: '';
float: right;
height: 0px;
margin: 1px auto;
position: absolute;
top: -3px;
right: -18px;
width: 0px;
}
Я не уверен, что перемещение события click в td
является для вас решением.
jsbin
Обновление
Чтобы работать с несколькими td
, обновите CSS, как показано ниже:
table tbody tr td {
position: relative;
}
.arrow-left td:last-of-type:after {
border-bottom: 20px solid transparent;
border-left: 20px solid #eee;
border-right: 20px solid transparent;
border-top: 20px solid transparent;
clear: both;
content: '';
float: right;
height: 0px;
position: absolute;
top: -2px;
right: 0;
width: 0px;
}
jsbin
Ответ 3
Если вы примените position: relative
к элементу таблицы, стрелка не выйдет из контейнера. По какой-то причине спецификация говорит position: relative
on table-row
, а другие элементы таблицы - undefined
.
Здесь спецификация для получения дополнительной информации:
https://www.w3.org/TR/CSS21/visuren.html#propdef-position
Ответ 4
Вы ожидали такого.
(function() {
'use strict';
angular
.module('app', [])
.controller('TableController', function($log, $scope) {
$scope.tables = [{
"name": "one_table",
"purpose": "test"
},
{
"name": "one_",
"purpose": "test"
}, {
"name": "two_",
"purpose": "test"
}, {
"name": "three_",
"purpose": "test"
}, {
"name": "four_",
"purpose": "test"
}, {
"name": "five_",
"purpose": "test"
}, {
"name": "six_",
"purpose": "test"
}, {
"name": "seven_",
"purpose": "test"
}, {
"name": "eight_",
"purpose": "test"
}, {
"name": "nine_",
"purpose": "test"
}, {
"name": "ten_",
"purpose": "test"
}
];
$scope.tindex = -1;
$scope.rowClicked = function(idx) {
$scope.tindex = idx;
}
});
})();
.panel-body {
display: block;
height: 230px;
overflow-x: hidden;
overflow-y: auto;
}
table {
color:#000!important;
width: 100%;
max-width: 100%;
}
.arrow-left:after {
border-bottom: 15px solid transparent;
border-left: 15px solid #eee;
border-right: 15px solid transparent;
border-top: 15px solid transparent;
clear: both;
content: '';
float: right;
height: 0px;
margin: 1px auto;
position: relative;
right: 8px;
width: 0px;
}
.arrow-left1:after {
border-bottom: 15px solid transparent;
border-left: 15px solid #eee;
border-right: 15px solid transparent;
border-top: 15px solid transparent;
clear: both;
content: '';
float: left;
height: 0px;
margin: 1px auto;
position: relative;
right: 0px;
width: 0px;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<body ng-controller="TableController">
<div class="row col-md-12">
<div class="col-md-4" data-define="tables">
<div class="panel panel-default">
<div class="panel-heading">
<span>Tables</span>
</div>
<div class="panel-body no-padding">
<table class="table table-striped">
<tbody>
<tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)">
<td>{{table.name}}</td>
<td>{{table.purpose}}</td>
<td ng-class="tindex === $index ? 'arrow-left' : ''"></td>
</tr>
</tbody>
</table>
</div>
<br><br>
<div class="panel-body no-padding">
<table class="table table-striped">
<tbody>
<tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)" ng-class="tindex === $index ? 'arrow-left1' : ''">
<td>{{table.name}}</td>
<td>{{table.purpose}}</td>
<td>{{table.purpose}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
Ответ 5
пожалуйста, проверьте эти результаты, я думаю, что он работает правильно, ожидая
(function() {
'use strict';
angular
.module('app',[])
.controller('TableController', function($log, $scope) {
$scope.tables = [
{
"name": "one_table",
"columns": [
{"name": "id"},{"name": "f_name"}
]
},
{
"name": "one_",
"columns": []
}, {
"name": "two_",
"columns": []
}, {
"name": "three_",
"columns": []
}, {
"name": "four_",
"columns": []
}, {
"name": "five_",
"columns": []
}, {
"name": "six_",
"columns": []
}, {
"name": "seven_",
"columns": []
}, {
"name": "eight_",
"columns": []
}, {
"name": "nine_",
"columns": []
}, {
"name": "ten_",
"columns": []
}
];
$scope.tindex = -1;
$scope.rowClicked = function (idx) {
$scope.tindex = idx;
}
});
})();
.panel-body {
display: block;
height: 230px;
overflow-x: hidden;
overflow-y: auto;
}
table {
width:100%;
max-width: 100%;
}
.table tbody tr td {
border-top: 0px !important;
}
.arrow-left:after {
border-bottom: 20px solid transparent;
border-left: 20px solid #ccc;
/* border-right: 20px solid transparent; */
border-top: 20px solid transparent;
clear: both;
content: '';
float: right;
height: 0px;
/* margin: 1px auto; */
position: relative;
right:8px;
width: 0px;
}
table tr {
width:100%;
position:relative;
border-top: 1px solid #ccc;
}
table tr td {
width:100%;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="#" onclick="location.href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'; return false;" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<body ng-controller="TableController">
<div class="row col-md-12">
<div class="col-md-4" data-define="tables">
<div class="panel panel-default">
<div class="panel-heading">
<span>Tables</span>
</div>
<div class="panel-body no-padding">
<table class="table table-striped">
<tbody >
<tr ng-repeat="table in tables track by $index" ng-click="rowClicked($index)" ng-class="tindex === $index ? 'arrow-left' : ''">
<td>{{table.name}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-md-4" data-define="tables">HERE </div>
</div>
</div>
</body>
</html>