netzke-core 0.4.5 → 0.4.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|