Parcourir la source

Refactor selects js

Denis K il y a 8 ans
Parent
commit
b2dd72ad1a
1 fichiers modifiés avec 196 ajouts et 178 suppressions
  1. 196 178
      jet/static/jet/js/src/features/selects.js

+ 196 - 178
jet/static/jet/js/src/features/selects.js

@@ -1,214 +1,232 @@
 require('select2');
 
 var $ = require('jquery');
-var Utils = $.fn.select2.amd.require('select2/utils');
-var DropdownAdapter = $.fn.select2.amd.require('select2/dropdown');
-var AttachBody = $.fn.select2.amd.require('select2/dropdown/attachBody');
-var DropdownSearch = $.fn.select2.amd.require('select2/dropdown/search');
-var MinimumResultsForSearch = $.fn.select2.amd.require('select2/dropdown/minimumResultsForSearch');
-var closeOnSelect = $.fn.select2.amd.require('select2/dropdown/closeOnSelect');
 
-AttachBody.prototype._positionDropdown = function () {
-    var $window = $(window);
+var Select2 = function() { };
 
-    var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
-    var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
+Select2.prototype = {
+    updateAttachBody: function(AttachBody) {
+        AttachBody.prototype._positionDropdown = function () {
+            var $window = $(window);
 
-    var newDirection = null;
+            var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
+            var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
 
-    var position = this.$container.position();
-    var offset = this.$container.offset();
+            var newDirection = null;
 
-    offset.bottom = offset.top + this.$container.outerHeight(false);
+            var position = this.$container.position();
+            var offset = this.$container.offset();
 
-    var container = {
-        height: this.$container.outerHeight(false)
-    };
+            offset.bottom = offset.top + this.$container.outerHeight(false);
 
-    container.top = offset.top;
-    container.bottom = offset.top + container.height;
+            var container = {
+                height: this.$container.outerHeight(false)
+            };
 
-    var dropdown = {
-        height: this.$dropdown.outerHeight(false)
-    };
+            container.top = offset.top;
+            container.bottom = offset.top + container.height;
 
-    var viewport = {
-        top: $window.scrollTop(),
-        bottom: $window.scrollTop() + $window.height()
-    };
+            var dropdown = {
+                height: this.$dropdown.outerHeight(false)
+            };
 
-    var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
-    var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
+            var viewport = {
+                top: $window.scrollTop(),
+                bottom: $window.scrollTop() + $window.height()
+            };
 
-    var css = {
-        left: offset.left,
-        top: container.bottom
-    };
+            var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
+            var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
 
-    if (!isCurrentlyAbove && !isCurrentlyBelow) {
-        newDirection = 'below';
-    }
-
-    if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
-        newDirection = 'above';
-    } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
-        newDirection = 'below';
-    }
+            var css = {
+                left: offset.left,
+                top: container.bottom
+            };
 
-    if (newDirection == 'above' ||
-        (isCurrentlyAbove && newDirection !== 'below')) {
-        css.top = container.top - dropdown.height;
-    }
+            if (!isCurrentlyAbove && !isCurrentlyBelow) {
+                newDirection = 'below';
+            }
 
-    if (newDirection != null) {
-        this.$dropdown
-            .removeClass('select2-dropdown--below select2-dropdown--above')
-            .addClass('select2-dropdown--' + newDirection);
-        this.$container
-            .removeClass('select2-container--below select2-container--above')
-            .addClass('select2-container--' + newDirection);
-
-        //hack
-        var $search = this.$dropdown.find('.select2-search');
-
-        if (newDirection == 'above' && $search.is(':first-child')) {
-            $search.detach().appendTo(this.$dropdown);
-        } else if (newDirection == 'below' && $search.is(':last-child')) {
-            $search.detach().prependTo(this.$dropdown);
-        }
-    }
+            if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
+                newDirection = 'above';
+            } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
+                newDirection = 'below';
+            }
 
-    this.$dropdownContainer.css(css);
-};
+            if (newDirection == 'above' ||
+                (isCurrentlyAbove && newDirection !== 'below')) {
+                css.top = container.top - dropdown.height;
+            }
 
-AttachBody.prototype.render = function (decorated) {
-    var $container = $('<span></span>');
+            if (newDirection != null) {
+                this.$dropdown
+                    .removeClass('select2-dropdown--below select2-dropdown--above')
+                    .addClass('select2-dropdown--' + newDirection);
+                this.$container
+                    .removeClass('select2-container--below select2-container--above')
+                    .addClass('select2-container--' + newDirection);
+
+                //hack
+                var $search = this.$dropdown.find('.select2-search');
+
+                if (newDirection == 'above' && $search.is(':first-child')) {
+                    $search.detach().appendTo(this.$dropdown);
+                } else if (newDirection == 'below' && $search.is(':last-child')) {
+                    $search.detach().prependTo(this.$dropdown);
+                }
+            }
 
-    var $dropdown = decorated.call(this);
-    $container.append($dropdown);
+            this.$dropdownContainer.css(css);
+        };
 
-    this.$dropdownContainer = $container;
+        AttachBody.prototype.render = function (decorated) {
+            var $container = $('<span></span>');
 
-    //hack
-    if (this.$element.prop('multiple')) {
-        this.$dropdown.addClass('select2-multiple-dropdown');
-    } else {
-        this.$dropdown.removeClass('select2-multiple-dropdown');
-    }
+            var $dropdown = decorated.call(this);
+            $container.append($dropdown);
 
-    return $container;
-};
+            this.$dropdownContainer = $container;
 
-DropdownAdapter.prototype.render = function () {
-    var buttons = '';
+            //hack
+            if (this.$element.prop('multiple')) {
+                this.$dropdown.addClass('select2-multiple-dropdown');
+            } else {
+                this.$dropdown.removeClass('select2-multiple-dropdown');
+            }
 
-    if (this.options.get('multiple')) {
-        buttons =
-            '<div class="select2-buttons">' +
-                '<a href="#" class="select2-buttons-button select2-buttons-button-select-all">' +
+            return $container;
+        };
+    },
+    updateDropdownAdapter: function(DropdownAdapter) {
+        DropdownAdapter.prototype.render = function () {
+            var buttons = '';
+
+            if (this.options.get('multiple')) {
+                buttons =
+                    '<div class="select2-buttons">' +
+                    '<a href="#" class="select2-buttons-button select2-buttons-button-select-all">' +
                     django.gettext('select all') +
-                '</a> ' +
-                '<a href="#" class="select2-buttons-button select2-buttons-button-deselect-all">' +
+                    '</a> ' +
+                    '<a href="#" class="select2-buttons-button select2-buttons-button-deselect-all">' +
                     django.gettext('deselect all') +
-                '</a>' +
-            '</div>';
-    }
-
-    var $dropdown = $(
-        '<span class="select2-dropdown">' +
-        buttons +
-        '<span class="select2-results"></span>' +
-        '</span>'
-    );
-
-    var $element = this.$element;
-
-    $dropdown.find('.select2-buttons-button-select-all').on('click', function(e) {
-        e.preventDefault();
-        var selected = [];
-        $element.find('option').each(function() {
-            selected.push($(this).val());
-        });
-        $element.select2('val', selected);
-        $element.select2('close');
-    });
-
-    $dropdown.find('.select2-buttons-button-deselect-all').on('click', function(e) {
-        e.preventDefault();
-        $element.select2('val', '');
-        $element.select2('close');
-    });
-
-    $dropdown.attr('dir', this.options.get('dir'));
-    this.$dropdown = $dropdown;
-    return $dropdown;
-};
-
-var dropdownAdapter = Utils.Decorate(
-    Utils.Decorate(
-        DropdownAdapter,
-        DropdownSearch
-    ),
-    AttachBody
-);
-
-dropdownAdapter = Utils.Decorate(dropdownAdapter, MinimumResultsForSearch);
-dropdownAdapter = Utils.Decorate(dropdownAdapter, closeOnSelect);
-
-$(document).on('select:init', 'select', function() {
-    var $select = $(this);
+                    '</a>' +
+                    '</div>';
+            }
 
-    if ($select.parents('.empty-form').length > 0) {
-        return;
-    }
+            var $dropdown = $(
+                '<span class="select2-dropdown">' +
+                buttons +
+                '<span class="select2-results"></span>' +
+                '</span>'
+            );
+
+            var $element = this.$element;
+
+            $dropdown.find('.select2-buttons-button-select-all').on('click', function (e) {
+                e.preventDefault();
+                var selected = [];
+                $element.find('option').each(function () {
+                    selected.push($(this).val());
+                });
+                $element.select2('val', selected);
+                $element.select2('close');
+            });
+
+            $dropdown.find('.select2-buttons-button-deselect-all').on('click', function (e) {
+                e.preventDefault();
+                $element.select2('val', '');
+                $element.select2('close');
+            });
+
+            $dropdown.attr('dir', this.options.get('dir'));
+            this.$dropdown = $dropdown;
+            return $dropdown;
+        };
+    },
+    initSelect: function($select, DropdownAdapter) {
+        var settings = {
+            theme: 'jet',
+            dropdownAdapter: DropdownAdapter
+        };
 
-    var settings = {
-        theme: 'jet',
-        dropdownAdapter: dropdownAdapter
-    };
-
-    if ($select.hasClass('ajax')) {
-        var contentTypeId = $select.data('content-type-id');
-        var appLabel = $select.data('app-label');
-        var model = $select.data('model');
-        var objectId = $select.data('object-id');
-        var pageSize = 100;
-
-        settings['ajax'] = {
-            dataType: 'json',
-            data: function (params) {
-                return {
-                    content_type: contentTypeId,
-                    app_label: appLabel,
-                    model: model,
-                    q: params.term,
-                    page: params.page,
-                    page_size: pageSize,
-                    object_id: objectId
-                };
-            },
-            processResults: function (data, params) {
-                if (data.error) {
-                    return {}
+        if ($select.hasClass('ajax')) {
+            var contentTypeId = $select.data('content-type-id');
+            var appLabel = $select.data('app-label');
+            var model = $select.data('model');
+            var objectId = $select.data('object-id');
+            var pageSize = 100;
+
+            settings['ajax'] = {
+                dataType: 'json',
+                data: function (params) {
+                    return {
+                        content_type: contentTypeId,
+                        app_label: appLabel,
+                        model: model,
+                        q: params.term,
+                        page: params.page,
+                        page_size: pageSize,
+                        object_id: objectId
+                    };
+                },
+                processResults: function (data, params) {
+                    if (data.error) {
+                        return {}
+                    }
+
+                    params.page = params.page || 1;
+                    var more = (params.page * pageSize) < data.total;
+
+                    return {
+                      results: data.items,
+                      pagination: {
+                        more: more
+                      }
+                    };
                 }
+            };
+        }
 
-                params.page = params.page || 1;
-                var more = (params.page * pageSize) < data.total;
-
-                return {
-                  results: data.items,
-                  pagination: {
-                    more: more
-                  }
-                };
+        $select.select2(settings);
+    },
+    initSelect2: function() {
+        var self = this;
+        var AttachBody = $.fn.select2.amd.require('select2/dropdown/attachBody');
+        var DropdownAdapter = $.fn.select2.amd.require('select2/dropdown');
+        var Utils = $.fn.select2.amd.require('select2/utils');
+        var DropdownSearch = $.fn.select2.amd.require('select2/dropdown/search');
+        var MinimumResultsForSearch = $.fn.select2.amd.require('select2/dropdown/minimumResultsForSearch');
+        var closeOnSelect = $.fn.select2.amd.require('select2/dropdown/closeOnSelect');
+
+        this.updateAttachBody(AttachBody);
+        this.updateDropdownAdapter(DropdownAdapter);
+
+        DropdownAdapter = Utils.Decorate(DropdownAdapter, DropdownSearch);
+        DropdownAdapter = Utils.Decorate(DropdownAdapter, AttachBody);
+        DropdownAdapter = Utils.Decorate(DropdownAdapter, MinimumResultsForSearch);
+        DropdownAdapter = Utils.Decorate(DropdownAdapter, closeOnSelect);
+
+        $(document).on('select:init', 'select', function() {
+            var $select = $(this);
+
+            if ($select.parents('.empty-form').length > 0) {
+                return;
             }
-        };
-    }
 
-    $select.select2(settings);
-});
+            self.initSelect($select, DropdownAdapter);
+        });
+
+        $('select').trigger('select:init');
+    },
+    run: function() {
+        try {
+            this.initSelect2();
+        } catch (e) {
+            console.error(e, e.stack);
+        }
+    }
+};
 
 $(document).ready(function() {
-    $('select').trigger('select:init');
+    new Select2().run();
 });
-