瀏覽代碼

Normalize internal select/unselect events

Also pull the logic for automatically closing the dropdown into the
dropdown adapter, taking it out of the core.

The `selected` and `unselected` events are now `select` and
`unselect`, which is what many of the other adapters were expecting
them to be.

Some tests for placeholders have been added.
Kevin Brown 10 年之前
父節點
當前提交
024d41b412

+ 22 - 37
dist/js/select2.amd.full.js

@@ -445,11 +445,11 @@ define('select2/results',[
       var data = $highlighted.data('data');
 
       if ($highlighted.attr('aria-selected') == 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           data: data
         });
       } else {
-        self.trigger('selected', {
+        self.trigger('select', {
           data: data
         });
       }
@@ -567,7 +567,7 @@ define('select2/results',[
       var data = $this.data('data');
 
       if ($this.attr('aria-selected') === 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           originalEvent: evt,
           data: data
         });
@@ -575,7 +575,7 @@ define('select2/results',[
         return;
       }
 
-      self.trigger('selected', {
+      self.trigger('select', {
         originalEvent: evt,
         data: data
       });
@@ -936,7 +936,7 @@ define('select2/selection/multiple',[
 
       var data = $selection.data('data');
 
-      self.trigger('unselected', {
+      self.trigger('unselect', {
         originalEvent: evt,
         data: data
       });
@@ -1194,7 +1194,7 @@ define('select2/selection/search',[
   };
 
   Search.prototype.searchRemoveChoice = function (decorated, item) {
-    this.trigger('unselected', {
+    this.trigger('unselect', {
       data: item
     });
 
@@ -2867,7 +2867,21 @@ define('select2/dropdown',[
   };
 
   Dropdown.prototype.bind = function (container, $container) {
-    // Can be implemented in subclasses
+    container.on('select', function (params) {
+      self._onSelect(params);
+    });
+
+    container.on('unselect', function (params) {
+      self._onUnSelect(params);
+    });
+  };
+
+  Dropdown.prototype._onSelect = function () {
+    self.trigger('close');
+  };
+
+  Dropdown.prototype._onUnSelect = function () {
+    self.trigger('close');
   };
 
   return Dropdown;
@@ -3884,24 +3898,12 @@ define('select2/core',[
 
   Select2.prototype._registerSelectionEvents = function () {
     var self = this;
-    var nonRelayEvents = ['open', 'close', 'toggle', 'unselected'];
+    var nonRelayEvents = ['toggle'];
 
-    this.selection.on('open', function () {
-      self.open();
-    });
-    this.selection.on('close', function () {
-      self.close();
-    });
     this.selection.on('toggle', function () {
       self.toggleDropdown();
     });
 
-    this.selection.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
-
     this.selection.on('*', function (name, params) {
       if (nonRelayEvents.indexOf(name) !== -1) {
         return;
@@ -3921,25 +3923,8 @@ define('select2/core',[
 
   Select2.prototype._registerResultsEvents = function () {
     var self = this;
-    var nonRelayEvents = ['selected', 'unselected'];
-
-    this.results.on('selected', function (params) {
-      self.trigger('select', params);
-
-      self.close();
-    });
-
-    this.results.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
 
     this.results.on('*', function (name, params) {
-      if (nonRelayEvents.indexOf(name) !== -1) {
-        return;
-      }
-
       self.trigger(name, params);
     });
   };

+ 22 - 37
dist/js/select2.amd.js

@@ -445,11 +445,11 @@ define('select2/results',[
       var data = $highlighted.data('data');
 
       if ($highlighted.attr('aria-selected') == 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           data: data
         });
       } else {
-        self.trigger('selected', {
+        self.trigger('select', {
           data: data
         });
       }
@@ -567,7 +567,7 @@ define('select2/results',[
       var data = $this.data('data');
 
       if ($this.attr('aria-selected') === 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           originalEvent: evt,
           data: data
         });
@@ -575,7 +575,7 @@ define('select2/results',[
         return;
       }
 
-      self.trigger('selected', {
+      self.trigger('select', {
         originalEvent: evt,
         data: data
       });
@@ -936,7 +936,7 @@ define('select2/selection/multiple',[
 
       var data = $selection.data('data');
 
-      self.trigger('unselected', {
+      self.trigger('unselect', {
         originalEvent: evt,
         data: data
       });
@@ -1194,7 +1194,7 @@ define('select2/selection/search',[
   };
 
   Search.prototype.searchRemoveChoice = function (decorated, item) {
-    this.trigger('unselected', {
+    this.trigger('unselect', {
       data: item
     });
 
@@ -2867,7 +2867,21 @@ define('select2/dropdown',[
   };
 
   Dropdown.prototype.bind = function (container, $container) {
-    // Can be implemented in subclasses
+    container.on('select', function (params) {
+      self._onSelect(params);
+    });
+
+    container.on('unselect', function (params) {
+      self._onUnSelect(params);
+    });
+  };
+
+  Dropdown.prototype._onSelect = function () {
+    self.trigger('close');
+  };
+
+  Dropdown.prototype._onUnSelect = function () {
+    self.trigger('close');
   };
 
   return Dropdown;
@@ -3884,24 +3898,12 @@ define('select2/core',[
 
   Select2.prototype._registerSelectionEvents = function () {
     var self = this;
-    var nonRelayEvents = ['open', 'close', 'toggle', 'unselected'];
+    var nonRelayEvents = ['toggle'];
 
-    this.selection.on('open', function () {
-      self.open();
-    });
-    this.selection.on('close', function () {
-      self.close();
-    });
     this.selection.on('toggle', function () {
       self.toggleDropdown();
     });
 
-    this.selection.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
-
     this.selection.on('*', function (name, params) {
       if (nonRelayEvents.indexOf(name) !== -1) {
         return;
@@ -3921,25 +3923,8 @@ define('select2/core',[
 
   Select2.prototype._registerResultsEvents = function () {
     var self = this;
-    var nonRelayEvents = ['selected', 'unselected'];
-
-    this.results.on('selected', function (params) {
-      self.trigger('select', params);
-
-      self.close();
-    });
-
-    this.results.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
 
     this.results.on('*', function (name, params) {
-      if (nonRelayEvents.indexOf(name) !== -1) {
-        return;
-      }
-
       self.trigger(name, params);
     });
   };

+ 22 - 37
dist/js/select2.full.js

@@ -9980,11 +9980,11 @@ define('select2/results',[
       var data = $highlighted.data('data');
 
       if ($highlighted.attr('aria-selected') == 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           data: data
         });
       } else {
-        self.trigger('selected', {
+        self.trigger('select', {
           data: data
         });
       }
@@ -10102,7 +10102,7 @@ define('select2/results',[
       var data = $this.data('data');
 
       if ($this.attr('aria-selected') === 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           originalEvent: evt,
           data: data
         });
@@ -10110,7 +10110,7 @@ define('select2/results',[
         return;
       }
 
-      self.trigger('selected', {
+      self.trigger('select', {
         originalEvent: evt,
         data: data
       });
@@ -10471,7 +10471,7 @@ define('select2/selection/multiple',[
 
       var data = $selection.data('data');
 
-      self.trigger('unselected', {
+      self.trigger('unselect', {
         originalEvent: evt,
         data: data
       });
@@ -10729,7 +10729,7 @@ define('select2/selection/search',[
   };
 
   Search.prototype.searchRemoveChoice = function (decorated, item) {
-    this.trigger('unselected', {
+    this.trigger('unselect', {
       data: item
     });
 
@@ -12402,7 +12402,21 @@ define('select2/dropdown',[
   };
 
   Dropdown.prototype.bind = function (container, $container) {
-    // Can be implemented in subclasses
+    container.on('select', function (params) {
+      self._onSelect(params);
+    });
+
+    container.on('unselect', function (params) {
+      self._onUnSelect(params);
+    });
+  };
+
+  Dropdown.prototype._onSelect = function () {
+    self.trigger('close');
+  };
+
+  Dropdown.prototype._onUnSelect = function () {
+    self.trigger('close');
   };
 
   return Dropdown;
@@ -13419,24 +13433,12 @@ define('select2/core',[
 
   Select2.prototype._registerSelectionEvents = function () {
     var self = this;
-    var nonRelayEvents = ['open', 'close', 'toggle', 'unselected'];
+    var nonRelayEvents = ['toggle'];
 
-    this.selection.on('open', function () {
-      self.open();
-    });
-    this.selection.on('close', function () {
-      self.close();
-    });
     this.selection.on('toggle', function () {
       self.toggleDropdown();
     });
 
-    this.selection.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
-
     this.selection.on('*', function (name, params) {
       if (nonRelayEvents.indexOf(name) !== -1) {
         return;
@@ -13456,25 +13458,8 @@ define('select2/core',[
 
   Select2.prototype._registerResultsEvents = function () {
     var self = this;
-    var nonRelayEvents = ['selected', 'unselected'];
-
-    this.results.on('selected', function (params) {
-      self.trigger('select', params);
-
-      self.close();
-    });
-
-    this.results.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
 
     this.results.on('*', function (name, params) {
-      if (nonRelayEvents.indexOf(name) !== -1) {
-        return;
-      }
-
       self.trigger(name, params);
     });
   };

File diff suppressed because it is too large
+ 0 - 0
dist/js/select2.full.min.js


+ 22 - 37
dist/js/select2.js

@@ -873,11 +873,11 @@ define('select2/results',[
       var data = $highlighted.data('data');
 
       if ($highlighted.attr('aria-selected') == 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           data: data
         });
       } else {
-        self.trigger('selected', {
+        self.trigger('select', {
           data: data
         });
       }
@@ -995,7 +995,7 @@ define('select2/results',[
       var data = $this.data('data');
 
       if ($this.attr('aria-selected') === 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           originalEvent: evt,
           data: data
         });
@@ -1003,7 +1003,7 @@ define('select2/results',[
         return;
       }
 
-      self.trigger('selected', {
+      self.trigger('select', {
         originalEvent: evt,
         data: data
       });
@@ -1364,7 +1364,7 @@ define('select2/selection/multiple',[
 
       var data = $selection.data('data');
 
-      self.trigger('unselected', {
+      self.trigger('unselect', {
         originalEvent: evt,
         data: data
       });
@@ -1622,7 +1622,7 @@ define('select2/selection/search',[
   };
 
   Search.prototype.searchRemoveChoice = function (decorated, item) {
-    this.trigger('unselected', {
+    this.trigger('unselect', {
       data: item
     });
 
@@ -3295,7 +3295,21 @@ define('select2/dropdown',[
   };
 
   Dropdown.prototype.bind = function (container, $container) {
-    // Can be implemented in subclasses
+    container.on('select', function (params) {
+      self._onSelect(params);
+    });
+
+    container.on('unselect', function (params) {
+      self._onUnSelect(params);
+    });
+  };
+
+  Dropdown.prototype._onSelect = function () {
+    self.trigger('close');
+  };
+
+  Dropdown.prototype._onUnSelect = function () {
+    self.trigger('close');
   };
 
   return Dropdown;
@@ -4312,24 +4326,12 @@ define('select2/core',[
 
   Select2.prototype._registerSelectionEvents = function () {
     var self = this;
-    var nonRelayEvents = ['open', 'close', 'toggle', 'unselected'];
+    var nonRelayEvents = ['toggle'];
 
-    this.selection.on('open', function () {
-      self.open();
-    });
-    this.selection.on('close', function () {
-      self.close();
-    });
     this.selection.on('toggle', function () {
       self.toggleDropdown();
     });
 
-    this.selection.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
-
     this.selection.on('*', function (name, params) {
       if (nonRelayEvents.indexOf(name) !== -1) {
         return;
@@ -4349,25 +4351,8 @@ define('select2/core',[
 
   Select2.prototype._registerResultsEvents = function () {
     var self = this;
-    var nonRelayEvents = ['selected', 'unselected'];
-
-    this.results.on('selected', function (params) {
-      self.trigger('select', params);
-
-      self.close();
-    });
-
-    this.results.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
 
     this.results.on('*', function (name, params) {
-      if (nonRelayEvents.indexOf(name) !== -1) {
-        return;
-      }
-
       self.trigger(name, params);
     });
   };

File diff suppressed because it is too large
+ 0 - 0
dist/js/select2.min.js


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

@@ -157,24 +157,12 @@ define([
 
   Select2.prototype._registerSelectionEvents = function () {
     var self = this;
-    var nonRelayEvents = ['open', 'close', 'toggle', 'unselected'];
+    var nonRelayEvents = ['toggle'];
 
-    this.selection.on('open', function () {
-      self.open();
-    });
-    this.selection.on('close', function () {
-      self.close();
-    });
     this.selection.on('toggle', function () {
       self.toggleDropdown();
     });
 
-    this.selection.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
-
     this.selection.on('*', function (name, params) {
       if (nonRelayEvents.indexOf(name) !== -1) {
         return;
@@ -194,25 +182,8 @@ define([
 
   Select2.prototype._registerResultsEvents = function () {
     var self = this;
-    var nonRelayEvents = ['selected', 'unselected'];
-
-    this.results.on('selected', function (params) {
-      self.trigger('select', params);
-
-      self.close();
-    });
-
-    this.results.on('unselected', function (params) {
-      self.trigger('unselect', params);
-
-      self.close();
-    });
 
     this.results.on('*', function (name, params) {
-      if (nonRelayEvents.indexOf(name) !== -1) {
-        return;
-      }
-
       self.trigger(name, params);
     });
   };

+ 15 - 1
src/js/select2/dropdown.js

@@ -34,7 +34,21 @@ define([
   };
 
   Dropdown.prototype.bind = function (container, $container) {
-    // Can be implemented in subclasses
+    container.on('select', function (params) {
+      self._onSelect(params);
+    });
+
+    container.on('unselect', function (params) {
+      self._onUnSelect(params);
+    });
+  };
+
+  Dropdown.prototype._onSelect = function () {
+    self.trigger('close');
+  };
+
+  Dropdown.prototype._onUnSelect = function () {
+    self.trigger('close');
   };
 
   return Dropdown;

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

@@ -281,11 +281,11 @@ define([
       var data = $highlighted.data('data');
 
       if ($highlighted.attr('aria-selected') == 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           data: data
         });
       } else {
-        self.trigger('selected', {
+        self.trigger('select', {
           data: data
         });
       }
@@ -403,7 +403,7 @@ define([
       var data = $this.data('data');
 
       if ($this.attr('aria-selected') === 'true') {
-        self.trigger('unselected', {
+        self.trigger('unselect', {
           originalEvent: evt,
           data: data
         });
@@ -411,7 +411,7 @@ define([
         return;
       }
 
-      self.trigger('selected', {
+      self.trigger('select', {
         originalEvent: evt,
         data: data
       });

+ 1 - 1
src/js/select2/selection/multiple.js

@@ -42,7 +42,7 @@ define([
 
       var data = $selection.data('data');
 
-      self.trigger('unselected', {
+      self.trigger('unselect', {
         originalEvent: evt,
         data: data
       });

+ 1 - 1
src/js/select2/selection/search.js

@@ -103,7 +103,7 @@ define([
   };
 
   Search.prototype.searchRemoveChoice = function (decorated, item) {
-    this.trigger('unselected', {
+    this.trigger('unselect', {
       data: item
     });
 

+ 74 - 0
tests/selection/placeholder-tests.js

@@ -0,0 +1,74 @@
+module('Selection containers - Placeholders');
+
+var Placeholder = require('select2/selection/placeholder');
+var SingleSelection = require('select2/selection/single');
+
+var $ = require('jquery');
+var Options = require('select2/options');
+var Utils = require('select2/utils');
+
+var SinglePlaceholder = Utils.Decorate(SingleSelection, Placeholder);
+
+var options = new Options({
+  placeholder: {
+    id: 'placeholder',
+    text: 'This is the placeholder'
+  }
+});
+
+test('normalizing placeholder ignores objects', function (assert) {
+  var selection = new SinglePlaceholder(
+    $('#qunit-fixture .single'),
+    options
+  );
+
+  var original = {
+    id: 'test',
+    text: 'testing'
+  };
+
+  var normalized = selection.normalizePlaceholder(original);
+
+  assert.equal(original, normalized);
+});
+
+test('normalizing placeholder gives object for string', function (assert) {
+  var selection = new SinglePlaceholder(
+    $('#qunit-fixture .single'),
+    options
+  );
+
+  var normalized = selection.normalizePlaceholder('placeholder');
+
+  assert.equal(normalized.id, '');
+  assert.equal(normalized.text, 'placeholder');
+});
+
+
+test('text is shown for placeholder option on single', function (assert) {
+  var selection = new SinglePlaceholder(
+    $('#qunit-fixture .single'),
+    options
+  );
+
+  var $selection = selection.render();
+
+  selection.update([{
+    id: 'placeholder'
+  }]);
+
+  assert.equal($selection.text(), 'This is the placeholder');
+});
+
+test('placeholder is shown when no options are selected', function (assert) {
+  var selection = new SinglePlaceholder(
+    $('#qunit-fixture .multiple'),
+    options
+  );
+
+  var $selection = selection.render();
+
+  selection.update([]);
+
+  assert.equal($selection.text(), 'This is the placeholder');
+});

+ 26 - 0
tests/selection/placeholder.html

@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+  <head>
+    <link rel="stylesheet" href="../vendor/qunit-1.14.0.css" type="text/css" />
+    <link rel="stylesheet" href="../../dist/css/select2.css" type="text/css" />
+  </head>
+  <body>
+    <div id="qunit"></div>
+    <div id="qunit-fixture">
+      <select class="single">
+        <option>One</option>
+      </select>
+
+      <select class="multiple" multiple="multiple">
+        <option>One</option>
+      </select>
+    </div>
+
+    <script src="../vendor/qunit-1.14.0.js" type="text/javascript"></script>
+    <script src="../../vendor/almond-0.2.9.js" type="text/javascript"></script>
+    <script src="../../vendor/jquery-2.1.0.js" type="text/javascript"></script>
+    <script src="../../dist/js/select2.amd.js" type="text/javascript"></script>
+
+    <script src="placeholder-tests.js" type="text/javascript"></script>
+  </body>
+</html>

Some files were not shown because too many files changed in this diff