summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-10-09 06:03:26 +0000
committerGerrit Code Review <review@openstack.org>2013-10-09 06:03:26 +0000
commit177d972960beaa306f31b35060e4f73ea6b00c77 (patch)
tree77e84b165536d71bb3ba66b6c1225a4db566958b
parent99fb8f630c751b8a938808a9974fe6a4003afdcc (diff)
parent87ce84eede864660b5d1be45592e12c37a312d52 (diff)
downloadtuskar-ui-177d972960beaa306f31b35060e4f73ea6b00c77.tar.gz
Merge "JavaScript enhancements for the FormsetDataTable"
-rw-r--r--tuskar_ui/infrastructure/static/infrastructure/js/tuskar.formset_table.js79
-rw-r--r--tuskar_ui/infrastructure/static/infrastructure/tests/formset_table.js73
-rw-r--r--tuskar_ui/infrastructure/templates/formset_table/_table.html11
-rw-r--r--tuskar_ui/infrastructure/templates/infrastructure/_scripts.html1
-rw-r--r--tuskar_ui/infrastructure/templates/infrastructure/qunit.html162
5 files changed, 326 insertions, 0 deletions
diff --git a/tuskar_ui/infrastructure/static/infrastructure/js/tuskar.formset_table.js b/tuskar_ui/infrastructure/static/infrastructure/js/tuskar.formset_table.js
new file mode 100644
index 00000000..61b0a87d
--- /dev/null
+++ b/tuskar_ui/infrastructure/static/infrastructure/js/tuskar.formset_table.js
@@ -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;
+} ());
diff --git a/tuskar_ui/infrastructure/static/infrastructure/tests/formset_table.js b/tuskar_ui/infrastructure/static/infrastructure/tests/formset_table.js
new file mode 100644
index 00000000..720b9d56
--- /dev/null
+++ b/tuskar_ui/infrastructure/static/infrastructure/tests/formset_table.js
@@ -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);
+ });
+});
diff --git a/tuskar_ui/infrastructure/templates/formset_table/_table.html b/tuskar_ui/infrastructure/templates/formset_table/_table.html
index 5ef160af..22532bd1 100644
--- a/tuskar_ui/infrastructure/templates/formset_table/_table.html
+++ b/tuskar_ui/infrastructure/templates/formset_table/_table.html
@@ -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 %}
diff --git a/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html b/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html
index 73733889..a764f386 100644
--- a/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html
+++ b/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html
@@ -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 %}
diff --git a/tuskar_ui/infrastructure/templates/infrastructure/qunit.html b/tuskar_ui/infrastructure/templates/infrastructure/qunit.html
index ad03ae99..e0e0ba8a 100644
--- a/tuskar_ui/infrastructure/templates/infrastructure/qunit.html
+++ b/tuskar_ui/infrastructure/templates/infrastructure/qunit.html
@@ -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>