您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
小説家になろうのヘッダーを便利にする
// ==UserScript== // @name Narrow_DynamicHeader // @namespace phodra // @description 小説家になろうのヘッダーを便利にする // @version 1.2 // @include http://ncode.syosetu.com/* // @include http://novelcom.syosetu.com/* // @include http://novel18.syosetu.com/* // @include http://novelcom18.syosetu.com/* // ==/UserScript== (function (){ // ユーザーID // 自分のIDを調べて書き換えてください。 // 通常版のユーザーIDは、ホーム画面の右上に以下のように表示されています。 // (ユーザー名)[ID:000000]でログイン中 // 18禁サイト用のユーザーIDは、Xホーム右側の // 「評価をつけた作品一覧」のURLから得ることが出来ます。 const MY_USER_ID = 0; const MY_XUSER_ID = 0; // ※そのまま移動させると元の場所が埋め立てられるので、 // ※クローンを作成したのちにオリジナルは visibility = hidden で隠す。 // ヘッダー(オリジナル) var $header_org = $("#novel_header"); // ヘッダー(クローン) var $header = $header_org.clone(true); $header.css( 'position', 'relative'); // オリジナルを隠す $header_org.css( 'visibility', 'hidden'); // header Height var headerH = $header.outerHeight(); // ヘッダーの親になるボックス var $box = $("<div id='box'>"); $box.css( 'position', 'fixed'); $box.append($header); // マウス検知エリア var $detect = $("<div id='detect_area' />"); $detect.css( { 'position': 'fixed', 'height': headerH, 'top': 0 } ); // ヘッダーボックスに乗せる、外す $detect.hover( function() { _boxon = true; if( scTop>0 ) HeaderShow(true); else _show = 2; }, function() { _boxon = false; if( scTop>0 ) HeaderHide( !_lockB && !_lockM ); else _show = 0; } ); $detect.append($box); $("body").append($detect); // 章タイトルとサブタイトルのラベル if( $(".margin_r20").size() ){ // コンテンツinfoのクローン var $info_org = $(".contents1"); var $info = $info_org.clone(true); $info_org.css( 'visibility', 'hidden'); $info.css( { 'left': 0, 'right': 0, 'margin': 'auto', 'opacity': '0.8' } ); var $label = $("<div />"); var $cp_title = $info.children(".chapter_title"); $cp_title.hide(); if( $cp_title.size() ) { var $cp_title2 = $("<span class='label_chapter' />"); $cp_title2.append($(".chapter_title").text()); $label.append($cp_title2); $label.append(" - "); } // サブタイトル用のエレメント var $label_sub = $("<span class='label_subtitle' />"); $label_sub.append($(".novel_subtitle").text()); $label.append($label_sub); $info.append($label); $box.append($info); } var boxheight = $box.height(); // 移動ボタン群 const NDH_BTN = 'ndh_button'; var move_a = "<a class='"+ NDH_BTN +"' />"; var move_div = "<div class='"+ NDH_BTN +"' />"; // 前ページ var bn_p = $("a:contains('<<')"); if( bn_p.size() ) { var $preEp = $(move_a); $preEp.text("<"); $preEp.attr( { 'alt': 'Prev Episode', 'href': bn_p.attr('href') } ); $preEp.css('left', '15px'); $header.append($preEp); } // 次ページ var bn_n = $("a:contains('>>')"); if( bn_n.size() ) { var $nxtEp = $(move_a); $nxtEp.text(">"); $nxtEp.attr( { 'alt': 'Next Episode', 'href': bn_n.attr('href') } ); $nxtEp.css( 'left', '55px'); $header.append($nxtEp); } $("#pageBottom").remove(); $("#pageTop").remove(); // 最上部へ移動 var $ptop = $(move_div); $ptop.attr( 'alt', 'Scroll Top'); $ptop.css( 'right', '55px'); $ptop.text("↑"); $ptop.click( function(e) { $("html,body").animate( { 'scroll-top': 0 }, 500 ); } ); $header.append($ptop); // 最下部へ移動 var $pbtm = $(move_div); $pbtm.text("↓"); $pbtm.attr( 'alt', 'Scroll Bottom'); $pbtm.css( 'right', '15px'); $pbtm.click( function(e) { $("html,body").animate( { 'scroll-top': $(document).height() -$(window).height() }, 500 ); } ); $header.append($pbtm); // AutoPagerizeのページ移動 // ※インストールしていなくても作製して非表示にしておき、 // AutoPagerizeの初期化イベントで表示させる。 // AP初期化イベント中ではなくこの時点で作成するのは、 // 高さの計算を簡略化するため。 // 前のページ var $ap_prev = $(move_div) $ap_prev.text("△"); $ap_prev.attr( 'alt', 'Scroll Prev Page'); $ap_prev.css( { 'display': 'none', 'right': '140px', } ); $ap_prev.click( function(e) { $("html,body").animate( { 'scroll-top': scTop==ap.seam[ap.page]? ap.seam[ap.page-1]: ap.seam[ap.page] }, 500 ); } ); $header.append($ap_prev); // 次のページ var $ap_next = $(move_div); $ap_next.text("▽"); $ap_next.attr( 'alt', 'Scroll Next Page'); $ap_next.css( { 'display': 'none', 'right': '100px', } ); $ap_next.click( function(e) { $("html,body").animate( { 'scroll-top': ap.page+1<ap.seam.length? ap.seam[ap.page+1]: $(document).height() -$(window).height() }, 500 ); } ); $header.append($ap_next); // 移動ボタンのスタイル var NDH_BTN_Style = "." + NDH_BTN +"{ \ box-sizing: border-box; \ border: solid 1px transparent; \ }" + "." + NDH_BTN + ":hover{ \ border: outset 1px black; \ }" + "." + NDH_BTN + ":active{ \ border: inset 1px black; \ background-color: #fafafa; \ }"; var mb_style = $("<style type='text/css' />"); mb_style.append(NDH_BTN_Style); $("head").append(mb_style); // 追加したボタンのスタイルをまとめて設定 $( "." +NDH_BTN ).css( { 'cursor': 'pointer', 'position': 'absolute', 'top': 0, 'bottom': 0, 'margin': '4px', 'padding': '0px 10px', 'line-height': function() { return $(this).height()+'px'; } } ); // フラグ var _boxon = false; var _lockB = 0, _lockM = 0; var _show = 0; // 表示設定 var $navi_box = $("#novelnavi_right"); if( $navi_box.size() ) { $header_org.find("#novelnavi_right").remove(); $header.find("#novelnavi_right").hide(); var $navi = $("<div id='navi_button' class='" + NDH_BTN + "' />"); $navi.css( { 'position': 'absolute', 'display': 'block', 'margin': 0, 'top': 16, 'right': 3, 'height': 28, 'width': 10 } ); $navi.click( function() { if( _lockM ) { $("#menu_off").click(); _lockM = false; }else { $("#menu_on").click(); _lockM = true; } } ); $header.append($navi); var $navi_menu = $(".novelview_navi"); $navi_menu.css( { 'top': headerH, 'right': 0 } ); $header.append($navi_menu); $("input[name='fix_menu_bar']").prop( { 'disabled': true, 'checked': false, } ); $("#menu_off_2").click( function(e){ $navi.click(); } ); } // AutoPagerize 互換 var ap; // AP用変数とボタンを初期化 var AP_Init = function() { ap = { 'seam': [0], 'page': 0, }; $ap_next.show(); $ap_prev.show(); }; // ページを継ぎ足した時、継ぎ目の位置を記録する var AP_SeamLine = function() { if( ap != null) { var $ap_sep = $(".autopagerize_page_separator"); var $ap_sep_last = $ap_sep.eq(-1); ap.seam[$ap_sep.index($ap_sep_last)+1] = parseInt($ap_sep_last.offset().top)-boxheight; } }; if( window.AutoPagerize ) { console.log( 'window.AutoPagerize' ); // 初期化 AP_Init(); // 継ぎ足した時 AutoPagerize.addFilter(AP_SeamLine); }else { $(document).on( { 'GM_AutoPagerizeLoaded': function(){ AP_Init(); }, 'GM_AutoPagerizeNextPageLoaded': function(){ AP_SeamLine(); } } ); } var scTop = $(window).scrollTop(); // ヘッダーを表示させる var HeaderShow = function(bool) { if( _show<1 && bool ) { _show = 1; // 消えている最中でもすぐにまた表示させる $box.stop(); // ヘッダーを表示させるアニメ $box.animate( { 'top': 0}, { 'duration': 'fast', 'easing' : 'swing', 'complete': function() { _show = 2; } } ); } } // ヘッダーを隠す var HeaderHide = function(bool) { if( _show>0 && bool ) { _show = -1; $box.stop(); // ヘッダーを非表示にするアニメ $box.animate( { 'top': -boxheight}, { 'duration': 'normal', 'easing' : 'linear', 'complete': function() { _show = 0; }, 'progress' : function(e) { if( parseInt($(this).css('top')) <= -scTop ) { $box.stop(false,true); $box.css( 'top', -scTop); } } } ); } } // スクロール位置によってヘッダー位置を調整 // ※上端でチラ見えしてるときは絶対座標っぽくずらす // そうでなければ、画面のすぐ上で待機させる var HeaderPosSet = function() { if( scTop <= boxheight || parseInt($box.css('top')) != -boxheight ) { $box.stop(); $box.css( 'top', scTop<=boxheight? -scTop: -boxheight ); } } HeaderPosSet(); var novel_title = $(".margin_r20:first").text(); $(window).on( { 'ready resize': function() { $detect.width($(window).width()); $box.width($(window).width()); }, 'scroll': function() { scTop = $(window).scrollTop(); // ヘッダーを追従させる if( _show==0 && !_lockB && !_lockM ) HeaderPosSet(); // AutoPagerize if( ap != null ) { for( var i=ap.seam.length-1; i>=0; i-- ) { if( scTop >= ap.seam[i]-1 ) { if( ap.page != i ) { ap.page = i; if( $("#novel_honbun").size() ) { $label_sub.text( $(".novel_subtitle").eq(i).text()); document.title = novel_title + " - " + $label_sub.text(); } } break; } } } if( $(".novel_hyouka,#novel_footer,#footer").offset().top < scTop + $(window).height() ) { if( !_lockB ) { HeaderShow(true); _lockB = true; } }else { if( _lockB ) _lockB = false; HeaderHide( !_lockM && !_boxon ); } } } ); var href; // ヘッダーに「目次」を追加 var $index_li = $("<li />"); var $index_node = $("<a />"); var index_href = $("#contents_main>a:first").attr('href'); if( index_href==null ){ // 携帯用のアドレスから生成 var handheld = $("link[media='handheld']").attr('href'); index_href = handheld.match(/\/n\d+?\w+?\//); } $index_node.text("目次"); $index_node.attr( 'href', index_href); $index_li.append($index_node); $header.find("li:contains('感想')").before($index_li); var userid; // ノベルフッターから作者コードを抜く var user_href = $(".undernavi a:contains('マイページ')").attr('href'); if( user_href==null ){ // よくわからんけど作者コードっぽいので引っこ抜く var atom = $("link[title='Atom']").attr('href'); if( atom ){ userid = atom.match(/(\d+|x\d+[^\.]+?)/)[0] + "/"; user_href = "http://mypage.syosetu.com/" + userid; }else{ userid=null; user_href=null; } }else{ userid = user_href.match(/(\d+\/|x\d+.+)/)[0]; } // ヘッダーに「作者マイページ」を追加 var $user_li = $("<li />"); var $user_node = $("<a />"); $user_node.text("作者"); if( userid ){ $user_node.attr( 'href', user_href); }else{ $user_node.css( 'cssText', 'color: rgba(200,200,200,0.3) !important;'); } $user_li.append($user_node); $header.find("li:contains('感想')").before($user_li); // ヘッダーに「メール」を追加 var $mail_li = $("<li />"); var $mail_node = $("<a />"); $mail_node.text("メール"); if( userid && userid[0]!="x" ){ $mail_node.attr( 'href', 'http://syosetu.com/message/sendinput/to/' + userid); }else{ $mail_node.css( 'cssText', 'color: rgba(200,200,200,0.3) !important;'); } $mail_li.append($mail_node); $header.find("li:contains('感想')").before($mail_li); // N2コードを取得 var dlurl, n2code; dlurl = $(".undernavi li:contains('ダウンロード')>a"); if( dlurl.size() ){ n2code = dlurl.attr('href').match(/\d+\//); } var bm_config = userid && userid[0]=="x"? "http://syosetu.com/favnovelmain18/updateinput/xidfavncode/" + MY_XUSER_ID: "http://syosetu.com/favnovelmain/updateinput/useridfavncode/" + MY_USER_ID; bm_config += "_" + n2code; var dl_prm = { 'hankaku': '0', 'code': 'utf-8', 'kaigyo': 'crlf' }; // テキストダウンロードボタンを追加 var num = location.href.match( /\d+(?=\/$)/ ); var $down_li = $("<li />"); var $down_node = $("<a />"); $down_node.text("DL"); if( n2code && num ){ var txtdl_url = userid[0]=="x"? "http://novel18.syosetu.com/txtdownload/dlstart/ncode/": "http://ncode.syosetu.com/txtdownload/dlstart/ncode/"; $down_node.attr( 'href', txtdl_url + n2code + "?hankaku=" + dl_prm.hankaku + "&code=" + dl_prm.code + "&kaigyo=" + dl_prm.kaigyo + "&no=" + location.href.match( /\d+(?=\/$)/ ) ); }else{ $down_node.css( 'cssText', 'color: rgba(200,200,200,0.3) !important;'); $down_node.css( 'pointerEvents', 'none'); } $down_li.append($down_node); $header.find("li:contains('レビュー')").after($down_li); // 「縦書で読む」を消す $header.find("li a.menu").parent().hide(); // 「ブックマークに追加」/「ブックマークを解除」を改変 var $fav = $("li.booklist,li.booklist_now"); var $fav_a = $fav.children("a"); $fav_a.css( 'cssText', "color: #F4FA58 !important;" ); $fav_a.css( 'font-size', '150%'); if( $("li.booklist").size() ){ $fav_a.text("☆"); $fav_a.attr( 'alt', 'ブックマークに追加'); }else{ $fav_a.text("★"); $fav_a.attr( { 'href': bm_config, 'alt': 'ブックマーク設定' } ); } $fav.attr( 'class', null); // しおりを挿む/しおり中ボタンの改変 var $bmark_img = $("<img>"); var $bmark = $header.find("li.bookmark,li.bookmark_now"); $bmark.attr( { 'id': 'bookmark_icongap', 'class': null } ); var $bmark_a = $bmark.children("a"); if( $bmark_a.size() ){ $bmark_a.text( "挿栞"); $bmark_a.attr( 'alt', 'しおりを挿む'); $bmark_img.attr( 'src', '/novelview/img/bookmarker_now.png'); }else{ $bmark.text(""); $bmark_a = $("<a />"); $bmark_a.attr( { 'href': bm_config, 'alt': 'ブックマーク設定' } ); $bmark_a.text("設定"); $bmark.append($bmark_a); $bmark_img.attr( 'src', '/novelview/img/bookmarker.png'); } var col = $header_org.find("li>a:first").css('border-left-color'); if( $fav.size() ){ $bmark_img.css( { 'pointer-events': 'none', 'position': 'absolute', 'top': 0, 'bottom': 0, 'margin': 'auto', 'padding': '0px 8px 0px 12px', } ); $bmark_a.before($bmark_img); $bmark_a.css( 'cssText', // padding-left は画像サイズから手計算。 // ※自動計算はloadイベントを使用しなければならないので、 // 表示の反映に若干ラグが出る(&コードがややこしくなる)。 "padding-left: 33px !important;" + "border-left: none !important;" ); // <a>要素のテキストを縦中央合わせ // ※heightが確定していなければ、適切なline-heightを求められない var Li_Fix = function($li_a){ $li_a.outerHeight(headerH-1); $li_a.css( { 'line-height': $li_a.height()+'px', 'border-right': '1px solid ' + col, } ); $li_a.parent().css('padding',0); }; Li_Fix($bmark_a); Li_Fix($fav_a); }else{ $down_node.css( 'border-right', '1px solid ' + col ); } // 感想ページ if( location.href.indexOf("impression")>0){ // コメントフォームをコメント一覧の上に持っていく var hyouka = "#hyoukalan"; var $hyouka = $(hyouka); if( $hyouka.size() ) { var $target = $("h1:eq(0)"); $target.before($hyouka); $target.before($("<hr>")); // 横幅いっぱいにする $("textarea," + hyouka).css( { 'box-sizing': 'border-box', 'width': '100%' } ); // "▽感想を書く"を消去 $(".input").hide(); } } })(); // novel_headerのpositionを記録しないようにする window.changeMenuBar = function(fixMenuBar){}