Просмотр исходного кода

Support duplicate options

Now that the data objects have the `element` property, we can test
to make sure it's a DOM element and then use it for selecting the
option. This allows us to select multiple options with the same id,
as well as handle cases where that is already happening.

You cannot use `$e.val()` to select two options with the same id,
as jQuery will reject it, but you can set the second option to
`.selected = true`, which is supported.
Kevin Brown 10 лет назад
Родитель
Сommit
0bc73941fe

+ 17 - 0
dist/js/select2.amd.full.js

@@ -2153,6 +2153,15 @@ define('select2/data/select',[
   SelectAdapter.prototype.select = function (data) {
     var self = this;
 
+    // If data.element is a DOM nose, use it instead
+    if ($(data.element).is('option')) {
+      data.element.selected = true;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     if (this.$element.prop('multiple')) {
       this.current(function (currentData) {
         var val = [];
@@ -2187,6 +2196,14 @@ define('select2/data/select',[
       return;
     }
 
+    if ($(data.element).is('option')) {
+      data.element.selected = false;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     this.current(function (currentData) {
       var val = [];
 

+ 17 - 0
dist/js/select2.amd.js

@@ -2153,6 +2153,15 @@ define('select2/data/select',[
   SelectAdapter.prototype.select = function (data) {
     var self = this;
 
+    // If data.element is a DOM nose, use it instead
+    if ($(data.element).is('option')) {
+      data.element.selected = true;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     if (this.$element.prop('multiple')) {
       this.current(function (currentData) {
         var val = [];
@@ -2187,6 +2196,14 @@ define('select2/data/select',[
       return;
     }
 
+    if ($(data.element).is('option')) {
+      data.element.selected = false;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     this.current(function (currentData) {
       var val = [];
 

+ 17 - 0
dist/js/select2.full.js

@@ -11688,6 +11688,15 @@ define('select2/data/select',[
   SelectAdapter.prototype.select = function (data) {
     var self = this;
 
+    // If data.element is a DOM nose, use it instead
+    if ($(data.element).is('option')) {
+      data.element.selected = true;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     if (this.$element.prop('multiple')) {
       this.current(function (currentData) {
         var val = [];
@@ -11722,6 +11731,14 @@ define('select2/data/select',[
       return;
     }
 
+    if ($(data.element).is('option')) {
+      data.element.selected = false;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     this.current(function (currentData) {
       var val = [];
 

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/js/select2.full.min.js


+ 17 - 0
dist/js/select2.js

@@ -2581,6 +2581,15 @@ define('select2/data/select',[
   SelectAdapter.prototype.select = function (data) {
     var self = this;
 
+    // If data.element is a DOM nose, use it instead
+    if ($(data.element).is('option')) {
+      data.element.selected = true;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     if (this.$element.prop('multiple')) {
       this.current(function (currentData) {
         var val = [];
@@ -2615,6 +2624,14 @@ define('select2/data/select',[
       return;
     }
 
+    if ($(data.element).is('option')) {
+      data.element.selected = false;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     this.current(function (currentData) {
       var val = [];
 

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/js/select2.min.js


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

@@ -30,6 +30,15 @@ define([
   SelectAdapter.prototype.select = function (data) {
     var self = this;
 
+    // If data.element is a DOM nose, use it instead
+    if ($(data.element).is('option')) {
+      data.element.selected = true;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     if (this.$element.prop('multiple')) {
       this.current(function (currentData) {
         var val = [];
@@ -64,6 +73,14 @@ define([
       return;
     }
 
+    if ($(data.element).is('option')) {
+      data.element.selected = false;
+
+      this.$element.trigger('change');
+
+      return;
+    }
+
     this.current(function (currentData) {
       var val = [];
 

+ 181 - 0
tests/data/select-tests.js

@@ -154,6 +154,158 @@ test('multiple adds to the old value', function (assert) {
   assert.deepEqual($select.val(), ['default', '2']);
 });
 
+test('duplicates - single - same id on select triggers change',
+  function (assert) {
+  var $select = $('#qunit-fixture .duplicates');
+
+  var data = new SelectData($select, data);
+  var second = $('#qunit-fixture .duplicates option')[2];
+
+  var changeTriggered = false;
+
+  assert.equal($select.val(), 'one');
+
+  $select.on('change', function () {
+    changeTriggered = true;
+  });
+
+  data.select({
+    id: 'one',
+    text: 'Uno',
+    element: second
+  });
+
+  assert.equal(
+    $select.val(),
+    'one',
+    'The value never changed'
+  );
+
+  assert.ok(
+    changeTriggered,
+    'The change event should be triggered'
+  );
+
+  assert.ok(
+    second.selected,
+    'The second duplicate is selected, not the first'
+  );
+});
+
+test('duplicates - single - different id on select triggers change',
+  function (assert) {
+  var $select = $('#qunit-fixture .duplicates');
+
+  var data = new SelectData($select, data);
+  var second = $('#qunit-fixture .duplicates option')[2];
+
+  var changeTriggered = false;
+
+  $select.val('two');
+
+  $select.on('change', function () {
+    changeTriggered = true;
+  });
+
+  data.select({
+    id: 'one',
+    text: 'Uno',
+    element: second
+  });
+
+  assert.equal(
+    $select.val(),
+    'one',
+    'The value changed to the duplicate id'
+  );
+
+  assert.ok(
+    changeTriggered,
+    'The change event should be triggered'
+  );
+
+  assert.ok(
+    second.selected,
+    'The second duplicate is selected, not the first'
+  );
+});
+
+test('duplicates - multiple - same id on select triggers change',
+function (assert) {
+  var $select = $('#qunit-fixture .duplicates-multi');
+
+  var data = new SelectData($select, data);
+  var second = $('#qunit-fixture .duplicates-multi option')[2];
+
+  var changeTriggered = false;
+
+  $select.val(['one']);
+
+  $select.on('change', function () {
+    changeTriggered = true;
+  });
+
+  data.select({
+    id: 'one',
+    text: 'Uno',
+    element: second
+  });
+
+  assert.deepEqual(
+    $select.val(),
+    ['one', 'one'],
+    'The value now has duplicates'
+  );
+
+  assert.ok(
+    changeTriggered,
+    'The change event should be triggered'
+  );
+
+  assert.ok(
+    second.selected,
+    'The second duplicate is selected, not the first'
+  );
+});
+
+test('duplicates - multiple - different id on select triggers change',
+function (assert) {
+  var $select = $('#qunit-fixture .duplicates-multi');
+
+  var data = new SelectData($select, data);
+  var second = $('#qunit-fixture .duplicates-multi option')[2];
+
+  var changeTriggered = false;
+
+  $select.val(['two']);
+
+  $select.on('change', function () {
+    changeTriggered = true;
+  });
+
+  data.select({
+    id: 'one',
+    text: 'Uno',
+    element: second
+  });
+
+  assert.deepEqual(
+    $select.val(),
+    ['two', 'one'],
+    'The value has the new id'
+  );
+
+  assert.ok(
+    changeTriggered,
+    'The change event should be triggered'
+  );
+
+  assert.ok(
+    second.selected,
+    'The second duplicate is selected, not the first'
+  );
+});
+
 module('Data adapter - Select - query');
 
 test('all options are returned with no term', function (assert) {
@@ -258,3 +410,32 @@ test('empty optgroups are still shown when queried', function (assert) {
     );
   });
 });
+
+test('multiple options with the same value are returned', function (assert) {
+  var $select = $('#qunit-fixture .duplicates');
+
+  var data = new SelectData($select, options);
+
+  data.query({}, function (data) {
+    assert.equal(
+      data.length,
+      3,
+      'The duplicate option should still be returned when queried'
+    );
+
+    var first = data[0];
+    var duplicate = data[2];
+
+    assert.equal(
+      first.id,
+      duplicate.id,
+      'The duplicates should have the same id'
+    );
+
+    assert.notEqual(
+      first.text,
+      duplicate.text,
+      'The duplicates do not have the same text'
+    );
+  });
+});

+ 12 - 0
tests/data/select.html

@@ -26,6 +26,18 @@
         </optgroup>
         <optgroup label="Empty"></optgroup>
       </select>
+
+      <select class="duplicates">
+        <option value="one">One</option>
+        <option value="two">Two</option>
+        <option value="one">Uno</option>
+      </select>
+
+      <select class="duplicates-multi" multiple="multiple">
+        <option value="one">One</option>
+        <option value="two">Two</option>
+        <option value="one">Uno</option>
+      </select>
     </div>
 
     <script src="../vendor/qunit-1.14.0.js" type="text/javascript"></script>

Некоторые файлы не были показаны из-за большого количества измененных файлов