netzke-basepack 0.6.2 → 0.6.3

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 (104) hide show
  1. data/CHANGELOG.rdoc +27 -2
  2. data/TODO.rdoc +1 -5
  3. data/app/models/netzke_persistent_array_auto_model.rb +0 -1
  4. data/features/components_in_view.feature +11 -0
  5. data/features/form_panel.feature +49 -0
  6. data/features/grid_panel.feature +32 -1
  7. data/features/i18n.feature +18 -0
  8. data/features/nested_attributes.feature +23 -0
  9. data/features/search_in_grid.feature +9 -9
  10. data/features/simple_app.feature +10 -0
  11. data/features/step_definitions/grid_panel_steps.rb +23 -0
  12. data/features/support/paths.rb +6 -0
  13. data/features/support/pickle.rb +0 -1
  14. data/features/virtual_attributes.feature +20 -0
  15. data/javascripts/basepack.js +166 -243
  16. data/lib/netzke-basepack.rb +3 -3
  17. data/lib/netzke/active_record.rb +6 -7
  18. data/lib/netzke/active_record/attributes.rb +214 -143
  19. data/lib/netzke/active_record/combobox_options.rb +12 -10
  20. data/lib/netzke/basepack.rb +6 -3
  21. data/lib/netzke/basepack/accordion_panel.rb +4 -2
  22. data/lib/netzke/basepack/auth_app.rb +152 -0
  23. data/lib/netzke/basepack/basic_app.rb +2 -262
  24. data/lib/netzke/basepack/form_panel.rb +35 -27
  25. data/lib/netzke/basepack/form_panel/fields.rb +35 -17
  26. data/lib/netzke/basepack/form_panel/javascripts/comma_list_cbg.js +59 -0
  27. data/lib/netzke/basepack/form_panel/javascripts/display_mode.js +62 -0
  28. data/lib/netzke/basepack/form_panel/javascripts/main.js +138 -0
  29. data/lib/netzke/basepack/form_panel/javascripts/n_radio_group.js +25 -0
  30. data/lib/netzke/basepack/form_panel/services.rb +12 -9
  31. data/lib/netzke/basepack/grid_panel.rb +87 -53
  32. data/lib/netzke/basepack/grid_panel/columns.rb +60 -15
  33. data/lib/netzke/basepack/grid_panel/javascripts/advanced_search.js +2 -64
  34. data/lib/netzke/basepack/grid_panel/javascripts/edit_in_form.js +2 -2
  35. data/lib/netzke/basepack/grid_panel/javascripts/{pre.js → main.js} +35 -17
  36. data/lib/netzke/basepack/grid_panel/javascripts/misc.js +4 -0
  37. data/lib/netzke/basepack/grid_panel/services.rb +17 -14
  38. data/lib/netzke/basepack/paging_form_panel.rb +92 -0
  39. data/lib/netzke/basepack/simple_app.rb +71 -0
  40. data/lib/netzke/basepack/simple_app/javascripts/main.js +53 -0
  41. data/lib/netzke/basepack/{basic_app → simple_app/javascripts}/statusbar_ext.js +0 -0
  42. data/lib/netzke/basepack/tab_panel.rb +2 -12
  43. data/lib/netzke/basepack/tab_panel/javascripts/main.js +11 -0
  44. data/lib/netzke/basepack/version.rb +2 -2
  45. data/lib/netzke/basepack/window.rb +6 -7
  46. data/lib/netzke/basepack/wrap_lazy_loaded.rb +3 -1
  47. data/lib/netzke/data_accessor.rb +25 -14
  48. data/lib/netzke/ext.rb +1 -1
  49. data/locales/en.yml +22 -0
  50. data/netzke-basepack.gemspec +66 -12
  51. data/spec/active_record/attributes_spec.rb +31 -2
  52. data/spec/factories.rb +16 -1
  53. data/test/rails_app/Gemfile +2 -2
  54. data/test/rails_app/Gemfile.lock +76 -77
  55. data/test/rails_app/app/components/author_grid.rb +7 -0
  56. data/test/rails_app/app/components/book_form.rb +24 -0
  57. data/test/rails_app/app/components/book_grid.rb +6 -1
  58. data/test/rails_app/app/components/book_grid_with_default_values.rb +11 -0
  59. data/test/rails_app/app/components/book_grid_with_nested_attributes.rb +13 -0
  60. data/test/rails_app/app/components/book_grid_with_virtual_attributes.rb +22 -0
  61. data/test/rails_app/app/components/book_paging_form_panel.rb +20 -0
  62. data/test/rails_app/app/components/book_presentation.rb +18 -0
  63. data/test/rails_app/app/components/books_bound_to_author.rb +10 -0
  64. data/test/rails_app/app/components/form_without_model.rb +19 -0
  65. data/test/rails_app/app/components/lockable_book_form.rb +17 -0
  66. data/test/rails_app/app/components/lockable_user_form.rb +7 -0
  67. data/test/rails_app/app/components/simple_window.rb +10 -0
  68. data/test/rails_app/app/components/some_accordion_panel.rb +22 -0
  69. data/test/rails_app/app/components/{simple_basic_app.rb → some_auth_app.rb} +3 -3
  70. data/test/rails_app/app/components/some_border_layout.rb +10 -7
  71. data/test/rails_app/app/components/some_simple_app.rb +34 -0
  72. data/test/rails_app/app/components/some_tab_panel.rb +16 -11
  73. data/test/rails_app/app/components/user_form.rb +11 -4
  74. data/test/rails_app/app/components/user_grid.rb +7 -1
  75. data/test/rails_app/app/components/window_component_loader.rb +1 -0
  76. data/test/rails_app/app/controllers/application_controller.rb +6 -0
  77. data/test/rails_app/app/controllers/components_controller.rb +3 -3
  78. data/test/rails_app/app/controllers/welcome_controller.rb +2 -2
  79. data/test/rails_app/app/helpers/embedded_components_helper.rb +2 -0
  80. data/test/rails_app/app/models/address.rb +3 -0
  81. data/test/rails_app/app/models/author.rb +2 -0
  82. data/test/rails_app/app/models/book.rb +1 -0
  83. data/test/rails_app/app/models/user.rb +1 -2
  84. data/test/rails_app/app/views/components/simple_panel.html.erb +1 -0
  85. data/test/rails_app/app/views/layouts/nested.html.erb +5 -0
  86. data/test/rails_app/config/application.rb +1 -1
  87. data/test/rails_app/config/initializers/netzke.rb +0 -4
  88. data/test/rails_app/config/locales/es.yml +16 -0
  89. data/test/rails_app/config/routes.rb +4 -1
  90. data/test/rails_app/db/development_structure.sql +33 -4
  91. data/test/rails_app/db/migrate/20101026190021_create_books.rb +2 -0
  92. data/test/rails_app/db/migrate/20110101143818_create_addresses.rb +17 -0
  93. data/test/rails_app/db/schema.rb +33 -1
  94. data/test/rails_app/spec/controllers/embedded_components_controller_spec.rb +12 -0
  95. data/test/rails_app/spec/helpers/embedded_components_helper_spec.rb +15 -0
  96. data/test/rails_app/spec/models/address_spec.rb +5 -0
  97. data/test/rails_app/spec/views/embedded_components/index.html.erb_spec.rb +5 -0
  98. metadata +67 -13
  99. data/features/basic_app.feature +0 -12
  100. data/lib/netzke/active_record/association_attributes.rb +0 -102
  101. data/lib/netzke/basepack/form_panel/javascripts/pre.js +0 -76
  102. data/lib/netzke/basepack/form_panel/javascripts/xcheckbox.js +0 -82
  103. data/lib/netzke/basepack/grid_panel/javascript.rb +0 -69
  104. data/locale/en.yml +0 -16
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,28 @@
1
+ = v0.6.3 - 2011-01-14
2
+ * compatibility with netzke-core 0.6.5
3
+
4
+ * refactoring
5
+ * GridPanel code restructured, using the new +js_mixin+ method
6
+
7
+ * bug fix
8
+ * GridPanel respects strong_default_attrs
9
+ * TabPanel doesn't fire multiple load requests per tab in case of lazy-loaded tabs and fast clicking
10
+ * Filtering/sorting on virtual columns is now disabled by default
11
+ * Filtering on date columns
12
+
13
+ * enhancements
14
+ * I18n for Grid/FormPanel
15
+ * new +getter+ config option for columns/fields, a lambda receiving the record as parameter
16
+ * new +setter+ config option for columns/fields, a lambda receiving the record as first parameter, new value as the second
17
+ * GridPanel passes columns' default values to the "Add in form" form
18
+ * FormPanel can now be used without specifying a model
19
+ * New +commalistcbg+ form field for checkboxes, where boxLabels of selected checkboxes are serialized into comma-separated string (the separator is configurable)
20
+ * New +nradiogroup+ form field for radio buttons, where the value is defined by the boxLabel of the selected radio button
21
+ * New +no_binding+ option for configuring a form field. Set it to "true" when you don't want Netzke to expand the field configuration based on the +name+ property. May be needed in some cases, e.g. when using checkboxes/radio buttons in the form.
22
+ * New +nested_attribute+ option for configuring data attributes (thus applicable for a column, a field, or a +netzke_attribute+ in the model). When set to true for an association attribute (e.g. author__name), assigning a value to it will change the association's attribute, *not* trying to find an association by name and reassign it if found (default behavior).
23
+ * FormPanel shows the "Updating..." mask while sending values to the server (configurable with updateMask option/property)
24
+ * FormPanel now can be used in the "lockable" mode (:config => :lockable), which makes it load initially in "display mode", then "unlock" it, change the values, and "lock" it again (updating the values on the server)
25
+
1
26
  = v0.6.2 - 2010-11-05
2
27
  * compatibility with netzke-core 0.6.4
3
28
  * bug fix
@@ -7,7 +32,7 @@
7
32
  * enhancements
8
33
  * BorderLayoutPanel persistence: remembers region sizes and collapsed/expanded states
9
34
  * tooltips for grid buttons
10
-
35
+
11
36
  * bug fix
12
37
  * auto-detection of association's method when the latter is virtual was broken in 1.9.2
13
38
 
@@ -321,4 +346,4 @@
321
346
  * Meta work: replacing underscore with dash in the name
322
347
 
323
348
  = v0.1.0 - 2008-12-20
324
- * Initial release
349
+ * Initial release
data/TODO.rdoc CHANGED
@@ -1,6 +1,5 @@
1
1
  == Priority
2
- * Fix :meta => true config in columns work
3
- * On grid refresh, reset the dirty fields, so that the "Apply" button doesn't do anything
2
+ * Make GridPanel show the mask straight after pressing "Apply"
4
3
  * DataAccessor#to_array should not rescue exceptions, but rather check the availability of the attributes; `respond_to_with_basepack?` should be extended to also return true for association columns
5
4
  * GridPanel's read_only vs editable (doesn't work now) options
6
5
  * Find a way to print the grid nicely (along with the column and rows that don't fit on the screen)
@@ -10,6 +9,3 @@
10
9
 
11
10
  == Optimizations
12
11
  * Check persistent_config-related queries (aren't they too many?)
13
-
14
- == One day
15
- * Replace xcheckbox with checkbox in FormPanel
@@ -41,7 +41,6 @@ class NetzkePersistentArrayAutoModel < ActiveRecord::Base
41
41
  # only select those attributes that were provided to us as columns. The rest is ignored.
42
42
  column_names = config[:columns].map{ |c| c[:name] }
43
43
  clean_data = data.collect{ |c| c.reject{ |k,v| !column_names.include?(k.to_s) } }
44
- Rails.logger.debug "!!! clean_data: #{clean_data.inspect}\n"
45
44
  self.delete_all
46
45
  self.create(clean_data)
47
46
  end
@@ -0,0 +1,11 @@
1
+ Feature: Components in view
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ @javascript
7
+ Scenario: Components configured in the view should render properly
8
+ When I go to the "simple panel" view
9
+ Then I should see "Simple Panel content"
10
+ When I press "Update html"
11
+ Then I should see "HTML received from server"
@@ -38,3 +38,52 @@ Scenario: UserFormWithDefaultFields should render properly
38
38
  And I should see "Castaneda"
39
39
  And I should see "writer"
40
40
 
41
+ @javascript
42
+ Scenario: FormPanel should be functional without model provided
43
+ Given I am on the FormWithoutModel test page
44
+ When I fill in "Text field:" with "Some text"
45
+ And I fill in "Number field:" with "42"
46
+ And I check "Boolean field:"
47
+ And I press "Apply"
48
+
49
+ Then I should see "Text field: Some text"
50
+ And I should see "Number field: 42"
51
+ And I should see "Boolean field: true"
52
+
53
+ @javascript
54
+ Scenario: Checkbox field should work properly
55
+ Given an author exists with first_name: "Carlos"
56
+ And a book exists with author: that author, digitized: false, exemplars: 2, title: "Some Title"
57
+ When I go to the BookForm test page
58
+ And I fill in "Exemplars:" with "4"
59
+ And I check "Digitized:"
60
+ And I press "Apply"
61
+ Then I should see "YES"
62
+ And a book should exist with digitized: true, author: that author, exemplars: 4
63
+ And a book should not exist with digitized: false, author: that author
64
+
65
+ @javascript
66
+ Scenario: Checkbox group for tags should work properly
67
+ Given a book exists with title: "Some Title"
68
+ When I go to the BookForm test page
69
+ And I check "recommend"
70
+ And I check "cool"
71
+ And I press "Apply"
72
+ Then the "cool" checkbox should be checked
73
+ And the "recommend" checkbox should be checked
74
+ But the "read" checkbox should not be checked
75
+ And a book should exist with tags: "cool,recommend"
76
+
77
+ # Needs cleaner check whether AJAX request was completed
78
+ # @javascript
79
+ # Scenario: Validations
80
+ # Given a book exists with title: "Some Title"
81
+ # When I go to the BookForm test page
82
+ # And I fill in "Title:" with ""
83
+ # And I press "Apply"
84
+ # And I sleep 1 second
85
+ # Then I should see "Title can't be blank"
86
+ # When I fill in "Title:" with ""
87
+ # And I press "Apply"
88
+ # And I sleep 1 second
89
+ # Then I should not see "Title can't be blank"
@@ -57,7 +57,8 @@ Scenario: Multi-editing records
57
57
  And I press "Edit in form"
58
58
  And I fill in "First name:" with "Maxim"
59
59
  And I press "OK"
60
- Then the following users should exist:
60
+ Then I should see "Updated 2 records."
61
+ And the following users should exist:
61
62
  | first_name | last_name |
62
63
  | Maxim | Castaneda |
63
64
  | Maxim | Hesse |
@@ -71,4 +72,34 @@ Scenario: Filling out association column with association's virtual method
71
72
  Then I should see "Nabokov, Vladimir"
72
73
  And I should see "Lolita"
73
74
 
75
+ @javascript
76
+ Scenario: Grid with strong_default_attrs
77
+ Given an author exists with first_name: "Vladimir", last_name: "Nabokov"
78
+ And a book exists with title: "Lolita", author: that author
79
+ And a book exists with title: "Unknown"
80
+ When I go to the BooksBoundToAuthor test page
81
+ And I press "Add in form"
82
+ And I fill in "Title:" with "The Luzhin Defence"
83
+ And I press "OK"
84
+ And I should see "The Luzhin Defence"
85
+ And I should see "Lolita"
86
+ But I should not see "Unknown"
74
87
 
88
+ @javascript
89
+ Scenario: Grid with columns with default values
90
+ Given I am on the BookGridWithDefaultValues test page
91
+ When I press "Add in form"
92
+ And I press "OK"
93
+ And I sleep 1 second
94
+ Then a book should exist with title: "Lolita", exemplars: 100
95
+
96
+ @javascript
97
+ Scenario: Inline editing
98
+ Given a book exists with title: "Magus", exemplars: 100
99
+ When I go to the BookGrid test page
100
+ And I edit row 1 of the grid with title: "Collector", exemplars: 200
101
+ And I press "Apply"
102
+ And I sleep 1 second
103
+ Then the grid should have 0 modified records
104
+ And a book should exist with title: "Collector", exemplars: 200
105
+ But a book should not exist with title: "Magus"
@@ -0,0 +1,18 @@
1
+ Feature: I18n
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ Scenario: A grid with localized column headers
7
+ When I go to the "es" version of the BookGrid page
8
+ Then I should see "Autor"
9
+ And I should see "Creado en"
10
+ But I should not see "Author"
11
+ And I should not see "Created at"
12
+
13
+ Scenario: A form with localized field labels
14
+ When I go to the "es" version of the BookForm page
15
+ Then I should see "Autor"
16
+ And I should see "En abundancia"
17
+ But I should not see "Author"
18
+ And I should not see "In abundance"
@@ -0,0 +1,23 @@
1
+ Feature: Nested attributes
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ @javascript
7
+ Scenario: Grid with nested attributes
8
+ Given an author exists with first_name: "Vlad", last_name: "Nabokoff"
9
+ And a book exists with title: "Lola", author: that author
10
+ When I go to the BookGridWithNestedAttributes test page
11
+ And I select first row in the grid
12
+ And I press "Edit in form"
13
+ And I fill in "Author first name:" with "Vladimir"
14
+ And I fill in "Author last name:" with "Nabokov"
15
+ And I fill in "Title:" with "Lolita"
16
+ And I press "OK"
17
+
18
+ Then I should see "Nabokov"
19
+ Then an author should exist with first_name: "Vladimir", last_name: "Nabokov"
20
+ And a book should exist with title: "Lolita", author: that author
21
+
22
+ But an author should not exist with first_name: "Vlad"
23
+ And a book should not exist with title: "Lola"
@@ -6,17 +6,17 @@ Feature: Search
6
6
  @javascript
7
7
  Scenario: Search via Search window
8
8
  Given the following roles exist:
9
- | name |
10
- | admin |
11
- | superadmin |
12
- | user |
9
+ | id | name |
10
+ | 1 | admin |
11
+ | 2 | superadmin |
12
+ | 3 | user |
13
13
 
14
14
  And the following users exist:
15
- | first_name | last_name | role__name |
16
- | Paul | Bley | admin |
17
- | Dalai | Lama | user |
18
- | Taisha | Abelar | superadmin |
19
- | Florinda | Donner | admin |
15
+ | first_name | last_name | role_id |
16
+ | Paul | Bley | 1 |
17
+ | Dalai | Lama | 3 |
18
+ | Taisha | Abelar | 2 |
19
+ | Florinda | Donner | 1 |
20
20
 
21
21
  When I go to the UserGrid test page
22
22
  Then the grid should show 4 records
@@ -0,0 +1,10 @@
1
+ Feature: Basic application
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ @javascript
7
+ Scenario: SimpleApp should load its components dynamically
8
+ Given I am on the SomeSimpleApp test page
9
+ When I press "Simple accordion"
10
+ Then I should see "Some simple app simple accordion"
@@ -24,3 +24,26 @@ Then /^the grid should show (\d+) records$/ do |arg1|
24
24
  return grid.getStore().getCount();
25
25
  JS
26
26
  end
27
+
28
+ When /^I edit row (\d+) of the grid with #{capture_fields}$/ do |rowIndex, fields|
29
+ fields = ActiveSupport::JSON.decode("{#{fields}}")
30
+ js_set_fields = fields.each_pair.map do |k,v|
31
+ "r.set('#{k}', '#{v}');"
32
+ end.join
33
+ page.driver.browser.execute_script <<-JS
34
+ var components = [];
35
+ for (var cmp in Netzke.page) { components.push(cmp); }
36
+ var grid = Netzke.page[components[0]];
37
+ var r = grid.getStore().getAt(#{rowIndex.to_i-1});
38
+ #{js_set_fields}
39
+ JS
40
+ end
41
+
42
+ Then /^the grid should have (\d+) modified records$/ do |n|
43
+ page.driver.browser.execute_script(<<-JS).should == n.to_i
44
+ var components = [];
45
+ for (var cmp in Netzke.page) { components.push(cmp); }
46
+ var grid = Netzke.page[components[0]];
47
+ return grid.getStore().getModifiedRecords().length;
48
+ JS
49
+ end
@@ -40,9 +40,15 @@ module NavigationHelpers
40
40
  when /the component loader page/
41
41
  '/panel/component_loader'
42
42
 
43
+ when /the "(.*)" view/
44
+ embedded_components_path(:action => $1.gsub(" ", "_"))
45
+
43
46
  when /the (.*) test page/
44
47
  components_path(:component => $1)
45
48
 
49
+ when /the "(.+)" version of the (.*) page/
50
+ components_path(:component => $2, :locale => $1)
51
+
46
52
  else
47
53
  begin
48
54
  page_name =~ /the (.*) page/
@@ -22,4 +22,3 @@ require 'pickle/world'
22
22
  # config.adapters = [:machinist]
23
23
  # config.map 'I', 'myself', 'me', 'my', :to => 'user: "me"'
24
24
  # end
25
- require 'pickle/path/world'
@@ -0,0 +1,20 @@
1
+ Feature: Window component loader
2
+ In order to value
3
+ As a role
4
+ I want feature
5
+
6
+ @javascript
7
+ Scenario: Columns and fields with custom setter/getter methods should work as expected
8
+ Given an author exists with first_name: "Victor"
9
+ And a book exists with title: "Lolita", exemplars: "5", author: that author
10
+ And I am on the BookGridWithVirtualAttributes test page
11
+ Then I should see "Victor"
12
+ And I should see "YES"
13
+
14
+ When I select first row in the grid
15
+ And I press "Edit in form"
16
+ And I fill in "Author first name" with "Vladimir"
17
+ And I fill in "Exemplars" with "3"
18
+ And I press "OK"
19
+ Then I should see "Vladimir"
20
+ And I should see "NO"
@@ -1,4 +1,5 @@
1
1
  Ext.ns("Netzke.pre");
2
+ Ext.ns("Netzke.pre.Basepack");
2
3
  Ext.ns("Ext.ux.grid");
3
4
 
4
5
  Ext.apply(Ext.History, new Ext.util.Observable());
@@ -38,12 +39,12 @@ Ext.netzke.ComboBox = Ext.extend(Ext.form.ComboBox, {
38
39
  });
39
40
 
40
41
  var parent = Ext.getCmp(this.parentId);
41
- // Is parent a grid?
42
- if (parent.getSelectionModel) {
43
- this.on('beforequery',function(qe) {
44
- delete qe.combo.lastQuery;
45
- },this);
46
- }
42
+ // Is parent a grid?
43
+ if (parent.getSelectionModel) {
44
+ this.on('beforequery',function(qe) {
45
+ delete qe.combo.lastQuery;
46
+ },this);
47
+ }
47
48
 
48
49
  // A not-so-clean approach to submit the current record id
49
50
  store.on('beforeload',function(store, options){
@@ -53,7 +54,7 @@ Ext.netzke.ComboBox = Ext.extend(Ext.form.ComboBox, {
53
54
  } else {
54
55
  // TODO: also for the FormPanel
55
56
  }
56
- },this)
57
+ }, this);
57
58
  }
58
59
  });
59
60
 
@@ -63,65 +64,6 @@ Ext.util.Format.mask = function(v){
63
64
  return "********";
64
65
  };
65
66
 
66
- // Implementation of totalProperty, successProperty and root configuration options for ArrayReader
67
- Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
68
- readRecords : function(o){
69
- var sid = this.meta ? this.meta.id : null;
70
- var recordType = this.recordType, fields = recordType.prototype.fields;
71
- var records = [];
72
- var root = o[this.meta.root] || o, totalRecords = o[this.meta.totalProperty], success = o[this.meta.successProperty];
73
- for(var i = 0; i < root.length; i++){
74
- var n = root[i];
75
- var values = {};
76
- var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
77
- for(var j = 0, jlen = fields.length; j < jlen; j++){
78
- var f = fields.items[j];
79
- var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
80
- var v = n[k] !== undefined ? n[k] : f.defaultValue;
81
- v = f.convert(v, n);
82
- values[f.name] = v;
83
- }
84
- var record = new recordType(values, id);
85
- record.json = n;
86
- records[records.length] = record;
87
- }
88
- return {
89
- records : records,
90
- totalRecords : totalRecords,
91
- success : success
92
- };
93
- }
94
- });
95
-
96
-
97
- Ext.data.RecordArrayReader = Ext.extend(Ext.data.JsonReader, {
98
- /**
99
- * Create a data block containing Ext.data.Records from an Array.
100
- * @param {Object} o An Array of row objects which represents the dataset.
101
- * @return {Object} data A data block which is used by an Ext.data.Store object as
102
- * a cache of Ext.data.Records.
103
- */
104
- readRecord : function(o){
105
- var sid = this.meta ? this.meta.id : null;
106
- var recordType = this.recordType, fields = recordType.prototype.fields;
107
- var records = [];
108
- var root = o;
109
- var n = root;
110
- var values = {};
111
- var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
112
- for(var j = 0, jlen = fields.length; j < jlen; j++){
113
- var f = fields.items[j];
114
- var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
115
- var v = n[k] !== undefined ? n[k] : f.defaultValue;
116
- v = f.convert(v, n);
117
- values[f.name] = v;
118
- }
119
- var record = new recordType(values, id);
120
- record.json = n;
121
- return record;
122
- }
123
- });
124
-
125
67
  Ext.netzke.JsonField = Ext.extend(Ext.form.TextField, {
126
68
  validator: function(value) {
127
69
  try{
@@ -794,185 +736,166 @@ Ext.grid.HeaderDropZone.prototype.onNodeDrop = function(n, dd, e, data){
794
736
  return false;
795
737
  };
796
738
 
797
- // Temporary fix for Ext 3.1 resize problem:
798
- Ext.override(Ext.Panel, {
799
-
800
- // private
801
- onResize : function(w, h, rw, rh){
802
- if(Ext.isDefined(w) || Ext.isDefined(h)){
803
- if(!this.collapsed){
804
- // First, set the the Panel's body width.
805
- // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
806
- // The Toolbars must not buffer this resize operation because we need to know their heights.
807
-
808
- if(Ext.isNumber(w)){
809
- this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
810
- } else if (w == 'auto') {
811
- w = this.body.setWidth('auto').dom.offsetWidth;
812
- } else {
813
- w = this.body.dom.offsetWidth;
814
- }
739
+ Ext.ns('Ext.ux.form');
740
+ Ext.ux.form.TriCheckbox = Ext.extend(Ext.form.Checkbox, {
741
+ checked: null,
742
+ valueList: [null, false, true],
743
+ stateClassList: ['x-checkbox-undef', null, 'x-checkbox-checked'],
744
+ overClass: 'x-form-check-over',
745
+ clickClass: 'x-form-check-down',
746
+ triState: true,
747
+ defaultAutoCreate: {tag: 'input', type: 'hidden', autocomplete: 'off'},
748
+ initComponent: function() {
749
+ this.value = this.checked;
750
+ Ext.ux.form.TriCheckbox.superclass.initComponent.apply(this, arguments);
751
+ // make a copy before modifying valueList and stateClassList arrays
752
+ this.vList = this.valueList.slice(0);
753
+ this.cList = this.stateClassList.slice(0);
754
+ if(this.triState !== true) {
755
+ // consider 'undefined' value and its class go first in arrays
756
+ this.vList.shift();
757
+ this.cList.shift();
758
+ }
759
+ if(this.overCls !== undefined) {
760
+ this.overClass = this.overCls;
761
+ delete this.overCls;
762
+ }
763
+ this.value = this.normalizeValue(this.value);
764
+ },
765
+ onRender : function(ct, position){
766
+ Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
767
+
768
+ this.innerWrap = this.el.wrap({tag: 'span', cls: 'x-form-check-innerwrap'});
769
+ this.wrap = this.innerWrap.wrap({cls: 'x-form-check-wrap'});
770
+
771
+ this.currCls = this.getCls(this.value);
772
+ this.wrap.addClass(this.currCls);
773
+ if(this.clickClass && !this.disabled && !this.readOnly)
774
+ this.innerWrap.addClassOnClick(this.clickClass);
775
+ if(this.overClass && !this.disabled && !this.readOnly)
776
+ this.innerWrap.addClassOnOver(this.overClass);
777
+
778
+ this.imageEl = this.innerWrap.createChild({
779
+ tag: 'img',
780
+ src: Ext.BLANK_IMAGE_URL,
781
+ cls: 'x-form-tscheckbox'
782
+ }, this.el);
783
+ if(this.fieldClass) this.imageEl.addClass(this.fieldClass);
784
+
785
+ if(this.boxLabel){
786
+ this.innerWrap.createChild({
787
+ tag: 'label',
788
+ htmlFor: this.el.id,
789
+ cls: 'x-form-cb-label',
790
+ html: this.boxLabel
791
+ });
792
+ }
815
793
 
816
- if(this.tbar){
817
- this.tbar.setWidth(w);
818
- if(this.topToolbar){
819
- this.topToolbar.setSize(w);
820
- }
821
- }
822
- if(this.bbar){
823
- this.bbar.setWidth(w);
824
- if(this.bottomToolbar){
825
- this.bottomToolbar.setSize(w);
826
- // The bbar does not move on resize without this.
827
- if (Ext.isIE) {
828
- this.bbar.setStyle('position', 'static');
829
- this.bbar.setStyle('position', '');
830
- }
831
- }
832
- }
833
- if(this.footer){
834
- this.footer.setWidth(w);
835
- if(this.fbar){
836
- this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
837
- }
838
- }
794
+ // Need to repaint for IE, otherwise positioning is broken
795
+ if(Ext.isIE){
796
+ this.wrap.repaint();
797
+ }
798
+ this.resizeEl = this.positionEl = this.wrap;
799
+ },
800
+ onResize : function(){
801
+ Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
802
+ if(!this.boxLabel && !this.fieldLabel && this.imageEl){
803
+ this.imageEl.alignTo(this.wrap, 'c-c');
804
+ }
805
+ },
806
+ initEvents : function(){
807
+ Ext.form.Checkbox.superclass.initEvents.call(this);
808
+ this.mon(this.innerWrap, {
809
+ scope: this,
810
+ click: this.onClick
811
+ });
812
+ },
813
+ onClick : function(){
814
+ if (!this.disabled && !this.readOnly) {
815
+ this.setValue(this.vList[(this.vList.indexOf(this.value) + 1) % this.vList.length]);
816
+ }
817
+ },
818
+ getValue : function(){
819
+ return this.value;
820
+ },
821
+ setValue : function(v){
822
+ var value = this.value;
823
+ this.value = this.normalizeValue(v);
824
+ if(this.rendered) this.el.dom.value = this.value;
825
+
826
+ if(value !== this.value){
827
+ this.updateView();
828
+ this.fireEvent('check', this, this.value);
829
+ if(this.handler) this.handler.call(this.scope || this, this, this.value);
830
+ }
831
+ return this;
832
+ },
833
+ normalizeValue: function(v) {
834
+ return (v === null || v === undefined) && this.triState ? null :
835
+ (v === true || (['true', 'yes', 'on', '1']).indexOf(String(v).toLowerCase()) != -1);
836
+ },
837
+ getCls: function(v) {
838
+ var idx = this.vList.indexOf(this.value);
839
+ return idx > -1 ? this.cList[idx] : undefined;
840
+ },
841
+ updateView: function() {
842
+ var cls = this.getCls(this.value);
843
+ if (!this.wrap || cls === undefined) return;
844
+
845
+ this.wrap.replaceClass(this.currCls, cls);
846
+ this.currCls = cls;
847
+ }
848
+ });
849
+ Ext.reg('tricheckbox', Ext.ux.form.TriCheckbox);
839
850
 
840
- // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
841
- if(Ext.isNumber(h)){
842
- h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
843
- this.body.setHeight(h);
844
- }else if(h == 'auto'){
845
- this.body.setHeight(h);
846
- }
847
851
 
848
- if(this.disabled && this.el._mask){
849
- this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
850
- }
851
- }else{
852
- this.queuedBodySize = {width: w, height: h};
853
- if(!this.queuedExpand && this.allowQueuedExpand !== false){
854
- this.queuedExpand = true;
855
- this.on('expand', function(){
856
- delete this.queuedExpand;
857
- this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
858
- }, this, {single:true});
859
- }
860
- }
861
- this.onBodyResize(w, h);
852
+ // Enabling checkbox submission when unchecked
853
+ (function() {
854
+ origCheckboxRender = Ext.form.Checkbox.prototype.onRender;
855
+ origCheckboxSetValue = Ext.form.Checkbox.prototype.setValue;
856
+
857
+ Ext.override(Ext.form.Checkbox, {
858
+ onRender: function() {
859
+ // call the original onRender() function
860
+ origCheckboxRender.apply(this, arguments);
861
+
862
+ if (this.getXType() === 'radio') return;
863
+
864
+ // Handle initial case based on this.checked
865
+ if (this.checked == false) {
866
+ this.noValEl = Ext.DomHelper.insertAfter(this.el, {
867
+ tag: 'input',
868
+ type: 'hidden',
869
+ value: false,
870
+ name: this.getName()
871
+ }, true);
872
+ }
873
+ else {
874
+ this.noValEl = null;
875
+ }
876
+ },
877
+ setValue: function() {
878
+ // call original setValue() function
879
+ origCheckboxSetValue.apply(this, arguments);
880
+
881
+ if (this.getXType() === 'radio') return;
882
+
883
+ if (this.checked) {
884
+ if (this.noValEl != null) {
885
+ // Remove the extra hidden element
886
+ this.noValEl.remove();
887
+ this.noValEl = null;
862
888
  }
863
- this.syncShadow();
864
- Ext.Panel.superclass.onResize.call(this, w, h, rw, rh);
889
+ }
890
+ else {
891
+ // Add our hidden element for (unchecked) value
892
+ if (this.noValEl == null) this.noValEl = Ext.DomHelper.insertAfter(this.el, {
893
+ tag: 'input',
894
+ type: 'hidden',
895
+ value: false,
896
+ name: this.getName()
897
+ }, true);
898
+ }
865
899
  }
866
- });
867
-
868
- Ext.ns('Ext.ux.form');
869
- Ext.ux.form.TriCheckbox = Ext.extend(Ext.form.Checkbox, {
870
- checked: null,
871
- valueList: [null, false, true],
872
- stateClassList: ['x-checkbox-undef', null, 'x-checkbox-checked'],
873
- overClass: 'x-form-check-over',
874
- clickClass: 'x-form-check-down',
875
- triState: true,
876
- defaultAutoCreate: {tag: 'input', type: 'hidden', autocomplete: 'off'},
877
- initComponent: function() {
878
- this.value = this.checked;
879
- Ext.ux.form.TriCheckbox.superclass.initComponent.apply(this, arguments);
880
- // make a copy before modifying valueList and stateClassList arrays
881
- this.vList = this.valueList.slice(0);
882
- this.cList = this.stateClassList.slice(0);
883
- if(this.triState !== true) {
884
- // consider 'undefined' value and its class go first in arrays
885
- this.vList.shift();
886
- this.cList.shift();
887
- }
888
- if(this.overCls !== undefined) {
889
- this.overClass = this.overCls;
890
- delete this.overCls;
891
- }
892
- this.value = this.normalizeValue(this.value);
893
- },
894
- onRender : function(ct, position){
895
- Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
896
-
897
- this.innerWrap = this.el.wrap({tag: 'span', cls: 'x-form-check-innerwrap'});
898
- this.wrap = this.innerWrap.wrap({cls: 'x-form-check-wrap'});
899
-
900
- this.currCls = this.getCls(this.value);
901
- this.wrap.addClass(this.currCls);
902
- if(this.clickClass && !this.disabled && !this.readOnly)
903
- this.innerWrap.addClassOnClick(this.clickClass);
904
- if(this.overClass && !this.disabled && !this.readOnly)
905
- this.innerWrap.addClassOnOver(this.overClass);
906
-
907
- this.imageEl = this.innerWrap.createChild({
908
- tag: 'img',
909
- src: Ext.BLANK_IMAGE_URL,
910
- cls: 'x-form-tscheckbox'
911
- }, this.el);
912
- if(this.fieldClass) this.imageEl.addClass(this.fieldClass);
913
-
914
- if(this.boxLabel){
915
- this.innerWrap.createChild({
916
- tag: 'label',
917
- htmlFor: this.el.id,
918
- cls: 'x-form-cb-label',
919
- html: this.boxLabel
920
- });
921
- }
922
-
923
- // Need to repaint for IE, otherwise positioning is broken
924
- if(Ext.isIE){
925
- this.wrap.repaint();
926
- }
927
- this.resizeEl = this.positionEl = this.wrap;
928
- },
929
- onResize : function(){
930
- Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
931
- if(!this.boxLabel && !this.fieldLabel && this.imageEl){
932
- this.imageEl.alignTo(this.wrap, 'c-c');
933
- }
934
- },
935
- initEvents : function(){
936
- Ext.form.Checkbox.superclass.initEvents.call(this);
937
- this.mon(this.innerWrap, {
938
- scope: this,
939
- click: this.onClick
940
- });
941
- },
942
- onClick : function(){
943
- if (!this.disabled && !this.readOnly) {
944
- this.setValue(this.vList[(this.vList.indexOf(this.value) + 1) % this.vList.length]);
945
- }
946
- },
947
- getValue : function(){
948
- return this.value;
949
- },
950
- setValue : function(v){
951
- var value = this.value;
952
- this.value = this.normalizeValue(v);
953
- if(this.rendered) this.el.dom.value = this.value;
954
-
955
- if(value !== this.value){
956
- this.updateView();
957
- this.fireEvent('check', this, this.value);
958
- if(this.handler) this.handler.call(this.scope || this, this, this.value);
959
- }
960
- return this;
961
- },
962
- normalizeValue: function(v) {
963
- return (v === null || v === undefined) && this.triState ? null :
964
- (v === true || (['true', 'yes', 'on', '1']).indexOf(String(v).toLowerCase()) != -1);
965
- },
966
- getCls: function(v) {
967
- var idx = this.vList.indexOf(this.value);
968
- return idx > -1 ? this.cList[idx] : undefined;
969
- },
970
- updateView: function() {
971
- var cls = this.getCls(this.value);
972
- if (!this.wrap || cls === undefined) return;
973
-
974
- this.wrap.replaceClass(this.currCls, cls);
975
- this.currCls = cls;
976
- }
977
- });
978
- Ext.reg('tricheckbox', Ext.ux.form.TriCheckbox);
900
+ });
901
+ })();