Ver código fonte

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 anos atrás
pai
commit
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 = [];
 

Diferenças do arquivo suprimidas por serem muito extensas
+ 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 = [];
 

Diferenças do arquivo suprimidas por serem muito extensas
+ 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>

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