浏览代码

checkbox均支持shift多选

xiedanbo 9 年之前
父节点
当前提交
93739939c5

+ 52 - 0
rrd/static/js/angular-multi-check.js

@@ -0,0 +1,52 @@
+/*
+ * angular-multi-check
+ * http://schlogen.github.io/angular-multi-check/
+
+ * Version: 1.0 - 2014-24-11
+ * License: Apache
+ */
+angular.module('angular-multi-check', [])
+    .directive('multiCheckGroup', function() {
+        return {
+            scope: {},
+            controller: function($scope) {
+                this.getElements = function() {
+                    var dataMultiCheck = Array.prototype.slice.call($scope.element[0].querySelectorAll('[data-multi-check]'), 0);
+                    var multiCheck = Array.prototype.slice.call($scope.element[0].querySelectorAll('[multi-check]'), 0);
+
+                    return multiCheck.concat(dataMultiCheck);
+                };
+                this.lastChecked = null;
+            },
+            link: function(scope, element) {
+                scope.element = element;
+            }
+        };
+    })
+    .directive('multiCheck', function() {
+        return {
+            require: ['^ngModel', '^multiCheckGroup'],
+            restrict: 'A',
+            link: function(scope, el, attrs, controllers) {
+                var groupCtrl = controllers[1];
+
+                el.bind('click', function(event) {
+                    var last = groupCtrl.lastChecked;
+                    if (last && event.shiftKey) {
+                        var chkboxes = groupCtrl.getElements(),
+                            start = chkboxes.indexOf(event.target),
+                            end = chkboxes.indexOf(last),
+                            checked = last.checked;
+
+                        angular.forEach(chkboxes.slice(Math.min(start, end), Math.max(start, end) + 1), function(box) {
+                            var model = angular.element(box).data('$ngModelController');
+                            model.$setViewValue(checked);
+                            model.$render();
+                        });
+                    }
+                    groupCtrl.lastChecked = event.target;
+                });
+
+            }
+        };
+    });

+ 1 - 1
rrd/static/js/big_ng.js

@@ -1,5 +1,5 @@
 
-angular.module('app', ['app.util'])
+angular.module('app', ['app.util','angular-multi-check'])
 .config(function($interpolateProvider) {
     $interpolateProvider.startSymbol('[[');
     $interpolateProvider.endSymbol(']]');

+ 196 - 0
rrd/static/js/jquery.shiftcheckbox.js

@@ -0,0 +1,196 @@
+/* ShiftCheckbox jQuery plugin
+ *
+ * Copyright (C) 2011-2012 James Nylen
+ *
+ * Released under MIT license
+ * For details see:
+ * https://github.com/nylen/shiftcheckbox
+ *
+ * Requires jQuery v1.7 or higher.
+ */
+
+(function($) {
+  var ns = '.shiftcheckbox';
+
+  $.fn.shiftcheckbox = function(opts) {
+    opts = $.extend({
+      checkboxSelector : null,
+      selectAll        : null,
+      onChange         : null,
+      ignoreClick      : null
+    }, opts);
+
+    if (typeof opts.onChange != 'function') {
+      opts.onChange = function(checked) { };
+    }
+
+    $.fn.scb_changeChecked = function(opts, checked) {
+      this.prop('checked', checked);
+      opts.onChange.call(this, checked);
+      return this;
+    }
+
+    var $containers,
+        $checkboxes,
+        $containersSelectAll,
+        $checkboxesSelectAll,
+        $otherSelectAll,
+        $containersAll,
+        $checkboxesAll;
+
+    if (opts.selectAll) {
+      // We need to set up a "select all" control
+      $containersSelectAll = $(opts.selectAll);
+      if ($containersSelectAll && !$containersSelectAll.length) {
+        $containersSelectAll = false;
+      }
+    }
+
+    if ($containersSelectAll) {
+      $checkboxesSelectAll = $containersSelectAll
+        .filter(':checkbox')
+        .add($containersSelectAll.find(':checkbox'));
+
+      $containersSelectAll = $containersSelectAll.not(':checkbox');
+      $otherSelectAll = $containersSelectAll.filter(function() {
+        return !$(this).find($checkboxesSelectAll).length;
+      });
+      $containersSelectAll = $containersSelectAll.filter(function() {
+        return !!$(this).find($checkboxesSelectAll).length;
+      }).each(function() {
+        $(this).data('childCheckbox', $(this).find($checkboxesSelectAll)[0]);
+      });
+    }
+
+    if (opts.checkboxSelector) {
+
+      // checkboxSelector means that the elements we need to attach handlers to
+      // ($containers) are not actually checkboxes but contain them instead
+
+      $containersAll = this.filter(function() {
+        return !!$(this).find(opts.checkboxSelector).filter(':checkbox').length;
+      }).each(function() {
+        $(this).data('childCheckbox', $(this).find(opts.checkboxSelector).filter(':checkbox')[0]);
+      }).add($containersSelectAll);
+
+      $checkboxesAll = $containersAll.map(function() {
+        return $(this).data('childCheckbox');
+      });
+
+    } else {
+
+      $checkboxesAll = this.filter(':checkbox');
+
+    }
+
+    if ($checkboxesSelectAll && !$checkboxesSelectAll.length) {
+      $checkboxesSelectAll = false;
+    } else {
+      $checkboxesAll = $checkboxesAll.add($checkboxesSelectAll);
+    }
+
+    if ($otherSelectAll && !$otherSelectAll.length) {
+      $otherSelectAll = false;
+    }
+
+    if ($containersAll) {
+      $containers = $containersAll.not($containersSelectAll);
+    }
+    $checkboxes = $checkboxesAll.not($checkboxesSelectAll);
+
+    if (!$checkboxes.length) {
+      return;
+    }
+
+    var lastIndex = -1;
+
+    var checkboxClicked = function(e) {
+      var checked = !!$(this).prop('checked');
+
+      var curIndex = $checkboxes.index(this);
+      if (curIndex < 0) {
+        if ($checkboxesSelectAll.filter(this).length) {
+          $checkboxesAll.scb_changeChecked(opts, checked);
+        }
+        return;
+      }
+
+      if (e.shiftKey && lastIndex != -1) {
+        var di = (curIndex > lastIndex ? 1 : -1);
+        for (var i = lastIndex; i != curIndex; i += di) {
+          $checkboxes.eq(i).scb_changeChecked(opts, checked);
+        }
+      }
+
+      if ($checkboxesSelectAll) {
+        if (checked && !$checkboxes.not(':checked').length) {
+          $checkboxesSelectAll.scb_changeChecked(opts, true);
+        } else if (!checked) {
+          $checkboxesSelectAll.scb_changeChecked(opts, false);
+        }
+      }
+
+      lastIndex = curIndex;
+    };
+
+    if ($checkboxesSelectAll) {
+      $checkboxesSelectAll
+        .prop('checked', !$checkboxes.not(':checked').length)
+        .filter(function() {
+          return !$containersAll.find(this).length;
+        }).on('click' + ns, checkboxClicked);
+    }
+
+    if ($otherSelectAll) {
+      $otherSelectAll.on('click' + ns, function() {
+        var checked;
+        if ($checkboxesSelectAll) {
+          checked = !!$checkboxesSelectAll.eq(0).prop('checked');
+        } else {
+          checked = !!$checkboxes.eq(0).prop('checked');
+        }
+        $checkboxesAll.scb_changeChecked(opts, !checked);
+      });
+    }
+
+    if (opts.checkboxSelector) {
+      $containersAll.on('click' + ns, function(e) {
+        if ($(e.target).closest(opts.ignoreClick).length) {
+          return;
+        }
+        var $checkbox = $($(this).data('childCheckbox'));
+        $checkbox.not(e.target).each(function() {
+          var checked = !$checkbox.prop('checked');
+          $(this).scb_changeChecked(opts, checked);
+        });
+
+        $checkbox[0].focus();
+        checkboxClicked.call($checkbox, e);
+
+        // If the user clicked on a label inside the row that points to the
+        // current row's checkbox, cancel the event.
+        var $label = $(e.target).closest('label');
+        var labelFor = $label.attr('for');
+        if (labelFor && labelFor == $checkbox.attr('id')) {
+          if ($label.find($checkbox).length) {
+            // Special case:  The label contains the checkbox.
+            if ($checkbox[0] != e.target) {
+              return false;
+            }
+          } else {
+            return false;
+          }
+        }
+      }).on('mousedown' + ns, function(e) {
+        if (e.shiftKey) {
+          // Prevent selecting text by Shift+click
+          return false;
+        }
+      });
+    } else {
+      $checkboxes.on('click' + ns, checkboxClicked);
+    }
+
+    return this;
+  };
+})(jQuery);

+ 4 - 2
rrd/static/js/xperf.js

@@ -19,10 +19,11 @@ function fn_list_endpoints()
                 for (var hidx in hosts) {
                     var h = hosts[hidx];
                     var line_html = '<tr>'
-                    + '<td><input type="checkbox" data-fullname="'+ h +'"></input></td>'
+                    + '<td><input type="checkbox" class="input shiftCheckbox" data-fullname="'+ h +'"></input></td>'
                     + '<td>' + h + '</td>'
                     + '</tr>';
                     tbody_hosts.append($(line_html));
+                    tbody_hosts.find('.shiftCheckbox').shiftcheckbox();
                 }
                 fn_check_all_hosts();
     }).error(function(req, ret, errorThrown){
@@ -65,12 +66,13 @@ function fn_list_counters(){
                         display_counter_type = "原始值";
                     }
                     var line_html = '<tr>'
-                    + '<td><input type="checkbox" data-fullkey="'+c[0]+'"></input></td>'
+                    + '<td><input type="checkbox" class="input shiftCheckbox" data-fullkey="'+c[0]+'"></input></td>'
                     + '<td><a href="javascript:void(0);" onclick="fn_show_chart(\'' + c[0] + '\')" >' + c[0] + '</a></td>'
                     + '<td>'+ display_counter_type +'</td>'
                     + '<td>'+ c[2] +'s</td>'
                     + '</tr>'
                     tbody_items.append($(line_html));
+                    tbody_items.find('.shiftCheckbox').shiftcheckbox();
                 }
             }else{
                 alert("搜索失败:" + ret.msg);

+ 3 - 2
rrd/templates/chart/big_ng.html

@@ -33,6 +33,7 @@
 <script src="{{url_for('static', filename='js/underscore.js')}}"></script>
 <script src="/static/js/util_ng.js?_v=0.0.4"></script>
 <script src="/static/js/big_ng.js?_v=0.0.4"></script>
+<script src="/static/js/angular-multi-check.js"></script>
 {%endblock%}
 
 {%block body_head%}
@@ -118,9 +119,9 @@
                                             type="search" placeholder="输入字符过滤, 回车刷新..">
                                     </div>
                                 </div>
-                                <ul class="list-unstyled" style="font-family: 'verdana', 'Microsoft YaHei', 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono';">
+                                <ul multi-check-group class="list-unstyled" style="font-family: 'verdana', 'Microsoft YaHei', 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono';">
                                     <li ng-repeat="s in vm.data | filter: { label:vm.query }">
-                                        <input id="" type="checkbox" style="margin-right:5px;" ng-model="s.check" value="[[ s.label ]]">[[ s.label ]]
+                                        <input id="" type="checkbox" style="margin-right:5px;" multi-check ng-model="s.check" value="[[ s.label ]]">[[ s.label ]]
                                     </li>
                                 </ul>
                             </div>

+ 9 - 5
rrd/templates/index.html

@@ -6,10 +6,14 @@
 {% block more_head %}
 {{super()}}
 
+<script src="/static/js/jquery.shiftcheckbox.js" type= "text/javascript" ></script>
 <script src="/static/js/xperf.js?_v=0.1.0"></script>
 <script>
 
         $(function(){
+            $(document).ready (function() {
+                $('.shiftCheckbox').shiftcheckbox();
+            });
             $("#check_all_endpoints").bind("click", fn_check_all_hosts);
             $("#check_all_counters").bind("click", fn_check_all_items);
             $("#endpoint-search").keydown(function(event){
@@ -97,7 +101,7 @@
                             </form>
                             <form class="form-inline" role="form">
                                 <div class="form-group">
-                                    <button type="button" id="btn-search-endpoints" class="btn btn-default btn-sm" onclick="fn_list_endpoints();return false;">全局搜索</button>
+                                    <button type="button" id="btn-search-endpoints" class="btn btn-default btn-sm btn-success" onclick="fn_list_endpoints();return false;">全局搜索</button>
                                     <select class="form-control input-sm" id="endpoint-limit" onchange="fn_list_endpoints();return false;">
                                         <option value="50"> Limit 50</option>
                                         <option value="100">Limit 100</option>
@@ -109,14 +113,14 @@
                             <form class="form-inline" role="form">
                                 <div class="form-group">
                                     <input id="endpoint-filter" type="text" class="form-control input-sm">
-                                    <button class="btn btn-default btn-sm" onclick="filter_endpoint();return false;">快速过滤</button>
+                                    <button class="btn btn-default btn-sm btn-info" onclick="filter_endpoint();return false;">快速过滤</button>
                                 </div>
                             </form>
 
                         </div>
 
                         <table class="table table-striped">
-                            <thead> <tr>
+                            <thead> <tr> <p class="help-block"><span class="text-warning">支持shift多选</span></p>
                                 <th width="30px" colspan=2><input type="checkbox" id="check_all_endpoints"></th>
                                 <th><button class="btn btn-link btn-xs pull-right" onclick="fn_list_counters();return false;">刷新counter列表</button></th>
                             </tr></thead>
@@ -151,7 +155,7 @@
                             </form>
 
                             <form class="form-inline" role="form">
-                                <button class="btn btn-default btn-sm" onclick="fn_list_counters();return false;">搜索</button>
+                                <button class="btn btn-default btn-sm btn-success" onclick="fn_list_counters();return false;">搜索</button>
                                 <div class="form-group">
                                     <select class="form-control input-sm" id="counter-limit" onchange="fn_list_counters();return false;">
                                         <option value="50"> Limit 50</option>
@@ -161,7 +165,7 @@
                                 </div>
                                 <div class="form-group">
                                     <input id="counter-filter" type="text" class="form-control input-sm">
-                                    <button class="btn btn-default btn-sm" onclick="filter_counter();return false;">快速过滤</button>
+                                    <button class="btn btn-default btn-sm btn-info" onclick="filter_counter();return false;">快速过滤</button>
                                 </div>
 
                                 <div class="dropdown form-group pull-right">