Dropdownlist width in IE - javascript

In IE, the dropdown-list takes the same width as the dropbox (I hope I am making sense) whereas in Firefox the dropdown-list's width varies according to the content.
This basically means that I have to make sure that the dropbox is wide enough to display the longest selection possible. This makes my page look very ugly :(
Is there any workaround for this problem?
How can I use CSS to set different widths for dropbox and the dropdownlist?

Here's another jQuery based example. In contrary to all the other answers posted here, it takes all keyboard and mouse events into account, especially clicks:
if (!$.support.leadingWhitespace) { // if IE6/7/8
$('select.wide')
.bind('focus mouseover', function() { $(this).addClass('expand').removeClass('clicked'); })
.bind('click', function() { $(this).toggleClass('clicked'); })
.bind('mouseout', function() { if (!$(this).hasClass('clicked')) { $(this).removeClass('expand'); }})
.bind('blur', function() { $(this).removeClass('expand clicked'); });
}
Use it in combination with this piece of CSS:
select {
width: 150px; /* Or whatever width you want. */
}
select.expand {
width: auto;
}
All you need to do is to add the class wide to the dropdown element(s) in question.
<select class="wide">
...
</select>
Here is a jsfiddle example.

Creating your own drop down list is more of a pain than it's worth. You can use some JavaScript to make the IE drop down work.
It uses a bit of the YUI library and a special extension for fixing IE select boxes.
You will need to include the following and wrap your <select> elements in a <span class="select-box">
Put these before the body tag of your page:
<script src="http://us.js2.yimg.com/us.js.yimg.com/lib/common/utils/2/yahoo_2.0.0-b3.js" type="text/javascript">
</script>
<script src="http://us.js2.yimg.com/us.js.yimg.com/lib/common/utils/2/event_2.0.0-b3.js" type="text/javascript">
</script>
<script src="http://us.js2.yimg.com/us.js.yimg.com/lib/common/utils/2/dom_2.0.2-b3.js" type="text/javascript">
</script>
<script src="ie-select-width-fix.js" type="text/javascript">
</script>
<script>
// for each select box you want to affect, apply this:
var s1 = new YAHOO.Hack.FixIESelectWidth( 's1' ); // s1 is the ID of the select box you want to affect
</script>
Post acceptance edit:
You can also do this without the YUI library and Hack control. All you really need to do is put an onmouseover="this.style.width='auto'" onmouseout="this.style.width='100px'" (or whatever you want) on the select element. The YUI control gives it that nice animation but it's not necessary. This task can also be accomplished with jquery and other libraries (although, I haven't found explicit documentation for this)
-- amendment to the edit:
IE has a problem with the onmouseout for select controls (it doesn't consider mouseover on options being a mouseover on the select). This makes using a mouseout very tricky. The first solution is the best I've found so far.

you could just try the following...
styleClass="someStyleWidth"
onmousedown="javascript:if(navigator.appName=='Microsoft Internet Explorer'){this.style.position='absolute';this.style.width='auto'}"
onblur="this.style.position='';this.style.width=''"
I tried and it works for me. Nothing else is required.

I used the following solution and it seems to work well in most situations.
<style>
select{width:100px}
</style>
<html>
<select onmousedown="if($.browser.msie){this.style.position='absolute';this.style.width='auto'}" onblur="this.style.position='';this.style.width=''">
<option>One</option>
<option>Two - A long option that gets cut off in IE</option>
</select>
</html>
Note: the $.browser.msie does require jquery.

#Thad you need to add a blur event handler as well
$(document).ready(function(){
$("#dropdown").mousedown(function(){
if($.browser.msie) {
$(this).css("width","auto");
}
});
$("#dropdown").change(function(){
if ($.browser.msie) {
$(this).css("width","175px");
}
});
$("#dropdown").blur(function(){
if ($.browser.msie) {
$(this).css("width","175px");
}
});
});
However, this will still expand the selectbox on click, instead of just the elements. (and it seems to fail in IE6, but works perfectly in Chrome and IE7)

There is no way to do it in IE6/IE7/IE8. The control is drawn by the app and IE simply doesn't draw it that way. Your best bet is to implement your own drop-down via simple HTML/CSS/JavaScript if it's that important to have the the drop-down one width and the list another width.

If you use jQuery then try out this IE select width plugin:
http://www.jainaewen.com/files/javascript/jquery/ie-select-style/
Applying this plugin makes the select box in Internet Explorer appear to work as it would work in Firefox, Opera etc by allowing the option elements to open at full width without loosing the look and style of the fixed width. It also adds support for padding and borders on the select box in Internet Explorer 6 and 7.

In jQuery this works fairly well. Assume the dropdown has id="dropdown".
$(document).ready(function(){
$("#dropdown").mousedown(function(){
if($.browser.msie) {
$(this).css("width","auto");
}
});
$("#dropdown").change(function(){
if ($.browser.msie) {
$(this).css("width","175px");
}
});
});

Here is the simplest solution.
Before I start, I must tell you dropdown select box will automatically expand in almost all the browsers except IE6. So, I would do a browser check (i.e., IE6) and write the following only to that browser. Here it goes. First check for the browser.
The code will magically expands the dropdown select box. The only problem with the solution is onmouseover the dropdown will be expanded to 420px, and because the overflow = hidden we are hiding the expanded dropdown size and showing it as 170px; so, the arrow at the right side of the ddl will be hidden and cannot be seen. but the select box will be expanded to 420px; which is what we really want. Just try the code below for yourself and use it if you like it.
.ctrDropDown
{
width:420px; <%--this is the actual width of the dropdown list--%>
}
.ctrDropDownClick
{
width:420px; <%-- this the width of the dropdown select box.--%>
}
<div style="width:170px; overflow:hidden;">
<asp:DropDownList runat="server" ID="ddlApplication" onmouseout = "this.className='ctrDropDown';" onmouseover ="this.className='ctrDropDownClick';" class="ctrDropDown" onBlur="this.className='ctrDropDown';" onMouseDown="this.className='ctrDropDownClick';" onChange="this.className='ctrDropDown';"></asp:DropDownList>
</div>
The above is the IE6 CSS. The common CSS for all other browsers should be as below.
.ctrDropDown
{
width:170px; <%--this is the actual width of the dropdown list--%>
}
.ctrDropDownClick
{
width:auto; <%-- this the width of the dropdown select box.--%>
}

if you want a simple dropdown &/or flyout menu with no transition effects just use CSS... you can force IE6 to support :hover on all element using an .htc file (css3hover?) with behavior (IE6 only property) defined in the conditionally attached CSS file.

check this out.. it's not perfect but it works and it's for IE only and doesn't affect FF. I used the regular javascript for onmousedown to establish IE only fix.. but the msie from jquery could be used as well in the onmousedown.. the main idea is the "onchange" and on blur to have the select box return to normal... decide you're own width for those. I needed 35%.
onmousedown="javascript:if(navigator.appName=='Microsoft Internet Explorer'){this.style.width='auto'}"
onchange="this.style.width='35%'"
onblur="this.style.width='35%'"

BalusC's answer above works great, but there is a small fix I would add if the content of your dropdown has a smaller width than what you define in your CSS select.expand, add this to the mouseover bind:
.bind('mouseover', function() { $(this).addClass('expand').removeClass('clicked');
if ($(this).width() < 300) // put your desired minwidth here
{
$(this).removeClass('expand');
}})

This is something l have done taking bits from other people's stuff.
$(document).ready(function () {
if (document.all) {
$('#<%=cboDisability.ClientID %>').mousedown(function () {
$('#<%=cboDisability.ClientID %>').css({ 'width': 'auto' });
});
$('#<%=cboDisability.ClientID %>').blur(function () {
$(this).css({ 'width': '208px' });
});
$('#<%=cboDisability.ClientID %>').change(function () {
$('#<%=cboDisability.ClientID %>').css({ 'width': '208px' });
});
$('#<%=cboEthnicity.ClientID %>').mousedown(function () {
$('#<%=cboEthnicity.ClientID %>').css({ 'width': 'auto' });
});
$('#<%=cboEthnicity.ClientID %>').blur(function () {
$(this).css({ 'width': '208px' });
});
$('#<%=cboEthnicity.ClientID %>').change(function () {
$('#<%=cboEthnicity.ClientID %>').css({ 'width': '208px' });
});
}
});
where cboEthnicity and cboDisability are dropdowns with option text wider than the width of the select itself.
As you can see, l have specified document.all as this only works in IE. Also, l encased the dropdowns within div elements like this:
<div id="dvEthnicity" style="width: 208px; overflow: hidden; position: relative; float: right;"><asp:DropDownList CssClass="select" ID="cboEthnicity" runat="server" DataTextField="description" DataValueField="id" Width="200px"></asp:DropDownList></div>
This takes care of the other elements moving out of place when your dropdown expands. The only downside here is that the menulist visual disappears when you are selecting but returns as soon as you have selected.
Hope this helps someone.

this is the best way to do this:
select:focus{
min-width:165px;
width:auto;
z-index:9999999999;
position:absolute;
}
it's exactly the same like BalusC solution.
Only this is easier. ;)

A full fledged jQuery plugin is available. It supports non-breaking layout and keyboard interactions, check out the demo page: http://powerkiki.github.com/ie_expand_select_width/
disclaimer: I coded that thing, patches welcome

http://developer.yahoo.com/yui/examples/button/button-menu-select.html#

The jquery BalusC's solution improved by me. Used also: Brad Robertson's comment here.
Just put this in a .js, use the wide class for your desired combos and don't forge to give it an Id. Call the function in the onload (or documentReady or whatever).
As simple ass that :)
It will use the width that you defined for the combo as minimun length.
function fixIeCombos() {
if ($.browser.msie && $.browser.version < 9) {
var style = $('<style>select.expand { width: auto; }</style>');
$('html > head').append(style);
var defaultWidth = "200";
// get predefined combo's widths.
var widths = new Array();
$('select.wide').each(function() {
var width = $(this).width();
if (!width) {
width = defaultWidth;
}
widths[$(this).attr('id')] = width;
});
$('select.wide')
.bind('focus mouseover', function() {
// We're going to do the expansion only if the resultant size is bigger
// than the original size of the combo.
// In order to find out the resultant size, we first clon the combo as
// a hidden element, add to the dom, and then test the width.
var originalWidth = widths[$(this).attr('id')];
var $selectClone = $(this).clone();
$selectClone.addClass('expand').hide();
$(this).after( $selectClone );
var expandedWidth = $selectClone.width()
$selectClone.remove();
if (expandedWidth > originalWidth) {
$(this).addClass('expand').removeClass('clicked');
}
})
.bind('click', function() {
$(this).toggleClass('clicked');
})
.bind('mouseout', function() {
if (!$(this).hasClass('clicked')) {
$(this).removeClass('expand');
}
})
.bind('blur', function() {
$(this).removeClass('expand clicked');
})
}
}

You can add a style directly to the select element:
<select name="foo" style="width: 200px">
So this select item will be 200 pixels wide.
Alternatively you can apply a class or id to the element and reference it in a stylesheet

So far there isn't one. Don't know about IE8 but it cannot be done in IE6 & IE7, unless you implement your own dropdown list functionality with javascript. There are examples how to do it on the web, though I don't see much benefit in duplicating existing functionality.

We have the same thing on an asp:dropdownlist:
In Firefox(3.0.5) the dropdown is the width of the longest item in the dropdown, which is like 600 pixels wide or something like that.

This seems to work with IE6 and doesn't appear to break others. The other nice thing is that it changes the menu automatically as soon as you change your drop down selection.
$(document).ready(function(){
$("#dropdown").mouseover(function(){
if($.browser.msie) {
$(this).css("width","auto");
}
});
$("#dropdown").change(function(){
if ($.browser.msie) {
$("#dropdown").trigger("mouseover");
}
});
});

The hedgerwow link (the YUI animation work-around) in the first best answer is broken, I guess the domain got expired. I copied the code before it got expired, so you can find it here (owner of code can let me know if I am breaching any copyrights by uploading it again)
http://ciitronian.com/blog/programming/yui-button-mimicking-native-select-dropdown-avoid-width-problem/
On the same blog post I wrote about making an exact same SELECT element like the normal one using YUI Button menu. Have a look and let me know if this helps!

Based on the solution posted by Sai, this is how to do it with jQuery.
$(document).ready(function() {
if ($.browser.msie) $('select.wide')
.bind('onmousedown', function() { $(this).css({position:'absolute',width:'auto'}); })
.bind('blur', function() { $(this).css({position:'static',width:''}); });
});

I thought I'd throw my hat in the ring. I make a SaaS application and I had a select menu embedded inside a table. This method worked, but it skewed everything in the table.
onmousedown="if(navigator.appName=='Microsoft Internet Explorer'){this.style.position='absolute';this.style.width='auto'}
onblur="if(navigator.appName=='Microsoft Internet Explorer'){this.style.position=''; this.style.width= '225px';}"
So what I did to make it all better was throw the select inside a z-indexed div.
<td valign="top" style="width:225px; overflow:hidden;">
<div style="position: absolute; z-index: 5;" onmousedown="var select = document.getElementById('select'); if(navigator.appName=='Microsoft Internet Explorer'){select.style.position='absolute';select.style.width='auto'}">
<select name="select_name" id="select" style="width: 225px;" onblur="if(navigator.appName=='Microsoft Internet Explorer'){this.style.position=''; this.style.width= '225px';}" onChange="reportFormValues('filter_<?=$job_id?>','form_values')">
<option value="0">All</option>
<!--More Options-->
</select>
</div>
</td>

I've had to work around this issue and once came up with a pretty complete and scalable solution working for IE6, 7 and 8 (and compatible with other browsers obviously).
I've written a whole article about it right here: http://www.edgeoftheworld.fr/wp/work/dealing-with-fixed-sized-dropdown-lists-in-internet-explorer
Thought I'd share this for people who are still running into this problem, as none of the above solutions work in every case (in my opinion).

I tried all of these solutions and none worked completely for me. This is what I came up with
$(document).ready(function () {
var clicknum = 0;
$('.dropdown').click(
function() {
clicknum++;
if (clicknum == 2) {
clicknum = 0;
$(this).css('position', '');
$(this).css('width', '');
}
}).blur(
function() {
$(this).css('position', '');
$(this).css('width', '');
clicknum = 0;
}).focus(
function() {
$(this).css('position', 'relative');
$(this).css('width', 'auto');
}).mousedown(
function() {
$(this).css('position', 'relative');
$(this).css('width', 'auto');
});
})(jQuery);
Be sure to add a dropdown class to each dropdown in your html
The trick here is using the specialized click function (I found it here Fire event each time a DropDownList item is selected with jQuery). Many of the other solutions on here use the event handler change, which works well but won't trigger if the user selects the same option as was previously selected.
Like many of the other solutions, focus and mousedown is for when the user puts the dropdown in focus, blur is for when they click away.
You may also want to stick some kind of browser detection in this so it only effects ie. It doesn't look bad in other browsers though

Its tested in all version of IE, Chrome, FF & Safari
JavaScript code:
<!-- begin hiding
function expandSELECT(sel) {
sel.style.width = '';
}
function contractSELECT(sel) {
sel.style.width = '100px';
}
// end hiding -->
Html code:
<select name="sideeffect" id="sideeffect" style="width:100px;" onfocus="expandSELECT(this);" onblur="contractSELECT(this);" >
<option value="0" selected="selected" readonly="readonly">Select</option>
<option value="1" >Apple</option>
<option value="2" >Orange + Banana + Grapes</option>

Related

jQuery: fadeIn / fadeOut on hover - alternatives on mobile devices?

I'm using fadeIn and fadeOut in jQuery and it works fine on desktop. However, on mobile devices (I've only tested on iPhones though), the child div opens on touch but won't hide after touching an outside element. I'm fairly new to jQuery so I'm not quite sure what kind of solution I could implement here. Perhaps mobile detection and execute touch to open/hide, although I have no idea how I can do this. Here's my JSFiddle:
https://jsfiddle.net/9LL3mmzt/
jQuery:
$(document).ready(function() {
$(".parent").hover(function() {
$(this).children(".child").fadeIn("fast");
}, function() {
$(this).children(".child").fadeOut("fast");
});
});
HTML:
<div class="parent">
<span>Peek-A-</span>
<div class="child">
<span>Boo</span>
</div>
</div>
CSS:
.child {
display: none;
}
I tried the first solution from this thread: time-out on jQuery hover function
However, I could not make it work correctly due to my limited knowledge.
The hover function isn't really what you should be using on touch devices. I think you need to check out the touchstart function.
Edit 1:
An example is this:
$('div.example').on("touchstart", function (e) {
alert('testing');
});
But keep in mind that you can still use your hover javascript but you must specify this for only using it on no-touch devices. See Modernizr for this.
Hope this helps.
FYI #James Douglas as you can see I can't post any comments yet because of my reputation score. And if possible please comment or help us find the anwser for this question I think that would be more useful.
Edit 2: Modernizr is very handy. In your case you get a class touch or no-touch (on the html element) depending on which device you are.
So in my example you could use it then as $('.touch div.example')...
There are possibly different solutions but I think this is the best way (also see What's the best way to detect a 'touch screen' device using JavaScript?). You just need to add de modernizr.js file to your website (best in the head of your webpage).
Edit 3: I have tested your jsfiddle example on iPhone and Android and it works. So for me it's a good.
I was able to make this work (at least on iPhones) using the example from #Nick's post and the solution from the thread I linked in OP:
Here's the JSFiddle: https://jsfiddle.net/tkeaoffd/
JQuery:
$(document).ready(function() {
function hasTouch() {
try {
document.createEvent("TouchEvent");
return (true);
} catch (e) {
return (false);
}
}
var touchPresent = hasTouch();
$('.parent').hover(function() {
var caption = $(this).find('.child');
caption.stop(true, true).fadeIn("fast");
if (touchPresent) {
$('.parent').on("touchstart", function(e) {
$(this).children(".child").fadeToggle("fast");
});
}
}, function() {
$(this).find('.child').stop(true, true).fadeOut("fast");
});
});
HTML / CSS:
<div class="parent">
<span>Peek-A-</span>
<div class="child">
<span>Boo</span>
</div>
</div>
.child {
display: none;
}

jQuery function doesn't respond to ".click" until I move the cursor?

I have a website with a simple CSS style switcher. I use the following code for the function that handles clicking the two theme buttons, initiating the switch from dark to light and vice versa:
<script>
$(function() {
$(".light").click(function(){
$("link").attr("href", "css/lightHome.css");
$(".light").attr("disabled", "disabled");
$(".dark").removeAttr("disabled", "disabled")
})
$(".dark").click(function(){
$("link").attr("href", "css/home.css");
$(".dark").attr("disabled", "disabled");
$(".light").removeAttr("disabled", "disabled")
})
});
</script>
Everything about it operates exactly as I want, except the fact that when I click the button, nothing happens. But the second I shift the cursor position after the click, then the switch occurs. I don't have the best jQuery grasp, so I am hoping it is a simple lack of understanding regarding the DOM processes. Possibly having to do with the lack of "on ready"?
I've tried clicking and waiting several minutes, and nothing happens until I move the cursor.
The website:
http://watsoncn.info
Instead of completely switching the CSS file, an alternative solution would be to have a single CSS file with both your styles and then prefixing all your selectors with .theme.dark or .theme.light;
This would be pretty easy to do with nesting in LESS or SASS if you're using them (if you're not, you really should consider it. I can't imagine writing CSS without a preprocessor now), but might be cumbersome in pure CSS.
CSS:
.theme.dark <rest of selectors> {
//CSS
}
.theme.light <rest of selectors> {
//CSS
}
HTML:
<body class="theme">
and then code that runs on button clicks would be
$('body').addClass('dark')
$('body').removeClass('light')
and
$('body').addClass('light')
$('body').removeClass('dark')
Try this function:
function toggleCss(file, index) {
var oldFile = document.getElementsByTagName("link").item(index);
var newFile = document.createElement("link");
newFile.setAttribute("rel", "stylesheet");
newFile.setAttribute("type", "text/css");
newFile.setAttribute("href", file);
document.getElementsByTagName("head").item(0).replaceChild(newFile, oldFile);
}
$(".dark").on("click", function() {
toggleCss("css/lightHome.css");
$(".dark").attr("disabled", "disabled");
$(".light").removeAttr("disabled", "disabled");
});
$(".light").on("click", function() {
toggleCss("css/home.css");
$(".light").attr("disabled", "disabled");
$(".dark").removeAttr("disabled", "disabled");
});
Try to add use not a JavaScript, but the "checkbox trick". The checkbox handler set to display none, then style the main style, and on :checked style the handler like it clicked.
With this you can not use JavaScript but make it 100% working without any bugs, if you did everything right!
You can find the DevTips channel on YouTube
https://www.youtube.com/user/DevTipsForDesigners
on his channel you can find the tutorial how to do that!

how to Hide a div when css is disabled?

i have a div which is hidden initially and will be visible later depending on some click events results.
I have wrote this
$(document).ready(function () {
$('#<%=disable.ClientID %>').hide();
});
<div id="disable" runat="server">The following question is disabled</div>
But when i disable CSS it appears, when i don't disable css it gets invisible. how do i make this invisible even when css is disabled and visible later again
There is no way to make something invisible without CSS. But you can remove it:
$(document).ready(function () {
$('#<%=disable.ClientID %>').remove();
});
You would then need to readd all the mark up again should you wish to show it again.
Edit
You could do something like this:
$(document).ready(function () {
var item = $('#<%=disable.ClientID %>');
$(document).data('myElement', item.clone());
item.remove();
});
then you could re-add it
$(document).append($(document).data('myElement'));
If you are willing to write server code for this, then you could do this in the code-behind.
// c#
if(some condition...)
{
disable.Visible = false;
}
This will remove the div from the HTML output of the page.
I do not get you when talking about enabling and disabling css, but you can always manage the DOM elements via DOM manipulation. As you tagged jQuery:
$(document).ready(function () {
/* please try top avoid mix server side variables and javascript code */
$('#myTargetDiv').hide();
$('#myToggleButton').on('click',function(){
/* select the elements you want to hide / show with the click on this element */
var $elements = $('#myTargetDiv');
$elements.toggle();
});
});

Prevent position absolute element from sticking inside scrollable div

Having this issue with multiple items (e.g. a color picker, date picker, and a time picker) where when they pop out and are thus positioned absolute relative to the input, if a user scrolls the newly spawned element also moves with it.
Based on the nature of most plugins (all major bootstrap plugins I've noticed do this) I'm trying to think of a way to target and keep these elements fixed relative to their original location without hacking every plugin if possible.
Below is an example of the issue in which I utilized the bootstrap datepicker. Click on input to spawn datepicker and then scroll and notice the datepicker staying relative to the screen not the input.
Link to JSFiddle: http://jsfiddle.net/GuJR6/1/
Thanks!
.container {
margin-top: 15px;
height:400px;
overflow-y: scroll;
}
.scrolling-content {
height:1000px;
}
<div class="container">
<div class="scrolling-content">
<div class="well text-center">
<input type="text" class="datetimepicker" readonly>
</div>
</div>
</div>
$(".datetimepicker").datetimepicker({format: 'yyyy-mm-dd hh:ii'});
I just forked bootstrap-datetimepicker and added the container option mention by Jan Peapke. You can use it like this:
$(selector).datetimepicker({ container: nativeDOMElement });
$(selector).datetimepicker({ container: jQueryObject });
$(selector).datetimepicker({ container: jQuerySelector });
This allows you to solve your problem:
In your css:
.scrolling-content {
position: relative;
}
Compare: CSS-Tricks
js
$(".datetimepicker").datetimepicker({
format: 'yyyy-mm-dd hh:ii',
container: '.scrolling-content'
});
Fiddle
http://jsfiddle.net/marionebl/GuJR6/2/
The first input in the fiddle applies the explained fix for your issue. The second should behave like before.
Related pull request
https://github.com/smalot/bootstrap-datetimepicker/pull/215
I'm afraid the problem lies with the bootstrap datetimepicker itself.
Instead of attaching it to the same container as the input, it is attached to the body.
I looked up the documentation to see if there is an option to set the parent, but I'm afraid there is not.
As a solution you could try another framework, like jQueryUI or this plugin.
You could also try to correct the position of the picker manually by attaching a click handler to the input field that removes the datepicker from the body, adds it to the content of the scrollcontainer and uses the events mouse coordinates to position it correctly inside the container. Seems like a lot of hassle though. :)
regards,
J
$('YOURCLASSNAME').on('scroll', function () {
var $this = $('.input-group.date');
$this.datepicker('place');
});
Add above code before
Datepicker.prototype = {...}
This is the solution. and works fine on all devices and screen sizes
Even i have been facing this issue.
Found out a solution to this By adding var t;
$('YOURCLASSNAME').on('scroll', function () {
var $this = $('.input-group.date');
window.clearTimeout(t);
t = window.setTimeout(function () {
$this.datepicker('place');
}, 50)
});
Add above code after if (showFocus) this.show();
in this block
var Datepicker = function (element, options) {....} of bootstrap-datepicker.js plugin

JQuery reproducing onmouseenter logic inline at element level

I have a very large HTML page whereby an enterprise user is displaying thousands of database records as part of a batch-update/validation process.
Within the page I need to add tooltips to many of the elements. Previously we have used the trusty approach of doing this in the <head>:
$("elementID").mouseenter(function(){
// tool tip logic
// goes here
});
The problem is that this is adding tens of thousands of lines of JavaScript and causing massive performance problems. So, I am researching the differences of applying this at element level instead. So rather than having the above code for each element that requires a tooltip, I am declaring a single script block like this:
function ShowTooltip(ctrl, tooltip) {
var o = $(ctrl).offset();
var y = o.top;
var x = o.left;
$("#ttfloat").css({ top: o.top, left: o.left });
$("#ttfloat").html(tooltip);
$("#ttfloat").show();
}
function HideToolTip() {
$("#ttfloat").hide();
}
And then firing this using the following approach for each respective element:
<div id="ttfloat"> </div>
<p>Tool tip <span id="lbl1" runat="server" onmouseover="ShowTooltip(this, 'Tip Text');" onmouseout="HideToolTip();">appears here</span></p>
The problem is that when hovering over the <span> elements, there is a flicker of the tooltip element as the browser fires onmouseover repeatedly. I read on other SO solutions that JQuery mouseenter is the way to go to solve this, but can only find examples that wire up the events in the head. Can it be done in-line in the element, or is there a better way altogether? The solution must work with older browsers and be standards compliant.
See JSFiddle
How about something like this:
<span data-tooltip-text="Tip text here">blah blah</span>
And then:
$("[data-tooltip-text]").on({
mouseenter : function() {
var o = $(this).offset();
var tooltip = $(this).attr("data-tooltip-text");
$("#ttfloat").css({ top: o.top, left: o.left })
.html(tooltip)
.show();
},
mouseleave : function() {
$("#ttfloat").hide();
}
});
Demo: http://jsfiddle.net/szCU2/2/
I'd suggest you offset the vertical position of the tooltip a little bit, so that it doesn't completely cover the element that you're hovering over (which is clunky looking, and can potentially cause a mouseleave event since the mouse is then over the tooltip):
o.top + 18; // or whatever offset works for you
Demo: http://jsfiddle.net/szCU2/3/
If the behavior is the same in all of them, you should use a class selector instead of an id selector and simply add that class to all of your divs. Then you just need that code once rather than having a copy of it for every single div. Store the data somewhere useful (like a custom attribute for the div) and use that in your code.
html:
<div id="blah" class="divWithTooltip" data-custom-attribute="some tooltip text">
javascript:
$('.divWithTooltip')
.on('mouseenter', function() {
someMethodToDoYourTooltipStuff( $(this).attr('data-custom-attribute') );
})
.on('mouseout', function() {
someMethodToHideYourTooltip();
});

Categories