How can I use <ul> list instead of <select> dropdown for the languages switcher?
Asked Answered
A

4

10

I use msDropDown to convert the <select> to <ul> list for languages switcher. But the problem is that with this jQuery plugin, the select takes a long time to load after page loaded.

So, how can I use a ul list rather than select?

This is my select code:

<select name="lang" class="language" onchange="location.href='index.php?lang='+this.value+''.$trackpage.'">
    <option name="lang" data-image="style/lang/de.png" value="de">Deutsch</option>
    <option name="lang" data-image="style/lang/en.png" value="en" selected="selected">English</option>
    <option name="lang" data-image="style/lang/es.png" value="es">Espanol</option>
    <option name="lang" data-image="style/lang/fr.png" value="fr">Francais</option>
    <option name="lang" data-image="style/lang/it.png" value="it">Italiano</option>
</select>

I tried with:

<ul onchange="location.href='index.php?lang='+this.value+'">
    <li>
        <a href="" name="lang" data-image="style/lang/de.png" value="de">English</a>
    </li>
</ul>

but value and onchange is not supported by ul and a.
Is there a way to make ul works with the select attributes?

Thank you! And sorry for my bad English!

Adverbial answered 17/2, 2013 at 21:38 Comment(1)
you wish it to act as drop down list? or you fine with list of elements?Praedial
C
23

Updated Answer 2015

As this question is still visited very often and due to some requests in the comments, I've revisit my code. You can still find my original answer below.

HTML

<button class="language_selector">Choose Language</button>
<ul class="languages">
    <li><a href="/en">English</a></li>
    <li><a href="/de">Deutsch</a></li>
</ul>

<article>
    <h1>More Content</h1>
</article>

JavaScript

var trigger = $('.language_selector');
var list = $('.languages');

trigger.click(function() {
    trigger.toggleClass('active');
    list.slideToggle(200);
});

// this is optional to close the list while the new page is loading
list.click(function() {
    trigger.click();
});

CSS

.language_selector {
    width: 200px;
    background: #222;
    color:  #eee;
    line-height: 25px;
    font-size: 14px;
    padding: 0 10px;
    cursor: pointer;
}

.languages {
    display: none;
    position: absolute;
    margin: 0;
    background: #dddddd;
}

.languages > li {
    width: 200px;
    background: #eee;
    line-height: 25px;
    font-size: 14px;
    padding: 0 10px;
    cursor: pointer;
}

.languages > li:hover {
    background: #aaa;
}

Demo

Try before buy


Original Answer From 2013

I would do it like this:

var nav = $('#nav');
var selection = $('.select');
var select = selection.find('li');

nav.click(function(event) {
    if (nav.hasClass('active')) {
        nav.removeClass('active');
        selection.stop().slideUp(200);
    } else {
        nav.addClass('active');
        selection.stop().slideDown(200);
    }
    event.preventDefault();
});

select.click(function(event) {
    // updated code to select the current language
    select.removeClass('active');
    $(this).addClass('active');

    alert ("location.href = 'index.php?lang=" + $(this).attr('data-value'));
});
h2 {
    width: 200px;
    background: #222;
    color:  #eee;
    line-height: 25px;
    font-size: 14px;
    padding: 0 10px;
    cursor: pointer;
}
ol.select {
    display: none;
}

ol.select > li {
    width: 200px;
    background: #eee;
    line-height: 25px;
    font-size: 14px;
    padding: 0 10px;
    cursor: pointer;
}

ol.select > li:hover {
    background: #aaa;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h2 id="nav">Choose Language</h2>
<ol class="select">
    <li data-value="en">English</li>
    <li data-value="de">Deutsch</li>
</ol>

This one adds a class the the selected element. This works, if you stay on that very page after the select and don't use location.href.

Chinatown answered 17/2, 2013 at 22:1 Comment(6)
you are quick, very nice solution... (using the select exact attributes) +1Praedial
Thank you very much. I've built something similar to this before, so I could adapt it quickly.Chinatown
@Chinatown Hello, but how i can add the class to selected language? I treid with $('.select li').removeClass('active'); $(this).addClass('active'); doesn't work, but with a standard list works fine, why?Adverbial
Hey @Fuiba actually it should work like you wrote. I've updated my answer. You don't have to use another selector again, as the lis are stored in a variable. This won't work if you use location.href as the page gets reloaded afterwards. If you do so, you can add the class active using PHP when printing the language list.Chinatown
How would I do this same thing but NOT have it push elements below down? (ie. if you add a bunch of text below your </ol> and run the snippet, you see it pushes down rather than covering over like one would expect with a drop-down)Exsect
@Exsect You can use position: absolute on the list. I've updated my answer and in this new example you can see how it works.Chinatown
P
3

You can't use the select attributes, instead you can create your own attributes and use them in <ul> element

Maybe this will help you

First the html code

<div id="language">Change Lang</div>
<ul id="lang">
    <li>
        <a href="" name="lang" data-val="de">
           <img src="http://icons.iconarchive.com/icons/famfamfam/flag/16/ad-icon.png"/>
        English</a></li>
    <li>
        <a href="" name="lang" data-val="he">
            <img src="http://icons.iconarchive.com/icons/famfamfam/flag/16/il-icon.png"/>
            Hebrew</a></li>
</ul>

Next the jquery code

$("#language").click(function(){
   $("#lang li").slideToggle();
});

$("#lang li").click(function() {
    var url = location.href = "index.php?lang=" + $(this).find('a').attr("data-val");
   location.href =url;
});

i have did it without the plugin.

Pay attention that i created a data-val attribute so store the desire language. and i getting this attribute using jquery code

Praedial answered 17/2, 2013 at 21:59 Comment(0)
H
1

A very simple one (ul to select dropdown jquery transformation) no need to change html, very useful for mobile menus:

$(function(){
  var close = function() {
    $("ul").each(function() {
      var $thisUl = $(this);    
      if($thisUl.find("li > a.click").length == 0) {
        var $li = $(document.createElement('li')).append($(document.createElement('a')).attr({
          "class": "click selectable visible",
          "href": "#"
        }).text("Select"));
        $thisUl.append($li);
      }
      else {
        $thisUl.find("li > a.click").addClass("visible");
      }
      $thisUl.find("li:has(> a:not(.click))").hide();
      $thisUl.find("li > a.click").show();
    });
  };

  var sentinel = function() {
    $("ul").each(function(){
      var $thisUl = $(this);
      $($thisUl).find("li > a").click(function(event){
        if($(event.target).is('ul li a.visible')) {
          event.preventDefault();
          $thisUl.find("li:has(> a:not(.click))").show();
          $thisUl.find("li > a.selectable").hide();
          $thisUl.find("li > a.click").removeClass("visible");
        }
        else {
          $thisUl.find("li").each(function(){
            $(this).find("a").removeClass("click selectable visible");
            $(this).find("a.selectable").remove();
          });
          $(this).addClass("click visible");
          close();
        }
      });
    });
  };

  var reconnaissance = function() {
    $(document).click(function(event) {
      if(!$(event.target).is('ul li a')) {
        close();
      }
    });
  };

  close();
  sentinel();
  reconnaissance();
});
ul { 
  width: auto;
  margin: 2px auto;
  background-color: #ddd;
  border-top: 1px solid #999;
  border-bottom: 3px solid #999;
  border-left: 1px solid #999;
  border-right: 1px solid #999;
  border-radius: 8px;
  list-style:none;
  background-size: 16px 16px;
  background-repeat: no-repeat;
  background-attachment: scroll;
  background-position: left 2px;
  background-color: transparent;
  cursor: pointer;
}
li > a.click { 
  color: darkgreen; 
  font-weight: bold;
}
li a {
  color:darkblue;
  text-decoration:none;
}
li a:active, li a:hover {
  color:darkred;
  background-color: lightyellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
  <li><a href="#">Option 1</a></li>
  <li><a class="click" href="#">Option 2</a></li>
  <li><a href="#">Option 3</a></li>
</ul>

<ul>
  <li><a href="#">Option 1</a></li>
  <li><a href="#">Option 2</a></li>
  <li><a href="#">Option 3</a></li>
</ul>
Hamford answered 28/10, 2015 at 11:10 Comment(0)
F
0

// Generated by CoffeeScript 1.4.0
(function() {
  var $;

  $ = window.jQuery || window.Zepto || window.$;

  $.fn.fancySelect = function(opts) {
    var isiOS, settings;
    if (opts == null) {
      opts = {};
    }
    settings = $.extend({
      forceiOS: false,
      includeBlank: false,
      optionTemplate: function(optionEl) {
        return optionEl.text();
      },
      triggerTemplate: function(optionEl) {
        return optionEl.text();
      }
    }, opts);
    isiOS = !!navigator.userAgent.match(/iP(hone|od|ad)/i);
    return this.each(function() {
      var copyOptionsToList, disabled, options, sel, trigger, updateTriggerText, wrapper;
      sel = $(this);
      if (sel.hasClass('fancified') || sel[0].tagName !== 'SELECT') {
        return;
      }
      sel.addClass('fancified');
      sel.css({
        width: 1,
        height: 1,
        display: 'block',
        position: 'absolute',
        top: 0,
        left: 0,
        opacity: 0
      });
      sel.wrap('<div class="fancy-select">');
      wrapper = sel.parent();
      if (sel.data('class')) {
        wrapper.addClass(sel.data('class'));
      }
      wrapper.append('<div class="trigger">');
      if (!(isiOS && !settings.forceiOS)) {
        wrapper.append('<ul class="options">');
      }
      trigger = wrapper.find('.trigger');
      options = wrapper.find('.options');
      disabled = sel.prop('disabled');
      if (disabled) {
        wrapper.addClass('disabled');
      }
      updateTriggerText = function() {
        var triggerHtml;
        triggerHtml = settings.triggerTemplate(sel.find(':selected'));
        return trigger.html(triggerHtml);
      };
      sel.on('blur.fs', function() {
        if (trigger.hasClass('open')) {
          return setTimeout(function() {
            return trigger.trigger('close.fs');
          }, 120);
        }
      });
      trigger.on('close.fs', function() {
        trigger.removeClass('open');
        return options.removeClass('open');
      });
      trigger.on('click.fs', function() {
        var offParent, parent;
        if (!disabled) {
          trigger.toggleClass('open');
          if (isiOS && !settings.forceiOS) {
            if (trigger.hasClass('open')) {
              return sel.focus();
            }
          } else {
            if (trigger.hasClass('open')) {
              parent = trigger.parent();
              offParent = parent.offsetParent();
              if ((parent.offset().top + parent.outerHeight() + options.outerHeight() + 20) > $(window).height() + $(window).scrollTop()) {
                options.addClass('overflowing');
              } else {
                options.removeClass('overflowing');
              }
            }
            options.toggleClass('open');
            if (!isiOS) {
              return sel.focus();
            }
          }
        }
      });
      sel.on('enable', function() {
        sel.prop('disabled', false);
        wrapper.removeClass('disabled');
        disabled = false;
        return copyOptionsToList();
      });
      sel.on('disable', function() {
        sel.prop('disabled', true);
        wrapper.addClass('disabled');
        return disabled = true;
      });
      sel.on('change.fs', function(e) {
        if (e.originalEvent && e.originalEvent.isTrusted) {
          return e.stopPropagation();
        } else {
          return updateTriggerText();
        }
      });
      sel.on('keydown', function(e) {
        var hovered, newHovered, w;
        w = e.which;
        hovered = options.find('.hover');
        hovered.removeClass('hover');
        if (!options.hasClass('open')) {
          if (w === 13 || w === 32 || w === 38 || w === 40) {
            e.preventDefault();
            return trigger.trigger('click.fs');
          }
        } else {
          if (w === 38) {
            e.preventDefault();
            if (hovered.length && hovered.index() > 0) {
              hovered.prev().addClass('hover');
            } else {
              options.find('li:last-child').addClass('hover');
            }
          } else if (w === 40) {
            e.preventDefault();
            if (hovered.length && hovered.index() < options.find('li').length - 1) {
              hovered.next().addClass('hover');
            } else {
              options.find('li:first-child').addClass('hover');
            }
          } else if (w === 27) {
            e.preventDefault();
            trigger.trigger('click.fs');
          } else if (w === 13 || w === 32) {
            e.preventDefault();
            hovered.trigger('click.fs');
          } else if (w === 9) {
            if (trigger.hasClass('open')) {
              trigger.trigger('close.fs');
            }
          }
          newHovered = options.find('.hover');
          if (newHovered.length) {
            options.scrollTop(0);
            return options.scrollTop(newHovered.position().top - 12);
          }
        }
      });
      options.on('click.fs', 'li', function(e) {
        var clicked;
        clicked = $(this);
        sel.val(clicked.data('raw-value'));
        if (!isiOS) {
          sel.trigger('blur.fs').trigger('focus.fs');
        }
        options.find('.selected').removeClass('selected');
        clicked.addClass('selected');
        return sel.val(clicked.data('raw-value')).trigger('change.fs').trigger('blur.fs').trigger('focus.fs');
      });
      options.on('mouseenter.fs', 'li', function() {
        var hovered, nowHovered;
        nowHovered = $(this);
        hovered = options.find('.hover');
        hovered.removeClass('hover');
        return nowHovered.addClass('hover');
      });
      options.on('mouseleave.fs', 'li', function() {
        return options.find('.hover').removeClass('hover');
      });
      copyOptionsToList = function() {
        var selOpts;
        updateTriggerText();
        if (isiOS && !settings.forceiOS) {
          return;
        }
        selOpts = sel.find('option');
        return sel.find('option').each(function(i, opt) {
          var optHtml;
          opt = $(opt);
          if (!opt.prop('disabled') && (opt.val() || settings.includeBlank)) {
            optHtml = settings.optionTemplate(opt);
            if (opt.prop('selected')) {
              return options.append("<li data-raw-value=\"" + (opt.val()) + "\" class=\"selected\">" + optHtml + "</li>");
            } else {
              return options.append("<li data-raw-value=\"" + (opt.val()) + "\">" + optHtml + "</li>");
            }
          }
        });
      };
      sel.on('update.fs', function() {
        wrapper.find('.options').empty();
        return copyOptionsToList();
      });
      return copyOptionsToList();
    });
  };

}).call(this);
div.fancy-select {
  position: relative;
  color: #505050;  
}

div.fancy-select.disabled {
	opacity: 0.5;
}

div.fancy-select select:focus + div.trigger {
}

div.fancy-select select:focus + div.trigger.open {
}

div.fancy-select div.trigger {
  cursor: pointer;
  height: 50px;
  line-height: 50px;
  padding-left: 20px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  position: relative;
  width: 100%;
  border: 1px solid #6e6e6e;
  
  transition: all 240ms ease-out;
  -webkit-transition: all 240ms ease-out;
  -moz-transition: all 240ms ease-out;
  -ms-transition: all 240ms ease-out;
  -o-transition: all 240ms ease-out;
}

div.fancy-select div.trigger:after {
	content: "";
	display: block;
	position: absolute;
	width: 0;
	height: 0;
	border: 5px solid transparent;
	border-top-color: #4B5468;
	top: 20px;
	right: 9px;
}

div.fancy-select div.trigger.open {
}

div.fancy-select div.trigger.open:after {
}

div.fancy-select ul.options {
	list-style: none;
	margin: 0;
	position: absolute;
	top: 49px;
	left: 0;
	visibility: hidden;
	opacity: 0;
	z-index: 50;
	max-height: 200px;
	overflow: auto;
	border: 1px solid #6e6e6e;
	width: 100%;
  	padding: 0;
	background: #fff;
	transition: opacity 300ms ease-out, top 300ms ease-out, visibility 300ms ease-out;
	-webkit-transition: opacity 300ms ease-out, top 300ms ease-out, visibility 300ms ease-out;
	-moz-transition: opacity 300ms ease-out, top 300ms ease-out, visibility 300ms ease-out;
	-ms-transition: opacity 300ms ease-out, top 300ms ease-out, visibility 300ms ease-out;
	-o-transition: opacity 300ms ease-out, top 300ms ease-out, visibility 300ms ease-out;
}

div.fancy-select ul.options.open {
	visibility: visible;
	top: 50px;
	opacity: 1;

	/* have to use a non-visibility transition to prevent this iOS issue (bug?): */
	/*https://mcmap.net/q/1161416/-css-animation-visibility-visible-works-on-chrome-and-safari-but-not-on-ios*/
	transition: opacity 300ms ease-out, top 300ms ease-out;
	-webkit-transition: opacity 300ms ease-out, top 300ms ease-out;
	-moz-transition: opacity 300ms ease-out, top 300ms ease-out;
	-ms-transition: opacity 300ms ease-out, top 300ms ease-out;
	-o-transition: opacity 300ms ease-out, top 300ms ease-out;
}

div.fancy-select ul.options.overflowing {
	top: auto;
	bottom: 40px;

	transition: opacity 300ms ease-out, bottom 300ms ease-out, visibility 300ms ease-out;
	-webkit-transition: opacity 300ms ease-out, bottom 300ms ease-out, visibility 300ms ease-out;
	-moz-transition: opacity 300ms ease-out, bottom 300ms ease-out, visibility 300ms ease-out;
	-ms-transition: opacity 300ms ease-out, bottom 300ms ease-out, visibility 300ms ease-out;
	-o-transition: opacity 300ms ease-out, bottom 300ms ease-out, visibility 300ms ease-out;
}

div.fancy-select ul.options.overflowing.open {
	top: auto;
	bottom: 50px;

	transition: opacity 300ms ease-out, bottom 300ms ease-out;
	-webkit-transition: opacity 300ms ease-out, bottom 300ms ease-out;
	-moz-transition: opacity 300ms ease-out, bottom 300ms ease-out;
	-ms-transition: opacity 300ms ease-out, bottom 300ms ease-out;
	-o-transition: opacity 300ms ease-out, bottom 300ms ease-out;
}

div.fancy-select ul.options li {
	padding: 8px 20px;
	color: #000;
	cursor: pointer;
	white-space: nowrap;

	transition: all 150ms ease-out;
	-webkit-transition: all 150ms ease-out;
	-moz-transition: all 150ms ease-out;
	-ms-transition: all 150ms ease-out;
	-o-transition: all 150ms ease-out;
}

div.fancy-select ul.options li.selected {
	background: #d3d3d3;
	color: #000;
}

div.fancy-select ul.options li:hover, div.fancy-select ul.options li.hover {
  	background: #d3d3d3;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<select name="SortBy" id="SortBy" class="filters-toolbar__input">
  <option value="" selected="selected">Option 1</option>
  <option value="" selected="selected">Option 2</option>
  <option value="" selected="selected">Option 3</option>
</select>

/* --- fancySelect --- */



$(function() {
$('#SortBy').fancySelect();
});
Fiertz answered 18/9, 2018 at 2:36 Comment(2)
Welcome to Stack Overflow and thank you for the detailed and long answer. Could you edit your answer and explain how this solves the original question?Bygone
A good answer has a better explanation How do I write a good answer?Puli

© 2022 - 2024 — McMap. All rights reserved.