simple cities selecter

citiesSelect

by extempl

HTML

<!doctype html>
<html>
<head>
    <title>some</title>
</head>
<body onload="init()">
<form style="margin: 10px">
<select name="cities" data-type="selectCity">
    <optgroup label="Мегаполисы" data-label="main">
        <option value="Москва">Москва</option>
        <option value="Санкт-Петербург">Санкт-Петербург</option>
    </optgroup>
    <optgroup label="Большие города" data-label="big">
        <option value="Екатеринбург">Екатеринбург</option>
        <option value="Новосибирск">Новосибирск</option>
        <option value="Казань">Казань</option>
        <option value="Киев">Киев</option>
        <option value="Красноярск">Красноярск</option>
        <option value="Хабаровск">Хабаровск</option>
    </optgroup>
    <optgroup label="Остальные" data-label="other">
        <option value="Коркин" selected="selected">Коркин</option>
        <option value="Чебоксары">Чебоксары</option>
        <option value="Челюскин">Челюскин</option>
        <option value="Челябинск">Челябинск</option>
        <option value="Чернигов">Чернигов</option>
        <option value="Чехов">Чехов</option>
    </optgroup>
</select>

<select name="cities" data-type="selectCity">
    <optgroup label="Мегаполисы" data-label="main">
        <option value="Москва">Москва</option>
        <option value="Санкт-Петербург">Санкт-Петербург</option>
    </optgroup>
    <optgroup label="Большие города" data-label="big">
        <option value="Екатеринбург">Екатеринбург</option>
        <option value="Новосибирск">Новосибирск</option>
        <option value="Казань" selected="selected">Казань</option>
        <option value="Красноярск">Красноярск</option>
        <option value="Хабаровск">Хабаровск</option>
    </optgroup>
    <optgroup label="Остальные" data-label="other">
        <option value="Коркин">Коркин</option>
        <option value="Чебоксары">Чебоксары</option>
        <option value="Челюскин">Челюскин</option>
        <option value="Челябинск">Челябинск</option>
        <option...

CSS

.selectCityWrapper {
    position: relative;
    display: inline-block;
}

.selectCityWrapper, .selectCityWrapper input, .selectCityWrapper button {
    font-family: Verdana;
    font-size:   11px;
}

.selectCityWrapper button {
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAFCAQAAADfhhWZAAAABGdBTUEAALGPC/xhBQAAAAJiS0dEAP7wiPwpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAANUlEQVQI12NgWcP4GwZZ1jCgAXnmqxAp5qsM8gwYwB0iyeDOgBV0M/5m6GbABTBtY2BgYAAA+h8Rc1nZBkQAAAAASUVORK5CYII=), -webkit-linear-gradient(top, #fefefe 0%, #ececec 100%);
    background-position: right center;
    background-repeat: no-repeat, repeat;
    box-shadow: #b8b8b8 0 1px 1px;
    padding: 2px 20px 0 4px;
    height: 20px;
    border: 1px solid #e0e0e0;
    border-radius: 3px;
    cursor: pointer;
    margin: 0;
}

.selectCityWrapper > button:active, .selectCityWrapper.opened > button {
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAFCAQAAADfhhWZAAAABGdBTUEAALGPC/xhBQAAAAJiS0dEAP7wiPwpAAAACXBIWXMAAAsTAAALEwEAmpwYAAAANUlEQVQI12NgWcP4GwZZ1jCgAXnmqxAp5qsM8gwYwB0iyeDOgBV0M/5m6GbABTBtY2BgYAAA+h8Rc1nZBkQAAAAASUVORK5CYII=), -webkit-linear-gradient(top, #e7e7e7 0%, #fbfbfb 100%);
    box-shadow: inset #b8b8b8 0 1px 1px;
}

.popupCityWrapper {
    position: absolute;
    border: 1px solid #e0e0e0;
    border-bottom-color: #747474;
    border-radius:4px;
    box-shadow: #a4a4a4 0 2px 3px;
    left: 0;
    display: none;
    margin-top: 1px;
    min-width: 136px;
}

.selectCityWrapper.opened > .popupCityWrapper {
    display: block;
}

.popupCityWrapper > ul {
    max-height: 85px;
    overflow-y: auto;
    position: relative;
    margin: 0;
    padding: 0;
    list-style: none;
}

.popupCityWrapper > ul > li {
    cursor: pointer;
    padding: 2px 4px;
    -moz-user-select: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
}

.popupCityWrapper li.act, .popupCityWrapper > ul > li:hover  {
    background: #a7d3ff;
}

.inputCitiesWrapper {
   ...

JavaScript

"use strict";
var init = function () {
    var selectCity = new SelectCity({citiesListLimit: 5});
    selectCity.init();
};

var SelectCity = function (parameters) {
    // TODO make two options - from existing select and from transferred in parameters citiesList (one for all citiesSelects)
    this.parameters = mergeObjects({
//        citiesList: {
//            main: ['Москва', 'Санкт-Петербург'],
//            big:  ['Екатеринбург', 'Новосибирск', 'Казань', 'Красноярск', 'Хабаровск'],
//            other:  ['Коркин', 'Чебоксары', 'Челюскин', 'Челябинск', 'Чернигов', 'Чехов']
//        }
    }, parameters || {});
};

SelectCity.prototype = {
    /**
    * public init method
    * param el - environment, where we need to find and replace selects
    * runs once
    */
    init: function (el) {
        var self = this;
        var selects;

        // init popup
        self._initPopup();

        // find all selects
        selects = (el || document).getElementsByTagName('select');
        for(var i = 0, l = selects.length; i < l; i++)
            if(selects[i].getAttribute('data-selectCity') != 'initialised')
                self._initCustomSelect(selects[i]);

        document.addEventListener('mousedown', function (e) {
            self._outsideClickChecker(e);
        });

    },
    _popupClassName: 'popupCityWrapper',
    _popupTpl: '' +
    '<ul class="mainCities"></ul>' +
    '<div class="inputCitiesWrapper">' +
        '<input placeholder="или введите другой" tabindex="-1" />' +
        '<div class="pseudoPlaceholderCities"></div>' +
    '</div>' +
    '<ul class="searchCitiesResults"></ul>',
    /**
    * private method, runs once on init
    * initialise popup,
    * called by {@link init()}
    */
    _initPopup: function () {
        var self = this;
        if(!document.getElementsByClassName(self._popupClassName).length) {
            self._renderPopup();
            self._bindPopupEvents();
        }
    },
    /**
    * add listeners to popup...