瀏覽代碼

Added optgroup support

Kevin Brown 10 年之前
父節點
當前提交
acd469c658

+ 7 - 1
dist/css/select2.css

@@ -88,9 +88,15 @@
 .select2-container.select2-theme-default .dropdown .results {
   max-height: 200px;
   overflow-y: scroll; }
+  .select2-container.select2-theme-default .dropdown .results .options .option.group {
+    padding: 0; }
+    .select2-container.select2-theme-default .dropdown .results .options .option.group .group-label {
+      cursor: default;
+      display: block;
+      padding: 6px; }
   .select2-container.select2-theme-default .dropdown .results .options .option.selected {
     background-color: #ddd; }
-  .select2-container.select2-theme-default .dropdown .results .options .option.highlighted {
+  .select2-container.select2-theme-default .dropdown .results .options .option.highlightable.highlighted {
     background-color: #5897fb;
     color: white; }
 

文件差異過大導致無法顯示
+ 0 - 0
dist/css/select2.min.css


+ 92 - 14
dist/js/select2.amd.full.js

@@ -200,10 +200,39 @@ define('select2/results',[
 
   Results.prototype.option = function (data) {
     var $option = $(
-      '<li class="option"></li>'
+      '<li class="option highlightable selectable"></li>'
     );
 
-    $option.html(data.text);
+    if (data.children && data.children.length > 0) {
+      $option.addClass('group').removeClass('highlightable selectable');
+
+      var $label = $('<strong class="group-label"></strong>');
+      $label.html(data.text);
+
+      var $children = [];
+
+      for (var c = 0; c < data.children.length; c++) {
+        var child = data.children[c];
+
+        var $child = this.option(child);
+
+        $children.push($child);
+      }
+
+      var $childrenContainer = $('<ul class="options nested-options"></ul>');
+
+      $childrenContainer.append($children);
+
+      $option.append($label);
+      $option.append($childrenContainer);
+    } else {
+      $option.html(data.text);
+    }
+
+    if (data.disabled) {
+      $option.removeClass('selectable').addClass('disabled');
+    }
+
     $option.data('data', data);
 
     return $option;
@@ -225,7 +254,7 @@ define('select2/results',[
       self.setClasses();
     });
 
-    this.$results.on('mouseup', '.option', function (evt) {
+    this.$results.on('mouseup', '.option.selectable', function (evt) {
       var $this = $(this);
 
       var data = $this.data('data');
@@ -248,7 +277,7 @@ define('select2/results',[
       self.setClasses();
     });
 
-    this.$results.on('mouseenter', '.option', function (evt) {
+    this.$results.on('mouseenter', '.option.highlightable', function (evt) {
       self.$results.find('.option.highlighted').removeClass('highlighted');
       $(this).addClass('highlighted');
     });
@@ -540,13 +569,21 @@ define('select2/data/select',[
     var data = [];
     var self = this;
 
-    this.$element.find('option').each(function () {
+    var $options = this.$element.children();
+
+    $options.each(function () {
       var $option = $(this);
 
+      if (!$option.is('option') && !$option.is('optgroup')) {
+        return;
+      }
+
       var option = self.item($option);
 
-      if (self.matches(params, option)) {
-        data.push(option);
+      var matches = self.matches(params, option);
+
+      if (matches !== null) {
+        data.push(matches);
       }
     });
 
@@ -558,10 +595,32 @@ define('select2/data/select',[
 
     // If the data has already be generated, use it
     if (data == null) {
-      data = {
-        id: $option.val(),
-        text: $option.html()
-      };
+      if ($option.is('option')) {
+        data = {
+          id: $option.val(),
+          text: $option.html(),
+          disabled: $option.prop('disabled')
+        };
+      } else if ($option.is('optgroup')) {
+        data = {
+          id: -1,
+          text: $option.attr('label'),
+          children: []
+        };
+
+        var $children = $option.children('option');
+        var children = [];
+
+        for (var c = 0; c < $children.length; c++) {
+          var $child = $($children[c]);
+
+          var child = this.item($child);
+
+          children.push(child);
+        }
+
+        data.children = children;
+      }
 
       $option.data('data', data);
     }
@@ -570,15 +629,34 @@ define('select2/data/select',[
   };
 
   SelectAdapter.prototype.matches = function (params, data) {
+    var match = $.extend(true, {}, data);
+
+    if (data.children) {
+      for (var c = data.children.length - 1; c >= 0; c--) {
+        var child = data.children[c];
+
+        var matches = this.matches(params, child);
+
+        // If there wasn't a match, remove the object in the array
+        if (matches === null) {
+          match.children.splice(c, 1);
+        }
+      }
+
+      if (match.children.length > 0) {
+        return match;
+      }
+    }
+
     if ($.trim(params.term) === '') {
-      return true;
+      return match;
     }
 
     if (data.text.indexOf(params.term) > -1) {
-      return true;
+      return match;
     }
 
-    return false;
+    return null;
   };
 
   return SelectAdapter;

+ 92 - 14
dist/js/select2.amd.js

@@ -200,10 +200,39 @@ define('select2/results',[
 
   Results.prototype.option = function (data) {
     var $option = $(
-      '<li class="option"></li>'
+      '<li class="option highlightable selectable"></li>'
     );
 
-    $option.html(data.text);
+    if (data.children && data.children.length > 0) {
+      $option.addClass('group').removeClass('highlightable selectable');
+
+      var $label = $('<strong class="group-label"></strong>');
+      $label.html(data.text);
+
+      var $children = [];
+
+      for (var c = 0; c < data.children.length; c++) {
+        var child = data.children[c];
+
+        var $child = this.option(child);
+
+        $children.push($child);
+      }
+
+      var $childrenContainer = $('<ul class="options nested-options"></ul>');
+
+      $childrenContainer.append($children);
+
+      $option.append($label);
+      $option.append($childrenContainer);
+    } else {
+      $option.html(data.text);
+    }
+
+    if (data.disabled) {
+      $option.removeClass('selectable').addClass('disabled');
+    }
+
     $option.data('data', data);
 
     return $option;
@@ -225,7 +254,7 @@ define('select2/results',[
       self.setClasses();
     });
 
-    this.$results.on('mouseup', '.option', function (evt) {
+    this.$results.on('mouseup', '.option.selectable', function (evt) {
       var $this = $(this);
 
       var data = $this.data('data');
@@ -248,7 +277,7 @@ define('select2/results',[
       self.setClasses();
     });
 
-    this.$results.on('mouseenter', '.option', function (evt) {
+    this.$results.on('mouseenter', '.option.highlightable', function (evt) {
       self.$results.find('.option.highlighted').removeClass('highlighted');
       $(this).addClass('highlighted');
     });
@@ -540,13 +569,21 @@ define('select2/data/select',[
     var data = [];
     var self = this;
 
-    this.$element.find('option').each(function () {
+    var $options = this.$element.children();
+
+    $options.each(function () {
       var $option = $(this);
 
+      if (!$option.is('option') && !$option.is('optgroup')) {
+        return;
+      }
+
       var option = self.item($option);
 
-      if (self.matches(params, option)) {
-        data.push(option);
+      var matches = self.matches(params, option);
+
+      if (matches !== null) {
+        data.push(matches);
       }
     });
 
@@ -558,10 +595,32 @@ define('select2/data/select',[
 
     // If the data has already be generated, use it
     if (data == null) {
-      data = {
-        id: $option.val(),
-        text: $option.html()
-      };
+      if ($option.is('option')) {
+        data = {
+          id: $option.val(),
+          text: $option.html(),
+          disabled: $option.prop('disabled')
+        };
+      } else if ($option.is('optgroup')) {
+        data = {
+          id: -1,
+          text: $option.attr('label'),
+          children: []
+        };
+
+        var $children = $option.children('option');
+        var children = [];
+
+        for (var c = 0; c < $children.length; c++) {
+          var $child = $($children[c]);
+
+          var child = this.item($child);
+
+          children.push(child);
+        }
+
+        data.children = children;
+      }
 
       $option.data('data', data);
     }
@@ -570,15 +629,34 @@ define('select2/data/select',[
   };
 
   SelectAdapter.prototype.matches = function (params, data) {
+    var match = $.extend(true, {}, data);
+
+    if (data.children) {
+      for (var c = data.children.length - 1; c >= 0; c--) {
+        var child = data.children[c];
+
+        var matches = this.matches(params, child);
+
+        // If there wasn't a match, remove the object in the array
+        if (matches === null) {
+          match.children.splice(c, 1);
+        }
+      }
+
+      if (match.children.length > 0) {
+        return match;
+      }
+    }
+
     if ($.trim(params.term) === '') {
-      return true;
+      return match;
     }
 
     if (data.text.indexOf(params.term) > -1) {
-      return true;
+      return match;
     }
 
-    return false;
+    return null;
   };
 
   return SelectAdapter;

+ 92 - 14
dist/js/select2.full.js

@@ -9738,10 +9738,39 @@ define('select2/results',[
 
   Results.prototype.option = function (data) {
     var $option = $(
-      '<li class="option"></li>'
+      '<li class="option highlightable selectable"></li>'
     );
 
-    $option.html(data.text);
+    if (data.children && data.children.length > 0) {
+      $option.addClass('group').removeClass('highlightable selectable');
+
+      var $label = $('<strong class="group-label"></strong>');
+      $label.html(data.text);
+
+      var $children = [];
+
+      for (var c = 0; c < data.children.length; c++) {
+        var child = data.children[c];
+
+        var $child = this.option(child);
+
+        $children.push($child);
+      }
+
+      var $childrenContainer = $('<ul class="options nested-options"></ul>');
+
+      $childrenContainer.append($children);
+
+      $option.append($label);
+      $option.append($childrenContainer);
+    } else {
+      $option.html(data.text);
+    }
+
+    if (data.disabled) {
+      $option.removeClass('selectable').addClass('disabled');
+    }
+
     $option.data('data', data);
 
     return $option;
@@ -9763,7 +9792,7 @@ define('select2/results',[
       self.setClasses();
     });
 
-    this.$results.on('mouseup', '.option', function (evt) {
+    this.$results.on('mouseup', '.option.selectable', function (evt) {
       var $this = $(this);
 
       var data = $this.data('data');
@@ -9786,7 +9815,7 @@ define('select2/results',[
       self.setClasses();
     });
 
-    this.$results.on('mouseenter', '.option', function (evt) {
+    this.$results.on('mouseenter', '.option.highlightable', function (evt) {
       self.$results.find('.option.highlighted').removeClass('highlighted');
       $(this).addClass('highlighted');
     });
@@ -10078,13 +10107,21 @@ define('select2/data/select',[
     var data = [];
     var self = this;
 
-    this.$element.find('option').each(function () {
+    var $options = this.$element.children();
+
+    $options.each(function () {
       var $option = $(this);
 
+      if (!$option.is('option') && !$option.is('optgroup')) {
+        return;
+      }
+
       var option = self.item($option);
 
-      if (self.matches(params, option)) {
-        data.push(option);
+      var matches = self.matches(params, option);
+
+      if (matches !== null) {
+        data.push(matches);
       }
     });
 
@@ -10096,10 +10133,32 @@ define('select2/data/select',[
 
     // If the data has already be generated, use it
     if (data == null) {
-      data = {
-        id: $option.val(),
-        text: $option.html()
-      };
+      if ($option.is('option')) {
+        data = {
+          id: $option.val(),
+          text: $option.html(),
+          disabled: $option.prop('disabled')
+        };
+      } else if ($option.is('optgroup')) {
+        data = {
+          id: -1,
+          text: $option.attr('label'),
+          children: []
+        };
+
+        var $children = $option.children('option');
+        var children = [];
+
+        for (var c = 0; c < $children.length; c++) {
+          var $child = $($children[c]);
+
+          var child = this.item($child);
+
+          children.push(child);
+        }
+
+        data.children = children;
+      }
 
       $option.data('data', data);
     }
@@ -10108,15 +10167,34 @@ define('select2/data/select',[
   };
 
   SelectAdapter.prototype.matches = function (params, data) {
+    var match = $.extend(true, {}, data);
+
+    if (data.children) {
+      for (var c = data.children.length - 1; c >= 0; c--) {
+        var child = data.children[c];
+
+        var matches = this.matches(params, child);
+
+        // If there wasn't a match, remove the object in the array
+        if (matches === null) {
+          match.children.splice(c, 1);
+        }
+      }
+
+      if (match.children.length > 0) {
+        return match;
+      }
+    }
+
     if ($.trim(params.term) === '') {
-      return true;
+      return match;
     }
 
     if (data.text.indexOf(params.term) > -1) {
-      return true;
+      return match;
     }
 
-    return false;
+    return null;
   };
 
   return SelectAdapter;

文件差異過大導致無法顯示
+ 0 - 0
dist/js/select2.full.min.js


+ 92 - 14
dist/js/select2.js

@@ -629,10 +629,39 @@ define('select2/results',[
 
   Results.prototype.option = function (data) {
     var $option = $(
-      '<li class="option"></li>'
+      '<li class="option highlightable selectable"></li>'
     );
 
-    $option.html(data.text);
+    if (data.children && data.children.length > 0) {
+      $option.addClass('group').removeClass('highlightable selectable');
+
+      var $label = $('<strong class="group-label"></strong>');
+      $label.html(data.text);
+
+      var $children = [];
+
+      for (var c = 0; c < data.children.length; c++) {
+        var child = data.children[c];
+
+        var $child = this.option(child);
+
+        $children.push($child);
+      }
+
+      var $childrenContainer = $('<ul class="options nested-options"></ul>');
+
+      $childrenContainer.append($children);
+
+      $option.append($label);
+      $option.append($childrenContainer);
+    } else {
+      $option.html(data.text);
+    }
+
+    if (data.disabled) {
+      $option.removeClass('selectable').addClass('disabled');
+    }
+
     $option.data('data', data);
 
     return $option;
@@ -654,7 +683,7 @@ define('select2/results',[
       self.setClasses();
     });
 
-    this.$results.on('mouseup', '.option', function (evt) {
+    this.$results.on('mouseup', '.option.selectable', function (evt) {
       var $this = $(this);
 
       var data = $this.data('data');
@@ -677,7 +706,7 @@ define('select2/results',[
       self.setClasses();
     });
 
-    this.$results.on('mouseenter', '.option', function (evt) {
+    this.$results.on('mouseenter', '.option.highlightable', function (evt) {
       self.$results.find('.option.highlighted').removeClass('highlighted');
       $(this).addClass('highlighted');
     });
@@ -969,13 +998,21 @@ define('select2/data/select',[
     var data = [];
     var self = this;
 
-    this.$element.find('option').each(function () {
+    var $options = this.$element.children();
+
+    $options.each(function () {
       var $option = $(this);
 
+      if (!$option.is('option') && !$option.is('optgroup')) {
+        return;
+      }
+
       var option = self.item($option);
 
-      if (self.matches(params, option)) {
-        data.push(option);
+      var matches = self.matches(params, option);
+
+      if (matches !== null) {
+        data.push(matches);
       }
     });
 
@@ -987,10 +1024,32 @@ define('select2/data/select',[
 
     // If the data has already be generated, use it
     if (data == null) {
-      data = {
-        id: $option.val(),
-        text: $option.html()
-      };
+      if ($option.is('option')) {
+        data = {
+          id: $option.val(),
+          text: $option.html(),
+          disabled: $option.prop('disabled')
+        };
+      } else if ($option.is('optgroup')) {
+        data = {
+          id: -1,
+          text: $option.attr('label'),
+          children: []
+        };
+
+        var $children = $option.children('option');
+        var children = [];
+
+        for (var c = 0; c < $children.length; c++) {
+          var $child = $($children[c]);
+
+          var child = this.item($child);
+
+          children.push(child);
+        }
+
+        data.children = children;
+      }
 
       $option.data('data', data);
     }
@@ -999,15 +1058,34 @@ define('select2/data/select',[
   };
 
   SelectAdapter.prototype.matches = function (params, data) {
+    var match = $.extend(true, {}, data);
+
+    if (data.children) {
+      for (var c = data.children.length - 1; c >= 0; c--) {
+        var child = data.children[c];
+
+        var matches = this.matches(params, child);
+
+        // If there wasn't a match, remove the object in the array
+        if (matches === null) {
+          match.children.splice(c, 1);
+        }
+      }
+
+      if (match.children.length > 0) {
+        return match;
+      }
+    }
+
     if ($.trim(params.term) === '') {
-      return true;
+      return match;
     }
 
     if (data.text.indexOf(params.term) > -1) {
-      return true;
+      return match;
     }
 
-    return false;
+    return null;
   };
 
   return SelectAdapter;

文件差異過大導致無法顯示
+ 0 - 0
dist/js/select2.min.js


+ 1 - 1
docs/_includes/head.html

@@ -6,7 +6,7 @@
   {{ page.title }}
 </title>
 
-<script type="text/javascript" src="dist/js/select2.full.min.js"></script>
+<script type="text/javascript" src="dist/js/select2.full.js"></script>
 <script type="text/javascript" src="vendor/js/bootstrap.min.js"></script>
 <script type="text/javascript" src="vendor/js/prettify.min.js"></script>
 

+ 59 - 10
src/js/select2/data/select.js

@@ -94,13 +94,21 @@ define([
     var data = [];
     var self = this;
 
-    this.$element.find('option').each(function () {
+    var $options = this.$element.children();
+
+    $options.each(function () {
       var $option = $(this);
 
+      if (!$option.is('option') && !$option.is('optgroup')) {
+        return;
+      }
+
       var option = self.item($option);
 
-      if (self.matches(params, option)) {
-        data.push(option);
+      var matches = self.matches(params, option);
+
+      if (matches !== null) {
+        data.push(matches);
       }
     });
 
@@ -112,10 +120,32 @@ define([
 
     // If the data has already be generated, use it
     if (data == null) {
-      data = {
-        id: $option.val(),
-        text: $option.html()
-      };
+      if ($option.is('option')) {
+        data = {
+          id: $option.val(),
+          text: $option.html(),
+          disabled: $option.prop('disabled')
+        };
+      } else if ($option.is('optgroup')) {
+        data = {
+          id: -1,
+          text: $option.attr('label'),
+          children: []
+        };
+
+        var $children = $option.children('option');
+        var children = [];
+
+        for (var c = 0; c < $children.length; c++) {
+          var $child = $($children[c]);
+
+          var child = this.item($child);
+
+          children.push(child);
+        }
+
+        data.children = children;
+      }
 
       $option.data('data', data);
     }
@@ -124,15 +154,34 @@ define([
   };
 
   SelectAdapter.prototype.matches = function (params, data) {
+    var match = $.extend(true, {}, data);
+
+    if (data.children) {
+      for (var c = data.children.length - 1; c >= 0; c--) {
+        var child = data.children[c];
+
+        var matches = this.matches(params, child);
+
+        // If there wasn't a match, remove the object in the array
+        if (matches === null) {
+          match.children.splice(c, 1);
+        }
+      }
+
+      if (match.children.length > 0) {
+        return match;
+      }
+    }
+
     if ($.trim(params.term) === '') {
-      return true;
+      return match;
     }
 
     if (data.text.indexOf(params.term) > -1) {
-      return true;
+      return match;
     }
 
-    return false;
+    return null;
   };
 
   return SelectAdapter;

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

@@ -61,10 +61,39 @@ define([
 
   Results.prototype.option = function (data) {
     var $option = $(
-      '<li class="option"></li>'
+      '<li class="option highlightable selectable"></li>'
     );
 
-    $option.html(data.text);
+    if (data.children && data.children.length > 0) {
+      $option.addClass('group').removeClass('highlightable selectable');
+
+      var $label = $('<strong class="group-label"></strong>');
+      $label.html(data.text);
+
+      var $children = [];
+
+      for (var c = 0; c < data.children.length; c++) {
+        var child = data.children[c];
+
+        var $child = this.option(child);
+
+        $children.push($child);
+      }
+
+      var $childrenContainer = $('<ul class="options nested-options"></ul>');
+
+      $childrenContainer.append($children);
+
+      $option.append($label);
+      $option.append($childrenContainer);
+    } else {
+      $option.html(data.text);
+    }
+
+    if (data.disabled) {
+      $option.removeClass('selectable').addClass('disabled');
+    }
+
     $option.data('data', data);
 
     return $option;
@@ -86,7 +115,7 @@ define([
       self.setClasses();
     });
 
-    this.$results.on('mouseup', '.option', function (evt) {
+    this.$results.on('mouseup', '.option.selectable', function (evt) {
       var $this = $(this);
 
       var data = $this.data('data');
@@ -109,7 +138,7 @@ define([
       self.setClasses();
     });
 
-    this.$results.on('mouseenter', '.option', function (evt) {
+    this.$results.on('mouseenter', '.option.highlightable', function (evt) {
       self.$results.find('.option.highlighted').removeClass('highlighted');
       $(this).addClass('highlighted');
     });

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

@@ -55,11 +55,21 @@
 
       .options {
         .option {
+          &.group {
+            padding: 0;
+
+            .group-label {
+              cursor: default;
+              display: block;
+              padding: 6px;
+            }
+          }
+
           &.selected {
             background-color: #ddd;
           }
 
-          &.highlighted {
+          &.highlightable.highlighted {
             background-color: #5897fb;
             color: white;
           }

部分文件因文件數量過多而無法顯示