Merge "JavaScript enhancements for the FormsetDataTable"
This commit is contained in:
commit
177d972960
@ -0,0 +1,79 @@
|
||||
tuskar.formset_table = (function () {
|
||||
'use strict';
|
||||
|
||||
var module = {};
|
||||
|
||||
|
||||
// go through the whole table and fix the numbering of rows
|
||||
module.reenumerate_rows = function (table, prefix) {
|
||||
var count = 0;
|
||||
var input_name_re = new RegExp('^' + prefix + '-(\\d+|__prefix__)-');
|
||||
var input_id_re = new RegExp('^id_' + prefix + '-(\\d+|__prefix__)-');
|
||||
|
||||
table.find('tbody tr').each(function () {
|
||||
$(this).find('input').each(function () {
|
||||
var input = $(this);
|
||||
input.attr('name', input.attr('name').replace(
|
||||
input_name_re, prefix + '-' + count + '-'));
|
||||
input.attr('id', input.attr('id').replace(
|
||||
input_id_re, 'id_' + prefix + '-' + count + '-'));
|
||||
});
|
||||
count += 1;
|
||||
});
|
||||
$('#id_' + prefix + '-TOTAL_FORMS').val(count);
|
||||
};
|
||||
|
||||
// mark a row as deleted and hide it
|
||||
module.delete_row = function (e) {
|
||||
$(this).closest('tr').hide();
|
||||
$(this).prev('input[name$="-DELETE"]').attr('checked', true);
|
||||
};
|
||||
|
||||
// replace the "Delete" checkboxes with × for deleting rows
|
||||
module.replace_delete = function (where) {
|
||||
where.find('input[name$="-DELETE"]').hide().after(
|
||||
$('<a href="#" class="close">×</a>').click(module.delete_row)
|
||||
);
|
||||
};
|
||||
|
||||
// add more empty rows in the flavors table
|
||||
module.add_row = function (table, prefix, empty_row_html) {
|
||||
var new_row = $(empty_row_html);
|
||||
module.replace_delete(new_row);
|
||||
table.find('tbody').append(new_row);
|
||||
module.reenumerate_rows(table, prefix);
|
||||
};
|
||||
|
||||
// prepare all the javascript for formset table
|
||||
module.init = function (prefix, empty_row_html, add_label) {
|
||||
|
||||
var table = $('table#' + prefix);
|
||||
|
||||
module.replace_delete(table);
|
||||
|
||||
// if there are extra empty rows, add the button for new rows
|
||||
if ($('#id_' + prefix + '-TOTAL_FORMS').val() >
|
||||
$('#id_' + prefix + '-INITIAL_FORMS').val()) {
|
||||
table.find('tfoot td').append(
|
||||
'<a href="#" class="btn btn-small pull-right">' +
|
||||
add_label +
|
||||
'</a>'
|
||||
).click(function () {
|
||||
module.add_row(table, prefix, empty_row_html);
|
||||
});
|
||||
};
|
||||
|
||||
// if the formset is not empty, and is not being redisplayed,
|
||||
// delete the empty extra row from the end
|
||||
if (table.find('tbody tr').length > 1 &&
|
||||
$('#id_' + prefix + '-TOTAL_FORMS').val() >
|
||||
$('#id_' + prefix + '-INITIAL_FORMS').val()) {
|
||||
table.find('tbody tr:last').remove();
|
||||
module.reenumerate_rows(table, prefix);
|
||||
$('#id_' + prefix + '-INITIAL_FORMS').val(
|
||||
$('#id_' + prefix + '-TOTAL_FORMS').val());
|
||||
};
|
||||
};
|
||||
|
||||
return module;
|
||||
} ());
|
@ -0,0 +1,73 @@
|
||||
horizon.addInitFunction(function () {
|
||||
module("Formset table (tuskar.formset_table.js)");
|
||||
|
||||
test("Reenumerate rows", function () {
|
||||
var html = $('#qunit-fixture');
|
||||
var table = html.find('table');
|
||||
var input = table.find('tbody tr#flavors__row__14 input').first();
|
||||
|
||||
input.attr('id', 'id_flavors-3-name');
|
||||
tuskar.formset_table.reenumerate_rows(table, 'flavors');
|
||||
equal(input.attr('id'), 'id_flavors-0-name', "Enumerate old rows ids");
|
||||
input.attr('id', 'id_flavors-__prefix__-name');
|
||||
tuskar.formset_table.reenumerate_rows(table, 'flavors');
|
||||
equal(input.attr('id'), 'id_flavors-0-name', "Enumerate new rows ids");
|
||||
});
|
||||
|
||||
test("Delete row", function () {
|
||||
var html = $('#qunit-fixture');
|
||||
var table = html.find('table');
|
||||
var row = table.find('tbody tr').first();
|
||||
var input = row.find('input#id_flavors-0-DELETE');
|
||||
|
||||
equal(row.css("display"), 'table-row');
|
||||
equal(input.attr('checked'), undefined);
|
||||
tuskar.formset_table.replace_delete(row);
|
||||
var x = input.next('a');
|
||||
tuskar.formset_table.delete_row.call(x)
|
||||
equal(row.css("display"), 'none');
|
||||
equal(input.attr('checked'), 'checked');
|
||||
});
|
||||
|
||||
test("Add row", function() {
|
||||
var html = $('#qunit-fixture');
|
||||
var table = html.find('table');
|
||||
var empty_row_html = '<tr><td><input id="id_flavors-__prefix__-name" name="flavors-__prefix__-name"></td></tr>';
|
||||
|
||||
equal(table.find('tbody tr').length, 3);
|
||||
equal(html.find('#id_flavors-TOTAL_FORMS').val(), 3);
|
||||
tuskar.formset_table.add_row(table, 'flavors', empty_row_html);
|
||||
equal(table.find('tbody tr').length, 4);
|
||||
equal(table.find('tbody tr:last input').attr('id'), 'id_flavors-3-name');
|
||||
equal(html.find('#id_flavors-TOTAL_FORMS').val(), 4);
|
||||
});
|
||||
|
||||
test("Init formset table", function() {
|
||||
var html = $('#qunit-fixture');
|
||||
var table = html.find('table');
|
||||
|
||||
equal(table.find('tbody tr').length, 3);
|
||||
equal(html.find('#id_flavors-TOTAL_FORMS').val(), 3);
|
||||
equal(html.find('#id_flavors-INITIAL_FORMS').val(), 2);
|
||||
tuskar.formset_table.init('flavors', '', 'Add row');
|
||||
equal(table.find('tfoot tr a').html(), 'Add row');
|
||||
equal(table.find('tbody tr').length, 2);
|
||||
equal(html.find('#id_flavors-TOTAL_FORMS').val(), 2);
|
||||
equal(html.find('#id_flavors-INITIAL_FORMS').val(), 2);
|
||||
});
|
||||
|
||||
test("Init formset table -- no add", function() {
|
||||
var html = $('#qunit-fixture');
|
||||
var table = html.find('table');
|
||||
|
||||
table.find('tbody tr:last').remove();
|
||||
html.find('#id_flavors-TOTAL_FORMS').val(2);
|
||||
html.find('#id_flavors-INITIAL_FORMS').val(2);
|
||||
equal(table.find('tbody tr').length, 2);
|
||||
tuskar.formset_table.init('flavors', '', 'Add row');
|
||||
equal(table.find('tfoot tr a').length, 0);
|
||||
equal(table.find('tbody tr').length, 2);
|
||||
equal(html.find('#id_flavors-TOTAL_FORMS').val(), 2);
|
||||
equal(html.find('#id_flavors-INITIAL_FORMS').val(), 2);
|
||||
});
|
||||
});
|
@ -25,4 +25,15 @@
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{{ block.super }}
|
||||
|
||||
<script type="text/javascript">
|
||||
($ || addHorizonLoadEvent)(function () {
|
||||
// prepare the js-enabled parts of the formset data table
|
||||
var prefix = '{{ table.name|escapejs }}';
|
||||
var empty_row_html = '{% filter escapejs %}{% include "formset_table/_row.html" with row=table.get_empty_row %}{% endfilter %}';
|
||||
var add_label = '{% filter escapejs %}{% trans "Add a row" %}{% endfilter %}';
|
||||
|
||||
tuskar.formset_table.init(prefix, empty_row_html, add_label);
|
||||
});
|
||||
</script>
|
||||
{% endblock table %}
|
||||
|
@ -5,6 +5,7 @@
|
||||
<script src='{{ STATIC_URL }}infrastructure/js/horizon.d3singlebarchart.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script src='{{ STATIC_URL }}infrastructure/js/tuskar.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script src='{{ STATIC_URL }}infrastructure/js/tuskar.templates.js' type='text/javascript' charset='utf-8'></script>
|
||||
<script src='{{ STATIC_URL }}infrastructure/js/tuskar.formset_table.js' type='text/javascript' charset='utf-8'></script>
|
||||
{% endblock %}
|
||||
|
||||
{% comment %} Tuskar-UI Client-side Templates (These should *not* be inside the "compress" tag.) {% endcomment %}
|
||||
|
@ -9,6 +9,7 @@
|
||||
{% include "horizon/_conf.html" %}
|
||||
|
||||
{% comment %}Load test modules here.{% endcomment %}
|
||||
<script type="text/javascript" src="{{ STATIC_URL }}infrastructure/tests/formset_table.js"></script>
|
||||
{% comment %}End test modules.{% endcomment %}
|
||||
|
||||
{% include "horizon/_scripts.html" %}
|
||||
@ -22,6 +23,167 @@
|
||||
<ol id="qunit-tests"></ol>
|
||||
<div id="qunit-fixture">
|
||||
<!-- Test markup; will be hidden. -->
|
||||
|
||||
<div class="table_wrapper">
|
||||
<input id="id_flavors-TOTAL_FORMS" name="flavors-TOTAL_FORMS"
|
||||
type="hidden" value="3"><input id="id_flavors-INITIAL_FORMS"
|
||||
name="flavors-INITIAL_FORMS" type="hidden" value="2"><input id=
|
||||
"id_flavors-MAX_NUM_FORMS" name="flavors-MAX_NUM_FORMS" type=
|
||||
"hidden" value="1000">
|
||||
|
||||
<table id="flavors" class=
|
||||
"table table-bordered table-striped datatable">
|
||||
<thead>
|
||||
<tr class='table_caption'>
|
||||
<th class='table_header' colspan='8'>
|
||||
<h3 class='table_title'>Flavors</h3>
|
||||
|
||||
<div class="table_actions clearfix"></div>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th class="sortable normal_column"><span class=
|
||||
"required">Flavor Name</span></th>
|
||||
|
||||
<th class="sortable normal_column"><span class=
|
||||
"required">VCPU</span></th>
|
||||
|
||||
<th class="sortable normal_column"><span class=
|
||||
"required">RAM (MB)</span></th>
|
||||
|
||||
<th class="sortable normal_column"><span class=
|
||||
"required">Root Disk (GB)</span></th>
|
||||
|
||||
<th class="sortable normal_column"><span>Ephemeral Disk
|
||||
(GB)</span></th>
|
||||
|
||||
<th class="sortable normal_column"><span>Swap Disk
|
||||
(MB)</span></th>
|
||||
|
||||
<th class="sortable normal_column"><span>Max.
|
||||
VMs</span></th>
|
||||
|
||||
<th class="sortable normal_column">
|
||||
<span>Delete</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr class="" data-display="yyy.1" id="flavors__row__14">
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input input-small" id="id_flavors-0-name" maxlength="25"
|
||||
name="flavors-0-name" type="text" value="1"> <input id=
|
||||
"id_flavors-0-id" name="flavors-0-id" type="hidden"
|
||||
value="14"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-0-cpu" name=
|
||||
"flavors-0-cpu" type="number" value="1"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-0-memory" name=
|
||||
"flavors-0-memory" type="number" value="1"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-0-storage" name=
|
||||
"flavors-0-storage" type="number" value="1"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id=
|
||||
"id_flavors-0-ephemeral_disk" name=
|
||||
"flavors-0-ephemeral_disk" type="number"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-0-swap_disk"
|
||||
name="flavors-0-swap_disk" type="number"></td>
|
||||
|
||||
<td class="sortable normal_column">-</td>
|
||||
|
||||
<td class="sortable normal_column"><input id=
|
||||
"id_flavors-0-DELETE" name="flavors-0-DELETE" type=
|
||||
"checkbox"></td>
|
||||
</tr>
|
||||
|
||||
<tr class="" data-display="yyy.2" id="flavors__row__15">
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input input-small" id="id_flavors-1-name" maxlength="25"
|
||||
name="flavors-1-name" type="text" value="2"> <input id=
|
||||
"id_flavors-1-id" name="flavors-1-id" type="hidden"
|
||||
value="15"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-1-cpu" name=
|
||||
"flavors-1-cpu" type="number" value="2"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-1-memory" name=
|
||||
"flavors-1-memory" type="number" value="2"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-1-storage" name=
|
||||
"flavors-1-storage" type="number" value="2"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id=
|
||||
"id_flavors-1-ephemeral_disk" name=
|
||||
"flavors-1-ephemeral_disk" type="number"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-1-swap_disk"
|
||||
name="flavors-1-swap_disk" type="number"></td>
|
||||
|
||||
<td class="sortable normal_column">-</td>
|
||||
|
||||
<td class="sortable normal_column"><input id=
|
||||
"id_flavors-1-DELETE" name="flavors-1-DELETE" type=
|
||||
"checkbox"></td>
|
||||
</tr>
|
||||
|
||||
<tr class="current_selected">
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input input-small" id="id_flavors-2-name" maxlength="25"
|
||||
name="flavors-2-name" type="text"> <input id=
|
||||
"id_flavors-2-id" name="flavors-2-id" type="hidden"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-2-cpu" name=
|
||||
"flavors-2-cpu" type="number"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-2-memory" name=
|
||||
"flavors-2-memory" type="number"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-2-storage" name=
|
||||
"flavors-2-storage" type="number"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id=
|
||||
"id_flavors-2-ephemeral_disk" name=
|
||||
"flavors-2-ephemeral_disk" type="number"></td>
|
||||
|
||||
<td class="sortable normal_column"><input class=
|
||||
"input number_input_slim" id="id_flavors-2-swap_disk"
|
||||
name="flavors-2-swap_disk" type="number"></td>
|
||||
|
||||
<td class="sortable normal_column">-</td>
|
||||
|
||||
<td class="sortable normal_column"><input id=
|
||||
"id_flavors-2-DELETE" name="flavors-2-DELETE" type=
|
||||
"checkbox"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="8"><span class="table_count">Displaying 3
|
||||
items</span></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user