netzke-core 0.4.5 → 0.4.5.1
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.
- data/CHANGELOG.rdoc +5 -1
- data/Rakefile +1 -1
- data/javascripts/core.js +12 -8
- data/lib/netzke/base.rb +12 -3
- data/lib/netzke/base_js.rb +78 -52
- data/lib/netzke-core.rb +0 -2
- data/test/unit/netzke_core_test.rb +19 -2
- metadata +2 -3
- data/lib/netzke/feedback_ghost.rb +0 -43
data/CHANGELOG.rdoc
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
=
|
1
|
+
= v0.4.5.1 - 2009-11-09
|
2
|
+
* Regression: fixing inheritance and caching.
|
3
|
+
* FeedbackGhost is too simple to be a Netzke widget (having no server part), so, moved to static JavaScript.
|
4
|
+
|
5
|
+
= v0.4.5 - 2009-11-08
|
2
6
|
* API change: Netzke::Base: <tt>id_name</tt> accessor renamed to <tt>global_id</tt>
|
3
7
|
* Code: several internal code changes
|
4
8
|
* Code: lightly better test coverage
|
data/Rakefile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
begin
|
2
2
|
require 'jeweler'
|
3
3
|
Jeweler::Tasks.new do |gemspec|
|
4
|
-
gemspec.version = "0.4.5"
|
4
|
+
gemspec.version = "0.4.5.1"
|
5
5
|
gemspec.name = "netzke-core"
|
6
6
|
gemspec.summary = "Build ExtJS/Rails widgets with minimum effort"
|
7
7
|
gemspec.description = "Allows building ExtJS/Rails reusable code in a DRY way"
|
data/javascripts/core.js
CHANGED
@@ -3,10 +3,11 @@ This file gets loaded along with the rest of Ext library at the initial load
|
|
3
3
|
*/
|
4
4
|
|
5
5
|
Ext.BLANK_IMAGE_URL = "/extjs/resources/images/default/s.gif";
|
6
|
-
Ext.
|
7
|
-
Ext.
|
6
|
+
Ext.ns('Ext.netzke'); // namespace for extensions that depend on Ext
|
7
|
+
Ext.ns('Netzke'); // Netzke namespace
|
8
|
+
Netzke.cache = {}; // empty Netzke cache at the moment of loading
|
8
9
|
|
9
|
-
Ext.QuickTips.init();
|
10
|
+
Ext.QuickTips.init();
|
10
11
|
|
11
12
|
// To comply with Rails' forgery protection
|
12
13
|
Ext.Ajax.extraParams = {
|
@@ -98,11 +99,11 @@ Ext.widgetMixIn = {
|
|
98
99
|
var apiParams = Ext.apply({id: params.id, container: params.container}, params.params);
|
99
100
|
|
100
101
|
// build the cached widgets list to send it to the server
|
101
|
-
var cachedWidgetNames =
|
102
|
-
for (name in Netzke.
|
103
|
-
cachedWidgetNames
|
102
|
+
var cachedWidgetNames = "";
|
103
|
+
for (name in Netzke.cache) {
|
104
|
+
cachedWidgetNames += name + ",";
|
104
105
|
}
|
105
|
-
apiParams.cache =
|
106
|
+
apiParams.cache = cachedWidgetNames;
|
106
107
|
|
107
108
|
// remember the passed callback for the future
|
108
109
|
if (params.callback) {
|
@@ -415,7 +416,7 @@ Ext.widgetMixIn = {
|
|
415
416
|
// At this moment component is fully initializied
|
416
417
|
commonAfterConstructor : function(config){
|
417
418
|
// From everywhere accessible FeedbackGhost
|
418
|
-
this.feedbackGhost =
|
419
|
+
this.feedbackGhost = new Netzke.FeedbackGhost();
|
419
420
|
|
420
421
|
// Add the menus
|
421
422
|
if (this.initialConfig.menu) {this.addMenu(this.initialConfig.menu, this);}
|
@@ -524,6 +525,9 @@ Ext.override(Ext.Container, {
|
|
524
525
|
Ext.each(n.split("."), function(s){
|
525
526
|
klass = klass[s];
|
526
527
|
});
|
528
|
+
// Caching the class
|
529
|
+
Netzke.cache[n] = true;
|
530
|
+
// console.info(Netzke.cache);
|
527
531
|
return klass;
|
528
532
|
},
|
529
533
|
|
data/lib/netzke/base.rb
CHANGED
@@ -47,12 +47,20 @@ module Netzke
|
|
47
47
|
# Class-level Netzke::Base configuration. The defaults also get specified here.
|
48
48
|
def self.config
|
49
49
|
set_default_config({
|
50
|
-
#
|
50
|
+
# Which javascripts and stylesheets must get included at the initial load (see netzke-core.rb)
|
51
51
|
:javascripts => [],
|
52
52
|
:stylesheets => [],
|
53
53
|
|
54
|
+
# AR model that provides us with persistent config functionality
|
54
55
|
:persistent_config_manager => "NetzkePreference",
|
56
|
+
|
57
|
+
# Default location of extjs library
|
55
58
|
:ext_location => defined?(RAILS_ROOT) && "#{RAILS_ROOT}/public/extjs",
|
59
|
+
|
60
|
+
# Default location of icons (TODO: has no effect for now)
|
61
|
+
:icons_location => defined?(RAILS_ROOT) && "#{RAILS_ROOT}/public/images/icons",
|
62
|
+
|
63
|
+
# Default instance config
|
56
64
|
:default_config => {
|
57
65
|
:persistent_config => true
|
58
66
|
}
|
@@ -83,7 +91,7 @@ module Netzke
|
|
83
91
|
# Short widget class name, e.g.:
|
84
92
|
# Netzke::Module::SomeWidget => Module::SomeWidget
|
85
93
|
def self.short_widget_class_name
|
86
|
-
self.name.sub(
|
94
|
+
self.name.sub(/^Netzke::/, "")
|
87
95
|
end
|
88
96
|
|
89
97
|
# Access to controller sessions
|
@@ -397,6 +405,7 @@ module Netzke
|
|
397
405
|
end
|
398
406
|
|
399
407
|
# recursively instantiates an aggregatee based on its "path": e.g. if we have an aggregatee :aggr1 which in its turn has an aggregatee :aggr10, the path to the latter would be "aggr1__aggr10"
|
408
|
+
# TODO: introduce memoization
|
400
409
|
def aggregatee_instance(name, strong_config = {})
|
401
410
|
aggregator = self
|
402
411
|
name.to_s.split('__').each do |aggr|
|
@@ -481,7 +490,7 @@ module Netzke
|
|
481
490
|
# * <tt>:id</tt> - reference to the aggregatee
|
482
491
|
# * <tt>:container</tt> - Ext id of the container where in which the aggregatee will be rendered
|
483
492
|
def load_aggregatee_with_cache(params)
|
484
|
-
cache =
|
493
|
+
cache = params[:cache].gsub(".", "::").split(",") # array of cached class names (in Ruby)
|
485
494
|
relative_widget_id = params.delete(:id).underscore.to_sym
|
486
495
|
widget = aggregatees[relative_widget_id] && aggregatee_instance(relative_widget_id)
|
487
496
|
|
data/lib/netzke/base_js.rb
CHANGED
@@ -57,7 +57,6 @@ module Netzke
|
|
57
57
|
res[:persistent_config] = persistent_config_enabled?
|
58
58
|
|
59
59
|
# Merge with all config options passed as hash to config[:ext_config]
|
60
|
-
logger.debug "!!! ext_config: #{ext_config.inspect}\n"
|
61
60
|
res.merge!(ext_config)
|
62
61
|
|
63
62
|
res
|
@@ -65,16 +64,16 @@ module Netzke
|
|
65
64
|
|
66
65
|
# All the JS-code required by this instance of the widget to be instantiated in the browser.
|
67
66
|
# It includes the JS-class for the widget itself, as well as JS-classes for all widgets' (non-late) aggregatees.
|
68
|
-
def js_missing_code(
|
67
|
+
def js_missing_code(cached = [])
|
69
68
|
code = dependency_classes.inject("") do |r,k|
|
70
|
-
|
69
|
+
cached.include?(k) ? r : r + "Netzke::#{k}".constantize.js_code(cached).strip_js_comments
|
71
70
|
end
|
72
71
|
code.blank? ? nil : code
|
73
72
|
end
|
74
73
|
|
75
|
-
def css_missing_code(
|
74
|
+
def css_missing_code(cached = [])
|
76
75
|
code = dependency_classes.inject("") do |r,k|
|
77
|
-
|
76
|
+
cached.include?(k) ? r : r + "Netzke::#{k}".constantize.css_code(cached)
|
78
77
|
end
|
79
78
|
code.blank? ? nil : code
|
80
79
|
end
|
@@ -90,13 +89,7 @@ module Netzke
|
|
90
89
|
|
91
90
|
# rendering
|
92
91
|
def js_widget_render
|
93
|
-
%Q{
|
94
|
-
if (#{name.jsonify}.isXType("netzkewindow")) {
|
95
|
-
#{name.jsonify}.show();
|
96
|
-
} else {
|
97
|
-
#{name.jsonify}.render("#{name.to_s.split('_').join('-')}-div");
|
98
|
-
}
|
99
|
-
}
|
92
|
+
self.class.js_xtype == "netzkewindow" ? %Q{#{name.jsonify}.show();} : %Q{#{name.jsonify}.render("#{name.to_s.split('_').join('-')}-div");}
|
100
93
|
end
|
101
94
|
|
102
95
|
# container for rendering
|
@@ -132,35 +125,52 @@ module Netzke
|
|
132
125
|
def js_extend_properties
|
133
126
|
{}
|
134
127
|
end
|
135
|
-
|
136
|
-
#
|
137
|
-
|
128
|
+
|
129
|
+
# widget's menus
|
130
|
+
def js_menus; []; end
|
131
|
+
|
132
|
+
# Given class name, e.g. GridPanelLib::Widgets::RecordFormWindow,
|
133
|
+
# returns its scope: "Widgets.RecordFormWindow"
|
134
|
+
def js_class_name_to_scope(name)
|
135
|
+
name.split("::")[0..-2].join(".")
|
136
|
+
end
|
137
|
+
|
138
|
+
# Top level scope which will be used to cope out Netzke classes, e.g. "Netzke.classes" (default)
|
139
|
+
def js_default_scope
|
140
|
+
"Netzke.classes"
|
141
|
+
end
|
142
|
+
|
143
|
+
# Scope of this widget without default scope
|
144
|
+
# e.g.: GridPanelLib.Widgets
|
138
145
|
def js_scope
|
139
|
-
|
146
|
+
js_class_name_to_scope(short_widget_class_name)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Returns the scope of this widget
|
150
|
+
# e.g. "Netzke.classes.GridPanelLib"
|
151
|
+
def js_full_scope
|
152
|
+
js_scope.empty? ? js_default_scope : [js_default_scope, js_scope].join(".")
|
140
153
|
end
|
141
154
|
|
142
|
-
# Returns the name of the JavaScript class for this widget, including the
|
143
|
-
# e.g.: "
|
155
|
+
# Returns the name of the JavaScript class for this widget, including the scope
|
156
|
+
# e.g.: "GridPanelLib.RecordFormWindow"
|
144
157
|
def js_scoped_class_name
|
145
|
-
|
158
|
+
short_widget_class_name.gsub("::", ".")
|
146
159
|
end
|
147
160
|
|
148
161
|
# Returns the full name of the JavaScript class, including the scopes *and* the common scope, which is
|
149
162
|
# Netzke.classes.
|
150
163
|
# E.g.: "Netzke.classes.Netzke.GridPanelLib.RecordFormWindow"
|
151
164
|
def js_full_class_name
|
152
|
-
"
|
165
|
+
[js_full_scope, short_widget_class_name.split("::").last].join(".")
|
153
166
|
end
|
154
|
-
|
167
|
+
|
155
168
|
# Builds this widget's xtype
|
156
169
|
# E.g.: netzkewindow, netzkegridpanel
|
157
170
|
def js_xtype
|
158
171
|
name.gsub("::", "").downcase
|
159
172
|
end
|
160
173
|
|
161
|
-
# widget's menus
|
162
|
-
def js_menus; []; end
|
163
|
-
|
164
174
|
# are we using JS inheritance? for now, if js_base_class is a Netzke class - yes
|
165
175
|
def js_inheritance?
|
166
176
|
superclass != Netzke::Base
|
@@ -168,28 +178,40 @@ module Netzke
|
|
168
178
|
|
169
179
|
# Declaration of widget's class (stored in the cache storage (Ext.netzke.cache) at the client side
|
170
180
|
# to be reused at the moment of widget instantiation)
|
171
|
-
def js_class
|
181
|
+
def js_class(cached = [])
|
182
|
+
# Setting the scope.
|
183
|
+
# TODO: invent an easy and error-prove way to check if adding this scope is necessary.
|
184
|
+
# For now setting it each and every time (very save and not really bothering).
|
185
|
+
res = %Q{
|
186
|
+
Ext.ns("#{js_full_scope}");
|
187
|
+
}
|
188
|
+
|
172
189
|
if js_inheritance?
|
173
|
-
#
|
174
|
-
<<-END_OF_JAVASCRIPT
|
175
|
-
//
|
176
|
-
Ext.ns("#{js_scope}");
|
177
|
-
// Create the class
|
190
|
+
# Using javascript inheritance
|
191
|
+
res << <<-END_OF_JAVASCRIPT
|
192
|
+
// Costructor
|
178
193
|
#{js_full_class_name} = function(config){
|
179
194
|
#{js_full_class_name}.superclass.constructor.call(this, config);
|
180
195
|
};
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
196
|
+
END_OF_JAVASCRIPT
|
197
|
+
|
198
|
+
# Do we specify our own extend properties (overrriding js_extend_properties)? If so, include them, if not - don't re-include those from the parent!
|
199
|
+
res << (singleton_methods(false).include?("js_extend_properties") ? %Q{
|
200
|
+
Ext.extend(#{js_full_class_name}, #{superclass.js_full_class_name}, #{js_extend_properties.to_nifty_json});
|
201
|
+
} : %Q{
|
202
|
+
Ext.extend(#{js_full_class_name}, #{superclass.js_full_class_name});
|
203
|
+
})
|
185
204
|
|
205
|
+
res << <<-END_OF_JAVASCRIPT
|
206
|
+
// Register our xtype
|
207
|
+
Ext.reg("#{js_xtype}", #{js_full_class_name});
|
186
208
|
END_OF_JAVASCRIPT
|
187
209
|
|
188
210
|
else
|
211
|
+
# Menus
|
189
212
|
js_add_menus = "this.addMenus(#{js_menus.to_nifty_json});" unless js_menus.empty?
|
190
|
-
|
191
|
-
|
192
|
-
Ext.ns("#{js_scope}");
|
213
|
+
|
214
|
+
res << <<-END_OF_JAVASCRIPT
|
193
215
|
// Constructor
|
194
216
|
#{js_full_class_name} = function(config){
|
195
217
|
// Do all the initializations that every Netzke widget should do: create methods for API-points,
|
@@ -204,9 +226,10 @@ module Netzke
|
|
204
226
|
Ext.extend(#{js_full_class_name}, #{js_base_class}, Ext.applyIf(#{js_extend_properties.to_nifty_json}, Ext.widgetMixIn));
|
205
227
|
// Register xtype
|
206
228
|
Ext.reg("#{js_xtype}", #{js_full_class_name});
|
207
|
-
|
208
229
|
END_OF_JAVASCRIPT
|
209
230
|
end
|
231
|
+
|
232
|
+
res
|
210
233
|
end
|
211
234
|
|
212
235
|
#
|
@@ -215,15 +238,16 @@ module Netzke
|
|
215
238
|
|
216
239
|
# Override this method. Must return an array of paths to javascript files that we depend on.
|
217
240
|
# This javascript code will be loaded along with the widget's class, and before it.
|
218
|
-
def include_js
|
219
|
-
|
220
|
-
end
|
241
|
+
# def include_js
|
242
|
+
# []
|
243
|
+
# end
|
221
244
|
|
222
245
|
# Returns all extra JavaScript-code (as string) required by this widget's class
|
223
246
|
def js_included
|
224
247
|
res = ""
|
225
|
-
|
226
|
-
|
248
|
+
|
249
|
+
# Prevent re-including code that was already included by the parent
|
250
|
+
singleton_methods(false).include?("include_js") && include_js.each do |path|
|
227
251
|
f = File.new(path)
|
228
252
|
res << f.read << "\n"
|
229
253
|
end
|
@@ -232,17 +256,19 @@ module Netzke
|
|
232
256
|
end
|
233
257
|
|
234
258
|
# All JavaScript code needed for this class, including one from the ancestor widget
|
235
|
-
def js_code(
|
259
|
+
def js_code(cached = [])
|
236
260
|
res = ""
|
237
261
|
|
238
262
|
# include the base-class javascript if doing JS inheritance
|
239
|
-
|
263
|
+
if js_inheritance? && !cached.include?(superclass.short_widget_class_name)
|
264
|
+
res << superclass.js_code(cached) << "\n"
|
265
|
+
end
|
240
266
|
|
241
267
|
# include static javascripts
|
242
268
|
res << js_included << "\n"
|
243
269
|
|
244
270
|
# our own JS class definition
|
245
|
-
res << js_class
|
271
|
+
res << js_class(cached)
|
246
272
|
res
|
247
273
|
end
|
248
274
|
|
@@ -251,15 +277,15 @@ module Netzke
|
|
251
277
|
#
|
252
278
|
|
253
279
|
# Override this method. Must return an array of paths to css files that we depend on.
|
254
|
-
def include_css
|
255
|
-
|
256
|
-
end
|
280
|
+
# def include_css
|
281
|
+
# []
|
282
|
+
# end
|
257
283
|
|
258
284
|
# Returns all extra CSS code (as string) required by this widget's class
|
259
285
|
def css_included
|
260
286
|
res = ""
|
261
287
|
|
262
|
-
include_css.each do |path|
|
288
|
+
singleton_methods(false).include?("include_css") && include_css.each do |path|
|
263
289
|
f = File.new(path)
|
264
290
|
res << f.read << "\n"
|
265
291
|
end
|
@@ -268,11 +294,11 @@ module Netzke
|
|
268
294
|
end
|
269
295
|
|
270
296
|
# All CSS code needed for this class including the one from the ancestor widget
|
271
|
-
def css_code(
|
297
|
+
def css_code(cached = [])
|
272
298
|
res = ""
|
273
299
|
|
274
300
|
# include the base-class javascript if doing JS inheritance
|
275
|
-
res << superclass.css_code << "\n" if js_inheritance? && !
|
301
|
+
res << superclass.css_code << "\n" if js_inheritance? && !cached.include?(superclass.short_widget_class_name)
|
276
302
|
|
277
303
|
res << css_included << "\n"
|
278
304
|
|
data/lib/netzke-core.rb
CHANGED
@@ -8,8 +8,6 @@ require 'netzke/controller_extensions'
|
|
8
8
|
require 'netzke/core_ext'
|
9
9
|
require 'netzke/routing'
|
10
10
|
|
11
|
-
require 'netzke/feedback_ghost'
|
12
|
-
|
13
11
|
# Load models and controllers from lib/app
|
14
12
|
%w{ models controllers }.each do |dir|
|
15
13
|
path = File.join(File.dirname(__FILE__), 'app', dir)
|
@@ -56,6 +56,11 @@ module Netzke
|
|
56
56
|
class JsInheritanceWidget < Widget
|
57
57
|
end
|
58
58
|
|
59
|
+
module ScopedWidgets
|
60
|
+
class SomeScopedWidget < Base
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
59
64
|
class InheritedWidget < Widget
|
60
65
|
def self.config
|
61
66
|
super.merge({
|
@@ -144,8 +149,8 @@ class NetzkeCoreTest < ActiveSupport::TestCase
|
|
144
149
|
|
145
150
|
test "js inheritance" do
|
146
151
|
widget = JsInheritanceWidget.new
|
147
|
-
assert(widget.js_missing_code.index("Netzke.classes.
|
148
|
-
assert(widget.js_missing_code.index("Netzke.classes.
|
152
|
+
assert(widget.js_missing_code.index("Netzke.classes.JsInheritanceWidget"))
|
153
|
+
assert(widget.js_missing_code.index("Netzke.classes.Widget"))
|
149
154
|
end
|
150
155
|
|
151
156
|
test "class-level configuration" do
|
@@ -163,4 +168,16 @@ class NetzkeCoreTest < ActiveSupport::TestCase
|
|
163
168
|
|
164
169
|
end
|
165
170
|
|
171
|
+
test "JS class names and scopes" do
|
172
|
+
klass = Netzke::NestedWidgetOne
|
173
|
+
assert_equal("Netzke.classes", klass.js_full_scope)
|
174
|
+
assert_equal("", klass.js_class_name_to_scope(klass.short_widget_class_name))
|
175
|
+
|
176
|
+
klass = Netzke::ScopedWidgets::SomeScopedWidget
|
177
|
+
assert_equal("Netzke.classes", klass.js_default_scope)
|
178
|
+
assert_equal("ScopedWidgets::SomeScopedWidget", klass.short_widget_class_name)
|
179
|
+
assert_equal("ScopedWidgets", klass.js_class_name_to_scope(klass.short_widget_class_name))
|
180
|
+
assert_equal("Netzke.classes.ScopedWidgets", klass.js_full_scope)
|
181
|
+
end
|
182
|
+
|
166
183
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: netzke-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.5
|
4
|
+
version: 0.4.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergei Kozlov
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-09 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -46,7 +46,6 @@ files:
|
|
46
46
|
- lib/netzke/base_js.rb
|
47
47
|
- lib/netzke/controller_extensions.rb
|
48
48
|
- lib/netzke/core_ext.rb
|
49
|
-
- lib/netzke/feedback_ghost.rb
|
50
49
|
- lib/netzke/routing.rb
|
51
50
|
- stylesheets/core.css
|
52
51
|
- tasks/netzke_core_tasks.rake
|
@@ -1,43 +0,0 @@
|
|
1
|
-
module Netzke
|
2
|
-
#
|
3
|
-
# An invisible component that provides feedback service for all Netzke widgets
|
4
|
-
#
|
5
|
-
class FeedbackGhost < Base
|
6
|
-
def self.js_base_class
|
7
|
-
"Ext.Component" # yes, invisible
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.js_extend_properties
|
11
|
-
{
|
12
|
-
:show_feedback => <<-END_OF_JAVASCRIPT.l,
|
13
|
-
function(msg){
|
14
|
-
var createBox = function(s, l){
|
15
|
-
return ['<div class="msg">',
|
16
|
-
'<div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>',
|
17
|
-
'<div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">', s, '</div></div></div>',
|
18
|
-
'<div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>',
|
19
|
-
'</div>'].join('');
|
20
|
-
}
|
21
|
-
|
22
|
-
var showBox = function(msg, lvl){
|
23
|
-
if (!lvl) {lvl = 'notice'};
|
24
|
-
var msgCt = Ext.DomHelper.insertFirst(document.body, {'class':'netzke-feedback'}, true);
|
25
|
-
var m = Ext.DomHelper.append(msgCt, {html:createBox(msg,lvl)}, true);
|
26
|
-
m.slideIn('t').pause(2).ghost("b", {remove:true});
|
27
|
-
}
|
28
|
-
|
29
|
-
if (typeof msg != 'string') {
|
30
|
-
var compoundMsg = "";
|
31
|
-
Ext.each(msg, function(m){
|
32
|
-
compoundMsg += m.msg + '<br>';
|
33
|
-
});
|
34
|
-
if (compoundMsg != "") showBox(compoundMsg, null); // the second parameter will be level
|
35
|
-
} else {
|
36
|
-
showBox(msg);
|
37
|
-
}
|
38
|
-
}
|
39
|
-
END_OF_JAVASCRIPT
|
40
|
-
}
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|