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
@@ -16,7 +16,7 @@ fx.ui.pages.BtCreatePage = function() {
16
16
  var self = this;
17
17
  this.startButton = new util.Button("bt-create__start", "start", function() {
18
18
  self.start();
19
- });
19
+ }, fx.template.Templates.common.button.start);
20
20
  this.startButton.setEnable( true );
21
21
 
22
22
  // カレンダー
@@ -49,7 +49,11 @@ fx.ui.pages.BtCreatePage.prototype = {
49
49
  msg.style.display = "none";
50
50
 
51
51
  this.topicPath.set( "バックテスト:新規作成" );
52
-
52
+
53
+ // 日付の設定パネルを初期化
54
+ var el = document.getElementById("bt-create__range-summary");
55
+ el.innerHTML = fx.template.Templates.btcreate.dateSummary.notSelect;
56
+
53
57
  // 利用可能な日時
54
58
  var self = this;
55
59
  if ( this.startCalendar ) this.startCalendar.destroy();
@@ -70,6 +74,9 @@ fx.ui.pages.BtCreatePage.prototype = {
70
74
  self.endCalendar.listener.addListener( "selected", f );
71
75
  self.endCalendar.listener.addListener( "blur", f );
72
76
  }, null ); // TODO
77
+
78
+ // セレクタを初期化。
79
+ this.agentSelector.setAgents([]);
73
80
  },
74
81
  /**
75
82
  * ページを初期化する。
@@ -88,7 +95,7 @@ fx.ui.pages.BtCreatePage.prototype = {
88
95
  this.dialog.show( "warn", {
89
96
  message : "エージェントの設定に問題があります。",
90
97
  buttons : [
91
- { type:"ok" }
98
+ { type:"ok", alt: fx.template.Templates.common.button.ok, key: "Enter" }
92
99
  ]
93
100
  } );
94
101
  return;
@@ -99,7 +106,7 @@ fx.ui.pages.BtCreatePage.prototype = {
99
106
  if ( !name ) {
100
107
  this.dialog.show( "warn", {
101
108
  message : "名前が入力されていません。",
102
- buttons : [ { type:"ok" }]
109
+ buttons : [ { type:"ok", alt: fx.template.Templates.common.button.ok, key: "Enter" }]
103
110
  } );
104
111
  return;
105
112
  }
@@ -109,7 +116,7 @@ fx.ui.pages.BtCreatePage.prototype = {
109
116
  if ( !startDate ) {
110
117
  this.dialog.show( "warn", {
111
118
  message : "開始日が入力されていないか、フォーマットが不正です。",
112
- buttons : [ { type:"ok" }]
119
+ buttons : [ { type:"ok", alt: fx.template.Templates.common.button.ok, key: "Enter" }]
113
120
  } );
114
121
  return;
115
122
  }
@@ -118,14 +125,14 @@ fx.ui.pages.BtCreatePage.prototype = {
118
125
  if ( !endDate ) {
119
126
  this.dialog.show( "warn", {
120
127
  message : "終了日が入力されていないか、フォーマットが不正です。",
121
- buttons : [{ type:"ok" }]
128
+ buttons : [{ type:"ok", alt: fx.template.Templates.common.button.ok, key: "Enter" }]
122
129
  } );
123
130
  return;
124
131
  }
125
132
  if ( endDate.getTime() <= startDate.getTime() ) {
126
133
  this.dialog.show( "warn", {
127
134
  message : "開始日または終了日が不正です。",
128
- buttons : [{ type:"ok" }]
135
+ buttons : [{ type:"ok", alt: fx.template.Templates.common.button.ok, key: "Enter" }]
129
136
  } );
130
137
  return;
131
138
  }
@@ -136,7 +143,10 @@ fx.ui.pages.BtCreatePage.prototype = {
136
143
  this.dialog.show( "input", {
137
144
  message : "バックテストを開始します。よろしいですか?<br/>",
138
145
  buttons : [
139
- { type:"ok", action: function(dialog){
146
+ { type:"ok",
147
+ alt: fx.template.Templates.common.button.ok,
148
+ key: "Enter",
149
+ action: function(dialog){
140
150
  var memo = document.getElementById("bt-create_memo").value;
141
151
  self.processServiceStub.new_test( name, memo,
142
152
  startDate.getTime()/1000, endDate.getTime()/1000, agents, function(info) {
@@ -149,10 +159,13 @@ fx.ui.pages.BtCreatePage.prototype = {
149
159
  var msg = document.getElementById("bt-create_msg");
150
160
  msg.innerHTML = "※開始しました。( " + dateStr + " )";
151
161
  msg.style.display = "block";
152
-
153
- }, null ); //TODO
162
+ }, function(error){
163
+ self.dialog.show( "warn", {
164
+ message : fx.template.Templates.btcreate.start.error.evaluate({"error":error[0].error.escapeHTML()})
165
+ });
166
+ } );
154
167
  } },
155
- { type:"cancel" }
168
+ { type:"cancel", alt: fx.template.Templates.common.button.cancel, key: "Esc" }
156
169
  ]
157
170
  } );
158
171
  },
data/html/js/dialog.js CHANGED
@@ -38,10 +38,11 @@ util.Dialog = function() {
38
38
 
39
39
  this.dialog.style.visibility = "hidden";
40
40
  this.mask.style.visibility = "hidden";
41
+ this.keybind = new util.KeyBind( {}, this.dialog ) ;
41
42
  }
42
43
  util.Dialog.prototype = {
43
- TIME : 5,
44
- SPEED : 10,
44
+ TIME : 10,
45
+ SPEED : 25,
45
46
  WRAPPER : 'content',
46
47
 
47
48
  show : function( type, params ) {
@@ -60,20 +61,20 @@ util.Dialog.prototype = {
60
61
  this.header.style.display = "none";
61
62
  }
62
63
 
63
- var keybind = { "Tab" : function(){} };
64
+ var bind = { "Tab" : function(){} };
64
65
  this.buttons.innerHTML = "";
65
66
  if ( params.buttons ) {
66
67
  for ( var i = 0; i < params.buttons.length ; i++ ) {
67
- this.createButton( params.buttons[i], keybind );
68
+ this.createButton( params.buttons[i], bind );
68
69
  }
69
70
  } else {
70
71
  this.createButton( {
71
72
  id : "close",
72
- alt : "閉じる",
73
+ type : "close",
73
74
  accesskey: "C",
74
- key: "Enter"}, keybind);
75
+ key: "Enter"}, bind);
75
76
  }
76
- new util.KeyBind( keybind, this.dialog ) ;
77
+ this.keybind.binding = bind;
77
78
 
78
79
  // ダイアログを表示
79
80
  this.mask.style.visibility = "visible";
@@ -100,36 +101,42 @@ util.Dialog.prototype = {
100
101
  var content = document.getElementById(this.WRAPPER);
101
102
  this.mask.style.height = content.offsetHeight + 'px';
102
103
  var self = this;
104
+ // すでに変化中であれば一旦停止
105
+ if ( this.timer != null ) {
106
+ clearInterval(this.timer);
107
+ // コントロールの無効化はすでにされているので行わない。
108
+ } else {
109
+ // リンクとコントロールを無効化
110
+ this.cache = [];
111
+ var f = function( elms ) {
112
+ for( var i = 0 ; i < elms.length; i++ ) {
113
+ var old = {
114
+ target: elms[i],
115
+ disabled: elms[i].disabled,
116
+ accesskey: elms[i].accessKey,
117
+ tabIndex : elms[i].tabIndex
118
+ };
119
+ elms[i].disabled = true;
120
+ elms[i].accessKey = null;
121
+ elms[i].tabIndex = -1;
122
+ self.cache.push( old );
123
+ }
124
+ }
125
+ this.eachElements( "input", f);
126
+ this.eachElements( "textarea", f);
127
+ this.eachElements( "a", f);
128
+ this.eachElements( "object", function(elms){
129
+ for( var i = 0 ; i < elms.length; i++ ) {
130
+ elms[i].style.visibility = "hidden";
131
+ }
132
+ });
133
+ }
103
134
  this.timer = setInterval(function(){ self.fadeDialog(1); }, this.TIME);
104
-
135
+ var as = this.buttons.getElementsByTagName( "a" );
136
+ if ( as && as[0] ) { as[0].focus(); }
105
137
  if ( params.init ) {
106
138
  params.init.call( null, this );
107
139
  }
108
-
109
- // リンクとコントロールを無効化
110
- this.cache = [];
111
- var f = function( elms ) {
112
- for( var i = 0 ; i < elms.length; i++ ) {
113
- var old = {
114
- target: elms[i],
115
- disabled: elms[i].disabled,
116
- accesskey: elms[i].accessKey,
117
- tabIndex : elms[i].tabIndex
118
- };
119
- elms[i].disabled = true;
120
- elms[i].accessKey = null;
121
- elms[i].tabIndex = -1;
122
- self.cache.push( old );
123
- }
124
- }
125
- this.eachElements( "input", f);
126
- this.eachElements( "textarea", f);
127
- this.eachElements( "a", f);
128
- this.eachElements( "object", function(elms){
129
- for( var i = 0 ; i < elms.length; i++ ) {
130
- elms[i].style.visibility = "hidden";
131
- }
132
- });
133
140
  },
134
141
 
135
142
  createButton: function( params, keybind ) {
@@ -188,7 +195,6 @@ util.Dialog.prototype = {
188
195
  c.target.tabIndex = c.tabIndex;
189
196
  c.target.disabled = c.disabled;
190
197
  }
191
- this.cache = null;
192
198
 
193
199
  this.eachElements( "object", function(elms){
194
200
  for( var i = 0 ; i < elms.length; i++ ) {
@@ -196,9 +202,12 @@ util.Dialog.prototype = {
196
202
  }
197
203
  });
198
204
 
205
+ this.keybind.binding = {};
206
+
199
207
  this.dialog.style.visibility = "hidden";
200
208
  this.mask.style.visibility = "hidden";
201
209
  clearInterval(this.timer);
210
+ this.timer = null;
202
211
  }
203
212
  },
204
213
 
@@ -92,7 +92,7 @@ fx.ui.pages.LogResultPage = function() {
92
92
  var self = this;
93
93
  this.updateButton = new util.Button("subpage-log__update", "update", function() {
94
94
  self.update();
95
- });
95
+ }, fx.template.Templates.common.button.update);
96
96
  this.updateButton.setEnable( true );
97
97
  }
98
98
  fx.ui.pages.LogResultPage.prototype = {
@@ -118,7 +118,7 @@ fx.ui.pages.LogResultPage.prototype = {
118
118
  var logEl = document.getElementById( "subpage-log_log" );
119
119
  logEl.innerHTML= fx.template.Templates.common.loading;
120
120
  this.outputServiceStub.get_log( this.currentProcessId, function( log ) {
121
- logEl.innerHTML = "<pre style='line-height: 110%;'>" + log + "</pre>";
121
+ logEl.innerHTML = "<pre style='line-height: 110%;'>" + log.escapeHTML() + "</pre>";
122
122
  }, function(){} ); // TODO
123
123
  }
124
124
  }
@@ -133,9 +133,9 @@ fx.ui.pages.TradeResultPage = function() {
133
133
  this.tradeListTable.initialize();
134
134
  this.agentResultListTable = new fx.ui.AgentResultListTable( "subpage-trade__agent-list" );
135
135
  this.agentResultListTable.initialize();
136
- this.updateButton = new util.Button("subpage-trade__update", "update", function() {
136
+ this.updateButton = new util.Button("subpage-trade__update", "update_s", function() {
137
137
  self.update();
138
- });
138
+ }, fx.template.Templates.common.button.update);
139
139
  this.updateButton.setEnable( true );
140
140
  }
141
141
  fx.ui.pages.TradeResultPage.prototype = {
@@ -192,25 +192,25 @@ fx.ui.pages.TradeResultPage.prototype = {
192
192
  this.dialog.show( "warn", {
193
193
  message : "表示範囲に数値が入力されていません。",
194
194
  buttons : [
195
- { type:"ok" }
195
+ { type:"ok", alt: fx.template.Templates.common.button.ok, key: "Enter" }
196
196
  ]
197
197
  } );
198
198
  return;
199
199
  }
200
200
  } else {
201
- // 入力がなければ今月のデータを表示
201
+ // 入力がなければ今週のデータを表示
202
202
  var now = new Date();
203
- var end = new Date( now.getFullYear(), now.getMonth()+1, 0 );
204
- startDate = new Date( now.getFullYear(), now.getMonth(), 1 ).getTime()/1000;
205
- endDate = end.getTime()/1000;
203
+ var start = new Date( now.getFullYear(), now.getMonth(), now.getDate()-7 );
204
+ startDate = start.getTime()/1000;
205
+ endDate = now.getTime()/1000;
206
206
 
207
207
  // フィールドにも設定しておく
208
208
  document.getElementById("subpage-trade_range-year").value = now.getFullYear();
209
209
  document.getElementById("subpage-trade_range-month").value = now.getMonth()+1;
210
- document.getElementById("subpage-trade_range-day").value = 1;
210
+ document.getElementById("subpage-trade_range-day").value = start.getDate();
211
211
  document.getElementById("subpage-trade_range-end-year").value = now.getFullYear();
212
212
  document.getElementById("subpage-trade_range-end-month").value = now.getMonth()+1;
213
- document.getElementById("subpage-trade_range-end-day").value = end.getDate();
213
+ document.getElementById("subpage-trade_range-end-day").value = now.getDate();
214
214
  }
215
215
  } else {
216
216
  // バックテストの場合、全テストが対象
@@ -219,7 +219,9 @@ fx.ui.pages.TradeResultPage.prototype = {
219
219
  }
220
220
  // ロード中に変更
221
221
  summaryEl.innerHTML= fx.template.Templates.common.loading;
222
-
222
+ this.agentResultListTable.loading(true);
223
+ this.tradeListTable.loading(true);
224
+
223
225
  var self = this;
224
226
  // 終了時間はその日の終わりにする
225
227
  this.tradeResultServiceStub.list( this.currentProcessId, "6h", startDate, endDate+60*60*25, function( list ) {
@@ -231,7 +233,10 @@ fx.ui.pages.TradeResultPage.prototype = {
231
233
  return (b.date || 0) - ( a.date || 0);
232
234
  } ) );
233
235
  self.agentResultListTable.setData( value[1] );
234
-
236
+
237
+ self.agentResultListTable.loading(false);
238
+ self.tradeListTable.loading(false);
239
+
235
240
  }, function(){} ); // TODO
236
241
  },
237
242
  aggregate: function( list ) {
@@ -256,7 +261,7 @@ fx.ui.pages.TradeResultPage.prototype = {
256
261
  for( var j in pairList ) {
257
262
  if (typeof pairList[j] == "function" ) continue;
258
263
  all.pair += fx.template.Templates.submenu.trade.pair.evaluate(
259
- {pair:j,value:pairList[j]} );
264
+ {pair:j.escapeHTML(),value:pairList[j]} );
260
265
  }
261
266
  all = this.finish( all, true );
262
267
  var tmp = [];
@@ -422,23 +427,27 @@ fx.ui.TradeListTable.prototype = util.merge( util.BasicTable, {
422
427
  cell.innerHTML = "不明"; break;
423
428
  }
424
429
  }},
425
- {key:"pair", label:"通貨ペア", sortable:true, resizeable:true, width:50 },
430
+ {key:"pair", label:"通貨ペア", sortable:true, resizeable:true, formatter: function( cell, record, column, data){
431
+ cell.innerHTML = String(data).escapeHTML();
432
+ }, width:50 },
426
433
  {key:"rate", label:"レート", sortable:true, resizeable:true,width:50 },
427
434
  {key:"fix_rate", label:"決済レート", sortable:true, resizeable:true,width:50,formatter: function( cell, record, column, data){
428
435
  cell.innerHTML = data ? data : "-";
429
436
  } },
430
437
  {key:"count", label:"数量", sortable:true, resizeable:true,width:30 },
431
438
  {key:"trader", label:"エージェント", sortable:true, resizeable:true,width:50,formatter: function( cell, record, column, data){
432
- cell.innerHTML = data ? data : "-";
439
+ cell.innerHTML = data ? data.escapeHTML() : "-";
433
440
  } },
434
441
  {key:"date", label:"取引日時", sortable:true, resizeable:true,width:118, formatter: function( cell, record, column, data){
435
442
  var d = new Date(data*1000);
436
443
  cell.innerHTML = util.formatDate(d);
444
+ //cell.innerHTML = '<a href="javascript:util.getSwf(\'chart\').setDate( ' + data + ' );scrollTo( 0, 0 );">' + util.formatDate(d) + '</a>';
437
445
  } },
438
446
  {key:"fix_date", label:"決済日時", sortable:true, resizeable:true,width:118, formatter: function( cell, record, column, data){
439
447
  if (data) {
440
448
  var d = new Date(data*1000);
441
449
  cell.innerHTML = util.formatDate(d);
450
+ //cell.innerHTML = '<a href="javascript:util.getSwf(\'chart\').setDate( ' + data + ' );scrollTo( 0, 0 );">' + util.formatDate(d) + '</a>';
442
451
  } else {
443
452
  cell.innerHTML = "-";
444
453
  }
@@ -471,7 +480,9 @@ fx.ui.AgentResultListTable.prototype = util.merge( util.BasicTable, {
471
480
  initialize: function() {
472
481
  var self = this;
473
482
  var columnDefs = [
474
- {key:"agentName", label:"名前", sortable:true, resizeable:true,width:100 },
483
+ {key:"agentName", label:"名前", sortable:true, resizeable:true, formatter: function( cell, record, column, data){
484
+ cell.innerHTML = String(data).escapeHTML();
485
+ }, width:100 },
475
486
  {key:"totalProfitOrLoss", label:"損益合計", sortable:true, resizeable:true,width:70, formatter: function( cell, record, column, data){
476
487
  cell.innerHTML = "<div style='text-align:right;'>"
477
488
  + fx.ui.pages.TradeResultPage.prototype.decorateProfitOrLoss(data)
@@ -564,6 +575,8 @@ fx.ui.pages.InfoResultPage.prototype = {
564
575
  // ロード中に変更
565
576
  infoEl.innerHTML= fx.template.Templates.common.loading;
566
577
 
578
+ // セレクタを初期化。
579
+ this.agentSelector.setAgents([]);
567
580
  var self = this;
568
581
  this.processServiceStub.get( this.currentProcessId, function( p ) {
569
582
  if ( self.currentProcessId == "rmt" ) {
@@ -576,8 +589,8 @@ fx.ui.pages.InfoResultPage.prototype = {
576
589
  var startStr = s.getFullYear() + "-" + (s.getMonth()+1) + "-" + s.getDate();
577
590
  var endStr = e.getFullYear() + "-" + (e.getMonth()+1) + "-" + e.getDate();
578
591
  infoEl.innerHTML = fx.template.Templates.submenu.info.info.evaluate( {
579
- name: p.name,
580
- memo: p.memo.replace(/^\s+|\s+$/g, '') || "&nbsp;",
592
+ name: p.name.escapeHTML(),
593
+ memo: p.memo.escapeHTML().replace(/^\s+|\s+$/g, '') || "&nbsp;",
581
594
  range: startStr + " ~ " + endStr
582
595
  });
583
596
  }
@@ -641,8 +654,8 @@ fx.ui.pages.GraphSettingResultPage.prototype = {
641
654
  colorsBody += '<div id="submenu-graph_color_' + index + '_' + k + '"></div>';
642
655
  }
643
656
  itemBody += fx.template.Templates.submenu.graph.item.evaluate( {
644
- name: j,
645
- agentName: i,
657
+ name: j.escapeHTML(),
658
+ agentName: i.escapeHTML(),
646
659
  checked: outs[i][j]["visible"] == false ? "" : 'checked="checked"',
647
660
  id : index,
648
661
  colors: colorsBody
@@ -650,12 +663,12 @@ fx.ui.pages.GraphSettingResultPage.prototype = {
650
663
  index += 1;
651
664
  }
652
665
  str += fx.template.Templates.submenu.graph.agent.evaluate( {
653
- agentName: self.agentNameMap[i] || "(不明)",
666
+ agentName: self.agentNameMap[i].escapeHTML() || "(不明)",
654
667
  items: itemBody
655
668
  } );
656
669
  }
657
- el.innerHTML = str || '<div style="margin:10px 0px 0px 0px;">( グラフはありません。)</div>';
658
-
670
+ el.innerHTML = str || '<div style="margin:10px 0px 0px 0px;">( グラフはありません。)</div>';
671
+
659
672
  // イベントを割り当て
660
673
  self.pickers = [];
661
674
  for ( var i=0; i<index; i++ ) {
@@ -674,7 +687,6 @@ fx.ui.pages.GraphSettingResultPage.prototype = {
674
687
  // 色
675
688
  var index = i;
676
689
  var colorChanged = function() {
677
- debug(index);
678
690
  var colors = [];
679
691
  for ( var j = 0, n=self.pickers[index].length;j<n;j++ ) {
680
692
  colors.push( self.pickers[index][j].get());
@@ -16,7 +16,7 @@ fx.ui.pages.RtSettingPage = function() {
16
16
  var self = this;
17
17
  this.applyButton = new util.Button("rt-setting__ok", "apply", function() {
18
18
  self.ok();
19
- });
19
+ }, fx.template.Templates.common.button.apply);
20
20
  this.applyButton.setEnable( true );
21
21
  }
22
22
  fx.ui.pages.RtSettingPage.prototype = {
@@ -66,7 +66,7 @@ fx.ui.pages.RtSettingPage.prototype = {
66
66
  this.dialog.show( "warn", {
67
67
  message : "エージェントの設定に問題があります。",
68
68
  buttons : [
69
- { type:"ok" }
69
+ { type:"ok", alt: fx.template.Templates.common.button.ok, key: "Enter" }
70
70
  ]
71
71
  } );
72
72
  return;
@@ -78,10 +78,13 @@ fx.ui.pages.RtSettingPage.prototype = {
78
78
  this.dialog.show( "input", {
79
79
  message : "設定を反映します。よろしいですか?<br/>",
80
80
  buttons : [
81
- { type:"ok", action: function(dialog){
81
+ { type:"ok",
82
+ alt: fx.template.Templates.common.button.ok,
83
+ key: "Enter",
84
+ action: function(dialog){
82
85
  var enable = document.getElementById("rt-setting_trade-enable").checked;
83
86
  self.updateSetting( enable, agents, function() {
84
- // 更新時刻を表示 // TODO
87
+ // 更新時刻を表示
85
88
  var dateStr = util.formatDate( new Date() );
86
89
  var msg = document.getElementById("rt-setting_msg");
87
90
  msg.innerHTML = "※設定を反映しました。( " + dateStr + " )";
@@ -90,9 +93,13 @@ fx.ui.pages.RtSettingPage.prototype = {
90
93
  // 自動更新設定を更新
91
94
  self.tradeEnable.set( enable );
92
95
 
93
- }, null ); //TODO
96
+ }, function(error){
97
+ self.dialog.show( "warn", {
98
+ message : fx.template.Templates.rtsetting.apply.error.evaluate({"error":error[0].error.escapeHTML()})
99
+ });
100
+ });
94
101
  } },
95
- { type:"cancel" }
102
+ { type:"cancel", alt: fx.template.Templates.common.button.cancel, key: "Esc" }
96
103
  ]
97
104
  } );
98
105
  },
data/html/js/sidebar.js CHANGED
@@ -131,7 +131,10 @@ fx.ui.SideBar.prototype = {
131
131
  this.dialog.show( "input", {
132
132
  message : "バックテストを削除します。よろしいですか?",
133
133
  buttons : [
134
- { type:"ok", action: function(dialog){
134
+ { type:"ok",
135
+ alt: fx.template.Templates.common.button.ok,
136
+ key: "Enter",
137
+ action: function(dialog){
135
138
  self.processServiceStub.delete_test( processId, function(p) {
136
139
  var tmp = [];
137
140
  for ( var i=0,n=self.runnings.length;i<n;i++ ) {
@@ -144,7 +147,7 @@ fx.ui.SideBar.prototype = {
144
147
 
145
148
  }, function(){} ); // TODO
146
149
  } },
147
- { type:"cancel" }
150
+ { type:"cancel", alt: fx.template.Templates.common.button.cancel, key: "Esc" }
148
151
  ]
149
152
  } );
150
153
  },
@@ -190,7 +193,7 @@ fx.ui.SideBar.prototype = {
190
193
  e.style.display = "none";
191
194
  state.innerHTML = this.stateToDisplayName( p.state == "RUNNING" ? "FINISHED" : p.state );
192
195
  // 実行結果へのリンクを有効化する。
193
- name.innerHTML = '<a href="javascript:fx.app.sideBar.to( \'sidebar_result_' + p.id + '\' );">' + p.name + "</a>";
196
+ name.innerHTML = '<a href="javascript:fx.app.sideBar.to( \'sidebar_result_' + p.id + '\' );">' + p.name.escapeHTML() + "</a>";
194
197
  }
195
198
  },
196
199
 
@@ -203,9 +206,9 @@ fx.ui.SideBar.prototype = {
203
206
  div.id = "process_" + process.id;
204
207
  div.innerHTML = fx.template.Templates.sidebar.process.evaluate({
205
208
  id : process.id,
206
- name : process.name,
209
+ name : process.name.escapeHTML(),
207
210
  date : util.formatDate(new Date(process.create_date*1000)),
208
- state : this.stateToDisplayName( process.state)
211
+ state : this.stateToDisplayName(process.state)
209
212
  });
210
213
  return div;
211
214
  },
data/html/js/templates.js CHANGED
@@ -4,26 +4,48 @@ namespace( "fx.template" )
4
4
 
5
5
  fx.template.Templates = {
6
6
  common: {
7
- loading : '<img src="./img/loading.gif" alt="loading.." />',
7
+ loading : '<img src="./img/loading.gif" alt="loading.." title="loading.." />',
8
8
  date: {
9
9
  d:"日", m:"月", y:"年",
10
10
  h:"時間", mm: "分", s:"秒"
11
11
  },
12
12
  button : {
13
+ start: "開始",
14
+ apply : "適用",
15
+ update : "更新",
13
16
  add : "追加",
14
17
  del : "削除",
18
+ save : "保存",
15
19
  ok : "OK",
16
- cancel: "キャンセル"
20
+ cancel: "キャンセル",
21
+ yes : "はい",
22
+ no: "いいえ"
17
23
  }
18
24
  },
25
+ agentSelector: {
26
+ error : new Template( '<div class="problem">※#{error}</div>#{msg}')
27
+ },
19
28
  agentEditor: {
20
29
  topicPath: {
21
30
  agent: "エージェント:エージェントの作成/編集",
22
31
  sharedLib: "エージェント:共有ライブラリの作成/編集"
23
32
  },
33
+ desc: {
34
+ agent: "※エージェントを作成・編集します。一覧からファイルを選択して編集、または追加ボタンから追加して下さい。<br/>"
35
+ + "※改変後のコードは次にエージェントを使用した場合に有効になります。",
36
+ sharedLib: "※共有ライブラリを作成・編集します。一覧からファイルを選択して編集、または追加ボタンから追加して下さい。<br/>"
37
+ + "※改変後のコードは次にライブラリのクラスや関数を使用した場合に有効になります。"
38
+ },
39
+ saved : {
40
+ error : new Template(
41
+ '<span class="problem">※コンパイルエラー</span> <span style="color: #FF3366;">( #{now} ) <br/>' +
42
+ ' #{result}</span>'),
43
+ success : new Template('※保存しました。 ( #{now} )')
44
+ },
45
+ dosave : "未保存のデータがあります。保存しますか?",
24
46
  add : {
25
47
  error : new Template(
26
- '<div class="warn_msg">※#{error}</div>'
48
+ '<div class="problem">※#{error}</div>'
27
49
  ),
28
50
  body : new Template(
29
51
  "追加するファイル名を入力してください。<br/>" +
@@ -121,8 +143,20 @@ fx.template.Templates = {
121
143
  ' <tr><td class="label small" >推定所要時間</td><td class="value">#{time} </td></tr>' +
122
144
  ' </table>'),
123
145
  error: "<span class='problem'>※開始日、終了日の設定が不正です。</span>"
146
+ },
147
+ start : {
148
+ error: new Template("<span class='problem'>※テストの開始に失敗しました。" +
149
+ "<pre style='width:350px;height:200px;overflow:scroll;font-size:11px;font-weight:normal'>#{error}</pre>" +
150
+ "</span>")
124
151
  }
125
152
  },
153
+ rtsetting : {
154
+ apply: {
155
+ error: new Template("<span class='problem'>※設定の反映に失敗しました。" +
156
+ "<pre style='width:350px;height:200px;overflow:scroll;font-size:11px;font-weight:normal'>#{error}</pre>" +
157
+ "</span>")
158
+ }
159
+ },
126
160
  submenu : {
127
161
  info : {
128
162
  info : new Template(