I don't understand why I have to wrap the scrollTop
function inside a setTimeout
. I know what is happen with setTimeout behind the scene : put function in the Callback queue (providing from web API) and gonna be executed when all code in the call stack is done. But why in this case I have this behavior without setTimeout
?
Select spain
and luxembourg
(ctrl+click) for example, stay at the bottom of the select
selector. Test with both buttons. Happen two differents behaviors.
EDIT 1: EDIT : Remove all console.log
, still not working without setTimeout
EDIT 2 : After the first answer, I tried the code from @Murali Nepalli and still not working. You can see what it happen exactly (i'm on Google Chrome)
EDIT 3 : Only appear on Chrome, my version : 75.0.3770.142 (Build officiel) (64 bits) (cohort: Stable)
$(function() { $('form').on('resetwithtimeout', function(e) { var $select = $(e.currentTarget).find('select'); $select.find('option') .filter(':selected').prop("selected", false).end() .filter(':first').prop("selected", true); setTimeout(function() { $select.scrollTop(0); }, 0); }); $('form').on('resetwithouttimeout', function(e) { var $select = $(e.currentTarget).find('select'); $select.find('option') .filter(':selected').prop("selected", false).end() .filter(':first').prop("selected", true); $select.scrollTop(0); }); $('#button1').on('click', function(e) { $('form').trigger('resetwithtimeout'); }) $('#button2').on('click', function(e) { $('form').trigger('resetwithouttimeout'); }) });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <body> <form> <select name="country" id="country-select" multiple size="5"> <option selected value="austria">Austria</option> <option value="belgium">Belgium</option> <option value="bulgaria">Bulgaria</option> <option value="croatia">Croatia</option> <option value="republic">Republic of Cyprus</option> <option value="czech">Czech Republic</option> <option value="denmark">Denmark</option> <option value="estonia">Estonia</option> <option value="finland">Finland</option> <option value="france">France</option> <option value="germany">Germany</option> <option value="greece">Greece</option> <option value="hungary">Hungary</option> <option value="ireland">Ireland</option> <option value="italy">Italy</option> <option value="latvia">Latvia</option> <option value="lithuania">Lithuania</option> <option value="luxembourg">Luxembourg</option> <option value="malta">Malta</option> <option value="netherlands">Netherlands</option> <option value="poland">Poland</option> <option value="portugal">Portugal</option> <option value="romania">Romania</option> <option value="slovakia">Slovakia</option> <option value="slovenia">Slovenia</option> <option value="spain">Spain</option> <option value="sweden">Sweden and the UK</option> </select> <button id="button1" type="button">Reset form with scroll inside setTimeout</button> <button id="button2" type="button">Reset form with scroll not inside a setTimeout</button> </form> </body>
Thanks !
You can just change the selection index of "select" element. That will reset the scroll position to top. https://jsfiddle.net/hbL8tzma/
$('form').on('resetwithouttimeout', function(e) {
var $select = $(e.currentTarget).find('select');
$select[0].selectedIndex = 0;
});
That's a Chrome bug.
For whatever reason, they try to call scrollIntoView
on the last user-selected <option> every time we programmatically change the selected property of one of the <option>s, as demonstrated in this snippet:
var $select = $('select') .on('input', function() { console.log('try to scroll inside the select'); current = 0; this.scrollTop = 0; // move to top startSelect(); $select .find('.user-selected').removeClass('user-selected') .end().find(':selected').addClass('user-selected'); }) var $options = $select.find('option'); var current = 0; console.log('select any option'); // selects all the <option>s one by one function startSelect() { setTimeout(function() { $options.prop("selected", false) .get(current).selected = true; // call recursively if ((++current) < 26) startSelect(); }, 1000); }
.user-selected { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <form> <select name="country" id="country-select" multiple size="5"> <option value="austria">Austria</option> <option value="belgium">Belgium</option> <option value="bulgaria">Bulgaria</option> <option value="croatia">Croatia</option> <option value="republic">Republic of Cyprus</option> <option value="czech">Czech Republic</option> <option value="denmark">Denmark</option> <option value="estonia">Estonia</option> <option value="finland">Finland</option> <option value="france">France</option> <option value="germany">Germany</option> <option value="greece">Greece</option> <option value="hungary">Hungary</option> <option value="ireland">Ireland</option> <option value="italy">Italy</option> <option value="latvia">Latvia</option> <option value="lithuania">Lithuania</option> <option value="luxembourg">Luxembourg</option> <option value="malta">Malta</option> <option value="netherlands">Netherlands</option> <option value="poland">Poland</option> <option value="portugal">Portugal</option> <option value="romania">Romania</option> <option value="slovakia">Slovakia</option> <option value="slovenia">Slovenia</option> <option value="spain">Spain</option> <option value="sweden">Sweden and the UK</option> </select> </form>
And since they apparently call it with the { behavior: "auto" }
option, you can't even be sure that your setTimeout(fn, 0)
will be enough to counter it.
But for what you are trying to do, maybe the reset()
method of the <form> element might suit, or even just a <button type="reset">
. These are not affected by this weird behavior:
var $form = $('form'); var $select = $form.find('select'); $form.on('reset', function() { $select.scrollTop(0); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <form> <select name="country" id="country-select" multiple size="5"> <option selected value="austria">Austria</option> <option value="belgium">Belgium</option> <option value="bulgaria">Bulgaria</option> <option value="croatia">Croatia</option> <option value="republic">Republic of Cyprus</option> <option value="czech">Czech Republic</option> <option value="denmark">Denmark</option> <option value="estonia">Estonia</option> <option value="finland">Finland</option> <option value="france">France</option> <option value="germany">Germany</option> <option value="greece">Greece</option> <option value="hungary">Hungary</option> <option value="ireland">Ireland</option> <option value="italy">Italy</option> <option value="latvia">Latvia</option> <option value="lithuania">Lithuania</option> <option value="luxembourg">Luxembourg</option> <option value="malta">Malta</option> <option value="netherlands">Netherlands</option> <option value="poland">Poland</option> <option value="portugal">Portugal</option> <option value="romania">Romania</option> <option value="slovakia">Slovakia</option> <option value="slovenia">Slovenia</option> <option value="spain">Spain</option> <option value="sweden">Sweden and the UK</option> </select> <button type="reset">Reset form</button> </form>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.