abb42e9f25
Yay, been wanting this for some time now.
297 lines
8.6 KiB
JavaScript
297 lines
8.6 KiB
JavaScript
|
|
/************************************************************
|
|
*
|
|
* tailbone.js
|
|
*
|
|
************************************************************/
|
|
|
|
|
|
/*
|
|
* Initialize the disabled filters array. This is populated from within the
|
|
* /grids/search.mako template.
|
|
*/
|
|
var filters_to_disable = [];
|
|
|
|
|
|
/*
|
|
* Disables options within the "add filter" dropdown which correspond to those
|
|
* filters already being displayed. Called from /grids/search.mako template.
|
|
*/
|
|
function disable_filter_options() {
|
|
while (filters_to_disable.length) {
|
|
var filter = filters_to_disable.shift();
|
|
var option = $('#add-filter option[value="' + filter + '"]');
|
|
option.attr('disabled', 'disabled');
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Convenience function to disable a form button.
|
|
*/
|
|
function disable_button(button, label) {
|
|
if (label) {
|
|
$(button).html(label + ", please wait...");
|
|
}
|
|
$(button).attr('disabled', 'disabled');
|
|
}
|
|
|
|
|
|
/*
|
|
* Load next / previous page of results to grid. This function is called on
|
|
* the click event from the pager links, via inline script code.
|
|
*/
|
|
function grid_navigate_page(link, url) {
|
|
var wrapper = $(link).parents('div.grid-wrapper');
|
|
var grid = wrapper.find('div.grid');
|
|
wrapper.mask("Loading...");
|
|
$.get(url, function(data) {
|
|
wrapper.unmask();
|
|
grid.replaceWith(data);
|
|
});
|
|
}
|
|
|
|
|
|
/*
|
|
* Fetch the UUID value associated with a table row.
|
|
*/
|
|
function get_uuid(obj) {
|
|
obj = $(obj);
|
|
if (obj.attr('uuid')) {
|
|
return obj.attr('uuid');
|
|
}
|
|
var tr = obj.parents('tr:first');
|
|
if (tr.attr('uuid')) {
|
|
return tr.attr('uuid');
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
|
|
/*
|
|
* get_dialog(id, callback)
|
|
*
|
|
* Returns a <DIV> element suitable for use as a jQuery dialog.
|
|
*
|
|
* ``id`` is used to construct a proper ID for the element and allows the
|
|
* dialog to be resused if possible.
|
|
*
|
|
* ``callback``, if specified, should be a callback function for the dialog.
|
|
* This function will be called whenever the dialog has been closed
|
|
* "successfully" (i.e. data submitted) by the user, and should accept a single
|
|
* ``data`` object which is the JSON response returned by the server.
|
|
*/
|
|
|
|
function get_dialog(id, callback) {
|
|
var dialog = $('#'+id+'-dialog');
|
|
if (! dialog.length) {
|
|
dialog = $('<div class="dialog" id="'+id+'-dialog"></div>');
|
|
}
|
|
if (callback) {
|
|
dialog.attr('callback', callback);
|
|
}
|
|
return dialog;
|
|
}
|
|
|
|
|
|
$(function() {
|
|
|
|
/*
|
|
* Initialize the menu bar.
|
|
*/
|
|
$('ul.menubar').menubar({
|
|
buttons: true,
|
|
menuIcon: true,
|
|
autoExpand: true
|
|
});
|
|
|
|
/*
|
|
* Fix buttons.
|
|
*/
|
|
$('button, a.button').button();
|
|
$('input[type=submit]').button();
|
|
$('input[type=reset]').button();
|
|
|
|
/* Also automatically disable any buttons marked for that. */
|
|
$('a.button[disabled=disabled]').button('option', 'disabled', true);
|
|
|
|
/*
|
|
* Apply timepicker behavior to text inputs which are marked for it.
|
|
*/
|
|
$('input[type=text].timepicker').timepicker({
|
|
showPeriod: true
|
|
});
|
|
|
|
/*
|
|
* When filter labels are clicked, (un)check the associated checkbox.
|
|
*/
|
|
$('body').on('click', '.grid-wrapper .filter label', function() {
|
|
var checkbox = $(this).prev('input[type="checkbox"]');
|
|
if (checkbox.prop('checked')) {
|
|
checkbox.prop('checked', false);
|
|
return false;
|
|
}
|
|
checkbox.prop('checked', true);
|
|
});
|
|
|
|
/*
|
|
* When a new filter is selected in the "add filter" dropdown, show it in
|
|
* the UI. This selects the filter's checkbox and puts focus to its input
|
|
* element. If all available filters have been displayed, the "add filter"
|
|
* dropdown will be hidden.
|
|
*/
|
|
$('body').on('change', '#add-filter', function() {
|
|
var select = $(this);
|
|
var filters = select.parents('div.filters:first');
|
|
var filter = filters.find('#filter-' + select.val());
|
|
var checkbox = filter.find('input[type="checkbox"]:first');
|
|
var input = filter.find(':last-child');
|
|
|
|
checkbox.prop('checked', true);
|
|
filter.show();
|
|
input.select();
|
|
input.focus();
|
|
|
|
filters.find('input[type="submit"]').show();
|
|
filters.find('button[type="reset"]').show();
|
|
|
|
select.find('option:selected').attr('disabled', true);
|
|
select.val('add a filter');
|
|
if (select.find('option:enabled').length == 1) {
|
|
select.hide();
|
|
}
|
|
});
|
|
|
|
/*
|
|
* When user clicks the grid filters search button, perform the search in
|
|
* the background and reload the grid in-place.
|
|
*/
|
|
$('body').on('submit', '.filters form', function() {
|
|
var form = $(this);
|
|
var wrapper = form.parents('div.grid-wrapper');
|
|
var grid = wrapper.find('div.grid');
|
|
var data = form.serializeArray();
|
|
data.push({name: 'partial', value: true});
|
|
wrapper.mask("Loading...");
|
|
$.get(grid.attr('url'), data, function(data) {
|
|
wrapper.unmask();
|
|
grid.replaceWith(data);
|
|
});
|
|
return false;
|
|
});
|
|
|
|
/*
|
|
* When user clicks the grid filters reset button, manually clear all
|
|
* filter input elements, and submit a new search.
|
|
*/
|
|
$('body').on('click', '.filters form button[type="reset"]', function() {
|
|
var form = $(this).parents('form');
|
|
form.find('div.filter').each(function() {
|
|
$(this).find('div.value input').val('');
|
|
});
|
|
form.submit();
|
|
return false;
|
|
});
|
|
|
|
$('body').on('click', '.grid thead th.sortable a', function() {
|
|
var th = $(this).parent();
|
|
var wrapper = th.parents('div.grid-wrapper');
|
|
var grid = wrapper.find('div.grid');
|
|
var data = {
|
|
sort: th.attr('field'),
|
|
dir: (th.hasClass('sorted') && th.hasClass('asc')) ? 'desc' : 'asc',
|
|
page: 1,
|
|
partial: true
|
|
};
|
|
wrapper.mask("Loading...");
|
|
$.get(grid.attr('url'), data, function(data) {
|
|
wrapper.unmask();
|
|
grid.replaceWith(data);
|
|
});
|
|
return false;
|
|
});
|
|
|
|
$('body').on('mouseenter', '.grid.hoverable tbody tr', function() {
|
|
$(this).addClass('hovering');
|
|
});
|
|
|
|
$('body').on('mouseleave', '.grid.hoverable tbody tr', function() {
|
|
$(this).removeClass('hovering');
|
|
});
|
|
|
|
$('body').on('click', '.grid tbody td.view', function() {
|
|
var url = $(this).attr('url');
|
|
if (url) {
|
|
location.href = url;
|
|
}
|
|
});
|
|
|
|
$('body').on('click', '.grid tbody td.edit', function() {
|
|
var url = $(this).attr('url');
|
|
if (url) {
|
|
location.href = url;
|
|
}
|
|
});
|
|
|
|
$('body').on('click', '.grid tbody td.delete', function() {
|
|
var url = $(this).attr('url');
|
|
if (url) {
|
|
if (confirm("Do you really wish to delete this object?")) {
|
|
location.href = url;
|
|
}
|
|
}
|
|
});
|
|
|
|
// $('div.grid-wrapper').on('change', 'div.grid div.pager select#grid-page-count', function() {
|
|
$('body').on('change', '.grid .pager #grid-page-count', function() {
|
|
var select = $(this);
|
|
var wrapper = select.parents('div.grid-wrapper');
|
|
var grid = wrapper.find('div.grid');
|
|
var data = {
|
|
per_page: select.val(),
|
|
partial: true
|
|
};
|
|
wrapper.mask("Loading...");
|
|
$.get(grid.attr('url'), data, function(data) {
|
|
wrapper.unmask();
|
|
grid.replaceWith(data);
|
|
});
|
|
|
|
});
|
|
|
|
/*
|
|
* Whenever the "change" button is clicked within the context of an
|
|
* autocomplete field, hide the static display and show the autocomplete
|
|
* textbox.
|
|
*/
|
|
$('div.autocomplete-container button.autocomplete-change').click(function() {
|
|
var container = $(this).parents('div.autocomplete-container');
|
|
var textbox = container.find('input.autocomplete-textbox');
|
|
|
|
container.find('input[type="hidden"]').val('');
|
|
container.find('div.autocomplete-display').hide();
|
|
|
|
textbox.val('');
|
|
textbox.show();
|
|
textbox.select();
|
|
textbox.focus();
|
|
});
|
|
|
|
/*
|
|
* Add "check all" functionality to tables with checkboxes.
|
|
*/
|
|
$('body').on('click', '.grid thead th.checkbox input[type="checkbox"]', function() {
|
|
var table = $(this).parents('table:first');
|
|
var checked = $(this).prop('checked');
|
|
table.find('tbody tr').each(function() {
|
|
$(this).find('td.checkbox input[type="checkbox"]').prop('checked', checked);
|
|
});
|
|
});
|
|
|
|
$('body').on('click', 'div.dialog button.close', function() {
|
|
var dialog = $(this).parents('div.dialog:first');
|
|
dialog.dialog('close');
|
|
});
|
|
|
|
});
|