Sharepointカスタマイズポイントメモ

#導入
Sharepointの基本機能だけで業務サポートサイトを構築するので、ポイントや忘れがちな点を一覧化しておく。
目的別の見出しで並べていく。


##ページのタイトル書き換え
#####Javascript
```javascript
$(function() {
  var headerTitleElement = $("#DeltaPlaceHolderPageTitleInTitleArea>span>span>a");
  headerTitleElement[0].innerHTML = "書換え後のタイトル名";
});
```

#####css
なし

##JavaScriptでのGetパラメータ取得
#####Javascript
```javascript
 var arg  = new Object;
 url = location.search.substring(1).split('&');

for(i=0; url[i]; i++) {
    var k = url[i].split('=');
    arg[k[0]] = k[1];
}

var id = arg.user_id;
```

#####css
なし


##文字列リンクを画像リンクに差し替える
#####Javascript
```javascript
$(function() {
  var ele = $("#scriptWPQ3 tbody td:nth-of-type(6)");
  ele[0].innerHTML = '<img src="/sites/jphgt4743/SiteAssets/document_download.png">';
  ele[1].innerHTML = '<img src="/sites/jphgt4743/SiteAssets/document_download.png">';
});
```

#####css
```css
#scriptWPQ3 tbody td:nth-of-type(6) img {
  width: 23px;
}
```


##複数行のHTMLコンテンツをJavaScriptファイルに記述する
#####Javascript
```javascript
  ele[0].innerHTML = (function () {/*
      <div>
        <span>Hello World!</span>
      </div>
    */}).toString().replace(/(\n)/g, '').split('*')[1];

```

#####css
なし

##標準パーツのリストのセルテキストをspanタグで囲む
#####Javascript
```javascript
  $(".ms-listviewtable tbody tr td:nth-of-type(3)").wrap('<td class="ms-cellstyle ms-vb2"><span class="analysis-request approval-pending"></span></td>');
  $(".ms-listviewtable tbody tr td:nth-of-type(3) span td").contents().unwrap();
```

##指定の要素のそのままで　タグを挿げ替える／タグを外す

####属性は無視していいなら
例）

```html
<h1 class="test">Hello World!</h1>
↓
<p>Hello World!</p>
```

#####Javascript
```javascript
$('h1').replaceWith(function() {
  $(this).replaceWith("<p>"+$(this).text()+"</p>")
});
```

####ID属性とCLASS属性は引き継いで
例）

```html
<h1 class="test">Hello World!</h1>
↓
<p class="test">Hello World!</p>
```

#####Javascript
```javascript
$('h1').replaceWith(function() {
  var tag_class = $(this).attr("class");
  var tag_id = $(this).attr("id");
  
  if ( tag_class == null) {
    var tag_class_plus =[];
  } else {
    var tag_class_plus = 'class="'+tag_class+'"';
  }
  if ( tag_id == null ) {
    var tag_id_plus =[];
  } else {
    var tag_id_plus = 'id="'+tag_id+'"';
  }
  $(this).replaceWith('<p '+tag_id_plus+'  '+tag_class_plus+'>'+$(this).html()+'</p>');
});
```

##GETパラメータによって読み込むCSSを切り替える
```javascript
  jQuery(function(){
    var arg  = new Object;
    url = location.search.substring(1).split('&');
   
   for(i=0; url[i]; i++) {
       var k = url[i].split('=');
       arg[k[0]] = k[1];
   }
   
    var stylename="";
    if(arg.user_id==1) {
      stylename = '../../SiteAssets/samplemanage_02.css';
    } else {
      stylename = '../../SiteAssets/samplemanage_03.css';
    }
      var link_style = $('<link>').attr({
        'rel': 'stylesheet',
        'href': stylename
      });
      $('body').append(link_style);
  });
```

##要素の囲い込み
#####マッチする要素をそれぞれ囲む
#####html
```html
<div class="hoge">
    <span>span</span>
    <span>span2</span>
    <b>b</b>
</div>
```
#####Javascript
```javascript
$( '.hoge span' ).wrap( '<p></p>' );
```
#####実行結果
```html
<div class="hoge">
    <p><span>span</span></p>
    <p><span>span2</span></p>
    <b>b</b>
</div>
```

#####マッチする要素の子要素を囲む
#####html
```html
<div class="hoge">
    <span>span</span>
    <span>span2</span>
    <b>b</b>
</div>
```
#####Javascript
```javascript
$( '.hoge' ).wrapInner( '<p></p>' );
```
#####実行結果
```html
<div class="hoge">
    <p>
        <span>span</span>
        <span>span2</span>
        <b>b</b>
    </p>
</div>
```

#####マッチする要素を1つにまとめて囲む
#####html
```html
<div class="hoge">
    <span>span</span>
    <span>span2</span>
    <b>b</b>
</div>
```
#####Javascript
```javascript
$( '.hoge span' ).wrapAll( '<p></p>' );
```
#####実行結果
```html
<div class="hoge">
    <p>
        <span>span</span>
        <span>span2</span>
    </p>
    <b>b</b>
</div>
```

##複数行のステータスラベル装飾
```javascript
  var elements = $(".ms-listviewtable tbody tr td:nth-of-type(3)");
  for (var i = 1; i <= elements.length; i++) {
    var label = $(".ms-listviewtable tbody tr:nth-of-type(" + i + ") td:nth-of-type(3)")[0].innerText;
    $(".ms-listviewtable tbody tr:nth-of-type(" + i + ") td:nth-of-type(3)")
      .wrap('<td class="ms-cellstyle ms-vb2"><span class="' + window.CommonUtil.getAnalysisRequestStatusClassName(label) + '"></span></td>');
    $(".ms-listviewtable tbody tr:nth-of-type(" + i + ") td:nth-of-type(3) span td").contents().unwrap();
  }
```

##SelectBoxのラベル化
IE11もサポートしたやり方
Javascript

```javascript
  // タスクの状態のラベル化と装飾
  $(".AnalysisPlanStatus select").attr("disabled", "disabled");
  $(".AnalysisPlanStatus select").addClass(window.CommonUtil.getAnalysisPlanStatusClassName($(".AnalysisPlanStatus select").val()));
```
CSS

```css
.AnalysisPlanStatus  select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

.AnalysisPlanStatus ::-ms-expand {
  display: none;
}
.AnalysisPlanStatus ::-ms-value {
  color: black;
}
```


##フォーム登録や編集画面のボタンクリック時の遷移先制御

#####保存ボタン
URLのクエリーパラメータ「Source」に遷移先を指定するやり方でしかうまく動かなかった。
つまり、遷移元からSourceをつけて画面を呼び出すようにした。

```javascript
//新しいアイテム登録ボタン
function newItemButtonclick() {
  location.href = "../Lists/AnalysisRequestList/frmAnalysisRequestRegist.aspx" + 
                  "?Source=" + location.href.replace(location.origin, "");
}
```

（ボツ）
保存時の組み込みコールバック”PreSaveAction"で、aspnetForm.actionに遷移先URLを追加することで制御できる記事があり試してみたが、遷移はするが保存されなかった。

```javascript
function PreSaveAction() {
  var args = window.CommonUtil.getQueryParams();
  window.CommonUtil.actionUrlOverride({リダイレクト先});
  return true;
}

window.CommonUtil.actionUrlOverride = function (newSrcUrl) {
  var srcUrl=GetSource();
  var i = aspnetForm.action.lastIndexOf(srcUrl);
  aspnetForm.action = aspnetForm.action.substring(0,i) + newSrcUrl ;
}
```


#####キャンセルボタン
クエリーパラメータなしでリダイレクトするだけなら元々の「SharePoint:GoBackButton 」にRedirectUrl属性で指定すればよい。

```html
  <SharePoint:GoBackButton runat="server" ControlMode="Edit" id="gobackbutton2" RedirectUrl="{リダイレクト先}" />
```

ただし、クエリーパラメータありの場合はRedirectUrlに展開させる方法がわからなかったので、自前でbuttonを作ってonclick属性でJavascriptの関数を呼び出すようにして対応した。（保存と違ってサーバ側の処理を期待しないからできるやり方だろう。)

```html
  <input runat="server" id="gobackbutton2" type="button" value="キャンセル" onclick="javascript:cancelRedirect()"/>
```

```javascript
//キャンセルボタンの遷移
function cancelRedirect() {
  location.href = window.CommonUtil.getSiteBaseUrl() + "/SitePages/A-01.aspx?function_id=A-01";
}
```

##スクリプトによるカスタムリストの検索
Javascript

```javascript
//本処理
function searchTest() { 
  var clientContext = new SP.ClientContext('/sites/xxxxxx');
  var oList = clientContext.get_web().get_lists().getByTitle('DeviceSchedule');
  this.oListItem = oList.getItemById(1);
  clientContext.load(oListItem, 'Title');
  clientContext.load(oListItem, 'Category');
  clientContext.load(oListItem, 'Equipment');
  clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
//成功時コールバック
function onQuerySucceeded() {
  var listItemInfo = '';
  listItemInfo += '\nタイトル: ' + oListItem.get_item('Title') + 
    '\nカテゴリ: ' + oListItem.get_item('Category') + 
    '\n使用する装置（型式）: ' + oListItem.get_item('Equipment').get_lookupValue();
    alert(listItemInfo.toString());
  }
  //失敗時コールバック
  function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
  }
```

##スクリプトによるカスタムリストの更新
Javascript

```javascript
//本処理
function ayastatusupdate() { 
  var clientContext = new SP.ClientContext('/sites/xxxxxx');
  var oList = clientContext.get_web().get_lists().getByTitle('AnalysisRequestList');
  this.oListItem = oList.getItemById(2);
  oListItem.set_item('RequestStatus', '測定中');
  oListItem.update();
  clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
//成功時コールバック
function onQuerySucceeded() {
  alert('Item updated!');
}
//失敗時コールバック
function onQueryFailed(sender, args) {
  alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
```

##ヘッダーやフッターの挿入
Javascript

```javascript

(function () {
  //header     
	_header_content=(function () {/*
    <div class="common-header">
      <table>
        <tbody>
          <tr>
            <td class="main-title">
              <span>ヘッダータイトル</span>
            </td>
            <td rowspan="2" class="logo">
              <img src="{ヘッダーロゴイメージ}" />
            </td>
          </tr>
          <tr>
            <td class="under-title">
              <span>ヘッダーサブタイトル</span>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
     */}).toString().replace(/(\n)/g, '').split('*')[1];
  $("#titleAreaRow > div.ms-breadcrumb-box.ms-tableCell.ms-verticalAlignTop").html(_header_content);
  //footer
	_footer_content=(function () {/*
    <div class="common-footer">
      <img src="{フッターロゴイメージ}" />
    </div>
     */}).toString().replace(/(\n)/g, '').split('*')[1];
  $("#s4-workspace").append(_footer_content);

})();
```
css

```css
/*  ヘッダー  */
.common-header {
  background: #2F62AD;
  width: 100%;
  display: block;
  height: 64px;
}

#titleAreaBox {
  margin: initial;  
}

#s4-titlerow {
  padding-top: initial;
  padding-bottom: initial;
}

.common-header > table {
  width: 100%;
}

.common-header .main-title {
  text-align: center;
}

.common-header .main-title span {
  color: white;
  font-size: 3rem;
  font-family: 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ Pro W3', Meiryo, メイリオ, Osaka, 'MS PGothic', arial, helvetica, sans-serif;
  line-height: 40px;
  position: relative;
  top: 10px;
}

.common-header .under-title {
  text-align: right;
}

.common-header .under-title span {
  line-height: 13px;
  color: white;
  font-size: 0.8rem;
  font-family: 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ Pro W3', Meiryo, メイリオ, Osaka, 'MS PGothic', arial, helvetica, sans-serif;
}

.common-header .logo {
  width: 100px;
}

.common-header .logo img {
  height: 60px;
}

/*  フッター  */
.common-footer {
  background: #2F62AD;
  width: 100%;
  display: block;
  text-align: center;
}

.common-footer img {
  margin: 3px 0;
  height: 20px;
}

#s4-bodyContainer {
  min-height: calc(100vh - 129px) !important;
}
```