I need to scroll to a select option after the user moves it up or down and the option moves past the viewport. Note this issue is only observed on Chrome and IE11. It works fine on Firefox.
I tried using focus() or click() on the element, however, this does not work in Chrome. Note that this issue is not observed in FireFox.
Here is the HTML:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>AngularJS Select</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.css">
<script src="script.js"></script>
</head>
<body ng-app="demo">
<h1>AngularJS Select focus</h1>
<div ng-controller="mainCtrl">
<div class="col-md-5 col-sm-5">
<div class="row">
<select class="form-control" style="min-height: 200px;"
id="Items"
multiple ng-multiple="true"
ng-model="captureRemoved"
ng-options="item.Title for item in selectedItems"
ng-value="item">
</select>
</div>
</div>
<div class="col-md-1 col-sm-1" style="padding-right: 5px; padding-left: 5px;">
<div style="padding-top: 36.5px;">
<div class="pull-center">
<a type="button" ng-click="moveDown()"><span><i class="fa fa-chevron-circle-down fa-lg" style="padding-left:8px">Down</i></span></a>
</div>
</div>
</div>
</div>
</body>
</html>
Javascript:
var app = angular.module('demo', []);
app.controller("mainCtrl", function ($scope) {
$scope.selectedItems = [];//new Array();
$scope.captureRemoved = [];
$scope.item = "";
$scope.load = function () {
for (var i = 0; i < 30; i++) {
var lbl = "item" + i;
var item = {Id: i, Title: lbl};
$scope.selectedItems.push(item);
}
$scope.selectedItem = 29;
var x = 0;
};
$scope.load();
$scope.moveDown = function () {
var Id = 0;
var origin = 0;
var destination = 0;
if ($scope.captureRemoved.length == 1) {
Id = $scope.captureRemoved[0].Id;
}
for (var i = 0; i < $scope.selectedItems.length; i++) {
if ($scope.selectedItems[i].Id == Id) {
origin = i;
destination = i + 1; // increment position or move down
break;
}
}
if (destination >= 0 && destination < $scope.selectedItems.length && $scope.selectedItems[destination] != null) {
var temp = $scope.selectedItems[destination];
$scope.selectedItems[destination] = $scope.selectedItems[origin];
$scope.selectedItems[origin] = temp;
var m = document.getElementById('Items').options[destination];
//m.click(); //does not work
m.focus(); //does not work
}
};
});
I also need to set the focus on the element in case it scrolls past the viewport. e.g. Select Item 9 and click on the "Down" button twice. Now Item 9 cannot be viewed.
Can someone help?
To scroll the contents of the <select>
element, set the scrollTop
property of that element:
if (destination >= 0 && destination < $scope.selectedItems.length && $scope.selectedItems[destination] != null) {
var temp = $scope.selectedItems[destination];
$scope.selectedItems[destination] = $scope.selectedItems[origin];
$scope.selectedItems[origin] = temp;
var m = document.getElementById('Items').options[destination];
//m.click(); //does not work
//m.focus(); //does not work
$timeout(function() {
var p = m.parentElement;
//GET offsetTop of <option> element
var x = m.offsetTop;
//SET scrollTop of <select> element
p.scrollTop = x-100;
})
}
The above example uses the offsetTop
property of the <option>
element and sets the scrollTop
property of the parent <select>
element. It places the <option>
element 100 pixels below the top of the scroll window.
The DEMO on PLNKR