Commits

Anton Shestakov committed b09cdd2

Working prototype.

Comments (0)

Files changed (1)

+(function($) {
+    "use strict";
+    
+    var settings, $select, $widget, $modal, $filter, $container, $closeButton;
+    
+    function Lensy(element, options) {
+        $select = $(element);
+        settings = $.extend({}, $.fn.lensy.defaults, options);
+        
+        this.build();
+        this.bindEvents();
+    }
+    
+    Lensy.prototype = {
+        build: function() {
+            $widget = $('<ul>').addClass(settings.widgetClass);
+            $modal = $('<div>').addClass(settings.modalClass).hide();
+            $filter = $('<input>').attr('type', 'text').addClass(settings.filterClass);
+            $container = $('<ul>').addClass(settings.containerClass);
+            $closeButton = $('<a>').text(settings.closeButtonText).addClass(settings.closeButtonClass);
+            
+            $select.hide();
+            
+            $widget
+                .insertAfter($select);
+            
+            $modal
+                .append($filter)
+                .append($container)
+                .append($closeButton)
+                .appendTo('body');
+        },
+        
+        show: function() {
+            $modal.show();
+            $filter.focus();
+        },
+        
+        hide: function() {
+            $modal.hide();
+        },
+        
+        bindEvents: function() {
+            $widget.click($.proxy(this.show, this));
+            
+            $closeButton.click($.proxy(this.hide, this));
+            
+            // $item in $container gets clicked on
+            var itemSelected = function() {
+                var $item = $(this);
+                var value = $item.attr('data-original-value');
+                var values = $select.val() || [];
+                
+                if (values.indexOf(value) == -1) {
+                    $select.val(values.concat(value));
+                } else {
+                    $select.val($.grep(values, function(v) { return v != value; }));
+                }
+                
+                $select.trigger('change');
+            };
+            
+            // $container is populated with $items
+            $select.find('option').each(function() {
+                var $option = $(this);
+                var $item = $('<li>').addClass(settings.itemClass);
+                
+                $item.attr('data-original-value', $option.val());
+                $item.html(settings.itemFn($option.val()));
+                $container.append($item);
+                
+                $item.on('click', itemSelected);
+            });
+            
+            var update = function() {
+                var values = $select.val() || [];
+                
+                $widget.empty();
+                $container.find('[data-original-value]').each(function() {
+                    var $item = $(this);
+                    var value = $item.attr('data-original-value');
+                    
+                    if (values.indexOf(value) == -1) {
+                        $item.removeClass(settings.itemActiveClass);
+                    } else {
+                        $item.addClass(settings.itemActiveClass);
+                        
+                        var $widgetItem = $('<li>').addClass(settings.itemClass);
+                        $widgetItem.html((settings.widgetItemFn || settings.itemFn)(value));
+                        $widget.append($widgetItem);
+                    }
+                });
+            };
+            
+            $select.on('change', update);
+            update();
+            
+            var filter = function() {
+                $container.find('[data-original-value]').each(function() {
+                    var $item = $(this);
+                    var value = $item.attr('data-original-value');
+                    if (settings.filterFn($filter.val(), value, $item)) {
+                        $item.show();
+                    } else {
+                        $item.hide();
+                    }
+                });
+            };
+            
+            $filter.on('change keyup', filter);
+            filter();
+            
+            return this;
+        }
+    };
+    
+    $.fn.lensy = function(options) {
+        return this.each(function() {
+            if (!$.data(this, 'lensy')) {
+                $.data(this, 'lensy', new Lensy(this, options));
+            }
+        });
+    };
+    
+    $.fn.lensy.defaults = {
+        // escape action: close / clean filter
+        containerClass: 'lensy-container',
+        closeButtonText: 'Close',
+        closeButtonClass: 'lensy-button',
+        modalClass: 'lensy-modal',
+        filterClass: 'lensy-filter',
+        widgetClass: 'lensy-widget',
+        itemClass: 'lensy-item',
+        itemActiveClass: 'active',
+        itemFn: function(value) { return $('<span>').text(value); },
+        widgetItemFn: undefined,
+        filterFn: function(filterString, value) { return value.toLowerCase().indexOf(filterString.toLowerCase()) != -1; }
+    };
+})(jQuery);