グルーピングの見出しに色をつけて簡易ダッシュボード的なものをつくってみた

SharePoint2010で、進捗管理にカスタムリストを利用したときのお話です。

サイトのトップページでパッと見て進捗がわかるようにできるといいよね~、というので作ってみたものです。
20140827
リストwebパーツをステータスでグループ化したビューで表示し、グループ化の見出しにJavaScriptで色をつけています。

ソースコードです。

JavaScript : Indicator.js

$(document).ready(function () {
    $("td.ms-gb:contains('Not Started')").css({ "color": "#ffff00", "background-color": "red" });
    $("td.ms-gb:contains('In Progress')").css({ "color": "#0000ff", "background-color": "yellow" });
    $("td.ms-gb:contains('Completed')").css({ "color": "#ffffff", "background-color": "green" });
});

HTML(※こちらをtxtファイルでライブラリに格納し、リストwebパーツを配置したのと同じページにコンテンツエディタwebパーツでリンクします)

<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="/[your site]/Lib/Indicator.js"></script>

こういったwebパーツをいくつかトップページに配置しておけば、簡易ダッシュボード的なものが作れるのではないかと思います。

カスタムリストの中身をコンテンツスライダーで表示してみた

夏休みボケがまだ直らない感じなので、お遊びネタを一つ。

若干時代遅れ感ありつつも、まだまだ世の中のwebサイトでよく見かけるコンテンツスライダー。
これをSharePointのページに表示させたりしたらかっちょいいのでは・・・と、SharePoint2013で息抜きがてらに作ってみました。

BHvfSMH3t5K
コンテンツスライダーは、こちらのjQueryプラグインを利用しています。設置がとても簡単なうえ、オプションも多数あり、とても使い勝手がよいです。
jQuery Content Slider | Responsive jQuery Slider | bxSlider.

表示させる中身は以下のようなカスタムリストに登録し、RESTサービスを利用して引っ張ってきています。
リスト名:SliderContents
列:
Title(1行テキスト)
Caption(1行テキスト、画像にオーバーレイで表示させるキャプション)
contentURL(1行テキスト、画像をクリックしたら飛んでいく先)
imageURL(1行テキスト、スライダーに表示させる画像のURL)

ソースコードです。

JavaScript

$(function () {
	$("#main-slider").empty();
	$.ajax({
		url: "/[your site]/_api/web/lists/getbytitle('SliderContents')/items?$select=*", 
		method: "GET", 
		headers: { "Accept": "application/json; odata=verbose" },
		success : function(data){
			var liHtml = "<ul class='bxslider'>";
			$.each(data.d.results, function(index, item){
				liHtml += "<li><a href='" + item.contentURL + "'>";
				liHtml += "<img src='" + item.imageURL + "' alt='" + item.Title + "' title='" + item.Caption + "' />";
				liHtml += "</a></li>";
			}); //end each
			liHtml += "</ul>";
			$("#main-slider").append(liHtml);
			$(".bxslider").bxSlider({
				captions: true,
				auto: true,
				autoControls: true,
				autoHover: true,
				pager: false
			});
		},
	});
});

HTML(こちらをスクリプトエディタwebパーツでページに埋め込みます)

<!-- jQuery library (served from Google) -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<!-- bxSlider Javascript file -->
<script src="/[your site]/Lib/jquery.bxslider/jquery.bxslider.min.js"></script>
<!-- bxSlider CSS file -->
<link href="/[your site]/Lib/jquery.bxslider/jquery.bxslider.css" rel="stylesheet" />
<script type="text/javascript" src="/[your site]/Lib/slider/SliderSample.js" ></script>
<div id="main-slider">
</div>

ほとんどSharePointとは関係ない世界にはいってるような気もしますが・・・ご参考まで。

ページ最下部までスクロールすると自動で次のアイテムを読み込む何かを作ってみた

Facebookのように、ページの最後までスクロールすると次のアイテムが自動で読み込まれるみたいなサイト、最近ほんと増えましたよね。
で、SharePointでもこれできないかな?と考えていたところ、こちらの記事

jQueryでページ最下部までスクロールした際に外部HTML(JSON形式)化した要素を追加する方法 | BlackFlag

を読みまして、SharePoint2013でトライしてみることにしました。

scroll

サイト内に作成したカスタムリスト(ここではtestというリスト名で作成、列はTitleとBodyだけ)からRESTサービスでリストアイテムを呼び出し、読み込んでいます。
(ほんとは標準のリストビューで無限スクロールできればカッコよかったのですが、私の技量ではどうにも無理なのでこの形になりました・・・)

なお、下記ソースは上記BlackFlagさんの記事からほとんどいただいておりますので、ぜひ元記事もご参照ください。
※CSSは、ほぼそのまま拝借させていただいております。ありがとうございます!

[追記]
最初のソースでは、アイテムへのリンクをクリックして表示したのち前のページに戻ると、スクロール位置が最初に戻ってしまい、読み込んでいた内容が消えてしまって「ああああ・・・」という感じだったので、リンクをクリックしたらアイテムをダイアログで表示させるようにしてみました。これで、少しは実用に近づいてきたでしょうか・・・?

[さらに追記]
超・有名ブログSharePoint Maniacsの著者、シンプレッソ・コンサルティング中村様から、このようにAjaxによる非同期通信でリストアイテムを表示するのがSharePointのパフォーマンス改善に効果があり、今年のSharePoint カンファレンス(米国)でもレスポンスアップに関するセッションで紹介されていた、とのコメントをいただきました。
私がこの記事を書いたときは、パフォーマンス改善のことはまったく念頭になかったので追記させていただきます。
なお、上記SharePointカンファレンスのセッションはこちらです。
http://channel9.msdn.com/events/SharePoint-Conference/2014/SPC3993
ぜんぜんSharePointの機能じゃないじゃんよ~、というツッコミはさておき、こういうやり方もあるよ、ということで。

HTML

<link rel="stylesheet" type="text/css" href="/[your site]/[your library]/jsonSample.css" />
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="/[your site]/[your library]/jasonSample.js"></script>
<div id="loadarea"></div>

jsonSample.js

$(function(){
	var setArea = $('#loadarea'),
	loadNum = 1, // 読み込む個数
	loadTxt = 'Now Loading...', // Loading中の表示テキスト
	fadeSpeed = 500; // フェードスピード

	var onclickStr;
	var txt;
	$.ajax({
		url: "/[your site]/_api/web/lists/getbytitle('test')/items?$select=*", 
		method: "GET", 
		headers: { "Accept": "application/json; odata=verbose" },
		success : function(data){
			for (var i=0; i<5; i++) {
				onclickStr = "openInDialog('/[your site]/Lists/test/DispForm.aspx?ID=" + data.d.results[i].ID + "',500,500,true,true,false); return:false;";
				txt = data.d.results[i].Body;
				if(txt.length > 200){txt = txt.substr(0, 200) + "...";}
				$('<div id="' + data.d.results[i].Title + '" class="loadItem"><h3>'
					+ data.d.results[i].Title + '</h3><br>'
					+ txt + ' <a href="javascript:void(0)" onclick=' 
					+ onclickStr + '>' + '[read more]'+ '</a></div>').appendTo(setArea);
			}
		}
	});

	$("#s4-workspace").scroll(function(){
		var winHeight = $("#s4-workspace").height(); 
		var posBottom = $("#s4-bodyContainer").height() - winHeight;
		if($("#s4-workspace").scrollTop() >= posBottom) {
			var adjScrTop = $("#s4-workspace").scrollTop();
			$("#s4-bodyContainer").animate({scrollTop:(adjScrTop)-1},0);
			$.ajax({
				url: "/[your site]/_api/web/lists/getbytitle('test')/items?$select=*", 
				method: "GET", 
				headers: { "Accept": "application/json; odata=verbose" },
				success : function(data){
					var dataLengh = data.d.results.length,
					loadItemLength = setArea.find('.loadItem').length,
					setAdj = (dataLengh)-(loadItemLength),
					setBeg = (dataLengh)-(setAdj);
					if(!(dataLengh == loadItemLength)){
						setArea.append('<div id="nowLoading">' + loadTxt + '</div>');
						if(loadItemLength == 0){
							for (var i=0; i<loadNum; i++) {
								onclickStr = "openInDialog('/[your site]/Lists/test/DispForm.aspx?ID=" + data.d.results[i].ID + ",500,500,true,true,false'); return:false;";
								txt = data.d.results[i].Body;
								if(txt.length > 200){txt = txt.substr(0, 200) + "...";}
								$('<div id="' + data.d.results[i].Title + '" class="loadItem"><h3>'
									+ data.d.results[i].Title + '</h3><br>'
									+ txt + ' <a href="javascript:void(0)" onclick=' 
									+ onclickStr + '>' + '[read more]'+ '</a></div>').appendTo(setArea)
								.css({opacity:'0'}).animate({opacity:'1'},fadeSpeed);
							}
						} else if(loadItemLength > 0 && loadItemLength < dataLengh){
							if(loadNum < setAdj){
								for (var i=0; i<loadNum; i++) {
									v = i+setBeg;
									onclickStr = "openInDialog('/[your site]/Lists/test/DispForm.aspx?ID=" + data.d.results[v].ID + "',500,500,true,true,false); return:false;";
									txt = data.d.results[v].Body;
									if(txt.length > 200){txt = txt.substr(0, 200) + "...";}
									$('<div id="' + data.d.results[v].Title + '" class="loadItem"><h3>'
										+ data.d.results[v].Title + '</h3><br>'
										+ txt + ' <a href="javascript:void(0)" onclick=' 
										+ onclickStr + '>' + '[read more]'+ '</a></div>').appendTo(setArea)
									.css({opacity:'0'}).animate({opacity:'1'},fadeSpeed);
								}
							} else if(loadNum >= setAdj){
								for (var i=0; i<setAdj; i++) {
									v = i+setBeg;
									onclickStr = "openInDialog('/[your site]/Lists/test/DispForm.aspx?ID=" + data.d.results[v].ID + "'500,500,true,true,false); return:false;";
									txt = data.d.results[v].Body;
									if(txt.length > 200){txt = txt.substr(0, 200) + "...";}
									$('<div id="' + data.d.results[v].Title + '" class="loadItem"><h3>'
										+ data.d.results[v].Title + '</h3><br>'
										+ txt + ' <a href="javascript:void(0)" onclick=' 
										+ onclickStr + '>' + '[read more]'+ '</a></div>').appendTo(setArea)
									.css({opacity:'0'}).animate({opacity:'1'},fadeSpeed);
								}
							}
						} else if(loadItemLength == dataLengh){
							return false;
						}
					} else {
						return false;
					}
				},
				complete : function(){
					$('#nowLoading').each(function(){
						$(this).remove();
					});
					return false;
				}
			});
			return false;
		}
	});

    //add button go back to page top
    var topBtn = $('#page-top');
    topBtn.hide();
    $('#s4-workspace').scroll(function () {
        if ($(this).scrollTop() > 400) {
            topBtn.fadeIn();
        } else {
            topBtn.fadeOut();
        }
    });
    topBtn.click(function () {
        $('#s4-workspace').animate({
            scrollTop: 0
        }, 500, "swing");
        return false;
    });
});

//Open item in dialog
function openInDialog(pageUrl, dlgWidth, dlgHeight, dlgAllowMaximize,dlgShowClose,needCallbackFunction){
	var options = {
		url: pageUrl,
		width: dlgWidth,
		height: dlgHeight,
		allowMaximize: dlgAllowMaximize,
		showClose: dlgShowClose
	};
	if(needCallbackFunction){
		options.dialogReturnValueCallback = Function.createDelegate(null, CloseDialogCallback);
	}
	SP.SOD.execute('sp.ui.dialog.js', 'SP.UI.ModalDialog.showModalDialog', options);
}

function CloseDialogCallback(dialogResult, returnValue){
	if(dialogResult == SP.UI.DialogResult.OK){
		//do something
		;
	}else if(dialogResult == SP.UI.DialogResult.cancel){
		;
	}else{
		;
	}
}

jsonSample.css

/* #loadarea
--------------------------- */
#loadarea {
	margin: 0 auto;
	width: 500px;
	text-align: left;
}
#loadarea .loadItem {
	padding: 10px 0;
	width: 500px;
	line-height: 160%;
	border-bottom: #666 1px dotted;
}
/* #nowLoading
--------------------------- */
#nowLoading {
	padding: 5px 0;
	width: 100%;
	text-align: center;
	color: #fff;
}

/* =======================================
	ClearFixElements
======================================= */
#loadarea .loadItem:after {
	content: ".";
	height: 0;
	clear: both;
	display: block;
	visibility: hidden;
}

#loadarea .loadItem {
	display: inline-block;
	overflow: hidden;
}

/* =======================================
	Page Top Button
======================================= */
#page-top
{
    position: fixed;
    bottom: 20px;
    right: 50px;
}

#page-top a
{
    background: #666;
    text-decoration: none;
    color: #fff;
    width: 50px;
    padding: 8px 0;
    text-align: center;
    display: block;
    border-radius: 3px;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
}

#page-top a:hover
{
    text-decoration: none;
    background: #999;
}

Gistにも置きました。
JS
https://gist.github.com/marineko/7a1061a633f5e21560ee
CSS
https://gist.github.com/marineko/8c4dcfddf7fa45b59956

手前味噌ですが、こちらの記事で実装した「TOPへ戻る」ボタンも併用しています。ページが長くなってもにゅるっと最初に戻れていい感じです。
スクロールするとトップへ戻るボタンを表示してみた

そのほか、プログラムを書くにあたり参考にさせていただいた記事です。

☆RESTサービスの使い方

SharePoint 2013 で REST サービスを使用したプログラミング方法 – Japan SharePoint Support Team Blog – Site Home – TechNet Blogs.

SharePoint 2013 – CRUD on List Items Using REST Services & jQuery | Plus Consulting Blog.

☆アイテムをダイアログで開く

SharePoint 2010 ダイアログで開く input タグ | クリエ・イルミネート ブログ.