/* * Jquery UI city selector widget. * * Depends on: * jquery.core.js v1.7 * jquery.ui.core.js v1.8 * jquery.ui.widget.js v1.8 * * You can grab the rest of the code at https://bitbucket.org/JustDelight/city_selector */ (function($) { "use strict"; var META = { RES: { COUNTRIES : 'countries', REGIONS : 'regions', CITIES : 'cities' } }, CachItem = { store: function (data) { if (!this.isNotEmpty()) { this.data = data Object.freeze(this) } }, isNotEmpty: function () { return Object.isFrozen(this) } }, AbstractLoader = { cache: {}, queues: {}, _getNestedItem: function (obj, descriptor) { var nested = obj; descriptor.forEach(function (item) { if (!(item in nested)) { nested[item] = {} } nested = nested[item] }) return nested }, _getQueue: function (descriptor) { var last = descriptor.pop(), nested = this._getNestedItem(this.queues, descriptor); if (!(nested[last] instanceof Array)) { nested[last] = [] } return nested[last] }, getCacheItem: function (descriptor) { var item = this._getNestedItem(this.cache, descriptor); if (item.__proto__ != CachItem) { item.__proto__ = CachItem; } return item; }, _getData: function (descriptor, callback, path_item) { var res, queue, cache_item = this.getCacheItem(descriptor); if (cache_item.isNotEmpty()) { callback.call(null, cache_item.data) } else { queue = this._getQueue(descriptor) if (queue.push(callback) == 1) { $.ajax({ context: this, url: this.CONFIG.base_url + path_item, dataType: 'json', success: function (data, status, xhr) { var callback; while (callback = queue.pop()) { callback.call(null, data) } cache_item.store(data) }, error: function (e) { console.error(e) } }) } } }, }, GeoItemsLoader = { CONFIG: { base_url: '/some_path/' }, __proto__: AbstractLoader, load: function (resource_description, callback) { this._getData(resource_description, callback, resource_description.join('/') + '/') } }; $.widget("ui.city_selector", { options : { position: 'bottom', base_url: '/select/', locale: 'ru' }, strings_pack: { 'ru': { city: 'Город', region: 'Регион', country: 'Страна', prompt: 'выберите город' }, 'en': { city: 'City', region: 'Region', country: 'Country', prompt: 'select the city' } }, _create: function () { this._setLocale(this.options.locale) GeoItemsLoader.CONFIG.base_url = this.options.base_url this._buildWidget() if ('data' in this.options) { this.options.data.forEach(function (item) { GeoItemsLoader.getCacheItem(item[0]).store(item[1]) }) } if ('initial' in this.options) { this._loadInitialData('data' in this.options) } this._loadCountires() this._kbdHideHandler = this._handleDocMouseDown.bind(this) this._mouseHideHandler = this._handleDocKeyPress.bind(this) }, destroy: function () { //TODO: implement it! }, _setOption: function(option, value) { if (option == 'locale') { this._setLocale(value) } else if ((option == 'position') && ((value != 'top') || (value != 'bottom'))) { throw 'unsupported postion' } this.options[option] = value }, _: function(name) { return this._localeStrings[name] }, _setLocale: function(locale) { if (!(locale in this.strings_pack)) { throw 'Unsupported locale: ' + locale } else { this._localeStrings = this.strings_pack[locale] } }, _loadInitialData: function () { var res, value; for (res in this.options['initial']) { value = this.options['initial'][res] $(this).bind(res, (function (res, value, e) { $(this).unbind(e) this._setSelectedValue(res, value) }).bind(this, res, value)) } }, _buildWidget: function () { var title = this.element.attr('value') ? this.element.attr('value') : this._('prompt'), value, name, id, comp_style, show_handler = (function () { this._root.is(":visible") ? this.hide() : this.show() }).bind(this), country_change_handler = this._loadRegions.bind(this), region_change_handler = this._loadCities.bind(this); this.anchor = $('' + title + ''); this.element.after(this.anchor) this.element.hide() this.anchor.click(show_handler) this.anchor.addClass(this.options.position == 'top' ? 'bottom' : 'top') this._root = $('
').addClass("ui-widget ui-widget-content ui-city_celector").appendTo($(document.body)).hide() this._selects = {} this._selects[META.RES.COUNTRIES] = $('').attr('name', 'region').appendTo(this._root).hide() this._selects[META.RES.CITIES] = $('