netzke-basepack 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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;