SharePointのリストフォームに採番機能をJavaScriptで実装する

この世にはようかんぱんなるものがあることを知り気になって仕方ないのですが、そんなことはどうでもいいですね。

さて、だいぶ間が空いてしまいましたが久々の更新です!
いぜん、ページにビューカウンタをつける方法をポストしましたが、意外とよく読まれているようなので、気を良くして応用編(?)です。

SharePointのリストアイテムに、システム的に振られるIDではなく、独自ルールで採番したカスタムIDを振りたい!という要望はよくありますよね。
そこで、ページビューカウンタと同じやり方で、採番機能を実現してみました。
新規フォームで見るとこんな感じ。
20151217

実装方法です。
事前に「counter」という名前の採番用カスタムリストを同じサイト内に作成しておきます。
採番用カウンタは、Titleフィールドをそのまま使います。
新規フォーム作成時に、採番用リストから番号を取得し採番フィールドに表示、保存時のアクションでインクリメントした番号を採番用リストに返す仕組みです。
なので、新規フォームをキャンセルした場合は、インクリメントされません。

以下、ソースコードです。
こちらをNewForm.aspxにコンテンツエディタwebパーツで埋め込んでください。

<script src="//code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2014.01/jquery.SPServices.min.js" type="text/javascript"></script>
<script type="text/javascript">
var count;
var itemId;
$(document).ready( function () {
var numStr;
$().SPServices({
operation: "GetListItems",
async: false,
listName: "counter",
completefunc: function (xData, Status) {
$(xData.responseXML).SPFilterNode("z:row").each( function () {
itemId= $(this).attr("ows_ID");
count = Number($(this).attr("ows_Title"));
});
}
});
count++;
numStr = "CustomID - " + ("0000000" + count).slice(-8);
$("input[title='CustomID']").val(numStr).attr("readonly", "readonly").css("color", "#6a6a6a");
$(":text:not([readonly])").eq(0).focus();
});
function PreSaveAction(){
$().SPServices({
operation: "UpdateListItems",
async: false,
batchCmd: "Update",
listName: "counter",
valuepairs: [["Title", count]],
ID: itemId,
completefunc: function(xData, Status) {
}
});
return true;
}
</script>

SPServicesjQuery使ってます。

さらにちょっとした小技として、

21行目:カスタムIDの数値部分を桁固定0埋めで表示
23行目:採番フィールドを読み取り専用にする
24行目:採番フィールドがフォームの最初のフィールドでもフォーカスを当てない

などを盛り込んでおります。

なお、EditForm.aspxには以下を埋め込んでおきます。

<script src="//code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$("input[title='CustomID']").attr("readonly", "readonly").css("color","6a6a6a");
$(":text:not([readonly])").eq(0).focus();
});
</script>

検証環境は2010ですが、2007、2013でも動くと思います。
参考にしていただけるとうれしいです!

ログインユーザーの権限をJavaScriptでチェックする

ひさびさの更新になってしまいましたがちゃんと生きてますよ!!
というわけで、生きている証を立てたいと思います。

ログインユーザの権限に応じて、サイトのUIの一部を非表示にしたいといった要望は多いですよね。
そこで、今回はClient Object Modelを使ってユーザー権限をチェックするコードをJavaScriptで実装してみたいと思います。

Client Object Modelでユーザー権限を取得するには、SP.Web.effectiveBasePermissions propertyを使います。
これで、ユーザーがサイトに対して持っている権限の一覧が取れるので、そこからユーザー権限を判断します。
たとえば、「Webサイトの管理」権限を持っていればフルコントロール権限があるだろう、とか。

では、ログインユーザーが「Web サイトの管理」権限を持っているかチェックするサンプルコードを書いてみます。jQueryも使ってます。

$(function(){
    ExecuteOrDelayUntilScriptLoaded(CheckPermissionOnWeb, "sp.js");
});

function CheckPermissionOnWeb() {
    var ctx = new SP.ClientContext.get_current();
    var web = ctx.get_web();

    var currentUser = web.get_currentUser();
    ctx.load(currentUser);
    ctx.load(web,'EffectiveBasePermissions');
    ctx.executeQueryAsync(Function.createDelegate(this, onSuccessMethod), Function.createDelegate(this, onFailureMethod));        

    function onSuccessMethod(sender, args) {
        if (web.get_effectiveBasePermissions().has(SP.PermissionKind.manageWeb)) {
            console.log('You are Site Admin.');
        }
    }

    function onFailureMethod(sender, args) {
        console.log('Error:' + args.get_message());
    }
}

上記で「SP.PermissionKind.manageWeb」の「manageWeb」のところを変えれば、別の権限を持っているかもチェックできます。
たとえば、「manageLists」ならリストの管理権限があることになります。
具体的には、以下をご参考に。
https://msdn.microsoft.com/en-us/library/ee556747.aspx

対象ユーザーを使って、ビューのアクセス制御っぽいことを実現する

小ネタ、というかメモとして書いておきます。

ご存じのように、SharePointではビューに固有のアクセス権をつけることはできません。
が、ちょっとした工夫でアクセス制御っぽい機能を実現することができます(「ぽい」です、あくまで)。

SharePointのwebパーツには、「対象ユーザー」を設定することができますよね。
リストのビューもwebパーツではあるので、対象ユーザーを設定して特定のユーザーにしか見せないようにできます。

【設定手順】
※以下、画面は2010ですが、2013でも同様にできることを確認しています。

①アクセス制限をかけたいビューを表示した状態で、「サイトの操作」→「ページの編集」を選択します。
②リストビューwebパーツのドロップダウンから、「webパーツの編集」を選択します。
20150114-1
③webパーツの設定画面の「詳細設定」セクションの「対象ユーザー」に、ビューにアクセスさせたいSharePointグループを指定し、「OK」をクリックします。
20150114-2
④リボンで「編集の終了」を押して保存します。
以上です!

これで、指定したグループに登録されていないユーザーは、ページにはアクセスできるもののビューが表示されません。
20150114-3
リボンにも「参照」タブしか表示されず、いい感じです。

厳密にいえば、隠してるだけでほんとのセキュリティではないのですが、こんなやり方もあるよ、ということで。

SharePointのwikiページにページビューカウンタをつけてみた

気が付いたら、今年も残すところあと数日・・・早いものですね。
私らしくどうでもいいネタで今年を締めくくりたいと思います。

もうすっかり前世紀の遺物となってしまった感のあるアクセスカウンターですが、サイトのトップページやお知らせページなんかの場合てっとりばやくどのくらいアクセスがあるのか知りたいって時もあるんじゃないかと思います。

実装するやり方はいろいろあるかと思いますが、ここではアクセスカウントを格納しておくカスタムリストを一つつくっておいて、ページロードの時にJavaScriptでカウンタをインクリメントするようにしてみました。
試した環境はSharePoint2010ですが、2013でもたぶんいけると思います。

下準備:
①サイト内にカスタムリストを作成し、countという一行テキスト列を追加しておきます。
今回は「test」という名前でカスタムリストを作成しました。
②作成したリストに新規アイテムを一つ作成し、countには「0」を入れておきます。

以上で準備は終わりです。
次に、カウンタをつけたいページにコンテンツエディタwebパーツを追加し、そのHTMLソースに以下のコードを記述します。

<div id="pageView"></div>
<script src="http://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2014.01/jquery.SPServices.min.js" type="text/javascript"></script>
<script type="text/javascript">
(function (){

    var itemId;
    var count;

    $().SPServices({
        operation: "GetListItems",
        async: false,
        listName: 'test',
        completefunc: function (xData, Status) {
            $(xData.responseXML).SPFilterNode("z:row").each(function () {
                itemId= $(this).attr("ows_ID");
                count = Number($(this).attr("ows_count"));
            });
        }
    });

    count++;
    count = String(count);

    $().SPServices({
        operation: "UpdateListItems",
        async: false,
        batchCmd: "Update",
        listName: "test",
        valuepairs: [["count", count]],
        ID: itemId,
        completefunc: function(xData, Status) {
          //
        }
    });

    $('#pageView').empty();
    $('#pageView').append('<p>' + count + ' views</p>' );

})();
</script>

以上でOKです!
こんな感じで控え目にページビューが表示されます。
20141226

ちなみに、上記サンプルコードは、多数アクセスがあったときの排他制御とか、複数ビューカウンタをつけたい場合とか、自分のアクセスや編集モードにしたときのページロードを排除するとかは一切考慮しておりません。
何かのヒントになればうれしいです。

それではみなさま、よいお年を!

SharePoint2010にコンテンツエリア拡大ボタンをつけてみた

SharePointのヘッダー部分や、サイドリンクバーって意外と場所をとりますよね。
なんで、コンテンツがもりだくさんのページの場合、もっと大きな画面で見せたい時があると思います。

そういうニーズを受けてかなのか、SharePoint2013なら、コンテンツエリアを拡大して見せるボタン(*)が標準であるのですが、残念ながら2010にはありません。

* コレ↓です
20141128

というわけで、自前で作ってみました。
動作イメージはこんな感じです。画面右下、「全画面」ボタンを押すとコンテンツエリアがぐぐっとひろがります。
20141128

ソースコードです。これをコンテンツエディタwebパーツでページにぺたっと貼ればOKです。

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
<style type="text/css">
  .screen-change
  {
      position: fixed;
      bottom: 20px;
      right: 80px;
  }

  .screen-change a
  {
      background: #666;
      text-decoration: none;
      color: #fff;
      width: 120px;
      padding: 8px 0;
      text-align: center;
      display: block;
      border-radius: 3px;
      -webkit-border-radius: 3px;
      -moz-border-radius: 3px;
      opacity: 0.8;
      filter: alpha(opacity=80); /* IE lt 8 */
      -ms-filter: "alpha(opacity=80)"; /* IE 8 */
  }

  .screen-change a:hover
  {
      text-decoration: none;
      background: #222;
  }
</style>
<script>
  $(function(){
    $(document.body).append('<p id="only-content-area" class="screen-change"><a href="#">全画面表示</a></p><p id="default-screen" class="screen-change"><a href="#">元に戻す</a></p>');
    $("#default-screen").hide();
    $(".screen-change").click(function() {
      $('#s4-titlerow, #s4-leftpanel, #RibbonContainer-TabRowLeft, .ms-cui-tts').toggle('slide', '', 500);
      var hide = $('#default-screen').css('display');
      if(hide == 'none'){
        $('.s4-ca').css('margin-left', '0px');
      } else {
        $('.s4-ca').css('margin-left', '155px');
      };
      $("#only-content-area, #default-screen" ).toggle();
    });
  });
</script>

リボンメニューが表示されている状態で拡大するとあやしい動きになってしまうので、リボンメニューを表示させられるツールバーのボタンやタブも軒並み隠してますが、それならいっそツールバー自体を隠しちゃってもよかったかも。
そのへんはお好みで調整してください。

ふと、思ったのですが、これ応用したら印刷用画面としても使えるかも・・・?

ドキュメントライブラリのファイルがPDFだったら別窓で開く

ひさびさの更新になってしまいました。気が付けば、今年も残すところあと2か月、巷には早くもクリスマスのイルミが・・・という季節になってしまいました。早すぎるだろ。

さて、SharePoint2010のお話です。

ドキュメントライブラリでPDFを入れている場合、該当のファイル名をクリックするとブラウザの同じウィンドウ内で開いてしまいます。
(ブラウザでPDFを開く設定にしていれば、ですが。)
その時、うっかりタブを閉じたりすると元のライブラリに戻れなくなっちゃったりします。
地味に不便ですよね。

で、PDFファイルの場合だけ選択的に別窓で開かせるスクリプトを書いてみました。jQuery使ってます。

// これだとグルーピングしたビューではダメ
$('a[href$=".pdf"]').each(function(){
	$(this).removeAttr('onclick');
});
//無理やりだけど・・・
$(document).on('mouseover', 'a[href$=".pdf"]',
	function(eo) {
		$(eo.target).removeAttr('onclick');
	}
);
//クリックイベントを設定
$(document).on('click', 'a[href$=".pdf"]',
	function(eo) {
		window.open(eo.target.href, '_blank');
		return false;
   	}
);

ドキュメントライブラリのリストビューだと、クリック時 onclick属性に設定されてるファンクションが先に動いてしまうので、まずそいつを削除する、しかもmouseoverイベントで・・・という荒ワザをやっております。
こんなことしていいかよくわかりませんけど、よくない気もしますけど、もっといいやり方があったら教えていただけるとうれしいです。

また、グルーピングしたビューの場合アイテムが動的に追加されるため hoge.click(function… みたいな書き方は通用しません。
で、こちらなど参考にしつつ、
外部リンクを別窓で開くJavaScriptを改善した – rakugaki-box.net.
上記コードに落ち着きました。

リンクリストで、外部リンクは別窓で開かせたい!なんて場合にも応用できそうですね。

SharePointのページ内リンクでスムーススクロール

またしてもSharePointの機能とはさして関係のないネタです。当ブログ、こんなんばっかりですがお許しください・・・

以前、こんな記事を書きましたが、
SharePointでスクロールするとトップへ戻るボタンを表示してみた
こちらの姉妹編のエントリです。

最近のwebサイトでは、ページ内リンクへのジャンプはアニメーションでスルスル~っとスクロールしてくのがもう定番ですよね。
これをSharePointのページにも実装してみました。
smoothScroll

スムーススクロールは巷にプラグインなどあふれてますが、余計なものを入れたくなかったのでCSS-Tricksにあったこちらを元ネタにしました。
Smooth Scrolling | CSS-Tricks
jQueryさえあれば動かせます。

ソースコードです。SharePoint2010、2013で動作確認しています。
JavaScript

$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    var def = $('div[id*=titlerow]').offset().top;
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('#s4-workspace').animate({
        	scrollTop: target.offset().top - def
        }, 500);
        return false;
      }
    }
  });
});

HTMLサンプル

<h3>​​​​​​<a href="#section1">Section1</a></h3>
<h3><a href="#section2">Section2​</a></h3>

<h1 id="section1">Section1</h1>
<div>Vivamus suscipit tortor eget felis porttitor volutpat. Pellentesque in ipsum id orci porta dapibus.
 Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. 
Quisque velit nisi, pretium ut lacinia in, elementum id enim. Pellentesque in ipsum id orci porta dapibus. 
Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. 
Pellentesque in ipsum id orci porta dapibus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. 
Cras ultricies ligula sed magna dictum porta. Proin eget tortor risus.</div>

<h1 id="section2">Section2</h1>
<div>Vivamus suscipit tortor eget felis porttitor volutpat. 
Pellentesque in ipsum id orci porta dapibus. Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. 
Quisque velit nisi, pretium ut lacinia in, elementum id enim. 
Pellentesque in ipsum id orci porta dapibus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. 
Pellentesque in ipsum id orci porta dapibus. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. 
Cras ultricies ligula sed magna dictum porta. Proin eget tortor risus.</div>

SharePointで実装するときの注意点ですが、windowオブジェクトではスクロール位置がとれないので、idが”#s4-workspace”のdiv要素を動かします。
また、リンク元の要素がページの半ばにあることも考慮して、サイトのタイトルエリアがwindowのトップからどれだけ上にふっ飛んでるかでスクロール幅を調整しています。
HTML側は、サンプルのように基本飛ばしたい先の要素にハッシュと同じID名を振ればよいのですが、スクリプト的にはアンカーにも対応してます。

余談ですが、SharePointでページにアンカーをつけたい時は、リンクツールでBookmark欄に任意のアンカー名をいれればつけられます。
20141003

なので、上記コードをパッケージ化(コンテンツエディタwebパーツに仕込んでExportするなど)すれば、HTMLを書けないユーザでもスムーススクロールできるようになりそうですね!

SharePoint 2010のwikiページを2013のosloテーマっぽくするCSS

先日ひさびさにバンドの練習で歌ってきたのですが、背中と脇腹が筋肉痛になりました。普段からまじめにトレーニングしないとだめですね・・・

さて、SharePoint2013になってosloテーマができ、サイドリンクバーなしの中央固定幅のレイアウトが選べるようになりました。
SharePoint2010のチームサイトでもosloっぽいレイアウトにしてみたく、CSSで強引につくってみました。
これを適用したいwikiページにコンテンツエディタ webパーツで埋め込んでください。

CSS

#s4-leftpanel
{
    display : none;
}
.s4-ca
{
    margin-left : 0px !important;
} 

.ms-rtestate-field{
    max-width: 1024px;
    min-width: 768px;
    margin: 0 auto;
    padding: 0;
}

max-width、min-widthはお好みや環境に応じて設定してください。

いちおう、wikiページのテキストレイアウトをいろいろ変更しても中央固定幅になることは確認してますが、そんなにしっかりテストはしてないので、実環境に適用される場合は副作用がないか十分検証してくださいね。

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

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パーツをいくつかトップページに配置しておけば、簡易ダッシュボード的なものが作れるのではないかと思います。

SharePointの予定表をjQueryUIのDatePickerで表示してみた

SharePoint2013の検証環境が壊れてしまいショック死しておりましたが、ようやく生き返りました。サーバーも早く息を吹き返してほしいものです・・・

さて、SharePointのチームサイトでは、予定表はよく使う機能の一つだと思います。
ただ、webパーツとしてサイトのトップページに表示させたい場合、標準のwebパーツだとはっきり言ってデカいです。
で、小さくしたい!しかもかっちょよく!と常々思っていました。

CSSで何とかするやり方は

予定表 Web パーツのカレンダー表示をコンパクトにしてみた | idea.toString;

とかあって、これでいいよねこれで・・・といったんは思ったんですが、ついでにイベント一覧も表示したりできるといいよね、ということで自作してみることにしました。

UIはjQuery UIのDatePickerかっこいいから使いたい、そこでググってみたところCodePlexによさそうなソリューションを発見。
http://jqcalendarpart.codeplex.com/
おお~、これこれ!と思ったのですが、一つ問題が・・・
Limitations:
The web part will not work if you try to navigate to the next month or to the previous month. Please wait as I’m working on a fix to highlight all the dates which are having event registered when a user is navigating to the next month.

とあるように、月を切り替えるとイベントが表示されなくなっちゃうという・・・うむむむ・・・これでは実用に耐えない・・・

というので、上のコードを元にがんばって動くものを作ってみました。
上記のCodePlexのソリューションとは違い、ホバーではなく下に表示月のイベントを表示するようにしています。
20140722

なお、月を切り替えてもちゃんとイベントの日付を色付けするには、どうやら下記のようにonChangeイベントでやりたい処理をsetTimeoutで遅延させるのがキモのようです。
(参考にさせていただいた記事:書いて忘れる: jQuery:UI datepickerの週末に色をつける.)

    $(".divDatePicker").datepicker({
        onChangeMonthYear: function (year, month, inst) { //表示月変更 
            setTimeout(function () { syncCalendar(year, month, selectDate.getDate()); }, 100);
        },
        onSelect: function (dateText, inst) { //選択日変更
            dispDayEvent(dateText);
        }
    });

完全なソースコードはGistに置いてます。ご自由におとりください。
HTML←これをコンテンツエディタ webパーツでページに埋め込んでください。
https://gist.github.com/marineko/6baa039110521f3b043a
JavaScript
https://gist.github.com/marineko/63c7a386786ea7d6d2de
CSS
https://gist.github.com/marineko/469a84fd8ab882d41e76
※SharePoint2010、2013両方で動作確認済みです。

依存関係のあるファイルです。上記ソースコードと合わせ、以下もページに読み込んでおいてください。
jQuery
jQuery UI
XDate
SPServices

なお、jQuery UIのテーマは、フラットなUIテーマの作れる以下のwebサービスで作りました。便利な世の中になりましたねー。

Build jQuery UI themes with jQUIT Builder

なお、コンテンツエディタを使ってページにスクリプトなどを置くやり方は、以下のポストをご参考に・・・
JavaScriptなど外部ファイルをページに読み込む
予定表のフォームで会議ワークスペース列を非表示にする