Ver código fonte

Added `destroy` method

Now Select2 supports destroying itself, and all elements that it
creates.
Kevin Brown 10 anos atrás
pai
commit
a2766b7ed6

+ 56 - 1
dist/js/select2.amd.full.js

@@ -520,6 +520,10 @@ define('select2/results',[
     });
   };
 
+  Results.prototype.destroy = function () {
+    this.$results.remove();
+  };
+
   Results.prototype.ensureHighlightVisible = function () {
     var $highlighted = this.$results.find('.highlighted');
 
@@ -604,6 +608,11 @@ define('select2/selection/base',[
     });
   };
 
+  BaseSelection.prototype.destroy = function () {
+    // Unbind the dropdown click handler if it exists
+    $(document.body).off('.select2.' + container.id);
+  };
+
   BaseSelection.prototype.update = function (data) {
     throw new Error('The `update` method must be defined in child classes.');
   };
@@ -961,6 +970,10 @@ define('select2/data/base',[
     // Can be implemented in subclasses
   };
 
+  BaseAdapter.prototype.destroy = function () {
+    // Can be implemented in subclasses
+  };
+
   BaseAdapter.prototype.generateResultId = function (container, data) {
     var id = container.id + '-result-';
 
@@ -1074,6 +1087,14 @@ define('select2/data/select',[
     });
   };
 
+  SelectAdapter.prototype.destroy = function () {
+    // Remove anything added to child elements
+    this.$element.find('*').each(function () {
+      // Remove any custom data set by Select2
+      $.removeData(this, 'data');
+    });
+  };
+
   SelectAdapter.prototype.query = function (params, callback) {
     var data = [];
     var self = this;
@@ -1479,9 +1500,16 @@ define('select2/dropdown',[
       '</span>'
     );
 
+    this.$dropdown = $dropdown;
+
     return $dropdown;
   };
 
+  Dropdown.prototype.destroy = function () {
+    // Remove the dropdown from the DOM
+    this.$dropdown.remove();
+  };
+
   Dropdown.prototype.bind = function (container, $container) {
     // Can be implemented in subclasses
   };
@@ -1950,6 +1978,10 @@ define('select2/core',[
   './keys'
 ], function ($, Options, Utils, KEYS) {
   var Select2 = function ($element, options) {
+    if ($element.data('select2') != null) {
+      return;
+    }
+
     this.$element = $element;
 
     this.id = this._generateId($element);
@@ -2018,6 +2050,9 @@ define('select2/core',[
     // Hide the original select
 
     $element.hide();
+
+    this._tabindex = $element.attr('tabindex') || 0;
+
     $element.attr('tabindex', '-1');
 
     $element.data('select2', this);
@@ -2074,7 +2109,7 @@ define('select2/core',[
   Select2.prototype._registerDomEvents = function () {
     var self = this;
 
-    this.$element.on('change', function () {
+    this.$element.on('change.select2', function () {
       self.data.current(function (data) {
         self.trigger('selection:update', {
           data: data
@@ -2251,6 +2286,26 @@ define('select2/core',[
     return this.$container.hasClass('open');
   };
 
+  Select2.prototype.destroy = function () {
+    this.$container.remove();
+
+    this.$element.off('.select2');
+    this.$element.attr('tabindex', this._tabindex);
+
+    this.$element.show();
+    this.$element.removeData('select2');
+
+    this.data.destroy();
+    this.selection.destroy();
+    this.dropdown.destroy();
+    this.results.destroy();
+
+    this.data = null;
+    this.selection = null;
+    this.dropdown = null;
+    this.results = null;
+  };
+
   Select2.prototype.render = function () {
     var $container = $(
       '<span class="select2 select2-container select2-theme-default">' +

+ 56 - 1
dist/js/select2.amd.js

@@ -520,6 +520,10 @@ define('select2/results',[
     });
   };
 
+  Results.prototype.destroy = function () {
+    this.$results.remove();
+  };
+
   Results.prototype.ensureHighlightVisible = function () {
     var $highlighted = this.$results.find('.highlighted');
 
@@ -604,6 +608,11 @@ define('select2/selection/base',[
     });
   };
 
+  BaseSelection.prototype.destroy = function () {
+    // Unbind the dropdown click handler if it exists
+    $(document.body).off('.select2.' + container.id);
+  };
+
   BaseSelection.prototype.update = function (data) {
     throw new Error('The `update` method must be defined in child classes.');
   };
@@ -961,6 +970,10 @@ define('select2/data/base',[
     // Can be implemented in subclasses
   };
 
+  BaseAdapter.prototype.destroy = function () {
+    // Can be implemented in subclasses
+  };
+
   BaseAdapter.prototype.generateResultId = function (container, data) {
     var id = container.id + '-result-';
 
@@ -1074,6 +1087,14 @@ define('select2/data/select',[
     });
   };
 
+  SelectAdapter.prototype.destroy = function () {
+    // Remove anything added to child elements
+    this.$element.find('*').each(function () {
+      // Remove any custom data set by Select2
+      $.removeData(this, 'data');
+    });
+  };
+
   SelectAdapter.prototype.query = function (params, callback) {
     var data = [];
     var self = this;
@@ -1479,9 +1500,16 @@ define('select2/dropdown',[
       '</span>'
     );
 
+    this.$dropdown = $dropdown;
+
     return $dropdown;
   };
 
+  Dropdown.prototype.destroy = function () {
+    // Remove the dropdown from the DOM
+    this.$dropdown.remove();
+  };
+
   Dropdown.prototype.bind = function (container, $container) {
     // Can be implemented in subclasses
   };
@@ -1950,6 +1978,10 @@ define('select2/core',[
   './keys'
 ], function ($, Options, Utils, KEYS) {
   var Select2 = function ($element, options) {
+    if ($element.data('select2') != null) {
+      return;
+    }
+
     this.$element = $element;
 
     this.id = this._generateId($element);
@@ -2018,6 +2050,9 @@ define('select2/core',[
     // Hide the original select
 
     $element.hide();
+
+    this._tabindex = $element.attr('tabindex') || 0;
+
     $element.attr('tabindex', '-1');
 
     $element.data('select2', this);
@@ -2074,7 +2109,7 @@ define('select2/core',[
   Select2.prototype._registerDomEvents = function () {
     var self = this;
 
-    this.$element.on('change', function () {
+    this.$element.on('change.select2', function () {
       self.data.current(function (data) {
         self.trigger('selection:update', {
           data: data
@@ -2251,6 +2286,26 @@ define('select2/core',[
     return this.$container.hasClass('open');
   };
 
+  Select2.prototype.destroy = function () {
+    this.$container.remove();
+
+    this.$element.off('.select2');
+    this.$element.attr('tabindex', this._tabindex);
+
+    this.$element.show();
+    this.$element.removeData('select2');
+
+    this.data.destroy();
+    this.selection.destroy();
+    this.dropdown.destroy();
+    this.results.destroy();
+
+    this.data = null;
+    this.selection = null;
+    this.dropdown = null;
+    this.results = null;
+  };
+
   Select2.prototype.render = function () {
     var $container = $(
       '<span class="select2 select2-container select2-theme-default">' +

+ 56 - 1
dist/js/select2.full.js

@@ -10055,6 +10055,10 @@ define('select2/results',[
     });
   };
 
+  Results.prototype.destroy = function () {
+    this.$results.remove();
+  };
+
   Results.prototype.ensureHighlightVisible = function () {
     var $highlighted = this.$results.find('.highlighted');
 
@@ -10139,6 +10143,11 @@ define('select2/selection/base',[
     });
   };
 
+  BaseSelection.prototype.destroy = function () {
+    // Unbind the dropdown click handler if it exists
+    $(document.body).off('.select2.' + container.id);
+  };
+
   BaseSelection.prototype.update = function (data) {
     throw new Error('The `update` method must be defined in child classes.');
   };
@@ -10496,6 +10505,10 @@ define('select2/data/base',[
     // Can be implemented in subclasses
   };
 
+  BaseAdapter.prototype.destroy = function () {
+    // Can be implemented in subclasses
+  };
+
   BaseAdapter.prototype.generateResultId = function (container, data) {
     var id = container.id + '-result-';
 
@@ -10609,6 +10622,14 @@ define('select2/data/select',[
     });
   };
 
+  SelectAdapter.prototype.destroy = function () {
+    // Remove anything added to child elements
+    this.$element.find('*').each(function () {
+      // Remove any custom data set by Select2
+      $.removeData(this, 'data');
+    });
+  };
+
   SelectAdapter.prototype.query = function (params, callback) {
     var data = [];
     var self = this;
@@ -11014,9 +11035,16 @@ define('select2/dropdown',[
       '</span>'
     );
 
+    this.$dropdown = $dropdown;
+
     return $dropdown;
   };
 
+  Dropdown.prototype.destroy = function () {
+    // Remove the dropdown from the DOM
+    this.$dropdown.remove();
+  };
+
   Dropdown.prototype.bind = function (container, $container) {
     // Can be implemented in subclasses
   };
@@ -11485,6 +11513,10 @@ define('select2/core',[
   './keys'
 ], function ($, Options, Utils, KEYS) {
   var Select2 = function ($element, options) {
+    if ($element.data('select2') != null) {
+      return;
+    }
+
     this.$element = $element;
 
     this.id = this._generateId($element);
@@ -11553,6 +11585,9 @@ define('select2/core',[
     // Hide the original select
 
     $element.hide();
+
+    this._tabindex = $element.attr('tabindex') || 0;
+
     $element.attr('tabindex', '-1');
 
     $element.data('select2', this);
@@ -11609,7 +11644,7 @@ define('select2/core',[
   Select2.prototype._registerDomEvents = function () {
     var self = this;
 
-    this.$element.on('change', function () {
+    this.$element.on('change.select2', function () {
       self.data.current(function (data) {
         self.trigger('selection:update', {
           data: data
@@ -11786,6 +11821,26 @@ define('select2/core',[
     return this.$container.hasClass('open');
   };
 
+  Select2.prototype.destroy = function () {
+    this.$container.remove();
+
+    this.$element.off('.select2');
+    this.$element.attr('tabindex', this._tabindex);
+
+    this.$element.show();
+    this.$element.removeData('select2');
+
+    this.data.destroy();
+    this.selection.destroy();
+    this.dropdown.destroy();
+    this.results.destroy();
+
+    this.data = null;
+    this.selection = null;
+    this.dropdown = null;
+    this.results = null;
+  };
+
   Select2.prototype.render = function () {
     var $container = $(
       '<span class="select2 select2-container select2-theme-default">' +

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/js/select2.full.min.js


+ 56 - 1
dist/js/select2.js

@@ -948,6 +948,10 @@ define('select2/results',[
     });
   };
 
+  Results.prototype.destroy = function () {
+    this.$results.remove();
+  };
+
   Results.prototype.ensureHighlightVisible = function () {
     var $highlighted = this.$results.find('.highlighted');
 
@@ -1032,6 +1036,11 @@ define('select2/selection/base',[
     });
   };
 
+  BaseSelection.prototype.destroy = function () {
+    // Unbind the dropdown click handler if it exists
+    $(document.body).off('.select2.' + container.id);
+  };
+
   BaseSelection.prototype.update = function (data) {
     throw new Error('The `update` method must be defined in child classes.');
   };
@@ -1389,6 +1398,10 @@ define('select2/data/base',[
     // Can be implemented in subclasses
   };
 
+  BaseAdapter.prototype.destroy = function () {
+    // Can be implemented in subclasses
+  };
+
   BaseAdapter.prototype.generateResultId = function (container, data) {
     var id = container.id + '-result-';
 
@@ -1502,6 +1515,14 @@ define('select2/data/select',[
     });
   };
 
+  SelectAdapter.prototype.destroy = function () {
+    // Remove anything added to child elements
+    this.$element.find('*').each(function () {
+      // Remove any custom data set by Select2
+      $.removeData(this, 'data');
+    });
+  };
+
   SelectAdapter.prototype.query = function (params, callback) {
     var data = [];
     var self = this;
@@ -1907,9 +1928,16 @@ define('select2/dropdown',[
       '</span>'
     );
 
+    this.$dropdown = $dropdown;
+
     return $dropdown;
   };
 
+  Dropdown.prototype.destroy = function () {
+    // Remove the dropdown from the DOM
+    this.$dropdown.remove();
+  };
+
   Dropdown.prototype.bind = function (container, $container) {
     // Can be implemented in subclasses
   };
@@ -2378,6 +2406,10 @@ define('select2/core',[
   './keys'
 ], function ($, Options, Utils, KEYS) {
   var Select2 = function ($element, options) {
+    if ($element.data('select2') != null) {
+      return;
+    }
+
     this.$element = $element;
 
     this.id = this._generateId($element);
@@ -2446,6 +2478,9 @@ define('select2/core',[
     // Hide the original select
 
     $element.hide();
+
+    this._tabindex = $element.attr('tabindex') || 0;
+
     $element.attr('tabindex', '-1');
 
     $element.data('select2', this);
@@ -2502,7 +2537,7 @@ define('select2/core',[
   Select2.prototype._registerDomEvents = function () {
     var self = this;
 
-    this.$element.on('change', function () {
+    this.$element.on('change.select2', function () {
       self.data.current(function (data) {
         self.trigger('selection:update', {
           data: data
@@ -2679,6 +2714,26 @@ define('select2/core',[
     return this.$container.hasClass('open');
   };
 
+  Select2.prototype.destroy = function () {
+    this.$container.remove();
+
+    this.$element.off('.select2');
+    this.$element.attr('tabindex', this._tabindex);
+
+    this.$element.show();
+    this.$element.removeData('select2');
+
+    this.data.destroy();
+    this.selection.destroy();
+    this.dropdown.destroy();
+    this.results.destroy();
+
+    this.data = null;
+    this.selection = null;
+    this.dropdown = null;
+    this.results = null;
+  };
+
   Select2.prototype.render = function () {
     var $container = $(
       '<span class="select2 select2-container select2-theme-default">' +

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/js/select2.min.js


+ 11 - 0
docs/examples.html

@@ -246,6 +246,14 @@ $(".js-example-data-array-selected").select2({
         <button class="js-programmatic-close btn btn-success">
           Close
         </button>
+
+        <button class="js-programmatic-init btn btn-danger">
+          Init
+        </button>
+
+        <button class="js-programmatic-destroy btn btn-danger">
+          Destroy
+        </button>
       </p>
 
       <p>
@@ -263,6 +271,9 @@ var $example = $(".js-example-programmatic");
 
 $(".js-programmatic-open").on("click", function () { $example.select2("open"); });
 $(".js-programmatic-close").on("click", function () { $example.select2("close"); });
+
+$(".js-programmatic-init").on("click", function () { $example.select2(); });
+$(".js-programmatic-destroy").on("click", function () { $example.select2("destroy"); });
 </script>
     </div>
   </section>

+ 28 - 1
src/js/select2/core.js

@@ -5,6 +5,10 @@ define([
   './keys'
 ], function ($, Options, Utils, KEYS) {
   var Select2 = function ($element, options) {
+    if ($element.data('select2') != null) {
+      return;
+    }
+
     this.$element = $element;
 
     this.id = this._generateId($element);
@@ -73,6 +77,9 @@ define([
     // Hide the original select
 
     $element.hide();
+
+    this._tabindex = $element.attr('tabindex') || 0;
+
     $element.attr('tabindex', '-1');
 
     $element.data('select2', this);
@@ -129,7 +136,7 @@ define([
   Select2.prototype._registerDomEvents = function () {
     var self = this;
 
-    this.$element.on('change', function () {
+    this.$element.on('change.select2', function () {
       self.data.current(function (data) {
         self.trigger('selection:update', {
           data: data
@@ -306,6 +313,26 @@ define([
     return this.$container.hasClass('open');
   };
 
+  Select2.prototype.destroy = function () {
+    this.$container.remove();
+
+    this.$element.off('.select2');
+    this.$element.attr('tabindex', this._tabindex);
+
+    this.$element.show();
+    this.$element.removeData('select2');
+
+    this.data.destroy();
+    this.selection.destroy();
+    this.dropdown.destroy();
+    this.results.destroy();
+
+    this.data = null;
+    this.selection = null;
+    this.dropdown = null;
+    this.results = null;
+  };
+
   Select2.prototype.render = function () {
     var $container = $(
       '<span class="select2 select2-container select2-theme-default">' +

+ 4 - 0
src/js/select2/data/base.js

@@ -19,6 +19,10 @@ define([
     // Can be implemented in subclasses
   };
 
+  BaseAdapter.prototype.destroy = function () {
+    // Can be implemented in subclasses
+  };
+
   BaseAdapter.prototype.generateResultId = function (container, data) {
     var id = container.id + '-result-';
 

+ 8 - 0
src/js/select2/data/select.js

@@ -95,6 +95,14 @@ define([
     });
   };
 
+  SelectAdapter.prototype.destroy = function () {
+    // Remove anything added to child elements
+    this.$element.find('*').each(function () {
+      // Remove any custom data set by Select2
+      $.removeData(this, 'data');
+    });
+  };
+
   SelectAdapter.prototype.query = function (params, callback) {
     var data = [];
     var self = this;

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

@@ -14,9 +14,16 @@ define([
       '</span>'
     );
 
+    this.$dropdown = $dropdown;
+
     return $dropdown;
   };
 
+  Dropdown.prototype.destroy = function () {
+    // Remove the dropdown from the DOM
+    this.$dropdown.remove();
+  };
+
   Dropdown.prototype.bind = function (container, $container) {
     // Can be implemented in subclasses
   };

+ 4 - 0
src/js/select2/results.js

@@ -366,6 +366,10 @@ define([
     });
   };
 
+  Results.prototype.destroy = function () {
+    this.$results.remove();
+  };
+
   Results.prototype.ensureHighlightVisible = function () {
     var $highlighted = this.$results.find('.highlighted');
 

+ 5 - 0
src/js/select2/selection/base.js

@@ -48,6 +48,11 @@ define([
     });
   };
 
+  BaseSelection.prototype.destroy = function () {
+    // Unbind the dropdown click handler if it exists
+    $(document.body).off('.select2.' + container.id);
+  };
+
   BaseSelection.prototype.update = function (data) {
     throw new Error('The `update` method must be defined in child classes.');
   };

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff