浏览代码

优化表格快捷搜索功能

jqh 5 年之前
父节点
当前提交
d944159111

+ 13 - 12
resources/assets/dcat-admin/main.css

@@ -889,8 +889,8 @@ input.label {
     border-bottom: 1px solid #e3e7eb;
     text-transform: capitalize;
     font-weight: bold;
-    font-size: 13px;
-    padding: .75rem 8px;
+    font-size: 14px;
+    padding: .8rem 8px;
     letter-spacing: .05em;
 }
 .table-header-default.table>thead>tr>th {
@@ -928,10 +928,6 @@ input.label {
     vertical-align: bottom !important;
 }
 
-td {
-    font-size: 13px
-}
-
 .table-bordered {
     border: 1px solid #ebeff2 !important
 }
@@ -2267,7 +2263,7 @@ div.layui-layer-btn{
 }
 
 .da-box .box-header,.da-box .card-header {
-    padding: 13px;
+    padding: 14px;
     /*border-top: 2px solid #fff*/
 }
 .da-box .box-header .btn, .da-box .card-header .btn {
@@ -2278,7 +2274,7 @@ div.layui-layer-btn{
     color: #7c858e!important;
     color:var(--80)!important;
     font-weight: bold;
-    font-size: 13px;
+    font-size: 14px;
 }
 .da-box .box-header .btn:hover,.da-box .card-header .btn:hover {
     background-color: #ebf0f3!important;
@@ -2316,12 +2312,17 @@ div.layui-layer-btn{
 }
 
 .grid-column-header a {
-    color: rgba(0, 0, 0, 0.5)!important;
+    color: #9ab1c3 !important;
     font-size: 13px;
 }
-.grid-column-header a:hover,.grid-column-header a.active {
-    color:#414750!important;
-    color: var(--font)!important;
+/*.grid-column-header a:hover {*/
+/*    color:#7c858e!important;*/
+/*    color: var(--80)!important;*/
+/*}*/
+
+.grid-column-header a.active, .grid-column-header a:hover {
+    color:#297ec0!important;
+    color: var(--primary-dark)!important;
 }
 
 .layui-layer {

+ 150 - 0
resources/assets/dcat-admin/main.js

@@ -1375,3 +1375,153 @@ window.require = window.define = window.exports = window.module = undefined;
 
     LA.AssetsLoader = new AssetsLoader;
 })(window);
+
+(function () {
+    /* @see https://github.com/lodash/lodash/blob/master/debounce.js */
+    /* @see https://www.lodashjs.com/docs/lodash.debounce */
+    function debounce(func, wait, options) {
+        var lastArgs,
+            lastThis,
+            maxWait,
+            result,
+            timerId,
+            lastCallTime;
+
+        var lastInvokeTime = 0;
+        var leading = false;
+        var maxing = false;
+        var trailing = true;
+
+        if (typeof func !== 'function') {
+            throw new TypeError('Expected a function')
+        }
+        wait = +wait || 0;
+        if (isObject(options)) {
+            leading = !!options.leading;
+            maxing = 'maxWait' in options;
+            maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : wait;
+            trailing = 'trailing' in options ? !!options.trailing : trailing
+        }
+
+        function isObject(value) {
+            var type = typeof value;
+            return value != null && (type === 'object' || type === 'function')
+        }
+
+
+        function invokeFunc(time) {
+            var args = lastArgs;
+            var thisArg = lastThis;
+
+            lastArgs = lastThis = undefined;
+            lastInvokeTime = time;
+            result = func.apply(thisArg, args);
+            return result
+        }
+
+        function startTimer(pendingFunc, wait) {
+            return setTimeout(pendingFunc, wait)
+        }
+
+        function cancelTimer(id) {
+            clearTimeout(id)
+        }
+
+        function leadingEdge(time) {
+            // Reset any `maxWait` timer.
+            lastInvokeTime = time;
+            // Start the timer for the trailing edge.
+            timerId = startTimer(timerExpired, wait);
+            // Invoke the leading edge.
+            return leading ? invokeFunc(time) : result
+        }
+
+        function remainingWait(time) {
+            var timeSinceLastCall = time - lastCallTime;
+            var timeSinceLastInvoke = time - lastInvokeTime;
+            var timeWaiting = wait - timeSinceLastCall;
+
+            return maxing
+                ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)
+                : timeWaiting
+        }
+
+        function shouldInvoke(time) {
+            var timeSinceLastCall = time - lastCallTime;
+            var timeSinceLastInvoke = time - lastInvokeTime;
+
+            // Either this is the first call, activity has stopped and we're at the
+            // trailing edge, the system time has gone backwards and we're treating
+            // it as the trailing edge, or we've hit the `maxWait` limit.
+            return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
+                (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait))
+        }
+
+        function timerExpired() {
+            var time = Date.now();
+            if (shouldInvoke(time)) {
+                return trailingEdge(time)
+            }
+            // Restart the timer.
+            timerId = startTimer(timerExpired, remainingWait(time))
+        }
+
+        function trailingEdge(time) {
+            timerId = undefined;
+
+            // Only invoke if we have `lastArgs` which means `func` has been
+            // debounced at least once.
+            if (trailing && lastArgs) {
+                return invokeFunc(time)
+            }
+            lastArgs = lastThis = undefined;
+            return result
+        }
+
+        function cancel() {
+            if (timerId !== undefined) {
+                cancelTimer(timerId)
+            }
+            lastInvokeTime = 0;
+            lastArgs = lastCallTime = lastThis = timerId = undefined
+        }
+
+        function flush() {
+            return timerId === undefined ? result : trailingEdge(Date.now())
+        }
+
+        function pending() {
+            return timerId !== undefined
+        }
+
+        function debounced() {
+            var time = Date.now();
+            var isInvoking = shouldInvoke(time);
+
+            lastArgs = arguments;
+            lastThis = this;
+            lastCallTime = time;
+
+            if (isInvoking) {
+                if (timerId === undefined) {
+                    return leadingEdge(lastCallTime)
+                }
+                if (maxing) {
+                    // Handle invocations in a tight loop.
+                    timerId = startTimer(timerExpired, wait);
+                    return invokeFunc(lastCallTime)
+                }
+            }
+            if (timerId === undefined) {
+                timerId = startTimer(timerExpired, wait)
+            }
+            return result
+        }
+        debounced.cancel = cancel;
+        debounced.flush = flush;
+        debounced.pending = pending;
+        return debounced
+    }
+
+    LA.debounce = debounce;
+})();

文件差异内容过多而无法显示
+ 0 - 0
resources/assets/dcat-admin/main.min.css


文件差异内容过多而无法显示
+ 0 - 0
resources/assets/dcat-admin/main.min.js


+ 1 - 1
resources/views/grid/batch-actions.blade.php

@@ -1,6 +1,6 @@
 <div class="btn-group default" style="margin-right:3px">
     <button type="button" class="btn btn-sm btn-default dropdown-toggle btn-mini" data-toggle="dropdown">
-        <span class="hidden-xs">{{ trans('admin.action') }}&nbsp;&nbsp;</span>
+        <span class="hidden-xs">{{ trans('admin.action') }}&nbsp;</span>
         <span class="caret"></span>
         <span class="sr-only"></span>
     </button>

+ 2 - 2
resources/views/grid/quick-search.blade.php

@@ -1,13 +1,13 @@
 <style>::-ms-clear,::-ms-reveal{display: none;}</style>
 
-<form action="{!! $action !!}" class="input-no-border" pjax-container style="display:inline-block;margin:0 5px 13px 0;">
+<form id="{{ $id }}" action="{!! $action !!}" class="input-no-border" pjax-container style="display:inline-block;margin:0 5px 13px 0;">
     <div class="input-group quick-search" style="width:{{$width}}rem;">
 
         <input type="text"
                placeholder="{{ $placeholder }}"
                name="{{ $key }}"
                class="form-control quick-search-input"
-               style="margin-left:-1px;padding:0 1.6rem 0 3.6rem;height:36px;line-height:36px;"
+               style="margin-left:-1px;padding:0 1.6rem 0 3.8rem;height:36px;line-height:36px;"
                value="{{ $value }}"
         >
         <a onclick="$(this).submit()" style="overflow:hidden;position:absolute;top:8px;margin-left:-{{$width - 0.9}}rem;cursor:pointer;z-index:100">

+ 4 - 0
src/Grid/Column/Sorter.php

@@ -94,6 +94,10 @@ class Sorter implements Renderable
             ]);
         }
 
+        if ($icon) {
+            $icon .= ' active';
+        }
+
         return " <a class=' glyphicon glyphicon-sort{$icon} $color' href='$url'></a>";
     }
 }

+ 1 - 1
src/Grid/Tools/ExportButton.php

@@ -104,7 +104,7 @@ JS;
         return <<<EOT
 <div class="btn-group " style="margin-right:3px">
     <button type="button" class="btn btn-sm btn-custom dropdown-toggle" data-toggle="dropdown">
-        <span class="hidden-xs">{$export}&nbsp;&nbsp;</span>
+        <span class="hidden-xs">{$export}&nbsp;</span>
         <span class="caret"></span>
         <span class="sr-only"></span>
     </button>

+ 46 - 23
src/Grid/Tools/QuickSearch.php

@@ -22,10 +22,20 @@ class QuickSearch extends AbstractTool
      */
     protected $queryName = '__search__';
 
+    /**
+     * @var string
+     */
+    protected $id;
+
     /**
      * @var int rem
      */
-    protected $width = 27;
+    protected $width = 29;
+
+    public function __construct($key = null, $title = null)
+    {
+        parent::__construct($key, $title);
+    }
 
     /**
      * @param string|null $name
@@ -34,6 +44,7 @@ class QuickSearch extends AbstractTool
      */
     public function setQueryName(?string $name)
     {
+        $this->id = 'grid-quick-search-'.$name;
         $this->queryName = $name;
 
         return $this;
@@ -78,7 +89,7 @@ class QuickSearch extends AbstractTool
      */
     public function value()
     {
-        return request($this->queryName);
+        return trim(request($this->queryName));
     }
 
     /**
@@ -86,11 +97,11 @@ class QuickSearch extends AbstractTool
      */
     public function render()
     {
-        $this->setupScript();
-
         $request = request();
         $query = $request->query();
 
+        $this->setupScript();
+
         Arr::forget($query, [
             $this->queryName,
             $this->parent->model()->getPageName(),
@@ -103,6 +114,7 @@ class QuickSearch extends AbstractTool
             'value'       => $this->value(),
             'placeholder' => $this->placeholder ?: trans('admin.search'),
             'width'       => $this->width,
+            'id'          => $this->id,
         ];
 
         return view($this->view, $vars);
@@ -111,25 +123,36 @@ class QuickSearch extends AbstractTool
     protected function setupScript()
     {
         $script = <<<'JS'
-var show = function () {
-    var t = $(this),
-        clear = t.parent().find('.quick-search-clear');
-
-    if (t.val()) {
-        clear.css({color: '#333'});
-    } else {
-        clear.css({color: '#fff'});
-    }
-    return false;
-};
-
-$('input.quick-search-input').on('focus', show).on('keyup', show);
-
-$('.quick-search-clear').click(function () {
-    $(this).parent().find('.quick-search-input').val('');
-
-    $(this).closest('form').submit();
-});
+(function () {
+    var show = function () {
+        var t = $(this),
+            clear = t.parent().find('.quick-search-clear');
+    
+        if (t.val()) {
+            clear.css({color: '#333'});
+        } else {
+            clear.css({color: '#fff'});
+        }
+        return false;
+    };
+    
+    var request = LA.debounce(function (input) {
+        $(input).parents('form').submit()
+    }, 500);
+    var $input = $('input.quick-search-input');
+    $input.on('focus', show).on('keyup', function () {
+        show.apply(this);
+        request(this);
+    });
+    var val = $input.val();
+    val !== '' && $input.val('').focus().val(val);
+    
+    $('.quick-search-clear').click(function () {
+        $(this).parent().find('.quick-search-input').val('');
+    
+        $(this).closest('form').submit();
+    });
+})()
 JS;
 
         Admin::script($script);

部分文件因为文件数量过多而无法显示