browser_app_base 0.0.2 → 0.0.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63c1acfb3f65ae7519a6f74b1a0b2b138fd04f129585070c11e4211850c0a880
4
- data.tar.gz: df7982ee9fe63c7442ac7f53404921aec97bd83fce49a36888df10b6dd58be8b
3
+ metadata.gz: ee14b20cd2c842b0c470d9b96f31549ae576912a5e79afcbb4b44b35d3cfc740
4
+ data.tar.gz: 746081592fef24334ae14f50fbcddb672fa29103b800ea8bd84048711ff0ec9e
5
5
  SHA512:
6
- metadata.gz: 9610604a065b31f377798eb211b13ac92b50770d353058d7ad9a969b4b2071c82e9f927725ca3c76fe494b09edb6842ff98323991a126f50ca2dfe51fda2aa3d
7
- data.tar.gz: 4db1d41f410dc0f546d4db93895118821530d955cb0b098506b823c2906538c6a131460afea3b156773253e8ca6c8c98bd3564e5ed8a952b2dffefbc7fd3b56d
6
+ metadata.gz: a0360895d392e1fdbf2930c73c82ba09a8551ea15014ee30f5e71393b4b04d48ea52773f174cc4eb884eea85574e338bf0d8661362c3c4f1cda8512429466f4c
7
+ data.tar.gz: a48af4eeb30f310d5f601e19a212fb2c4e4239b61952ab33b2cc50d9e2392dc14b7fec672abc64507aadf55d415831cb194048af9c8903e7fb7e604476895441
@@ -0,0 +1,15 @@
1
+ {
2
+ // IntelliSense を使用して利用可能な属性を学べます。
3
+ // 既存の属性の説明をホバーして表示します。
4
+ // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "Debug Local File",
9
+ "type": "Ruby",
10
+ "request": "launch",
11
+ "cwd": "${workspaceRoot}/lib/template/",
12
+ "program": "${workspaceRoot}/lib/template/start.rb"
13
+ }
14
+ ]
15
+ }
data/README.md CHANGED
@@ -24,16 +24,41 @@ Or install it yourself as:
24
24
 
25
25
  create_browser_app [options]
26
26
  -d, --dir dir_name application directory
27
+ -a, --app app_name application name
27
28
  -h, --help command help
28
29
 
29
30
 
30
- create app templat
31
+ ## Create app templat
31
32
 
32
- $ create_browser_app -d ~/test/
33
+ $ create_browser_app -d ~/test/ -a MyApp
33
34
 
34
- start application
35
+ ## add application code
36
+ $ cd ~/test/
37
+ $ vi my_app.rb
35
38
 
36
- $ cd ~/test/app
39
+ ```ruby
40
+ class MyApp < AppMainBase
41
+ def start(argv)
42
+ super
43
+ # add application code
44
+ end
45
+
46
+ def stop()
47
+ super
48
+ # add application code
49
+ end
50
+ end
51
+ ```
52
+
53
+ ui application sample
54
+
55
+ index.html
56
+ css/index.css
57
+ js/main.js
58
+
59
+ ## Start application
60
+
61
+ $ cd ~/test/
37
62
  $ ruby start.rb
38
63
 
39
64
  ## Development
@@ -7,6 +7,7 @@ require "optparse"
7
7
  opt = OptionParser.new
8
8
  o = {}
9
9
  opt.on("-d dir_name", "--dir dir_name", "application directory") { |v| o[:dir] = v }
10
+ opt.on("-a app_name", "--app app_name", "application name") { |v| o[:app] = v }
10
11
  opt.on("-h", "--help", "command help") { puts opt; exit }
11
12
  begin
12
13
  opt.parse!(ARGV)
@@ -20,4 +21,4 @@ if o[:dir] == nil
20
21
  exit
21
22
  end
22
23
 
23
- BrowserAppBase.create o[:dir]
24
+ BrowserAppBase.create o
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BrowserAppBase
4
- VERSION = "0.0.2"
4
+ VERSION = "0.0.6"
5
5
  end
@@ -1,20 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "browser_app_base/version"
4
-
5
4
  require "fileutils"
6
5
 
7
6
  module BrowserAppBase
8
7
  class Error < StandardError; end
9
8
 
10
- # Your code goes here...
9
+ def self.get_app_file(app)
10
+ app_file_name = ""
11
+ app.each_char do |s|
12
+ if s =~ /[A-Z]/
13
+ app_file_name += "_" if app_file_name.size != 0
14
+ app_file_name += s.downcase
15
+ else
16
+ app_file_name += s
17
+ end
18
+ end
19
+ return app_file_name + ".rb"
20
+ end
21
+
22
+ def self.get_app_name(app)
23
+ app_name = ""
24
+ app.each_char do |s|
25
+ if s =~ /[a-z]/ and app_name.size == 0
26
+ app_name += s.upcase
27
+ else
28
+ app_name += s
29
+ end
30
+ end
31
+ return app_name
32
+ end
11
33
 
12
- def self.create(dir)
34
+ def self.create(arg)
35
+ dir = arg[:dir]
36
+ app = arg[:app]
13
37
  puts "create application base #{dir}"
14
38
 
15
39
  FileUtils.mkdir_p dir
16
40
 
17
41
  path = File.dirname(File.expand_path(__FILE__))
18
- FileUtils.cp_r "#{path}/template", "#{dir}/app"
42
+ Dir.glob("#{path}/template/*") do |f|
43
+ puts "#{f} => #{dir}"
44
+ FileUtils.cp_r f, "#{dir}/"
45
+ end
46
+
47
+ if app
48
+ app_file = get_app_file(app)
49
+
50
+ load_app = <<"EOS"
51
+ require '#{app_file}'
52
+ $app = #{get_app_name(app)}.new
53
+ EOS
54
+
55
+ File.open("#{dir}/app_load.rb", "w") do |f|
56
+ f.write load_app
57
+ end
58
+
59
+ puts "create #{app_file}"
60
+ new_file = "#{dir}/#{app_file}"
61
+ FileUtils.cp("#{dir}/my_app_sample.rb", new_file)
62
+ buf = File.binread(new_file)
63
+ File.binwrite(new_file, buf.gsub(/MyApp/, get_app_name(app)))
64
+ end
19
65
  end
20
66
  end
@@ -0,0 +1,2 @@
1
+ require "my_app_sample.rb"
2
+ $app = MyApp.new
@@ -1,4 +1,4 @@
1
1
  {
2
- "chrome_win": "\"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe\"",
2
+ "chrome_win": "start chrome",
3
3
  "chrome_linux": "/bin/google-chrome"
4
4
  }
@@ -0,0 +1,50 @@
1
+ [
2
+ {
3
+ "name": "name1",
4
+ "value": "value1",
5
+ "type": "input",
6
+ "select": "",
7
+ "description": "設定項目1"
8
+ },
9
+ {
10
+ "name": "name2",
11
+ "value": true,
12
+ "type": "checkbox",
13
+ "select": "",
14
+ "description": "有効にする場合はチェック"
15
+ },
16
+ {
17
+ "name": "name3",
18
+ "value": "1",
19
+ "type": "select",
20
+ "select": [
21
+ "1",
22
+ "2",
23
+ "3",
24
+ "4",
25
+ "5"
26
+ ],
27
+ "description": "選択項目"
28
+ },
29
+ {
30
+ "name": "name4",
31
+ "value": "value4",
32
+ "type": "input",
33
+ "select": "",
34
+ "description": "設定項目4"
35
+ },
36
+ {
37
+ "name": "name5",
38
+ "value": "value5",
39
+ "type": "input",
40
+ "select": "",
41
+ "description": "設定項目5"
42
+ },
43
+ {
44
+ "name": "name6",
45
+ "value": "value6",
46
+ "type": "input",
47
+ "select": "",
48
+ "description": "設定項目6"
49
+ }
50
+ ]
@@ -24,6 +24,34 @@ get "/js/:name.js" do
24
24
  File.read "js/#{params[:name]}.js"
25
25
  end
26
26
 
27
+ get "/config/*.*" do |file, ext|
28
+ content_type "text/json", :charset => "utf-8"
29
+ puts "#{file}.#{ext}"
30
+ File.read "config/#{file}.#{ext}"
31
+ end
32
+
33
+ get "/open_dialog" do
34
+ dialog_html = <<'EOS'
35
+ <!DOCTYPE html>
36
+ <html>
37
+ <head>
38
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
39
+ <title>Message Dialog</title>
40
+ <style type="text/css">
41
+ <!--
42
+ body {
43
+ color: #000000;
44
+ background-color: #ffffff;
45
+ overflow: hidden;
46
+ font-size: 12px;
47
+ }
48
+ -->
49
+ </style>
50
+ </head>
51
+ EOS
52
+ dialog_html += "<body>" + params["msg"] + "</body></html>"
53
+ end
54
+
27
55
  map "/search" do
28
56
  run Search
29
57
  end
@@ -46,6 +74,6 @@ configure do
46
74
 
47
75
  end
48
76
 
49
- #\ --port 61820
77
+ #\ --port 54068
50
78
 
51
79
  run Sinatra::Application
@@ -2,6 +2,7 @@ body {
2
2
  color: #000000;
3
3
  background-color: #cac3ec4f;
4
4
  overflow: hidden;
5
+ font-size: 12px;
5
6
  }
6
7
 
7
8
  hr {
@@ -22,9 +23,9 @@ hr {
22
23
  padding: 5px;
23
24
  width: 95vw;
24
25
  height: 50vh;
26
+ overflow: auto;
25
27
  }
26
28
 
27
-
28
29
  .inarea {
29
30
  border: thin solid #000000;
30
31
  margin: 5px;
@@ -32,12 +33,6 @@ hr {
32
33
  width: 95%;
33
34
  }
34
35
 
35
- input {
36
- background-color: #FAFAFA;
37
- margin: 5px;
38
- padding: 5px;
39
- }
40
-
41
36
  input.long {
42
37
  width: 90%;
43
38
  background-color: #FAFAFA;
@@ -50,3 +45,60 @@ textarea.long {
50
45
  height: 50vh;
51
46
  }
52
47
 
48
+ .ui-widget {
49
+ font-size: 12px;
50
+ }
51
+
52
+ .ui-autocomplete {
53
+ max-height: 45vh;
54
+ max-width: 90wh;
55
+ overflow-y: auto;
56
+ overflow-x: auto;
57
+ padding-right: 10px;
58
+ }
59
+
60
+ #jquery-ui-autocomplete label {
61
+ float: left;
62
+ margin-right: 0.5em;
63
+ color: black;
64
+ }
65
+
66
+ .ui-dialog {
67
+ position: absolute;
68
+ top: 0;
69
+ left: 0;
70
+ padding: .2em;
71
+ outline: 0;
72
+ }
73
+
74
+ .long {
75
+ width: 90%;
76
+ }
77
+
78
+ #setting_dialog {
79
+ color: #796fe9;
80
+ background-color: #000000;
81
+ }
82
+
83
+ .setting_name {
84
+ width: 200px;
85
+ color: #796fe9;
86
+ background-color: #000000;
87
+ }
88
+
89
+ .setting_value {
90
+ width: 300px;
91
+ color: #796fe9;
92
+ background-color: #000000;
93
+ }
94
+
95
+ .setting_checkbox {
96
+ color: #796fe9;
97
+ background-color: #000000;
98
+ }
99
+
100
+ ul.log {
101
+ list-style-type: decimal;
102
+ font-size: 12px;
103
+ color: #5d0a94;
104
+ }
@@ -11,12 +11,12 @@
11
11
  <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
12
12
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
13
13
 
14
- <script src="http://localhost:61820/js/main.js"></script>
15
- <link rel="stylesheet" href="http://localhost:61820/css/index.css" type="text/css">
14
+ <script src="http://localhost:54068/js/main.js"></script>
15
+ <link rel="stylesheet" href="http://localhost:54068/css/index.css" type="text/css">
16
16
  </head>
17
17
 
18
18
  <body>
19
- <h3>サンプル</h3>
19
+ <h4>サンプル</h4>
20
20
  <hr>
21
21
  <table>
22
22
  <tr>
@@ -26,13 +26,39 @@
26
26
  <td>
27
27
  <input type="button" id="stop" name="stop" value="停止">
28
28
  </td>
29
+ <td>
30
+ <div id="setting_dialog" style="display:none;">
31
+ <dl id="wrap"></dl>
32
+ </div>
33
+ <input type="button" id="setting" value="設定" />
34
+ </td>
35
+ </tr>
36
+ </table>
37
+
38
+ <div id="dialog1" style="display:none;">
39
+ <input class="inarea" type="text" name="search_str" id="search_str">
40
+ </div>
41
+ <table>
42
+ <tr>
43
+ <td class="long"><input class="inarea" type="text" id="upFile" name="upFile"></td>
44
+ <td><input type="button" id="select_file" value="ファイル選択" /></td>
45
+ </tr>
46
+ </table>
47
+
48
+ <div id="dialog2" style="display:none;">
49
+ <input class="inarea" type="text" name="search_str2" id="search_str2">
50
+ </div>
51
+ <table>
52
+ <tr>
53
+ <td class="long"><input class="inarea" type="text" id="upDir" name="upDir"></td>
54
+ <td><input type="button" id="select_dir" value="フォルダ選択" /></td>
29
55
  </tr>
30
56
  </table>
31
- <input class="inarea" type="text" value="ファイル名を入力" name="search_str" id="search_str">
32
- <input class="inarea" type="file" id="upFile" name="upFile" value="upFile"><br>
33
- <input type="button" value="確認" onclick="dispFile()">
34
57
 
35
- <textarea name="log" id="log" class="outarea"></textarea><br/>
58
+ <div class="outarea">
59
+ <ul name="log" id="log" class="log">
60
+ </ul>
61
+ </div>
36
62
 
37
63
  </body>
38
64
 
@@ -1,6 +1,30 @@
1
1
  // main.js
2
2
 
3
3
  var $ws = null;
4
+ var $auto_scroll = true;
5
+ var dialog = null;
6
+
7
+ function open_dialog(msg) {
8
+ var top = window.screenTop + 10;
9
+ var left = window.screenLeft + 10;
10
+ if (dialog != null) {
11
+ dialog.close();
12
+ }
13
+ var dialog = window.open(
14
+ "/open_dialog?msg=" + msg,
15
+ "pop",
16
+ "width=300, height=100, left=" + left + ", top=" + top
17
+ );
18
+ console.log("open dialog dialog=" + dialog);
19
+ if (dialog == null) {
20
+ console.log("open dialog retry");
21
+ setTimeout(function () {
22
+ open_dialog(msg);
23
+ }, 1000);
24
+ } else {
25
+ dialog.focus();
26
+ }
27
+ }
4
28
 
5
29
  function server_connect(url) {
6
30
  var ws = new WebSocket(url);
@@ -10,21 +34,23 @@ function server_connect(url) {
10
34
  };
11
35
  ws.onmessage = function (evt) {
12
36
  //alert(evt.data);
37
+
13
38
  if (evt.data.match(/^startup:/)) {
14
39
  file_name = evt.data.replace(/^startup:/, "");
15
40
  //alert(file_name);
16
- var fs = new ActiveXObject("Scripting.FileSystemObject");
17
- var file = fs.CreateTextFile(file_name);
18
- file.Close();
41
+ }
42
+ else if (evt.data.match(/^app_end:normal/)) {
43
+ open_dialog("終了しました");
44
+ }
45
+ else if (evt.data.match(/^app_end:error/)) {
46
+ open_dialog("<font color='red'>エラーが発生しました</font>");
19
47
  } else {
20
- var log = $('#log').val() + evt.data + "\n";
21
- $('#log').val(log);
22
- var psconsole = $('#log');
23
- psconsole.scrollTop(
24
- psconsole[0].scrollHeight - psconsole.height()
25
- );
48
+ var log = "<li>" + evt.data + "</li>";
49
+ $('#log').append(log);
50
+ if ($auto_scroll) {
51
+ $('.outarea').scrollTop($('.outarea').get(0).scrollHeight);
52
+ }
26
53
  }
27
-
28
54
  };
29
55
  ws.onclose = function () {
30
56
  alert("アプリケーションが終了しました!!");
@@ -41,11 +67,20 @@ function send_message(msg) {
41
67
  }
42
68
  }
43
69
 
44
- function autocomp(id, url) {
70
+ function autocomp(id, file_kind) {
45
71
  $("#" + id).autocomplete({
72
+ autoFocus: true,
73
+ minLength: 0,
74
+ delay: 0,
75
+ select: function (event, ui) {
76
+ //console.log(ui.item.value);
77
+ jQuery("#" + id).val(ui.item.value);
78
+ //jQuery(this).autocomplete("search", "");
79
+ $(this).keydown();
80
+ },
46
81
  source: function (req, resp) {
47
82
  $.ajax({
48
- url: url(),
83
+ url: "http://localhost:54068/search?path=" + $("#" + id).val() + "&kind=" + file_kind,
49
84
  type: "GET",
50
85
  cache: false,
51
86
  dataType: "json",
@@ -61,6 +96,142 @@ function autocomp(id, url) {
61
96
  });
62
97
 
63
98
  }
99
+ }).focus(function () {
100
+ //jQuery(this).autocomplete("search", "");
101
+ $(this).keydown();
102
+ });
103
+ }
104
+
105
+ function select_file_dialog(search_id, file_kind, dialog_id, select_file, file_name) {
106
+ $("#" + select_file).click(function () {
107
+ autocomp(search_id, file_kind);
108
+ $(".ui-autocomplete").css("z-index", 1000);
109
+ $("#" + search_id).val("/");
110
+ $("#" + dialog_id).dialog({
111
+ modal: true
112
+ , show: "slide" //表示時のアニメーション
113
+ , hide: "explode" //閉じた時のアニメーション
114
+ , title: "Select File" //ダイアログのタイトル
115
+ , width: 580 //ダイアログの横幅
116
+ , height: 400 //ダイアログの高さ
117
+ , resizable: true //リサイズ可
118
+ , closeOnEscape: false //[ESC]キーで閉じられなくする
119
+ , draggable: true //ダイアログの移動を可に
120
+ , buttons: {
121
+ "OK": function () { //OKボタン
122
+ $("#" + file_name).val($("#" + search_id).val());
123
+ $(this).dialog("close");
124
+ $("#" + search_id).autocomplete("destroy");
125
+ },
126
+ "Cancel": function () { //Cancelボタン
127
+ $(this).dialog("close");
128
+ $("#" + search_id).autocomplete("destroy");
129
+ }
130
+ }
131
+ });
132
+ });
133
+ }
134
+
135
+ function setting_dialog(open_id, dialog_id, json_file) {
136
+ $("#" + open_id).click(function () {
137
+ $("#" + dialog_id).val = $(function () {
138
+ $("dl#wrap").empty();
139
+ $.getJSON(json_file, function (s) {
140
+ for (var i in s) {
141
+ if (s[i].type == "input") {
142
+ var h = "<table><tr>"
143
+ + "<td class='setting_name'>" + s[i].description + "</td>"
144
+ + "<td><input class='setting_value' type='text' " + "id=" + s[i].name + "_value " + "value=" + s[i].value + ">"
145
+ + "</td></tr></table>"
146
+ $("dl#wrap").append(h);
147
+ } else if (s[i].type == "checkbox") {
148
+ var h = "<table><tr>";
149
+ h += "<td class='setting_name'>" + s[i].description + "</td>";
150
+ if (s[i].value == true) {
151
+ h += "<td><input class='setting_checkbox' type='checkbox' " + "id=" + s[i].name + "_value checked ></td>";
152
+ } else {
153
+ h += "<td><input class='setting_checkbox' type='checkbox' " + "id=" + s[i].name + "_value ></td>";
154
+ }
155
+ h += "</tr></table>";
156
+ $("dl#wrap").append(h);
157
+ } else if (s[i].type == "select") {
158
+ var h = "<table><tr>";
159
+ h += "<td class='setting_name'>" + s[i].description + "</td>";
160
+ h += "<td> <select class='setting_value' id=" + s[i].name + "_value " + ">";
161
+ s[i].select.forEach(e => {
162
+ if (e == s[i].value) {
163
+ h += "<option value=" + e + " selected >" + e + "</option>";
164
+ } else {
165
+ h += "<option value=" + e + ">" + e + "</option>";
166
+ }
167
+ });
168
+ h += "</select></td>";
169
+ h += "</tr></table>";
170
+ $("dl#wrap").append(h);
171
+ } else {
172
+ //console.log("type=" + s[i].type);
173
+ }
174
+ }
175
+ });
176
+ });
177
+ $("#" + dialog_id).dialog({
178
+ modal: true
179
+ , show: "slide" //表示時のアニメーション
180
+ , hide: "explode" //閉じた時のアニメーション
181
+ , title: "Setting" //ダイアログのタイトル
182
+ , width: 580 //ダイアログの横幅
183
+ , height: 400 //ダイアログの高さ
184
+ , resizable: true //リサイズ可
185
+ , closeOnEscape: false //[ESC]キーで閉じられなくする
186
+ , draggable: true //ダイアログの移動を可に
187
+ , buttons: {
188
+ "OK": function () { //OKボタン
189
+ var json_data = []
190
+ $.getJSON(json_file, function (s) {
191
+ for (var i in s) {
192
+ //console.log(s[i].name);
193
+ if (s[i].type == "input") {
194
+ var data = {};
195
+ data["name"] = s[i].name;
196
+ data["value"] = $("#" + s[i].name + "_value").val();
197
+ data["type"] = s[i].type;
198
+ data["select"] = s[i].select;
199
+ data["description"] = s[i].description;
200
+ json_data.push(data);
201
+ }
202
+ else if (s[i].type == "checkbox") {
203
+ var data = {};
204
+ data["name"] = s[i].name;
205
+ if ($("#" + s[i].name + "_value:checked").val() == "on") {
206
+ data["value"] = true;
207
+ } else {
208
+ data["value"] = false;
209
+ }
210
+ data["type"] = s[i].type;
211
+ data["select"] = s[i].select;
212
+ data["description"] = s[i].description;
213
+ json_data.push(data);
214
+ } else if (s[i].type == "select") {
215
+ var data = {};
216
+ data["name"] = s[i].name;
217
+ data["value"] = $("#" + s[i].name + "_value" + " option:selected").val();
218
+ data["type"] = s[i].type;
219
+ data["select"] = s[i].select;
220
+ data["description"] = s[i].description;
221
+ json_data.push(data);
222
+ } else {
223
+ //console.log("type=" + s[i].type);
224
+ }
225
+ }
226
+ $ws.send("setting:" + JSON.stringify(json_data));
227
+ });
228
+ $(this).dialog("close");
229
+ },
230
+ "Cancel": function () { //Cancelボタン
231
+ $(this).dialog("close");
232
+ }
233
+ }
234
+ });
64
235
  });
65
236
  }
66
237
 
@@ -72,58 +243,62 @@ function get_dirname(path) {
72
243
  return result.replace(/\//g, "\\");
73
244
  }
74
245
 
75
- function select_file(id) {
76
- var file = $("#" + id).val();
77
- var dir = get_dirname(file);
78
- if (dir != "") {
79
- dir = dir + "\\*.*";
80
- } else {
81
- dir = "c:\\*.*";
82
- }
83
- var path = "";
84
- //alert(dir);
85
- //path = HtmlDlgHelper.openfiledlg(dir,"*.db","database(*.db)|*.db|all(*.*)|*.*|Text file(*.txt)|*.txt|");
86
- path = HtmlDlgHelper.openfiledlg(dir, "", "all(*.*)|*.*|Text file(*.txt)|*.txt|");
87
- $("#" + id).val(path);
88
- return (path);
89
- }
90
-
91
246
  function dispFile() {
92
247
  var fName = $("#upFile").val();
93
248
  alert('選択したファイルの値は' + fName + 'です');
94
249
  }
95
250
 
251
+ function openFile(file) {
252
+ $ws.send("openfile:" + file);
253
+ }
254
+
96
255
  // 起動時の処理
97
256
  $(document).ready(function () {
98
257
  // サーバに接続
99
- server_connect("ws://localhost:61820/wsserver")
258
+ server_connect("ws://localhost:54068/wsserver")
100
259
  // ウインドウサイズ
101
- var width = 600;
102
- var height = 700;
260
+ var width = 800;
261
+ var height = 600;
262
+ $(window).resize(function() {
263
+ $(".outarea").height( $(window).height() - 250 );
264
+ });
103
265
  // ウインドウの位置
104
266
  $(function () {
105
267
  window.resizeTo(width, height);
106
268
  window.moveTo((window.screen.width / 2) - (width / 2), (screen.height / 2) - (height / 2));
107
269
  //window.moveTo(0,0);
270
+ $(".outarea").height( $(window).height() - 250 );
108
271
  });
109
272
 
110
- // オートコンプリート設定
111
- var getUrl = function () {
112
- var url = "http://localhost:61820/search?path=" + $("#search_str").val();
113
- return url;
114
- };
115
- autocomp("search_str", getUrl);
273
+ $('.outarea').scroll(function () {
274
+ var h = $('.outarea').get(0).scrollHeight - $('.outarea').innerHeight();
275
+ //console.log("scrollEnd=" + Math.abs($('.outarea').scrollTop() - h));
276
+ if (Math.abs($('.outarea').scrollTop() - h) < 30) {
277
+ // 最後までスクロールしている
278
+ // 自動スクロールON
279
+ $auto_scroll = true;
280
+ } else {
281
+ // 自動スクロールOFF
282
+ $auto_scroll = false;
283
+ }
284
+ //console.log("auto_scroll=" + $auto_scroll);
285
+ });
116
286
 
117
287
  // ハンドラ登録
118
- $("#file").click(function () {
119
- select_file("search_str");
288
+ $("#stop").click(function () {
289
+ send_message("stop");
120
290
  });
291
+
121
292
  $("#exec").click(function () {
293
+ $('#log').empty();
122
294
  send_message("exec:" + $("#upFile").val());
123
295
  });
124
- $("#stop").click(function () {
125
- send_message("stop");
126
- });
296
+
297
+ select_file_dialog("search_str", "file", "dialog1", "select_file", "upFile");
298
+
299
+ select_file_dialog("search_str2", "dir", "dialog2", "select_dir", "upDir");
300
+
301
+ setting_dialog("setting", "setting_dialog", "config/setting.json");
127
302
 
128
303
  });
129
304
 
@@ -1,15 +1,18 @@
1
1
  # -*- coding: utf-8 -*-
2
- class AppMain
3
- def initialize
4
- @aboet = false
5
- end
2
+ require "server_app_base.rb"
6
3
 
7
- def start(file)
4
+ class MyApp < AppMainBase
5
+ def start(argv)
6
+ super
8
7
  begin
9
8
  @abort = false
10
- puts file
9
+ puts argv
10
+ argv.each do |v|
11
+ yield v if block_given?
12
+ end
11
13
  while true
12
14
  yield Time.now.to_s if block_given?
15
+ yield @config["name1"]
13
16
  sleep 1
14
17
  break if @abort
15
18
  end
@@ -20,6 +23,6 @@ class AppMain
20
23
  end
21
24
 
22
25
  def stop()
23
- @abort = true
26
+ super
24
27
  end
25
28
  end
@@ -1,9 +1,9 @@
1
- require 'json'
2
- require 'kconv'
1
+ require "json"
2
+ require "kconv"
3
3
 
4
4
  class Search < Sinatra::Base
5
5
  helpers Sinatra::Streaming
6
- get '' do
6
+ get "" do
7
7
  q_hash = {}
8
8
  puts request.query_string
9
9
  request.query_string.split("&").each do |q|
@@ -14,27 +14,45 @@ class Search < Sinatra::Base
14
14
  q_hash[work[0]] = ""
15
15
  end
16
16
  end
17
- str = q_hash["path"].gsub(/\\/,"/")
17
+ str = q_hash["path"].gsub(/\\/, "/")
18
18
  puts "str=#{str}"
19
+ kind = q_hash["kind"].gsub(/\\/, "/")
20
+ puts "kind=#{kind}"
19
21
  res = []
20
22
  str = str.gsub(/\\/, "/")
21
23
  dir = File.dirname(str)
22
- dir = "c:/" if dir == nil
23
24
  file = File.basename(str)
24
- file = "/" if file == nil
25
+ puts "dir=#{dir}"
26
+ puts "file=#{file}"
27
+
28
+ kernel = Facter.value(:kernel)
29
+ if kernel == "windows"
30
+ dir = "c:/" if dir == nil
31
+ dir = "c:/" if dir == "/"
32
+ elsif kernel == "Linux"
33
+ dir = "/" if dir == nil
34
+ else
35
+ dir = "c:/" if dir == nil
36
+ dir = "c:/" if dir == "/"
37
+ end
38
+
25
39
  path = "#{dir}/#{file}"
26
- if File.exists?(path)
40
+ if File.directory?(path)
27
41
  path = path + "/*"
28
42
  else
29
43
  path = path + "*"
30
44
  end
45
+ path.gsub!(/[\/]+/, "/")
31
46
  puts path
32
- Dir.glob(path).each do |file|
47
+ Dir.glob(path, File::FNM_DOTMATCH).each do |file|
33
48
  data = {}
49
+ next if File.basename(file) == "."
50
+ next if kind == "dir" and !File.directory?(file)
34
51
  data["label"] = File.basename(file)
35
- data["value"] = file
52
+ data["label"] += "/" if (File.directory?(file))
53
+ data["value"] = File.expand_path(file)
36
54
  res.push data
37
55
  end
38
- JSON.generate res
56
+ JSON.generate res.sort { |a, b| a["value"] <=> b["value"] }
39
57
  end
40
58
  end
@@ -0,0 +1,32 @@
1
+ # -*- coding: utf-8 -*-
2
+ class AppMainBase
3
+ def initialize
4
+ @config = nil
5
+ @aboet = false
6
+ @exec = false
7
+ @suspend = false
8
+ end
9
+
10
+ def set_config(config)
11
+ @config = config
12
+ end
13
+
14
+ def start(argv)
15
+ @exec = true
16
+ end
17
+
18
+ def stop()
19
+ @abort = true
20
+ @exec = false
21
+ end
22
+
23
+ def suspend()
24
+ @suspend = true
25
+ end
26
+
27
+ def resume()
28
+ @suspend = false
29
+ end
30
+ end
31
+
32
+ require "app_load.rb"
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env ruby
1
2
  # -*- coding: utf-8 -*-
2
3
  $LOAD_PATH << File.dirname(File.expand_path(__FILE__))
3
4
 
@@ -22,19 +23,19 @@ port = get_unused_port
22
23
  puts "port=#{port}"
23
24
 
24
25
  # config.ruの編集
25
- buf = File.read("config.ru").toutf8
26
+ buf = File.binread("config.ru").toutf8
26
27
  buf.gsub!(/port [0-9]+/, "port #{port}")
27
- File.write("config.ru", buf)
28
+ File.binwrite("config.ru", buf)
28
29
 
29
30
  # main.jsの編集
30
- buf = File.read("js/main.js").toutf8
31
+ buf = File.binread("js/main.js").toutf8
31
32
  buf.gsub!(/localhost:[0-9]+\//, "localhost:#{port}/")
32
- File.write("js/main.js", buf)
33
+ File.binwrite("js/main.js", buf)
33
34
 
34
35
  # index.htaの編集
35
- buf = File.read("index.html").toutf8
36
+ buf = File.binread("index.html").toutf8
36
37
  buf.gsub!(/localhost:[0-9]+\//, "localhost:#{port}/")
37
- File.write("index.html", buf)
38
+ File.binwrite("index.html", buf)
38
39
 
39
40
  Thread.start {
40
41
  puts "start browser"
@@ -49,7 +50,6 @@ Thread.start {
49
50
  else
50
51
  browser = json["chrome_win"]
51
52
  end
52
- #browser = "\"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe\" -app=http://localhost:#{port}"
53
53
  browser += " -app=http://localhost:#{port}"
54
54
  puts browser
55
55
  system browser
@@ -1,8 +1,19 @@
1
- require "./server_app"
2
- $app = AppMain.new
1
+ require "./server_app_base"
2
+ require "json"
3
+ require "cgi"
4
+
5
+ def config_json_hash(json)
6
+ config = {}
7
+ json.each do |j|
8
+ config[j["name"]] = j["value"]
9
+ end
10
+ return config
11
+ end
3
12
 
4
13
  class WsServer < Sinatra::Base
5
14
  $ws_list = []
15
+ json_config = nil
16
+ exec_thread = nil
6
17
  get "" do
7
18
  if !request.websocket?
8
19
  "no supported"
@@ -15,16 +26,63 @@ class WsServer < Sinatra::Base
15
26
  ws.onmessage do |msg|
16
27
  puts msg
17
28
  if msg =~ /^exec:/
18
- fname = msg.gsub(/^exec:/, "")
19
- Thread.new {
20
- $app.start fname do |out|
21
- ws.send(out)
22
- end
23
- }
29
+ if exec_thread == nil
30
+ json = JSON.parse(File.read("config/setting.json"))
31
+ json_config = config_json_hash(json)
32
+ $app.set_config(json_config)
33
+ argv = msg.gsub(/^exec:/, "")
34
+ exec_thread = Thread.new {
35
+ begin
36
+ $app.start(argv.split(",")) do |out|
37
+ ws.send(out)
38
+ end
39
+ ws.send("app_end:normal")
40
+ rescue
41
+ puts $!
42
+ puts $@
43
+ puts "app_end:err"
44
+ ws.send("app_end:error")
45
+ ensure
46
+ puts "exit thread"
47
+ exec_thread = nil
48
+ end
49
+ }
50
+ else
51
+ puts "app_end:err"
52
+ ws.send("app_end:error")
53
+ end
24
54
  end
25
55
  if msg =~ /^stop/
26
- $app.stop
56
+ if exec_thread
57
+ $app.stop
58
+ end
59
+ end
60
+ if msg =~ /^suspend/
61
+ if exec_thread
62
+ $app.suspend
63
+ end
27
64
  end
65
+ if msg =~ /^resume/
66
+ if exec_thread
67
+ $app.resume
68
+ end
69
+ end
70
+ if msg =~ /^setting:/
71
+ json_string = msg.gsub(/^setting:/, "")
72
+ json = JSON.parse(json_string)
73
+ File.open("config/setting.json", "w") do |w|
74
+ w.puts JSON.pretty_generate(json)
75
+ end
76
+ json_config = config_json_hash(json)
77
+ $app.set_config(json_config)
78
+ end
79
+ if msg =~ /^openfile:/
80
+ file = msg.gsub(/^openfile:/, "")
81
+ Thread.new {
82
+ system "#{json_config["editor"]} #{CGI.unescapeHTML(file)}"
83
+ }
84
+ end
85
+
28
86
  if msg == "exit"
29
87
  unless ENV["OCRA"] == "true"
30
88
  halt
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: browser_app_base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - masataka kuwayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-15 00:00:00.000000000 Z
11
+ date: 2021-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -104,6 +104,7 @@ extra_rdoc_files: []
104
104
  files:
105
105
  - ".gitignore"
106
106
  - ".rspec"
107
+ - ".vscode/launch.json"
107
108
  - Gemfile
108
109
  - LICENSE.txt
109
110
  - README.md
@@ -112,13 +113,16 @@ files:
112
113
  - browser_app_base.gemspec
113
114
  - lib/browser_app_base.rb
114
115
  - lib/browser_app_base/version.rb
116
+ - lib/template/app_load.rb
115
117
  - lib/template/config.ru
116
118
  - lib/template/config/browser.json
119
+ - lib/template/config/setting.json
117
120
  - lib/template/css/index.css
118
121
  - lib/template/index.html
119
122
  - lib/template/js/main.js
123
+ - lib/template/my_app_sample.rb
120
124
  - lib/template/server.rb
121
- - lib/template/server_app.rb
125
+ - lib/template/server_app_base.rb
122
126
  - lib/template/start.rb
123
127
  - lib/template/wsserver.rb
124
128
  homepage: https://github.com/kuwayama1971/BrowserAppBase