Narrow_DynamicHeader

小説家になろうのヘッダーを動的に表示する

当前为 2015-01-15 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Narrow_DynamicHeader
// @description 小説家になろうのヘッダーを動的に表示する
// @version     1
// @namespace   phodra531
// @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から得ることが出来ます。
	var myUserID = 0;
	var myXUserID = 0;

	// 移動ボタンのスタイル
	// 直下行の行頭の/を消すとコメント範囲が切り替わります。
//*
	//  標準のスタイル
	var moveButtonStyle = "\
		.move_button{ \
			color: #666 !important; \
			background-color:#cdd !important; \
		} \
		.move_button:hover{ \
			color: #fff !important; \
			background-color:#9bc !important; \
		} \
	";
/*/
	//  Stylishテーマ「小説家になろうを見やすく」(kanachan氏 作)
	//    https://userstyles.org/styles/107606/theme
	//  に合わせたスタイル
	var moveButtonStyle = "\
		.move_button{ \
			color: #ccc !important; \
			background-color:rgba(48, 48, 48, 0.9) !important; \
		} \
		.move_button:hover{ \
			color: #fff !important; \
			background-color:#666 !important; \
		} \
		.move_button:link{ \
			color:#ccc !important; \
		} \
		.move_button:visited{ \
			color:#ccc !important; \
		} \
	";
//*/



	// ※そのまま移動させると元の場所が埋め立てられるので、
	// ※クローンを作成したのちにオリジナルは visibility = hidden で隠す。
	// ヘッダー(オリジナル)
	var $header_org = $('#novel_header');
	// ヘッダー(クローン)
	var $header_cln = $header_org.clone(true);
	// 強制的に追従しない設定にする
	$header_cln.css( "position", "absolute");

	var title = $('.margin_r20').text();
	var chapter, cpt_txt;
	// 本文がある(作品各話)→情報ラベルを整形
	var infoHeight = 0;
	if( $('#novel_honbun').size() ){
		var $info_org = $('.contents1');
		// 情報ラベルにサブタイトルを埋め込む
		chapter = $('.chapter_title');
		if( chapter.size() ){
			cpt_txt = chapter.text();
			// 章分けがされている
			// チャプタータイトルにサブタイトルを追加
			chapter.append( " - " + $('.novel_subtitle').text() );
		}else{
			// 章分けなし
			// サブタイトル用のエレメントを作成
			var $subtitle = $('<p class="info_label"/>');
			$subtitle.text( $('.novel_subtitle').text() );
			$info_org.append($subtitle);
		}
		
		// 情報ラベルのクローン
		var $info_cln =  $info_org.clone(true);
		$info_cln.css(
			{	"margin": "0 auto",
				"opacity": "0.9"
			});

		infoHeight = $info_org.outerHeight();
		
		// ※$header_clnの兄弟だと設定が面倒なので子にする。
		$header_cln.append($info_cln);
		
		$info_org.css("visibility","hidden");
	}

	// ヘッダーの親になるボックス
	var $header_box =  $('<div/>');
	$header_box.attr( "id", "header_box");
	$header_box.css(
		{	"position": "fixed",
			"top": 0,
			"width": "100%",
			"height": $header_org.height() + infoHeight,
			"zIndex": 1
		});
	$header_box.append($header_cln);
	
	$('body').append($header_box);
	// オリジナルを隠す
	$header_org.css("visibility","hidden");



	// ボタンのボックス
	var $button_box = $('<div />');
	$button_box.attr( "id", "button_box");
	$button_box.css(
		{
			"pointerEvents": "none",
			"position": "fixed",
			"top": 0,
			"width": "100%",
			"height": $header_org.height(),
			"zIndex": 2
		});
	$('body').append($button_box);

	// 表示設定
	var $navi_box = $('#novelnavi_right');
	if( $navi_box.size() ){
		$header_org.find('#novelnavi_right').remove();
		$header_cln.find('#novelnavi_right').hide();
		var $navi = $('<div />');
		$navi.attr("id", "navi_button");
		$navi.css(
			{
				"pointerEvents": "auto",
				"position": "absolute",
				"display": "block",
				"margin": 0,
				"top": 16,
				"right": 3,
				"height": 28,
				"width": 10
			}
		);
		
		var $menu_on = $('<div />');
		var $menu_off = $('<div />');
		var menuStyle = {
			"position": "absolute",
			"height": "100%",
			"width": "100%"
		};
		$menu_on.css(menuStyle);
		$menu_on.attr(
			{
				"id": "menu_open",
				"class": "move_button"
			}
		);
		$menu_on.click(
			function(e){
				$('#menu_on').click();
				$menu_off.show();
				$menu_on.hide();
			}
		);
		$navi.append($menu_on);
		
		$menu_off.css(menuStyle);
		$menu_off.attr(
			{
				"id": "menu_close",
				"class": "move_button"
			}
		);
		$menu_off.click(
			function(e){
				$('#menu_off').click();
				$menu_off.hide();
				$menu_on.show();
			}
		);
		$navi.append($menu_off);
		$menu_off.hide();
		
		$navi.append($('.novelview_navi'));
		$button_box.append($navi);
		$('#menu_off_2').click(
			function(event){
				$menu_off.click();
				$button_box.fadeOut();
			}
		);
	}

	// 移動ボタン群
	var $btnDef = $('#pageBottom');
	var $moveButton = $('<a />');
	$moveButton.attr("class", "move_button");
	$moveButton.css(
		{
			"pointerEvents": "auto",
			"position": "absolute",
			"padding": "10px",
			"margin": "4px",
			"top": 0,
			"bottom": 0
		}
	);
	var mb_style = $('<style type="text/css" />');
	mb_style.append(moveButtonStyle);
	$('head').append(mb_style);

	// 最下部へ移動
	var $pbtm = $moveButton.clone();
	$pbtm.attr(
		{
			"id": "pageBottom2",
			"href": "#page_bottom"
		}
	);
	$pbtm.text("↓");
	$pbtm.css("right", "15px");
	$pbtm.click(
		function(e){
			$('html,body').animate(
				{scrollTop:$('body').height()},
				500
			);
			return event.preventDefault();
		});
	$button_box.append($pbtm);

	// 最上部へ移動
	var $ptop = $moveButton.clone();
	$ptop.attr(
		{
			"id": "pageTop2",
			"href": "#page_top"
		}
	);
	$ptop.text("↑");
	$ptop.css("right", "55px");
	$ptop.click(
		function(e){
			$('html,body').animate(
				{scrollTop:0},
				500
			);
			return event.preventDefault();
		});
	$button_box.append($ptop);

	// 前ページ
	var bn_p = $('a:contains("<<")');
	if( bn_p.size() ){
		var $preEp = $moveButton.clone()
		$preEp.attr(
			{
				"id": "pagePrev",
				"href": bn_p.attr("href")
			}
		);
		$preEp.text("<");
		$preEp.css("left", "15px");
		$button_box.append($preEp);
	}

	// 次ページ
	var bn_n = $('a:contains(">>")');
	if( bn_n.size() ){
		var $nxtEp = $moveButton.clone()
		$nxtEp.attr(
			{
				"id": "pageNext",
				"href": bn_n.attr("href")
			}
		);
		$nxtEp.text(">");
		$nxtEp.css("left", "55px");
		$button_box.append($nxtEp);
	}
	
	$('#pageBottom').remove();
	$('#pageTop').remove();
	
	// AutoPagerizeのページ移動
	if( $('#autopagerize_icon').size() ){
		var $pnxt = $moveButton.clone()
		$pnxt.attr(
			{
				"id": "pageNext",
				"href": "#page_next"
			}
		);
		$pnxt.text("▽");
		$pnxt.css("right", "100px");
		// ボタンが押された時
		$pnxt.click(function(event){
			var tgt_page = now_page+1;
			var tgt_posY =
				tgt_page>seams.length-1?
				$('body').height(): seams[tgt_page]+1;
			
			$('html,body').animate({scrollTop:tgt_posY}, 500);
			return event.preventDefault();
		});
		$button_box.append($pnxt);
	
		var $ppre = $moveButton.clone()
		$ppre.attr(
			{
				"id": "pagePrev",
				"href": "#page_prev"
			}
		);
		$ppre.text("△");
		$ppre.css("right", "140px");
		// ボタンが押された時
		$ppre.click(function(event){
			var tgt_page = $(window).scrollTop()==seams[now_page]+1?
				now_page-1: now_page;
			if( tgt_page<0 ) tgt_page=0;
			var tgt_posY = tgt_page>0? seams[tgt_page]+1: 0;
			
			$('html,body').animate({scrollTop:tgt_posY}, 500);
			return event.preventDefault();
		});
		$button_box.append($ppre);
	}


	// AutoPagerize対応
	var seams = [0];
	document.body.addEventListener('AutoPagerize_DOMNodeInserted',function(e){
		var $page_info = $('.autopagerize_page_info:eq(-1)');
		var num = parseInt( $page_info.children('a:first').text() );
		if( num>1 && seams[num-1]==null ){
			seams[num-1] = parseInt($page_info.eq(-1).offset().top)-$header_box.height();
		}
	}, false);

	var now_page=0;
	// 最下部で表示固定させるフラグ
	var lock = 0;
	// ウィンドウのスクロールが発生した時
	$(window).scroll(function(event){
		var scTop = $(window).scrollTop();
		
		if( moving == 0 ){
			SetHboxTop();
		}

		for( var i=seams.length-1; i>=0; i-- ){
			if( scTop > seams[i] ){
				if( $('#novel_honbun').size() ){
					var sub = $('.novel_subtitle').eq(i).text();
					document.title = title + " - " + sub;
					if( chapter.size() ){
						$('.chapter_title').text( cpt_txt + " - " + sub );
					}else{
						$('.info_label').text(sub);
					}
				}

				if( lock ){
					if( hoving==0 ){
						Hbox_Close();
					}
					lock = 0;
				}
				now_page = i;
				break;
			}
		}
		if( $('#autopagerize_icon').size()<1 ){
			var btmline = $('.novel_bn:eq(-1)');
			if( btmline.size()<1 ) btmline = $('#footer');
			if( btmline.offset().top < scTop + $(window).height() ){
				Hbox_Open( true );
				moving = 1;
				lock = 1;
			}
		}
	});



	// $header_boxの状態
	// 0:移動していない 1:出現中 -1:消失中 2:表示中
	var moving = 0;
	// $header_boxにマウスが乗っているか
	var hoving = 0;

	// 画面上部にポインターを近づける
	document.onmousemove = function (e){
		// InternetExplorer 用
		if(!e) e = window.event;

		if( e.clientY <= $header_org.height() ){
			if( $(window).scrollTop() > 0 &&
				moving < 1  && hoving == 0 ){
				Hbox_Open();
			}
			$button_box.fadeIn("fast");
		}else{
			if( $(window).scrollTop() > 0 &&
				moving != 0 && hoving == 0 && lock==0 ){
				Hbox_Close();
			}
			if( $navi_box.size()? $('.novelview_navi').css("display")=="none": true ){
				$button_box.fadeOut("fast");
			}
		}
	};
	// ヘッダーボックスに乗せる、外す
	$header_box.hover(
		function(){
			Hbox_Open();
			hoving = 1;
		},
		function(){
			if( $(window).scrollTop()>0 ){
				if( lock==0 ){
					Hbox_Close();
				}
			}else{
				moving = 0;
			}
			hoving = 0;
		}
	);

	// ヘッダーを表示させる
	var Hbox_Open = function(){
		if( moving<=0 ){
			// 消えている最中でもすぐにまた表示させる
			$header_box.stop();
			// ヘッダーを表示させるアニメ
			$header_box.animate(
				{"top": 0},
				{	duration : "fast",
					easing   : "swing",
					complete : function(){
						moving = 2;
					}
				}
			);
		}
		moving = 1;
	}
	// ヘッダーを隠す
	var Hbox_Close = function(){
		if( moving > 0 ){
			// とりあえず画面のすぐ上まで持っていく
			var target = -$header_box.height();
			
			$header_box.stop();
			// ヘッダーを非表示にするアニメ
			$header_box.animate(
				{"top": target},
				{
					duration : "normal",
					easing   : "linear",
					complete : function(){
						moving = 0;
					},
					progress : function(s){
						var scTop = $(window).scrollTop();
						if( parseInt($(this).css("top")) <= -scTop ){
							$(this).stop();
							$(this).css("top", -scTop);
							moving = 0;
						}
					}
				}
			);
		}
		moving = -1;
	}

	// ロードした時、ヘッダーが見えない位置なら隠す
	$(document).ready(function(){
		SetHboxTop();
		$button_box.hide();
		moving=0;
	});

	// スクロール位置によってヘッダー位置を調整
	var SetHboxTop = function(){
		var scTop = $(window).scrollTop();
		var hHgt = $header_box.height();
		if( scTop <= hHgt ){
			// 上端ならスクロール位置に合わせて絶対座標っぽく
			$header_box.css( "top", -scTop );
		}else if( $header_box.css("top") != -hHgt ){
			// 上部の表示される位置でなければ、画面のすぐ上
			$header_box.css( "top", -hHgt );
		}
	}



	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_box 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_box 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_box 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/" + myXUserID:
	"http://syosetu.com/favnovelmain/updateinput/useridfavncode/" + myUserID;
	bm_config += "_" + n2code;
	
	var dl_prm = {
		'hankaku': "0",
		'code': "utf-8",
		'kaigyo': "crlf"
	};
	// テキストダウンロードボタンを追加
	var $down_li = $('<li />');
	var $down_node = $('<a />');
	$down_node.text("DL");
	if( n2code ){
		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_li.append($down_node);
	$('#header_box li:contains("レビュー")').after($down_li);
	
	// 「縦書で読む」を消す
	$('#header_box li a.menu').parent().remove();
	
	// 「ブックマークに追加」/「ブックマークを解除」を改変
	var $blist = $('#header_box li.booklist>a');
	if( $blist.size() ){
		$blist.text("☆");
		$blist.attr("alt", "ブックマークに追加");
	}else{
		$blist = $('#header_box li.booklist_now>a');
		$blist.text("★");
		$blist.attr(
			{
				"href": bm_config,
				"alt": "ブックマーク設定"
			}
		);
	}
	$blist.css( "fontSize", "18px");

	// しおりを挿む/しおり中ボタンの改変
	var $bookmark = $('#header_box li.bookmark_now');
	var $bmark_li = $('<li />');
	var $bmark_img = $('<img>');
	var $bmark_node = $('<a />');
	if( $bookmark.size() ){
		var $a = $bookmark.children("li>a");
		$bmark_node.attr(
			{
				"href": $a.attr("href"),
				"alt": "しおりを挿む"
			}
		);
		$bmark_node.text("挿栞");
		$bmark_img.attr("src", "/novelview/img/bookmarker_now.png");
	}else{
		$bookmark  = $('#header_box .bookmark');
		$bmark_node.attr(
			{
				"href": bm_config,
				"alt": "ブックマーク設定"
			}
		);
		$bmark_node.text("設定");
		$bmark_img.attr("src", "/novelview/img/bookmarker.png");
	}
	
	if( $bookmark.size() ){
		$bmark_node.attr("class", "bookmark2");
		var bmark_style = $('<style type="text/css" />');
		bmark_style.append("\
			.bookmark2 { \
				font-weight: normal !important; \
				border-style: none !important; \
				padding-left: 34px !important; \
			} \
			.bookmark2:hover{ \
				font-weight: bold !important; \
				background: none !important; \
			} \
		");
		$('head').append(bmark_style);
		$bmark_img.css(
			{
				"pointer-events": "none",
				"position": "absolute",
				"top": 0,
				"bottom": 0,
				"margin": "auto",
				"padding-left": "12px"
			}
		);
		$bmark_li.append($bmark_img);
		$bmark_li.append($bmark_node);
		$header_cln.children('ul').append($bmark_li);
		$bookmark.remove();
	}
	
	
	
	// 感想ページ
	if( location.href.indexOf("impression")>0){
		// コメントフォームをコメント一覧の上に持っていく
		var parent = document.getElementById('contents_main');
		var target = document.getElementsByTagName('h1')[0];
		var hyouka = document.getElementById('hyoukalan');

		// 横幅いっぱいにする
		hyouka.style.boxSizing = "border-box";
		hyouka.style.width = "100%";
		var textarea = document.getElementsByTagName('textarea');
		for( var i=0; i<textarea.length; i++){
			textarea[i].style.boxSizing = "border-box";
			textarea[i].style.width = "100%";
		}

		parent.insertBefore( hyouka, target);
		parent.insertBefore( document.createElement('hr'), target);
		
		// "▽感想を書く"を消去
		document.getElementsByClassName('input')[0].style.display = "none";
	}
})();



// 小説メニューバーの振る舞いを変更
window.changeMenuBar = function(fixMenuBar){
//	// novel_headerエレメントを取得
//	var element = $('#novel_header');
//	if(element.size() == 0) return false;
//
//	if(isDefined(fixMenuBar)){
//		gIsFixMenuBar = fixMenuBar ? true : false;
//	}else{
//		gIsFixMenuBar = parseInt(CookieManager.get('fix_menu_bar'), 10);
//		if(isNaN(gIsFixMenuBar) || (gIsFixMenuBar != 0)){
//			gIsFixMenuBar = true;
//		}else{
//			gIsFixMenuBar = false;
//		}
//	}
//
//	if(gIsFixMenuBar){
//		$('#novel_header,#novelnavi_right,#menu_on,#menu_off').css('position', 'fixed');
//		$('input[name="fix_menu_bar"]').prop('checked', true);
//	}else{
//		$('#novel_header,#novelnavi_right,#menu_on,#menu_off').css('position', 'absolute');
//		$('.novelview_navi').css('position', 'fixed');
//		$('input[name="fix_menu_bar"]').removeProp('checked');
//	}
//
//	// クッキーに記憶
//	fixMenuBar = gIsFixMenuBar ? 1 : 0;
//	var expires = 86400 * 1000 * 90;	// 90日
//	CookieManager.set({key:'fix_menu_bar', value:fixMenuBar, domain:domain, path:'/', expires:expires});
}