narou 2.8.3 → 2.8.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of narou might be problematic. Click here for more details.

@@ -184,28 +184,21 @@ var Narou = (function() {
184
184
  });
185
185
  },
186
186
 
187
- on: function(event, block, once) {
187
+ on: function(event, block) {
188
188
  if (typeof block !== "function") {
189
189
  $.error("need a function");
190
190
  }
191
191
  var stack = this.events[event] || [];
192
- stack.push([block, once]);
192
+ stack.push(block);
193
193
  this.events[event] = stack;
194
194
  },
195
195
 
196
- one: function(event, block) {
197
- this.on(event, block, true);
198
- },
199
-
200
196
  trigger: function(event, data) {
201
197
  var self = this;
202
198
  var stack = this.events[event] || [];
203
- this.events[event] =
204
- _.reject(stack, function(pair) {
205
- var block = pair[0], once = pair[1];
206
- block.call(self, data);
207
- return once;
208
- });
199
+ $.each(stack, function() {
200
+ this.call(self, data);
201
+ });
209
202
  },
210
203
 
211
204
  send: function(json) {
@@ -231,7 +224,7 @@ var Narou = (function() {
231
224
  this.target_id = target_id;
232
225
  if (!this.closed) {
233
226
  // メニューを開いた状態で直接ボタンを押した場合に一旦閉じるイベントを起こさせる
234
- this.close();
227
+ $(document).trigger("click");
235
228
  }
236
229
  this.closed = false;
237
230
  var caller = function() {
@@ -248,10 +241,6 @@ var Narou = (function() {
248
241
  });
249
242
  },
250
243
 
251
- close: function() {
252
- $(document).trigger("click");
253
- },
254
-
255
244
  openConsoleDialog: function(callback) {
256
245
  if (typeof callback !== "function") return;
257
246
  var $console_dialog = $("#console-dialog");
@@ -314,18 +303,12 @@ var Narou = (function() {
314
303
  var self = this;
315
304
  $("#context-menu-setting").on("click", function(e) {
316
305
  e.preventDefault();
317
- var setting_page_path = "/novels/" + self.target_id + "/setting";
318
- if (storage.get("open_new_tab_setting_pages")) {
319
- window.open(setting_page_path);
320
- }
321
- else {
322
- location.href = setting_page_path;
323
- }
306
+ location.href = "/novels/" + self.target_id + "/setting";
324
307
  });
325
308
  $("#context-menu-update").on("click", function(e) {
326
309
  e.preventDefault();
327
310
  self.openConsoleDialog(function() {
328
- self.action.updateForce(self.target_id);
311
+ self.action.update(self.target_id);
329
312
  });
330
313
  });
331
314
  $("#context-menu-send").on("click", function(e) {
@@ -474,10 +457,10 @@ var Narou = (function() {
474
457
 
475
458
  updateGeneralLastup: function() {
476
459
  bootbox.dialog({
477
- title: "最新話掲載日の更新",
478
- message: "凍結済みを除く各小説の最新話掲載日のみを更新して反映させます。<br>" +
479
- "最新話掲載日は通常時のUpdateでも更新されるので、手動で更新する必要は基本的にはありません。<br>" +
480
- "掲載日だけを調べて、選択的にUpdateをかけるなど、用途を理解した上で小説サイトのサーバーに負荷をかけない範囲でご利用下さい。",
460
+ title: '最新話掲載日の更新',
461
+ message: "凍結済みを除く各小説の最新話掲載日を更新します。<br>" +
462
+ "最新話掲載日は通常時のUPDATEでも更新されるので、手動で更新する必要は基本的にはありません。<br>" +
463
+ "掲載日だけを調べて、選択的にUPDATEをかけるなど、用途を理解した上で小説サイトのサーバーに負荷をかけない範囲でご利用下さい。",
481
464
  backdrop: true,
482
465
  buttons: {
483
466
  cancel: {
@@ -623,70 +606,6 @@ var Narou = (function() {
623
606
  });
624
607
  });
625
608
  },
626
-
627
- rebootDialog: function() {
628
- var self = this;
629
- bootbox.dialog({
630
- title: '<span class="glyphicon glyphicon-refresh"></span> 再起動',
631
- message: "<p>Narou.rb WEB UI サーバを再起動します。<br>" +
632
- "バージョンを更新してある場合は最新バージョンで立ち上がります。</p>" +
633
- "<p class=text-danger>アップデート中や変換中の小説がある場合は中断されます。<br>" +
634
- "終わったかどうか確認しましょう。</p>",
635
- backdrop: true,
636
- buttons: {
637
- danger: {
638
- label: "再起動",
639
- className: "btn-danger",
640
- callback: function() {
641
- self.reboot();
642
- }
643
- },
644
- main: {
645
- label: "キャンセル",
646
- className: "btn-default",
647
- }
648
- }
649
- });
650
- },
651
-
652
- reboot: function() {
653
- $.post("/reboot", function(data) {
654
- bootbox.hideAll();
655
- bootbox.dialog({
656
- title: "",
657
- closeButton: false,
658
- message: data
659
- });
660
- });
661
- },
662
-
663
- checkUpdatedSystem: function(funcs) {
664
- $.post("/check_already_update_system", function(data) {
665
- if (data.result) {
666
- $.post("/gem_update_last_log", function(log) {
667
- funcs.already_updated(log);
668
- });
669
- }
670
- else {
671
- funcs.not_updated();
672
- }
673
- });
674
- },
675
-
676
- updateSystem: function(callback) {
677
- var notification = Notification.instance();
678
- notification.one("server.update.success", function(log) {
679
- callback("success", log);
680
- });
681
- notification.one("server.update.nothing", function(log) {
682
- callback("nothing", log);
683
- });
684
- notification.one("server.update.failure", function(log) {
685
- callback("failure", log);
686
- });
687
- $.post("/update_system");
688
- },
689
-
690
609
  });
691
610
 
692
611
  /*************************************************************************
@@ -9,8 +9,6 @@ $(document).ready(function() {
9
9
  var touchable_device = "ontouchstart" in window;
10
10
  var click_event_name = (touchable_device ? "touchstart" : "click");
11
11
 
12
- var datatables_init_completed = false;
13
-
14
12
  // MEMO: table 全てに対して操作
15
13
  // table.$("tr.selected").removeClass("selected");
16
14
  // MEMO: .selected が付いている行を全て取得
@@ -22,13 +20,13 @@ $(document).ready(function() {
22
20
  {
23
21
  id: false, last_update: false, title: true, author: false, sitename: false,
24
22
  toc_url: false, novel_type: false, tags: false, status: false, menu: true,
25
- download: true, folder: false, update_button: false, general_lastup: false,
23
+ download: true, folder: false, general_lastup: false,
26
24
  }
27
25
  // PC
28
26
  : {
29
27
  id: true, last_update: true, title: true, author: true, sitename: true,
30
28
  toc_url: true, novel_type: true, tags: true, status: true, menu: true,
31
- download: true, folder: true, update_button: true, general_lastup: true,
29
+ download: true, folder: true, general_lastup: true,
32
30
  });
33
31
 
34
32
  $.fn.dataTable.Api.register("fireChangeSelect()", function() {
@@ -75,7 +73,10 @@ $(document).ready(function() {
75
73
 
76
74
  // initComplete や ajax.reload した時に再設定するために呼ばれる
77
75
  function resettingTableState() {
78
- refreshTooltop(table.$("[data-toggle=tooltip]"), null, "top");
76
+ table.$("[data-toggle=tooltip]").tooltip({
77
+ animation: false,
78
+ container: "body",
79
+ });
79
80
  // バッジを更新しておく(.selectedの復元が終わってから呼ぶ)
80
81
  table.fireChangeSelect();
81
82
  // タグのイベントを反映
@@ -84,23 +85,6 @@ $(document).ready(function() {
84
85
  table.draw(false);
85
86
  }
86
87
 
87
- function openContextMenuWithTr(tr, event) {
88
- var $tr = $(tr);
89
- var target_id = table.row(tr).data().id;
90
- var $cover = $("<div class=context-menu-target-cover>");
91
- // MEMO: IEだと要素を追加してから座標を指定しないと反映されない
92
- $("body").append($cover);
93
- $cover.offset($tr.offset()).width($tr.width()).height($tr.height());
94
- $cover.one("contextmenu", function(e) {
95
- e.preventDefault();
96
- $cover.remove();
97
- context_menu.close();
98
- });
99
- context_menu.open(target_id, get_event_position(event), function() {
100
- $cover.remove();
101
- });
102
- }
103
-
104
88
  var table = t = $("#novel-list").DataTable({
105
89
  ajax: "/api/list",
106
90
  dom: (touchable_device ? 'lprtpi' : 'Rlprtpi'),
@@ -137,7 +121,7 @@ $(document).ready(function() {
137
121
  display = "<span class=" + klass + ">" + display + "</span>";
138
122
  }
139
123
  }
140
- return "<div>" + display + "</div>";
124
+ return display;
141
125
  }
142
126
  return data;
143
127
  }
@@ -161,7 +145,7 @@ $(document).ready(function() {
161
145
  klass = value[1];
162
146
  if (value[0] === -1 || diff_time <= value[0]) break;
163
147
  }
164
- return '<div><span class="general-lastup ' + klass + '">' + display + '</span></div>';
148
+ return '<span class="general-lastup ' + klass + '">' + display + '</span>';
165
149
  }
166
150
  else if (type === "sort") {
167
151
  return data * 10000 + (row.id | 0);
@@ -217,36 +201,27 @@ $(document).ready(function() {
217
201
  },
218
202
  render: function() {}
219
203
  },
220
- {
221
- title: "更新",
222
- data: "update_button", className: "text-center", orderable: false,
223
- searchable: false, visible: cell_visible.update_button,
224
- defaultContent: '<button class="btn btn-default btn-xs">' +
225
- '<span class="glyphicon glyphicon-refresh"></span></button>',
226
- createdCell: function(td, cellData, rowData, rowIndex, colIndex) {
227
- $(td).children("button")
228
- .data("targetId", rowData.id)
229
- .on("click", function(e) {
230
- e.stopPropagation();
231
- var $this = $(this);
232
- var target_id = $this.data("targetId");
233
- action.updateForce(target_id);
234
- });
235
- },
236
- render: function() {}
237
- },
238
204
  {
239
205
  title: "個別",
240
206
  data: "menu", className: "text-center",
241
207
  defaultContent: '<button class="btn btn-default btn-xs">' +
242
- '<span class="glyphicon glyphicon-option-horizontal"></span></button>',
208
+ '<span class="glyphicon glyphicon-cog"></span></button>',
243
209
  visible: cell_visible.menu,
244
210
  createdCell: function(td, cellData, rowData, rowIndex, colIndex) {
245
211
  $(td).children("button")
246
212
  .data("targetId", rowData.id)
247
213
  .on("click", function(e) {
248
214
  e.stopPropagation();
249
- openContextMenuWithTr($(e.target).closest("tr"), e);
215
+ var $this = $(this);
216
+ var $tr = $(e.target).closest("tr");
217
+ var target_id = $this.data("targetId");
218
+ var $cover = $("<div class=context-menu-target-cover>");
219
+ // MEMO: IEだと要素を追加してから座標を指定しないと反映されない
220
+ $("body").append($cover);
221
+ $cover.offset($tr.offset()).width($tr.width()).height($tr.height());
222
+ context_menu.open(target_id, get_event_position(e), function() {
223
+ $cover.remove();
224
+ });
250
225
  });
251
226
  },
252
227
  render: function() {},
@@ -300,8 +275,6 @@ $(document).ready(function() {
300
275
  resettingTableState();
301
276
 
302
277
  table.draw(false);
303
-
304
- datatables_init_completed = true;
305
278
  },
306
279
  language: {
307
280
  //lengthMenu: "_MENU_ 件分表示 <span id='icon-refresh-table' class='glyphicon glyphicon-repeat'></span>",
@@ -325,23 +298,7 @@ $(document).ready(function() {
325
298
  * Extensions section
326
299
  */
327
300
  colReorder: {
328
- realtime: false,
329
-
330
- // colReorder でカラムの順番が入れ替えられた場合、createdCell 内で
331
- // 設定している内容が全てリセットされてしまいイベント等が消えてしまうので、
332
- // ここで一旦リロードしてイベントが再設定されるようにする。
333
- // これは createdCell が初期化時に一度しか呼ばれないためで、dataTables の
334
- // 今後のバージョンアップで予定されている updatedCell が実装されるまでの
335
- // 暫定処置として reorderCallback で代用する。
336
- // https://github.com/DataTables/ColReorder/issues/49
337
- reorderCallback: function() {
338
- // stateSave が有効な状態でカラムが入れ替えられていた場合、
339
- // initComplete イベントが発火する前に一度この reorderCallback が発火されるので、
340
- // 無駄なリロードをしないように初期化後のみ有効にする
341
- if (datatables_init_completed) {
342
- notification.trigger("table.reload");
343
- }
344
- },
301
+ "realtime": false
345
302
  },
346
303
  });
347
304
 
@@ -368,24 +325,20 @@ $(document).ready(function() {
368
325
  }
369
326
  });
370
327
 
371
- function restoreVisibilityForViewMenu() {
328
+ function restoreVisibilityForFrozen() {
372
329
  visibility_frozen_novel = storage.get("visibility_frozen_novel");
373
330
  visibility_nonfrozen_novel = storage.get("visibility_nonfrozen_novel");
374
- var visibility_open_new_tab = storage.get("open_new_tab_setting_pages");
375
331
  if (typeof visibility_frozen_novel === "undefined")
376
332
  visibility_frozen_novel = true;
377
333
  if (typeof visibility_nonfrozen_novel === "undefined")
378
334
  visibility_nonfrozen_novel = true;
379
- if (typeof visibility_open_new_tab === "undefined")
380
- visibility_open_new_tab = false;
381
335
  // メニューのチェック状態も復元
382
336
  var method = ["removeClass", "addClass"];
383
337
  $("#action-view-frozen")[method[visibility_frozen_novel | 0]]("active");
384
338
  $("#action-view-nonfrozen")[method[visibility_nonfrozen_novel | 0]]("active");
385
- $("#action-view-toggle-setting-page-open-new-tab")[method[visibility_open_new_tab | 0]]("active");
386
339
  }
387
340
 
388
- restoreVisibilityForViewMenu();
341
+ restoreVisibilityForFrozen();
389
342
 
390
343
  function saveVisibilityFrozen() {
391
344
  storage.set("visibility_frozen_novel", visibility_frozen_novel);
@@ -394,11 +347,11 @@ $(document).ready(function() {
394
347
  }
395
348
 
396
349
  function toggleVisibilityFrozen() {
397
- visibility_frozen_novel = !visibility_frozen_novel;
350
+ visibility_frozen_novel = visibility_frozen_novel ? false : true;
398
351
  }
399
352
 
400
353
  function toggleVisibilityNonFrozen() {
401
- visibility_nonfrozen_novel = !visibility_nonfrozen_novel;
354
+ visibility_nonfrozen_novel = visibility_nonfrozen_novel ? false : true;
402
355
  }
403
356
 
404
357
  /*
@@ -424,13 +377,6 @@ $(document).ready(function() {
424
377
  }, false);
425
378
  });
426
379
 
427
- /*
428
- * サーバ再起動イベント定義
429
- */
430
- notification.on("server.rebooted", function() {
431
- location.href = "/";
432
- });
433
-
434
380
  notification.on("tag.updateCanvas", function() {
435
381
  tag.updateCanvas();
436
382
  });
@@ -543,21 +489,6 @@ $(document).ready(function() {
543
489
  $("#action-select-mode-rect").addClass("disabled");
544
490
  }
545
491
  else {
546
- // 小説一覧テーブル内で右クリックしたら個別メニューを表示
547
- $("#novel-list tbody").on("contextmenu", function(e) {
548
- var target_tag_name = e.target.tagName.toLowerCase();
549
- // ボタンとかリンクはブラウザの右クリックメニューをそのまま使いたい
550
- if (target_tag_name === "button" || target_tag_name === "a" ||
551
- $(e.target).parent("button, a")[0])
552
- return;
553
-
554
- e.preventDefault(); // ブラウザの右クリックメニューを抑制
555
- e.stopPropagation();
556
- var mousedowned_element = $.elementFromPoint(get_event_position(e));
557
- var tr = mousedowned_element.parents("tr");
558
- openContextMenuWithTr(tr, e);
559
- });
560
-
561
492
  var initMode = function(mode) {
562
493
  if (select_mode != mode) {
563
494
  $("#action-select-mode-" + mode).addClass("active");
@@ -694,11 +625,6 @@ $(document).ready(function() {
694
625
  var mousedowned_element = $.elementFromPoint(_pos);
695
626
  if (!mousedowned_element || mousedowned_element.closest("#novel-list tbody").length === 0)
696
627
  return;
697
-
698
- // 右クリックは無視(contextmenu イベント内で個別メニューを表示する)
699
- if (e.which == 3)
700
- return;
701
-
702
628
  e.preventDefault();
703
629
  e.stopPropagation();
704
630
  var self = this;
@@ -722,7 +648,6 @@ $(document).ready(function() {
722
648
  if (not_clicked_yet) {
723
649
  // 範囲選択開始
724
650
  $("#rect-select-menu").hide();
725
- context_menu.close();
726
651
  unregister_close_handler();
727
652
  not_clicked_yet = false;
728
653
  start_position = _pos;
@@ -855,19 +780,6 @@ $(document).ready(function() {
855
780
  table.draw();
856
781
  });
857
782
 
858
- /*
859
- * メニュー
860
- * 表示>変換設定ページは新規タブで開く
861
- */
862
- $("#action-view-toggle-setting-page-open-new-tab").on(click_event_name, function(e) {
863
- e.preventDefault();
864
- slideNavbar.slide();
865
- $(this).toggleClass("active");
866
- var open_new_tab = storage.get("open_new_tab_setting_pages");
867
- storage.set("open_new_tab_setting_pages", !open_new_tab);
868
- storage.save();
869
- });
870
-
871
783
  /*
872
784
  * メニュー
873
785
  * 表示>表示設定を全てリセット
@@ -980,16 +892,6 @@ $(document).ready(function() {
980
892
  });
981
893
  });
982
894
 
983
- /*
984
- * メニュー
985
- * オプション>サーバを再起動
986
- */
987
- $("#action-option-server-reboot").on(click_event_name, function(e) {
988
- e.preventDefault();
989
- slideNavbar.slide();
990
- action.rebootDialog();
991
- });
992
-
993
895
  /*
994
896
  * メニュー
995
897
  * オプション>サーバをシャットダウン
@@ -999,11 +901,10 @@ $(document).ready(function() {
999
901
  slideNavbar.slide();
1000
902
  bootbox.dialog({
1001
903
  title: '<span class="glyphicon glyphicon-off"></span> シャットダウン',
1002
- message: "<p>Narou.rb WEB UI サーバをシャットダウンします。<br>" +
1003
- "シャットダウンすると再度立ち上げるまではアクセスは出来なくなります。<br>" +
1004
- "再度立ち上げるにはコンソールでもう一度 <kbd>narou web</kbd> を実行して下さい。</p>" +
1005
- "<p class=text-danger>アップデート中や変換中の小説がある場合は中断されます。<br>" +
1006
- "終わったかどうか確認しましょう。</p>",
904
+ message: "Narou.rb WEB UI サーバをシャットダウンします。<br>" +
905
+ "シャットダウンすると再起動するまでアクセスは出来なくなります。<br>" +
906
+ "再起動するにはコンソールでもう一度 <kbd>narou web</kbd> を実行" +
907
+ "して下さい。",
1007
908
  backdrop: true,
1008
909
  buttons: {
1009
910
  danger: {
@@ -1023,23 +924,6 @@ $(document).ready(function() {
1023
924
  });
1024
925
  });
1025
926
 
1026
- var tooltip_opt = {
1027
- animation: false,
1028
- container: "body",
1029
- placement: "bottom"
1030
- }
1031
-
1032
- var refreshTooltop = function(id, title, placement) {
1033
- $(id)
1034
- .tooltip("destroy")
1035
- .tooltip(_.merge({}, tooltip_opt, { title: title, placement: placement }))
1036
- .on("shown.bs.tooltip", function(e) {
1037
- setTimeout(function() {
1038
- $(e.target).tooltip("hide");
1039
- }, 3500);
1040
- });
1041
- };
1042
-
1043
927
  /*
1044
928
  * 「選択」メニューの横に現在選択中の小説数をバッジで表示
1045
929
  */
@@ -1047,14 +931,23 @@ $(document).ready(function() {
1047
931
  table.on("changeselect", function() {
1048
932
  var selected_count = table.rows(".selected").data().length;
1049
933
  $("#badge-number-of-selecting").text(selected_count);
934
+ var tooltip_opt = {
935
+ animation: false,
936
+ container: "body",
937
+ placement: "bottom"
938
+ }
1050
939
  if (selected_count > 0) {
1051
- refreshTooltop("#button-update", "選択した小説を更新");
1052
- refreshTooltop("#button-send", "選択した小説を送信");
940
+ tooltip_opt.title = "選択した小説を更新";
941
+ $("#button-update").tooltip("destroy").tooltip(tooltip_opt);
942
+ tooltip_opt.title = "選択した小説を送信";
943
+ $("#button-send").tooltip("destroy").tooltip(tooltip_opt);
1053
944
  enable_menu_item(".enable-selected");
1054
945
  }
1055
946
  else {
1056
- refreshTooltop("#button-update", "すべての小説を更新");
1057
- refreshTooltop("#button-send", "更新された小説を送信");
947
+ tooltip_opt.title = "すべての小説を更新";
948
+ $("#button-update").tooltip("destroy").tooltip(tooltip_opt);
949
+ tooltip_opt.title = "更新された小説を送信";
950
+ $("#button-send").tooltip("destroy").tooltip(tooltip_opt);
1058
951
  disable_menu_item(".enable-selected");
1059
952
  }
1060
953
  });
@@ -1064,7 +957,17 @@ $(document).ready(function() {
1064
957
  /*
1065
958
  * Tooltip 化
1066
959
  */
1067
- refreshTooltop("[data-toggle=tooltip]");
960
+ $("[data-toggle=tooltip]").tooltip({
961
+ animation: false,
962
+ container: "body",
963
+ placement: "bottom",
964
+ });
965
+
966
+ $("#icon-refresh-table").tooltip({
967
+ title: "リストを再読み込み",
968
+ animation: false,
969
+ container: "body",
970
+ });
1068
971
 
1069
972
  $("button").on("mouseleave", function() {
1070
973
  $(this).tooltip("hide");
@@ -1284,9 +1187,6 @@ $(document).ready(function() {
1284
1187
  if ($("#rect-select-menu").is(":visible")) {
1285
1188
  close_rect_select_menu_handler();
1286
1189
  }
1287
- if (!context_menu.closed) {
1288
- context_menu.close();
1289
- }
1290
1190
  else {
1291
1191
  action.selectClear();
1292
1192
  }