I am using select and ng-options in angularjs to show a list of years that I construct myself. I pass the current year as the default value to the select.
here is the plunker link.
My question is:
How to center the list on the default value?
My plunker is not complete because my real situation is like the one found here
http://www.cliptheme.com/demo/clip-two/AngularJs-Admin/STANDARD/#/app/form/wizard
Go to Forms / Form Wizard / Step 3 Billings
as you can see, by choosing a year, and then clicking back again on it, the menu is centered on that selected year.
But my problem is that when I pass the default year value to it, as if I have already selected, and then I click back on the list, I should see it centered on that default value, but it isn't. Once I click again on that year, and click on the list again, I see it centered.
In other words, passing a year as default value doesn't play the same role as if I selected it for the first time by clicking, because when I re-click again, it is not centered. How can we fix this problem?
Here is the CSS file for the selecter I am using: css link, this is not included in the plunker nor in the snippet, because I couldn't properly reproduce that CSS on the plunker, if you can, please do it.
var app = angular.module('app', []);
app.controller('MyCtrl', function($scope) {
$scope.dates = {};
$scope.years = [{value: 'Year', disabled: true}];
var current_year = new Date().getFullYear();
for(var i = current_year - 20; i <= current_year + 20; i++){
$scope.years.push({value: i + ''});
}
var d = new Date();
var n = d.getFullYear();
$scope.dates.startYear = n;
});
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="MyCtrl">
<label class="control-label">Year</label>
<select name="startYear" ng-model="dates.startYear" id="startYear"
ng-options="year.value as year.value disable when year.disabled for year in years"
required>
<option value="" disabled >Choose one</option>
</select>
</div>
</body>
update 1:
Here is the directive that handles this particular element:
https://pastebin.com/0diFfH6t
update 2:
Here is the plunker that shows exactly the problem even after Dekel's solution.
https://plnkr.co/edit/aWbZkp4xitvBcMmhHadI?p=preview
as you can see, on the page load, when clicked on the dropdown menu, it doesn't center on the default value.
First I gotta say that the <select> tag is not a standard tag, since the rendering of that tag is partially done by the OS and not the browser, so it behaves a little different then other elements, and you can't really apply css to everything you need there.
Having said that - there are (almost) always hacks that can be done, and I'm going to show this example as one of the hacks:
function selectfocus() {
el = event.target;
sizeWhenOpen = 5;
el.size=sizeWhenOpen;
totalHeight = el.getBoundingClientRect().height;
heightPerOption = el.scrollHeight/el.options.length;
currentIndex = el.selectedIndex;
el.scrollTop = heightPerOption * (currentIndex - Math.floor(sizeWhenOpen/2));
}
<select
onfocus="selectfocus()"
onblur="this.size=1;"
onchange="this.size=1; this.blur();">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
<option>11</option>
<option>12</option>
<option>13</option>
<option>14</option>
<option>15</option>
<option>16</option>
<option>17</option>
<option>18</option>
<option>19</option>
<option>20</option>
<option>21</option>
</select>
Since we can't control the number of elements that will be displayed when the <select> is open, i used two states - one when closed (size=0) and one when open (size=5 in the example). When the select is open - I took the current selected option (based on the index) and scrolled the select to the relevant position do make sure it's centered.
Another important note - inside your application you might need use css to position (absolute/relative) the select/it's container in order to keep the original size (the size when open is bigger than the size when closed).
And here is the angular version, based on your plunkr:
https://plnkr.co/edit/eV1sPxENpcO1xXcS6JL3?p=preview
Final note - If you need exact things from the <select> tag in your website - use an implementation of drop-down that is based on regular html elements and not select :)
Why not just write some CSS to target the span tag?
span { text-align: center; }
or better yet.... tag it to an id or class
.className { text-align: center; }
#idName { text-align: center; }
Below is a functional plunker.
Plunker Example
With reference to your Update 2 plunk link you just need to update your CSS. Specify the width(whatever you want) of your area in which you have to place the select box. This will surely fix your problem :)
.myctrl {
position: absolute;
vertical-align: top;
margin-left: 50px;
width: 200px;
}
The thing is that your example on cliptheme.com does not scroll at all. It just stays centered because the div keeps it scroll position.
So to solve your issue you just need to calculate the right position and set it to the .cs-options div. One event which could be used is _toggleSelect.
Working example (see line 370-372):
https://plnkr.co/edit/XgoeU8igSSeu044EFBCV
This is just a hint and your final solution should be more sophisticated (like not query the elements every time the list is opened).
You can apply styling to id of select box as below
<!DOCTYPE html>
<html ng-app="app">
<head>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js"></script>
<script src="script.js"></script>
</head>
<style>
#startYear{
padding:0 1% 0 10%;
}
</style>
<body>
<div ng-controller="MyCtrl">
<label class="control-label">Year</label>
<select name="startYear" ng-model="dates.startYear" id="startYear"
ng-options="year.value as year.value disable when year.disabled for year in years"
required>
<option value="" disabled >Choose one</option>
</select>
</div>
</body>
</html>
Related
I'm trying to make a personalized :hover for <option> elements in <select> selector by mouseover eventListener. But for some reasons mouseover does not fired when the mouse has been on the option element.
var selectOne = document.querySelector('.select__first');
var selectTwo = document.querySelector('.select__second');
for (var key in selectOne) {
if (key % 2 == 0)
selectOne[key].classList.add('select__option-blue');
}
for (var key in selectTwo) {
if (key % 2 == 0)
selectTwo[key].classList.add('select__option-blue');
}
function onMouseOver(e) {
var target = event.target;
var options = event.target.closest('option');
if (!options) return;
console.log(options);
}
document.addEventListener( 'mouseover', onMouseOver);
.select__element > p, span {
display: inline-block;
}
.select {
-webkit-appearance: listbox;
cursor: pointer;
}
.select__option-blue {
background-color: lightblue;
}
option {
cursor: pointer;
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style type="text/css">
</style>
</head>
<body>
<div class="select-row">
<div class="select__element">
<p>The last element: </p><span class="select__element-last"></span>
</div>
<select class="select select__first">
<option value="birds" hidden>Select an element...</option>
<option value="birds">One</option>
<option value="fishes">Two</option>
<option value="animals">Three</option>
<option value="dino">Four</option>
<option value="simplest">Five</option>
</select>
<select class="select select__second">
<option value="birds" hidden>Select an element...</option>
<option value="ploto">One</option>
<option value="trava">Two</option>
<option value="vseyad">Three</option>
</select>
</div>
<script>
</script>
</body>
</html>
Apparently, Chrome doesn't support mouse events on option elements, unless you specify the size attribute to the select element.
Mouse over option in select tag
jQuery-Select list option hover
onMouseMove doesn't fire over <option> element in Chrome
So, yes, the situation around option is a very sad. :(... As say #Veehmot - we cannot bind mouseevents on option elements of selector select normaly in pure JS.
But! In view of the fact that I did not find any clear information on stackoverflow about what exactly can be done to stylize options and select selector on pure JavaScript, I want to share my success in this direction and give the community 2 ways of solving this problem based on pure JavaScript.
I found a really two working ways for coders, who also like me will face the necessity of styling option and select on pure JavaScript without the use of frameworks (jQuery, etc.)
The first way (not direct and harder) is to make the select element with options in the form of <div> selector with <buttons> or <li> list inside. The introdusing of how it work you can see on my CodePen project-page below:
https://codepen.io/Sviatoslav_FrontEnd/pen/PQbBYQ
The second way is to connect one interesting JS library, created for options and select styling. This is really what we want, and it base on pure JavaScript with CSS. BUT! I want to admit, that this script is not mine. I found it on the open-source blog resource. So I'm not responsible for its support or help in setting up. All at your own peril and risk.
I place here a link to this JS library and support files solely to help the same as I - lovers a pure javascript.
Link: https://di-grand.com/blog?download=1&kccpid=3338&kcccount=https://di-grand.com/blog/wp-content/uploads/2016/10/select.rar
I have a page with a set of drop-downs. Changing those drop-downs generates a small snippet of code corresponding to the selection.
The sample below is a how all bindings have been written at the moment.
jQuery('#one').on('change', function(event){
var selectedElement = $(this).find('option:selected');
jQuery('#code-section').text("You have selected " + selectedElement.text());
});
.code-section {
width: 100px;
height: 50px;
margin-top: 20px;
border: 1px solid red;
padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="block" class="block-one">
<select name="one" id="one">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<div class="code-section" id="code-section">
//This is the code snippet area
</div>
</div>
I now have to add another set to the same page. It will behave exactly like the first set but will generate a different kind of snippet.
All the javascript bindings for the 1st set are coupled with element ids. How do I add another dropdown with its own bindings with minimal duplication of code?
Some of the ways I have been trying are:
Move all bindings from ids to classes - The issues with this method is that almost all operations have been done using absolute ids and corresponding attributes of those element. This will require a massive rewrite of all the JS.
Rewrite the Javascript to make it operate on parameters instead of direct bindings - This theoretically would be the right approach but will require a lot of time which is something I cannot afford at the moment.
Duplicate both markup and JS for the dropdown and change all ids in the copy - Not ideal but will the get the job done.
Is there is any other way to look at this?
First of all, I am really sorry that I could not give specific title about the issue. I have a .net 4.6.1 view page.
I want to create this feature.
Depending on the DepositType, the DefaultDeposit should display either a £ sign or %.
One of the logic, I already tried was to create another property called DefaultDepositPercent. Create a Input Box which is hidden underneath and use Jquery to display or hide this Input Box. Then in my service layer, pass the value inputted in the DefaultDepositPercent to DefaultDeposit.
However, there was an inconvenience that the mvc form also passes the DefaultDeposit value as 0. And there is also an issue of someone fiddling with the Javascript.
I have googled but could not find any answers. It is likely because I could describe the issue in few words.
Any direction would be helpful. Thanks
In bootstrap we just have to place the span tag above or below the input element to get the Prefix or Postfix effect. More Details Here
So the idea is first not to have this post / prefix span tag initially but add it either on DOM ready event or when the drop down selection changes using Jquery insertBefore and insertAfter. Here is a working sample. Hope this is helpful.
$(function() {
SetUpDepositTextBox(); // set up the input box once when DOM is ready
$('.DepositType').on('change', function() {
SetUpDepositTextBox(); // set up the text box when ever the dropdown changes
});
});
function SetUpDepositTextBox() {
$('#depositDefaultWrapper span').remove();
var $this = $('.DepositType');
if ($this.val() == "Amount") {
$('<span class="input-group-addon">£</span>').insertBefore('#depositDefaultWrapper input');
} else {
$('<span class="input-group-addon">%</span>').insertAfter('#depositDefaultWrapper input');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
Deposit Type
<select class="DepositType form-control">
<option value="Amount">Amount</option>
<option value="Percentage">Percentage</option>
</select>
Default Deposit
<div id="depositDefaultWrapper" class="input-group">
<input type="text" class="form-control" value="10">
</div>
The bootstrap pagination control doesn't appear to have an option to set the number of rows per page on the UI.
I have seen lots of pagination controls based on bootstrap but very few have this option.
bs_pagination comes close, however, it seems to just be a fixed value in the settings rather than an array.
jeasyui can do it but the license is not compatible with my project and it has a style of its own.
Something like Angular UI Pagination would fit well with the project but I don't know how to handle the missing "rows per page" component.
Is there something pre-built for what I want?
If not, how would I go about adding it to an existing control?
EDIT: I have tried adding a control to the Angular UI component using Bootstrap input groups but I end up with a really wide select box with massive amounts of padding in the grouped control.
http://plnkr.co/edit/k1ZXOBZPAfp8Nb1kLKn6?p=preview
<div class="input-group">
<span class="input-group-addon">
<uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" boundary-links="true" rotate="true" num-pages="numPages" previous-text="‹" next-text="›" first-text="«" last-text="»"></uib-pagination>
</span>
<span class="input-group-addon">
<select id="numbers" class="form-control">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</span>
</div>
You can use following link . UI Bootsrap pagination demo
And also the new codes have been changed and I think there's a problem with them. You can use following codes and also import my specific version. Then you can use it without errors.
<pagination total-items="totalItems" ng-model="currentPage" ng-show="showPagination"
ng-change="pageChanged()"></pagination>
In here, i use ng-show to hide the pagination until data is loaded. And also totalItems are loaded from the server and also you ca hard code that. And also pageChanged() is the following function and you can change that as you want.
$scope.pageChanged = function () {
console.log($scope.currentPage);
var number = parseInt(00);
number = parseInt($scope.currentPage);
if (number === 1) {
number = 0;
} else {
number = (number - 1) * 10;
}
console.log("OFFSET IS : ,", number);
getData($scope.loan.branch, $scope.loan.center, $scope.loan.fromDate, $scope.loan.toDate, number);
};
And use the following script to load angular ui setup.
<script src="lib/js/ui-bootstrap-tpls-0.11.0.js" type="text/javascript"></script>
Use this js file and you can get that from early versions of ui bootstrap. 100% working for me.
I have a div that contains text that is selected dynamically using a drop down menu. When my page loads the text shows before disappearing once the page has fully loaded. Is there any way of stopping this happening? As i only want the text to appear once it has been selected.
HTML :
<select id="selectMe">
<option value="option1">option1</option>
<option value="option2">option2</option>
<option value="option3">option3</option>
<option value="option4">option4</option> </select>
<div class="group" id="option1">asdf</div>
<div class="group" id="option2">Tilt.</div>
<div class="group" id="option3">zxcv</div>
<div class="group" id="option4">qwerty</div>
Jquery:
(function($) {
$(document).ready(function () {
$('.group').hide();
$('#option1').show();
$('#selectMe').change(function () {
$('.group').hide();
$('#'+$(this).val()).show();
})
})
})(jQuery);
It has to be hidden BEFORE your code runs. Use CSS:
.group { display: none }
Simply hide them by default:
.group {
display: none;
}
Or, if you need them to still occupy block space (to prevent page "jumps"):
.group {
visibility: hidden;
}
There is an another way round with JavaScript like this:-
document.getElementById("option1").innerHTML="asdf";
By using this you can keep the div(where the text is to be shown) empty in the starting so that there will be no chance of text being displayed before it is needed, and when a user clicks on the options then JS will just add this text to the div!
You may use innerhtml to introduce the display:none rule to avoid to hide it even if jQuery/javascript is not avalaible .
basicly, in your head right before the body tag you can do this :
<script>
var el=document.body;
el.innerHTML = "<style>.group {display: none;}</style>";
</script>
It will hide the .group elements untill jQuery is loaded and effective.
If , for some reason javaScript is not avalaible, nothing will be hidden.
You can play with it here : http://codepen.io/anon/pen/khbnp
Version with jQuery removed http://codepen.io/anon/pen/tjraw
Version without jQuery nor javaScript http://codepen.io/anon/pen/disut actually shows what's hidden by previous version