netzke-basepack 0.6.5 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. data/CHANGELOG.rdoc +7 -4
  2. data/README.md +63 -0
  3. data/Rakefile +4 -4
  4. data/javascripts/basepack.js +113 -133
  5. data/lib/netzke-basepack.rb +9 -2
  6. data/lib/netzke/basepack.rb +9 -6
  7. data/lib/netzke/basepack/accordion_panel.rb +1 -1
  8. data/lib/netzke/basepack/auth_app.rb +28 -21
  9. data/lib/netzke/basepack/border_layout_panel.rb +9 -57
  10. data/lib/netzke/basepack/border_layout_panel/javascripts/border_layout_panel.js +40 -0
  11. data/lib/netzke/basepack/data_accessor.rb +3 -5
  12. data/lib/netzke/basepack/form_panel.rb +55 -52
  13. data/lib/netzke/basepack/form_panel/fields.rb +4 -2
  14. data/lib/netzke/basepack/form_panel/javascripts/comma_list_cbg.js +13 -28
  15. data/lib/netzke/basepack/form_panel/javascripts/form_panel.js +61 -34
  16. data/lib/netzke/basepack/form_panel/javascripts/n_radio_group.js +4 -3
  17. data/lib/netzke/basepack/form_panel/javascripts/readonly_mode.js +10 -10
  18. data/lib/netzke/basepack/form_panel/services.rb +1 -1
  19. data/lib/netzke/basepack/grid_panel.rb +23 -17
  20. data/lib/netzke/basepack/grid_panel/columns.rb +116 -71
  21. data/lib/netzke/basepack/grid_panel/javascripts/advanced_search.js +5 -7
  22. data/lib/netzke/basepack/grid_panel/javascripts/check_column_fix.js +6 -0
  23. data/lib/netzke/basepack/grid_panel/javascripts/edit_in_form.js +18 -15
  24. data/lib/netzke/basepack/grid_panel/javascripts/event_handling.js +178 -0
  25. data/lib/netzke/basepack/grid_panel/javascripts/grid_panel.js +230 -454
  26. data/lib/netzke/basepack/grid_panel/javascripts/rows-dd.js +1 -0
  27. data/lib/netzke/basepack/grid_panel/record_form_window.rb +8 -8
  28. data/lib/netzke/basepack/grid_panel/services.rb +12 -15
  29. data/lib/netzke/basepack/paging_form_panel.rb +1 -82
  30. data/lib/netzke/basepack/paging_form_panel/javascripts/paging_form_panel.js +76 -0
  31. data/lib/netzke/basepack/query_builder.rb +4 -4
  32. data/lib/netzke/basepack/query_builder/javascripts/query_builder.js +7 -4
  33. data/lib/netzke/basepack/search_panel.rb +1 -1
  34. data/lib/netzke/basepack/search_panel/javascripts/condition_field.js +27 -20
  35. data/lib/netzke/basepack/search_panel/javascripts/search_panel.js +4 -4
  36. data/lib/netzke/basepack/search_window.rb +4 -4
  37. data/lib/netzke/basepack/simple_app.rb +36 -8
  38. data/lib/netzke/basepack/simple_app/javascripts/simple_app.js +27 -16
  39. data/lib/netzke/basepack/tab_panel/javascripts/tab_panel.js +1 -1
  40. data/lib/netzke/basepack/version.rb +2 -2
  41. data/lib/netzke/basepack/window.rb +2 -45
  42. data/lib/netzke/basepack/window/javascripts/window.js +18 -0
  43. data/lib/netzke/basepack/wrap_lazy_loaded.rb +1 -1
  44. data/locales/de.yml +79 -0
  45. data/locales/en.yml +0 -10
  46. data/netzke-basepack.gemspec +32 -19
  47. data/stylesheets/basepack.css +16 -16
  48. data/test/rails_app/.gitignore +1 -0
  49. data/test/rails_app/Gemfile +9 -5
  50. data/test/rails_app/Gemfile.lock +51 -49
  51. data/test/rails_app/app/components/author_form.rb +32 -0
  52. data/test/rails_app/app/components/book_form.rb +6 -4
  53. data/test/rails_app/app/components/book_grid.rb +4 -3
  54. data/test/rails_app/app/components/book_grid_loader.rb +2 -2
  55. data/test/rails_app/app/components/book_grid_with_custom_columns.rb +11 -5
  56. data/test/rails_app/app/components/book_grid_with_default_values.rb +1 -1
  57. data/test/rails_app/app/components/book_grid_with_extra_feedback.rb +11 -0
  58. data/test/rails_app/app/components/book_grid_with_extra_filters.rb +14 -0
  59. data/test/rails_app/app/components/book_grid_with_paging.rb +10 -0
  60. data/test/rails_app/app/components/book_grid_with_persistence.rb +6 -0
  61. data/test/rails_app/app/components/book_paging_form_panel.rb +3 -3
  62. data/test/rails_app/app/components/book_with_custom_primary_key_grid.rb +10 -0
  63. data/test/rails_app/app/components/form_without_model.rb +5 -4
  64. data/test/rails_app/app/components/paging_form_with_search.rb +3 -2
  65. data/test/rails_app/app/components/some_auth_app.rb +3 -3
  66. data/test/rails_app/app/components/some_border_layout.rb +2 -2
  67. data/test/rails_app/app/components/some_simple_app.rb +6 -5
  68. data/test/rails_app/app/components/window_component_loader.rb +11 -2
  69. data/test/rails_app/app/controllers/components_controller.rb +1 -1
  70. data/test/rails_app/app/models/book_with_custom_primary_key.rb +4 -0
  71. data/test/rails_app/config/initializers/netzke.rb +6 -0
  72. data/test/rails_app/config/locales/es.yml +0 -10
  73. data/test/rails_app/db/migrate/20110701070052_create_book_with_custom_primary_keys.rb +15 -0
  74. data/test/rails_app/db/schema.rb +12 -2
  75. data/test/rails_app/db/seeds.rb +21 -1
  76. data/test/rails_app/features/form_panel.feature +17 -17
  77. data/test/rails_app/features/grid_panel.feature +20 -4
  78. data/test/rails_app/features/grid_panel_with_custom_primary_key.feature +15 -0
  79. data/test/rails_app/features/paging_form_panel.feature +14 -0
  80. data/test/rails_app/features/search_in_grid.feature +2 -1
  81. data/test/rails_app/features/simple_app.feature +5 -0
  82. data/test/rails_app/features/step_definitions/accordion_steps.rb +1 -5
  83. data/test/rails_app/features/step_definitions/ext_steps.rb +16 -0
  84. data/test/rails_app/features/step_definitions/form_panel_steps.rb +10 -12
  85. data/test/rails_app/features/step_definitions/generic_steps.rb +12 -4
  86. data/test/rails_app/features/step_definitions/grid_panel_steps.rb +47 -32
  87. data/test/rails_app/features/tab_panel.feature +2 -2
  88. data/test/rails_app/spec/factories.rb +4 -0
  89. metadata +26 -13
  90. data/README.rdoc +0 -67
  91. data/from_05_to_06.rdoc +0 -2
  92. data/javascripts/feedback_ghost.js +0 -34
  93. data/test/rails_app/public/netzke/basepack/ts-checkbox.gif +0 -0
@@ -1,6 +1,10 @@
1
1
  module Netzke
2
2
  module Basepack
3
- # Panel with border layout
3
+ # Panel with border layout.
4
+ #
5
+ # == Features
6
+ # * When persistence enabled, remembers the sizes and collapsed/expanded states of its regions.
7
+ #
4
8
  # == Example configuration:
5
9
  #
6
10
  # :items => [
@@ -8,13 +12,15 @@ module Netzke
8
12
  # {:title => "Item Two", :class_name => "Basepack::Panel", :region => :west, :width => 300, :split => true}
9
13
  # ]
10
14
  class BorderLayoutPanel < Netzke::Base
15
+ js_mixin :border_layout_panel
16
+
11
17
  def items
12
18
  @border_layout_items ||= begin
13
19
  updated_items = super
14
20
 
15
21
  if config[:persistence]
16
22
  updated_items.each do |item|
17
- region = item[:region] || components[item[:component]][:region]
23
+ region = item[:region] || components[item[:netzke_component]][:region]
18
24
  item.merge!({
19
25
  :width => state[:"#{region}_region_width"],
20
26
  :height => state[:"#{region}_region_height"],
@@ -22,64 +28,10 @@ module Netzke
22
28
  })
23
29
  end
24
30
  end
25
-
31
+
26
32
  updated_items
27
33
  end
28
34
  end
29
-
30
- js_property :layout, :border
31
-
32
- js_method :init_component, <<-JS
33
- function(){
34
- Ext.each(['center', 'west', 'east', 'south', 'north'], function(r){
35
- // A function to access a region component (even if the component gets reloaded, the function will work).
36
- // E.g.: getEastComponent()
37
- var methodName = 'get'+r.capitalize()+'Component';
38
- this[methodName] = function(){
39
- Netzke.deprecationWarning("Instead of '" + methodName + "' use getChildComponent('<name of your component>').");
40
- return this.find('region', r)[0];
41
- }.createDelegate(this);
42
- }, this);
43
-
44
- // Now let Ext.Panel do the rest
45
- #{js_full_class_name}.superclass.initComponent.call(this);
46
-
47
- // First time on "afterlayout", set resize events
48
- if (this.persistence) {this.on('afterlayout', this.setRegionEvents, this, {single: true});}
49
- }
50
- JS
51
-
52
- js_method :set_region_events, <<-JS
53
- function(){
54
- this.items.each(function(item, index, length){
55
- if (!item.oldSize) item.oldSize = item.getSize(); // remember initial size
56
-
57
- item.on('resize', function(panel, w, h){
58
- if (panel.region !== 'center' && w && h) {
59
- var params = {region:panel.region};
60
-
61
- if (panel.oldSize.width != w) {
62
- params.width = w;
63
- } else {
64
- params.height = h;
65
- }
66
-
67
- panel.oldSize = panel.getSize();
68
- this.regionResized(params);
69
- }
70
- }, this);
71
-
72
- item.on('collapse', function(panel){
73
- this.regionCollapsed({region: panel.region});
74
- }, this);
75
-
76
- item.on('expand', function(panel){
77
- this.regionExpanded({region: panel.region});
78
- }, this);
79
-
80
- }, this);
81
- }
82
- JS
83
35
 
84
36
  endpoint :region_resized do |params|
85
37
  size_state_hash = {}
@@ -0,0 +1,40 @@
1
+ {
2
+ layout: 'border',
3
+
4
+ initComponent: function(){
5
+ this.callParent();
6
+
7
+ // First time on "afterlayout", set resize events
8
+ if (this.persistence) {this.on('afterlayout', this.setRegionEvents, this, {single: true});}
9
+ },
10
+
11
+ setRegionEvents: function(){
12
+ this.items.each(function(item, index, length){
13
+ if (!item.oldSize) item.oldSize = item.getSize(); // remember initial size
14
+
15
+ item.on('resize', function(panel, w, h){
16
+ if (panel.region !== 'center' && w && h) {
17
+ var params = {region:panel.region};
18
+
19
+ if (panel.oldSize.width != w) {
20
+ params.width = w;
21
+ } else {
22
+ params.height = h;
23
+ }
24
+
25
+ panel.oldSize = panel.getSize();
26
+ this.regionResized(params);
27
+ }
28
+ }, this);
29
+
30
+ item.on('collapse', function(panel){
31
+ this.regionCollapsed({region: panel.region});
32
+ }, this);
33
+
34
+ item.on('expand', function(panel){
35
+ this.regionExpanded({region: panel.region});
36
+ }, this);
37
+
38
+ }, this);
39
+ }
40
+ }
@@ -1,5 +1,3 @@
1
- require 'netzke/active_record'
2
-
3
1
  module Netzke
4
2
  module Basepack
5
3
  # This module is included into such data-driven components as GridPanel, FormPanel, PagingFormPanel, etc.
@@ -14,7 +12,7 @@ module Netzke
14
12
  if options
15
13
  query ? options.select{ |o| o.index(/^#{query}/) }.map{ |el| [el] } : options
16
14
  else
17
- assoc, assoc_method = assoc_and_assoc_method_for_column(column)
15
+ assoc, assoc_method = assoc_and_assoc_method_for_attr(column)
18
16
 
19
17
  if assoc
20
18
  # Options for an asssociation attribute
@@ -66,7 +64,7 @@ module Netzke
66
64
  end
67
65
 
68
66
  # Returns association and association method for a column
69
- def assoc_and_assoc_method_for_column(c)
67
+ def assoc_and_assoc_method_for_attr(c)
70
68
  assoc_name, assoc_method = c[:name].split('__')
71
69
  assoc = data_class.reflect_on_association(assoc_name.to_sym) if assoc_method
72
70
  [assoc, assoc_method]
@@ -100,7 +98,7 @@ module Netzke
100
98
  # Mark an attribute as "virtual" by default, when it doesn't reflect a model column, or a model column of an association
101
99
  def set_default_virtual(c)
102
100
  if c[:virtual].nil? # sometimes at maybe handy to mark a column as non-virtual forcefully
103
- assoc, assoc_method = assoc_and_assoc_method_for_column(c)
101
+ assoc, assoc_method = assoc_and_assoc_method_for_attr(c)
104
102
  if assoc
105
103
  c[:virtual] = true if !assoc.klass.column_names.map(&:to_sym).include?(assoc_method.to_sym)
106
104
  else
@@ -4,22 +4,23 @@ require "netzke/basepack/form_panel/services"
4
4
 
5
5
  module Netzke
6
6
  module Basepack
7
- # Ext.form.FormPanel-based component with different goodies
7
+ # Ext.form.Panel-based component
8
8
  #
9
9
  # == Configuration
10
- # Besides all the standard +Ext.form.FormPanel+ config options, accepts:
11
10
  # * +model+ - name of the ActiveRecord model that provides data to this GridPanel.
12
11
  # * +record+ - record to be displayd in the form. Takes precedence over +:record_id+
13
12
  # * +record_id+ - id of the record to be displayd in the form. Also see +:record+
13
+ # * +items+ - the layout of the fields as an array. See "Layout configuration".
14
14
  # * +mode+ - render mode, accepted options:
15
15
  # * +lockable+ - makes the form panel load initially in "display mode", then lets "unlock" it, change the values, and "lock" it again, while updating the values on the server
16
16
  # * +updateMask+ - +Ext.LoadMask+ config options for the mask shown while the form is submitting its values
17
+ # Besides, FormPanel can accept any meaninful :
17
18
  #
18
19
  # === Layout configuration
19
20
  # The layout of the form is configured by supplying the +item+ config option, same way it would be configured in Ext (thus allowing for complex form layouts). FormPanel will expand fields by looking at their names (unless +no_binding+ set to +true+ is specified for a specific field).
20
21
  class FormPanel < Netzke::Base
21
22
 
22
- js_base_class "Ext.form.FormPanel"
23
+ js_base_class "Ext.form.Panel"
23
24
 
24
25
  # Class-level configuration
25
26
  class_attribute :config_tool_available
@@ -77,10 +78,12 @@ module Netzke
77
78
  js_include :n_radio_group, :readonly_mode
78
79
  css_include :readonly_mode
79
80
 
80
- js_include Netzke::Core.ext_location.join("examples/ux/fileuploadfield/FileUploadField.js")
81
- css_include Netzke::Core.ext_location.join("examples/ux/fileuploadfield/css/fileuploadfield.css")
81
+ # WIP
82
+ # js_include Netzke::Core.ext_path.join("examples/ux/fileuploadfield/FileUploadField.js")
83
+ # css_include Netzke::Core.ext_path.join("examples/ux/fileuploadfield/css/fileuploadfield.css")
82
84
 
83
- js_include :misc
85
+ # WIP: Needed for FileUploadField
86
+ # js_include :misc
84
87
 
85
88
  def js_config
86
89
  super.tap do |res|
@@ -98,61 +101,61 @@ module Netzke
98
101
  @record ||= config[:record] || config[:record_id] && data_class && data_class.where(data_class.primary_key => config[:record_id]).first
99
102
  end
100
103
 
101
- def configuration_components
102
- res = []
103
-
104
- res << {
105
- :name => 'fields',
106
- :class_name => "FieldsConfigurator",
107
- :active => true,
108
- :owner => self,
109
- :persistent_config => true
110
- }
111
-
112
- res << {
113
- :name => 'general',
114
- :class_name => "PropertyEditor",
115
- :component => self,
116
- :title => false
117
- }
118
-
119
- res
120
- end
104
+ # def configuration_components
105
+ # res = []
106
+ #
107
+ # res << {
108
+ # :name => 'fields',
109
+ # :class_name => "FieldsConfigurator",
110
+ # :active => true,
111
+ # :owner => self,
112
+ # :persistent_config => true
113
+ # }
114
+ #
115
+ # res << {
116
+ # :name => 'general',
117
+ # :class_name => "PropertyEditor",
118
+ # :component => self,
119
+ # :title => false
120
+ # }
121
+ #
122
+ # res
123
+ # end
124
+
125
+ def self.property_fields
126
+ res = [
127
+ {:name => "ext_config__title", :attr_type => :string},
128
+ {:name => "ext_config__header", :attr_type => :boolean, :default => true},
129
+ {:name => "ext_config__bbar", :attr_type => :json}
130
+ ]
131
+
132
+ res
133
+ end
121
134
 
122
- def self.property_fields
123
- res = [
124
- # {:name => "ext_config__title", :attr_type => :string},
125
- # {:name => "ext_config__header", :attr_type => :boolean, :default => true},
126
- # {:name => "ext_config__bbar", :attr_type => :json}
127
- ]
135
+ private
128
136
 
129
- res
137
+ def self.server_side_config_options
138
+ super + [:record, :scope]
130
139
  end
131
140
 
132
- private
133
-
134
- def self.server_side_config_options
135
- super + [:record, :scope]
141
+ def meta_field
142
+ {}.tap do |res|
143
+ assoc_values = get_association_values
144
+ res[:association_values] = assoc_values.literalize_keys if record && !assoc_values.empty?
136
145
  end
146
+ end
137
147
 
138
- def meta_field
139
- {}.tap do |res|
140
- assoc_values = get_association_values
141
- res[:association_values] = assoc_values.literalize_keys if record && !assoc_values.empty?
142
- end
148
+ def get_association_values
149
+ fields_that_need_associated_values = fields.select{ |k,v| k.to_s.index("__") && !fields[k][:nested_attribute] }
150
+ # Take care of Ruby 1.8.7
151
+ if fields_that_need_associated_values.is_a?(Array)
152
+ fields_that_need_associated_values = fields_that_need_associated_values.inject({}){|r,(k,v)| r.merge(k => v)}
143
153
  end
144
154
 
145
- def get_association_values
146
- fields_that_need_associated_values = fields.select{ |k,v| k.to_s.index("__") && !fields[k][:nested_attribute] }
147
- # Take care of Ruby 1.8.7
148
- if fields_that_need_associated_values.is_a?(Array)
149
- fields_that_need_associated_values = fields_that_need_associated_values.inject({}){|r,(k,v)| r.merge(k => v)}
150
- end
151
-
152
- fields_that_need_associated_values.each_pair.inject({}) do |r,(k,v)|
153
- r.merge(k => record.value_for_attribute(fields_that_need_associated_values[k], true))
154
- end
155
+ fields_that_need_associated_values.each_pair.inject({}) do |r,(k,v)|
156
+ r.merge(k => record.value_for_attribute(fields_that_need_associated_values[k], true))
155
157
  end
158
+ end
156
159
 
157
160
  # include ::Netzke::Plugins::ConfigurationTool if config_tool_available # it will load ConfigurationPanel into a modal window
158
161
  end
@@ -179,9 +179,11 @@ module Netzke
179
179
  def attr_type_to_xtype_map
180
180
  {
181
181
  :integer => :numberfield,
182
- :boolean => :checkbox,
182
+ :boolean => :checkboxfield,
183
183
  :date => :datefield,
184
- :datetime => :datetimefield,
184
+ # WIP: waiting for datetime.js implementation for ExtJS 4
185
+ # :datetime => :datetimefield,
186
+
185
187
  :text => :textarea,
186
188
  :json => :jsonfield,
187
189
  :string => :textfield
@@ -6,52 +6,38 @@ Config options:
6
6
  * separator - separator of values in the string (defaults to ",")
7
7
  * options - all checkboxes, by boxLabel, e.g.: ["Cool", "To read", "Important"]
8
8
  */
9
- Ext.netzke.form.CommaListCbg = Ext.extend(Ext.form.CheckboxGroup, {
9
+ Ext.define('Ext.netzke.form.CommaListCbg', {
10
+ extend: 'Ext.form.CheckboxGroup',
11
+ alias: 'widget.commalistcbg',
10
12
  separator: ",",
11
13
 
12
14
  initComponent: function(){
13
- Ext.netzke.form.CommaListCbg.superclass.initComponent.call(this);
14
-
15
15
  this.items = [];
16
16
  Ext.each(this.options, function(o){
17
- this.items.push({boxLabel: o});
18
- }, this);
19
-
20
- this.on('change', function(el){
21
- this.hiddenEl.dom.value = this.getValue();
17
+ this.items.push({ boxLabel: o, displayOnly:true });
22
18
  }, this);
23
- },
24
19
 
25
- onRender: function(ct, position){
26
- Ext.netzke.form.CommaListCbg.superclass.onRender.call(this, ct, position)
27
- this.hiddenEl = Ext.DomHelper.append(ct, {tag:'input', type: 'hidden', name: this.name}, true);
28
-
29
- // Don't submit individual checkboxes
30
- this.items.each(function(i){
31
- i.el.dom.removeAttribute("name");
32
- });
20
+ this.callParent();
33
21
  },
34
22
 
35
- getValue: function(){
36
- var checkedBoxes = Ext.netzke.form.CommaListCbg.superclass.getValue.call(this);
23
+ getSubmitData: function(){
37
24
  var res = [];
38
- Ext.each(checkedBoxes, function(cb){
39
- res.push(cb.boxLabel);
40
- });
25
+ Ext.each(this.getChecked(), function( item ){ res.push( item.boxLabel ) });
41
26
  res = res.join(this.separator);
42
- return res;
27
+ var o = {};
28
+ o[this.name]=res;
29
+ return o;
43
30
  },
44
31
 
45
32
  setValue: function(v){
46
33
  if (Ext.isString(v)) {
47
34
  var passedValues = v.split(this.separator);
48
- var values = [];
49
35
  this.items.each(function(i){
50
- values.push(passedValues.indexOf(i.boxLabel) >= 0);
36
+ i.setValue( passedValues.indexOf(i.boxLabel) >= 0 );
51
37
  });
52
- Ext.netzke.form.CommaListCbg.superclass.setValue.call(this, values);
38
+ // we can alse set values the Ext way
53
39
  } else {
54
- Ext.netzke.form.CommaListCbg.superclass.setValue.call(this, arguments);
40
+ this.callParent(arguments);
55
41
  }
56
42
  },
57
43
 
@@ -63,4 +49,3 @@ Ext.netzke.form.CommaListCbg = Ext.extend(Ext.form.CheckboxGroup, {
63
49
 
64
50
  });
65
51
 
66
- Ext.reg('commalistcbg', Ext.netzke.form.CommaListCbg);
@@ -1,8 +1,8 @@
1
1
  {
2
2
  bodyStyle : 'padding:5px 5px 0',
3
3
  autoScroll : true,
4
- labelWidth : 150,
5
- applyMask : {msg: "Updating..."},
4
+ fieldDefaults : { labelWidth : 150 },
5
+ applyMask : { msg: "Updating..." },
6
6
 
7
7
  defaults : {
8
8
  anchor : '-20', // to leave some space for the scrollbar
@@ -17,6 +17,13 @@
17
17
  },
18
18
 
19
19
  initComponent: function(){
20
+ // passing config options to BasicForm is possible via initialConfig only
21
+ // see Ext.form.Panel documentation
22
+ this.initialConfig = {
23
+ // form tracks it's default field values so they can be reset()
24
+ trackResetOnLoad: true,
25
+ }
26
+
20
27
  if (!this.bbar) this.bbar = {xtype: 'toolbar'}; // an empty bbar by default, so that we can dynamically add buttons
21
28
 
22
29
  // Custom error reader. We don't use it to process form values, but rather to normalize the response from the server in case of "real" (iframe) form submit.
@@ -32,15 +39,17 @@
32
39
 
33
40
  this.initialConfig.errorReader = new ErrorReader();
34
41
 
42
+ // this.getForm().trackResetOnLoad = true;
43
+
35
44
  // Now let Ext.form.FormPanel do the rest
36
- Netzke.classes.Basepack.FormPanel.superclass.initComponent.call(this);
45
+ this.callParent(arguments);
37
46
 
38
47
  // To inform the parent about the apply event
39
- this.addEvents('apply');
48
+ this.addEvents('apply', 'cancel');
40
49
  },
41
50
 
42
51
  afterRender: function(){
43
- Netzke.classes.Basepack.FormPanel.superclass.afterRender.call(this);
52
+ this.callParent();
44
53
 
45
54
  // have a record to be displayed?
46
55
  if (this.record) { this.setFormValues(this.record); }
@@ -54,33 +63,39 @@
54
63
  },
55
64
 
56
65
  onCancel: function(){
66
+ this.getForm().reset();
57
67
  this.setReadonlyMode(true, true);
58
68
  },
59
69
 
60
70
  updateToolbar: function(){
61
- var tbar = this.getBottomToolbar();
62
-
63
- if (this.inReadonlyMode) {
64
- var buttonIndex = tbar.items.findIndex("name", "apply");
65
- var buttonToRemove = tbar.items.itemAt(buttonIndex);
66
- if (buttonToRemove) {
67
- tbar.remove(buttonToRemove);
71
+ var tbar = this.child('toolbar');
72
+
73
+ if ( this.inReadonlyMode ) {
74
+ // if the form in readonly mode, remove "Apply" and "Cancel"
75
+ // buttons from toolbar and add "Edit" button
76
+ var buttonToRemove = tbar.child("button[name='apply']");
77
+ if ( buttonToRemove ) {
78
+ tbar.remove( buttonToRemove );
68
79
  }
69
80
 
70
- var buttonIndex = tbar.items.findIndex("name", "cancel");
71
- var buttonToRemove = tbar.items.itemAt(buttonIndex);
72
- if (buttonToRemove) {
73
- tbar.remove(buttonToRemove);
81
+ var buttonToRemove = tbar.child("button[name='cancel']");
82
+ if ( buttonToRemove ) {
83
+ tbar.remove( buttonToRemove );
74
84
  }
75
- tbar.add(this.actions.edit);
85
+
86
+ tbar.add( this.actions.edit );
87
+
76
88
  } else {
89
+ // if the form editable, remove "edit" button and
90
+ // insert "apply" and "cancel" instead
91
+
77
92
  var buttonIndex = tbar.items.findIndex("name", "edit");
78
- var buttonToRemove = tbar.items.itemAt(buttonIndex);
93
+ var buttonToRemove = tbar.items.getAt(buttonIndex);
79
94
  if (buttonToRemove) {
80
95
  tbar.remove(buttonToRemove);
81
96
  }
82
- tbar.insertButton(buttonIndex, this.actions.apply);
83
- tbar.insertButton(buttonIndex, this.actions.cancel);
97
+ tbar.insert( buttonIndex, this.actions.cancel );
98
+ tbar.insert( buttonIndex, this.actions.apply );
84
99
  }
85
100
 
86
101
  tbar.doLayout();
@@ -88,33 +103,40 @@
88
103
 
89
104
  onApply: function() {
90
105
  if (this.fireEvent('apply', this)) {
91
- var values = this.getForm().getFieldValues();
92
-
106
+ var values = this.getForm().getValues();
93
107
  for (var fieldName in values) {
94
108
  var field = this.getForm().findField(fieldName);
95
109
 
96
110
  // TODO: move the following checks to the server side (through the :display_only option)
97
111
 
98
112
  // do not submit values from disabled fields
99
- if (!field || field.disabled) delete values[fieldName];
113
+ if (!field || field.disabled) {
114
+ delete values[fieldName];
115
+ }
100
116
 
101
117
  // do not submit values from read-only association fields
102
118
  if (field
103
119
  && field.name.indexOf("__") !== -1
104
- && (field.readOnly || !field.getStore)
120
+ && (field.readOnly || !field.isXType('combobox'))
105
121
  && (!field.nestedAttribute) // except for "nested attributes"
106
- ) delete values[fieldName];
122
+ ) {
123
+ delete values[fieldName];
124
+ }
107
125
 
108
126
  // do not submit values from displayfields
109
- if (field.isXType('displayfield')) delete values[fieldName];
127
+ if (field.isXType('displayfield')) {
128
+ delete values[fieldName];
129
+ }
110
130
 
111
131
  // do not submit displayOnly fields
112
- if (field.displayOnly) delete values[fieldName];
132
+ if (field.displayOnly) {
133
+ delete values[fieldName];
134
+ }
113
135
  }
114
-
136
+ // WIP: commented out on 2011-05-11 because of fatal errors
115
137
  // apply mask
116
- if (!this.applyMaskCmp) this.applyMaskCmp = new Ext.LoadMask(this.bwrap, this.applyMask);
117
- this.applyMaskCmp.show();
138
+ // if (!this.applyMaskCmp) this.applyMaskCmp = new Ext.LoadMask(this.bwrap, this.applyMask);
139
+ // this.applyMaskCmp.show();
118
140
 
119
141
  // We must use a different approach when the form is multipart, as we can't use the endpoint
120
142
  if (this.fileUpload) {
@@ -155,9 +177,11 @@
155
177
  setFormValues: function(values){
156
178
  var assocValues = values._meta.associationValues || {};
157
179
  for (var assocFieldName in assocValues) {
158
- var assocField = this.find('name', assocFieldName)[0];
159
- if (assocField.getStore) {
160
- assocField.getStore().loadData({data: [[values[assocFieldName], assocValues[assocFieldName]]]});
180
+
181
+ var assocField = this.getForm().getFields().filter('name', assocFieldName).first();
182
+ if (assocField.isXType('combobox')) {
183
+ // HACK: using private property 'store' here!
184
+ assocField.store.loadData([[values[assocFieldName], assocValues[assocFieldName]]]);
161
185
  delete assocField.lastQuery; // force loading the store next time user clicks the trigger
162
186
  } else {
163
187
  assocField.setValue(assocValues[assocFieldName]);
@@ -170,7 +194,10 @@
170
194
 
171
195
  setReadonlyMode: function(onOff, cancel){
172
196
  if (this.inReadonlyMode == onOff) return;
173
- this.getForm().items.each(function(i){i.setReadonlyMode(onOff);});
197
+ this.getForm().getFields().each(function(i){
198
+ if (i.setReadonlyMode) i.setReadonlyMode(onOff);
199
+ });
200
+
174
201
  // this.getForm().cleanDestroyed(); // because fields inside of composite fields are not auto-cleaned!
175
202
  this.doLayout();
176
203
  this.inReadonlyMode = onOff;