92 Stimmen

Verschachtelte optgroups in einer Dropdownliste/select

Ich habe ein benutzerdefiniertes c# DropDownList-Steuerelement erstellt, das seine Inhalte als optgroups rendern kann (Nicht von Grund auf neu, ich habe einige im Internet gefundenen Codes bearbeitet, obwohl ich genau verstehe, was es macht), und es funktioniert gut.

Allerdings bin ich nun auf eine Situation gestoßen, in der ich zwei Ebenen von Einrückungen in meinem Dropdown benötige, d.h.

     A.1 

       A.B.1 

     A.2 

Allerdings wird im obigen Beispiel-Snippet angezeigt, als wäre Ebene Zwei genauso eingerückt wie Ebene Eins.

Gibt es eine Möglichkeit, das verschachtelte optgroup-Verhalten zu erreichen, nach dem ich suche?

0 Stimmen

Hinzugefügt dieses Thema als Vorschlag an das HTMLWG: github.com/whatwg/html/issues/5789

5voto

Matthew Groves Punkte 23929

Ich denke, wenn Sie etwas haben, das strukturiert und komplex ist, sollten Sie vielleicht etwas anderes als ein einzelnes Dropdown-Feld in Betracht ziehen.

4 Stimmen

Nicht mein Design, ich setze nur Dinge um, obwohl ich zustimme, dass es vernünftigerweise verrückt ist. Ein Teil der Freude, an einem vorab vereinbarten Design zu arbeiten.

5voto

James Billingham Punkte 760

Ich weiß, dass das schon eine Weile her ist, aber ich habe noch etwas hinzuzufügen:

Dies ist in HTML5 oder in früheren Spezifikationen nicht möglich, noch ist es in HTML5.1 vorgeschlagen. Ich habe eine Anfrage an die public-html-comments-Mailingliste geschickt, aber wir werden sehen, ob etwas daraus wird.

Ungeachtet dessen, ob dies mit schon möglich ist, können Sie einen ähnlichen Effekt mit dem folgenden HTML und etwas CSS für die Optik erzielen: Vereinigte Staaten

`* Nordosten

  • New Hampshire
  • Vermont
  • Maine
    • Südosten
  • Georgia
  • Alabama`

    `* Kanada

  • Ontario
  • Quebec
  • Manitoba`

Als zusätzlichen Vorteil bedeutet dies auch, dass Sie die Auswahl der selbst ermöglichen können. Dies könnte nützlich sein, wenn Sie zum Beispiel verschachtelte Kategorien haben, in denen die Kategorien detailliert sind und Sie Benutzern ermöglichen möchten, weiter oben in der Hierarchie zu wählen.

All dies funktioniert ohne JavaScript, aber Sie könnten einige verwenden, um die Radiobuttons auszublenden und dann die Hintergrundfarbe des ausgewählten Elements zu ändern oder etwas Ähnliches.

Bitte beachten Sie, dass dies keine perfekte Lösung ist, aber wenn Sie unbedingt ein verschachteltes Select-Menü mit vernünftiger Browserkompatibilität benötigen, ist dies wahrscheinlich so nahe wie Sie kommen werden.

0 Stimmen

Können Sie einige Beispielformate für CSS hinzufügen, für diejenigen unter uns, die CSS nicht so gut kennen, wie wir sollten?

0 Stimmen

Das ist nichts weiter als eine verschachtelte Liste. Das verfehlt völlig den Sinn der Frage, die eine Art von ausklappbarer Liste haben soll.

1 Stimmen

@Cerbrus Vielleicht solltest du die Frage noch einmal lesen. An keinem Punkt wird behauptet, dass die Abschnitte ausklappbar sein müssen. Das spezifische Problem, das er lösen wollte, war eine Methode, um verschachtelte s zu haben, die eingerückt sind. Natürlich kann man HTML mit einigen sehr einfachen CSS und/oder JS wie ein Dropdown-Menü rendern lassen, aber der OP war nicht auf der Suche nach Hilfe dafür.

4voto

Matija Nalis Punkte 640

Ich brauchte eine saubere und leichte Lösung (also kein jQuery und Ähnliches), die genau wie einfaches HTML aussehen würde, auch weiterhin funktionieren würde, wenn nur einfaches HTML vorhanden ist (JavaScript es also nur verbessern würde) und die die Suche nach Anfangsbuchstaben ermöglichen würde (einschließlich nationaler UTF-8-Buchstaben), falls möglich, ohne zusätzliches Gewicht hinzuzufügen. Es muss auch schnell auf sehr langsamen Browsern funktionieren (denken Sie an rPi - also idealerweise kein JavaScript, das nach dem Laden der Seite ausgeführt wird).

In Firefox verwendet es CSS-Einzüge und ermöglicht so die Suche nach Buchstaben, während es in anderen Browsern zur Einrückung verwendet (dort jedoch die schnelle Suche nach Buchstaben nicht unterstützt). Wie auch immer, ich bin ziemlich zufrieden mit den Ergebnissen.

Sie können hier eine Demo sehen

Es funktioniert so:

CSS:

.i0 { }
.i1 { margin-left: 1em; }
.i2 { margin-left: 2em; }
.i3 { margin-left: 3em; }
.i4 { margin-left: 4em; }
.i5 { margin-left: 5em; }

HTML (Klasse "i1", "i2" usw. geben die Einrückungsebene an):

Svugdje
Bosna i Hercegovina
Babin Do  
Banja Luka
Tuzla
Crna Gora
Podgorica
Hrvatska
Bjelovarsko-bilogorska županija
Bjelovar
Daruvar  
Garešnica
Grubišno Polje
Cazma
Brodsko-posavska županija
Gornji Bogicevci
Klakar
Nova Gradiška

<!--
        window.onload = loadFilter;
// -->   

JavaScript:

function loadFilter() {
  'use strict';
  // rückt alle Optionen je nach "i" CSS Klasse ein
  function add_nbsp() {
    var opt = document.getElementsByTagName("option");
    for (var i = 0; i < opt.length; i++) {
      if (opt[i].className[0] === 'i') {
      opt[i].innerHTML = Array(3*opt[i].className[1]+1).join(" ") + opt[i].innerHTML;      // das bedeutet " " x (3*$Einrückung)
      }
    }
  }
  // erkennt den Browser
  navigator.sayswho= (function() {
    var ua= navigator.userAgent, tem,
    M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*([\d\.]+)/i) || [];
    if(/trident/i.test(M[1])){
        tem=  /\brv[ :]+(\d+(\.\d+)?)/g.exec(ua) || [];
        return 'IE '+(tem[1] || '');
    }
    M= M[2]? [M[1], M[2]]:[navigator.appName, navigator.appVersion, '-?'];
    if((tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1];
    return M.join(' ');
  })();
  // schnelle Erkennung, ob der Browser Firefox ist
  function isFirefox() {
    var ua= navigator.userAgent,
    M= ua.match(/firefox\//i);  
    return M;
  }
  // eingerückte Select-Optionen Unterstützung für nicht-Firefox-Browser
  if (!isFirefox()) {
    add_nbsp();
  }
}

0 Stimmen

Durch das Hinzufügen von CSS-Klassen zur Steuerung des Einzugs würde das Problem des OP ohne Beeinträchtigung der Funktionalität des select gelöst werden. Gute Idee, da optgroups nicht verschachtelt werden können.

0 Stimmen

Warum hast du den Code für margin-left: 1em; , wenn er sowieso nichts tut und du am Ende benutzt, nur um den Rand erscheinen zu lassen? Dein CSS-Code hier macht absolut nichts. Demo von nicht funktionierenden linken Rändern

0 Stimmen

@HoldOffHunger beachten Sie, dass die obige Antwort aus dem Jahr 2015 stammt und eine spezielle isFirefox()-Behandlung enthält - damals benötigte Firefox kein (was die Suchfunktion von Dropdown-Listen bei der Eingabe von Text zerstörte) und damals wurden auch Ränder in Dropdown-Listen berücksichtigt (leider funktioniert es zumindest bis Firefox 78.5 nicht mehr auf diese Weise)

4voto

Nickolay Punkte 46

Ich habe ein schönes, verschachteltes Select geschrieben. Vielleicht wird es Ihnen helfen.

https://jsfiddle.net/nomorepls/tg13w5r7/1/

function on_change_select(e) {
  alert(e.value, e.title, e.option, e.select);
}

$(document).ready(() => {
  // NESTED SELECT

  $(document).on('click', '.nested-cell', function() {
    $(this).next('div').toggle('medium');
  });

  $(document).on('change', 'input[name="nested-select-hidden-radio"]', function() {
    const parent = $(this).closest(".nested-select");
    const value = $(this).attr('value');
    const title = $(this).attr('title');
    const executer = parent.attr('executer');
    if (executer) {
      const event = new Object();
      event.value = value;
      event.title = title;
      event.option = $(this);
      event.select = parent;
      window[executer].apply(null, [event]);
    }
    parent.attr('value', value);
    parent.parent().slideToggle();
    const button = parent.parent().prev();
    button.toggleClass('active');
    button.addClass('selected');
    button.children('.nested-select-title').html(title);
  });

  $(document).on('click', '.nested-select-button', function() {
    const button = $(this);
    let select = button.parent().children('.nested-select-wrapper');

    if (!button.hasClass('active')) {
      select = select.detach();
      if (button.height() + button.offset().top + $(window).height() * 0.4 > $(window).height()) {
        select.insertBefore(button);
        select.css('margin-top', '-44vh');
        select.css('top', '0');
      } else {
        select.insertAfter(button);
        select.css('margin-top', '');
        select.css('top', '40px');
      }
    }
    select.slideToggle();
    button.toggleClass('active');
  });
});

.container {
  width: 200px;
  position: relative;
  top: 0;
  left: 0;
  right: 0;
  height: auto;
}

.nested-select-box {
  font-family: Arial, Helvetica, sans-serif;
  display: block;
  position: relative;
  width: 100%;
  height: fit-content;
  cursor: pointer;
  color: #2196f3;
  height: 40px;
  font-size: small;
  /* z-index: 2000; */
}

.nested-select-box .nested-select-button {
  border: 1px solid #2196f3;
  position: absolute;
  width: calc(100% - 20px);
  padding: 0 10px;
  min-height: 40px;
  word-wrap: break-word;
  margin: 0 auto;
  overflow: hidden;
}

.nested-select-box.danger .nested-select-button {
  border: 1px solid rgba(250, 33, 33, 0.678);
}

.nested-select-box .nested-select-button .nested-select-title {
  padding-right: 25px;
  padding-left: 25px;
  width: calc(100% - 50px);
  margin: auto;
  height: fit-content;
  text-align: center;
  vertical-align: middle;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
}

.nested-select-box .nested-select-button.selected .nested-select-title {
  bottom: unset;
  top: 5px;
}

.nested-select-box .nested-select-button .nested-select-title-icon {
  position: absolute;
  height: 20px;
  width: 20px;
  top: 10px;
  bottom: 10px;
  right: 7px;
  transition: all 0.5s ease 0s;
}

.nested-select-box .nested-select-button.active .nested-select-title-icon {
  -moz-transform: scale(-1, -1);
  -o-transform: scale(-1, -1);
  -webkit-transform: scale(-1, -1);
  transform: scale(-1, -1);
}

.nested-select-box .nested-select-button .nested-select-title-icon::before,
.nested-select-box .nested-select-button .nested-select-title-icon::after {
  content: "";
  background-color: #2196f3;
  position: absolute;
  width: 70%;
  height: 2px;
  transition: all 0.5s ease 0s;
  top: 9px;
}

.nested-select-box .nested-select-button .nested-select-title-icon::before {
  transform: rotate(45deg);
  left: -1.6px;
}

.nested-select-box .nested-select-button .nested-select-title-icon::after {
  transform: rotate(-45deg);
  left: 7px;
}

.nested-select-box .nested-select-wrapper {
  width: 100%;
  top: 40px;
  position: relative;
  border: 1px solid #2196f3;
  background: #ffffff;
  z-index: 2005;
  opacity: 1;
}

.nested-select {
  font-family: Arial, Helvetica, sans-serif;
  display: inline-block;
  overflow-y: scroll;
  max-height: 40vh;
  width: calc(100% - 10px);
  padding: 5px;
  -ms-overflow-style: none;
  scrollbar-width: none;
}

.nested-select::-webkit-scrollbar {
  display: none;
}

.nested-select a,
.nested-select span {
  padding: 0 5px;
  border-radius: 3px;
  cursor: pointer;
  text-align: start;
}

.nested-select a:hover {
  background-color: #62b2f3;
  color: #ffffff;
}

.nested-select span:hover {
  background-color: #c4c4c4;
  color: #ffffff;
}

.nested-select input[type="radio"] {
  display: none;
}

.nested-select input[type="radio"]+span {
  display: block;
}

.nested-select input[type="radio"]:checked+span {
  background-color: #2196f3;
  color: #ffffff;
}

.nested-select div {
  margin-left: 15px;
}

.nested-select label>span:before,
.nested-select a:before {
  content: "\2022";
  margin-right: 5px;
}

.nested-select a {
  display: block;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="nested-select-box w-100">
    <div class="nested-select-button">
      <p class="nested-select-title">
        Account
      </p>
      <span class="nested-select-title-icon"></span>
    </div>
    <div class="nested-select-wrapper" style="display: none;">
      <div class="nested-select" executer="on_change_select">

        <label>
        <input title="Accounting and legal services" value="1565142000000891539" type="radio" name="nested-select-hidden-radio">
        <span>Accounting and legal services</span>
      </label>

        <label>
        <input title="Advertising agencies" value="1565142000000891341" type="radio" name="nested-select-hidden-radio">
        <span>Advertising agencies</span>
      </label>

        <a class="nested-cell">Advertising And Marketing</a>
        <div>

          <label>
          <input title="Advertising agencies" value="1565142000000891341" type="radio" name="nested-select-hidden-radio">
          <span>Advertising agencies</span>
        </label>

          <a class="nested-cell">Adwords - traffic</a>
          <div>

            <label>
            <input title="Adwords - traffic: Charters and general search" value="1565142000003929177" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Charters and general search</span>
          </label>

            <label>
            <input title="Adwords - traffic: Distance course" value="1565142000007821291" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Distance course</span>
          </label>

            <label>
            <input title="Adwords - traffic: Events" value="1565142000003929189" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Events</span>
          </label>

            <label>
            <input title="Adwords - traffic: Practices" value="1565142000003929165" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Practices</span>
          </label>

            <label>
            <input title="Adwords - traffic: Sailing tours" value="1565142000003929183" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Sailing tours</span>
          </label>

            <label>
            <input title="Adwords - traffic: Theoretical courses" value="1565142000003929171" type="radio" name="nested-select-hidden-radio">
            <span>Adwords - traffic: Theoretical courses</span>
          </label>

          </div>

          <label>
          <input title="Branded products" value="1565142000000891533" type="radio" name="nested-select-hidden-radio">
          <span>Branded products</span>
        </label>

          <label>
          <input title="Business cards" value="1565142000005438323" type="radio" name="nested-select-hidden-radio">
          <span>Business cards</span>
        </label>

          <a class="nested-cell">Facebook, Instagram - traffic</a>
          <div>

            <label>
            <input title="Facebook, Instagram - traffic: Charters and general search" value="1565142000003929145" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Charters and general search</span>
          </label>

            <label>
            <input title="Facebook, Instagram - traffic: Distance course" value="1565142000007821285" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Distance course</span>
          </label>

            <label>
            <input title="Facebook, Instagram - traffic: Events" value="1565142000003929157" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Events</span>
          </label>

            <label>
            <input title="Facebook, Instagram - traffic: Practices" value="1565142000003929133" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Practices</span>
          </label>

            <label>
            <input title="Facebook, Instagram - traffic: Sailing tours" value="1565142000003929151" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Sailing tours</span>
          </label>

            <label>
            <input title="Facebook, Instagram - traffic: Theoretical courses" value="1565142000003929139" type="radio" name="nested-select-hidden-radio">
            <span>Facebook, Instagram - traffic: Theoretical courses</span>
          </label>

          </div>

          <label>
          <input title="Offline Advertising (posters, banners, partnerships)" value="1565142000000891377" type="radio" name="nested-select-hidden-radio">
          <span>Offline Advertising (posters, banners, partnerships)</span>
        </label>

          <label>
          <input title="Photos, video etc." value="1565142000000891371" type="radio" name="nested-select-hidden-radio">
          <span>Photos, video etc.</span>
        </label>

          <label>
          <input title="Prize fund" value="1565142000001404931" type="radio" name="nested-select-hidden-radio">
          <span>Prize fund</span>
        </label>

          <label>
          <input title="SEO" value="1565142000000891365" type="radio" name="nested-select-hidden-radio">
          <span>SEO</span>
        </label>

          <label>
          <input title="SMM Content creation (texts, copywriting)" value="1565142000000891389" type="radio" name="nested-select-hidden-radio">
          <span>SMM Content creation (texts, copywriting)</span>
        </label>

          <a class="nested-cell">YouTube</a>
          <div>

            <label>
            <input title="YouTube: travel expenses" value="1565142000008100163" type="radio" name="nested-select-hidden-radio">
            <span>YouTube: travel expenses</span>
          </label>

            <label>
            <input title="Youtube: video editing" value="1565142000008100157" type="radio" name="nested-select-hidden-radio">
            <span>Youtube: video editing</span>
          </label>

          </div>

        </div>

      </div>
    </div>
  </div>
</div>

2voto

Danny Lin Punkte 1922

Es scheint, dass die ursprünglichen Erfinder des Standards eine gruppenbasierte Auswahlliste anstelle einer hierarchischen Liste wünschen. Leider wird sich der zukünftige HTML-Standard wahrscheinlich aufgrund eines hohen Risikos für die Abwärtskompatibilität nicht ändern.

Wenn es akzeptabel ist, kann die hierarchische Liste in eine nach Segmenten benannte Gruppenliste umgewandelt werden:

     A.1 

     A.B.1 

     A.2 

Wenn eine Änderung der Reihenfolge akzeptabel ist, sollten die Elemente mit dem gleichen Gruppennamen für ein besseres Aussehen zusammengeführt werden:

     A.1 
     A.2 

     A.B.1 

Wenn beides nicht akzeptabel ist und eine hierarchische Auswahlliste wirklich erforderlich ist, kann die Implementierung eines Modaldialogs mit Kontrollkästchen (und möglicherweise einer JavaScript-Tastenfalle für die Mehrfachauswahl mit Shift- oder Strg-Taste) erforderlich sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X