From 4bab6b7e5d4f6454e5293c3b403fded397f93610 Mon Sep 17 00:00:00 2001 From: Petr Vobornik Date: Tue, 22 Nov 2011 15:41:33 +0100 Subject: Splitting basic widgets into visual widgets and fields https://fedorahosted.org/freeipa/ticket/2040 --- install/ui/certificate.js | 2 +- install/ui/entitle.js | 2 +- install/ui/field.js | 224 +++++++++++++- install/ui/host.js | 4 +- install/ui/ipa.js | 2 + install/ui/service.js | 4 +- install/ui/test/details_tests.js | 2 +- install/ui/test/widget_tests.js | 2 +- install/ui/widget.js | 620 +++++++++++++++++---------------------- 9 files changed, 495 insertions(+), 367 deletions(-) diff --git a/install/ui/certificate.js b/install/ui/certificate.js index d3411d05f..c9d243cae 100755 --- a/install/ui/certificate.js +++ b/install/ui/certificate.js @@ -483,7 +483,7 @@ IPA.cert.status_widget = function(spec) { spec = spec || {}; - var that = IPA.widget(spec); + var that = IPA.input_widget(spec); that.entity_label = spec.entity_label || that.entity.metadata.label_singular; diff --git a/install/ui/entitle.js b/install/ui/entitle.js index d2039c4b5..066ececfb 100644 --- a/install/ui/entitle.js +++ b/install/ui/entitle.js @@ -698,7 +698,7 @@ IPA.entitle.download_widget = function(spec) { spec = spec || {}; - var that = IPA.widget(spec); + var that = IPA.input_widget(spec); that.create = function(container) { that.link = $('', { diff --git a/install/ui/field.js b/install/ui/field.js index 2e6a5e9a3..c9bfb700a 100644 --- a/install/ui/field.js +++ b/install/ui/field.js @@ -47,6 +47,8 @@ IPA.field = function(spec) { // writable is set during load that.writable = true; + that.enabled = spec.enabled === undefined ? true : spec.enabled; + that.undo = spec.undo === undefined ? true : spec.undo; that.join = spec.join; @@ -89,7 +91,7 @@ IPA.field = function(spec) { }; that.update_required = function() { - if(that.widget) { + if(that.widget && that.widget.set_required) { that.widget.set_required(that.is_required()); } }; @@ -208,6 +210,7 @@ IPA.field = function(spec) { }; that.reset = function() { + that.set_widget_flags(); that.update_required(); that.update(); that.validate(); @@ -238,6 +241,8 @@ IPA.field = function(spec) { var values = that.values; + if(!that.enabled) return ['']; + if(that.widget) { values = that.widget.save(); } @@ -312,28 +317,32 @@ IPA.field = function(spec) { that.show_undo(dirty); } - if(old !== dirty) { + if (old !== dirty) { that.dirty_changed.notify([], that); } }; that.show_error = function(message) { - if(that.widget) that.widget.show_error(message); + if (that.widget && that.widget.show_error) that.widget.show_error(message); }; that.hide_error = function() { - if(that.widget) that.widget.hide_error(); + if (that.widget && that.widget.hide_error) that.widget.hide_error(); }; that.show_undo = function(value) { - if(that.widget) { + if (that.widget && that.widget.show_undo) { if(value) { that.widget.show_undo(); } - else { that.widget.hide_undo();} + else { that.widget.hide_undo(); } } }; - that.set_enabled = function() { + that.set_enabled = function(value) { + that.enabled = value; + if (that.widget && that.widget.set_enabled) { + that.widget.set_enabled(value); + } }; that.refresh = function() { @@ -341,11 +350,13 @@ IPA.field = function(spec) { that.set_widget_flags = function() { - that.widget.label = that.label; - that.widget.title = that.title; - that.widget.undo = that.undo; - that.widget.writable = that.writable; - that.widget.read_only = that.read_only; + if (that.widget) { + if(that.label) that.widget.label = that.label; + if(that.title) that.widget.title = that.title; + that.widget.undo = that.undo; + that.widget.writable = that.writable; + that.widget.read_only = that.read_only; + } }; that.widgets_created = function() { @@ -381,4 +392,191 @@ IPA.field = function(spec) { that.field_widgets_created = that.widgets_created; return that; -}; \ No newline at end of file +}; + +IPA.checkbox_field = function(spec) { + + spec = spec || {}; + + var that = IPA.field(spec); + + that.checked = spec.checked || false; + + that.widgets_created = function() { + + that.field_widgets_created(); + that.widget.checked = that.checked; + }; + + // a checkbox will always have a value, so it's never required + that.is_required = function() { + return false; + }; + + that.checkbox_load = that.load; + + return that; +}; + +IPA.checkboxes_field = function(spec) { + + spec = spec || {}; + + var that = IPA.field(spec); + + that.checkbox_load = that.load; +/* + // a checkbox will always have a value, so it's never required + that.is_required = function() { + return false; + }; +*/ + return that; +}; + +IPA.radio_field = function(spec) { + + spec = spec || {}; + + var that = IPA.field(spec); + + // a radio will always have a value, so it's never required + that.is_required = function() { + return false; + }; + + that.widgets_created = function() { + + that.field_widgets_created(); + }; + + return that; +}; + +IPA.multivalued_field = function(spec) { + + spec = spec || {}; + + var that = IPA.field(spec); + + that.widgets_created = function() { + + that.field_widgets_created(); + }; + + that.load = function(record) { + + that.field_load(record); + }; + + that.test_dirty = function() { + var dirty = that.field_test_dirty(); + dirty |= that.widget.test_dirty(); //also checks order + return dirty; + }; + + that.widget_value_changed = function() { + that.set_dirty(that.test_dirty()); + //that.validate(); disabling validation for now + }; + + return that; +}; + +IPA.select_field = function(spec) { + + spec = spec || {}; + + var that = IPA.field(spec); + + that.widgets_created = function() { + + that.field_widgets_created(); + }; + + return that; +}; + + +IPA.combobox_field = function(spec) { + + spec = spec || {}; + + var that = IPA.field(spec); + + that.widgets_created = function() { + + that.field_widgets_created(); + that.widget.input_field_changed.attach(that.on_input_field_changed); + }; + + that.on_input_field_changed = function() { + that.validate(); + }; + + return that; +}; + +IPA.link_field = function(spec) { + + spec = spec || {}; + + var that = IPA.field(spec); + + var other_entity = spec.other_entity; + + function other_pkeys () { + return that.entity.get_primary_key(); + } + that.other_pkeys = spec.other_pkeys || other_pkeys; + + that.on_link_clicked = function() { + + IPA.nav.show_entity_page( + IPA.get_entity(other_entity), + 'default', + that.other_pkeys()); + }; + + that.load = function(record) { + + that.field_load(record); + that.check_entity_link(); + }; + + that.check_entity_link = function() { + + IPA.command({ + entity: other_entity, + method: 'show', + args: that.other_pkeys(), + options: {}, + retry: false, + on_success: function (result) { + that.widget.is_link = result.result !== undefined; + that.widget.update(that.values); + } + }).execute(); + }; + + that.widgets_created = function() { + that.field_widgets_created(); + that.widget.link_clicked.attach(that.on_link_clicked); + }; + + + return that; +}; + +IPA.field_factories['field'] = IPA.field; +IPA.field_factories['text'] = IPA.field; +IPA.field_factories['password'] = IPA.field; +IPA.field_factories['checkbox'] = IPA.checkbox_field; +IPA.field_factories['checkboxes'] = IPA.checkboxes_field; +IPA.field_factories['radio'] = IPA.radio_field; +IPA.field_factories['multivalued'] = IPA.multivalued_field; +IPA.field_factories['select'] = IPA.select_field; +IPA.field_factories['textarea'] = IPA.field; +IPA.field_factories['entity_select'] = IPA.combobox_field; +IPA.field_factories['combobox'] = IPA.combobox_field; +IPA.field_factories['link'] = IPA.link_field; diff --git a/install/ui/host.js b/install/ui/host.js index ab33892c6..345051ec8 100644 --- a/install/ui/host.js +++ b/install/ui/host.js @@ -475,7 +475,7 @@ IPA.host_keytab_widget = function(spec) { spec = spec || {}; - var that = IPA.widget(spec); + var that = IPA.input_widget(spec); that.create = function(container) { @@ -602,7 +602,7 @@ IPA.host_password_widget = function(spec) { spec = spec || {}; - var that = IPA.widget(spec); + var that = IPA.input_widget(spec); that.create = function(container) { diff --git a/install/ui/ipa.js b/install/ui/ipa.js index 1ebf1acc4..08d8722ce 100644 --- a/install/ui/ipa.js +++ b/install/ui/ipa.js @@ -48,6 +48,8 @@ var IPA = function() { that.entities = $.ordered_map(); that.entity_factories = {}; + that.field_factories = {}; + that.widget_factories = {}; that.network_call_count = 0; diff --git a/install/ui/service.js b/install/ui/service.js index 7dc73488e..742beef61 100644 --- a/install/ui/service.js +++ b/install/ui/service.js @@ -96,7 +96,7 @@ IPA.service_adder_dialog = function(spec) { spec = spec || {}; var that = IPA.entity_adder_dialog(spec). - field(IPA.widget({ + field(IPA.input_widget({ name: 'krbprincipalname', required: false, entity: spec.entity, @@ -201,7 +201,7 @@ IPA.service_provisioning_status_widget = function (spec) { spec = spec || {}; - var that = IPA.widget(spec); + var that = IPA.input_widget(spec); that.create = function(container) { diff --git a/install/ui/test/details_tests.js b/install/ui/test/details_tests.js index 80136649b..333464232 100644 --- a/install/ui/test/details_tests.js +++ b/install/ui/test/details_tests.js @@ -142,7 +142,7 @@ test("Testing details lifecycle: create, load.", function(){ } function test_widget(spec){ - var widget = IPA.widget(spec); + var widget = IPA.input_widget(spec); widget.load = function(record) { load_called = true; diff --git a/install/ui/test/widget_tests.js b/install/ui/test/widget_tests.js index 4549d5a94..26d508c04 100644 --- a/install/ui/test/widget_tests.js +++ b/install/ui/test/widget_tests.js @@ -199,7 +199,7 @@ test("Testing base widget.", function() { name:'title' }; - factory = IPA.widget; + factory = IPA.input_widget; base_widget_test('test_value'); widget_string_test(); }); diff --git a/install/ui/widget.js b/install/ui/widget.js index 59a4091d3..710b6c256 100644 --- a/install/ui/widget.js +++ b/install/ui/widget.js @@ -61,8 +61,9 @@ IPA.input_widget = function(spec) { that.height = spec.height; that.undo = spec.undo === undefined ? true : spec.undo; - that.writable = spec.writable; + 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 @@ -168,8 +169,6 @@ IPA.input_widget = function(spec) { 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; @@ -196,7 +195,7 @@ IPA.text_widget = function(spec) { spec = spec || {}; - var that = IPA.widget(spec); + var that = IPA.input_widget(spec); that.size = spec.size || 30; that.type = spec.type || 'text'; @@ -223,8 +222,7 @@ IPA.text_widget = function(spec) { size: that.size, title: that.tooltip, keyup: function() { - that.set_dirty(that.test_dirty()); - that.validate(); + that.value_changed.notify([], that); } }).appendTo(container); @@ -235,8 +233,8 @@ IPA.text_widget = function(spec) { that.create_error_link(container); }; - that.update = function() { - var value = that.values && that.values.length ? that.values[0] : ''; + that.update = function(values) { + var value = values && values.length ? values[0] : ''; if (that.read_only || !that.writable) { that.display_control.text(value); @@ -274,299 +272,274 @@ IPA.text_widget = function(spec) { 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.type = 'password'; + + var that = IPA.text_widget(spec); + return that; +}; + IPA.multivalued_text_widget = function(spec) { spec = spec || {}; - var that = IPA.widget(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.get_undo = function(index) { - if (index === undefined) { - return $('span[name="undo_all"]', that.container); + that.rows = []; - } else { - var row = that.get_row(index); - return $('span[name="undo"]', row); + that.on_child_value_changed = function(row) { + if(that.test_dirty_row(row)) { + row.widget.show_undo(); + row.remove_link.hide(); } + + that.value_changed.notify([], that); }; - that.test_dirty = function(index) { - if (index === undefined) { - return that.widget_test_dirty(); + 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(); } - var row = that.get_row(index); - var input = $('input[name="'+that.name+'"]', row); + row.widget.hide_undo(); + that.value_changed.notify([], that); + }; - if (input.is('.strikethrough')) { - return true; - } + that.hide_undo = function() { - var value = input.val(); - if (value !== that.values[index]) { - return true; + $(that.undo_span).css('display', 'none'); + for(var i=0; i', { name: 'value'}); - that.template = $('
', { - name: 'value' + row.widget = that.widget_factory({ + name: that.name+'-'+row_index, + undo: that.undo, + read_only: that.read_only, + writable: that.writable }); - $('', { - type: 'text', - name: that.name, - disabled: that.disabled, - size: that.size, - title: that.tooltip - }).appendTo(that.template); + row.widget.create(row.container); - that.template.append(' '); + 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 = $('', { name: 'remove', href: 'jslink', title: IPA.messages.buttons.remove, - html: IPA.messages.buttons.remove - }).appendTo(that.template); + html: IPA.messages.buttons.remove, + click: function () { + that.remove_row(row); + that.value_changed.notify([], that); + return false; + } + }).appendTo(row.container); - if (that.undo) { - that.create_undo(that.template, false /* no callback */); + 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-text-widget'); + + that.widget_create(container); + that.create_error_link(container); - $('', { + that.add_link = $('', { name: 'add', href: 'jslink', title: IPA.messages.buttons.add, html: IPA.messages.buttons.add, click: function() { that.add_row(''); - var input = $('input[name="'+that.name+'"]:last', that.container); - input.focus(); + that.focus_last(); return false; } }).appendTo(container); - //create other container.append(' '); - $('', { + that.undo_span = $('', { name: 'undo_all', style: 'display: none;', 'class': 'ui-state-highlight ui-corner-all undo', html: IPA.messages.widget.undo_all, click: function() { - that.reset(); + that.undo_clicked.notify([], that); } }).appendTo(container); }; - that.save = function() { - var values = []; - if (that.read_only || !that.writable) { - $('label[name="'+that.name+'"]', that.container).each(function() { - var input = $(this); - var value = input.html(); - values.push(value); - }); - + 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 { - $('input[name="'+that.name+'"]', that.container).each(function() { - var input = $(this); - if (input.is('.strikethrough')) return; - - var value = input.val(); - values.push(value); - }); + row.deleted = true; + row.widget.set_deleted(true); + row.remove_link.hide(); + row.widget.show_undo(); } - return values; }; - that.add_row = function(value) { - - var add_link = $('a[name=add]', that.container); + that.remove_rows = function() { + for(var i=0; i < that.rows.length; i++) { + that.rows[i].container.remove(); + } + that.rows = []; + }; - var row = that.template.clone(); - row.insertBefore(add_link); + that.clear = function() { + that.remove_rows(); + }; - var input = $('input[name="'+that.name+'"]', row); - var remove_link = $('a[name=remove]', row); - var undo_link = $('span[name=undo]', row); + that.test_dirty_row = function(row) { - if (that.read_only || !that.writable) { - var label = $('