diff options
author | Paul Duncan <pabs@pablotron.org> | 2016-04-02 02:06:31 -0400 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2016-04-02 02:06:31 -0400 |
commit | 6ceae6b02d89bfebbb3bec13ce9525014cbdd2a7 (patch) | |
tree | 3aa1292d70e199a7919c5ea522758e6d8ea0f5b6 | |
parent | 23ba337de24e88c6aaf6ceb37507997f5c5f4920 (diff) | |
download | old-guff-6ceae6b02d89bfebbb3bec13ce9525014cbdd2a7.tar.bz2 old-guff-6ceae6b02d89bfebbb3bec13ce9525014cbdd2a7.zip |
add search-field and searching to users panel
-rw-r--r-- | data/stuff/js/search-field.js | 79 | ||||
-rw-r--r-- | data/stuff/js/util.js | 15 | ||||
-rw-r--r-- | data/stuff/test/auth.js | 30 | ||||
-rw-r--r-- | src/guff/views/ecrs/test/auth.ecr | 80 | ||||
-rw-r--r-- | src/guff/views/html/test/auth.cr | 6 |
5 files changed, 191 insertions, 19 deletions
diff --git a/data/stuff/js/search-field.js b/data/stuff/js/search-field.js new file mode 100644 index 0000000..42bec10 --- /dev/null +++ b/data/stuff/js/search-field.js @@ -0,0 +1,79 @@ +jQuery(function($) { + "use strict"; + + function clear_delay(el) { + var ival = el.data('search-interval'); + + if (ival) { + // clear interval + clearInterval(ival); + el.data('search-interval', null); + } + } + + function trigger_search(el, q) { + if (q == el.data('q')) + return; + + // cache search + el.data('q', q); + + // trigger search + el.trigger({ + type: "search-update", + query: "", + }); + } + + $('.btn.search-toggle').click(function() { + var btn = $(this), + bar = btn.parents('.panel').find('.panel-heading.search-toggle'), + field = bar.find('input'); + + // toggle button highlight + btn.toggleClass('btn-primary btn-default') + var active = btn.hasClass('btn-primary'); + + // clear field + field.val(''); + + // toggle bar visibility + bar.toggleClass('hidden', !active); + + if (active) { + setTimeout(function() { + // focus text field + field.focus(); + }, 10); + } else { + // trigger search + trigger_search(field, ''); + } + }); + + $('.panel-heading.search-toggle input').keydown(function(ev) { + var me = $(this), + trigger = me.data('search-trigger') || 'delay'; + + if (trigger == 'delay') { + clear_delay(me); + + setTimeout(function() { + clear_delay(me); + trigger_search(me, me.val()); + }, me.data('search-delay') || 100); + } else if (trigger == 'enter') { + if (ev.which == 13) { + setTimeout(function() { + trigger_search(me, me.val()); + }, 10); + + // stop event + return false; + } + } else { + // unknown trigger type + throw new Error('unknown search trigger: ' + trigger); + } + }); +}); diff --git a/data/stuff/js/util.js b/data/stuff/js/util.js index c021499..ed048ec 100644 --- a/data/stuff/js/util.js +++ b/data/stuff/js/util.js @@ -1,3 +1,18 @@ +$.fn.reduce = (function() { + if (Array.prototype.reduce) { + return Array.prototype.reduce; + } else { + return function(a, cb, r) { + a = [].concat(a); + + for (var i = 0, l = a.length; i < l; i++) + r = cb(r, a[i]); + + return r; + }; + } +})(); + jQuery(function($) { "use strict"; diff --git a/data/stuff/test/auth.js b/data/stuff/test/auth.js index 0776bfd..3960da6 100644 --- a/data/stuff/test/auth.js +++ b/data/stuff/test/auth.js @@ -7,6 +7,7 @@ jQuery(function($) { "class='list-group-item %{css|h}' ", "title='Edit user \"%{user_name|h}\".' ", "data-row='%{row|json|h}' ", + "data-q='%{q|h}' ", ">", "<i class='fa fa-fw fa-spinner fa-spin hidden loading'></i>", "<i class='fa fa-fw fa-user loading'></i>", @@ -34,6 +35,27 @@ jQuery(function($) { ], }); + function filter() { + var qs = $('#filter-q').val().replace(/^\s+|\s+$/g, '').toLowerCase().split(/\s+/); + + if (qs.length > 0) { + // hide all users + $('#users .list-group-item').addClass('hidden'); + + // show matching users + $($.grep($('#users .list-group-item'), function(el) { + var eq = $(el).data('q'); + + return ($.grep(qs, function(q) { + return eq.indexOf(q) !== -1; + }).length == qs.length); + })).removeClass('hidden'); + } else { + // show all users + $('#users .list-group-item').removeClass('hidden'); + } + } + function reload() { var btn = $('#reload'), list = $('#users'); @@ -51,9 +73,13 @@ jQuery(function($) { }).done(function(r) { list.html($.map(r.users, function(row) { return TEMPLATES.run('user', $.extend({}, row, { + q: [row.user_id, row.user_name, row.email, row.role_name].join(' ').toLowerCase(), row: row, })); }).join('')); + + // refresh filters + filter(); }); // stop event @@ -70,6 +96,10 @@ jQuery(function($) { }); } + $('#filter-q').on('search-update', function() { + filter(); + }); + $('#users').on('click', 'a.list-group-item', function() { var me = $(this); diff --git a/src/guff/views/ecrs/test/auth.ecr b/src/guff/views/ecrs/test/auth.ecr index ab9f552..00cc918 100644 --- a/src/guff/views/ecrs/test/auth.ecr +++ b/src/guff/views/ecrs/test/auth.ecr @@ -27,25 +27,8 @@ <div class='btn-group btn-group-xs pull-right'> <a href='#' - id='reload' - class='btn btn-default btn-xs' - title='Reload users.' - > - <span class='loading'> - <i class='fa fa-refresh'></i> - </span> - - <span class='loading hidden'> - <i class='fa fa-spinner fa-spin'></i> - </span> - </a><!-- #reload --> - </div><!-- btn-group --> - - <div class='btn-group btn-group-xs pull-right'> - <a - href='#' class='btn btn-primary btn-xs' - title='Add new user.' + title='Create new user.' data-toggle='modal' data-target='#add-dialog' > @@ -55,6 +38,67 @@ </div><!-- btn-group --> </div><!-- panel-heading --> + <div class='panel-heading'> + <div class='btn-toolbar'> + <div class='btn-group btn-group-sm'> + <a + href='#' + class='btn btn-default' + title='Filter users by role.' + data-toggle='dropdown' + > + Role: <span></span> + <i class='fa fa-caret-down'></i> + </a> + + <ul id='filter-roles' class='dropdown-menu'> + </ul> + </div><!-- btn-group --> + + <div class='btn-group btn-group-sm pull-right'> + <a + href='#' + id='reload' + class='btn btn-default' + title='Reload users.' + > + <span class='loading'> + <i class='fa fa-refresh'></i> + </span> + + <span class='loading hidden'> + <i class='fa fa-spinner fa-spin'></i> + </span> + </a><!-- #reload --> + </div><!-- btn-group --> + + <div class='btn-group btn-group-sm pull-right'> + <a + href='#' + class='btn btn-default search-toggle' + title='Toggle search field.' + > + <i class='fa fa-search'></i> + </a><!-- btn--> + </div><!-- btn-group --> + </div><!-- btn-toolbar --> + </div><!-- panel-heading --> + + <div class='panel-heading hidden search-toggle'> + <div class='input-group input-group-sm'> + <span class='input-group-addon'> + <i class='fa fa-search'></i> + </span> + + <input + type='text' + id='filter-q' + class='form-control' + title='Enter search terms' + /> + </div><!-- input-group --> + </div><!-- panel-heading --> + <div id='users' class='list-group'> <span class='list-group-item disabled'> <i class='fa fa-spinner fa-spin'></i> diff --git a/src/guff/views/html/test/auth.cr b/src/guff/views/html/test/auth.cr index 1baa7de..528b652 100644 --- a/src/guff/views/html/test/auth.cr +++ b/src/guff/views/html/test/auth.cr @@ -4,6 +4,10 @@ require "../page" class Guff::TestAuthHTMLView TITLE = "Guff Auth Test" FEATURES = %w{bootstrap font-awesome guff/util} + SCRIPTS = %w{ + /guff-stuff/js/search-field.js + /guff-stuff/test/auth.js + } TEMPLATES = TemplateCache.new({ role: " @@ -27,7 +31,7 @@ class Guff::TestAuthHTMLView def run(context) page = PageHTMLView.new(TITLE, self.to_s) page.add_features(FEATURES) - page.scripts << "/guff-stuff/test/auth.js" + page.scripts.concat(SCRIPTS) context.response.content_type = page.content_type context.response.puts page end |