web-dev-qa-db-fra.com

Sélectionnez le menu déroulant avec une largeur fixe coupant le contenu dans IE

Le problème:

Certains éléments de la sélection nécessitent plus que la largeur spécifiée de 145px pour pouvoir être affichés intégralement.

Comportement Firefox : cliquer sur la sélection fait apparaître la liste des éléments déroulants ajustée à la largeur de l'élément le plus long.

Comportement IE6 & IE7 : un clic sur la sélection fait apparaître la liste des éléments déroulants limitée à une largeur de 145 pixels rendant impossible la lecture des éléments les plus longs.

L’interface utilisateur actuelle nous oblige à adapter cette liste déroulante à 145 pixels et à lui attribuer des éléments d’hôte avec des descriptions plus longues. 

Un conseil sur la résolution du problème avec IE?

L'élément du haut doit rester large de 145 pixels même lorsque la liste est développée.

Je vous remercie!

Le css: 

select.center_pull {
    background:#eeeeee none repeat scroll 0 0;
    border:1px solid #7E7E7E;
    color:#333333;
    font-size:12px;
    margin-bottom:4px;
    margin-right:4px;
    margin-top:4px;
    width:145px;
}

Voici le code d'entrée sélectionné (il n'y a pas de définition du style backend_dropbox pour le moment)

<select id="select_1" class="center_pull backend_dropbox" name="select_1">
<option value="-1" selected="selected">Browse options</option>
<option value="-1">------------------------------------</option>
<option value="224">Option 1</option>
<option value="234">Longer title for option 2</option>
<option value="242">Very long and extensively descriptive title for option 3</option>
</select>

Page html complète au cas où vous souhaiteriez tester rapidement dans un navigateur:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>dropdown test</title>

<style type="text/css">
<!--
select.center_pull {
    background:#eeeeee none repeat scroll 0 0;
    border:1px solid #7E7E7E;
    color:#333333;
    font-size:12px;
    margin-bottom:4px;
    margin-right:4px;
    margin-top:4px;
    width:145px;
}
-->
</style>
</head>

<body>
<p>Select width test</p>
<form id="form1" name="form1" method="post" action="">
<select id="select_1" class="center_pull backend_dropbox" name="select_1">
<option value="-1" selected="selected">Browse options</option>
<option value="-1">------------------------------------</option>
<option value="224">Option 1</option>
<option value="234">Longer title for option 2</option>
<option value="242">Very long and extensively descriptive title for option 3</option>
</select>
</form>
</body>
</html>
55
aaandre

Pour IE 8, il existe une solution simple basée sur css:

select:focus {
    width: auto;
    position: relative;
}

(Vous devez définir la propriété position si la zone de sélection est l'enfant d'un conteneur de largeur fixe.)

Malheureusement, IE 7 et moins ne prennent pas en charge le sélecteur: focus.

29
rusty

Je connaissais bien ce problème avec Google mais je n’ai trouvé aucune meilleure solution. Ainsi, So Created est une solution qui fonctionne très bien dans tous les navigateurs.

il suffit d'appeler la fonction badFixSelectBoxDataWidthIE () au chargement de la page.

function badFixSelectBoxDataWidthIE(){
    if ($.browser.msie){
      $('select').each(function(){
    if($(this).attr('multiple')== false){
      $(this)
          .mousedown(function(){
               if($(this).css("width") != "auto") {
                   var width = $(this).width();
                   $(this).data("origWidth", $(this).css("width"))
                          .css("width", "auto");
                   /* if the width is now less than before then undo */
                   if($(this).width() < width) {
        $(this).unbind('mousedown');
                       $(this).css("width", $(this).data("origWidth"));
                   }
               }
           })
           /* Handle blur if the user does not change the value */
           .blur(function(){
               $(this).css("width", $(this).data("origWidth"));

           })
           /* Handle change of the user does change the value */
           .change(function(){
               $(this).css("width", $(this).data("origWidth"));

           });
        }
      });
    }
    }
10
Anoop Sharma

Voici un petit script qui devrait vous aider:

http://www.icant.co.uk/forreview/tamingselect/

7
Zac

Pour une solution simple sans Javascript, ajouter un attribut title à votre <option> contenant le texte peut suffire, selon vos besoins.

<option value="242" title="Very long and extensively descriptive text">
  Very long and extensively descriptive text
</option>

Cela affichera le texte coupé sous la forme d'une info-bulle sur le survol de l'option <option>, quelle que soit la largeur de l'élément <select>. 

Fonctionne pour IE7 +.

7
islander

Je ne crains rien, javascript est gratuit

$('#del_select').mouseenter(function () {

    $(this).css("width","auto");

});

$('#del_select').mouseout(function () {

    $(this).css("width","170px");

}); 
3
stukerr

Simplement vous pouvez utiliser ce plugin pour jquery;) 

http://plugins.jquery.com/project/skinner

$(function(){
          $('.select1').skinner({'width':'200px'});
});
3
anbi

Mise à jour petite, mais utile, du code de MainMa & user558204 (merci les gars), qui supprime l’inutile chaque boucle, stocke une copie de $ (this) dans une variable de chaque gestionnaire d’événements, car elle est utilisée plus d’une fois. flou et changer les événements car ils avaient la même action.

Oui, ce n'est toujours pas parfait car il redimensionne l'élément sélectionné, plutôt que les seules options déroulantes. Mais bon, ça m’a fait sortir du pétrin, je dois (très, très malheureusement) toujours supporter une base d’utilisateurs IE6 dominante dans l’entreprise.

// IE test from from: https://Gist.github.com/527683
var ie = (function () {
  var undef, v = 3, div = document.createElement('div'), all = div.getElementsByTagName('i');
  while (
    div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
    all[0]
  );
  return v > 4 ? v : undef;
} ());


function badFixSelectBoxDataWidthIE() {
  if (ie < 9) {
    $('select').not('[multiple]')
      .mousedown(function() {
        var t = $(this);
        if (t.css("width") != "auto") {
          var width = t.width();
          t.data("ow", t.css("width")).css("width", "auto");

          // If the width is now less than before then undo
          if (t.width() < width) {
            t.unbind('mousedown');
            t.css("width", t.data("ow"));
          }
        }
      })

      //blur or change if the user does change the value
      .bind('blur change', function() {
        var t = $(this);
        t.css("width", t.data("ow"));
      });
  }
}
2
TechSpud

Pourquoi quelqu'un voudrait-il que la souris survole un événement dans une liste déroulante? Voici un moyen de manipuler IE8 pour le fonctionnement d'une liste déroulante:

Premièrement, assurons-nous que nous ne faisons que passer notre fonction dans IE8:

    var isIE8 = $.browser.version.substring(0, 2) === "8.";
    if (isIE8) {
       //fix me code
    }

Ensuite, pour permettre à la sélection de se développer en dehors de la zone de contenu, encapsulons nos listes déroulantes dans les div avec la structure correcte, si ce n'est déjà fait, puis appelons la fonction d'assistance:

        var isIE8 = $.browser.version.substring(0, 2) === "8.";
    if (isIE8) {
        $('select').wrap('<div class="wrapper" style="position:relative; display: inline-block; float: left;"></div>').css('position', 'absolute');

        //helper function for fix
        ddlFix();
    }

Maintenant sur les événements. Étant donné que IE8 génère un événement après s'être concentré pour une raison quelconque, IE fermera le widget après le rendu lors de la tentative d'extension. La solution consiste à relier 'focusin' et 'focusout' à une classe qui se développera automatiquement en fonction du texte d'option le plus long. Ensuite, pour assurer une largeur minimale constante qui ne se réduit pas au-delà de la valeur par défaut, nous pouvons obtenir la largeur actuelle de la liste de sélection et la définir sur la propriété de liste déroulante min-width du 'onchange' binding :

    function ddlFix() {
    var minWidth;

    $('select')

    .each(function () {
        minWidth = $(this).width();
        $(this).css('min-width', minWidth);
    })
    .bind('focusin', function () {
        $(this).addClass('expand');
    })
    .change(function () {
        $(this).css('width', minWidth);
    })
    .bind('focusout', function () {
        $(this).removeClass('expand');
    });
}

Enfin, assurez-vous d’ajouter cette classe à la feuille de style:

 select:focus, select.expand {
    width: auto;
}
1
Ben Sewards

Un plugin complet jQuery est disponible, consultez la page de démonstration: http://powerkiki.github.com/ie_expand_select_width/

disclaimer: J'ai codé cette chose, les correctifs sont les bienvenus

1
PowerKiKi
for (i=1;i<=5;i++){
   idname = "Usert" + i;
   document.getElementById(idname).style.width = "100%";

}

J'ai utilisé cette méthode pour afficher la liste déroulante lorsque la largeur n'est pas affichée correctement.

Cela fonctionne pour IE6, Firefox et Chrome.

1
keong

une solution similaire peut être trouvée ici en utilisant jQuery pour définir la largeur automatique lorsque focus (ou mouseenter) et définir la largeur initiale lorsque flou (ou mouseleave) http://css-tricks.com/select-cuts-off-options -in-ie-fix/

1
schrodinger's code

Une approche différente:

  1. au lieu d'une sélection en faire une zone d'édition, désactivée afin que personne ne puisse saisir quoi que ce soit manuellement ou modifier le contenu après la sélection
  2. une autre édition masquée contenant l'id d'une option sélectionnée (expliquée ci-dessous)
  3. faire un bouton [..] et le script pour montrer que div ci-dessous
  4. faire un div caché avec une position absolue sous ou près de la boîte d'édition
  5. faire que cette div contienne une sélection avec style size = "6" (pour afficher 6 options et une barre de défilement plutôt que dans une liste déroulante) et un bouton "sélectionner" et éventuellement "annuler"
  6. Ne modifiez pas la largeur de manière à ce que l'ensemble assume la largeur de l'option la plus large ou du bouton, plus éventuellement un rembourrage de votre choix
  7. écrivez le bouton "select" pour copier l'identifiant de l'option sélectionnée dans la zone d'édition masquée et sa valeur pour l'option visible, ainsi que pour masquer à nouveau le div.

Total de 4 commandes javascript simples.

1
Kitet

J'ai trouvé une solution assez simple pour cela. Dans l'élément <select> html, ajoutez ces propriétés:

onmouseover="autoWidth(this)" 
onblur="resetWidth(this)" 

Ainsi, chaque fois que l'utilisateur clique sur le fait que la largeur se développe automatiquement et qu'il quitte la zone de sélection, la largeur est réinitialisée.

1
TheOnlyOne

Pour ma mise en page, je ne voulais pas de piratage (pas de largeur croissante, pas de clic sur auto puis retour à l’original). Cela a cassé ma mise en page existante. Je voulais juste que cela fonctionne normalement comme les autres navigateurs. 

J'ai trouvé que c'était exactement comme ça: -

http://www.jquerybyexample.net/2012/05/fix-for-ie-select-dropdown-with-fixed.html

0
Steve

J'ai encore une autre contribution à cela. J'ai écrit ceci il y a quelque temps que vous pourriez trouver utile: http://dpatrickcaldwell.blogspot.com/2011/06/giantdropdown-jquery-plugin-for-styling.html

C'est un plugin jQuery qui permet de créer une liste non ordonnable à styler, appuyée par l'élément de sélection caché.

La source est sur github: https://github.com/tncbbthositg/GiantDropdown

Vous seriez capable de gérer des comportements et des styles sur l'UL que vous ne pouvez pas utiliser avec SELECT. Tout le reste devrait être identique car la liste de sélection est toujours là, elle est simplement masquée mais l'UL l'utilisera comme magasin de données de sauvegarde (si vous voulez).

0
D. Patrick

Une solution de contournement si vous ne vous souciez pas de la vue étrange après la sélection d’une option (par exemple, sélectionnez pour accéder à une nouvelle page):

<!-- Limit width of the wrapping div instead of the select and use 'overflow: hidden' to hide the right part of it. -->
<div style='width: 145px; overflow: hidden; border-right: 1px solid #aaa;'>
  <select onchange='jump();'>
    <!-- '&#9660;(▼)' produces a fake dropdown indicator -->
    <option value=''>Jump to ... &#9660;</option>
    <option value='1'>http://stackoverflow.com/questions/682764/select-dropdown-with-fixed-width-cutting-off-content-in-ie</option>
    ...
  </select>
</div>
0
Mergen Wu

Voici une solution qui fonctionne réellement. 

Il définit la largeur dans IE, ne gâche pas la mise en page et ne ferme pas la liste déroulante lorsque vous passez la souris sur les options de sélection, comme certaines des solutions de cette page. 

Cependant, vous devrez modifier les valeurs margin-right et width pour correspondre à ce que vous avez pour les champs sélectionnés. 

Vous pouvez également remplacer la $('select') par la $('#Your_Select_ID_HERE') pour n’affecter qu’un champ de sélection spécifique. De plus, vous devrez appeler la fonction fixIESelect() sur le corps onload ou via jQuery en utilisant DOM ready comme je l’ai fait dans mon code ci-dessous:

//////////////////////////
// FIX IE SELECT INPUT //
/////////////////////////
window.fixIESelect_clickset = false;
function fixIESelect()
{
 if ($.browser.msie)
 {
  $('select').mouseenter(function ()
  {
   $(this).css("width","auto");
   $(this).css("margin-right","-100");
  });
  $('select').bind('click focus',function ()
  {
   window.fixIESelect_clickset = true;
  });
  $('select').mouseout(function ()
  {
   if(window.fixIESelect_clickset != true)
   {
    $(this).css("width","93px");
    window.fixIESelect_clickset = false;
   }
  });
  $('select').bind('blur change',function ()
  {
   $(this).css("width","93px");
  });
 }
}
/////////////
// ONLOAD //
////////////
$(document).ready(function()
{
 fixIESelect();
});
0
Gallagher

Une solution purement css: http://bavotasan.com/2011/style-select-box-using-only-css/

.styled-select select {
   background: transparent;
   width: 268px;
   padding: 5px;
   font-size: 16px;
   line-height: 1;
   border: 0;
   border-radius: 0;
   height: 34px;
   -webkit-appearance: none;
   }

.styled-select {
   width: 240px;
   height: 34px;
   overflow: hidden;
   background: url(http://cdn.bavotasan.com/wp-content/uploads/2011/05/down_arrow_select.jpg) no-repeat right #ddd;
   border: 1px solid #ccc;
   }
<div class="styled-select">
   <select>
      <option>Here is the first option</option>
      <option>The second option</option>
   </select>
</div>

0
Teenage

Je voulais que cela fonctionne avec les sélections que j'ai ajoutées dynamiquement à la page. Après de nombreuses expérimentations, j'ai donc donné toutes les sélections voulues avec la classe "fixedwidth", puis j'ai ajouté le CSS suivant:

table#System_table select.fixedwidth { width: 10em; }
table#System_table select.fixedwidth.clicked { width: auto; }

et ce code

<!--[if lt IE 9]>
    <script type="text/javascript">
        jQuery(document).ready(function() {
            jQuery(document).on(
              {
                'mouseenter': function(event) {
                    jQuery(this).addClass('clicked');
                    },
                'focusout change blur': function() {
                    jQuery(this).removeClass('clicked');
                    }
              }, 'select.fixedwidth');
        });
    </script>
<![endif]-->

Quelques points à noter:

  • En dépit du fait que mes sélections sont toutes dans une table, je devais faire "on" à la jQuery(document).on au lieu de jQuery('table#System_table').on
  • Malgré le fait que la documentation jQuery indique d'utiliser "mouseleave" au lieu de "blur", j'ai constaté que dans IE7, lorsque je déplaçais la souris dans la liste déroulante, un événement mouseleave était créé, mais pas un blur.
0
Paul Tomblin

Le jQuery BalusC's solution améliorée par moi. Utilisé aussi: Commentaire de Brad Robertson ici .

Il suffit de mettre cela dans un fichier .js, d’utiliser la classe wide pour les combinaisons désirées et de ne pas forger pour lui attribuer un identifiant Appelez la fonction dans le onload (ou documentReady ou autre).
Aussi simple que ça :)
Il utilisera la largeur que vous avez définie pour le combo comme longueur minimale.

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');
    })
    }
}
0
Federico Valido

Son testé dans toutes les versions de IE, Chrome, FF et Safari

// code JavaScript

    <script type="text/javascript">
    <!-- begin hiding
    function expandSELECT(sel) {
      sel.style.width = '';
    }
    function contractSELECT(sel) {
      sel.style.width = '100px';
    }
    // end hiding -->
    </script>

// 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>
0
Arif

Je ne crains rien non plus en javascript et ma solution nécessite une bibliothèque js. Toutefois, vous ne pouvez utiliser que les fichiers dont vous avez besoin plutôt que de les utiliser tous, peut-être mieux adaptés à ceux qui utilisent déjà YUI pour leurs projets un à utiliser. Regardez: http://ciitronian.com/blog/programming/yui-button-mimicking-native-select-dropdown-avoid-width-problem/

Mon article de blog aborde également d'autres solutions. L'une d'entre elles est référencée ici sur stackoverflow. Je suis donc retourné à la création de mon propre élément SELECT parce que, pour des raisons simples, je n'aime pas les événements d'agrandissement de la souris. Peut-être que si cela aide aussi quelqu'un d'autre!

0
Hammad Tariq