Add 'gridcore' jQuery plugin, for core behavior

also add 'selected' status for checkbox grids, etc.
This commit is contained in:
Lance Edgar 2018-02-09 15:17:29 -06:00
parent a3b2fbadb7
commit e2bfb31cb2
8 changed files with 127 additions and 102 deletions

View file

@ -240,6 +240,23 @@
text-align: center;
}
.grid tr:not(.header).selected.odd {
background-color: #507aaa;
}
.grid tr:not(.header).selected.even {
background-color: #628db6;
}
.grid tr:not(.header).selected.hovering {
background-color: #3e5b76;
color: white;
}
.grid tr:not(.header).selected a {
color: #cccccc;
}
/******************************
* main actions

View file

@ -1,8 +1,107 @@
// -*- coding: utf-8 -*-
/**********************************************************************
* jQuery UI plugins for Tailbone
**********************************************************************/
/**********************************************************************
* gridcore plugin
**********************************************************************/
(function($) {
$.widget('tailbone.gridcore', {
_create: function() {
var that = this;
// Add hover highlight effect to grid rows during mouse-over.
// this.element.on('mouseenter', 'tbody tr:not(.header)', function() {
this.element.on('mouseenter', 'tr:not(.header)', function() {
$(this).addClass('hovering');
});
// this.element.on('mouseleave', 'tbody tr:not(.header)', function() {
this.element.on('mouseleave', 'tr:not(.header)', function() {
$(this).removeClass('hovering');
});
// do some extra stuff for grids with checkboxes
// (un-)check all rows when clicking check-all box in header
if (this.element.find('tr.header td.checkbox :checkbox').length) {
this.element.on('click', 'tr.header td.checkbox :checkbox', function() {
var checked = $(this).prop('checked');
var rows = that.element.find('tr:not(.header)');
rows.find('td.checkbox :checkbox').prop('checked', checked);
if (checked) {
rows.addClass('selected');
} else {
rows.removeClass('selected');
}
that.element.trigger('gridchecked', that.count_selected());
});
}
// when row with checkbox is clicked, toggle selected status,
// unless clicking checkbox (since that already toggles it) or a
// link (since that does something completely different)
this.element.on('click', 'tr:not(.header)', function(event) {
var el = $(event.target);
if (!el.is('a') && !el.is(':checkbox')) {
$(this).find('td.checkbox :checkbox').click();
}
});
this.element.on('change', 'tr:not(.header) td.checkbox :checkbox', function() {
if (this.checked) {
$(this).parents('tr:first').addClass('selected');
} else {
$(this).parents('tr:first').removeClass('selected');
}
that.element.trigger('gridchecked', that.count_selected());
});
// Show 'more' actions when user hovers over 'more' link.
this.element.on('mouseenter', '.actions a.more', function() {
that.element.find('.actions div.more').hide();
$(this).siblings('div.more')
.show()
.position({my: 'left-5 top-4', at: 'left top', of: $(this)});
});
this.element.on('mouseleave', '.actions div.more', function() {
$(this).hide();
});
// Add speed bump for "Delete Row" action, if grid is so configured.
if (this.element.data('delete-speedbump')) {
this.element.on('click', 'tr:not(.header) .actions a.delete', function() {
return confirm("Are you sure you wish to delete this object?");
});
}
},
count_selected: function() {
return this.element.find('tr:not(.header) td.checkbox input:checked').length;
},
// TODO: deprecate / remove this?
count_checked: function() {
return this.count_selected();
},
selected_uuids: function() {
var uuids = [];
this.element.find('tr:not(.header) td.checkbox input:checked').each(function() {
uuids.push($(this).parents('tr:first').data('uuid'));
});
return uuids;
}
});
})( jQuery );
/**********************************************************************
* gridwrapper plugin
**********************************************************************/
@ -25,6 +124,9 @@
this.save_defaults = this.filters.find('#save-defaults');
this.grid = this.element.find('.grid');
// add standard grid behavior
this.grid.gridcore();
// Enhance filters etc.
this.filters.find('.filter').gridfilter();
this.apply_filters.button('option', 'icons', {primary: 'ui-icon-search'});
@ -147,56 +249,6 @@
that.refresh(this.search.substring(1)); // remove leading '?'
return false;
});
// Add hover highlight effect to grid rows during mouse-over.
this.element.on('mouseenter', 'tbody tr:not(.header)', function() {
$(this).addClass('hovering');
});
this.element.on('mouseleave', 'tbody tr:not(.header)', function() {
$(this).removeClass('hovering');
});
// do some extra stuff for grids with checkboxes
// (un-)check all rows when clicking check-all box in header
if (this.grid.find('tr.header td.checkbox input').length) {
this.element.on('click', 'tr.header td.checkbox input', function() {
var checked = $(this).prop('checked');
that.grid.find('tr:not(.header) td.checkbox input').prop('checked', checked);
});
}
// Select current row when clicked, unless clicking checkbox
// (since that already does select the row) or a link (since
// that does something completely different).
this.element.on('click', '.grid tr:not(.header) td.checkbox input', function(event) {
event.stopPropagation();
});
this.element.on('click', '.grid tr:not(.header) a', function(event) {
event.stopPropagation();
});
this.element.on('click', '.grid tr:not(.header)', function() {
$(this).find('td.checkbox input').click();
});
// Show 'more' actions when user hovers over 'more' link.
this.element.on('mouseenter', '.actions a.more', function() {
that.grid.find('.actions div.more').hide();
$(this).siblings('div.more')
.show()
.position({my: 'left-5 top-4', at: 'left top', of: $(this)});
});
this.element.on('mouseleave', '.actions div.more', function() {
$(this).hide();
});
// Add speed bump for "Delete Row" action, if grid is so configured.
if (this.grid.data('delete-speedbump')) {
this.element.on('click', 'tbody td.actions a.delete', function() {
return confirm("Are you sure you wish to delete this object?");
});
}
},
// Refreshes the visible data within the grid, according to the given settings.
@ -206,6 +258,7 @@
$.get(this.grid.data('url'), settings, function(data) {
that.grid.replaceWith(data);
that.grid = that.element.find('.grid');
that.grid.gridcore();
that.element.unmask();
});
}

View file

@ -155,7 +155,8 @@
var noop_url = '${request.route_url('noop')}';
</script>
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.js') + '?ver={}'.format(tailbone.__version__))}
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.feedback.js'))}
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.feedback.js') + '?ver={}'.format(tailbone.__version__))}
${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js') + '?ver={}'.format(tailbone.__version__))}
</%def>
<%def name="extra_javascript()"></%def>

View file

@ -3,7 +3,6 @@
<%def name="extra_javascript()">
${parent.extra_javascript()}
${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js'))}
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.batch.js'))}
<script type="text/javascript">

View file

@ -3,7 +3,6 @@
<%def name="extra_javascript()">
${parent.extra_javascript()}
${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js'))}
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.batch.js'))}
<script type="text/javascript">

View file

@ -14,7 +14,6 @@
<%def name="extra_javascript()">
${parent.extra_javascript()}
${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js'))}
<script type="text/javascript">
$(function() {
@ -22,18 +21,14 @@
% if master.mergeable and request.has_perm('{}.merge'.format(permission_prefix)):
$('form[name="merge-things"] button').button('option', 'disabled', $('.grid tbody td.checkbox input:checked').length != 2);
$('form[name="merge-things"] button').button('option', 'disabled', $('.grid').gridcore('count_selected') != 2);
$('.grid-wrapper').on('click', 'tbody td.checkbox input', function() {
$('form[name="merge-things"] button').button('option', 'disabled', $('.grid tbody td.checkbox input:checked').length != 2);
$('.grid-wrapper').on('gridchecked', '.grid', function(event, count) {
$('form[name="merge-things"] button').button('option', 'disabled', count != 2);
});
$('form[name="merge-things"]').submit(function() {
var uuids = [];
$('.grid tbody td.checkbox input:checked').each(function() {
uuids.push($(this).parents('tr:first').data('uuid'));
});
var uuids = $('.grid').gridcore('selected_uuids');
if (uuids.length != 2) {
return false;
}
@ -100,41 +95,4 @@
% endif
</%def>
## ${grid.render_complete(tools=capture(self.grid_tools).strip(), context_menu=capture(self.context_menu_items).strip())|n}
${grid.render_complete(tools=capture(self.grid_tools).strip(), context_menu=capture(self.context_menu_items).strip())|n}
## <div class="grid-wrapper">
##
## <table class="grid-header">
## <tbody>
## <tr>
##
## <td class="filters" rowspan="2">
## % if grid.filterable:
## ## TODO: should this be variable sometimes?
## ${grid.render_filters(allow_save_defaults=True)|n}
## % endif
## </td>
##
## <td class="menu">
## <ul id="context-menu">
## ${self.context_menu_items()}
## </ul>
## </td>
## </tr>
##
## <tr>
## <td class="tools">
## <div class="grid-tools">
## ${self.grid_tools()}
## </div><!-- grid-tools -->
## </td>
## </tr>
##
## </tbody>
## </table><!-- grid-header -->
##
## ${grid.render_grid()|n}
##
## </div><!-- grid-wrapper -->

View file

@ -10,7 +10,6 @@
<%def name="extra_javascript()">
${parent.extra_javascript()}
${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js'))}
<script type="text/javascript">
$(function() {
$('.grid-wrapper').gridwrapper();

View file

@ -6,7 +6,6 @@
<%def name="extra_javascript()">
${parent.extra_javascript()}
% if master.has_rows:
${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js'))}
<script type="text/javascript">
$(function() {
$('.grid-wrapper').gridwrapper();