Narrow_DynamicHeader

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

目前為 2015-01-15 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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});
}