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 000000000..61b0a87d8 --- /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( + $('×').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( + '' + + add_label + + '' + ).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 000000000..720b9d569 --- /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 = ''; + + 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 5ef160af5..22532bd11 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 }} + + {% endblock table %} diff --git a/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html b/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html index 73733889b..a764f3863 100644 --- a/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html +++ b/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html @@ -5,6 +5,7 @@ + {% 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 ad03ae993..e0e0ba8a2 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 %} + {% comment %}End test modules.{% endcomment %} {% include "horizon/_scripts.html" %} @@ -22,6 +23,167 @@
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Flavors

    + +
    +
    Flavor NameVCPURAM (MB)Root Disk (GB)Ephemeral Disk + (GB)Swap Disk + (MB)Max. + VMs + Delete
    -
    -
    -
    Displaying 3 + items
    +
    +