Explorar o código

Respect the disabled attribute

Added a disabled state for Select2. This will correctly listen to
property changes (so when the disabled property is changed) and
update the state of Select2 to reflect it.

Added a utility function to find a method to a different context.
Kevin Brown %!s(int64=10) %!d(string=hai) anos
pai
achega
358306ac8c

+ 7 - 0
dist/css/select2.css

@@ -134,6 +134,9 @@
       position: absolute;
       top: 50%;
       width: 0; }
+.select2-container--default.select2-container--disabled .select2-selection--single {
+  background-color: #eee;
+  cursor: default; }
 .select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
   border-color: transparent transparent #888 transparent;
   border-width: 0 4px 5px 4px; }
@@ -167,6 +170,9 @@
     margin-right: 2px; }
     .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
       color: #333; }
+.select2-container--default.select2-container--disabled .select2-selection--multiple {
+  background-color: #eee;
+  cursor: default; }
 .select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
   border-top-left-radius: 0;
   border-top-right-radius: 0; }
@@ -176,6 +182,7 @@
 .select2-container--default .select2-search--dropdown .select2-search__field {
   border: 1px solid #aaa; }
 .select2-container--default .select2-search--inline .select2-search__field {
+  background: transparent;
   border: none;
   outline: 0; }
 .select2-container--default .select2-results > .select2-results__options {

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
dist/css/select2.min.css


+ 98 - 2
dist/js/select2.amd.full.js

@@ -153,6 +153,12 @@ window.$ = window.$ || {};(function() { if ($ && $.fn && $.fn.select2 && $.fn.se
     return chars;
   };
 
+  Utils.bind = function (func, context) {
+    return function () {
+      func.apply(context, arguments);
+    };
+  };
+
   return Utils;
 });
 
@@ -813,6 +819,14 @@ define('select2/selection/single',[
       // User exits the container
     });
 
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
+
     container.on('selection:update', function (params) {
       self.update(params.data);
     });
@@ -897,6 +911,14 @@ define('select2/selection/multiple',[
         data: data
       });
     });
+
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
   };
 
   MultipleSelection.prototype.clear = function () {
@@ -1078,6 +1100,14 @@ define('select2/selection/search',[
       self.$search.val('');
     });
 
+    container.on('enable', function () {
+      self.$search.prop('disabled', false);
+    });
+
+    container.on('disable', function () {
+      self.$search.prop('disabled', true);
+    });
+
     this.$selection.on('keydown', '.select2-search--inline', function (evt) {
       evt.stopPropagation();
 
@@ -3379,6 +3409,10 @@ define('select2/options',[
       this.options.multiple = $e.prop('multiple');
     }
 
+    if (this.options.disabled == null) {
+      this.options.disabled = $e.prop('disabled');
+    }
+
     if (this.options.language == null) {
       if ($e.prop('lang')) {
         this.options.language = $e.prop('lang').toLowerCase();
@@ -3387,6 +3421,9 @@ define('select2/options',[
       }
     }
 
+    $e.prop('disabled', this.options.disabled);
+    $e.prop('multiple', this.options.multiple);
+
     var data = $e.data();
 
     function convertData (data) {
@@ -3517,7 +3554,6 @@ define('select2/core',[
     this._registerEvents();
 
     // Set the initial state
-
     this.data.current(function (initialData) {
       self.trigger('selection:update', {
         data: initialData
@@ -3525,9 +3561,11 @@ define('select2/core',[
     });
 
     // Hide the original select
-
     $element.hide();
 
+    // Synchronize any monitored attributes
+    this._syncAttributes();
+
     this._tabindex = $element.attr('tabindex') || 0;
 
     $element.attr('tabindex', '-1');
@@ -3576,6 +3614,27 @@ define('select2/core',[
         });
       });
     });
+
+    this._sync = Utils.bind(this._syncAttributes, this);
+
+    if (this.$element[0].attachEvent) {
+      this.$element[0].attachEvent('onpropertychange', this._sync);
+    }
+
+    var observer = window.MutationObserver ||
+      window.WebKitMutationObserver ||
+      window.MozMutationObserver
+    ;
+
+    if (observer != null) {
+      this._observer = new observer(function (mutations) {
+        $.each(mutations, self._sync);
+      });
+      this._observer.observe(this.$element[0], {
+        attributes: true,
+        subtree: false
+      });
+    }
   };
 
   Select2.prototype._registerDataEvents = function () {
@@ -3671,6 +3730,14 @@ define('select2/core',[
       self.$container.removeClass('select2-container--open');
     });
 
+    this.on('enable', function () {
+      self.$container.removeClass('select2-container--disabled');
+    });
+
+    this.on('disable', function () {
+      self.$container.addClass('select2-container--disabled');
+    });
+
     this.on('query', function (params) {
       this.data.query(params, function (data) {
         self.trigger('results:all', {
@@ -3720,7 +3787,25 @@ define('select2/core',[
     });
   };
 
+  Select2.prototype._syncAttributes = function () {
+    this.options.set('disabled', this.$element.prop('disabled'));
+
+    if (this.options.get('disabled')) {
+      if (this.isOpen()) {
+        this.trigger('close');
+      }
+
+      this.trigger('disable');
+    } else {
+      this.trigger('enable');
+    }
+  };
+
   Select2.prototype.toggleDropdown = function () {
+    if (this.options.get('disabled')) {
+      return;
+    }
+
     if (this.isOpen()) {
       this.close();
     } else {
@@ -3794,6 +3879,17 @@ define('select2/core',[
   Select2.prototype.destroy = function () {
     this.$container.remove();
 
+    if (this.$element[0].detachEvent) {
+      this.$element[0].detachEvent('onpropertychange', this._sync);
+    }
+
+    if (this._observer != null) {
+      this._observer.disconnect();
+      this._observer = null;
+    }
+
+    this._sync = null;
+
     this.$element.off('.select2');
     this.$element.attr('tabindex', this._tabindex);
 

+ 98 - 2
dist/js/select2.amd.js

@@ -153,6 +153,12 @@ window.$ = window.$ || {};(function() { if ($ && $.fn && $.fn.select2 && $.fn.se
     return chars;
   };
 
+  Utils.bind = function (func, context) {
+    return function () {
+      func.apply(context, arguments);
+    };
+  };
+
   return Utils;
 });
 
@@ -813,6 +819,14 @@ define('select2/selection/single',[
       // User exits the container
     });
 
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
+
     container.on('selection:update', function (params) {
       self.update(params.data);
     });
@@ -897,6 +911,14 @@ define('select2/selection/multiple',[
         data: data
       });
     });
+
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
   };
 
   MultipleSelection.prototype.clear = function () {
@@ -1078,6 +1100,14 @@ define('select2/selection/search',[
       self.$search.val('');
     });
 
+    container.on('enable', function () {
+      self.$search.prop('disabled', false);
+    });
+
+    container.on('disable', function () {
+      self.$search.prop('disabled', true);
+    });
+
     this.$selection.on('keydown', '.select2-search--inline', function (evt) {
       evt.stopPropagation();
 
@@ -3379,6 +3409,10 @@ define('select2/options',[
       this.options.multiple = $e.prop('multiple');
     }
 
+    if (this.options.disabled == null) {
+      this.options.disabled = $e.prop('disabled');
+    }
+
     if (this.options.language == null) {
       if ($e.prop('lang')) {
         this.options.language = $e.prop('lang').toLowerCase();
@@ -3387,6 +3421,9 @@ define('select2/options',[
       }
     }
 
+    $e.prop('disabled', this.options.disabled);
+    $e.prop('multiple', this.options.multiple);
+
     var data = $e.data();
 
     function convertData (data) {
@@ -3517,7 +3554,6 @@ define('select2/core',[
     this._registerEvents();
 
     // Set the initial state
-
     this.data.current(function (initialData) {
       self.trigger('selection:update', {
         data: initialData
@@ -3525,9 +3561,11 @@ define('select2/core',[
     });
 
     // Hide the original select
-
     $element.hide();
 
+    // Synchronize any monitored attributes
+    this._syncAttributes();
+
     this._tabindex = $element.attr('tabindex') || 0;
 
     $element.attr('tabindex', '-1');
@@ -3576,6 +3614,27 @@ define('select2/core',[
         });
       });
     });
+
+    this._sync = Utils.bind(this._syncAttributes, this);
+
+    if (this.$element[0].attachEvent) {
+      this.$element[0].attachEvent('onpropertychange', this._sync);
+    }
+
+    var observer = window.MutationObserver ||
+      window.WebKitMutationObserver ||
+      window.MozMutationObserver
+    ;
+
+    if (observer != null) {
+      this._observer = new observer(function (mutations) {
+        $.each(mutations, self._sync);
+      });
+      this._observer.observe(this.$element[0], {
+        attributes: true,
+        subtree: false
+      });
+    }
   };
 
   Select2.prototype._registerDataEvents = function () {
@@ -3671,6 +3730,14 @@ define('select2/core',[
       self.$container.removeClass('select2-container--open');
     });
 
+    this.on('enable', function () {
+      self.$container.removeClass('select2-container--disabled');
+    });
+
+    this.on('disable', function () {
+      self.$container.addClass('select2-container--disabled');
+    });
+
     this.on('query', function (params) {
       this.data.query(params, function (data) {
         self.trigger('results:all', {
@@ -3720,7 +3787,25 @@ define('select2/core',[
     });
   };
 
+  Select2.prototype._syncAttributes = function () {
+    this.options.set('disabled', this.$element.prop('disabled'));
+
+    if (this.options.get('disabled')) {
+      if (this.isOpen()) {
+        this.trigger('close');
+      }
+
+      this.trigger('disable');
+    } else {
+      this.trigger('enable');
+    }
+  };
+
   Select2.prototype.toggleDropdown = function () {
+    if (this.options.get('disabled')) {
+      return;
+    }
+
     if (this.isOpen()) {
       this.close();
     } else {
@@ -3794,6 +3879,17 @@ define('select2/core',[
   Select2.prototype.destroy = function () {
     this.$container.remove();
 
+    if (this.$element[0].detachEvent) {
+      this.$element[0].detachEvent('onpropertychange', this._sync);
+    }
+
+    if (this._observer != null) {
+      this._observer.disconnect();
+      this._observer = null;
+    }
+
+    this._sync = null;
+
     this.$element.off('.select2');
     this.$element.attr('tabindex', this._tabindex);
 

+ 98 - 2
dist/js/select2.full.js

@@ -9688,6 +9688,12 @@ define('select2/utils',[], function () {
     return chars;
   };
 
+  Utils.bind = function (func, context) {
+    return function () {
+      func.apply(context, arguments);
+    };
+  };
+
   return Utils;
 });
 
@@ -10348,6 +10354,14 @@ define('select2/selection/single',[
       // User exits the container
     });
 
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
+
     container.on('selection:update', function (params) {
       self.update(params.data);
     });
@@ -10432,6 +10446,14 @@ define('select2/selection/multiple',[
         data: data
       });
     });
+
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
   };
 
   MultipleSelection.prototype.clear = function () {
@@ -10613,6 +10635,14 @@ define('select2/selection/search',[
       self.$search.val('');
     });
 
+    container.on('enable', function () {
+      self.$search.prop('disabled', false);
+    });
+
+    container.on('disable', function () {
+      self.$search.prop('disabled', true);
+    });
+
     this.$selection.on('keydown', '.select2-search--inline', function (evt) {
       evt.stopPropagation();
 
@@ -12914,6 +12944,10 @@ define('select2/options',[
       this.options.multiple = $e.prop('multiple');
     }
 
+    if (this.options.disabled == null) {
+      this.options.disabled = $e.prop('disabled');
+    }
+
     if (this.options.language == null) {
       if ($e.prop('lang')) {
         this.options.language = $e.prop('lang').toLowerCase();
@@ -12922,6 +12956,9 @@ define('select2/options',[
       }
     }
 
+    $e.prop('disabled', this.options.disabled);
+    $e.prop('multiple', this.options.multiple);
+
     var data = $e.data();
 
     function convertData (data) {
@@ -13052,7 +13089,6 @@ define('select2/core',[
     this._registerEvents();
 
     // Set the initial state
-
     this.data.current(function (initialData) {
       self.trigger('selection:update', {
         data: initialData
@@ -13060,9 +13096,11 @@ define('select2/core',[
     });
 
     // Hide the original select
-
     $element.hide();
 
+    // Synchronize any monitored attributes
+    this._syncAttributes();
+
     this._tabindex = $element.attr('tabindex') || 0;
 
     $element.attr('tabindex', '-1');
@@ -13111,6 +13149,27 @@ define('select2/core',[
         });
       });
     });
+
+    this._sync = Utils.bind(this._syncAttributes, this);
+
+    if (this.$element[0].attachEvent) {
+      this.$element[0].attachEvent('onpropertychange', this._sync);
+    }
+
+    var observer = window.MutationObserver ||
+      window.WebKitMutationObserver ||
+      window.MozMutationObserver
+    ;
+
+    if (observer != null) {
+      this._observer = new observer(function (mutations) {
+        $.each(mutations, self._sync);
+      });
+      this._observer.observe(this.$element[0], {
+        attributes: true,
+        subtree: false
+      });
+    }
   };
 
   Select2.prototype._registerDataEvents = function () {
@@ -13206,6 +13265,14 @@ define('select2/core',[
       self.$container.removeClass('select2-container--open');
     });
 
+    this.on('enable', function () {
+      self.$container.removeClass('select2-container--disabled');
+    });
+
+    this.on('disable', function () {
+      self.$container.addClass('select2-container--disabled');
+    });
+
     this.on('query', function (params) {
       this.data.query(params, function (data) {
         self.trigger('results:all', {
@@ -13255,7 +13322,25 @@ define('select2/core',[
     });
   };
 
+  Select2.prototype._syncAttributes = function () {
+    this.options.set('disabled', this.$element.prop('disabled'));
+
+    if (this.options.get('disabled')) {
+      if (this.isOpen()) {
+        this.trigger('close');
+      }
+
+      this.trigger('disable');
+    } else {
+      this.trigger('enable');
+    }
+  };
+
   Select2.prototype.toggleDropdown = function () {
+    if (this.options.get('disabled')) {
+      return;
+    }
+
     if (this.isOpen()) {
       this.close();
     } else {
@@ -13329,6 +13414,17 @@ define('select2/core',[
   Select2.prototype.destroy = function () {
     this.$container.remove();
 
+    if (this.$element[0].detachEvent) {
+      this.$element[0].detachEvent('onpropertychange', this._sync);
+    }
+
+    if (this._observer != null) {
+      this._observer.disconnect();
+      this._observer = null;
+    }
+
+    this._sync = null;
+
     this.$element.off('.select2');
     this.$element.attr('tabindex', this._tabindex);
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
dist/js/select2.full.min.js


+ 98 - 2
dist/js/select2.js

@@ -581,6 +581,12 @@ define('select2/utils',[], function () {
     return chars;
   };
 
+  Utils.bind = function (func, context) {
+    return function () {
+      func.apply(context, arguments);
+    };
+  };
+
   return Utils;
 });
 
@@ -1241,6 +1247,14 @@ define('select2/selection/single',[
       // User exits the container
     });
 
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
+
     container.on('selection:update', function (params) {
       self.update(params.data);
     });
@@ -1325,6 +1339,14 @@ define('select2/selection/multiple',[
         data: data
       });
     });
+
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
   };
 
   MultipleSelection.prototype.clear = function () {
@@ -1506,6 +1528,14 @@ define('select2/selection/search',[
       self.$search.val('');
     });
 
+    container.on('enable', function () {
+      self.$search.prop('disabled', false);
+    });
+
+    container.on('disable', function () {
+      self.$search.prop('disabled', true);
+    });
+
     this.$selection.on('keydown', '.select2-search--inline', function (evt) {
       evt.stopPropagation();
 
@@ -3807,6 +3837,10 @@ define('select2/options',[
       this.options.multiple = $e.prop('multiple');
     }
 
+    if (this.options.disabled == null) {
+      this.options.disabled = $e.prop('disabled');
+    }
+
     if (this.options.language == null) {
       if ($e.prop('lang')) {
         this.options.language = $e.prop('lang').toLowerCase();
@@ -3815,6 +3849,9 @@ define('select2/options',[
       }
     }
 
+    $e.prop('disabled', this.options.disabled);
+    $e.prop('multiple', this.options.multiple);
+
     var data = $e.data();
 
     function convertData (data) {
@@ -3945,7 +3982,6 @@ define('select2/core',[
     this._registerEvents();
 
     // Set the initial state
-
     this.data.current(function (initialData) {
       self.trigger('selection:update', {
         data: initialData
@@ -3953,9 +3989,11 @@ define('select2/core',[
     });
 
     // Hide the original select
-
     $element.hide();
 
+    // Synchronize any monitored attributes
+    this._syncAttributes();
+
     this._tabindex = $element.attr('tabindex') || 0;
 
     $element.attr('tabindex', '-1');
@@ -4004,6 +4042,27 @@ define('select2/core',[
         });
       });
     });
+
+    this._sync = Utils.bind(this._syncAttributes, this);
+
+    if (this.$element[0].attachEvent) {
+      this.$element[0].attachEvent('onpropertychange', this._sync);
+    }
+
+    var observer = window.MutationObserver ||
+      window.WebKitMutationObserver ||
+      window.MozMutationObserver
+    ;
+
+    if (observer != null) {
+      this._observer = new observer(function (mutations) {
+        $.each(mutations, self._sync);
+      });
+      this._observer.observe(this.$element[0], {
+        attributes: true,
+        subtree: false
+      });
+    }
   };
 
   Select2.prototype._registerDataEvents = function () {
@@ -4099,6 +4158,14 @@ define('select2/core',[
       self.$container.removeClass('select2-container--open');
     });
 
+    this.on('enable', function () {
+      self.$container.removeClass('select2-container--disabled');
+    });
+
+    this.on('disable', function () {
+      self.$container.addClass('select2-container--disabled');
+    });
+
     this.on('query', function (params) {
       this.data.query(params, function (data) {
         self.trigger('results:all', {
@@ -4148,7 +4215,25 @@ define('select2/core',[
     });
   };
 
+  Select2.prototype._syncAttributes = function () {
+    this.options.set('disabled', this.$element.prop('disabled'));
+
+    if (this.options.get('disabled')) {
+      if (this.isOpen()) {
+        this.trigger('close');
+      }
+
+      this.trigger('disable');
+    } else {
+      this.trigger('enable');
+    }
+  };
+
   Select2.prototype.toggleDropdown = function () {
+    if (this.options.get('disabled')) {
+      return;
+    }
+
     if (this.isOpen()) {
       this.close();
     } else {
@@ -4222,6 +4307,17 @@ define('select2/core',[
   Select2.prototype.destroy = function () {
     this.$container.remove();
 
+    if (this.$element[0].detachEvent) {
+      this.$element[0].detachEvent('onpropertychange', this._sync);
+    }
+
+    if (this._observer != null) {
+      this._observer.disconnect();
+      this._observer = null;
+    }
+
+    this._sync = null;
+
     this.$element.off('.select2');
     this.$element.attr('tabindex', this._tabindex);
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
dist/js/select2.min.js


+ 49 - 1
docs/examples.html

@@ -238,6 +238,52 @@ $(".js-data-example-ajax").select2({
     </div>
   </section>
 
+  <section id="disabled" class="row">
+    <div class="col-md-4">
+      <h1>Disabled mode</h1>
+
+      <p>
+        Select2 will response the <code>disabled</code> attribute on
+        <code>&lt;select&gt;</code> elements. You can also initialize Select2
+        with <code>disabled: true</code> to get the same effect.
+      </p>
+
+      <p>
+        <select class="js-example-disabled js-states form-control" disabled="disabled"></select>
+      </p>
+
+      <p>
+        <select class="js-example-disabled-multi js-states form-control" multiple="multiple" disabled="disabled"></select>
+      </p>
+
+      <p>
+        <button class="js-programmatic-enable btn btn-primary">
+          Enable
+        </button>
+        <button class="js-programmatic-disable btn btn-warning">
+          Disable
+        </button>
+      </p>
+    </div>
+    <div class="col-md-8">
+      <h2>Example code</h2>
+
+      <pre data-fill-from=".js-code-disabled"></pre>
+
+<script type="text/javascript" class="js-code-disabled">
+$(".js-programmatic-enable").on("click", function () {
+  $(".js-example-disabled").prop("disabled", false);
+  $(".js-example-disabled-multi").prop("disabled", false);
+});
+
+$(".js-programmatic-disable").on("click", function () {
+  $(".js-example-disabled").prop("disabled", true);
+  $(".js-example-disabled-multi").prop("disabled", true);
+});
+</script>
+    </div>
+  </section>
+
   <section id="disabled-results" class="row">
     <div class="col-md-4">
       <h1>Disabled results</h1>
@@ -256,7 +302,6 @@ $(".js-data-example-ajax").select2({
           <option value="three">Third</option>
         </select>
       </p>
-
     </div>
     <div class="col-md-8">
       <h2>Example code</h2>
@@ -703,6 +748,9 @@ $.fn.select2.amd.require(
     }
   });
 
+  $(".js-example-disabled").select2();
+  $(".js-example-disabled-multi").select2();
+
   $disabledResults.select2();
 
   $(".js-example-programmatic").select2();

+ 61 - 2
src/js/select2/core.js

@@ -64,7 +64,6 @@ define([
     this._registerEvents();
 
     // Set the initial state
-
     this.data.current(function (initialData) {
       self.trigger('selection:update', {
         data: initialData
@@ -72,9 +71,11 @@ define([
     });
 
     // Hide the original select
-
     $element.hide();
 
+    // Synchronize any monitored attributes
+    this._syncAttributes();
+
     this._tabindex = $element.attr('tabindex') || 0;
 
     $element.attr('tabindex', '-1');
@@ -123,6 +124,27 @@ define([
         });
       });
     });
+
+    this._sync = Utils.bind(this._syncAttributes, this);
+
+    if (this.$element[0].attachEvent) {
+      this.$element[0].attachEvent('onpropertychange', this._sync);
+    }
+
+    var observer = window.MutationObserver ||
+      window.WebKitMutationObserver ||
+      window.MozMutationObserver
+    ;
+
+    if (observer != null) {
+      this._observer = new observer(function (mutations) {
+        $.each(mutations, self._sync);
+      });
+      this._observer.observe(this.$element[0], {
+        attributes: true,
+        subtree: false
+      });
+    }
   };
 
   Select2.prototype._registerDataEvents = function () {
@@ -218,6 +240,14 @@ define([
       self.$container.removeClass('select2-container--open');
     });
 
+    this.on('enable', function () {
+      self.$container.removeClass('select2-container--disabled');
+    });
+
+    this.on('disable', function () {
+      self.$container.addClass('select2-container--disabled');
+    });
+
     this.on('query', function (params) {
       this.data.query(params, function (data) {
         self.trigger('results:all', {
@@ -267,7 +297,25 @@ define([
     });
   };
 
+  Select2.prototype._syncAttributes = function () {
+    this.options.set('disabled', this.$element.prop('disabled'));
+
+    if (this.options.get('disabled')) {
+      if (this.isOpen()) {
+        this.trigger('close');
+      }
+
+      this.trigger('disable');
+    } else {
+      this.trigger('enable');
+    }
+  };
+
   Select2.prototype.toggleDropdown = function () {
+    if (this.options.get('disabled')) {
+      return;
+    }
+
     if (this.isOpen()) {
       this.close();
     } else {
@@ -341,6 +389,17 @@ define([
   Select2.prototype.destroy = function () {
     this.$container.remove();
 
+    if (this.$element[0].detachEvent) {
+      this.$element[0].detachEvent('onpropertychange', this._sync);
+    }
+
+    if (this._observer != null) {
+      this._observer.disconnect();
+      this._observer = null;
+    }
+
+    this._sync = null;
+
     this.$element.off('.select2');
     this.$element.attr('tabindex', this._tabindex);
 

+ 7 - 0
src/js/select2/options.js

@@ -19,6 +19,10 @@ define([
       this.options.multiple = $e.prop('multiple');
     }
 
+    if (this.options.disabled == null) {
+      this.options.disabled = $e.prop('disabled');
+    }
+
     if (this.options.language == null) {
       if ($e.prop('lang')) {
         this.options.language = $e.prop('lang').toLowerCase();
@@ -27,6 +31,9 @@ define([
       }
     }
 
+    $e.prop('disabled', this.options.disabled);
+    $e.prop('multiple', this.options.multiple);
+
     var data = $e.data();
 
     function convertData (data) {

+ 8 - 0
src/js/select2/selection/multiple.js

@@ -47,6 +47,14 @@ define([
         data: data
       });
     });
+
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
   };
 
   MultipleSelection.prototype.clear = function () {

+ 8 - 0
src/js/select2/selection/search.js

@@ -39,6 +39,14 @@ define([
       self.$search.val('');
     });
 
+    container.on('enable', function () {
+      self.$search.prop('disabled', false);
+    });
+
+    container.on('disable', function () {
+      self.$search.prop('disabled', true);
+    });
+
     this.$selection.on('keydown', '.select2-search--inline', function (evt) {
       evt.stopPropagation();
 

+ 8 - 0
src/js/select2/selection/single.js

@@ -57,6 +57,14 @@ define([
       // User exits the container
     });
 
+    container.on('enable', function () {
+      self.$selection.attr('tabindex', '0');
+    });
+
+    container.on('disable', function () {
+      self.$selection.attr('tabindex', '-1');
+    });
+
     container.on('selection:update', function (params) {
       self.update(params.data);
     });

+ 6 - 0
src/js/select2/utils.js

@@ -153,5 +153,11 @@ define([], function () {
     return chars;
   };
 
+  Utils.bind = function (func, context) {
+    return function () {
+      func.apply(context, arguments);
+    };
+  };
+
   return Utils;
 });

+ 7 - 0
src/scss/theme/default/_multiple.scss

@@ -46,3 +46,10 @@
     }
   }
 }
+
+&.select2-container--disabled {
+  .select2-selection--multiple {
+    background-color: #eee;
+    cursor: default;
+  }
+}

+ 7 - 0
src/scss/theme/default/_single.scss

@@ -47,6 +47,13 @@
   }
 }
 
+&.select2-container--disabled {
+  .select2-selection--single {
+    background-color: #eee;
+    cursor: default;
+  }
+}
+
 &.select2-container--open {
   .select2-selection--single {
     .select2-selection__arrow {

+ 1 - 0
src/scss/theme/default/layout.scss

@@ -24,6 +24,7 @@
 
   .select2-search--inline {
     .select2-search__field {
+      background: transparent;
       border: none;
       outline: 0;
     }

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio