スポンサーリンク

【pleasanter】編集画面にボタンを追加の実践例~ボタン表示・非表示、日付・ユーザーのセット~

プリザンター
スポンサーリンク
※当サイトは広告を含みます

事務パートのおばちゃんが挑むプリザンター開発。
前回は編集画面でボタンを表示したり非表示にしたり、をやりました。
今回は、その続きで、実践例をやってみたいと思います。
プリザンターで日付欄は yyyy/mm/dd hh:mm:ss 形式の文字列で取り扱うようなので、javaScript での日付時刻を文字列形式に変換する方法についても詳しく記載しています。

※おことわり
2023年5月時点の情報です。プリザンターのバージョンは 1.3.20.0 です。Google Chrome でやっています。
javascript,html,cssともに初心者です。調べながら、やってみながら、きっとこうすればいいんだ!という感じで書いていますので、間違っている場合、効率的な書き方ではない可能性が大いにあります。間違ってるよ!とか、こうしたほうがいいよ!ということがありましたら、コメント等で教えていただけると大変ありがたいです。

1.実践例の内容

以下の流れのものを作ってみたいと思います

1)日付の横に「確認」ボタンを表示
2)「確認」ボタンを押したら
 ①日にち欄に今日の日付を入力
 ②ログインユーザーを確認者欄に入力
 ③状況欄を「確認済」に変更
 ⑤「確認」ボタンを非表示にする

2.使用するサイト、完成イメージ

こんな感じ。

確認者:分類A。エディタの項目設定で、選択肢一覧に [[Users]] を指定しておく。
※ [[Users]] を指定しておくと、サイトの閲覧権限のあるユーザーがプルダウンリストにセットされます。
公式マニュアル https://pleasanter.org/manual/table-management-choices-text-users

確認日:日付A。エディタの項目設定で、エディタの書式に「日付と時刻(分)」を指定しました。日付項目でエディタの書式「年月日」を設定すると 2022/5/13 が表示されます。「日付と時刻(分)」だと 2022/5/13 14:22 、「日付と時刻(秒)」だと 2022/5/13 14:22 :22 のように表示されます。公式マニュアル https://pleasanter.org/manual/table-management-editor-format

状況:状況。900に「確認済」を設定しています。

3.コード

//関数定義//
//関数①
const fnDateFormat= function (d) {
    let d2 = d.toLocaleString("ja-JP", {
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit"
    });
    return d2.slice(0,16);
}
//②関数
const fnKakunin =function () {
    const userId = $p.userId();
    const d = fnDateFormat(new Date());
    $p.set($('#Results_ClassA'),userId);
    $p.set($('#Results_DateA'),d);
    $p.set($('#Results_Status'),'900');
    $('#kakunin').hide();   
}

//③処理
$p.events.on_editor_load = function () { 
    if ($('#Results_Status').val() !== '900' ) {
        $('#' + $p.getField('DateA')[0].id).after('<button type="button" onclick="fnKakunin()" id="kakunin" style="float: left;">確認</button>');    
    }
}

余談ですが、今回は、ごく短い処理なので、関数定義を最初にしてしまって上の方に持ってきています。

const fn1 = function () { 処理 }
と関数を変数名に入れて定義する場合は、関数を使用するコードより上にないとダメなのです。
function fn2 () { 処理 }
と関数を定義した場合は、関数を使用するコードより下にあっても大丈夫です。

(例)
fn1() //エラーとなる
const fn1 = function () { 処理 }
fn1() //エラーにならない

fn2() //エラーにならない
function fn2 () { 処理 }
fn2() //エラーにならない

私は「こうゆう処理をしているよ」というのがなるべく一目でわかる用がよいので、ごちゃごちゃした処理は関数にまとめて、主処理のコードは短く、また、関数は主処理部分とは別にまとめて置いておく方が好きです。主処理部分で「こうゆうことをやっている」という大まかな流れを読みとり、細かいことが知りたければ関数部分を読む、と。

で、上にまとめて書く方がよいのか、下にまとめるほうがいいのか、使用場所の近くにばらばらに書くのがよいのか。一般的にはどのようにするのがおススメなんでしょうね。呼び出しするコードより下に書いていても大丈夫、というのは javaScript 特有らしいので(vbaでもそうだから私は違和感なかった)、上に書く方がおススメと書いてある記事を見かけたような気がしますが。。。でも、関数部分が多すぎて主処理部分がしたーの方になってしまうのもやだから、うーーん、下にまとめるほうがいいのかなあ。。。

あ、あくまで私の好みの問題です。

4.コードの解説

下の方から解説しますね。。。③処理の部分から。

(1)処理の部分の解説

//③処理
$p.events.on_editor_load = function () { 
    if ($('#Results_Status').val() !== '900' ) {
        $('#' + $p.getField('DateA')[0].id).after('<button type="button" onclick="fnKakunin()" id="kakunin" style="float: left;">確認</button>');    
    }
}

$p.events.on_editor_load = function () { ここに処理 }

これはもう何度もやってきました。編集画面を立ち上げるときに走ってほしい処理をここに書きます。
公式マニュアル
https://pleasanter.org/manual/script-events-on-editor-load

if ($(‘#Results_Status’).val() !== ‘900’ ) { ここにボタンを表示する処理 }

状況欄が900(確認済)ではない場合、ボタンを表示する処理を書きます。

$(‘#’ + $p.getField(‘DateA’)[0].id).after(‘<button type=”button” onclick=”fnKakunin()” id=”kakunin” style=”float: left;”>確認</button>’);

ちょっと長いですが。日付Aの横にボタンをタグを挿入する、ということを書いています。

分けて解説しますと。

まず、挿入するhtml
‘<button type=”button” onclick=”fnKakunin()” id=”kakunin” style=”float: left;”>確認</button>’

buttonタグを使用します。onclick には関数定義した fnKakunin を指定しています。
ボタンをクリックすると fnKakunin が実行されます。

id には kakunin を指定しています。表示したり非表示にしたりするときに、id があると要素の指定が容易で便利です。

編集画面内にボタンを追加するについて、詳しくはこちらの記事でやっています

【pleasanter】スクリプトでhtmlの追加 リンクやボタンを編集画面に表示する ~実践例あり~ 

次に、
$(‘#’ + $p.getField(‘DateA’)[0].id).after

これは
$(‘#Results_ClassAField’).after
と同じ意味になります。
$p.getField は、対象の項目名からFieldを取得するメソッドです。$p.getField(‘DateA’)[0].id でフィールドのidを取得し、#とつなげています。

なんとなく、使ってみたかったので、このようにしています。
それと、テーブルには「記録テーブル」と「期限付きテーブル」がありますが、項目のidがその二つでは異なります。

たとえば、分類Aの項目idは
記録テーブルでは Results_ClassA 、期限付きテーブルでは Issues_ClassA
分類Aの項目のフィールドのidは
記録テーブルでは Results_ClassAField 、期限付きテーブルでは Issues_ClassAField

$p.getField や $p.getControl を使用することで、期限付きテーブルであっても記録テーブルであってもスクリプトの id 部分を書き換えなくてよいコードとなります。
コードのコピペによる使いまわしを考えている場合は、この手法を使うと便利ですね。

たとえば、以下のコードは期限付きテーブルでも記録テーブルでも有効です。

//分類Aの横に「テキスト」を追加
$('#' + $p.getField('ClassA')[0].id).after('<div style="float:left">テキスト</div>');
//分類Aの値に200を設定
$p.set($p.getControl('ClassA'),'200');
//分類Aの値を取得
let value = $p.getControl('ClassA').val();
console.log(value);

$p.getField や $p.getControlを使用しない場合は、記録テーブルではid部分が#Results_となります。

//分類Aの横に「テキスト」を追加
$('#Results_ClassAField').after('<div style="float:left">テキスト</div>');
//分類Aの値に200を設定
$p.set($('#Results_ClassA'),'200');
//分類Aの値を取得
let value = $('#Results_ClassA').val();
console.log(value);

期限付きテーブルではid部分が#Issues_となります。

//分類Aの横に「テキスト」を追加
$('#Issues_ClassAField').after('<div style="float:left">テキスト</div>');
//分類Aの値に200を設定
$p.set($('#Issues_ClassA'),'200');
//分類Aの値を取得
let value = $('#Issues_ClassA').val();
console.log(value);

なお、要素を取得する場合には $p.getControl(‘ClassA’) のようにすればよいのですが、要素のidを取得したいときは $p.getControl(‘ClassA’)[0].id のように配列の0番目のidといった書き方になります。

公式マニュアル $p.getField $p.getControl
https://pleasanter.org/manual/script-get-field
https://pleasanter.org/manual/script-get-control

(2)ボタンクリック時の関数の解説

②関数の解説です。(ここでは$p.getControl使わないんかい、という突っ込みはしないでください(*‘∀‘) やっぱり、ちょっと読むのが大変になるように思うんですよね)

//②関数
const fnKakunin = function () {
    const userId = $p.userId();
    const d = fnDateFormat(new Date());
    $p.set($('#Results_ClassA'),userId);
    $p.set($('#Results_DateA'),d);
    $p.set($('#Results_Status'),'900');
    $('#kakunin').hide();   
}

上から順に解説します。

const userId = $p.userId();

ログインしているユーザーのIDを取得し、変数 userId に代入しています。
$p.userId は、ログインしているユーザのユーザIdを取得するプリザンターの関数です。
https://pleasanter.org/manual/script-user-id

const d = fnDateFormat(new Date());

後述する fnDateFormat 関数で今日の日付を変数 d に代入しています。
fnDateFormat は自作の関数です。日付型の日付を yyyy/mm/dd hh:nn 形式のテキストに変換して返します。後述の(3)で解説します。
現在の日時は new Date() で取得します。
new Date()をそのまま引数として突っ込んでいますが、
let today = new Date();
console.log(today);
等としてコンソールを確認してみると、Dateのイメージがつかみやすいかと思います。
Dateについては以下のサイト等を参考としてください。
https://www.sejuku.net/blog/30171

$p.set($(‘#Results_ClassA’),userId);

取得した userId を分類A(確認者)にセットしています。
分類Aの選択肢一覧には [[Users]] を設定しているため、ユーザーIDをセットすることにより、氏名が表示されます。
選択肢一覧には [[Users]] を設定していない場合、ユーザーIDがそのまま表示されます。

分類Aのhtmlイメージ

$p.set($(‘#Results_DateA’),d);

日付Aに現在の日時をyyyy/m/dd hh:nn 形式で取得しておいた変数 d をセットしています。

日付項目にはテキスト形式で日時を入れなければならないらしく、new Date() 等、生の日付データをそのまま突っ込むとなにも表示されません。
$p.set($(‘#Results_DateA’),new Date());   //これはNG

$p.set($(‘#Results_Status’),’900′);

状況欄に 900 (確認済) を設定します。

$(‘#kakunin’).hide();

「確認」ボタンを非表示にしています。

ボタンにidを指定しておいたので、id名 kakunin で要素を指定しています。

なお、
$(‘#kakunin’).remove();
とすると、指定した要素自体を取っ払います。
出したり消したりではなく、また、自分で作成したボタンであれば、取っ払っちゃってもいいのかもしれませんね。

(3)日付をyyyy/mm/dd hh:mm のテキストにする関数

const fnDateFormat= function (d) {
    let d2 = d.toLocaleString("ja-JP", {
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit"
    });
    return d2.slice(0,16);
}

色々調べてみて、これがなんかかっこいいと思ったので toLocaleString を利用してみました。
こちらのサイトで勉強させていただきました。
https://www.javadrive.jp/javascript/date_class/index3.html
https://js.studio-kingdom.com/javascript/date/to_locale_string

日付のテキスト変換についてはこちらの記事で詳しくやっています
【javaScript】日付をテキストにする方法(初心者のメモ帳)

Date オブジェクトのインスタンスメソッドである toLocaleString は Date オブジェクトが持つ日付と時刻の値を指定したロケールの形式で文字列として返します。 toLocaleDateString は日付の情報を、 toLocaleTimeString は時刻の情報をそれぞれ指定したロケールの形式で文字列として返します。

引用元:https://www.javadrive.jp/javascript/date_class/index3.html

で?ロケール形式って何?

ロケール
別名:ロカール
【英】locale
ロケールとは、国や地域の文化によって異なる言語や単位、表記などの総称である。

ロケールとして扱われる単位は、尺度、暦、通貨や日時の並ぶ順序などがある。ソフトウェアの他言語への対応(ローカライズ)が行われる際には、言語の翻訳だけでなく、その国の文化に根ざした様々な表記法に対応する必要がある。

引用元:https://www.sophia-it.com/content/%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB

ロケールとは、時刻と日付の表現、数値表現、通貨表現、文字分類、大文字小文字変換、照合などを決定する、データ・フォーマット規則のセットです。

引用元:https://www.ibm.com/docs/ja/iis/11.7?topic=works-locales

ロケール形式とは・・・?ローカルな形式(地元の表現方法?)での表記方法ということでしょうか。。。
例えば通貨なんかは \100 は日本ロケール形式、$100 はアメリカとかその辺形式。
日付だと、日本は 2022/5/1、アメリカは 5/1/2022、フランスは1.5.2022 等。

toLocalString を使ってみました。例えばこのようにしてみると。

let d = new Date();
console.log(d);
d1 = d.toLocaleString('JP');
console.log(d1);

コンソールには以下のように表示されました。

1行目がそんまんま(Dateオブジェクト型?vba風にとらえると日付時刻型・・・)
2行目がその日付をtoLocaleStringで日本型(JP)を指定して変換したもの。

ふむふむ。
ここで惜しいのがyyyy/m/d形式になっており、プリザンターは yyyy/mm/dd 形式で月や日にちを二けたにしたい。
その場合、オプションで二けたにしてね(2-digit)と指定すればよさそうです。
オプションは{}に年はどうする、月はどうするという形で指定していきます。

let d = new Date();
console.log(d);
let d1 = d.toLocaleString('JP');
console.log(d1);
let d2 = d.toLocaleString('JP',{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"});
console.log(d2);

いけました。3行目のやつが 2-digit 指定したやつです。

年や時刻はオプション指定なしの2行目でも思った通りに出ているから、月と日だけ指定すればよいのでは?と以下のようにやってみたら、

let d2 = d.toLocaleString('JP',{month:"2-digit",day:"2-digit"});
console.log(d2);

05/03
と、出ました。なるほど。オプションは出したいものは何かしら指定しなければいけないんですね。

自作のfnDateFormat関数では、秒まで指定して 2023/05/13 17:53:21 となるように指定しています。

最後の
d2.slice(0,16)
ではd2(つまり2023/05/13 17:53:21″) の 左から16文字を取り出す、としています。
今回は秒の部分が不要なので、秒の21をカットしているイメージです。

対象.sliice(開始位置,終了位置)と指定しますが、ちょっと注意が必要なのは最初の文字は1文字目ではなく、0文字目となります。0,1,2,3…というように数えます。終了位置はしていた文字数まで取り出すかと思いきや、指定文字位置の一つ手前まで取り出します。
“あいうえお”.slice(1,4) とすると、いうえ が取り出しされます。
sliceについてはこちらの記事が分かりやすかったです。
https://www.sejuku.net/blog/25488

toLocalString のオプションで second:”2-digit” を指定しなければ slice しなくてもよいのですが、秒まで出したいときもあるかもしれないため、関数を使いまわししやすいように関数内では一旦秒まででるようにしています。

なお、日付だけでいいんだよぅ、という場合は toLocaleDateString、時刻だけでいいんだよぅ、という場合は toLocaleTimeString が使えます。

let d = new Date();
let d1 = d.toLocaleDateString('JP');
console.log(d1);       //出力結果 2023/5/14
let d2 = d.toLocaleTimeString('JP');
console.log(d2);       //出力結果 1:05:03

(4)日時を yyyy/mm/dd hh:mm:ss で取得する別の方法

javaScriptでの日付時刻型(Dateオブジェクト)のyyyy/mm/dd形式への変換を調べてみると、toLocaleString より、別の方法の方がポピュラーなのかな?という感じがしました。

なので、別解もやってみます。
主にこちらの記事を参考とさせていただきました。
https://johobase.com/javascript-date-yyyymmdd-hhmmss/

const toDateFormat2 = function (myDate) {
    const y = myDate.getFullYear();
    const m = ('00' + (myDate.getMonth() + 1)).slice(-2);
    const d = ('00' + myDate.getDate()).slice(-2);
    const h = ('00' + myDate.getHours()).slice(-2);
    const n = ('00' + myDate.getMinutes()).slice(-2);
    const s = ('00' + myDate.getSeconds()).slice(-2);
    return y + '/' + m + '/' + d + ' ' + h + ':' + n + ':' + s;
}
let d1 = toDateFormat2(new Date());
console.log(d1); 

’00’ と取得した月や日を結合させて、slice(-2) で後ろから2文字を取り出ししています。
例えば、5月の場合 ’00’ + ‘5’ => ‘005’
‘005’ の後ろから2文字を取り出し=> ’05’
となります。

もう一つ注意する点は、getMonth で日付から「月」を取得しますが、なんと取り出した月は0始まりなので、1を足さないといけないんですね。

5.最後に

実際に使うには穴だらけの実践例です。。。次回はもうちょっと実際に使えそうな例をやってみたいと思います。

それにしても、日付時刻を yyyy/mm/dd 形式にするのが javaScript では結構大変なんだな、というのが驚きポイントでした。

エクセルの関数なら
=TEXT(NOW(),”yyyy/mm/dd hh:mm:ss”)

エクセルVBAなら
Format(Now(), “yyyy/mm/dd hh:nn:ss”)

で、いいのに!

6.参考文献 サイト

プリザンター公式マニュアル
https://pleasanter.org/manual/table-management-choices-text-users
https://pleasanter.org/manual/table-management-editor-format
https://pleasanter.org/manual/script-events-on-editor-load
https://pleasanter.org/manual/script-get-field
https://pleasanter.org/manual/script-get-control
https://pleasanter.org/manual/script-user-id

日付処理を使い倒す! JavaScriptのDate活用法を徹底解説。
https://www.sejuku.net/blog/30171

Dateオブジェクトの値を指定のロケール形式にした文字列で取得する
https://www.javadrive.jp/javascript/date_class/index3.html

.toLocaleString()
https://js.studio-kingdom.com/javascript/date/to_locale_string

【JavaScript入門】sliceで文字列や配列(Array)を切り抜く方法まとめ
https://www.sejuku.net/blog/25488

JavaScriptでyyyymmdd形式の日付とhhmmss形式の時刻を取得(変換)
https://johobase.com/javascript-date-yyyymmdd-hhmmss/

プリザンターボタンシリーズ(内部リンク)
【pleasanter】スクリプトでボタンを編集画面に追加する
【pleasanter】編集画面のボタンを表示したり非表示にしたりする~スタイル・スクリプトの利用~
【pleasanter】スクリプトでhtmlの追加 リンクやボタンを編集画面に表示する ~実践例あり~
【pleasanter】拡張HTML~フィールドの右(左)に追加テキストを表示、ボタンの表示

日付をテキスト変換する方法
【javaScript】日付をテキストにする方法(初心者のメモ帳)

コメント

タイトルとURLをコピーしました