Merge pull request #3570 from birarda/master

fix for array tables with multiple columns
This commit is contained in:
Clément Brisset 2014-10-09 15:26:42 -07:00
commit eb26b64ae2
3 changed files with 125 additions and 34 deletions

View file

@ -59,6 +59,20 @@
"type": "password", "type": "password",
"help": "Password used for basic HTTP authentication. Leave this blank if you do not want to change it.", "help": "Password used for basic HTTP authentication. Leave this blank if you do not want to change it.",
"value-hidden": true "value-hidden": true
},
{
"name": "allowed_users",
"type": "table",
"label": "Allowed Users",
"help": "A list of usernames for the High Fidelity users you want to allow into your domain. Users not found in this list will not be allowed to connect.",
"numbered": false,
"columns": [
{
"name": "username",
"label": "Username",
"can_set": true
}
]
} }
] ]
}, },
@ -99,6 +113,33 @@
} }
] ]
}, },
{
"name": "attenuation_coefficients",
"type": "table",
"label": "Attenuation Coefficients",
"help": "In this table you can set custom attenuation coefficients between audio zones",
"numbered": false,
"columns": [
{
"name": "source",
"label": "Source",
"can_set": true,
"placeholder": "Zone_A"
},
{
"name": "listener",
"label": "Listener",
"can_set": true,
"placeholder": "Zone_B"
},
{
"name": "coefficient",
"label": "Attenuation coefficient",
"can_set": true,
"placeholder": "0.18"
}
]
},
{ {
"name": "enable_filter", "name": "enable_filter",
"type": "checkbox", "type": "checkbox",

View file

@ -84,3 +84,8 @@ td.buttons .glyphicon {
text-align: center; text-align: center;
font-size: 12px; font-size: 12px;
} }
tr.new-row {
color: #3c763d;
background-color: #dff0d8;
}

View file

@ -1,12 +1,22 @@
var Settings = { var Settings = {
showAdvanced: false showAdvanced: false,
ADVANCED_CLASS: 'advanced-setting',
TRIGGER_CHANGE_CLASS: 'trigger-change',
DATA_ROW_CLASS: 'value-row',
DATA_COL_CLASS: 'value-col',
ADD_ROW_BUTTON_CLASS: 'add-row',
ADD_ROW_SPAN_CLASSES: 'glyphicon glyphicon-plus add-row',
DEL_ROW_BUTTON_CLASS: 'del-row',
DEL_ROW_SPAN_CLASSES: 'glyphicon glyphicon-remove del-row',
TABLE_BUTTONS_CLASS: 'buttons',
NEW_ROW_CLASS: 'new-row'
}; };
var viewHelpers = { var viewHelpers = {
getFormGroup: function(groupName, setting, values, isAdvanced, isLocked) { getFormGroup: function(groupName, setting, values, isAdvanced, isLocked) {
setting_name = groupName + "." + setting.name setting_name = groupName + "." + setting.name
form_group = "<div class='form-group" + (isAdvanced ? " advanced-setting" : "") + "'>" form_group = "<div class='form-group " + (isAdvanced ? Settings.ADVANCED_CLASS : "") + "'>"
if (_.has(values, groupName) && _.has(values[groupName], setting.name)) { if (_.has(values, groupName) && _.has(values[groupName], setting.name)) {
setting_value = values[groupName][setting.name] setting_value = values[groupName][setting.name]
@ -22,7 +32,7 @@ var viewHelpers = {
} }
common_attrs = " class='" + (setting.type !== 'checkbox' ? 'form-control' : '') common_attrs = " class='" + (setting.type !== 'checkbox' ? 'form-control' : '')
+ " trigger-change' data-short-name='" + setting.name + "' name='" + setting_name + "' " + " " + Settings.TRIGGER_CHANGE_CLASS + "' data-short-name='" + setting.name + "' name='" + setting_name + "' "
if (setting.type === 'checkbox') { if (setting.type === 'checkbox') {
form_group += "<label class='" + label_class + "'>" + setting.label + "</label>" form_group += "<label class='" + label_class + "'>" + setting.label + "</label>"
@ -89,15 +99,33 @@ $(document).ready(function(){
$(window).resize(resizeFn); $(window).resize(resizeFn);
}) })
$('#settings-form').on('click', '.add-row', function(){ $('#settings-form').on('click', '.' + Settings.ADD_ROW_BUTTON_CLASS, function(){
addTableRow(this); addTableRow(this);
}) })
$('#settings-form').on('click', '.del-row', function(){ $('#settings-form').on('click', '.' + Settings.DEL_ROW_BUTTON_CLASS, function(){
deleteTableRow(this); deleteTableRow(this);
}) })
$('#settings-form').on('change', 'input.trigger-change', function(){ $('#settings-form').on('keypress', 'table input', function(e){
if (e.keyCode == 13) {
// capture enter in table input
// if we have a sibling next to us that has an input, jump to it, otherwise check if we have a glyphicon for add to click
sibling = $(this).parent('td').next();
if (sibling.hasClass(Settings.DATA_COL_CLASS)) {
// set focus to next input
sibling.find('input').focus()
} else if (sibling.hasClass(Settings.TABLE_BUTTONS_CLASS)) {
sibling.find('.' + Settings.ADD_ROW_BUTTON_CLASS).click()
// set focus to the first input in the new row
$(this).closest('table').find('tr.inputs input:first').focus()
}
}
});
$('#settings-form').on('change', '.' + Settings.TRIGGER_CHANGE_CLASS , function(){
// this input was changed, add the changed data attribute to it // this input was changed, add the changed data attribute to it
$(this).attr('data-changed', true) $(this).attr('data-changed', true)
@ -106,7 +134,7 @@ $(document).ready(function(){
$('#advanced-toggle-button').click(function(){ $('#advanced-toggle-button').click(function(){
Settings.showAdvanced = !Settings.showAdvanced Settings.showAdvanced = !Settings.showAdvanced
var advancedSelector = $('.advanced-setting') var advancedSelector = $('.' + Settings.ADVANCED_CLASS)
if (Settings.showAdvanced) { if (Settings.showAdvanced) {
advancedSelector.show() advancedSelector.show()
@ -210,7 +238,7 @@ function makeTable(setting, setting_name, setting_value) {
var html = "<label class='control-label'>" + setting.label + "</label>" var html = "<label class='control-label'>" + setting.label + "</label>"
html += "<span class='help-block'>" + setting.help + "</span>" html += "<span class='help-block'>" + setting.help + "</span>"
html += "<table class='table table-bordered' data-short-name='" + setting.name + "' name='" + setting_name + (isArray ? "[]" : "") html += "<table class='table table-bordered' data-short-name='" + setting.name + "' name='" + setting_name
+ "' data-setting-type='" + (isArray ? 'array' : 'hash') + "'>" + "' data-setting-type='" + (isArray ? 'array' : 'hash') + "'>"
// Column names // Column names
@ -234,7 +262,7 @@ function makeTable(setting, setting_name, setting_value) {
var row_num = 1 var row_num = 1
_.each(setting_value, function(row, indexOrName) { _.each(setting_value, function(row, indexOrName) {
html += "<tr class='row-data'" + (isArray ? "" : "name='" + setting_name + "." + indexOrName + "'") + ">" html += "<tr class='" + Settings.DATA_ROW_CLASS + "'" + (isArray ? "" : "name='" + setting_name + "." + indexOrName + "'") + ">"
if (setting.numbered === true) { if (setting.numbered === true) {
html += "<td class='numbered'>" + row_num + "</td>" html += "<td class='numbered'>" + row_num + "</td>"
@ -245,12 +273,16 @@ function makeTable(setting, setting_name, setting_value) {
} }
_.each(setting.columns, function(col) { _.each(setting.columns, function(col) {
html += "<td class='row-data'>" html += "<td class='" + Settings.DATA_COL_CLASS + "'>"
if (isArray) { if (isArray) {
html += row colIsArray = _.isArray(row)
colValue = colIsArray ? row : row[col.name]
html += colValue
// for arrays we add a hidden input to this td so that values can be posted appropriately // for arrays we add a hidden input to this td so that values can be posted appropriately
html += "<input type='hidden' name='" + setting_name + "[]' value='" + row + "'/>" html += "<input type='hidden' name='" + setting_name + "[" + indexOrName + "]"
+ (colIsArray ? "" : "." + col.name) + "' value='" + colValue + "'/>"
} else if (row.hasOwnProperty(col.name)) { } else if (row.hasOwnProperty(col.name)) {
html += row[col.name] html += row[col.name]
} }
@ -258,8 +290,9 @@ function makeTable(setting, setting_name, setting_value) {
html += "</td>" html += "</td>"
}) })
html += "<td class='buttons'><span class='glyphicon glyphicon-remove del-row'></span></td>" html += "<td class='buttons'><span class='" + Settings.DEL_ROW_SPAN_CLASSES + "'></span></td>"
html += "</tr>" html += "</tr>"
row_num++ row_num++
}) })
@ -284,12 +317,12 @@ function makeTableInputs(setting) {
} }
_.each(setting.columns, function(col) { _.each(setting.columns, function(col) {
html += "<td class='row-data'name='" + col.name + "'>\ html += "<td class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>\
<input type='text' class='form-control' placeholder='" + (col.key ? col.key : "") + "' value=''>\ <input type='text' class='form-control' placeholder='" + (col.key ? col.key : "") + "' value=''>\
</td>" </td>"
}) })
html += "<td class='buttons'><span class='glyphicon glyphicon-plus add-row'></span></td>" html += "<td class='buttons'><span class='glyphicon glyphicon-plus " + Settings.ADD_ROW_BUTTON_CLASS + "'></span></td>"
html += "</tr>" html += "</tr>"
return html return html
@ -327,19 +360,19 @@ function addTableRow(add_glyphicon) {
var table = row.parents('table') var table = row.parents('table')
var isArray = table.data('setting-type') === 'array' var isArray = table.data('setting-type') === 'array'
var data = row.parent().children(".row-data") var columns = row.parent().children('.' + Settings.DATA_ROW_CLASS)
if (!isArray) { if (!isArray) {
// Check key spaces // Check key spaces
var name = row.children(".key").children("input").val() var key = row.children(".key").children("input").val()
if (name.indexOf(' ') !== -1) { if (key.indexOf(' ') !== -1) {
showErrorMessage("Error", "Key contains spaces") showErrorMessage("Error", "Key contains spaces")
return return
} }
// Check keys with the same name // Check keys with the same name
var equals = false; var equals = false;
_.each(data.children(".key"), function(element) { _.each(columns.children(".key"), function(element) {
if ($(element).text() === name) { if ($(element).text() === key) {
equals = true equals = true
return return
} }
@ -352,12 +385,13 @@ function addTableRow(add_glyphicon) {
// Check empty fields // Check empty fields
var empty = false; var empty = false;
_.each(row.children(".row-data").children("input"), function(element) { _.each(row.children('.' + Settings.DATA_COL_CLASS + ' input'), function(element) {
if ($(element).val().length === 0) { if ($(element).val().length === 0) {
empty = true empty = true
return return
} }
}) })
if (empty) { if (empty) {
showErrorMessage("Error", "Empty field(s)") showErrorMessage("Error", "Empty field(s)")
return return
@ -368,14 +402,14 @@ function addTableRow(add_glyphicon) {
// Change input row to data row // Change input row to data row
var table = row.parents("table") var table = row.parents("table")
var setting_name = table.attr("name") var setting_name = table.attr("name")
var full_name = setting_name + "." + name var full_name = setting_name + "." + key
row.addClass("row-data new-row") row.addClass(Settings.DATA_ROW_CLASS + " " + Settings.NEW_ROW_CLASS)
row.removeClass("inputs") row.removeClass("inputs")
_.each(row.children(), function(element) { _.each(row.children(), function(element) {
if ($(element).hasClass("numbered")) { if ($(element).hasClass("numbered")) {
// Index row // Index row
var numbers = data.children(".numbered") var numbers = columns.children(".numbered")
if (numbers.length > 0) { if (numbers.length > 0) {
$(element).html(parseInt(numbers.last().text()) + 1) $(element).html(parseInt(numbers.last().text()) + 1)
} else { } else {
@ -384,19 +418,25 @@ function addTableRow(add_glyphicon) {
} else if ($(element).hasClass("buttons")) { } else if ($(element).hasClass("buttons")) {
// Change buttons // Change buttons
var span = $(element).children("span") var span = $(element).children("span")
span.removeClass("glyphicon-ok add-row") span.removeClass(Settings.ADD_ROW_SPAN_CLASSES)
span.addClass("glyphicon-remove del-row") span.addClass(Settings.DEL_ROW_SPAN_CLASSES)
} else if ($(element).hasClass("key")) { } else if ($(element).hasClass("key")) {
var input = $(element).children("input") var input = $(element).children("input")
$(element).html(input.val()) $(element).html(input.val())
input.remove() input.remove()
} else if ($(element).hasClass("row-data")) { } else if ($(element).hasClass(Settings.DATA_COL_CLASS)) {
// Hide inputs // Hide inputs
var input = $(element).children("input") var input = $(element).children("input")
input.attr("type", "hidden") input.attr("type", "hidden")
if (isArray) { if (isArray) {
input.attr("name", setting_name) var row_index = row.siblings('.' + Settings.DATA_ROW_CLASS).length
var key = $(element).attr('name')
// are there multiple columns or just one?
// with multiple we have an array of Objects, with one we have an array of whatever the value type is
var num_columns = row.children('.' + Settings.DATA_COL_CLASS).length
input.attr("name", setting_name + "[" + row_index + "]" + (num_columns > 1 ? "." + key : ""))
} else { } else {
input.attr("name", full_name + "." + $(element).attr("name")) input.attr("name", full_name + "." + $(element).attr("name"))
} }
@ -415,6 +455,9 @@ function addTableRow(add_glyphicon) {
if (isArray) { if (isArray) {
updateDataChangedForSiblingRows(row, true) updateDataChangedForSiblingRows(row, true)
// the addition of any table row should remove the empty-array-row
row.siblings('.empty-array-row').remove()
} }
badgeSidebarForDifferences($(table)) badgeSidebarForDifferences($(table))
@ -432,7 +475,7 @@ function deleteTableRow(delete_glyphicon) {
// this is a hash row, so we empty it but leave the hidden input blank so it is cleared when we save // this is a hash row, so we empty it but leave the hidden input blank so it is cleared when we save
row.empty() row.empty()
row.html("<input type='hidden' class='form-control' name='" + table.attr("name") + "' data-changed='true' value=''>"); row.html("<input type='hidden' class='form-control' name='" + table.attr("name") + "' data-changed='true' value=''>");
} else if (table.find('tr.row-data').length > 1) { } else if (table.find('.' + Settings.DATA_ROW_CLASS).length > 1) {
updateDataChangedForSiblingRows(row) updateDataChangedForSiblingRows(row)
// this isn't the last row - we can just remove it // this isn't the last row - we can just remove it
@ -441,6 +484,9 @@ function deleteTableRow(delete_glyphicon) {
// this is the last row, we can't remove it completely since we need to post an empty array // this is the last row, we can't remove it completely since we need to post an empty array
row.empty() row.empty()
row.removeClass(Settings.DATA_ROW_CLASS).removeClass(Settings.NEW_ROW_CLASS)
row.addClass('empty-array-row')
row.html("<input type='hidden' class='form-control' name='" + table.attr("name").replace('[]', '') row.html("<input type='hidden' class='form-control' name='" + table.attr("name").replace('[]', '')
+ "' data-changed='true' value=''>"); + "' data-changed='true' value=''>");
} }
@ -450,7 +496,7 @@ function deleteTableRow(delete_glyphicon) {
} }
function updateDataChangedForSiblingRows(row, forceTrue) { function updateDataChangedForSiblingRows(row, forceTrue) {
// anytime a new row is added to an array we need to set data-changed for all sibling row-data inputs to true // anytime a new row is added to an array we need to set data-changed for all sibling row inputs to true
// unless it matches the inital set of values // unless it matches the inital set of values
if (!forceTrue) { if (!forceTrue) {
@ -469,14 +515,13 @@ function updateDataChangedForSiblingRows(row, forceTrue) {
isTrue = true isTrue = true
} }
row.siblings('.row-data').each(function(){ row.siblings('.' + Settings.DATA_ROW_CLASS).each(function(){
var hiddenInput = $(this).find('td.row-data input') var hiddenInput = $(this).find('td.' + Settings.DATA_COL_CLASS + ' input')
if (isTrue) { if (isTrue) {
hiddenInput.attr('data-changed', isTrue) hiddenInput.attr('data-changed', isTrue)
} else { } else {
hiddenInput.removeAttr('data-changed') hiddenInput.removeAttr('data-changed')
} }
}) })
} }