unageanu-jiji 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. data/README +1 -0
  2. data/base/agents/moving_average_agent.rb +78 -0
  3. data/base/shared_lib/moving_average.rb +34 -0
  4. data/bin/jiji +5 -0
  5. data/html/css/default.css +7 -0
  6. data/html/img/button_calendar_over.gif +0 -0
  7. data/html/img/button_cancel.gif +0 -0
  8. data/html/img/button_no.gif +0 -0
  9. data/html/img/button_no_gray.gif +0 -0
  10. data/html/img/button_no_over.gif +0 -0
  11. data/html/img/button_save.gif +0 -0
  12. data/html/img/button_save_gray.gif +0 -0
  13. data/html/img/button_save_over.gif +0 -0
  14. data/html/img/button_update_s.gif +0 -0
  15. data/html/img/button_update_s_gray.gif +0 -0
  16. data/html/img/button_update_s_over.gif +0 -0
  17. data/html/img/button_yes.gif +0 -0
  18. data/html/img/button_yes_gray.gif +0 -0
  19. data/html/img/button_yes_over.gif +0 -0
  20. data/html/index.html +29 -33
  21. data/html/js/agent-editor-page.js +178 -88
  22. data/html/js/agent-selector.js +68 -39
  23. data/html/js/bt-create-page.js +24 -11
  24. data/html/js/dialog.js +43 -34
  25. data/html/js/result-page.js +37 -25
  26. data/html/js/rt-setting-page.js +13 -6
  27. data/html/js/sidebar.js +8 -5
  28. data/html/js/templates.js +37 -3
  29. data/html/js/utils.js +47 -9
  30. data/html/swf/chart.swf +0 -0
  31. data/lib/jiji/agent/agent_manager.rb +2 -2
  32. data/lib/jiji/agent/agent_registry.rb +4 -1
  33. data/lib/jiji/command.rb +6 -0
  34. data/lib/jiji/process.rb +32 -10
  35. data/lib/jiji/process_manager.rb +7 -0
  36. data/lib/jiji/registry.rb +6 -4
  37. data/lib/jiji/server.rb +6 -1
  38. data/lib/jiji/service/output_service.rb +10 -6
  39. data/swf/chart/fx/chart/Chart.as +4 -1
  40. data/swf/chart/fx/chart/ui/Constants.as +3 -3
  41. data/swf/chart/fx/chart/ui/InformationWindow.as +45 -41
  42. data/swf/chart/fx/chart/ui/Pointer.as +6 -4
  43. data/swf/chart/fx/chart/ui/Scroll.as +3 -2
  44. data/swf/chart/fx/chart/ui/Stage.as +3 -3
  45. data/swf/chart/fx/chart/ui/TradeDetailWindow.as +9 -8
  46. data/swf/chart/fx/chart/ui/TradeResult.as +3 -17
  47. data/swf/chart/fx/chart/ui/graph/Graph.as +4 -2
  48. data/swf/chart/fx/chart/ui/graph/GraphManager.as +3 -1
  49. data/swf/chart/fx/chart/ui/resource/fixed.gif +0 -0
  50. data/swf/chart/fx/chart/ui/resource/unfixed.gif +0 -0
  51. data/swf/chart/fx/net/StubFactory.as +3 -3
  52. data/test/all_tests.rb +1 -1
  53. data/test/test_AgentManager.rb +4 -4
  54. data/test/{test_AgentRegistory.rb → test_AgentRegistry.rb} +0 -0
  55. data/test/test_Collector.rb +1 -1
  56. data/test/test_Output_registry.rb +7 -3
  57. data/test/test_Process.rb +5 -5
  58. data/test/test_ProcessManager.rb +120 -68
  59. metadata +20 -14
  60. data/bin/jiji.rb +0 -6
  61. data/html/js/W3CDTF.js +0 -131
@@ -28,8 +28,16 @@ fx.ui.pages.AgentEditorPage = function() {
28
28
  }, fx.template.Templates.common.button.del);
29
29
  this.removeButton.setEnable( true );
30
30
 
31
+ this.saveButton = new util.Button("agent-edit_save", "save", function() {
32
+ if ( !self.editingFile ) { return; }
33
+ var newData = agent_editor.getCode();
34
+ newData = newData.strip();
35
+ self.save(true,self.editingFile, self.target, newData);
36
+ }, fx.template.Templates.common.button.save);
37
+ this.saveButton.setEnable( false );
38
+
31
39
  // 自動保存するためのタイマー
32
- this.autoSave = new util.Timer( 1000*10, function(){ self.save(); }, false );
40
+ // this.autoSave = new util.Timer( 1000*10, function(){ self.save(); }, false );
33
41
  }
34
42
  fx.ui.pages.AgentEditorPage.prototype = {
35
43
 
@@ -38,11 +46,15 @@ fx.ui.pages.AgentEditorPage.prototype = {
38
46
  * 戻り値としてfalseを返すと遷移をキャンセルする。
39
47
  */
40
48
  from : function(toId) {
41
- // 変更を強制的に反映するため、一旦保存
42
- this.save();
43
49
  // 自動更新タイマーを停止
44
- this.autoSave.stop();
45
-
50
+ // this.autoSave.stop();
51
+
52
+ // 変更を強制的に反映するため、一旦保存
53
+ var self = this;
54
+ this.saveIfNotSaved(function(){
55
+ self.clearEdit();
56
+ });
57
+
46
58
  // ページを非表示
47
59
  document.getElementById(this.elementId).style.display = "none";
48
60
  this.topicPath.set("");
@@ -66,25 +78,34 @@ fx.ui.pages.AgentEditorPage.prototype = {
66
78
  ? fx.template.Templates.agentEditor.topicPath.agent
67
79
  : fx.template.Templates.agentEditor.topicPath.sharedLib );
68
80
 
81
+ document.getElementById("agent_edit_desc").innerHTML =
82
+ this.target == "agent" ? fx.template.Templates.agentEditor.desc.agent : fx.template.Templates.agentEditor.desc.sharedLib;
83
+
84
+ this.clearEdit();
85
+
69
86
  // ファイル一覧を更新
70
87
  this.initialize();
71
- // 自動更新タイマーを開始
72
- this.autoSave.start();
73
88
  },
74
89
 
75
90
  initialize: function( ) {
76
91
  var self = this;
92
+ self.editingFile = null;
93
+ agent_editor.setCode("\n");
77
94
  this.agentFileListTable.initialize();
78
95
  this.agentFileListTable.table.subscribe("rowSelectEvent", function(ev){
79
- self.selectionChanged();
96
+ self.selectionChanged();
80
97
  });
81
98
  this.agentFileListTable.table.subscribe("rowUnselectEvent", function(ev){
82
- self.selectionChanged();
99
+ self.selectionChanged();
83
100
  });
101
+ this.agentFileListTable.loading(true);
84
102
  this.listAgentFiles( true, function( data ) {
85
103
  self.agentFiles = data;
86
104
  self.agentFileListTable.setData(data);
105
+ self.agentFileListTable.loading(false);
87
106
  self.selectionChanged();
107
+ // 自動更新タイマーを開始
108
+ // self.autoSave.start();
88
109
  }, null ); // TODO
89
110
  },
90
111
 
@@ -96,23 +117,24 @@ fx.ui.pages.AgentEditorPage.prototype = {
96
117
  this.dialog.show( "input", {
97
118
  message : fx.template.Templates.agentEditor.add.body.evaluate({ "text" : "" }),
98
119
  init: function() {
99
- document.file_name_input_form.file_name_input.focus();
120
+ document.file_name_input_form.file_name_input.focus();
100
121
  if ( !agent_editor.textarea.readOnly ) {
101
- agent_editor.toggleReadOnly();
122
+ agent_editor.toggleReadOnly();
102
123
  }
103
- },
124
+ },
104
125
  buttons : [
105
126
  { type:"ok",
106
- alt: "ok",
107
- key: "Enter",
108
- action: function(dialog){
127
+ alt: fx.template.Templates.common.button.ok,
128
+ key: "Enter",
129
+ action: function(dialog){
109
130
  var text = document.getElementById("file_name_input").value;
110
- // 文字列をチェック
131
+
132
+ // 文字列をチェック
111
133
  var error = null;
112
134
  if ( !text ) {
113
135
  error = fx.template.Templates.agentEditor.add.errormsgs.no;
114
136
  }
115
- if ( !error && !text.match( /^[A-Za-z0-9_\*\+\-\#\"\'\!\~\(\)\[\]\?\.]+$/ ) ) {
137
+ if ( !error && !text.match( /^[A-Za-z0-9_\*\+\-\#\"\'\!\~\(\)\[\]\?\.]+$/ ) ) {
116
138
  error = fx.template.Templates.agentEditor.add.errormsgs.illegalChar;
117
139
  }
118
140
  // 重複チェック
@@ -130,31 +152,31 @@ fx.ui.pages.AgentEditorPage.prototype = {
130
152
  }
131
153
  if (error) {
132
154
  dialog.content.innerHTML =
133
- fx.template.Templates.agentEditor.add.error.evaluate({ "error" : error })
134
- + fx.template.Templates.agentEditor.add.body.evaluate({ "text" : text })
155
+ fx.template.Templates.agentEditor.add.error.evaluate({ "error" : error.escapeHTML() })
156
+ + fx.template.Templates.agentEditor.add.body.evaluate({ "text" : text.escapeHTML() })
135
157
  return false;
136
158
  } else {
137
- self.saveFile( text, "", function(){
159
+ self.saveFile( text, self.target, "", function(){
138
160
  self.listAgentFiles( true, function( data ) {
139
161
  self.agentFiles = data;
140
162
  self.agentFileListTable.setData(data);
141
163
  self.selectionChanged();
142
164
  }, null ); // TODO
143
165
  }, null ); // TODO
144
- if ( old != agent_editor.textarea.readOnly ) {
145
- agent_editor.toggleReadOnly();
146
- }
166
+ if ( old != agent_editor.textarea.readOnly ) {
167
+ agent_editor.toggleReadOnly();
168
+ }
147
169
  return true;
148
170
  }
149
171
  } },
150
172
  { type:"cancel",
151
- alt: fx.template.Templates.common.button.cancel,
152
- key: "Esc",
153
- action: function(dialog){
154
- if ( old != agent_editor.textarea.readOnly ) {
155
- agent_editor.toggleReadOnly();
156
- }
157
- return true;
173
+ alt: fx.template.Templates.common.button.cancel,
174
+ key: "Esc",
175
+ action: function(dialog){
176
+ if ( old != agent_editor.textarea.readOnly ) {
177
+ agent_editor.toggleReadOnly();
178
+ }
179
+ return true;
158
180
  }}
159
181
  ]
160
182
  } );
@@ -168,7 +190,7 @@ fx.ui.pages.AgentEditorPage.prototype = {
168
190
  }
169
191
  var names = [];
170
192
  for( var i=0,s=selectedRowIds.length;i<s;i++ ) {
171
- names.push( this.agentFileListTable.table.getRecord( selectedRowIds[i] ).getData().name);
193
+ names.push( this.agentFileListTable.table.getRecord( selectedRowIds[i] ).getData().name);
172
194
  }
173
195
  // 確認
174
196
  var self = this;
@@ -177,14 +199,17 @@ fx.ui.pages.AgentEditorPage.prototype = {
177
199
  message : fx.template.Templates.agentEditor.remove.body,
178
200
  init: function() {
179
201
  if ( !agent_editor.textarea.readOnly ) {
180
- agent_editor.toggleReadOnly();
202
+ agent_editor.toggleReadOnly();
181
203
  }
182
- },
204
+ },
183
205
  buttons : [
184
- { type:"ok", action: function(dialog){
185
- if ( old != agent_editor.textarea.readOnly ) {
186
- agent_editor.toggleReadOnly();
187
- }
206
+ { type:"ok",
207
+ alt: fx.template.Templates.common.button.ok,
208
+ key: "Enter",
209
+ action: function(dialog){
210
+ if ( old != agent_editor.textarea.readOnly ) {
211
+ agent_editor.toggleReadOnly();
212
+ }
188
213
  // 行のデータを削除
189
214
  self.deleteFile( names, function(){
190
215
  self.listAgentFiles( true, function( data ) {
@@ -193,79 +218,142 @@ fx.ui.pages.AgentEditorPage.prototype = {
193
218
  self.selectionChanged();
194
219
  }, null ); // TODO
195
220
  }, null ); // TODO
221
+ return true;
196
222
  }},
197
223
  { type:"cancel",
198
- alt: fx.template.Templates.common.button.cancel,
199
- key: "Esc",
200
- action: function(dialog){
201
- if ( old != agent_editor.textarea.readOnly ) {
202
- agent_editor.toggleReadOnly();
203
- }
204
- return true;
224
+ alt: fx.template.Templates.common.button.cancel,
225
+ key: "Esc",
226
+ action: function(dialog){
227
+ if ( old != agent_editor.textarea.readOnly ) {
228
+ agent_editor.toggleReadOnly();
229
+ }
230
+ return true;
205
231
  }}
206
232
  ]
207
233
  });
208
234
  },
209
- save: function(){
210
- if ( !this.editingFile ) { return; }
211
- var newData = agent_editor.getCode();
235
+ save: function( showResult, editingFile, mode, newData ){
212
236
  var self = this;
213
- if ( self.prevCode == newData ) { return; }
214
- this.saveFile( this.editingFile, newData, function(){
237
+ this.saveFile( editingFile, mode, newData, function(result){
238
+ // 結果を表示しない == 別画面に移動する場合は、前のコードは不要なので変更しない。
239
+ if (!showResult) { return; }
215
240
  self.prevCode = newData;
241
+ if ( result == "success" ) {
242
+ document.getElementById("agent_edit_msg").innerHTML =
243
+ fx.template.Templates.agentEditor.saved.success.evaluate({ "now" : util.formatDate( new Date() ) });
244
+ } else {
245
+ document.getElementById("agent_edit_msg").innerHTML =
246
+ fx.template.Templates.agentEditor.saved.error.evaluate({ "now" : util.formatDate( new Date() ), "result":result.escapeHTML()} );
247
+ }
216
248
  }, null ); // TODO
217
249
  },
218
-
250
+ /**
251
+ * 未保存かどうかチェックして、未保存でかつtrueであれば保存を実行する。
252
+ */
253
+ saveIfNotSaved: function( callback ){
254
+ // 編集中でない
255
+ if ( !this.editingFile ) {
256
+ if (callback) { callback(); }
257
+ return true;
258
+ }
259
+ var editingFile = this.editingFile;
260
+ var target = this.target;
261
+
262
+ // コードが変更されていない
263
+ var newData = agent_editor.getCode();
264
+ newData = newData.strip();
265
+ var self = this;
266
+ if ( self.prevCode == newData ) {
267
+ if (callback) { callback(); }
268
+ return true;
269
+ }
270
+
271
+ // 確認ダイアログを表示
272
+ this.dialog.show( "input", {
273
+ message : fx.template.Templates.agentEditor.dosave,
274
+ buttons : [
275
+ { type:"yes",
276
+ alt: fx.template.Templates.common.button.yes,
277
+ key: "Enter",
278
+ action: function(dialog){
279
+ self.save(false, editingFile, target, newData);
280
+ if (callback) { callback(); }
281
+ return true;
282
+ }},
283
+ { type:"no",
284
+ alt: fx.template.Templates.common.button.no,
285
+ key: "Esc",
286
+ action: function(dialog){
287
+ if (callback) { callback(); }
288
+ return true;
289
+ }
290
+ }
291
+ ]
292
+ });
293
+ },
294
+ /**
295
+ * 編集なし状態にします。
296
+ */
297
+ clearEdit : function(){
298
+ this.editingFile = null;
299
+ agent_editor.setCode("\n");
300
+ this.saveButton.setEnable( false );
301
+ document.getElementById("agent_edit_msg").innerHTML = "";
302
+ },
219
303
  selectionChanged: function() {
220
304
 
221
305
  // 選択されている行を取得
222
- var self = this;
306
+ var self = this;
223
307
  var selectedRowIds = this.agentFileListTable.table.getSelectedTrEls();
224
308
  var data = null;
225
309
  var removeEnable = false;
226
310
  if ( selectedRowIds.length <= 0 ) {
227
- // 選択なし
228
- removeEnable = false;
229
- document.getElementById("agent-editor-file-name").innerHTML=
230
- fx.template.Templates.agentEditor.defaultFileName;
311
+ // 選択なし
312
+ removeEnable = false;
313
+ document.getElementById("agent-editor-file-name").innerHTML=
314
+ fx.template.Templates.agentEditor.defaultFileName;
231
315
  } else if ( selectedRowIds.length == 1 ) {
232
- removeEnable = true;
233
- // エディタも更新する。
234
- data = this.agentFileListTable.table.getRecord( selectedRowIds[0] ).getData();
316
+ removeEnable = true;
317
+ // エディタも更新する。
318
+ data = this.agentFileListTable.table.getRecord( selectedRowIds[0] ).getData();
235
319
  } else {
236
- removeEnable = true;
237
- // エディタは初期化
238
- document.getElementById("agent-editor-file-name").innerHTML= "---";
320
+ removeEnable = true;
321
+ // エディタは初期化
322
+ document.getElementById("agent-editor-file-name").innerHTML= "---";
239
323
  }
240
324
  // 削除の状態更新
241
325
  this.removeButton.setEnable(removeEnable);
326
+ this.saveButton.setEnable(false);
242
327
 
243
328
  // エディタのデータを更新
244
- self.save();
245
- if ( data ) {
246
- // 変更を強制的に反映するため、一旦保存
247
- self.editingFile = null;
248
- document.getElementById("agent-editor-file-name").innerHTML=
249
- fx.template.Templates.common.loading;
250
- self.getFile( data.name, function( body) {
251
- self.editingFile = data.name;
252
- self.prevCode = body;
253
- if ( agent_editor.textarea.readOnly ) {
254
- agent_editor.toggleReadOnly();
255
- }
256
- agent_editor.setCode(body);
257
- agent_editor.editor.syntaxHighlight('init');
258
- document.getElementById("agent-editor-file-name").innerHTML= data.name;
259
- }, null ); // TODO
260
- } else {
261
- self.save();
262
- self.editingFile = null;
263
- agent_editor.setCode("");
264
- agent_editor.editor.syntaxHighlight('init');
265
- if ( !agent_editor.textarea.readOnly ) {
266
- agent_editor.toggleReadOnly();
329
+ // 保存確認
330
+ self.saveIfNotSaved( function(){
331
+ if ( data ) {
332
+ self.editingFile = null;
333
+ document.getElementById("agent-editor-file-name").innerHTML=
334
+ fx.template.Templates.common.loading;
335
+ self.getFile( data.name, function( body ) {
336
+ body = body.strip();
337
+ self.editingFile = data.name;
338
+ self.prevCode = body;
339
+ if ( agent_editor.textarea.readOnly ) {
340
+ agent_editor.toggleReadOnly();
341
+ }
342
+ if( body == "" ) body = "\n" // 空文字をcodePressに設定するとバグるので対策。
343
+ agent_editor.setCode(body);
344
+ agent_editor.editor.syntaxHighlight('init');
345
+ document.getElementById("agent-editor-file-name").innerHTML= data.name;
346
+ document.getElementById("agent_edit_msg").innerHTML = "";
347
+ self.saveButton.setEnable( true );
348
+ }, null ); // TODO
349
+ } else {
350
+ self.clearEdit();
351
+ agent_editor.editor.syntaxHighlight('init');
352
+ if ( !agent_editor.textarea.readOnly ) {
353
+ agent_editor.toggleReadOnly();
354
+ }
267
355
  }
268
- }
356
+ });
269
357
  },
270
358
 
271
359
  /**
@@ -301,8 +389,8 @@ fx.ui.pages.AgentEditorPage.prototype = {
301
389
  * @param {Function} success 成功時のコールバック
302
390
  * @param {Function} fail 失敗時のコールバック
303
391
  */
304
- saveFile : function( file, content, success, fail ) {
305
- this.agentServiceStub.put_file( file, content, this.target, success, fail );
392
+ saveFile : function( file, target, content, success, fail ) {
393
+ this.agentServiceStub.put_file( file, content, target, success, fail );
306
394
  },
307
395
  /**
308
396
  * エージェントファイルを削除する。
@@ -327,7 +415,9 @@ fx.ui.AgentFileListTable.prototype = util.merge( util.BasicTable, {
327
415
  var self = this;
328
416
  var columnDefs = [
329
417
  {key:"name", label:fx.template.Templates.agentEditor.fileList.column.name,
330
- sortable:true, resizeable:true, width:122},
418
+ sortable:true, resizeable:true, formatter: function( cell, record, column, data){
419
+ cell.innerHTML = String(data).escapeHTML();
420
+ }, width:122},
331
421
  {key:"update", label:fx.template.Templates.agentEditor.fileList.column.update,
332
422
  sortable:true, resizeable:true, formatter: function( cell, record, column, data){
333
423
  var d = new Date(data*1000);
@@ -44,12 +44,12 @@ fx.agent.ui.AgentSelector.prototype = {
44
44
  if ( !this.readOnly ) {
45
45
  this.addButton = new util.Button(this.id + "__add", "add", function() {
46
46
  self.add();
47
- }, "追加");
47
+ }, fx.template.Templates.common.button.add);
48
48
  this.addButton.setEnable( true );
49
49
 
50
50
  this.removeButton = new util.Button(this.id + "__remove", "remove", function() {
51
51
  self.remove();
52
- }, "削除");
52
+ }, fx.template.Templates.common.button.del);
53
53
  this.removeButton.setEnable( false );
54
54
  }
55
55
  },
@@ -57,6 +57,7 @@ fx.agent.ui.AgentSelector.prototype = {
57
57
  * エージェントを設定する
58
58
  */
59
59
  setAgents : function(data) {
60
+ this.agentListTable.loading(false);
60
61
  if ( data ) {
61
62
  this.agentListTable.setData(data);
62
63
  if ( !this.readOnly ) {
@@ -73,6 +74,7 @@ fx.agent.ui.AgentSelector.prototype = {
73
74
  // 編集中なら、編集を確定
74
75
  if ( this.isEditing() ) {
75
76
  this.edit();
77
+ this.agentListTable.table.unselectAllRows();
76
78
  }
77
79
  var agents = [];
78
80
  var rs = this.agentListTable.table.getRecordSet().getRecords( 0, this.agentListTable.length() );
@@ -112,13 +114,16 @@ fx.agent.ui.AgentSelector.prototype = {
112
114
  self.listAgentClass( false, function( data ) {
113
115
  self.agentClasses = data;
114
116
  self.agentClassListTable.setData(data);
117
+ self.agentClassListTable.loading(false);
115
118
  if ( data.length > 0 ) {
116
119
  self.agentClassListTable.table.selectRow(0);
117
120
  }
118
121
  }, null ); // TODO
119
122
  },
120
123
  buttons : [
121
- { type:"ok", action: function(dialog){
124
+ { type:"ok",
125
+ alt: fx.template.Templates.common.button.ok,
126
+ key: "Enter", action: function(dialog){
122
127
 
123
128
  var selectedRowIds = self.agentClassListTable.table.getSelectedRows();
124
129
  var error = null;
@@ -134,17 +139,19 @@ fx.agent.ui.AgentSelector.prototype = {
134
139
  }
135
140
 
136
141
  if (error) {
137
- dialog.content.innerHTML = '<div class="warn_msg">※'
138
- + error + '</div>' + msg;
142
+ dialog.content.innerHTML = fx.template.Templates.agentSelector.error.evaluate({
143
+ error: error.escapeHTML(),
144
+ msg: msg.escapeHTML()
145
+ });
139
146
  self.agentClassListTable.elementId = "agent_class_list";
140
- self.agentClassListTable.initialize();
141
- self.agentClassListTable.setData(self.agentClasses);
147
+ self.agentClassListTable.initialize();
148
+ self.agentClassListTable.setData(self.agentClasses);
142
149
  return false;
143
150
  } else {
144
151
  self._add( agents );
145
152
  }
146
153
  } },
147
- { type:"cancel" }
154
+ { type:"cancel", alt: fx.template.Templates.common.button.cancel, key: "Esc" }
148
155
  ]
149
156
  } );
150
157
 
@@ -170,11 +177,14 @@ fx.agent.ui.AgentSelector.prototype = {
170
177
  var defs = newAgents[i].properties;
171
178
  var prop = {};
172
179
  var def = {};
180
+ var error = null;
173
181
  for ( var j=0, s=defs.length;j<s;j++ ) {
174
182
  def[defs[j]["id"]] = defs[j];
175
183
  prop[defs[j]["id"]] = defs[j]["default"] || "";
184
+ error = error || this.agentPropertyEditor.validate[defs[j].type].call(
185
+ this.agentPropertyEditor, prop[defs[j]["id"]], defs[j].restrict );
176
186
  }
177
-
187
+
178
188
  var a = {
179
189
  "id": UUID.generate(),
180
190
  "name": "名称未設定エージェント"+k,
@@ -183,7 +193,8 @@ fx.agent.ui.AgentSelector.prototype = {
183
193
  "file_name":newAgents[i].file_name,
184
194
  "description":newAgents[i].description,
185
195
  "property_def":def,
186
- "properties":prop
196
+ "properties":prop,
197
+ "state": error ? "error" : ""
187
198
  };
188
199
  this.agentListTable.add( a ); // テーブルを更新
189
200
  }
@@ -192,10 +203,10 @@ fx.agent.ui.AgentSelector.prototype = {
192
203
  // 削除
193
204
  remove: function(){
194
205
 
195
- // 編集中なら、編集を確定
196
- if ( this.isEditing() ) {
197
- this.edit();
198
- }
206
+ // // 編集中なら、編集を確定
207
+ // if ( this.isEditing() ) {
208
+ // this.edit();
209
+ // }
199
210
 
200
211
  // 選択されている行を取得
201
212
  var selectedRowIds = this.agentListTable.table.getSelectedTrEls();
@@ -208,7 +219,7 @@ fx.agent.ui.AgentSelector.prototype = {
208
219
  this.dialog.show( "input", {
209
220
  message : msg,
210
221
  buttons : [
211
- { type:"ok", action: function(dialog){
222
+ { type:"ok",alt: fx.template.Templates.common.button.ok, key: "Enter", action: function(dialog){
212
223
  // 行のデータを削除
213
224
  for( var j=0,s=selectedRowIds.length;j<s;j++ ) {
214
225
  self.agentListTable.remove( selectedRowIds[j] );
@@ -217,7 +228,7 @@ fx.agent.ui.AgentSelector.prototype = {
217
228
  self.selectionChanged();
218
229
  }},
219
230
  { type:"cancel",
220
- alt: "キャンセル",
231
+ alt: fx.template.Templates.common.button.cancel,
221
232
  key: "Esc"
222
233
  }
223
234
  ]
@@ -246,9 +257,15 @@ fx.agent.ui.AgentSelector.prototype = {
246
257
  removeEnable = true;
247
258
  // エディタも更新する。
248
259
  var selectedEl = this.agentListTable.table.getSelectedTrEls()[0];
249
- this.agentPropertyEditor.target = this.agentListTable.table.getRecord (selectedRowIds[0]);
250
- var data = this.agentListTable.table.getRecord( selectedRowIds[0] ).getData();
251
- self.agentPropertyEditor.set( data );
260
+ var target = this.agentListTable.table.getRecord(selectedRowIds[0]);
261
+ if ( target ) {
262
+ this.agentPropertyEditor.target = target;
263
+ var data = target.getData();
264
+ self.agentPropertyEditor.set( data );
265
+ } else {
266
+ removeEnable = false;
267
+ self.agentPropertyEditor.clear( "エージェントを選択してください。" );
268
+ }
252
269
  } else {
253
270
  removeEnable = true;
254
271
  // エディタは初期化
@@ -263,14 +280,14 @@ fx.agent.ui.AgentSelector.prototype = {
263
280
  /**
264
281
  * プロパティを保存
265
282
  */
266
- edit: function(){
283
+ edit: function( ){
267
284
  if ( this.readOnly ) return;
268
285
  var newData = this.agentPropertyEditor.get();
269
286
  if ( newData ) {
270
287
  this.agentListTable.update( this.agentPropertyEditor.target, newData );
271
288
  this.agentPropertyEditor.target = null;
272
289
  this.agentPropertyEditor.end();
273
-
290
+
274
291
  this.checkDuplicateName();
275
292
  }
276
293
  },
@@ -338,10 +355,14 @@ fx.agent.ui.AgentClassListTable.prototype = util.merge( util.BasicTable, {
338
355
  initialize: function() {
339
356
  var self = this;
340
357
  var columnDefs = [
341
- {key:"class_name", label:"クラス", sortable:true, resizeable:true, width:80 },
342
- {key:"file_name", label:"ファイル", sortable:true, resizeable:true, width:80 },
358
+ {key:"class_name", label:"クラス", sortable:true, resizeable:true, formatter: function( cell, record, column, data){
359
+ cell.innerHTML = String(data).escapeHTML();
360
+ }, width:80 },
361
+ {key:"file_name", label:"ファイル", sortable:true, resizeable:true, formatter: function( cell, record, column, data){
362
+ cell.innerHTML = String(data).escapeHTML();
363
+ }, width:80 },
343
364
  {key:"description", label:"説明", sortable:true, resizeable:true, formatter: function( cell, record, column, data){
344
- cell.innerHTML = "<pre>" + data + "</pre>";
365
+ cell.innerHTML = "<pre>" + String(data).escapeHTML() + "</pre>";
345
366
  }}
346
367
  ];
347
368
  self.ds = new YAHOO.util.DataSource([]);
@@ -374,16 +395,20 @@ fx.agent.ui.AgentListTable.prototype = util.merge( util.BasicTable, {
374
395
  {key:"name", label:"名前", sortable:true, resizeable:true, width:100, formatter: function( cell, record, column, data){
375
396
  var str = data.escapeHTML();
376
397
  if ( record.getData().state === "error" || record.getData().duplicate_name_error ) {
377
- str = '<div class="problem"><span style="padding-right:3px;padding-top:2px;"><img src="./img/problem.gif" alt="問題" /></span>' + str + '</div>';
398
+ str = '<div class="problem"><span style="padding-right:3px;padding-top:2px;"><!--img src="./img/problem.gif" alt="問題" / --></span>' + String(str).escapeHTML() + '</div>';
378
399
  }
379
400
  cell.innerHTML = str;
380
401
  }},
381
- {key:"class_name", label:"クラス", sortable:true, resizeable:true, width:80 },
382
- {key:"file_name", label:"ファイル", sortable:true, resizeable:true,width:80 },
402
+ {key:"class_name", label:"クラス", sortable:true, resizeable:true, formatter: function( cell, record, column, data){
403
+ cell.innerHTML = String(data).escapeHTML();
404
+ }, width:80 },
405
+ {key:"file_name", label:"ファイル", sortable:true, resizeable:true, formatter: function( cell, record, column, data){
406
+ cell.innerHTML = String(data).escapeHTML();
407
+ }, width:80 },
383
408
  {key:"properties", label:"プロパティ", sortable:true, resizeable:true, width:250, formatter: function( cell, record, column, data){
384
409
  var str = "";
385
410
  for( var k in data ) {
386
- str += String(record.getData().property_def[k].name) + "=" + String(data[k]) + ", ";
411
+ str += String(record.getData().property_def[k].name).escapeHTML() + "=" + String(data[k]).escapeHTML() + ", ";
387
412
  if ( str.length > 500 ) { break; }
388
413
  }
389
414
  cell.innerHTML = str;
@@ -433,16 +458,17 @@ fx.agent.ui.AgentPropertyEditor.prototype = {
433
458
  var props = "";
434
459
  for ( var i in agent.property_def ) {
435
460
  props += fx.template.Templates.agentPropertyEditor.property.evaluate({
436
- "name": agent.property_def[i].name,
461
+ "name": agent.property_def[i].name.escapeHTML(),
437
462
  "id": agent.property_def[i].id,
438
- "default": agent.properties[agent.property_def[i].id] || agent.property_def[i]["default"]
463
+ "default": agent.properties[agent.property_def[i].id] != null
464
+ ? agent.properties[agent.property_def[i].id] : agent.property_def[i]["default"]
439
465
  });
440
466
  }
441
467
  var info = {
442
468
  "id": this.elementId,
443
- "class_name":agent.class_name,
444
- "name": agent.name,
445
- "desc": agent.description,
469
+ "class_name":agent.class_name.escapeHTML(),
470
+ "name": agent.name.escapeHTML(),
471
+ "desc": agent.description.escapeHTML(),
446
472
  "properties":props
447
473
  };
448
474
  document.getElementById( this.elementId ).innerHTML =
@@ -496,7 +522,7 @@ fx.agent.ui.AgentPropertyEditor.prototype = {
496
522
  } else if ( input["name"].match(/^property\_(.+)$/) ) {
497
523
  var id = RegExp.$1;
498
524
  var def = this.validators["property_" + id];
499
- error = error || this.validate[def.type].call( this, this.editing["properties"][id], def );
525
+ error = error || this.validate[def.type].call( this, value, def );
500
526
  this.editing["properties"][id] = !error ? this.convert[def.type].call( this, value ) : value ;
501
527
  }
502
528
  }
@@ -505,6 +531,7 @@ fx.agent.ui.AgentPropertyEditor.prototype = {
505
531
  },
506
532
  end : function() {
507
533
  this.editing = null;
534
+ this.clear( "エージェントを選択してください。" );
508
535
  },
509
536
  /**
510
537
  * 何も編集していない状態にする。
@@ -607,17 +634,19 @@ fx.agent.ui.AgentPropertyEditorReadOnly.prototype = {
607
634
  this.editing = util.merge({}, agent);
608
635
  var props = "";
609
636
  for ( var i in agent.property_def ) {
637
+ var value = agent.properties[agent.property_def[i].id] || agent.property_def[i]["default"];
638
+ if (value && Object.isFunction(value.escapeHTML )) { value = value.escapeHTML(); }
610
639
  props += fx.template.Templates.agentPropertyEditor.propertyReadOnly.evaluate({
611
- "name": agent.property_def[i].name,
640
+ "name": agent.property_def[i].name.escapeHTML(),
612
641
  "id": agent.property_def[i].id,
613
- "default": agent.properties[agent.property_def[i].id] || agent.property_def[i]["default"]
642
+ "default": value
614
643
  });
615
644
  }
616
645
  var info = {
617
646
  "id": this.elementId,
618
- "class_name":agent.class_name,
619
- "name": agent.name,
620
- "desc": agent.description,
647
+ "class_name":agent.class_name.escapeHTML(),
648
+ "name": agent.name.escapeHTML(),
649
+ "desc": agent.description.escapeHTML(),
621
650
  "properties":props
622
651
  };
623
652
  document.getElementById( this.elementId ).innerHTML =