I have a gridview which contains a textbox control. I need to show the calendar for the user to pick the date and certain dates are to be disabled using jquery. I found a post on stackoverflow that talked about how to disable certain dates. I am done with that part, except not sure how to pass the textbox control to this jquery function. Here is the code.
<script type="text/javascript" language="javascript">
function pageLoad(sender, args) {
var enabledDays = ['09/21/2011', '10/05/2011', '10/19/2011', '11/02/2011', '11/16/2011'];
/* utility functions */
function editDays(date) {
for (var i = 0; i < enabledDays.length; i++) {
if (new Date(enabledDays[i]).toString() == date.toString()) {
return [true];
}
}
return [false];
}
/* create datepicker */
$(document).ready(function() {
$('#<%= txtInHomeDate.ClientID %>').datepicker({
beforeShow: springDate,
beforeShowDay: editDays,
dateFormat: 'mm/dd/yy',
buttonImage: 'images/cal.gif',
buttonText: 'Choose date',
firstDay: 1,
buttonImageOnly: true,
showOn: 'both',
showAnim: 'fadeIn',
onSelect: function() { $(this).trigger("onchange", null); }
});
function springDate() {
var defaultMin = new Date();
var defaultMax = new Date();
var Min = defaultMin;
var Max = defaultMax;
// make valid date from hiddenfied value format is MM/dd/yyyy
dateMin = $('#<%= hfStDate.ClientID %>').val();
dateMin = new Date(dateMin);
dateMax = $('#<%= hfEndDate.ClientID %>').val();
dateMax = new Date(dateMax);
if (dateMin && dateMax) {
Min = new Date(dateMin.getFullYear(), dateMin.getMonth(), dateMin.getDate());
Max = new Date(dateMax.getFullYear(), dateMax.getMonth(), dateMax.getDate());
}
return {
minDate: Min,
maxDate: Max
};
}
});
}
<....
<asp:TemplateField HeaderText="In-Home Date">
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:HiddenField ID="hfStDate" runat="server" Value="09/01/2011" />
<asp:HiddenField ID="hfEndDate" runat="server" Value="11/30/2011" />
<asp:TextBox ID="txtInHomeDate" runat="server" />
</ItemTemplate>
</asp:TemplateField>
Currently, it errors out since the jquery function won't find the txtInHomeDate. Could I get some help as I am pretty close to get this done? Thanks!!
Use class instead of ID:
<asp:TextBox ID="txtInHomeDate" runat="server" CssClass='textDate' />
Your JS code would looks like the following:
$('.textDate').datepicker({ ...
This will loop through all the textboxes with the given class and apply datepicker to them.
jQuery can't find your text box because each row in the Grid View contains a TextBox with a different ID. If your TextBox is always in the same column, I'd suggest using the eq selector to get all the TextBoxes at once, like:
$("tr :eq(3)").each(function() {
$(this).datepicker({
// setup here
});
});
Edit: Artem's selector is definitely more optimal than mine -- the class selector is much faster. If you need to get the hidden fields, you could use his selector above, like so:
$(".textDate").each(function() {
var $startDate = $(this).prevAll("[id$='hfStDate']");
var $endDate = $(this).prevAll("[id$='hfEndDate']");
// Datepicker setup goes here.
}
Edit 2: prev is incorrect -- it should've been prevAll. This feels very hack-y to me, and I'm sure there's a better way to accomplish this task, but regardless... Here's a link to a working jsfiddle example of this, without the datepicker.
Related
I realise this question has been asked but none of the answers worked for my project.
I have a button that when clicked calls an API, so there is a 1 second delay.
I have tried several things nothing works.
btnSave.Attributes.Add("onclick", " this.disabled = true; " + ClientScript.GetPostBackEventReference(btnSave, null) + ";");
Even that does nothing.
Prevent Double Click .Please add below code in your aspx page.
<script type="text/javascript" language="javascript">
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);
function BeginRequestHandler(sender, args) { var oControl = args.get_postBackElement(); oControl.disabled = true; }
</script>
This solution is simple and effective. On your button include this code:
OnClientClick="return CheckDouble();"
And wherever you want your JavaScript - e.g. At the bottom of your page:
<script type="text/javascript">
var submit = 0;
function CheckDouble() {
if (++submit > 1) {
alert('This sometimes takes a few seconds - please be patient.');
return false;
}
}
</script>
Most of the above suggestions failed to work for me. The one that did work was the following by tezzo:
Me.btnSave.Attributes.Add("onclick", "this.disabled=true;")
Me.btnSave.UseSubmitBehavior = False
Simpler still, rather than using the above in the code-behind, just use the following:
<asp:Button ID="btnSave" runat="server" Text="Save"
UseSubmitBehavior="false"
OnClientClick="this.disabled='true';"
</asp:button>
UseSubmitBehavior="false" is the key.
You can prevent double-clicking using this code:
Me.btnSave.Attributes.Add("onclick", "this.disabled=true;")
Me.btnSave.UseSubmitBehavior = False
So you can use btnSave_Click to call your API.
Usually I have a lot of Validators in my Page: setting Validator.SetFocusOnError = True I can run this code to reenable save button if a validation failed.
Me.YourControl.Attributes.Add("onfocus", Me.btnSave.ClientID & ".removeAttribute('disabled');")
This is the one I found works in all cases.
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button1" OnClick="Button1_Clicked" />
<asp:Button ID="Button2" runat="server" Text="Button2" />
</form>
Now here’s the short JavaScript snippet that will disable the button as soon as it is clicked so that when PostBack occurs the button cannot be clicked again.
<script type = "text/javascript">
function DisableButton() {
document.getElementById("<%=Button1.ClientID %>").disabled = true;
}
window.onbeforeunload = DisableButton;
</script>
The above script disables the ASP.Net Button as soon as the page is ready to do a PostBack or the ASP.Net form is submitted.
But in cases you might want to disable all Buttons and Submit Buttons on the page hence for such cases I have created another function which disables all Buttons and Submit buttons whenever there’s a PostBack or form submission
<script type = "text/javascript">
function DisableButtons() {
var inputs = document.getElementsByTagName("INPUT");
for (var i in inputs) {
if (inputs[i].type == "button" || inputs[i].type == "submit") {
inputs[i].disabled = true;
}
}
}
window.onbeforeunload = DisableButtons;
</script>
Prevent Double Click .Please add below code in your aspx page
<script type = "text/javascript">
function DisableButton() {
document.getElementById("<%=Button1.ClientID %>").disabled = true;
}
window.onbeforeunload = DisableButton;
</script>
At first my solution is like this:
<script>
function disableButton(btn) {
setTimeout(function () { btn.disabled = true; }, 20);
return true;
}
</script>
<asp:Button runat="server" ID="btnSave" Text="Save" OnClick="btnSave_Click" OnClientClick="return disableButton(this);" />
Without setTimeout the button will be immediately disabled and then the OnClick event will not be fired. The drawback of this approach is that the Save button will not be accessible anymore if some validation fails or some error happens.
So I don't think disable the button is a good solution, and come up with another solution:
function disableButton(btn) {
if (btn.hasclicked) return false;
btn.hasclicked = 1;
btn.onmouseenter = function () { this.hasclicked = 0; };
return true;
}
But my colleague points out that if the post processing is very slow, before it is finished, the user is still able to perform the double postback by leave-enter-click the button. So I figured out another two solutions:
Run the validation from client before submitting the form. But if your page contains multiple ValidationGroup, it is said that the following Page_ClientValidate() should be called multiple times with a passed-in ValidationGroup parameter: e.g. Page_ClientValidate("group1"):
function disableButton(btn) {
if (Page_ClientValidate) {
Page_ClientValidate();
if (!Page_IsValid) {
btn.setAttribute("btnClicked", "n");
return true;
}
}
if (btn.getAttribute("btnClicked") == "y") {
return false;
} else {
btn.setAttribute("btnClicked", "y");
return true;
}
}
As the ASP.NET has only one form in a page (not ASP.NET MVC), we can also let the onsubmit client event of the form to intercept the double click:
function disableButton(btn) {
$("form").submit(function () {
if (btn.getAttribute("btnClicked") == "y")
return false;
else
btn.setAttribute("btnClicked", "y");
return true;
});}
I'll ask QA to test those two approaches(Post edit: QA has proved that it is very dangerous to use this approach. Please refer to my following comments for details).
Try this way, it's a working solution:
For all browsers including Opera Mobile browser which doesn't support js, means your form will not be blocked in that type of browsers.
Add this in Page_load() method:
BtnID.Attributes.Add("onclick", "if(typeof (Page_ClientValidate) === 'function' && !Page_ClientValidate()){return false;} this.disabled = true;this.value = 'Working...';" + ClientScript.GetPostBackEventReference(BtnID, null) + ";");
I have a radio button inside a repeater as follow.
<asp:Repeater ID="rpt" runat="server">
<ItemTemplate>
<asp:RadioButton ID="rbtnCityName" runat="server" Text='<%# Bind("CityName") %>'
GroupName="Cities" />
</ItemTemplate>
</asp:Repeater>
Now problem is that how I can select a single radio button across multiples.
Even though I have given a groupname for radio button, I am not able to select any of them.
<script type="text/javascript" language="javascript">
function fnCheckUnCheck(objId)
{
var grd = document.getElementById("<%= rpt.ClientID %>");
var rdoArray = grd.getElementsByTagName("input");
for(i=0;i<=rdoArray.length-1;i++)
{
if(rdoArray[i].type == 'radio')
{
if(rdoArray[i].id != objId)
{
rdoArray[i].checked = false;
}
}
}
}
</script>
call this function on click of radiobutton
onclick="fnCheckUnCheck(this.id);"
the best solution for me was to simlpy create an html input control inside the repeater:
<input type="radio" name="yourGroup" value='<%# Eval("Value") %>'/>
got the solution from Radio button repeater problem solved
Just adding another solution in case someone else is still running into this in 2020...
It does use JavaScript.
If you inspect the radio button in the browser's dev tools you'll see that the RadioButton control is rendered as a span with an input inside it, just like other input controls such as CheckBox.
So this:
<asp:RadioButton runat="server" class="my-class" name="myGroup" value="myGroupOption1" />
Ends up as something like this:
<span name="myGroup" class="my-class">
<input id="(long generated id)" type="radio" name="(generated name)" value="myRadioButton">
</span>
Notice I didn't use ASP.NET's GroupName attribute. If you use that it will end up as a name attribute on the input, replaced with the generated value that is causing problems here. Just use the regular name attribute and it gets moved to the span.
Now, to fix the names in the browser you can do something like this. I used JQuery, but you could accomplish the same with pure JavaScript.
$(document).ready(function () {
$('.my-class').each(function () { // find all the spans
if ($(this).attr('name')) {
var groupName = $(this).attr('name'); // save the group name
$(this).children('input').each(function () { // find the input
$(this).attr('name', groupName); // fix the name attribute
});
}
});
});
Now the radio buttons are grouped properly.
So add a unique CSS class to your radio buttons and run that function on page load.
$('#SubmitAnswers').click(function () {
var names = [];
$('input[type="radio"]').each(function () {
// Creates an array with the names of all the different checkbox group.
names[$(this).attr('name')] = true;
});
// Goes through all the names and make sure there's at least one checked.
for (name in names) {
var radio_buttons = $("input[name='" + name + "']");
if (radio_buttons.filter(':checked').length == 0) {
// alert('none checked in ' + name);
$('#Group'+ name).css("visibility", "visible");
}
else {
// If you need to use the result you can do so without
// another (costly) jQuery selector call:
var val = radio_buttons.val();
$('#Group' + name).css("visibility", "hidden");
}
}
});
Hello, is it possible to get the current rowindex of a gridview using jQuery?
Bit of background:
I delete rows from a gridview using a server side link button in a template field like so:
<asp:LinkButton CausesValidation="false" CommandName="Delete" ID="lnkDelete"
OnClientClick="javascript: return(confirm('Delete item?'));" runat="server" Text="Delete" />
Which prompts the user to confirm or cancel the deletion. If the user clicks OK, it then calls this method on the codebehind:
protected void GridViewRowDeleting(object sender, GridViewDeleteEventArgs e)
{
this.gridview_uploads.EditIndex = -1;
if (!this.UploadsList.Count.Equals(0))
{
DocumentUpload upload = this.UploadsList[e.RowIndex];
if (upload != null)
{
this.UploadsList.RemoveAt(e.RowIndex);
this.BindInputGridview();
}
}
}
But the javascript confirm (Delete item?) looks a bit naff.
I'd much prefer to use something like JQuery's dialog, but if I do, I have no idea how to grab the rowindex using this approach (I can figure out how to call the server code).
Any ideas?
Sorry if this has already been asked - I did a trawl of SO and Googled it but couldn't find anything useful.
If the LinkButton is the only LinkButton/Anchor within the GridView, then you should be able to do something like
$('#GridView1 a').click(function(){
return confirm("Delete Item");
});
edit: change the #GridView1 to the .net ID of the control.
vb
<%=(me.GridView1.ClientID)%>
c#
<%=(this.GridView1.ClientID)%>
Reply to adrianos
If you look into the jQuery UI Dialog, this has a nice Modal Confirmation box.
In a similar way to the above code, but replacing the confirm function, you could have:
<script type="text/javascript">
$().ready(function(){
$( "#dialog" ).dialog( "destroy" );
$( "#dialog-confirm" ).dialog({
resizable: false,
height:140,
modal: true,
autoOpen: false;
buttons: {
"Delete item": function() {
$( this ).dialog( "close" );
// Put in your return true/false here to activate button
},
Cancel: function() {
$( this ).dialog( "close" );
}
}
});
$('#GridView1 a').click(function(){
$('#dialog-confirm').dialog("open");
return false;
});
)};
</script>
I figured out how to do this using the __doPostBack method (in Javascript)
>>> In the aspx:
Hidden field:
<asp:HiddenField ID="hidden_gridRowIndex" runat="server" />
In a script tag:
$(document).ready
(
function () {
$("#div_dialog_confirmUploadDelete").dialog({
autoOpen: false
, title: "Delete upload"
, buttons: {
"OK": function () {
__doPostBack('GridViewRowDelete', $("#<%# hidden_gridRowIndex.ClientID %>").val());
$(this).dialog('close');
}
, "Cancel": function () { $(this).dialog('close'); }
}
});
});
function deleteConfirm(index) {
$("#<%# hidden_gridRowIndex.ClientID %>").val(index)
$("#div_dialog_confirmUploadDelete").dialog('open');
}
On the gridview:
<asp:TemplateField>
<ItemTemplate>
<a href="javascript: void(0);" onclick='javascript:return deleteConfirm(<%# Container.DataItemIndex %>);'>Delete</a>
</ItemTemplate>
</asp:TemplateField>
>>> In the codebehind
On Page_Load:
if (Request["__EVENTTARGET"] != null)
{
switch (Request["__EVENTTARGET"])
{
case "GridViewRowDelete":
if (Request["__EVENTARGUMENT"] != null)
{
int index = -1;
if (int.TryParse(Request["__EVENTARGUMENT"], out index))
{
this.GridViewRowDelete(index);
}
}
break;
}
}
New method called by the page_load:
protected void GridViewRowDelete(int rowIndex)
{
this.gridview_uploads.EditIndex = -1;
if (!this.UploadsList.Count.Equals(0))
{
DocumentUpload upload = this.UploadsList[rowIndex];
if (upload != null)
{
this.UploadsList.RemoveAt(rowIndex);
this.BindInputGridview();
}
}
}
Thinking about it, I could have probably made the asp:HiddenField a regular html hidden input control as the server side never needs to see it.
It feels a bit ropey so feel free to throw stones at me / suggest improvements.
Add a custom attribute to your grid and set value on binding event
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<a href="#" test='<%# Container.DataItemIndex %>'>content</a>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Using .net clientId get the custom attribute value.
$(document).ready(function () {
$('#<%=(this.GridView1.ClientID)%> a').click(function () {
return alert("Last Name : " + this.getAttribute("test") );
})
}
);
In button click event how can I check all check boxes in gridview?
I dont need header checkbox.
Please provide your knowledge
awaiting your response....
Thanks
<input id="btncheckall" type="button" value="select all" />
add click event handler to button above (with jQuery)
<script type="text/javascript">
$(function(){
$("#btncheckall").click(function(){
$("#gridview input:checkbox").attr("checked","checked");
});
});
</script>
or you can use checkbox.
this is a checkbox outside gridview
<input id="checkall" type="checkbox" />
add change event handler to checkbox above (with jQuery)
<script type="text/javascript">
$(function(){
$("#checkall").change(function(){
$("#gridview input:checkbox").val( $(this).val() );
});
});
</script>
Assign a class to all your grid row check boxes and use the below script to get them all.
function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
node = document;
if ( tag == null )
tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
}
And you've to call it this way:
var messages = getElementsByClass("childbox");
Assign a class childbox to grid row child box.
document.getElementById("parentbox").onclick = function() {
for(var index=0; index < messages.length; index++) {
// prompt the content of the div
//message[index].checked = (message[index].checked) ? false : true;
}
}
you'll assign the parentbox class to the parent checkbox which is in grid header.
You don't need to define them - parentbox and childbox.
C#
Let's say you have a check all button
<asp:CheckBox ID="chkSelectAll" runat="server" Text="SelectAll"
AutoPostBack="true" OnCheckedChanged="chkSelectAll_CheckedChanged" />
and in that click event you would do something like:
protected void chkSelectAll_CheckedChanged(object sender, EventArgs e)
{
CheckBox chk; //assuming your gridview id=GridView1
foreach (GridViewRow rowItem in GridView1.Rows)
{
chk = (CheckBox)(rowItem.Cells[0].FindControl("chk1"));
chk.Checked =((CheckBox)sender).Checked;
}
}
javascript approach:
<script language="javascript">
function SelectAllCheckboxes(spanChk){
// Added as ASPX uses SPAN for checkbox
var oItem = spanChk.children;
var theBox= (spanChk.type=="checkbox") ?
spanChk : spanChk.children.item[0];
xState=theBox.checked;
elm=theBox.form.elements;
for(i=0;i<elm.length;i++)
if(elm[i].type=="checkbox" &&
elm[i].id!=theBox.id)
{
//elm[i].click();
if(elm[i].checked!=xState)
elm[i].click();
//elm[i].checked=xState;
}
}
</script>
Checkbox field as so:
<asp:CheckBox ID="chkAll" runat="server" Text="SelectAll"
onclick="javascript:SelectAllCheckboxes(this);" />
Hai Dominic,
If you want javascript look at this
https://web.archive.org/web/20210304130956/https://www.4guysfromrolla.com/articles/052406-1.aspx#postadlink
or
Check box in gridview with button
Jquery can make this easier. Hook into the external boxes onslected event, and inside there iterate the grid boxes selecting them all.
This is a great example of the evils of asp.net and how it's use by new developers really cripples them into thinking that all processing and interaction takes place server side, and all sorts of crazy hacks take place to maintain this illusion. It's backwards and insane.
Try this:
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField>
<HeaderTemplate><asp:CheckBox ID="SelectUnSelectAllCheckBox" runat="server" /></HeaderTemplate>
<ItemTemplate><asp:CheckBox ID="SelectCheckBox" runat="server" /></ItemTemplate>
</asp:TemplateField>
<!-- Other columns are omitted -->
</Columns>
</asp:GridView>
<script type="text/javascript">
$(document).ready(function(e) {
$("input[id$='SelectUnSelectAllCheckBox']").change(function() {
$("input[id$='SelectCheckBox']").attr("checked", this.checked);
});
});
</script>
If you're using jquery you could use the $('input:checkbox') selector so something like
<script type="text/javascript">
$(function() {
$('#NameOfButtonToSelectAll').click( function() {
$('input:checkbox').each( function() {
this.checked = !this.checked;
});
});
});
</script>
Kindly check it out and let me know when you got it worked.
Using Javascript :
http://wiki.asp.net/page.aspx/281/check-uncheck-checkboxes-in-gridview-using-javascript/
Using Serverside Script: (VB.Net)
https://web.archive.org/web/20211020145756/https://aspnet.4guysfromrolla.com/articles/052406-1.aspx
Using jQuery:
$('#SelectAll').click(function(){
var checked = $(this).is(':checked');
var allCheckboxes = $('table input:checkbox');
if(checked)
allCheckboxes.attr('checked','checked');
else
allCheckboxes.removeAttr('checked');
});
You probably want to change the selectors, assuming you have a class for your grid and checkbox.
In asp.net if you define an asp:ListBox as follows:
<asp:ListBox ID="listBox2" runat="server" SelectionMode="Single" Rows="3">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
<asp:ListItem>3</asp:ListItem>
<asp:ListItem>4</asp:ListItem>
<asp:ListItem>5</asp:ListItem>
<asp:ListItem>6</asp:ListItem>
<asp:ListItem>7</asp:ListItem>
<asp:ListItem Selected="True">8</asp:ListItem>
<asp:ListItem>9</asp:ListItem>
<asp:ListItem>10</asp:ListItem>
</asp:ListBox>
You will see that the selected item is visible at the top. But if you define it as a multiple selection list box, the selected items are not visible, and you have to scroll down the list to find them.
<asp:ListBox ID="listBox1" runat="server" SelectionMode="Multiple" Rows="3">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
<asp:ListItem>3</asp:ListItem>
<asp:ListItem>4</asp:ListItem>
<asp:ListItem>5</asp:ListItem>
<asp:ListItem>6</asp:ListItem>
<asp:ListItem>7</asp:ListItem>
<asp:ListItem Selected="True">8</asp:ListItem>
<asp:ListItem Selected="True">9</asp:ListItem>
<asp:ListItem>10</asp:ListItem>
</asp:ListBox>
I've done a bit of google searching, and see that this is not an uncommon problem. But I did not find any good solutions, so thought I would ask here.
My first thought was to try a bit of JQuery to solve this. What are some of your solutions?
Several of the answers don't even understand my problem. I only care about ensuring that the first selected option is visible. Make sure it is scrolled into view.
I played around with JQuery, and came up with the following:
<script type="text/javascript">
$(document).ready(function() {
$("#listBox1 option:nth-child(8)").attr('selected',true);
});
</script>
But I think I like #Cerebrus's answer the best.
Here's how I've done it in the past. Note that this scrolls the view to the last item in the listbox.
function FocusSelected()
{
var lb = document.getElementById("listBox1");
if (lb != null)
{
var options = lb.options;
for (var i = options.length - 1; i > 0 ; i--)
{
if (options[i].selected == true)
{
options[i].focus();
options[i].selected = true;
return;
}
}
}
}
It works for me on IE 7 and FF 3.0.
How are you looking to call this?
From Javascript:
<script type="text/javascript">
var myselect=document.getElementById("listBox1")
for (var i=0; i<myselect.options.length; i++){
if (myselect.options[i].selected==true){
alert("Selected Option's index: "+i)
break;
}
}
From the Code Behind:
foreach (ListItem li in listBox1.Items)
{
if (li.Selected)
{
return li;
}
}
It's bit clumsy, but I've done this once, and would welcome a better solution.
//get the selected value
var selected = (from l in lstFilterUsers.Items.Cast<ListItem>()
orderby l.Value
where l.Selected == true
select l).Take(1);
//get all the values except for that first selection
var all = (from l in lstFilterUsers.Items.Cast<ListItem>()
where l != selected
orderby l.Value
select l);
//create a temp array and fill it
ListItem[] lic = new ListItem[lstFilterUsers.Items.Count];
lic[0] = (ListItem)selected;
int i = 1;
foreach (var li in all)
{
lic[i++] = li;
}
//clear the listbox
lstFilterUsers.Items.Clear();
//readd the list
lstFilterUsers.Items.AddRange(lic);
In my limited experimentation, both Chrome and Firefox do the scrolling automatically.
For IE, I cooked this hacky bit of jQuery code up (tested on IE7):
$(document).ready(function(){
scrollToFirstSelection('select');
});
function scrollToFirstSelection(query) {
var select = $(query);
var singleOption = select.find('option')[0];
var heightOfSingleOption = select[0].offsetHeight / select.attr('size');
var indexOfFirstSelection = select.find('option').index($('option[selected=true]:first'));
select[0].scrollTop = heightOfSingleOption * indexOfFirstSelection;
}
It might not be exact if you use any crazy padding or margins, but it should be close enough.
I modified the code so as to get consistent result in both IE and FF, using scrollTo dependency for FF :
$('select').each(function () {
var options = $(this).find('option');
for (var i = options.length - 1; i > 0; i--) {
if (options[i].selected == true) {
var x = options[i];
if (jQuery.browser.msie) {
x.focus();
x.selected = true;
} else {
$(x).parents('select:eq(0)').scrollTo(x, 0);
}
return;
}
}
});
I've found that one line of client-side jQuery code solves this issue. For a multi-select listbox that arrives at the client with one or more selected options, use the power of selectors to find the first selected option. For some reason, simply calling focus() alone doesn't work, but resetting the selected to selected again will then have it scroll the selected element into view.
$(document).ready(function () {
// Scroll to **FIRST** selected option in multi select list
$("#lstCountries option:selected(:first)").focus().prop('selected', 'selected');
// Scroll to **LAST** selected option in multi select list
$("#lstStates option:selected").focus().prop('selected', 'selected');
});