summaryrefslogtreecommitdiffstats
path: root/install/ui/src/freeipa/widget.js
diff options
context:
space:
mode:
Diffstat (limited to 'install/ui/src/freeipa/widget.js')
-rw-r--r--install/ui/src/freeipa/widget.js3559
1 files changed, 3559 insertions, 0 deletions
diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js
new file mode 100644
index 000000000..8d2239d89
--- /dev/null
+++ b/install/ui/src/freeipa/widget.js
@@ -0,0 +1,3559 @@
+/*jsl:import ipa.js */
+/* Authors:
+ * Endi Sukma Dewata <edewata@redhat.com>
+ * Adam Young <ayoung@redhat.com>
+ * Pavel Zuna <pzuna@redhat.com>
+ *
+ * Copyright (C) 2010 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* REQUIRES: ipa.js */
+
+IPA.checkbox_column_width = 22;
+IPA.required_indicator = '*';
+
+IPA.widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.name = spec.name;
+ that.id = spec.id;
+ that.label = spec.label;
+ that.tooltip = spec.tooltip;
+ that.measurement_unit = spec.measurement_unit;
+ that.entity = IPA.get_entity(spec.entity); //some old widgets still need it
+ that.facet = spec.facet;
+
+ that.create = function(container) {
+ container.addClass('widget');
+ that.container = container;
+ };
+
+ that.clear = function() {
+ };
+
+ that.set_visible = function(visible) {
+
+ if (visible) {
+ that.container.show();
+ } else {
+ that.container.hide();
+ }
+ };
+
+ that.build_child = function(spec, factory) {
+
+ if (typeof spec === 'function') {
+ spec = {
+ factory: spec
+ };
+ }
+
+ $.extend(spec, {
+ parent: that,
+ entity: that.entity,
+ facet: that.facet
+ });
+
+ var child = IPA.build(spec, factory);
+ return child;
+ };
+
+ that.widget_create = that.create;
+
+ return that;
+};
+
+IPA.input_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.width = spec.width;
+ that.height = spec.height;
+
+ that.undo = spec.undo === undefined ? true : spec.undo;
+ that.writable = spec.writable === undefined ? true : spec.writable;
+ that.read_only = spec.read_only;
+ that.hidden = spec.hidden;
+
+ //events
+ //each widget can contain several events
+ that.value_changed = IPA.observer();
+ that.undo_clicked = IPA.observer();
+
+
+ that.create_error_link = function(container) {
+ container.append(' ');
+
+ $('<span/>', {
+ name: 'error_link',
+ 'class': 'ui-state-error ui-corner-all',
+ style: 'display:none'
+ }).appendTo(container);
+ };
+
+ that.create_required = function(container) {
+ that.required_indicator = $('<span/>', {
+ 'class': 'required-indicator',
+ text: IPA.required_indicator,
+ style: 'display: none;'
+ }).appendTo(container);
+ };
+
+ that.update = function() {
+ };
+
+ /**
+ * This function saves the values entered in the UI.
+ * It returns the values in an array, or null if
+ * the field should not be saved.
+ */
+ that.save = function() {
+ return [];
+ };
+
+ /**
+ * This function creates an undo link in the container.
+ * On_undo is a link click callback. It can be specified to custom
+ * callback. If a callback isn't set, default callback is used. If
+ * spefified to value other than a function, no callback is registered.
+ */
+ that.create_undo = function(container, on_undo) {
+ container.append(' ');
+
+ that.undo_span =
+ $('<span/>', {
+ name: 'undo',
+ style: 'display: none;',
+ 'class': 'ui-state-highlight ui-corner-all undo',
+ html: IPA.messages.widget.undo
+ }).appendTo(container);
+
+ if(on_undo === undefined) {
+ on_undo = function() {
+ that.undo_clicked.notify([], that);
+ };
+ }
+
+ if(typeof on_undo === 'function') {
+ that.undo_span.click(on_undo);
+ }
+ };
+
+ that.get_undo = function() {
+ return $(that.undo_span);
+ };
+
+ that.show_undo = function() {
+ that.get_undo().css('display', 'inline');
+ };
+
+ that.hide_undo = function() {
+ $(that.undo_span).css('display', 'none');
+ };
+
+ that.get_error_link = function() {
+ return $('span[name="error_link"]', that.container);
+ };
+
+ that.show_error = function(message) {
+ var error_link = that.get_error_link();
+ error_link.html(message);
+ error_link.css('display', 'block');
+ };
+
+ that.hide_error = function() {
+ var error_link = that.get_error_link();
+ error_link.css('display', 'none');
+ };
+
+ that.set_required = function(required) {
+
+ that.required = required;
+
+ if (that.required_indicator) {
+ that.required_indicator.css('display', that.required ? 'inline' : 'none');
+ }
+ };
+
+ that.on_value_changed = function() {
+ var value = that.save();
+ that.value_changed.notify([value], that);
+ };
+
+ that.focus_input = function() {};
+ that.set_deleted = function() {};
+
+ // methods that should be invoked by subclasses
+ that.widget_hide_error = that.hide_error;
+ that.widget_show_error = that.show_error;
+
+ return that;
+};
+
+/*uses a browser specific technique to select a range.*/
+IPA.select_range = function(input,start, end) {
+ input.focus();
+ if (input[0].setSelectionRange) {
+ input[0].setSelectionRange(start, end);
+ } else if (input[0].createTextRange) {
+ var range = input[0].createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', end);
+ range.moveStart('character', start);
+ range.select();
+ }
+};
+
+
+IPA.text_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ that.size = spec.size || 30;
+ that.input_type = spec.input_type || 'text';
+
+ that.select_range = function(start, end){
+ IPA.select_range(that.input, start, end);
+ };
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ container.addClass('text-widget');
+
+ that.display_control = $('<label/>', {
+ name: that.name,
+ style: 'display: none;'
+ }).appendTo(container);
+
+ that.input = $('<input/>', {
+ type: that.input_type,
+ name: that.name,
+ disabled: that.disabled,
+ size: that.size,
+ title: that.tooltip,
+ keyup: function() {
+ that.on_value_changed();
+ }
+ }).appendTo(container);
+
+ that.input.bind('input', function() {
+ that.on_value_changed();
+ });
+
+ if (that.undo) {
+ that.create_undo(container);
+ }
+
+ that.create_error_link(container);
+ };
+
+ that.update = function(values) {
+ var value = values && values.length ? values[0] : '';
+
+ if (that.read_only || !that.writable) {
+ that.display_control.text(value);
+ that.display_control.css('display', 'inline');
+ that.input.css('display', 'none');
+
+ } else {
+ that.input.val(value);
+ that.display_control.css('display', 'none');
+ that.input.css('display', 'inline');
+ }
+ };
+
+ that.save = function() {
+ if (that.read_only || !that.writable) {
+ return null;
+
+ } else {
+ var value = that.input.val();
+ return value === '' ? [] : [value];
+ }
+ };
+
+ that.set_enabled = function(value) {
+
+ that.input.prop('disabled', !value);
+ };
+
+ that.clear = function() {
+ that.input.val('');
+ that.display_control.text('');
+ };
+
+ that.focus_input = function() {
+ that.input.focus();
+ };
+
+ that.set_deleted = function(deleted) {
+ if(deleted) {
+ that.input.addClass('strikethrough');
+ } else {
+ that.input.removeClass('strikethrough');
+ }
+ };
+
+ // methods that should be invoked by subclasses
+ that.text_load = that.load;
+
+ return that;
+};
+
+IPA.password_widget = function(spec) {
+
+ spec = spec || {};
+ spec.input_type = 'password';
+
+ var that = IPA.text_widget(spec);
+ return that;
+};
+
+IPA.multivalued_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ that.widget_factory = spec.widget_factory || IPA.text_widget;
+ that.size = spec.size || 30;
+ that.undo_control;
+ that.initialized = false;
+
+ that.rows = [];
+
+ that.on_child_value_changed = function(row) {
+ if (that.test_dirty_row(row)) {
+ row.widget.show_undo();
+ row.remove_link.hide();
+ } else {
+ row.widget.hide_undo();
+ row.remove_link.show();
+ }
+
+ that.value_changed.notify([], that);
+ };
+
+ that.on_child_undo_clicked = function(row) {
+ if (row.is_new) {
+ that.remove_row(row);
+ } else {
+ //reset
+ row.widget.update(row.original_values);
+ row.widget.set_deleted(false);
+ row.deleted = false;
+ row.remove_link.show();
+ }
+
+ row.widget.hide_undo();
+ that.value_changed.notify([], that);
+ };
+
+ that.hide_undo = function() {
+
+ $(that.undo_span).css('display', 'none');
+ for(var i=0; i<that.rows.length; i++) {
+ var row = that.rows[i];
+ row.widget.hide_undo();
+ row.remove_link.show();
+ }
+ };
+
+
+ that.update_child = function(values, index) {
+ that.rows[index].widget.update(values);
+ };
+
+ that.show_child_undo = function(index) {
+ that.rows[index].widget.show_undo();
+ that.show_undo();
+ };
+
+ that.hide_error = function() {
+
+ that.widget_hide_error();
+
+ for (var i=0; i<that.rows.length; i++) {
+ that.rows[i].widget.hide_error();
+ }
+ };
+
+ that.show_child_error = function(index, error) {
+
+ that.rows[index].widget.show_error(error);
+ };
+
+ that.get_saved_value_row_index = function(index) {
+
+ for (var i=0; i<that.rows.length;i++) {
+
+ if(that.rows[i].deleted) index++;
+ if(i === index) return i;
+ }
+
+ return -1; //error state
+ };
+
+ that.save = function() {
+
+ var values = [];
+
+ for (var i=0; i<that.rows.length;i++) {
+
+ if(that.rows[i].deleted) continue;
+
+ values.push(that.extract_child_value(that.rows[i].widget.save()));
+ }
+
+ return values;
+ };
+
+ that.extract_child_value = function(value) {
+
+ if (value instanceof Array) {
+ if (value.length > 0) {
+ return value[0];
+ }
+ return '';
+ }
+
+ if (value) return value;
+
+ return '';
+ };
+
+ that.focus_last = function() {
+ var last_row = that.rows[that.rows.length-1];
+ last_row.widget.focus_input();
+ };
+
+ that.add_row = function(values) {
+ var row = {};
+ that.rows.push(row);
+ var row_index = that.rows.length - 1;
+ row.is_new = that.initialized;
+
+ row.container = $('<div/>', { name: 'value'});
+
+ row.widget = that.widget_factory({
+ name: that.name+'-'+row_index,
+ undo: that.undo || row.is_new,
+ read_only: that.read_only,
+ writable: that.writable
+ });
+
+ row.widget.create(row.container);
+
+ row.original_values = values;
+ row.widget.update(values);
+
+ row.widget.value_changed.attach(function() {
+ that.on_child_value_changed(row);
+ });
+ row.widget.undo_clicked.attach(function() {
+ that.on_child_undo_clicked(row);
+ });
+
+ row.remove_link = $('<a/>', {
+ name: 'remove',
+ href: 'jslink',
+ title: IPA.messages.buttons.remove,
+ html: IPA.messages.buttons.remove,
+ click: function () {
+ that.remove_row(row);
+ that.value_changed.notify([], that);
+ return false;
+ }
+ }).appendTo(row.container);
+
+ if(row.is_new) {
+ row.remove_link.hide();
+ row.widget.show_undo();
+ that.value_changed.notify([], that);
+ }
+
+ row.container.insertBefore(that.add_link);
+ };
+
+ that.create = function(container) {
+
+ container.addClass('multivalued-widget');
+
+ that.widget_create(container);
+
+ that.create_error_link(container);
+
+ that.add_link = $('<a/>', {
+ name: 'add',
+ href: 'jslink',
+ title: IPA.messages.buttons.add,
+ html: IPA.messages.buttons.add,
+ click: function() {
+ that.add_row('');
+ that.focus_last();
+ return false;
+ }
+ }).appendTo(container);
+
+
+ container.append(' ');
+
+ that.undo_span = $('<span/>', {
+ name: 'undo_all',
+ style: 'display: none;',
+ 'class': 'ui-state-highlight ui-corner-all undo',
+ html: IPA.messages.widget.undo_all,
+ click: function() {
+ that.undo_clicked.notify([], that);
+ }
+ }).appendTo(container);
+ };
+
+ that.remove_row = function(row) {
+ if (row.is_new) {
+ row.container.remove();
+ that.rows.splice(that.rows.indexOf(row), 1); //not supported by IE<9
+ } else {
+ row.deleted = true;
+ row.widget.set_deleted(true);
+ row.remove_link.hide();
+ row.widget.show_undo();
+ }
+ };
+
+ that.remove_rows = function() {
+ for(var i=0; i < that.rows.length; i++) {
+ that.rows[i].container.remove();
+ }
+ that.rows = [];
+ };
+
+ that.clear = function() {
+ that.remove_rows();
+ };
+
+ that.test_dirty_row = function(row) {
+
+ if (row.deleted || row.is_new) return true;
+
+ var values = row.widget.save();
+
+ if (row.original_values.length !== values.length) return true;
+
+ for (var i=0; i<values.length; i++) {
+ if (values[i] !== row.original_values[i]) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ that.test_dirty = function() {
+ var dirty = false;
+
+ for(var i=0; i < that.rows.length; i++) {
+ dirty = dirty || that.test_dirty_row(that.rows[i]);
+ }
+
+ return dirty;
+ };
+
+ that.update = function(values, index) {
+
+ var value;
+
+ if (index === undefined) {
+
+ that.initialized = false;
+ that.remove_rows();
+
+ for (var i=0; i<values.length; i++) {
+ value = [values[i]];
+ if(value[0]) {
+ that.add_row(value);
+ }
+ }
+
+ that.initialized = true;
+
+ if (that.read_only || !that.writable) {
+ that.add_link.css('display', 'none');
+ } else {
+ that.add_link.css('display', 'inline');
+ }
+
+ } else {
+ value = values[index];
+ var row = that.rows[index];
+ row.widget.update(values);
+ }
+ };
+
+ return that;
+};
+
+IPA.checkbox_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ // default value
+ that.checked = spec.checked || false;
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ container.addClass('checkbox-widget');
+
+ that.input = $('<input/>', {
+ type: 'checkbox',
+ name: that.name,
+ checked: that.checked,
+ title: that.tooltip,
+ change: function() {
+ that.value_changed.notify([that.save()], that);
+ }
+ }).appendTo(container);
+
+ if (that.undo) {
+ that.create_undo(container);
+ }
+
+ that.create_error_link(container);
+ };
+
+ that.save = function() {
+ var value = that.input.is(':checked');
+ return [value];
+ };
+
+ that.update = function(values) {
+ var value;
+
+ if (values && values.length) {
+ value = values[0];
+ }
+
+ if (typeof value !== 'boolean') {
+ // use default value
+ value = that.checked;
+ }
+
+ that.input.prop('checked', value);
+ };
+
+ that.clear = function() {
+ that.input.prop('checked', false);
+ };
+
+ that.checkbox_save = that.save;
+
+ return that;
+};
+
+IPA.checkboxes_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ that.options = spec.options || [];
+ that.direction = spec.direction || 'vertical';
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ container.addClass('checkboxes-widget');
+
+ var vertical = that.direction === 'vertical';
+
+ for (var i=0; i<that.options.length; i++) {
+ var option = that.options[i];
+ $('<input/>', {
+ type: 'checkbox',
+ name: that.name,
+ value: option.value,
+ title: that.tooltip
+ }).appendTo(container);
+
+ $('<label/>', {
+ text: option.label,
+ title: that.tooltip
+ }).appendTo(container);
+
+ if (vertical) {
+ $('<br/>').appendTo(container);
+ }
+ }
+
+ if (that.undo) {
+ that.create_undo(container);
+ }
+
+ var input = $('input[name="'+that.name+'"]', that.container);
+ input.change(function() {
+ that.value_changed.notify([that.save()], that);
+ });
+
+ that.create_error_link(container);
+ };
+
+ that.save = function() {
+ var values = [];
+
+ $('input[name="'+that.name+'"]:checked', that.container).each(function() {
+ values.push($(this).val());
+ });
+
+ return values;
+ };
+
+ that.update = function(values) {
+ var inputs = $('input[name="'+that.name+'"]', that.container);
+ inputs.prop('checked', false);
+
+ for (var j=0; values && j<values.length; j++) {
+ var value = values[j];
+ var input = $('input[name="'+that.name+'"][value="'+value+'"]', that.container);
+ if (!input.length) continue;
+ input.prop('checked', true);
+ }
+ };
+
+ that.clear = function() {
+ $('input[name="'+that.name+'"]').prop('checked', false);
+ };
+
+ that.add_option = function(option) {
+ that.options.push(option);
+ };
+
+ // methods that should be invoked by subclasses
+ that.checkboxes_update = that.update;
+
+ return that;
+};
+
+IPA.radio_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ that.default_value = spec.default_value;
+ that.options = spec.options;
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ container.addClass('radio-widget');
+
+ var name = IPA.html_util.get_next_id(that.name+'-');
+ that.selector = 'input[name="'+name+'"]';
+
+ for (var i=0; i<that.options.length; i++) {
+ var option = that.options[i];
+
+ var id = name+'-'+i;
+
+ $('<input/>', {
+ id: id,
+ type: 'radio',
+ name: name,
+ value: option.value
+ }).appendTo(container);
+
+ $('<label/>', {
+ text: option.label,
+ 'for': id
+ }).appendTo(container);
+ }
+
+ if (that.undo) {
+ that.create_undo(container);
+ }
+
+ var input = $(that.selector, that.container);
+ input.change(function() {
+ that.value_changed.notify([that.save()], that);
+ });
+
+ that.create_error_link(container);
+ };
+
+ that.save = function() {
+ var input = $(that.selector+':checked', that.container);
+ if (!input.length) return [];
+ return [input.val()];
+ };
+
+ that.update = function(values) {
+
+ $(that.selector, that.container).each(function() {
+ var input = this;
+ input.checked = false;
+ });
+
+ var value = values && values.length ? values[0] : '';
+ var input = $(that.selector+'[value="'+value+'"]', that.container);
+ if (input.length) {
+ input.prop('checked', true);
+ } else if (that.default_value) {
+ input = $(that.selector+'[value="'+that.default_value+'"]', that.container);
+ input.prop('checked', true);
+ }
+
+ that.value_changed.notify([that.save()], that);
+ };
+
+ that.clear = function() {
+ $(that.selector, that.container).prop('checked', false);
+
+ if (that.default_value) {
+ var input = $(that.selector+'[value="'+that.default_value+'"]', that.container);
+ input.prop('checked', true);
+ }
+ };
+
+ // methods that should be invoked by subclasses
+ that.radio_create = that.create;
+ that.radio_save = that.save;
+
+ return that;
+};
+
+IPA.select_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ that.options = spec.options || [];
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ container.addClass('select-widget');
+
+ that.select = $('<select/>', {
+ name: that.name,
+ change: function() {
+ that.value_changed.notify([], that);
+ return false;
+ }
+ }).appendTo(container);
+
+ that.create_options();
+
+ if (that.undo) {
+ that.create_undo(container);
+ }
+
+ that.create_error_link(container);
+ };
+
+ that.create_options = function() {
+
+ that.select.empty();
+
+ for (var i=0; i<that.options.length; i++) {
+ var option = that.options[i];
+
+ $('<option/>', {
+ text: option.label,
+ value: option.value
+ }).appendTo(that.select);
+ }
+ };
+
+ that.save = function() {
+ var value;
+
+ if (that.select) {
+ value = that.select.val() || '';
+ } else if (that.options.length > 0) {
+ value = that.options[0].value; //will be default value
+ }
+
+ return [value];
+ };
+
+ that.update = function(values) {
+ var value = values[0];
+ var option = $('option[value="'+value+'"]', that.select);
+ if (!option.length) return;
+ option.prop('selected', true);
+ };
+
+ that.empty = function() {
+ $('option', that.select).remove();
+ };
+
+ that.clear = function() {
+ $('option', that.select).prop('selected', false);
+ };
+
+ that.set_options_enabled = function(enabled, options) {
+
+ if (!options) {
+ $('option', that.select).prop('disabled', !enabled);
+ } else {
+ for (var i=0; i<options.length;i++) {
+ var value = options[i];
+ var option = $('option[value="'+value+'"]', that.select);
+ option.prop('disabled', !enabled);
+ }
+ }
+ };
+
+ that.enable_options = function(options) {
+
+ that.set_options_enabled(true, options);
+ };
+
+ that.disable_options = function(options) {
+
+ that.set_options_enabled(false, options);
+ };
+
+ // methods that should be invoked by subclasses
+ that.select_save = that.save;
+ that.select_update = that.update;
+
+ return that;
+};
+
+IPA.textarea_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ that.rows = spec.rows || 5;
+ that.cols = spec.cols || 40;
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ container.addClass('textarea-widget');
+
+ that.input = $('<textarea/>', {
+ name: that.name,
+ rows: that.rows,
+ cols: that.cols,
+ disabled: that.disabled,
+ title: that.tooltip,
+ keyup: function() {
+ that.on_value_changed();
+ }
+ }).appendTo(container);
+
+ that.input.bind('input', function() {
+ that.on_value_changed();
+ });
+
+ if (that.undo) {
+ that.create_undo(container);
+ }
+
+ that.create_error_link(container);
+ };
+
+ that.save = function() {
+ var value = that.input.val();
+ return [value];
+ };
+
+ that.update = function(values) {
+ var value = values && values.length ? values[0] : '';
+ that.input.val(value);
+ };
+
+ that.clear = function() {
+ that.input.val('');
+ };
+
+ return that;
+};
+
+IPA.formatter = function(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.type = spec.type; // default is text
+
+ // parse attribute value into a normalized value
+ that.parse = function(value) {
+ return value;
+ };
+
+ // format normalized value
+ that.format = function(value) {
+ return value;
+ };
+
+ return that;
+};
+
+IPA.boolean_formatter = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.formatter(spec);
+
+ that.true_value = spec.true_value || IPA.messages['true'];
+ that.false_value = spec.false_value || IPA.messages['false'];
+ that.show_false = spec.show_false;
+ that.invert_value = spec.invert_value;
+
+ // convert string boolean value into real boolean value, or keep the original value
+ that.parse = function(value) {
+
+ if (value === undefined || value === null) return '';
+
+ if (value instanceof Array) {
+ value = value[0];
+ }
+
+ if (typeof value === 'string') {
+ value = value.toLowerCase();
+
+ if (value === 'true') {
+ value = true;
+ } else if (value === 'false') {
+ value = false;
+ } // leave other values unchanged
+ }
+
+ if (typeof value === 'boolean') {
+ if (that.invert_value) value = !value;
+ }
+
+ return value;
+ };
+
+ // convert boolean value into formatted string, or keep the original value
+ that.format = function(value) {
+
+ if (typeof value === 'boolean') {
+ if (value) {
+ value = that.true_value;
+
+ } else {
+ if (that.show_false) {
+ value = that.false_value;
+ } else {
+ value = '';
+ }
+ }
+ }
+
+ return value;
+ };
+
+ that.boolean_formatter_parse = that.parse;
+ that.boolean_formatter_format = that.format;
+
+ return that;
+};
+
+IPA.boolean_status_formatter = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.boolean_formatter(spec);
+
+ that.true_value = spec.true_value || IPA.messages.status.enabled;
+ that.false_value = spec.false_value || IPA.messages.status.disabled;
+ that.show_false = true;
+ that.type = 'html';
+
+ that.format = function(value) {
+ var status = value ? 'enabled' : 'disabled';
+ var formatted_value = that.boolean_formatter_format(value);
+ formatted_value = '<span class=\"icon '+status+'-icon\"/> '+formatted_value;
+ return formatted_value;
+ };
+
+ return that;
+};
+
+/* Take an LDAP format date in UTC and format it */
+IPA.utc_date_formatter = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.formatter(spec);
+
+ that.format = function(value) {
+
+ if (!value) return '';
+ var date = IPA.parse_utc_date(value);
+ if (!date) return value;
+ return date.toString();
+ };
+
+ return that;
+};
+
+/*
+ The entity name must be set in the spec either directly or via entity.name
+*/
+IPA.column = function (spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.entity = IPA.get_entity(spec.entity);
+ that.name = spec.name;
+
+ that.label = spec.label;
+ that.width = spec.width;
+ that.primary_key = spec.primary_key;
+ that.link = spec.link;
+ that.formatter = spec.formatter;
+
+ if (!that.entity) {
+ throw {
+ expected: false,
+ message: 'Column created without an entity.'
+ };
+ }
+
+ that.setup = function(container, record, suppress_link) {
+
+ container.empty();
+
+ var value = record[that.name];
+ var type;
+ if (that.formatter) {
+ value = that.formatter.parse(value);
+ value = that.formatter.format(value);
+ type = that.formatter.type;
+ }
+ value = value ? value.toString() : '';
+
+ var c;
+ if (that.link && !suppress_link) {
+ c = $('<a/>', {
+ href: '#'+value,
+ click: function() {
+ return that.link_handler(value);
+ }
+ }).appendTo(container);
+
+ } else {
+ c = container;
+ }
+
+ if (type === 'html') {
+ c.html(value);
+ } else {
+ c.text(value);
+ }
+ };
+
+ that.link_handler = function(value) {
+ return false;
+ };
+
+
+ /*column initialization*/
+ if (that.entity && !that.label) {
+ var metadata = IPA.get_entity_param(that.entity.name, that.name);
+ if (metadata) {
+ that.label = metadata.label;
+ }
+ }
+
+
+ return that;
+};
+
+IPA.table_widget = function (spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ that.scrollable = spec.scrollable;
+ that.selectable = spec.selectable === undefined ? true : spec.selectable;
+ that.save_values = spec.save_values === undefined ? true : spec.save_values;
+ that['class'] = spec['class'];
+
+ that.pagination = spec.pagination;
+ that.current_page = 1;
+ that.total_pages = 1;
+ that.page_length = spec.page_length || 20;
+
+ that.multivalued = spec.multivalued === undefined ? true : spec.multivalued;
+
+ that.columns = $.ordered_map();
+ that.value_attr_name = spec.value_attribute || that.name;
+
+ that.get_columns = function() {
+ return that.columns.values;
+ };
+
+ that.get_column = function(name) {
+ return that.columns.get(name);
+ };
+
+ that.add_column = function(column) {
+ column.entity = that.entity;
+ that.columns.put(column.name, column);
+ };
+
+ that.set_columns = function(columns) {
+ that.clear_columns();
+ for (var i=0; i<columns.length; i++) {
+ that.add_column(columns[i]);
+ }
+ };
+
+ that.clear_columns = function() {
+ that.columns.empty();
+ };
+
+ that.create_column = function(spec) {
+ var column = IPA.column(spec);
+ that.add_column(column);
+ return column;
+ };
+
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ container.addClass('table-widget');
+
+ that.table = $('<table/>', {
+ 'class': 'search-table'
+ }).appendTo(container);
+
+ if (that['class']) that.table.addClass(that['class']);
+
+ if (that.scrollable) {
+ that.table.addClass('scrollable');
+ }
+
+ that.thead = $('<thead/>').appendTo(that.table);
+
+ var tr = $('<tr/>').appendTo(that.thead);
+
+ var th;
+
+ if (that.selectable) {
+ th = $('<th/>', {
+ 'style': 'width: '+IPA.checkbox_column_width+'px;'
+ }).appendTo(tr);
+
+ if (that.multivalued) {
+ var select_all_checkbox = $('<input/>', {
+ type: 'checkbox',
+ name: that.name,
+ title: IPA.messages.search.select_all
+ }).appendTo(th);
+
+ select_all_checkbox.change(function() {
+ if(select_all_checkbox.is(':checked')) {
+ that.select_all();
+ } else {
+ that.unselect_all();
+ }
+ return false;
+ });
+ }
+ }
+ var columns = that.columns.values;
+ var column;
+
+ var columns_without_width = 0;
+ var per_column_space = 16; //cell padding(2x6px), border (2x1px), spacing (2px)
+ var available_width = that.thead.width();
+ available_width -= 2; //first cell spacing
+
+ //subtract checkbox column
+ if(that.selectable) {
+ available_width -= IPA.checkbox_column_width;
+ available_width -= per_column_space;
+ }
+
+ //subtract width of columns with their width set
+ for (i=0; i<columns.length; i++) {
+ column = columns[i];
+ if (column.width) {
+ available_width -= parseInt(
+ column.width.substring(0, column.width.length-2),10);
+ available_width -= per_column_space;
+ } else {
+ columns_without_width++;
+ }
+ }
+
+ //width for columns without width set
+ var new_column_width = (available_width -
+ per_column_space * columns_without_width) /
+ columns_without_width;
+
+
+ //set the new width, now all columns should have width set
+ for (i=0; i<columns.length; i++) {
+ column = columns[i];
+ if (!column.width) {
+ column.width = new_column_width+"px";
+ }
+ }
+
+ for (i=0; i<columns.length; i++) {
+ column = columns[i];
+
+ th = $('<th/>').appendTo(tr);
+
+ th.css('width', column.width);
+ th.css('max-width', column.width);
+
+ var label = column.label;
+
+ $('<div/>', {
+ 'style': 'float: left;',
+ 'html': label
+ }).appendTo(th);
+
+ if (i == columns.length-1) {
+ that.buttons = $('<div/>', {
+ 'name': 'buttons',
+ 'style': 'float: right;'
+ }).appendTo(th);
+ }
+
+ }
+
+ that.tbody = $('<tbody/>').appendTo(that.table);
+
+ // workaround for #2835
+ if ($.browser.msie) {
+ that.tbody.mousedown(function(event) {
+ that.scroll_top = that.tbody.scrollTop();
+ window.setTimeout(function() {
+ if (that.tbody.scrollTop() === 0) {
+ that.tbody.scrollTop(that.scroll_top);
+ }
+ }, 0);
+ });
+ }
+
+ if (that.height) {
+ that.tbody.css('height', that.height);
+ }
+
+ that.row = $('<tr/>');
+
+ var td;
+
+ if (that.selectable) {
+ td = $('<td/>', {
+ 'style': 'width: '+ (IPA.checkbox_column_width + 7) +'px;'
+ }).appendTo(that.row);
+
+ if (that.multivalued) {
+ $('<input/>', {
+ type: 'checkbox',
+ name: that.name,
+ value: ''
+ }).appendTo(td);
+ } else {
+ $('<input/>', {
+ type: 'radio',
+ name: that.name,
+ value: ''
+ }).appendTo(td);
+ }
+ }
+
+ var width;
+
+ for (/* var */ i=0; i<columns.length; i++) {
+ /* var */ column = columns[i];
+
+ td = $('<td/>').appendTo(that.row);
+ if (column.width) {
+ width = parseInt(
+ column.width.substring(0, column.width.length-2),10);
+ width += 7; //data cells lack right padding
+ width += 'px';
+ td.css('width', width);
+ td.css('max-width', width);
+ }
+
+ $('<div/>', {
+ 'name': column.name
+ }).appendTo(td);
+ }
+
+ that.tfoot = $('<tfoot/>').appendTo(that.table);
+
+ tr = $('<tr/>').appendTo(that.tfoot);
+
+ td = $('<td/>', {
+ colspan: columns.length + (that.selectable ? 1 : 0)
+ }).appendTo(tr);
+
+ that.create_error_link(td);
+
+ that.summary = $('<span/>', {
+ 'name': 'summary'
+ }).appendTo(td);
+
+ that.pagination_control = $('<span/>', {
+ 'class': 'pagination-control'
+ }).appendTo(td);
+
+ if (that.pagination) {
+
+ $('<a/>', {
+ text: IPA.messages.widget.prev,
+ name: 'prev_page',
+ click: function() {
+ that.prev_page();
+ return false;
+ }
+ }).appendTo(that.pagination_control);
+
+ that.pagination_control.append(' ');
+
+ $('<a/>', {
+ text: IPA.messages.widget.next,
+ name: 'next_page',
+ click: function() {
+ that.next_page();
+ return false;
+ }
+ }).appendTo(that.pagination_control);
+
+ that.pagination_control.append(' ');
+ that.pagination_control.append(IPA.messages.widget.page);
+ that.pagination_control.append(': ');
+
+ that.current_page_input = $('<input/>', {
+ type: 'text',
+ name: 'current_page',
+ keypress: function(e) {
+ if (e.which == 13) {
+ var page = parseInt(that.current_page_input.val(), 10) || 1;
+ that.set_page(page);
+ }
+ }
+ }).appendTo(that.pagination_control);
+
+ that.pagination_control.append(' / ');
+
+ that.total_pages_span = $('<span/>', {
+ name: 'total_pages'
+ }).appendTo(that.pagination_control);
+ }
+ };
+
+ that.prev_page = function() {
+ if (that.current_page > 1) {
+ that.current_page--;
+ that.refresh();
+ }
+ };
+
+ that.next_page = function() {
+ if (that.current_page < that.total_pages) {
+ that.current_page++;
+ that.refresh();
+ }
+ };
+
+ that.set_page = function(page) {
+ if (page < 1) {
+ page = 1;
+ } else if (page > that.total_pages) {
+ page = that.total_pages;
+ }
+ that.current_page = page;
+ that.current_page_input.val(page);
+ that.refresh();
+ };
+
+ that.select_changed = function() {
+ };
+
+ that.select_all = function() {
+ $('input[name="'+that.name+'"]', that.thead).prop('checked', true).
+ attr('title', IPA.messages.search.unselect_all);
+ $('input[name="'+that.name+'"]', that.tbody).prop('checked', true);
+ that.select_changed();
+ };
+
+ that.unselect_all = function() {
+ $('input[name="'+that.name+'"]', that.thead).prop('checked', false).
+ attr('title', IPA.messages.search.select_all);
+ $('input[name="'+that.name+'"]', that.tbody).prop('checked', false);
+ that.select_changed();
+ };
+
+ that.set_values = function(values) {
+ $('input[name="'+that.name+'"]', that.tbody).prop('checked', false);
+ for (var i=0; values && i<values.length; i++) {
+ var value = values[i];
+ $('input[name="'+that.name+'"][value="'+value+'"]', that.tbody).prop('checked', true);
+ }
+ that.select_changed();
+ };
+
+ that.empty = function() {
+ that.tbody.empty();
+ };
+
+ that.load = function(result) {
+
+ that.empty();
+
+ that.values = result[that.value_attr_name] || [];
+ for (var i=0; i<that.values.length; i++) {
+ var record = that.get_record(result, i);
+ that.add_record(record);
+ }
+ };
+
+ that.update = function(records) {
+
+ that.empty();
+
+ that.values = [];
+ that.records = records;
+
+ for (var i=0; i<records.length; i++) {
+ var record = records[i];
+ that.values.push(record[that.value_attr_name]);
+ that.add_record(record);
+ }
+ };
+
+ that.save = function() {
+ if (that.save_values) {
+ var values = [];
+
+ $('input[name="'+that.name+'"]', that.tbody).each(function() {
+ values.push($(this).val());
+ });
+
+ return values;
+
+ } else {
+ return null;
+ }
+ };
+
+ that.get_selected_values = function() {
+ var values = [];
+
+ $('input[name="'+that.name+'"]:checked', that.tbody).each(function() {
+ values.push($(this).val());
+ });
+
+ return values;
+ };
+
+ that.get_selected_rows = function() {
+ return $('input[name="'+that.name+'"]:checked', that.tbody).closest('tr');
+ };
+
+ that.get_record = function(result, index) {
+
+ var record = {};
+
+ var columns = that.columns.values;
+ for (var i=0; i<columns.length; i++){
+ var name = columns[i].name;
+ var values = result[name];
+ if (!values) continue;
+
+ if (values instanceof Array){
+ record[name] = values[index];
+ } else {
+ record[name] = values;
+ }
+ }
+
+ return record;
+ };
+
+ that.add_record = function(record) {
+
+ var tr = that.row.clone();
+ tr.appendTo(that.tbody);
+
+ $('input[name="'+that.name+'"]', tr).click(function(){
+ that.select_changed();
+ });
+
+ var select_set = false;
+ var value;
+ var columns = that.columns.values;
+
+ for (var i=0; i<columns.length; i++){
+ var column = columns[i];
+
+ value = record[column.name];
+ value = value ? value.toString() : '';
+
+ if (column.primary_key) {
+ $('input[name="'+that.name+'"]', tr).val(value);
+ select_set = true;
+ }
+
+ var div = $('div[name="'+column.name+'"]', tr);
+
+ that.setup_column(column, div, record);
+ }
+
+ if (!select_set) {
+ value = record[that.value_attr_name];
+ value = value ? value.toString() : '';
+ $('input[name="'+that.name+'"]', tr).val(value);
+ }
+
+ return tr;
+ };
+
+ that.set_row_enabled = function(tr, enabled) {
+ if (enabled) {
+ tr.removeClass('disabled');
+ } else {
+ tr.addClass('disabled');
+ }
+ };
+
+ that.setup_column = function(column, div, record) {
+ column.setup(div, record);
+ };
+
+ that.add_rows = function(rows) {
+ for (var i=0; i<rows.length; i++) {
+ var tr = rows[i];
+ $('input', tr).attr('name', that.name);
+ that.tbody.append(tr);
+ }
+ };
+
+ that.remove_selected_rows = function() {
+ var rows = [];
+ that.tbody.children().each(function() {
+ var tr = $(this);
+ if (!$('input[name="'+that.name+'"]', tr).get(0).checked) return;
+ tr.detach();
+ rows.push(tr);
+ });
+ return rows;
+ };
+
+ that.show_error = function(message) {
+ var error_link = that.get_error_link();
+ error_link.html(message);
+ error_link.css('display', 'inline');
+ };
+
+ that.set_enabled = function(enabled) {
+ $('input[name="'+that.name+'"]', that.table).prop('disabled', !enabled);
+ };
+
+ that.clear = function() {
+ that.empty();
+ that.summary.text('');
+ };
+
+ //column initialization
+ if (spec.columns) {
+ for (var i=0; i<spec.columns; i++) {
+ that.create_column(spec.columns[i]);
+ }
+ }
+
+ // methods that should be invoked by subclasses
+ that.table_create = that.create;
+ that.table_load = that.load;
+ that.table_next_page = that.next_page;
+ that.table_prev_page = that.prev_page;
+ that.table_set_enabled = that.set_enabled;
+ that.table_set_page = that.set_page;
+ that.table_show_error = that.show_error;
+ that.table_set_values = that.set_values;
+ that.table_update = that.update;
+
+ return that;
+};
+
+
+IPA.attribute_table_widget = function(spec) {
+
+
+ spec = spec || {};
+ spec.columns = spec.columns || [];
+
+ var that = IPA.table_widget(spec);
+
+ that.attribute_name = spec.attribute_name || that.name;
+ that.adder_dialog_spec = spec.adder_dialog;
+ that.css_class = spec.css_class;
+
+ that.add_command = spec.add_command;
+ that.remove_command = spec.remove_command;
+
+ that.on_add = spec.on_add;
+ that.on_add_error = spec.on_add_error;
+ that.on_remove = spec.on_remove;
+ that.on_remove_error = spec.on_remove_error;
+
+ that.create_column = function(spec) {
+
+ if (typeof spec === 'string') {
+ spec = {
+ name: spec
+ };
+ }
+
+ spec.entity = that.entity;
+
+ var factory = spec.factory || IPA.column;
+
+ var column = factory(spec);
+ that.add_column(column);
+ return column;
+ };
+
+ that.create_columns = function() {
+ that.clear_columns();
+ if (spec.columns) {
+ for (var i=0; i<spec.columns.length; i++) {
+ that.create_column(spec.columns[i]);
+ }
+ }
+
+ that.post_create_columns();
+ };
+
+ that.post_create_columns = function() {
+ };
+
+ that.create_buttons = function(container) {
+
+ that.remove_button = IPA.action_button({
+ name: 'remove',
+ label: IPA.messages.buttons.remove,
+ icon: 'remove-icon',
+ 'class': 'action-button-disabled',
+ click: function() {
+ if (!that.remove_button.hasClass('action-button-disabled')) {
+ that.remove_handler();
+ }
+ return false;
+ }
+ }).appendTo(container);
+
+ that.add_button = IPA.action_button({
+ name: 'add',
+ label: IPA.messages.buttons.add,
+ icon: 'add-icon',
+ click: function() {
+ if (!that.add_button.hasClass('action-button-disabled')) {
+ that.add_handler();
+ }
+ return false;
+ }
+ }).appendTo(container);
+ };
+
+ that.create = function(container) {
+
+ that.create_columns();
+ that.table_create(container);
+ if (that.css_class)
+ container.addClass(that.css_class);
+ that.create_buttons(that.buttons);
+ };
+
+ that.set_enabled = function(enabled) {
+ that.table_set_enabled(enabled);
+ if (enabled) {
+ if(that.add_button) {
+ that.add_button.removeClass('action-button-disabled');
+ }
+ } else {
+ $('.action-button', that.table).addClass('action-button-disabled');
+ that.unselect_all();
+ }
+ that.enabled = enabled;
+ };
+
+ that.select_changed = function() {
+
+ var values = that.get_selected_values();
+
+ if (that.remove_button) {
+ if (values.length === 0) {
+ that.remove_button.addClass('action-button-disabled');
+ } else {
+ that.remove_button.removeClass('action-button-disabled');
+ }
+ }
+ };
+
+ that.add_handler = function() {
+ var facet = that.entity.get_facet();
+
+ if (facet.is_dirty()) {
+ var dialog = IPA.dirty_dialog({
+ entity:that.entity,
+ facet: facet
+ });
+
+ dialog.callback = function() {
+ that.show_add_dialog();
+ };
+
+ dialog.open(that.container);
+
+ } else {
+ that.show_add_dialog();
+ }
+ };
+
+ that.remove_handler = function() {
+ var facet = that.entity.get_facet();
+
+ if (facet.is_dirty()) {
+ var dialog = IPA.dirty_dialog({
+ entity:that.entity,
+ facet: facet
+ });
+
+ dialog.callback = function() {
+ that.show_remove_dialog();
+ };
+
+ dialog.open(that.container);
+
+ } else {
+ that.show_remove_dialog();
+ }
+ };
+
+ that.show_remove_dialog = function() {
+
+ var dialog = that.create_remove_dialog();
+ if (dialog) dialog.open(that.container);
+ };
+
+ that.create_remove_dialog = function() {
+ var selected_values = that.get_selected_values();
+
+ if (!selected_values.length) {
+ var message = IPA.messages.dialogs.remove_empty;
+ alert(message);
+ return null;
+ }
+
+ var dialog = IPA.deleter_dialog({
+ entity: that.entity,
+ values: selected_values
+ });
+
+ dialog.execute = function() {
+ var command = that.create_remove_command(
+ selected_values,
+ function(data, text_status, xhr) {
+ var handler = that.on_remove || that.on_command_success;
+ handler.call(this, data, text_status, xhr);
+ },
+ function(xhr, text_status, error_thrown) {
+ var handler = that.on_remove_error || that.on_command_error;
+ handler.call(this, xhr, text_status, error_thrown);
+ }
+ );
+ command.execute();
+ };
+
+ return dialog;
+ };
+
+ that.on_command_success = function(data) {
+ that.reload_facet(data);
+ };
+
+ that.on_command_error = function() {
+ that.refresh_facet();
+ };
+
+ that.get_pkeys = function() {
+ var pkey = IPA.nav.get_state(that.entity.name+'-pkey');
+ return [pkey];
+ };
+
+ that.get_additional_options = function() {
+ return [];
+ };
+
+ that.create_remove_command = function(values, on_success, on_error) {
+
+ var pkeys = that.get_pkeys();
+
+ var command = IPA.command({
+ entity: that.entity.name,
+ method: that.remove_command || 'del',
+ args: pkeys,
+ on_success: on_success,
+ on_error: on_error
+ });
+
+ command.set_option(that.attribute_name, values);
+
+ var additional_options = that.get_additional_options();
+ for (var i=0; i<additional_options.length; i++) {
+ var option = additional_options[i];
+ command.set_option(option.name, option.value);
+ }
+
+ return command;
+ };
+
+ that.create_add_dialog = function() {
+
+ var dialog_spec = {
+ entity: that.entity,
+ method: that.add_command
+ };
+
+ if (that.adder_dialog_spec) {
+ $.extend(dialog_spec, that.adder_dialog_spec);
+ }
+
+ var label = that.entity.metadata.label_singular;
+ var pkey = IPA.nav.get_state(that.entity.name+'-pkey');
+ dialog_spec.title = dialog_spec.title || IPA.messages.dialogs.add_title;
+ dialog_spec.title = dialog_spec.title.replace('${entity}', label);
+ dialog_spec.title = dialog_spec.title.replace('${pkey}', pkey);
+
+
+ var factory = dialog_spec.factory || IPA.entity_adder_dialog;
+ var dialog = factory(dialog_spec);
+
+ var cancel_button = dialog.buttons.get('cancel');
+ dialog.buttons.empty();
+
+ dialog.create_button({
+ name: 'add',
+ label: IPA.messages.buttons.add,
+ click: function() {
+ dialog.hide_message();
+ dialog.add(
+ function(data, text_status, xhr) {
+ var handler = that.on_add || that.on_command_success;
+ handler.call(this, data, text_status, xhr);
+ dialog.close();
+ },
+ dialog.on_error);
+ }
+ });
+
+ dialog.create_button({
+ name: 'add_and_add_another',
+ label: IPA.messages.buttons.add_and_add_another,
+ click: function() {
+ dialog.hide_message();
+ dialog.add(
+ function(data, text_status, xhr) {
+ var label = that.entity.metadata.label_singular;
+ var message = IPA.messages.dialogs.add_confirmation;
+ message = message.replace('${entity}', label);
+ dialog.show_message(message);
+
+ var handler = that.on_add || that.on_command_success;
+ handler.call(this, data, text_status, xhr);
+
+ dialog.reset();
+ },
+ dialog.on_error);
+ }
+ });
+
+ dialog.buttons.put('cancel', cancel_button);
+
+ dialog.create_add_command = function(record) {
+ return that.adder_dialog_create_command(dialog, record);
+ };
+
+ return dialog;
+ };
+
+ that.adder_dialog_create_command = function(dialog, record) {
+ var command = dialog.entity_adder_dialog_create_add_command(record);
+ command.args = that.get_pkeys();
+
+ var additional_options = that.get_additional_options();
+ for (var i=0; i<additional_options.length; i++) {
+ var option = additional_options[i];
+ command.set_option(option.name, option.value);
+ }
+
+ return command;
+ };
+
+ that.show_add_dialog = function() {
+
+ var dialog = that.create_add_dialog();
+ dialog.open(that.container);
+ };
+
+ that.update = function(values) {
+ that.table_update(values);
+ that.unselect_all();
+ };
+
+ that.reload_facet = function(data) {
+
+ //FIXME: bad approach - widget is directly manipulating with facet
+ var facet = IPA.current_entity.get_facet();
+ facet.load(data);
+ };
+
+ that.refresh_facet = function() {
+
+ //FIXME: bad approach
+ var facet = IPA.current_entity.get_facet();
+ facet.refresh();
+ };
+
+ that.attribute_table_adder_dialog_create_command = that.adder_dialog_create_command;
+ that.attribute_table_create_remove_command = that.create_remove_command;
+ that.attribute_table_update = that.update;
+
+ return that;
+};
+
+IPA.combobox_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ that.editable = spec.editable;
+ that.searchable = spec.searchable;
+ that.size = spec.size || 5;
+ that.empty_option = spec.empty_option === undefined ? true : spec.empty_option;
+ that.options = spec.options || [];
+ that.input_field_changed = IPA.observer();
+ that.z_index = spec.z_index ? spec.z_index + 9000000 : 9000000;
+
+ that.create = function(container) {
+ that.widget_create(container);
+
+ container.addClass('combobox-widget');
+
+ $(document).keyup(function(e) {
+ if (e.which == 27) { // Escape
+ that.close();
+ }
+ });
+
+ that.input_container = $('<div/>', {
+ 'class': 'combobox-widget-input'
+ }).appendTo(container);
+
+ that.text = $('<label/>', {
+ name: that.name,
+ style: 'display: none;'
+ }).appendTo(that.input_container);
+
+ that.input = $('<input/>', {
+ type: 'text',
+ name: that.name,
+ title: that.tooltip,
+ readonly: !that.editable || that.read_only,
+ keyup: function() {
+ that.input_field_changed.notify([], that);
+ },
+ click: function() {
+ if (that.editable) return false;
+ if (that.is_open()) {
+ that.close();
+ } else {
+ that.open();
+ }
+ return false;
+ }
+ }).appendTo(that.input_container);
+
+ that.input.bind('input', function() {
+ that.input_field_changed.notify([], that);
+ });
+
+ that.open_button = IPA.action_button({
+ name: 'open',
+ icon: 'combobox-icon',
+ click: function() {
+ if (that.is_open()) {
+ that.close();
+ } else {
+ that.open();
+ }
+ return false;
+ }
+ }).appendTo(that.input_container);
+
+ that.list_container = $('<div/>', {
+ 'class': 'combobox-widget-list',
+ css: { 'z-index': that.z_index }
+ }).appendTo(that.input_container);
+
+ var div = $('<div/>', {
+ style: 'position: relative; width: 100%;'
+ }).appendTo(that.list_container);
+
+ if (that.searchable) {
+ that.filter = $('<input/>', {
+ type: 'text',
+ name: 'filter',
+ keypress: function(e) {
+ if (e.which == 13) { // Enter
+ var filter = that.filter.val();
+ that.search(filter);
+ }
+ }
+ }).appendTo(div);
+
+ that.search_button = IPA.action_button({
+ name: 'search',
+ icon: 'search-icon',
+ click: function() {
+ var filter = that.filter.val();
+ that.search(filter);
+ return false;
+ }
+ }).appendTo(div);
+
+ div.append('<br/>');
+ }
+
+ that.list = $('<select/>', {
+ name: 'list',
+ size: that.size,
+ style: 'width: 100%',
+ change: that.select_on_change
+ }).appendTo(div);
+
+ if (that.undo) {
+ that.create_undo(container);
+ }
+
+ that.create_error_link(container);
+ };
+
+ that.select_on_change = function() {
+
+ if (!that.is_open()) return;
+
+ var value = that.list.val();
+ that.input.val(value);
+ IPA.select_range(that.input, 0, 0);
+
+ that.close();
+ that.value_changed.notify([[value]], that);
+ };
+
+ that.open = function() {
+ if (!that.read_only)
+ that.list_container.css('visibility', 'visible');
+ };
+
+ that.close = function() {
+ that.list_container.css('visibility', 'hidden');
+ };
+
+ that.is_open = function() {
+ return that.list_container.css('visibility') == 'visible';
+ };
+
+ that.search = function(filter, on_success, on_error) {
+
+ that.recreate_options();
+ if (on_success) on_success.call(this);
+ };
+
+ that.set_options = function(options) {
+ that.options = options;
+ that.recreate_options();
+ };
+
+ that.recreate_options = function() {
+
+ that.remove_options();
+
+ if (that.empty_option) {
+ that.create_option();
+ }
+
+ for (var i=0; i<that.options.length; i++) {
+ var option = that.options[i];
+
+ var label, value;
+ if (option instanceof Object) {
+ label = option.label;
+ value = option.value;
+ } else {
+ label = option;
+ value = option;
+ }
+
+ that.create_option(label, value);
+ }
+ };
+
+ that.update = function(values) {
+ that.close();
+
+ if (that.writable) {
+ that.text.css('display', 'none');
+ that.input.css('display', 'inline');
+ that.open_button.css('display', 'inline');
+ } else {
+ that.text.css('display', 'inline');
+ that.input.css('display', 'none');
+ that.open_button.css('display', 'none');
+ }
+
+ if (that.searchable) {
+ that.filter.empty();
+ }
+
+ // In a details page the following code will get the stored value.
+ // In a dialog box the value will be null.
+ var value = values.length ? values[0] : null;
+
+ // In a details page the following code will show the stored
+ // value immediately without waiting to populate the list.
+ // In a dialog box it will show blank.
+ that.set_value(value || '');
+
+ // In a details page the following code will populate the list
+ // and select the stored value.
+ // In a dialog box it will populate the list and select the first
+ // available option.
+ that.search(
+ null,
+ function(data, text_status, xhr) {
+ that.select(value);
+ }
+ );
+ };
+
+ that.set_value = function(value) {
+ that.text.text(value);
+ that.input.val(value);
+ };
+
+ that.select = function(value) {
+
+ var option;
+
+ if (value) {
+ // select specified value
+ option = $('option[value="'+value+'"]', that.list);
+ } else {
+ // select first available option
+ option = $('option', that.list).first();
+ }
+
+ // if no option found, skip
+ if (!option.length) return;
+
+ option.prop('selected', true);
+
+ that.set_value(option.val());
+ that.value_changed.notify([], that);
+ };
+
+ that.save = function() {
+ var value = that.input.val();
+ return value === '' ? [] : [value];
+ };
+
+ that.create_option = function(label, value) {
+ var option = $('<option/>', {
+ text: label,
+ value: value,
+ click: that.select_on_change
+ }).appendTo(that.list);
+ };
+
+ that.remove_options = function() {
+ that.list.empty();
+ };
+
+ that.clear = function() {
+ that.input.val('');
+ that.remove_options();
+ };
+
+ return that;
+};
+
+IPA.entity_select_widget = function(spec) {
+
+ spec = spec || {};
+ spec.searchable = spec.searchable === undefined ? true : spec.searchable;
+
+ var that = IPA.combobox_widget(spec);
+
+ that.other_entity = IPA.get_entity(spec.other_entity);
+ that.other_field = spec.other_field;
+
+ that.options = spec.options || [];
+
+ that.create_search_command = function(filter) {
+ return IPA.command({
+ entity: that.other_entity.name,
+ method: 'find',
+ args: [filter]
+ });
+ };
+
+ that.search = function(filter, on_success, on_error) {
+
+ that.on_search_success = on_success;
+
+ var command = that.create_search_command(filter);
+ command.on_success = that.search_success;
+ command.on_error = on_error;
+
+ command.execute();
+ };
+
+ that.search_success = function(data, text_status, xhr) {
+
+ //get options
+ var options = [];
+
+ var entries = data.result.result;
+ for (var i=0; i<data.result.count; i++) {
+ var entry = entries[i];
+ var values = entry[that.other_field];
+ var value = values[0];
+
+ options.push(value);
+ }
+
+ that.set_options(options);
+
+ if (that.on_search_success) that.on_search_success.call(this, data, text_status, xhr);
+ };
+
+ return that;
+};
+
+
+IPA.link_widget = function(spec) {
+ var that = IPA.input_widget(spec);
+
+ that.is_link = spec.is_link || false;
+ that.link_clicked = IPA.observer();
+
+ that.create = function(container) {
+ that.widget_create(container);
+ that.link =
+ $('<a/>', {
+ href: 'jslink',
+ title: '',
+ html: '',
+ click: function() {
+ that.link_clicked.notify([], that);
+ return false;
+ }
+ }).appendTo(container);
+
+ that.nonlink = $('<label/>').
+ appendTo(container);
+ };
+
+ that.update = function (values){
+
+ if (values || values.length > 0) {
+ that.nonlink.text(values[0]);
+ that.link.text(values[0]);
+ if(that.is_link) {
+ that.link.css('display','inline');
+ that.nonlink.css('display','none');
+ } else {
+ that.link.css('display','none');
+ that.nonlink.css('display','inline');
+ }
+ } else {
+ that.link.html('');
+ that.nonlink.html('');
+ that.link.css('display','none');
+ that.nonlink.css('display','none');
+ }
+ };
+
+ that.clear = function() {
+ that.nonlink.text('');
+ that.link.text('');
+ };
+
+
+ return that;
+};
+
+IPA.action_button = function(spec) {
+
+ spec = spec || {};
+
+ var button = $('<a/>', {
+ id: spec.id,
+ name: spec.name,
+ href: spec.href || '#' + (spec.name || 'button'),
+ title: spec.title || spec.label,
+ 'class': 'button action-button',
+ style: spec.style,
+ click: spec.click,
+ blur: spec.blur
+ });
+
+ if (spec['class']) button.addClass(spec['class']);
+
+ if (spec.icon) {
+ $('<span/>', {
+ 'class': 'icon '+spec.icon
+ }).appendTo(button);
+ }
+
+ if (spec.label) {
+ $('<span/>', {
+ 'class': 'button-label',
+ html: spec.label
+ }).appendTo(button);
+ }
+
+ return button;
+};
+
+IPA.button = function(spec) {
+
+ spec = spec || {};
+
+ var button = $('<a/>', {
+ id: spec.id,
+ name: spec.name,
+ href: spec.href || '#' + (spec.name || 'button')
+ });
+
+ var icons = { primary: spec.icon };
+ var label = spec.label;
+
+ button.button({
+ icons: icons,
+ label: label
+ });
+
+ button.click(spec.click);
+
+ return button;
+};
+
+IPA.button_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.href = spec.href;
+ that.style = spec.style;
+ that.click = spec.click;
+ that['class'] = spec['class'];
+ that.disabled_class = 'button-disabled';
+
+ that.on_click = function() {
+
+ if (that.click) {
+ that.click();
+ }
+ return false;
+ };
+
+ that.create = function(container) {
+ that.button = IPA.button({
+ id: that.id,
+ name: that.name,
+ href: that.href,
+ title: that.tooltip,
+ label: that.label,
+ 'class': that['class'],
+ style: that.style,
+ click: that.on_click
+ }).appendTo(container);
+ };
+
+ that.get_enabled = function() {
+
+ var enabled = true;
+
+ if (that.button) {
+ enabled = that.button.hasClass(that.disabled_class);
+ }
+
+ return enabled;
+ };
+
+ that.set_enabled = function(enabled) {
+
+ enabled ? that.enable() : that.disable();
+ };
+
+ that.enable = function() {
+ if (that.button) {
+ that.button.removeClass(that.disabled_class);
+ }
+ };
+
+ that.disable = function() {
+ if (that.button) {
+ that.button.addClass(that.disabled_class);
+ }
+ };
+
+ return that;
+};
+
+IPA.html_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.html = spec.html;
+ that.css_class = spec.css_class;
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ if (that.css_class) {
+ container.addClass(that.css_class);
+ }
+
+ if (that.html) {
+ container.append(that.html);
+ }
+ };
+
+ return that;
+};
+
+IPA.composite_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.widgets = IPA.widget_container();
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+ that.widgets.create(container);
+ };
+
+ that.clear = function() {
+
+ var widgets = that.widgets.get_widgets();
+
+ for (var i=0; i< widgets.length; i++) {
+ widgets[i].clear();
+ }
+ };
+
+ that.composite_widget_create = that.create;
+ that.composite_widget_clear = that.clear;
+
+ return that;
+};
+
+IPA.collapsible_section = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.composite_widget(spec);
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ that.header = $('<h2/>', {
+ name: that.name,
+ title: that.label
+ }).appendTo(container);
+
+ that.icon = $('<span/>', {
+ name: 'icon',
+ 'class': 'icon section-expand '+IPA.expanded_icon
+ }).appendTo(that.header);
+
+ that.header.append(' ');
+
+ that.header.append(that.label);
+
+ that.content_container = $('<div/>', {
+ name: that.name,
+ 'class': 'details-section'
+ }).appendTo(container);
+
+ that.header.click(function() {
+ var visible = that.content_container.is(":visible");
+ that.toggle(!visible);
+ });
+
+ that.composite_widget_create(that.content_container);
+ };
+
+ that.toggle = function(visible) {
+
+ that.icon.toggleClass(IPA.expanded_icon, visible);
+ that.icon.toggleClass(IPA.collapsed_icon, !visible);
+
+ if (visible != that.content_container.is(":visible")) {
+ that.content_container.slideToggle('slow');
+ }
+ };
+
+ return that;
+};
+
+IPA.details_section = IPA.collapsible_section;
+
+IPA.layout = function(spec) {
+ return {};
+};
+
+// Creates list of widgets into table with two columns: label and widget
+IPA.table_layout = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.layout(spec);
+ that.table_class = spec.table_class || 'section-table';
+ that.label_cell_class = spec.label_cell_class || 'section-cell-label';
+ that.field_cell_class = spec.field_cell_class || 'section-cell-field';
+ that.label_class = spec.label_class || 'field-label';
+ that.field_class = spec.field_class || 'field';
+
+ that.create = function(widgets) {
+
+ that.rows = $.ordered_map();
+
+ var table = $('<table/>', {
+ 'class': that.table_class
+ });
+
+ for (var i=0; i<widgets.length; i++) {
+ var widget = widgets[i];
+ var tr = $('<tr/>');
+ that.rows.put(widget.name, tr);
+
+ if (widget.hidden) {
+ tr.css('display', 'none');
+ }
+
+ tr.appendTo(table);
+
+ var td = $('<td/>', {
+ 'class': that.label_cell_class,
+ title: widget.label
+ }).appendTo(tr);
+
+ var label_text = widget.label + that.get_measurement_unit_text(widget) + ':';
+
+ $('<label/>', {
+ name: widget.name,
+ 'class': that.label_class,
+ text: label_text
+ }).appendTo(td);
+
+ if(widget.create_required) {
+ widget.create_required(td);
+ }
+
+ td = $('<td/>', {
+ 'class': that.field_cell_class,
+ title: widget.label
+ }).appendTo(tr);
+
+ var widget_container = $('<div/>', {
+ name: widget.name,
+ 'class': that.field_class
+ }).appendTo(td);
+
+ widget.create(widget_container);
+ }
+ return table;
+ };
+
+
+ that.get_measurement_unit_text = function(widget) {
+
+ if (widget.measurement_unit) {
+ var unit = IPA.messages.measurement_units[widget.measurement_unit];
+ return ' (' + unit + ')';
+ }
+ return '';
+ };
+
+ return that;
+};
+
+IPA.details_table_section = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_section(spec);
+ that.layout = IPA.build_default(spec.layout, IPA.table_layout);
+ that.action_panel = that.build_child(spec.action_panel);
+
+ that.rows = $.ordered_map();
+
+ that.composite_widget_create = function(container) {
+
+ that.widget_create(container);
+
+ if (that.action_panel) {
+ that.action_panel.create(container);
+ }
+ var widgets = that.widgets.get_widgets();
+ var table = that.layout.create(widgets);
+ table.appendTo(container);
+ that.rows = that.layout.rows;
+ };
+
+
+ that.add_row = function(name, row) {
+ that.rows.put(name, row);
+ };
+
+ that.get_row = function(name) {
+ return that.rows.get(name);
+ };
+
+ that.set_row_visible = function(name, visible) {
+ var row = that.get_row(name);
+ row.css('display', visible ? '' : 'none');
+ };
+
+ that.table_section_create = that.composite_widget_create;
+
+ return that;
+};
+
+//non-collabsible section
+IPA.details_table_section_nc = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.details_table_section(spec);
+
+ that.create = that.table_section_create;
+
+ return that;
+};
+
+IPA.multiple_choice_section = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.composite_widget(spec);
+ that.choices = $.ordered_map().put_array(spec.choices, 'name');
+ that.layout = IPA.build_default(spec.layout, IPA.table_layout);
+
+ that.create = function(container) {
+
+ var i, choice, choices;
+
+ that.widget_create(container);
+ that.container.addClass('multiple-choice-section');
+
+ that.header_element = $('<div/>', {
+ 'class': 'multiple-choice-section-header',
+ text: that.label
+ }).appendTo(container);
+
+ that.choice_container = $('<div/>', {
+ 'class': 'choices'
+ }).appendTo(container);
+
+ choices = that.choices.values;
+ for (i=0; i<choices.length; i++) {
+ choice = choices[i];
+ that.create_choice(choice);
+ }
+ };
+
+ that.create_choice = function(choice) {
+
+ var widgets, i, widget, field, section, choice_el, header, radio,
+ enabled, radio_id;
+
+ widgets = [];
+
+ if (choice.widgets) {
+ for (i=0; i<choice.widgets.length; i++) {
+ widget = that.widgets.get_widget(choice.widgets[i]);
+ widgets.push(widget);
+ }
+ } else if (choice.fields) {
+ for (i=0; i<choice.fields.length; i++) {
+ field = that.facet.fields.get_field(choice.fields[i]);
+ widgets.push(field.widget);
+ }
+ }
+
+ choice_el = $('<div/>',{
+ 'class': 'choice',
+ name: choice.name
+ });
+
+ header = $('<div/>',{
+ 'class': 'choice-header'
+ }).appendTo(choice_el);
+
+ enabled = choice.enabled !== undefined ? choice.enabled : false;
+
+ radio_id = that.name + '_' + choice.name;
+
+ $('<input/>',{
+ type: 'radio',
+ name: that.name,
+ id: radio_id,
+ value: choice.name,
+ checked: enabled,
+ change: function() {
+ that.select_choice(this.value);
+ }
+ }).appendTo(header);
+
+ $('<label/>',{
+ text: choice.label,
+ 'for': radio_id
+ }).appendTo(header);
+
+ section = that.layout.create(widgets);
+ section.appendTo(choice_el);
+ choice_el.appendTo(that.choice_container);
+ };
+
+ that.select_choice = function(choice_name) {
+
+ var i, choice, enabled;
+
+ for (i=0; i<that.choices.values.length; i++) {
+ choice = that.choices.values[i];
+ enabled = choice.name === choice_name;
+ that.set_enabled(choice, enabled);
+ }
+ };
+
+ that.set_enabled = function (choice, enabled) {
+
+ var i, field_name, field, fields, required;
+
+ fields = that.facet.fields;
+
+ for (i=0; i<choice.fields.length; i++) {
+ field_name = choice.fields[i];
+ field = fields.get_field(field_name);
+ field.set_enabled(enabled);
+ required = enabled && choice.required.indexOf(field_name) > -1;
+ field.set_required(required);
+ field.validate(); //hide validation errors
+ }
+ };
+
+ that.init_enabled = function() {
+
+ var i, choice;
+
+ for (i=0; i<that.choices.values.length; i++) {
+ choice = that.choices.values[i];
+ if (choice.enabled) {
+ that.select_choice(choice.name);
+ break;
+ }
+ }
+ };
+
+ return that;
+};
+
+IPA.multiple_choice_section_policy = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.facet_policy(spec);
+ that.widget_name = spec.widget;
+
+ that.init = function() {
+ that.widget = that.container.widgets.get_widget(that.widget_name);
+ };
+
+ that.post_create = function() {
+ that.widget.init_enabled();
+ };
+
+ return that;
+};
+
+IPA.enable_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.radio_widget(spec);
+
+ return that;
+};
+
+
+IPA.header_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.widget(spec);
+
+ that.level = spec.level || 3;
+ that.text = spec.text;
+ that.description = spec.description;
+
+ that.create = function(container) {
+ container.append($('<h'+that.level+' />', {
+ text: that.text,
+ title: that.description
+ }));
+ };
+
+ return that;
+};
+
+IPA.observer = function(spec) {
+
+ var that = {};
+
+ that.listeners = [];
+
+ that.attach = function(callback) {
+ that.listeners.push(callback);
+ };
+
+ that.detach = function(callback) {
+ for(var i=0; i < that.listeners.length; i++) {
+ if(callback === that.listeners[i]) {
+ that.listeners.splice(i,1);
+ break;
+ }
+ }
+ };
+
+ that.notify = function(args, context) {
+ args = args || [];
+ context = context || this;
+
+ for(var i=0; i < that.listeners.length; i++) {
+ that.listeners[i].apply(context, args);
+ }
+ };
+
+ return that;
+};
+
+IPA.html_util = function() {
+
+ var that = {};
+ that.id_count = 0;
+
+ that.get_next_id = function(prefix) {
+ that.id_count++;
+ return prefix ? prefix + that.id_count : that.id_count;
+ };
+
+ return that;
+}();
+
+IPA.widget_container = function(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.new_container_for_child = spec.new_container_for_child !== undefined ?
+ spec.new_container_for_child : true;
+
+ that.widgets = $.ordered_map();
+ that.widget_builder = spec.widget_builder || IPA.widget_builder();
+
+ that.add_widget = function(widget) {
+ that.widgets.put(widget.name, widget);
+ };
+
+ that.get_widget = function(path) {
+
+ var path_len = path.length;
+ var i = path.indexOf('.');
+ var name, child_path, widget, child;
+
+ if (i >= 0) {
+ name = path.substring(0, i);
+ child_path = path.substring(i + 1);
+
+ child = that.widgets.get(name);
+ widget = child.widgets.get_widget(child_path);
+ } else {
+ widget = that.widgets.get(path);
+ }
+
+ return widget;
+ };
+
+ that.get_widgets = function() {
+ return that.widgets.values;
+ };
+
+ that.create = function(container) {
+
+ var widgets = that.widgets.values;
+ for (var i=0; i<widgets.length; i++) {
+ var widget = widgets[i];
+
+ var child_container = container;
+ if(that.new_container_for_child) {
+ child_container = $('<div/>', {
+ name: widget.name,
+ title: widget.label,
+ 'class': widget['class']
+ }).appendTo(container);
+ }
+ widget.create(child_container);
+
+ if(i < widgets.length - 1) {
+ that.create_widget_delimiter(container);
+ }
+ }
+ };
+
+ that.clear = function() {
+
+ var widgets = that.widgets.values;
+ for (var i=0; i<widgets.length; i++) {
+ widgets[i].clear();
+ }
+ };
+
+ that.create_widget_delimiter = function(container) {
+ };
+
+ that.widget_container_create = that.create;
+ that.widget_container_clear = that.clear;
+
+ return that;
+};
+
+IPA.widget_builder = function(spec) {
+
+ spec = spec || {};
+
+ var that = {};
+
+ that.default_factory = spec.default_factory || IPA.text_widget;
+ that.container = spec.container;
+ that.widget_options = spec.widget_options || {};
+
+ that.get_widget_factory = function(spec) {
+
+ var factory;
+ if (spec.factory) {
+ factory = spec.factory;
+ } else if(spec.type) {
+ factory = IPA.widget_factories[spec.type];
+ }
+
+ if (!factory) {
+ factory = that.default_factory;
+ }
+
+ return factory;
+ };
+
+ that.build_widget = function(spec, container) {
+
+ container = container || that.container;
+
+ if(!(spec instanceof Object)) {
+ spec = { name: spec };
+ }
+
+ if(that.widget_options) {
+ $.extend(spec, that.widget_options);
+ }
+
+ var factory = that.get_widget_factory(spec);
+
+ var widget = factory(spec);
+
+ if(container) {
+ container.add_widget(widget);
+ }
+
+ if(spec.widgets) {
+ that.build_widgets(spec.widgets, widget.widgets);
+ }
+
+ return widget;
+ };
+
+ that.build_widgets = function(specs, container) {
+
+ container = container || that.container;
+
+ for(var i=0; i<specs.length; i++) {
+ that.build_widget(specs[i], container);
+ }
+ };
+
+ return that;
+};
+
+IPA.sshkeys_widget = function(spec) {
+
+ spec = spec || {};
+ spec.widget_factory = IPA.sshkey_widget;
+
+ var that = IPA.multivalued_widget(spec);
+
+ that.test_dirty_row = function(row) {
+
+ if(row.deleted || row.is_new) return true;
+
+ var values = row.widget.save();
+
+ var key = values[0];
+ var original_key = row.original_values[0];
+
+ if (original_key && original_key.key && original_key.key !== key) {
+ return true;
+ }
+
+ return false;
+ };
+
+ return that;
+};
+
+IPA.sshkey_widget = function(spec) {
+
+ spec = spec || {};
+
+ var that = IPA.input_widget(spec);
+
+ that.key = null;
+ that.originally_set = false;
+
+ that.create = function(container) {
+
+ that.widget_create(container);
+
+ container.addClass('text-widget');
+
+ that.status_label = $('<span />', {
+ 'class': 'sshkey-status',
+ text: ''
+ }).appendTo(container);
+
+ that.link = $('<a/>', {
+ type: that.type,
+ 'class': 'sshkey-set',
+ name: that.name,
+ href: '#show-certificate',
+ title: that.tooltip,
+ text: IPA.messages.objects.sshkeystore.show_set_key,
+ click: function() {
+ that.open_edit_dialog();
+ return false;
+ }
+ }).appendTo(container);
+
+ if (that.undo) {
+ that.create_undo(container);
+ }
+
+ that.create_error_link(container);
+ };
+
+ that.update = function(values) {
+
+ var key = values && values.length ? values[0] : null;
+
+ if (!key || key === '') {
+ key = {};
+ }
+
+ that.key = $.extend({}, key);
+
+ if (that.key.key && that.key.key !== '' &&
+ that.key.fingerprint && that.key.fingerprint !== '') {
+ that.originally_set = true;
+ that.original_key = that.key.key;
+ }
+ that.update_link();
+ };
+
+ that.set_deleted = function(deleted) {
+ if (deleted) {
+ that.status_label.addClass('strikethrough');
+ } else {
+ that.status_label.removeClass('strikethrough');
+ }
+ };
+
+ that.save = function() {
+ var value = that.key.key;
+ value = value ? [value] : [''];
+ return value;
+ };
+
+ that.update_link = function() {
+ var text = that.get_status();
+ that.status_label.text(text);
+ };
+
+ that.get_status = function() {
+
+ var text = '';
+ var value = that.key.key;
+
+ if (that.original_key) {
+
+ if (value !== that.original_key) {
+ if (value === '') {
+ text = IPA.messages.objects.sshkeystore.status_mod_ns;
+ } else {
+ text = IPA.messages.objects.sshkeystore.status_mod_s;
+ }
+ } else {
+ text = that.key.fingerprint;
+ }
+
+ } else {
+
+ if (!value || value === '') {
+ text = IPA.messages.objects.sshkeystore.status_new_ns;
+ } else {
+ text = IPA.messages.objects.sshkeystore.status_new_s;
+ }
+ }
+
+ return text;
+ };
+
+ that.set_user_value = function(value) {
+
+ var previous = that.key.key;
+ that.key.key = value;
+ that.update_link();
+
+ if (value !== previous) {
+ that.value_changed.notify([], that);
+ }
+ };
+
+ that.open_edit_dialog = function() {
+
+ var dialog = that.create_edit_dialog();
+ dialog.open();
+ };
+
+ that.create_edit_dialog = function() {
+
+ var dialog = IPA.dialog({
+ name: 'sshkey-edit-dialog',
+ title: IPA.messages.objects.sshkeystore.set_dialog_title,
+ width: 500,
+ height: 380
+ });
+
+ dialog.message = IPA.messages.objects.sshkeystore.set_dialog_help;
+
+ dialog.create_button({
+ name: 'update',
+ label: IPA.messages.buttons.set,
+ click: function() {
+ var value = dialog.textarea.val();
+ that.set_user_value(value);
+ dialog.close();
+ }
+ });
+
+ dialog.create_button({
+ name: 'cancel',
+ label: IPA.messages.buttons.cancel,
+ click: function() {
+ dialog.close();
+ }
+ });
+
+ dialog.create = function() {
+
+ dialog.container.append(dialog.message);
+
+ dialog.textarea = $('<textarea/>', {
+ 'class': 'certificate',
+ readonly: that.read_only
+ }).appendTo(dialog.container);
+
+ var key = that.key.key || '';
+ dialog.textarea.val(key);
+ };
+
+ return dialog;
+ };
+
+ return that;
+};
+
+IPA.action_panel = function(spec) {
+
+ spec = spec || {};
+ spec.label = spec.label || IPA.messages.actions.title;
+
+ var that = IPA.widget(spec);
+
+ that.action_names = spec.actions;
+ that.actions = $.ordered_map();
+ that.facet = spec.facet;
+ that.initialized = false;
+
+ that.init = function() {
+
+ for (var i=0; i<that.action_names.length; i++) {
+ var name = that.action_names[i];
+ var action = that.facet.actions.get(name);
+
+ that.add_action(action, true);
+
+ that.actions.put(name, action);
+ }
+
+ that.initialized = true;
+ };
+
+ that.add_action = function(action, batch) {
+ that.actions.put(action.name, action);
+ action.enabled_changed.attach(that.action_enabled_changed);
+ action.visible_changed.attach(that.action_visible_changed);
+
+ if (!batch) {
+ that.create_items();
+ }
+ };
+
+ that.create = function(container) {
+
+ if (!that.initialized) that.init();
+
+ that.element = $('<div/>', {
+ 'data-name': that.name,
+ 'class': 'action-panel'
+ });
+
+ that.header_element = $('<h3/>', {
+ 'class': 'action-title'
+ }).appendTo(that.element);
+
+ that.list_element = $('<ul/>', {
+ 'class': 'action-panel-list'
+ }).appendTo(that.element);
+
+ that.element.appendTo(container);
+
+ that.create_items();
+ };
+
+ that.create_item = function(action) {
+
+ var classes, state, li, a;
+
+ if (!action.visible) return;
+
+ classes = ['action'];
+ state = action.enabled ? 'enabled' : 'disabled';
+ classes.push(state);
+
+ li = $('<li/>');
+ a = $('<a/>', {
+ 'data-name': action.name,
+ href: '#',
+ text: action.label,
+ 'class': classes.join(' '),
+ click: function() {
+ that.action_clicked(action);
+ return false;
+ }
+ }).appendTo(li);
+ li.appendTo(that.list_element);
+ };
+
+ that.clear_items = function() {
+
+ that.list_element.empty();
+ };
+
+ that.create_items = function() {
+
+ if (!that.element) return;
+
+ that.clear_items();
+
+ var actions = that.actions.values;
+
+ for (var i=0; i<actions.length; i++) {
+ var action = actions[i];
+ that.create_item(action);
+ }
+
+ that.header_element.text(that.label);
+ };
+
+ that.action_clicked = function(action) {
+
+ if (!action.enabled || !action.visible) return;
+
+ action.execute(that.facet);
+ };
+
+ that.action_enabled_changed = function() {
+
+ that.create_items();
+ };
+
+ that.action_visible_changed = function() {
+
+ that.create_items();
+ };
+
+
+ return that;
+};
+
+IPA.value_map_widget = function(spec) {
+
+ spec = spec || {};
+ spec.read_only = true;
+
+ var that = IPA.input_widget(spec);
+ that.value_map = spec.value_map || {};
+ that.default_label = spec.default_label || '';
+
+ that.create = function(container) {
+ that.widget_create(container);
+ container.addClass('status-widget');
+
+ that.display_control = $('<span/>', {
+ name: that.name
+ }).appendTo(container);
+ };
+
+ that.update = function(values) {
+
+ var value, found, label;
+
+ found = false;
+
+ if ($.isArray(values)) {
+ for (value in that.value_map) {
+
+ if (!that.value_map.hasOwnProperty(value)) continue;
+
+ if (values.indexOf(value) > -1) {
+ label = that.value_map[value];
+ found = true;
+ }
+ }
+ }
+
+ if (!found) {
+ label = that.default_label;
+ }
+
+ that.display_control.text(label);
+ };
+
+ that.clear = function() {
+ that.display_control.text('');
+ };
+
+ return that;
+};
+
+IPA.widget_factories['attribute_table'] = IPA.attribute_table_widget;
+IPA.widget_factories['button'] = IPA.button_widget;
+IPA.widget_factories['checkbox'] = IPA.checkbox_widget;
+IPA.widget_factories['checkboxes'] = IPA.checkboxes_widget;
+IPA.widget_factories['combobox'] = IPA.combobox_widget;
+IPA.widget_factories['composite_widget'] = IPA.composite_widget;
+IPA.widget_factories['details_table_section'] = IPA.details_table_section;
+IPA.widget_factories['details_table_section_nc'] = IPA.details_table_section_nc;
+IPA.widget_factories['multiple_choice_section'] = IPA.multiple_choice_section;
+IPA.widget_factories['enable'] = IPA.enable_widget;
+IPA.widget_factories['entity_select'] = IPA.entity_select_widget;
+IPA.widget_factories['header'] = IPA.header_widget;
+IPA.widget_factories['html'] = IPA.html_widget;
+IPA.widget_factories['link'] = IPA.link_widget;
+IPA.widget_factories['multivalued'] = IPA.multivalued_widget;
+IPA.widget_factories['password'] = IPA.password_widget;
+IPA.widget_factories['radio'] = IPA.radio_widget;
+IPA.widget_factories['select'] = IPA.select_widget;
+IPA.widget_factories['sshkeys'] = IPA.sshkeys_widget;
+IPA.widget_factories['textarea'] = IPA.textarea_widget;
+IPA.widget_factories['text'] = IPA.text_widget;
+IPA.widget_factories['value_map'] = IPA.value_map_widget; \ No newline at end of file