diff options
Diffstat (limited to 'extensions/TrackingFlags/web/js/admin.js')
-rw-r--r-- | extensions/TrackingFlags/web/js/admin.js | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/extensions/TrackingFlags/web/js/admin.js b/extensions/TrackingFlags/web/js/admin.js new file mode 100644 index 000000000..58bdd294f --- /dev/null +++ b/extensions/TrackingFlags/web/js/admin.js @@ -0,0 +1,440 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This Source Code Form is "Incompatible With Secondary Licenses", as + * defined by the Mozilla Public License, v. 2.0. */ + +// init + +var Dom = YAHOO.util.Dom; +var Event = YAHOO.util.Event; + +Event.onDOMReady(function() { + try { + if (Dom.get('flag_list')) { + filter_flag_list(Dom.get('filter').checked); + } + else { + if (!JSON) + JSON = YAHOO.lang.JSON; + Event.addListener('flag_name', 'change', change_flag_name, Dom.get('flag_name')); + Event.addListener('flag_desc', 'change', change_string_value, Dom.get('flag_desc')); + Event.addListener('flag_type', 'change', change_select_value, Dom.get('flag_type')); + Event.addListener('flag_sort', 'change', change_int_value, Dom.get('flag_sort')); + + Event.addListener('product', 'change', function() { + if (Dom.get('product').value == '') + Dom.get('component').options.length = 0; + }); + + update_flag_values(); + update_flag_visibility(); + tag_missing_values(); + } + } catch(e) { + console.error(e); + } +}); + +// field + +function change_flag_name(e, o) { + change_string_value(e, o); + if (o.value == '') + return; + o.value = o.value.replace(/[^a-z0-9_]/g, '_'); + if (!o.value.match(/^cf_/)) + o.value = 'cf_' + o.value; + if (Dom.get('flag_desc').value == '') { + var desc = o.value; + desc = desc.replace(/^cf_/, ''); + desc = desc.replace(/_/g, '-'); + Dom.get('flag_desc').value = desc; + tag_missing_value(Dom.get('flag_desc')); + } +} + +function inc_field(id, amount) { + var el = Dom.get(id); + el.value = el.value.match(/-?\d+/) * 1 + amount; + change_int_value(null, el); +} + +// values + +function update_flag_values() { + // update the values table from the flag_values global + + var tbl = Dom.get('flag_values'); + if (!tbl) + return; + + // remove current entries + while (tbl.rows.length > 3) { + tbl.deleteRow(2); + } + + // add all entries + + for (var i = 0, l = flag_values.length; i < l; i++) { + var value = flag_values[i]; + + var row = tbl.insertRow(2 + (i * 2)); + var cell; + + // value + cell = row.insertCell(0); + if (value.value == '---') { + cell.innerHTML = '---'; + } + else { + var inputEl = document.createElement('input'); + inputEl.id = 'value_' + i; + inputEl.type = 'text'; + inputEl.className = 'option_value'; + inputEl.value = value.value; + Event.addListener(inputEl, 'change', change_string_value, inputEl); + Event.addListener(inputEl, 'change', function(e, o) { + flag_values[o.id.match(/\d+$/)].value = o.value; + tag_invalid_values(); + }, inputEl); + Event.addListener(inputEl, 'keyup', function(e, o) { + if ((e.key || e.keyCode) == 27 && o.value == '') + remove_value(o.id.match(/\d+$/)); + }, inputEl); + cell.appendChild(inputEl); + } + + // setter + cell = row.insertCell(1); + var selectEl = document.createElement('select'); + selectEl.id = 'setter_' + i; + Event.addListener(selectEl, 'change', change_select_value, selectEl); + var optionEl = document.createElement('option'); + optionEl.value = ''; + selectEl.appendChild(optionEl); + for (var j = 0, m = groups.length; j < m; j++) { + var group = groups[j]; + optionEl = document.createElement('option'); + optionEl.value = group.id; + optionEl.innerHTML = YAHOO.lang.escapeHTML(group.name); + optionEl.selected = group.id == value.setter_group_id; + selectEl.appendChild(optionEl); + } + Event.addListener(selectEl, 'change', function(e, o) { + flag_values[o.id.match(/\d+$/)].setter_group_id = o.value; + tag_invalid_values(); + }, selectEl); + cell.appendChild(selectEl); + + // active + cell = row.insertCell(2); + if (value.value == '---') { + cell.innerHTML = 'Yes'; + } + else { + var inputEl = document.createElement('input'); + inputEl.type = 'checkbox'; + inputEl.id = 'is_active_' + i; + inputEl.checked = value.is_active; + Event.addListener(inputEl, 'change', function(e, o) { + flag_values[o.id.match(/\d+$/)].is_active = o.checked; + }, inputEl); + cell.appendChild(inputEl); + } + + // actions + cell = row.insertCell(3); + var html = + '[' + + (i == 0 + ? '<span class="txt_icon"> - </span>' + : '<a class="txt_icon" href="#" onclick="value_move_up(' + i + ');return false"> Δ </a>' + ) + + '|' + + (i == l - 1 + ? '<span class="txt_icon"> - </span>' + : '<a class="txt_icon" href="#" onclick="value_move_down(' + i + ');return false"> ∇ </a>' + ); + if (value.value != '---') { + var lbl = value.comment == '' ? 'Set Comment' : 'Edit Comment'; + html += + '|<a href="#" onclick="remove_value(' + i + ');return false">Remove</a>' + + '|<a href="#" onclick="toggle_value_comment(this, ' + i + ');return false">' + lbl + '</a>' + + } + html += ' ]'; + cell.innerHTML = html; + + row = tbl.insertRow(3 + (i * 2)); + row.className = 'bz_default_hidden'; + row.id = 'comment_row_' + i; + cell = row.insertCell(0); + cell = row.insertCell(1); + cell.colSpan = 3; + var ta = document.createElement('textarea'); + ta.className = 'value_comment'; + ta.id = 'value_comment_' + i; + ta.rows = 5; + ta.value = value.comment; + cell.appendChild(ta); + Event.addListener(ta, 'blur', function(e, idx) { + flag_values[idx].comment = e.target.value; + }, i); + } + + tag_invalid_values(); +} + +function tag_invalid_values() { + // reset + for (var i = 0, l = flag_values.length; i < l; i++) { + Dom.removeClass('value_' + i, 'admin_error'); + } + + for (var i = 0, l = flag_values.length; i < l; i++) { + // missing + if (flag_values[i].value == '') + Dom.addClass('value_' + i, 'admin_error'); + if (!flag_values[i].setter_group_id) + Dom.addClass('setter_' + i, 'admin_error'); + + // duplicate values + for (var j = i; j < l; j++) { + if (i != j && flag_values[i].value == flag_values[j].value) { + Dom.addClass('value_' + i, 'admin_error'); + Dom.addClass('value_' + j, 'admin_error'); + } + } + } +} + +function value_move_up(idx) { + if (idx == 0) + return; + var tmp = flag_values[idx]; + flag_values[idx] = flag_values[idx - 1]; + flag_values[idx - 1] = tmp; + update_flag_values(); +} + +function value_move_down(idx) { + if (idx == flag_values.length - 1) + return; + var tmp = flag_values[idx]; + flag_values[idx] = flag_values[idx + 1]; + flag_values[idx + 1] = tmp; + update_flag_values(); +} + +function add_value() { + var value = new Object(); + value.id = 0; + value.value = ''; + value.setter_group_id = ''; + value.is_active = true; + var idx = flag_values.length; + flag_values[idx] = value; + update_flag_values(); + Dom.get('value_' + idx).focus(); +} + +function remove_value(idx) { + flag_values.splice(idx, 1); + update_flag_values(); +} + +function update_value(e, o) { + var i = o.value.match(/\d+/); + flag_values[i].value = o.value; +} + +function toggle_value_comment(btn, idx) { + var row = Dom.get('comment_row_' + idx); + if (Dom.hasClass(row, 'bz_default_hidden')) { + Dom.removeClass(row, 'bz_default_hidden'); + btn.innerHTML = 'Hide Comment'; + Dom.get('value_comment_' + idx).select(); + Dom.get('value_comment_' + idx).focus(); + } else { + Dom.addClass(row, 'bz_default_hidden'); + btn.innerHTML = flag_values[idx].comment == '' ? 'Set Comment' : 'Edit Comment'; + } +} + +// visibility + +function update_flag_visibility() { + // update the visibility table from the flag_visibility global + + var tbl = Dom.get('flag_visibility'); + if (!tbl) + return; + + // remove current entries + while (tbl.rows.length > 3) { + tbl.deleteRow(2); + } + + // show something if there aren't any components + + if (!flag_visibility.length) { + var row = tbl.insertRow(2); + var cell = row.insertCell(0); + cell.innerHTML = '<i class="admin_error_text">missing</i>'; + } + + // add all entries + + for (var i = 0, l = flag_visibility.length; i < l; i++) { + var visibility = flag_visibility[i]; + + var row = tbl.insertRow(2 + i); + var cell; + + // product + cell = row.insertCell(0); + cell.innerHTML = visibility.product; + + // component + cell = row.insertCell(1); + cell.innerHTML = visibility.component + ? visibility.component + : '<i>-- Any --</i>'; + + // actions + cell = row.insertCell(2); + cell.innerHTML = '[ <a href="#" onclick="remove_visibility(' + i + ');return false">Remove</a> ]'; + } +} + +function add_visibility() { + // validation + var product = Dom.get('product').value; + var component = Dom.get('component').value; + if (!product) { + alert('Please select a product.'); + return; + } + + // don't allow duplicates + for (var i = 0, l = flag_visibility.length; i < l; i++) { + if (flag_visibility[i].product == product && flag_visibility[i].component == component) { + Dom.get('product').value = ''; + Dom.get('component').options.length = 0; + return; + } + } + + if (component == '') { + // if we're adding an "any" component, remove non-any components + for (var i = 0; i < flag_visibility.length; i++) { + var visibility = flag_visibility[i]; + if (visibility.product == product) { + flag_visibility.splice(i, 1); + i--; + } + } + } + else { + // don't add non-any components if an "any" component exists + for (var i = 0, l = flag_visibility.length; i < l; i++) { + var visibility = flag_visibility[i]; + if (visibility.product == product && !visibility.component) + return; + } + } + + // add to model + var visibility = new Object(); + visibility.id = 0; + visibility.product = product; + visibility.component = component; + flag_visibility[flag_visibility.length] = visibility; + + // update ui + update_flag_visibility(); + Dom.get('product').value = ''; + Dom.get('component').options.length = 0; +} + +function remove_visibility(idx) { + flag_visibility.splice(idx, 1); + update_flag_visibility(); +} + +// validation and submission + +function tag_missing_values() { + var els = document.getElementsByTagName('input'); + for (var i = 0, l = els.length; i < l; i++) { + var el = els[i]; + if (el.id.match(/^(flag|value)_/)) + tag_missing_value(el); + } + tag_missing_value(Dom.get('flag_type')); +} + +function tag_missing_value(el) { + el.value == '' + ? Dom.addClass(el, 'admin_error') + : Dom.removeClass(el, 'admin_error'); +} + +function delete_confirm(flag) { + if (confirm('Are you sure you want to delete the flag ' + flag + ' ?')) { + Dom.get('delete').value = 1; + return true; + } + else { + return false; + } +} + +function on_submit() { + if (Dom.get('delete') && Dom.get('delete').value) + return; + // let perl manage most validation errors, because they are clearly marked + // the exception is an empty visibility list, so catch that here as well + if (!flag_visibility.length) { + alert('You must provide at least one product for visibility.'); + return false; + } + + Dom.get('values').value = JSON.stringify(flag_values); + Dom.get('visibility').value = JSON.stringify(flag_visibility); + return true; +} + +// flag list + +function filter_flag_list(show_disabled) { + var rows = Dom.getElementsByClassName('flag_row', 'tr', 'flag_list'); + for (var i = 0, l = rows.length; i < l; i++) { + if (Dom.hasClass(rows[i], 'is_disabled')) { + if (show_disabled) { + Dom.removeClass(rows[i], 'bz_default_hidden'); + } + else { + Dom.addClass(rows[i], 'bz_default_hidden'); + } + } + } +} + +// utils + +function change_string_value(e, o) { + o.value = YAHOO.lang.trim(o.value); + tag_missing_value(o); +} + +function change_int_value(e, o) { + o.value = o.value.match(/-?\d+/); + tag_missing_value(o); +} + +function change_select_value(e, o) { + tag_missing_value(o); +} |