SQLの窓

2016年05月18日


kintone で画像を表示する / PC と スマホで少し違います。PC ではスペース項目、スマホでは、スマホ用ヘッダスペースを使用します



一応動的に画像の HTML を組み込む方法は、『kintoneのレコード詳細ページからAmazon商品データを参照するテクニック』に記述されています。ただ、この解説ではスマホは対応していません。ですが、単純にコードから URL を作成して商品画像表示するだけならば、以下のようにすれば簡単に実装できます。

PC 用 JavaScript
// *****************************************
// (function(){実行コード})() は JavaSript 
// におけるブロックの実行
// *****************************************
(function() {
	"use strict";

	kintone.events.on('app.record.detail.show', function(event){

		// スペース
		var Space_LargeImg = kintone.app.record.getSpaceElement('Large_Image');
		// event 内のレコード情報より
		var No_Image = event.record.No_Image.value;

		// スペースのレイアウト幅を画像が超え無いようにする
		var image_css = '<style>.user_image {max-width: 200px; height: auto;}</style>';

		// 画像表示
		Space_LargeImg.innerHTML = image_css + '<img class="user_image" src="http://winofsql.jp/image/test/' + No_Image + '.png">';

	});

})();

フォームの編集で、画像表示用の『スペース』を設置しておきます。これは、PC でのみ有効で、設定できる内容は、JavaScript から参照できる 要素ID のみとなります。なので、ここは英数字で『Large_Image』と定義しています。また、画像が大きいとフォームレイアウトが崩れるので、固定で 200px に設定しています。





スマホ 用 JavaScript
// *****************************************
// (function(){実行コード})() は JavaSript 
// におけるブロックの実行
// *****************************************
(function() {
	"use strict";

	kintone.events.on('mobile.app.record.detail.show', function(event){

		// スマホ用ヘッダスペース
		var Space_LargeImg = kintone.mobile.app.getHeaderSpaceElement();
		// event 内のレコード情報より
		var No_Image = event.record.No_Image.value;

		// デバイスの最大幅を画像が超え無いようにする
		var image_css = '<style>.user_image {max-width: 100%; height: auto;}</style>';

		// 画像表示
		Space_LargeImg.innerHTML = image_css + '<img class="user_image" src="http://winofsql.jp/image/test/' + No_Image + '.png">';

	});

})();

スマホでは、スペース項目は使用できませんが、ヘッダの下を自由に使えるのでそこに画像を表示します。また、最大幅を 100% にする事によって、大きな画像は横幅いっぱいで、スマホの表示幅より小さい画像はそのまま表示されます。最初の一覧で表示される項目は、アプリの設定画面の『レコードタイトル』で選択します

  


関連する kintone ドキュメント

PC画面で使用できるAPI,スマートフォンのみで利用できるAPI,両方で利用できるAPIをまとめた表





posted by lightbox at 2016-05-18 14:34 | kintone | このブログの読者になる | 更新情報をチェックする

2016年05月06日


kintone JavaScript API で ルックアップ先が更新された場合の参照元を全て更新する

kintone のドキュメントは欲しいものを探しにくい欠点があるのですが、その中でも一番重要な『ルックアップの一括更新』について解説しているページのタイトルが『第11回 REST APIを利用したレコード更新』となっていて気がつきにくくなっている上に、少しバグっています(その通りに実装したら不具合が出た)

▼ 以下がこちらで作成したサンプルコードです。
// *****************************************
// (function(){実行コード})() は JavaSript 
// におけるブロックの実行
// *****************************************
(function() {
	"use strict";

	var target = null;
 
	// レコード一覧画面で更新した場合のイベント
	kintone.events.on('app.record.index.edit.submit', function(event) {

		console.log("レコード一覧画面の event オブジェクト");
		console.dir( event );

		// ルックアップを実装している対象 appid
		var appid = 23;
		// 今回更新したルックアップが参照している値
		// ※ 一般フィールドの場合、要重複不可設定
		var target = event.record.レコード番号R.value;

		var manager = new KintoneRecordManager;
		manager.getRecords(appid, target, function(records) {

			console.log("レコードの取得後のイベント");
			// 取得した全レコードの表示
			console.dir(records);

			// レコード取得後の処理
			updateLookup(appid, createPutRecords(records));
			// 空にしておかないと、次の UI での処理で残ってしまう
			KintoneRecordManager.prototype.records = [];
			KintoneRecordManager.prototype.offset = 0;

		});


	});

	// レコード編集画面
	kintone.events.on('app.record.edit.submit', function(event) {

		console.log("レコード編集画面の event オブジェクト");
		console.dir( event );

		// ルックアップを実装している対象 appid
		var appid = 23;
		// 今回更新したルックアップが参照している値
		// ※ 一般フィールドの場合、要重複不可設定
		var target = event.record.レコード番号R.value;

		var manager = new KintoneRecordManager;
		manager.getRecords(appid, target, function(records) {

			console.log("レコードの取得後のイベント");
			// 取得した全レコードの表示
			console.dir(records);

			// レコード取得後の処理
			updateLookup(appid, createPutRecords(records));
			// 空にしておかないと、次の UI での処理で残ってしまう
			KintoneRecordManager.prototype.records = [];
			KintoneRecordManager.prototype.offset = 0;

		});


	});
 
	// *****************************************
	// kintoneと通信を行うクラス
	// *****************************************
	var KintoneRecordManager = (function() {

		// これがこの中で作成される KintoneRecordManager
		function KintoneRecordManager() {
		}

		// プロパティの定義
		KintoneRecordManager.prototype.records = [];	// 取得したレコード
		KintoneRecordManager.prototype.limit = 2;		// 一回あたりの最大取得件数
		KintoneRecordManager.prototype.offset = 0;		// オフセット


		// すべてのレコード取得する メソッドの定義
		KintoneRecordManager.prototype.getRecords = function(appid, target, callback) {

			console.log("appid : " + appid);
			console.log("target : " + target);

			// kintone.api (REST APIリクエストを送信)
			kintone.api(
				// kintone REST APIのパス または kintone.api.urlで取得したURL
				kintone.api.url('/k/v1/records', true),
				// 使用するHTTPメソッド
				'GET',
				// APIに渡すパラメータ
				{
					app: appid,
					// 参照条件
					// ※ ここではフィールドコードを固定で定義するようにしています
					query: 'LUP_参照コード = "'+ target + '" ' + (' limit ' + this.limit + ' offset ' + this.offset)
				},
				// APIの呼び出しが成功したら実行されるコールバック関数
				// ※ function を return しているので、この中がコールバック処理です
				(function(_this) {
					return function(res) {

						console.log("kintone.api の callback が呼び出されました:" + appid + ":" + target);

						// ここからがコールバック処理
						var len;

						// KintoneRecordManager のプロパティに新しいレコードを追加
						Array.prototype.push.apply(_this.records, res.records);
						// 今回取得したレコード数
						len = res.records.length;

						console.log("今回取得したレコード数:" + len);

						// KintoneRecordManager のプロパティ全レコード数をセット
						_this.offset += len;

						// 読み込み件数制限付きで、全件読む方法
						if (len < _this.limit) { // まだレコードがあるか?

							// 全件読み込んだので、callback を呼び出す
							if (callback !== null) {
								callback(_this.records); // レコード取得後のcallback
							}
						}
						else {
							// まだレコードが残っているので、offset 以降を再度呼び出して処理する
							_this.getRecords(appid, target, callback); // 自分自身をコール
						}
					};
				// this は KintoneRecordManager なので、処理内の _this が KintoneRecordManager
				})(this)
			);
		};

		// この処理の中で作成した KintoneRecordManager 関数を外の KintoneRecordManager 変数に設定する事になります
		return KintoneRecordManager;
	})();


	// *****************************************
	// 更新用オブジェクトの配列を作成するメソッド
	// *****************************************
	function createPutRecords(records) {
		var putRecords = [];
		for (var i = 0, l = records.length; i < l; i++) {
			var record = records[i];
			putRecords[i] = {
				id: record['$id'].value,
				record: {
					"LUP_参照コード" : {
						value: record.LUP_参照コード.value
					}
				}
			};
		}

		// 更新用オブジェクトの配列
		console.dir("putRecords:" + putRecords);

		return putRecords;
	}

	// *****************************************
	// 更新用 API を呼び出すメソッド
	// *****************************************
	function updateLookup(appId, records) {
		// KintoneRecordManager.prototype.limit で割り切れるレコード数の場合
		// 最後に records.length == 0 で呼ばれる
		if ( records.length != 0 ) {
			kintone.api(

				// kintone REST APIのパス または kintone.api.urlで取得したURL
				kintone.api.url('/k/v1/records', true),
				// 使用するHTTPメソッド
				'PUT',
				// APIに渡すパラメータ
				{
					app: appId,
					records: records
				},
				function(resp) {
					// 更新完了時の処理
				}

			);
		}
	}

})();

オリジナルのソースコードからはとても解りにくいであろう、JavaScript 特有の記述が理解しやすいように記述してコメントを付加しています。

▼ 関連する API ページ
kintone.api と kintone.api.url
( その他 : kintone.api.urlForGet、kintone.getRequestToke )


要点

ここでは、参照するアプリ(テーブル)のレコード番号をキーに使用していますが、一般フィールドをキーとする場合、重複不可の設定が必要です。

レコード一覧画面で、直接変更する時と1レコードの表示にしてから変更する時とでは別々のイベント定義が必要です。

ルックアップを実装している対象 appid は現在一つだけ使用していますが、一般的な実装ではここは配列になるべきです。また、その場合は getRecords の完了部分で、次の呼び出しが必要になるので、それなりの改造とテストが必要になります。具体的には、全件読み込んだ後の callback を呼び出す部分で次の appid の呼び出しとなると思います。その場合、引数の appid は、他のプロパティと同様に、prototype で定義すれば良いと思います

参照(検索)用の フィールドコードを固定で定義して使用していますが、汎用的にするにはプロパティ定義か引数定義にします。

JavaScript では function を、処理を格納した変数や値の定義として多用します。例えば、無名 function の場合は return function(){} として処理を戻り値としたり、有名 function では、function name(){} として name という変数を定義してそれを return name として処理を戻り値として返したりしています。

▼ kintone.api.url では、最後のパラメータが省略されているので注意して下さい。
ゲストスペース内でtrueを指定する場合、REST APIの実行に必要なゲストスペース用のURIが返されます。
デフォルトはfalseです。


posted by lightbox at 2016-05-06 17:18 | kintone | このブログの読者になる | 更新情報をチェックする

2016年04月07日


kintone の開発者ライセンスを取得しました。一年有効で、見たところ4年ぐらい使えそうです

2016/4/7 : ルックアップのインポートの注意事項について追加
kintone のドキュメントはこちら



※ この本は、『開発者ライセンス』必要な人には必要無い本だとは思います


●● ● 様

「cybozu.com developer network」をご利用頂きましてありがとうございます。 
お申込みいただきましたサービスが利用可能な状態になりました。
( 一週間かかりました )

■ご使用方法
────────────────────────────────────────
以下のURLにアクセスして、サービスをご利用ください。

アクセスURL:https://ランダム文字列.cybozu.com
ログイン名:固定ユーザID
パスワード:初回パスワード
( ログイン後変更します )

ご利用ユーザー数:5ユーザー(固定ユーザ を除く)
ご利用期限:2020-12-31
( 4年使えそうな理由です )

■ご注意点
・ご利用できるサービスは、kintone のみとなります。
・開発者ライセンスは、kintoneのアプリケーション開発を目的として、ご利用いただけます。
 本運用、テクニカルサポートのご利用はできません。
・アクセスURLの変更、パスワードの再発行はできません。
・開発者ライセンスの発行は、申し込みの2,3営業日後になる場合がございます。
・ユーザー数 5、 ディスク容量 20GB の固定となり、変更はお受けできません。
・開発者ライセンスのお見積もり、ご発注はお受けできません。
・データリストアのサービスもお受けできません。
・cybozu.com Store の管理機能(IPアドレス制限、BASIC認証など)はご利用できません。
・開発者ライセンスをご利用中のユーザーさまは、テクニカルサポートサービスを利用することはできません。
 developer network のコミュニティをご利用ください。
・ライセンスの終了日はお申し込み日から1年後の月末となります。
 利用者から開発者ライセンスを終了する旨の通知がなされない限り、
 サービス提供期間の終了日からさらに1年間開発者ライセンスが更新されます。
 ライセンスの削除をご希望の方は、開発者ライセンスの終了前までにご連絡ください。


試用アカウントからの移行

kintoneシステム管理のアプリテンプレートで、既に作成したアプリからテンプレートを作成後ダウンロード(書き出す)して開発用アカウントでアプリ作成を『テンプレートから選ぶ』で移行できます。アプリ(この場合はスキーマというべきかな)とデータは別々で、データはアプリ画面から『ファイルに書き出す』でダウンロードファイルを作成してダウンロードします。







データインポート時の注意事項

レコード番号をキーにする場合、存在しないレコード番号がファイルのキーの列にあると、ファイルを読み込めません。レコード番号を追加してしまった場合は、読み込み時にチェックを外してキー扱いしないようにして読み込みます。



ルックアップしている項目のあるアプリーションへのインポートでは、ルックアップ先の照合項目を重複不可にしておく必要があります。これを考えた時、一般的なテーブル設計にのっとって、コードを重複不可にしておいて、照合をコードで行うようにエンドユーザに指導する必要がありますね。

重複不可にしていないルックアップデータをインポートしようとすると、ルックアップのコードと参照内容はインポートされませんが、その他の一般項目の内容は正しくインポートされます( インポートする際に警告が表示されますが、そんなに目立つ警告表示では無いので注意が必要です )



posted by lightbox at 2016-04-07 13:17 | kintone | このブログの読者になる | 更新情報をチェックする

2016年03月19日


kintone API のトークンを使った PHP コードの注意点

基本操作

これはセミナーとか行かないと直感的には失敗してしまいます。設定を変更したら最後に必ず「設定完了」ボタンをクリックして変更を確定させる必要があります



なので、トークンを生成して保存だけでは使え無いので注意です

▼ 以下、サイボウズ株式会社より返答された内容です
<作成手順> 
 1.アプリ右上の歯車マークより、アプリの設定画面を開きます。 
 
 2.画面下部の「詳細設定」をクリックします
 
 3.「APIトークン」をクリックします
 
 4.「生成する」をクリックします
 
 5.生成された APIトークンに対して、許可する操作のチェックボックス
    を選択します
 
 6. 画面左上の「保存」をクリックします
  
 7.「設定完了」をクリックします
 ※トークン作成後、アプリの設定画面にて、「設定完了」ボタンを
   押下する必要がございます。
API の呼び出し方のバリエーション HTTP ヘッダに Content-Type: application/json を指定すると、URL では無くデータとして送信する必要があります。以下のサンプルでは、curl では URL で渡すほうが簡単で解りやすいので Content-Type を指定していません。 PHP の環境 file_get_contents で API の URL を使用するには、php.ini で allow_url_fopen = On である必要があります。また、https を使用する為に、Windows では extension=php_openssl.dll が有効である必要があります。 curl を利用するには、Windows では extension=php_curl.dll が有効である必要があります ※ curl の オプションでの ssl の指定は、Windows(5.4.13) でも、WEB(5.4.45) でも必要ありませんでした
<?php
header( "Content-Type: text/html; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

print "<pre>";
 
// サブドメイン
$subDomain = "サブドメイン";
// トークン
$token = "トークン";
$apiURI = "https://" . $subDomain . ".cybozu.com/k/v1/records.json";

// リクエストヘッダ(1) : パラメータを json で渡す
$header1 = array(
	"Host: " . $subDomain . ".cybozu.com:443",
	"Content-Type: application/json",
	"X-Cybozu-API-Token: ". $token
);
// リクエストヘッダ(2) : パラメータを URL で渡す
$header2 = array(
	"Host: " . $subDomain . ".cybozu.com:443",
	"X-Cybozu-API-Token: ". $token
);

// アプリID
$appId = 1;
 
// *************************************
// HTTPコンテキスト1 ( content 指定 )
// *************************************
$context = array(
	"http" => array(
		"method" => 'GET',
		"header" => implode("\r\n", $header1),
		"content" => json_encode(array("app" => $appId))
	)
);
 
// REST API
$result = file_get_contents(
	$apiURI,
	false,
	stream_context_create($context) // コンテキストの生成
);
 
// 連想配列でダンプ出力 
var_dump( json_decode($result, true) );

print "--------------------------------------\n";

// *************************************
// HTTPコンテキスト2 ( content なし )
// *************************************
$context = array(
	"http" => array(
		"method" => 'GET',
		"header" => implode("\r\n", $header2)
	)
);
 
// REST API
$result = file_get_contents(
	$apiURI . "?app=" . $appId,
	false,
	stream_context_create($context) // コンテキストの生成
);
 
// 連想配列でダンプ出力 
var_dump( json_decode($result, true) );

print "--------------------------------------\n";

$curl = curl_init();
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_URL, $apiURI . "?app=" . $appId);

// *************************************
// http ヘッダ作成
// *************************************
$header = $header2;

curl_setopt($curl, CURLOPT_HTTPHEADER, $header);

// *************************************
// https 用 ( 無くても動作しています )
// *************************************
//curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
//curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);


// *************************************
// 送信
// *************************************
$result = curl_exec($curl);
if($result === false) {
	$json = json_decode("{}");
}
else {
	// echo 'Operation completed without any errors';
	$json = json_decode($result);
}
curl_close($curl);


// 連想配列でダンプ出力 
var_dump(json_decode($result, true));

print "</pre>";

?>


ログイン名 と パスワード を使用したサンプルは、サイボウズの REST APIの認証設定について にあります。
 


タグ:PHP kintone API
posted by lightbox at 2016-03-19 20:51 | kintone | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり