SQLの窓

2016年10月03日


jQuery で既存 table より Firebase Database のデータを作成する

サンプルページ


このページでは実際には更新できませんが、自分のスニペットをコピーして貼り付けて使用すると更新できます。このデータは Wikipedia にあるテーブルをデベロッパーツールでコピーして貼り付けたものです。欲しい行を限定したい場合は、先頭の TD に class="result" を入れておくというスタイルです。

二番目の処理は、TR の中に TD が無いので、JSON の中に jojo0 は作成されますが、値が空のオブジェクトとなるのでデーターベースにデータは作成されません

更新部分のソースコード
<script>

var jojo = { };

$(function(){

	$("#update1").on("click",function(){
		
		if ( confirm( config.authDomain + "へ更新しますか? \n(ルールで更新を許す必要があります)" ) ) {

			$(".result").each( function( idx ){
			
				jojo["jojo" + (idx+1) ] = {};
				
				$(this).parent().find("td").each( function( idx2 ){
				
					jojo["jojo" + (idx+1) ]["data" + idx2] = $(this).text();
				
				} );
				
			
			} );
			
			firebase.database().ref("jojo").set(jojo).then(
					function(){
						alert( "更新に成功しました" );
					}
			);

		}
	});

	$("#update2").on("click",function(){
		
		if ( confirm( config.authDomain + "へ更新しますか? \n(ルールで更新を許す必要があります)" ) ) {

			$("tr").each( function( idx ){
			
				jojo["jojo" + idx ] = {};
				
				$(this).find("td").each( function( idx2 ){
				
					jojo["jojo" + idx ]["data" + idx2] = $(this).text();
				
				} );
				
			
			} );
			
			firebase.database().ref("jojo").set(jojo).then(
					function(){
						alert( "更新に成功しました" );
					}
			);

		}
	});

	$("#update3").on("click",function(){
		
		if ( confirm( config.authDomain + "へ更新しますか? \n(ルールで更新を許す必要があります)" ) ) {

			$("tr").each( function( idx ){
			
				jojo["jojo" + idx ] = {};
				
				$(this).find("td,th").each( function( idx2 ){
				
					jojo["jojo" + idx ]["data" + idx2] = $(this).text();
				
				} );
				
			
			} );
			
			firebase.database().ref("jojo").set(jojo).then(
					function(){
						alert( "更新に成功しました" );
					}
			);

		}
	});

});

</script>
※ データベースルールを書き込み可能にしておく必要があります


タグ:jquery Firebase
posted by lightbox at 2016-10-03 02:17 | Comment(0) | Google | このブログの読者になる | 更新情報をチェックする

jQuery + Bootstrap(css) + mmenu : Firebase Database 参照と更新サンプル( 新規登録テンプレートより )

デモ( ログインはハンバーガメニューより選んで下さい )
 
※ 実際の更新はできません



新規登録テンプレートを元に、クラスメンバを修正する2会話のアプリケーションのサンプルです。新規登録と違う所は殆ど無く、データの存在チェックで内容を表示しています。
			// データベース参照
			var myFirebaseRef = firebase.database().ref('class/' + $("#key_fld").val() );

			// **************************************
			// データ存在チェック
			// **************************************
			myFirebaseRef.once('value', 
				function(snapshot) {

					if ( !snapshot.exists() ) {
						options.error( "データが存在しません" );
						return;
					}

					// 第二会話へ変更
					options.pass2();

					// フォーカス
					if ( !$.isMobile ) {
						$("#row2_fld").focus();
					}

					var user_data = snapshot.val();
		
					$("#row2_fld").val(user_data.name);
					$("#row3_fld").val(user_data.furi);
					$("#row4_fld").val(user_data.kyuyo);
					$("#row5_fld").val(user_data.sex);
					$("#row6_fld").prop( "checked", user_data.kanri );

				},
				function(error){
					$(".result").each(function(){
						$(this).next().text( error[ options[ $(this).prop("id") ].title ] );
					});
					options.error( "Firebase エラーです" );

					console.dir(error);
				}
			);
※ データの更新は、新規も修正も同じです。

左の画像は、toastr.js で表示されたエラーメッセージを表示したところですが、PC の場合は、ページ上部の中央に表示されます。

右の画像は、HTML の pattern 属性によるチェックが行われ、メッセージが表示されています。

データフォーマット



ソースコード

ダウンロードパッケージの中は、php としてテンプレート化されています。メインのコードは、view_main.php で、index.php から読み込まれます。
<?php
// *************************************
// セッション変数
// *************************************
session_start();

// *************************************
// ブラウザに対する指示
// *************************************
header( "Content-Type: text/html; charset=utf-8" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "x-ua-compatible: IE=11" );

require_once("view_main.php");
?>


view_main.php
<?php
// *************************************
// 表示コントロール
// *************************************
$GLOBALS['title'] = "2会話・テンプレート(修正)";
$GLOBALS['comment'] = 'ようこそ jQuery + Bootstrap(css) + mmenu + Firebase';

?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport">
<meta charset="utf-8">
<title><?= $GLOBALS['title'] ?></title>

<?php require_once('../std/libs.php') ?>

<link rel="stylesheet" href="../std/mmenu.css">
<link rel="stylesheet" href="../std/basic.css">

<?php require_once('../std/firebase.php') ?>

<style>
.fields {
	width: 90px;
	font-size: 12px;
	vertical-align: middle!important;
}

legend {
	font-size: 18px;
	padding-left: 6px;
}
</style>

<script>
<?php require_once('../std/js.php') ?>
var options = {
	key : { title :"クラス", css : { width : "100px" }, attr : { pattern : "[0-9]+", type: "tel" } },
	row2 : { title : "氏名"  },
	row3 : { title : "フリガナ"  },
	row4 : { title : "給与", attr : { pattern : "[0-9]+", type: "tel" } },
	row5 : { title : "性別", css : { height : "40px" } },
	row6 : { title : "管理者", label : "部下の有無"  },
	row_last : { title :"メッセージ" },
	erow1 : { title : "code"  },
	erow2 : { title : "message"  },

	curbtn: "",
	pass1 : function(){
		// 第一会話へ変更
		$("#form_head").prop("disabled", false );
		$("#form_body").prop("disabled", true );
	},
	pass2 : function(){
		// 第二会話へ変更
		$("#form_head").prop("disabled", true );
		$("#form_body").prop("disabled", false );
	},
	clear : function(){
		// 全てクリア
		$(".fields").next().find("input[type='text'],input[type='tel']").val("");
		$(".fields").next().find("input[type='checkbox']").prop("checked", false);
		$(".fields").next().find("select").prop("selectedIndex", 0);
	},
	error : function(message){
		$("#row_last").next().text( message );
		toastr.error(message);
	},
	info : function(message){
		$("#row_last").next().text( message );
		toastr.success(message);
	}
};

$(function(){

	// 1) options による行とフィールドの設定
	// 2) Bootstrap 用 form-control クラスの追加
	$(".fields").each(function(){
		if ( options[ $(this).prop("id") ] ) {
			$(this).text( options[ $(this).prop("id") ].title );
			// 個別 css
			if ( options[ $(this).prop("id") ].css ) {
				$(this).next().find("input,select").css( options[ $(this).prop("id") ].css );
			}
			// 入力チェック用属性
			if ( options[ $(this).prop("id") ].attr ) {
				$(this).next().find("input,select").attr( options[ $(this).prop("id") ].attr );
			}
			// 行内個別 ラベル
			if ( options[ $(this).prop("id") ].label ) {
				$(this).next().find("label").text( options[ $(this).prop("id") ].label );
			}
		}
		// Bootstrap form
		$(this).next().find("input,select").addClass("form-control");
	});
	// スマホでロード時の処理のチラつき防止用
	$("#wrapper").css("visibility","visible"); 

	// 第一会話
	options.pass1();

	// 初期フォーカス
	setTimeout( function(){$('#key_fld').focus();}, 100 );

	// 確認処理
	$("#frm").submit( function(event){
		// 本来の送信処理はキャンセル
		event.preventDefault();

		// エラーメッセージエリアをクリア
		$(".error").next().text( "" );

		// 確認ボタン
		if ( options.curbtn == "button_head" ) {

			// **************************************
			// 第一会話入力チェック
			// **************************************
			if ( $("#key_fld").val().trim() == "" ) {
				options.error( options['key'].title + " を入力して下さい" );
				return;
			}

			// **************************************
			// Firebase ログインチェック
			// **************************************
			user = firebase.auth().currentUser;
			if ( user == null ) {
				options.error( "ログインされていません" );
				return;
			}

			// データベース参照
			var myFirebaseRef = firebase.database().ref('class/' + $("#key_fld").val() );

			// **************************************
			// データ存在チェック
			// **************************************
			myFirebaseRef.once('value', 
				function(snapshot) {

					if ( !snapshot.exists() ) {
						options.error( "データが存在しません" );
						return;
					}

					// 第二会話へ変更
					options.pass2();

					// フォーカス
					if ( !$.isMobile ) {
						$("#row2_fld").focus();
					}

					var user_data = snapshot.val();
		
					$("#row2_fld").val(user_data.name);
					$("#row3_fld").val(user_data.furi);
					$("#row4_fld").val(user_data.kyuyo);
					$("#row5_fld").val(user_data.sex);
					$("#row6_fld").prop( "checked", user_data.kanri );

				},
				function(error){
					$(".result").each(function(){
						$(this).next().text( error[ options[ $(this).prop("id") ].title ] );
					});
					options.error( "Firebase エラーです" );

					console.dir(error);
				}
			);

		}

		// 更新ボタン
		if ( options.curbtn == "button_body" ) {

			// **************************************
			// 第ニ会話入力チェック
			// **************************************
			if ( $("#row2_fld").val().trim() == "" ) {
				options.error( options['row2'].title + " を入力して下さい" );
				return;
			}

			// **************************************
			// Firebase ログインチェック
			// **************************************
			user = firebase.auth().currentUser;
			if ( user == null ) {
				options.error( "ログインされていません" );

				alert("第一会話へ移動します");

				// 第一会話へ変更
				options.pass1();

				return;
			}

			// データベース参照
			var myFirebaseRef = firebase.database().ref('class/' + $("#key_fld").val() );

			// **************************************
			// データ存在チェック
			// **************************************
			myFirebaseRef.once('value', function(snapshot) {

				if ( !snapshot.exists() ) {
					options.error( "データが存在しません" );

					alert("第一会話へ移動します");

					// 第一会話へ変更
					options.pass1();

					return;
				}

				if ( !confirm("更新してよろしいですか?") ) {
					return false;
				}

				// **************************************
				// 更新
				// **************************************
				// 更新用 JSON
				var update_data = {
					"code" : $("#key_fld").val(),
					"name" : $("#row2_fld").val(),
					"furi" : $("#row3_fld").val(),
					"kyuyo" : $("#row4_fld").val(),
					"sex" : $("#row5_fld").val(),
					"kanri" : $("#row6_fld").prop("checked")
				}
				// 更新
				myFirebaseRef.set(update_data).then(
					function(){

						options.info( "更新に成功しました" );

						// 第一会話へ変更
						options.pass1();

						// 全てクリア
						options.clear();

						// フォーカス
						$("#key_fld").focus();

					},
					function(error){
						$(".result").each(function(){
							$(this).next().text( error[ options[ $(this).prop("id") ].title ] );
						});
						options.error( "Firebase エラーです" );

						console.dir(error);
					}
				);

			});

		}

	} );

	// **************************************
	// mmenu
	// **************************************
	$("#mmenu_left").mmenu({
		navbar: {
			title: "メニュー"
		},
		offCanvas: {
			position  : "left",
			zposition : "next"
		}
	});


});

</script>
</head>
<body>

<div id="wrapper">
<script>
// スマホでロード時の処理のチラつき防止用
$("#wrapper").css( "visibility", "hidden" );
</script>

	<div id="head">
		<?php require_once('../std/view_hamburger.php') ?>
		<div id="title"><?= $GLOBALS['title'] ?></div>
	</div>

	<div id="body">
		<form id="frm" class="form-inline">

			<fieldset id="form_head">
				<table class="table table-condensed">
			
					<tr>
						<td class="fields" id="key"></td>
						<td>
							<div class="input-group">
								<input type="text" id="key_fld" name="key_fld">
								<button id="button_head" type="submit" class="btn btn-primary btn-sm m-l" onclick="options.curbtn=this.id">確認</button>
							</div>
						</td>
					</tr>
			
				</table>

			</fieldset>

			<fieldset id="form_body">
				<table class="table table-condensed">
			
					<tr>
						<td class="fields" id="row2"></td>
						<td>
							<input type="text" id="row2_fld" name="row2_fld">
						</td>
					</tr>
					<tr>
						<td class="fields" id="row3"></td>
						<td>
							<input type="text" id="row3_fld" name="row3_fld">
						</td>
					</tr>
					<tr>
						<td class="fields" id="row4"></td>
						<td>
							<input type="text" id="row4_fld" name="row4_fld">
						</td>
					</tr>

					<tr>
						<td class="fields" id="row5"></td>
						<td>
							<select name="row5_fld" id="row5_fld">
								<option value="0">男性</option>
								<option value="1">女性</option>
							</select>
						</td>
					</tr>

					<tr>
						<td class="fields" id="row6"></td>
						<td>
							<div class="input-group">
								<label for="row6_fld">有り無し</label>
								<input
									type="checkbox"
									id="row6_fld"
									name="row6_fld">
							</div>
						</td>
					</tr>

					<tr>
						<td></td>
						<td>
							<button id="button_body" type="submit" class="btn btn-primary btn-sm" onclick="options.curbtn=this.id">更新</button>
							<button
								type="button"
								class="btn btn-primary btn-warning btn-sm m-l-lg"
								value="キャンセル"
								 onclick='location="index.php"'>キャンセル</button>
						</td>
					</tr>


					<tr>
						<td class="fields error" id="row_last"></td>
						<td></td>
					</tr>
			
				</table>

			</fieldset>

			<fieldset>
				<legend>Firebase エラー</legend>
				<table class="table table-condensed">

					<tr><td class="fields result error" id="erow1"></td><td></td></tr>
					<tr><td class="fields result error" id="erow2"></td><td></td></tr>

				</table>

			</fieldset>

		</form>
	</div>

	<div id="comment">
	<?= $GLOBALS['comment'] ?>
	</div>

</div>


<?php require_once('unit_menu.php') ?>


</body>
</html>


minimum-scale=1.0 maximum-scale=1.0 user-scalable=no は、スマホで mmenu を表示する場合に必要です。

25行目の width: 90px; で、フィールドのタイトル幅が決定します。

options.curbtn は、submit ボタンが submit 前に click イベントで自身の id をセットし、どのボタンで submit されたか判定する為にあります。(314行 と 371行)

スマホでのロード時のちらつきを、$("#wrapper").css( "visibility", "hidden" ); で、画面表示を消していますが、JavaScript が無効の場合に画面がなくならないように、JS で非表示にしています。元々、addClass("form-control"); を後から jQuery  で設定する為に発生するちらつきですが、画面定義に一様にクラス設定してしまうと汎用性に欠けると思ったのでそうしました。

関連する記事

jQuery + Bootstrap(css) + mmenu : Firebase ログインテンプレート

jQuery + Bootstrap(css) + mmenu : Firebase 新規登録テンプレート




posted by lightbox at 2016-10-03 00:33 | Comment(0) | Google | このブログの読者になる | 更新情報をチェックする

2016年10月02日


jQuery + Bootstrap(css) + mmenu : Firebase Database 新規登録テンプレート

2019/10/02 : テンプレートを変更しました

1) toastr.js を追加し、それに伴ってメッセージ表示をメソッド化して options に追加しました。

2) iPhone5 のサイズに合わせて、入力フィールドのタイトル幅を 90px に変更しました。
2019/10/01 : テンプレートを変更しました

1) HTML のチェックを使用できるように、form の submit イベントで処理した上で、submit しないようにしています。

2) options に、画面コントロール用の共通関数を追加しました

3) スマホ画面でちらつかないように、初期画面を非表示にして画面作成完了後に表示するようにしました

4) JavaScript のモバイルチェックを追加し、スマホで画面が隠れるフォーカス処理はしないようにしました。

5) ソースコードのインデントを減らし、可読性を上げる為に、エラーチェック等ではすぐ脱出するようにして、else をなくすようにしました。
デモページ ※ 0001 のデータが存在しています ▼ 以下のテンプレートのデモページでログインして、更新以外をテストできます jQuery + Bootstrap(css) + mmenu : Firebase ログインテンプレート このログインユーザは Database のルールで更新できないようにしています。この設定は、コンソールから直接 check ツリーのデータを変更する事によって、更新可能へと変更できます。
{
  "rules": {
      ".read": "root.child('check').hasChild(auth.uid)",
      ".write": "root.child('check').child(auth.uid).child('isAdmin').val() == true"
    }
}



テンプレートの構造と機能の概要を印刷する PDF

ソースコード

<!DOCTYPE html>
<html lang="ja">
<head>
<meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport">
<meta charset="utf-8">
<title>2会話・テンプレート(新規)</title>

<script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link id="link" rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/themes/base/jquery-ui.css">
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery.mmenu/5.5.3/core/js/jquery.mmenu.min.all.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jQuery.mmenu/5.5.3/core/css/jquery.mmenu.all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.js"></script>

<link rel="stylesheet" href="../std/mmenu.css">
<link rel="stylesheet" href="../std/basic.css">

<script src="https://www.gstatic.com/firebasejs/3.4.0/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "AIzaSyD9vub84g_ckSvglTzMdLjXe1TV6WC8LCo",
    authDomain: "lightbox-1c915.firebaseapp.com",
    databaseURL: "https://lightbox-1c915.firebaseio.com",
    storageBucket: "lightbox-1c915.appspot.com",
    messagingSenderId: "694762121907"
  };
  firebase.initializeApp(config);
</script>

<style>
.fields {
	width: 90px;
	font-size: 12px;
	vertical-align: middle!important;
}

legend {
	font-size: 18px;
	padding-left: 6px;
}
</style>

<script>
jQuery.isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
toastr.options={"closeButton":false,"debug":false,"newestOnTop":false,"progressBar":false,"positionClass":"toast-bottom-center","preventDuplicates":false,"onclick":null,"showDuration":"300","hideDuration":"1000","timeOut":"3000","extendedTimeOut":"1000","showEasing":"swing","hideEasing":"linear","showMethod":"fadeIn","hideMethod":"fadeOut"}
if ( !$.isMobile ) {
	toastr.options.positionClass = "toast-top-center";
}
var options = {
	key : { title :"キー項目", css : { width : "80px" }, attr : { pattern : "[0-9]+", type: "tel" } },
	row2 : { title : "明細A"  },
	row3 : { title : "明細B"  },
	row4 : { title : "明細C", attr : { pattern : "[0-9]+", type: "tel" }  },
	row5 : { title : "選択", css : { height : "40px" } },
	row6 : { title : "チェック"  },
	row_last : { title :"メッセージ" },
	erow1 : { title : "code"  },
	erow2 : { title : "message"  },

	curbtn: "",
	pass1 : function(){
		// 第一会話へ変更
		$("#form_head").prop("disabled", false );
		$("#form_body").prop("disabled", true );
	},
	pass2 : function(){
		// 第二会話へ変更
		$("#form_head").prop("disabled", true );
		$("#form_body").prop("disabled", false );
	},
	clear : function(){
		// 全てクリア
		$(".fields").next().find("input[type='text'],input[type='tel']").val("");
		$(".fields").next().find("input[type='checkbox']").prop("checked", false);
		$(".fields").next().find("select").prop("selectedIndex", 0);
	},
	error : function(message){
		$("#row_last").next().text( message );
		toastr.error(message);
	},
	info : function(message){
		$("#row_last").next().text( message );
		toastr.success(message);
	}
};

$(function(){

	// 1) options による行とフィールドの設定
	// 2) Bootstrap 用 form-control クラスの追加
	$(".fields").each(function(){
		if ( options[ $(this).prop("id") ] ) {
			$(this).text( options[ $(this).prop("id") ].title );
			// 個別 css
			if ( options[ $(this).prop("id") ].css ) {
				$(this).next().find("input,select").css( options[ $(this).prop("id") ].css );
			}
			// 入力チェック用属性
			if ( options[ $(this).prop("id") ].attr ) {
				$(this).next().find("input,select").attr( options[ $(this).prop("id") ].attr );
			}
		}
		$(this).next().find("input,select").addClass("form-control");
	});
	// スマホでロード時の処理のチラつき防止用
	$("#wrapper").css("visibility","visible"); 

	// 第一会話
	options.pass1();

	// 初期フォーカス
	setTimeout( function(){$('#key_fld').focus();}, 100 );

	// 確認処理
	$("#frm").submit( function(event){
		// 本来の送信処理はキャンセル
		event.preventDefault();

		// エラーメッセージエリアをクリア
		$(".error").next().text( "" );

		// 確認ボタン
		if ( options.curbtn == "button_head" ) {

			// **************************************
			// 第一会話入力チェック
			// **************************************
			if ( $("#key_fld").val().trim() == "" ) {
				options.error( options['key'].title + " を入力して下さい" );
				return;
			}

			// **************************************
			// Firebase ログインチェック
			// **************************************
			user = firebase.auth().currentUser;
			if ( user == null ) {
				options.error( "ログインされていません" );
				return;
			}

			// データベース参照
			var myFirebaseRef = firebase.database().ref('class/' + $("#key_fld").val() );

			// **************************************
			// データ存在チェック
			// **************************************
			myFirebaseRef.once('value', 
				function(snapshot) {

					if ( snapshot.exists() ) {
						options.error( "データが既に存在します" );
						return;
					}

					// 第二会話へ変更
					options.pass2();

					// フォーカス
					if ( !$.isMobile ) {
						$("#row2_fld").focus();
					}

				},
				function(error){
					$(".result").each(function(){
						$(this).next().text( error[ options[ $(this).prop("id") ].title ] );
					});
					options.error( "Firebase エラーです" );

					console.dir(error);
				}
			);

		}

		// 更新ボタン
		if ( options.curbtn == "button_body" ) {

			// **************************************
			// 第ニ会話入力チェック
			// **************************************
			if ( $("#row2_fld").val().trim() == "" ) {
				options.error( options['row2'].title + " を入力して下さい" );
				return;
			}

			// **************************************
			// Firebase ログインチェック
			// **************************************
			user = firebase.auth().currentUser;
			if ( user == null ) {
				options.error( "ログインされていません" );

				alert("第一会話へ移動します");

				// 第一会話へ変更
				options.pass1();

				return;
			}

			// データベース参照
			var myFirebaseRef = firebase.database().ref('class/' + $("#key_fld").val() );

			// **************************************
			// データ存在チェック
			// **************************************
			myFirebaseRef.once('value', function(snapshot) {

				if ( snapshot.exists() ) {
					options.error( "データが既に存在します" );

					alert("第一会話へ移動します");

					// 第一会話へ変更
					options.pass1();

					return;
				}

				if ( !confirm("更新してよろしいですか?") ) {
					return false;
				}

				// **************************************
				// 更新
				// **************************************
				// 更新用 JSON
				var update_data = {
					"code" : $("#key_fld").val(),
					"name" : $("#row2_fld").val(),
					"furi" : $("#row3_fld").val()
				}
				myFirebaseRef.set(update_data).then(
					function(){

						options.info( "更新に成功しました" );

						// 第一会話へ変更
						options.pass1();

						// 全てクリア
						options.clear();

						// フォーカス
						$("#key_fld").focus();

					},
					function(error){
						$(".result").each(function(){
							$(this).next().text( error[ options[ $(this).prop("id") ].title ] );
						});
						options.error( "Firebase エラーです" );

						console.dir(error);
					}
				);

			});

		}

	} );

	// **************************************
	// mmenu
	// **************************************
	$("#mmenu_left").mmenu({
		navbar: {
			title: "メニュー"
		},
		offCanvas: {
			position  : "left",
			zposition : "next"
		}
	});


});

</script>
</head>
<body>

<div id="wrapper">
<script>
// スマホでロード時の処理のチラつき防止用
$("#wrapper").css( "visibility", "hidden" );
</script>

	<div id="head">
		<a id="hamburger" href="#mmenu_left">
	<span class="top-bar"></span>
	<span class="middle-bar"></span>
	<span class="bottom-bar"></span>
</a>
		<div id="title">2会話・テンプレート(新規)</div>
	</div>

	<div id="body">
		<form id="frm" class="form-inline">

			<fieldset id="form_head">
				<table class="table table-condensed">
			
					<tr>
						<td class="fields" id="key"></td>
						<td>
							<div class="input-group">
								<input type="text" id="key_fld" name="key_fld">
								<button id="button_head" type="submit" class="btn btn-primary btn-sm m-l" onclick="options.curbtn=this.id">確認</button>
							</div>
						</td>
					</tr>
			
				</table>

			</fieldset>

			<fieldset id="form_body">
				<table class="table table-condensed">
			
					<tr>
						<td class="fields" id="row2"></td>
						<td>
							<input type="text" id="row2_fld" name="row2_fld">
						</td>
					</tr>
					<tr>
						<td class="fields" id="row3"></td>
						<td>
							<input type="text" id="row3_fld" name="row3_fld">
						</td>
					</tr>
					<tr>
						<td class="fields" id="row4"></td>
						<td>
							<input type="text" id="row4_fld" name="row4_fld">
						</td>
					</tr>

					<tr>
						<td class="fields" id="row5"></td>
						<td>
							<select name="row5_fld" id="row5_fld">
								<option value="27">大阪</option>
								<option value="26">京都</option>
								<option value="29">奈良</option>
							</select>
						</td>
					</tr>

					<tr>
						<td class="fields" id="row6"></td>
						<td>
							<div class="input-group">
								<label for="row6_fld">有り無し</label>
								<input
									type="checkbox"
									id="row6_fld"
									name="row6_fld">
							</div>
						</td>
					</tr>

					<tr>
						<td></td>
						<td>
							<button id="button_body" type="submit" class="btn btn-primary btn-sm" onclick="options.curbtn=this.id">更新</button>
							<button
								type="button"
								class="btn btn-primary btn-warning btn-sm m-l-lg"
								value="キャンセル"
								 onclick='location="index.php"'>キャンセル</button>
						</td>
					</tr>


					<tr>
						<td class="fields error" id="row_last"></td>
						<td></td>
					</tr>
			
				</table>

			</fieldset>

			<fieldset>
				<legend>Firebase エラー</legend>
				<table class="table table-condensed">

					<tr><td class="fields result error" id="erow1"></td><td></td></tr>
					<tr><td class="fields result error" id="erow2"></td><td></td></tr>

				</table>

			</fieldset>

		</form>
	</div>

	<div id="comment">
	ようこそ jQuery + Bootstrap(css) + mmenu + Firebase	</div>

</div>


<div id="mmenu_left">
<ul>
	<li class="mm_user_title">ページ選択</li>
	<li><a class="mm_link_left" href="#" onclick="location='index.php';void(0)">リセット</a></li>
	<li><a class="mm_link_left" href="https://lightbox.sakura.ne.jp/demo/firebase/static/pass1/index.php">ログイン</a></li>
	<li><a class="mm_link_left" href="#" onclick="firebase.auth().signOut()">ログアウト</a></li>
	<li><a class="mm_link_left" 
			href="http://getbootstrap.com/css/"
			onclick="location='index.php';void(0)"
			target="_blank"
		>Bootstrap(css)</a></li>
	<li><a class="mm_link_left"
			href="http://api.jquery.com/"
			onclick="location='index.php';void(0)"
			target="_blank"
		>jQuery ドキュメント</a></li>
</ul>
</div>


</body>
</html>


関連する記事

jQuery + Bootstrap(css) + mmenu : Firebase ログインテンプレート



posted by lightbox at 2016-10-02 22:31 | Comment(0) | Google | このブログの読者になる | 更新情報をチェックする

2016年10月01日


jQuery + Bootstrap(css) + mmenu : Firebase ログインテンプレート

2016/10/01 : IE 用に 縦スクロールバー用の設定を basic.css に追加しました
デモページ Bootstrap の css 部分のみ使用しています。なので、スマホでそのまま大差無く使用可能です。他ページへの移動や簡単な処理オプションの為、mmenu を使用して、スマホでも動作します。
ログイン情報の保持について Firebase の ログイン情報は localStorage に保存される為、ブラウザを閉じてもログインは保持されます。 テンプレートの mmenu と ハンバーガーアイコン部分 直接の動作とは関係無いので省いても問題はありません ( ソースコードの 13 〜 14 行, 118 〜 129 行, 142 〜 146 行, 220 〜 235 行 ) Firebase 実装部分 自分のコントロールパネルから『ウェブアプリに Firebase を追加』で取得可能な firebase.js と firebase.initializeApp( config ) 部分を該当部分に貼り付け直すだけです。 ( ソースコードの 17 〜 28 行 ) テンプレートの構造と機能の概要を印刷する PDF テンプレートの構造と機能の概要を印刷する PDF(ソースコードレベル) ソースコード

<!DOCTYPE html>
<html lang="ja">
<head>
<meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport">
<meta charset="utf-8">
<title>1会話・テンプレート(ログイン)</title>

<script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link id="link" rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/themes/base/jquery-ui.css">
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery.mmenu/5.5.3/core/js/jquery.mmenu.min.all.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jQuery.mmenu/5.5.3/core/css/jquery.mmenu.all.css">
<link rel="stylesheet" href="std/mmenu.css">
<link rel="stylesheet" href="std/basic.css">

<script src="https://www.gstatic.com/firebasejs/3.4.0/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "AIzaSyD9vub84g_ckSvglTzMdLjXe1TV6WC8LCo",
    authDomain: "lightbox-1c915.firebaseapp.com",
    databaseURL: "https://lightbox-1c915.firebaseio.com",
    storageBucket: "lightbox-1c915.appspot.com",
    messagingSenderId: "694762121907"
  };
  firebase.initializeApp(config);
</script>

<style>
.fields {
	width: 120px;
	font-size: 12px;
	vertical-align: middle!important;
}

legend {
	font-size: 18px;
	padding-left: 6px;
}
</style>

<script>
var options = {
	row1 : { title : "ユーザ", css: { "background-color": "azure", "font-weight": "bold" }  },
	row2 : { title : "パスワード"  },
	row3 : { title : ""  },
	row_last : { title :"メッセージ" },
	rrow1 : { title : "uid"  },
	rrow2 : { title : "email"  },
	rrow3 : { title : "emailVerified"  },
	rrow4 : { title : "displayName"  },
	rrow5 : { title : "isAnonymous"  },
	erow1 : { title : "code"  },
	erow2 : { title : "message"  }
};
var login_user_info = null;

$(function(){

	// 1) options による行とフィールドの設定
	// 2) Bootstrap 用 form-control クラスの追加
	$(".fields").each(function(){
		$(this).text( options[ $(this).prop("id") ].title );
		if ( options[ $(this).prop("id") ].css ) {
			$(this).next().find("input,select").css( options[ $(this).prop("id") ].css );
		}
		$(this).next().find("input,select").addClass("form-control");
	});


	// 初期フォーカス
	setTimeout( function(){$('#row1_fld').focus();}, 100 );

	// ログイン処理
	$("#login").on("click", function(){

		// 結果の表示エリアを全てクリア
		$(".result").next().text( "" );

		// 入力チェック
		if ( $("#row1_fld").val().trim() == "" ) {
			$("#row_last").next().text("ユーザを入力して下さい");
			return;
		}

		// **************************************
		// Firebase ログイン
		// **************************************
		var auth = firebase.auth();
		auth.signInWithEmailAndPassword($("#row1_fld").val(), $("#row2_fld").val())
		.then(
			// ログイン成功
			function( user ) {
				login_user_info = user;

				$(".result").each(function(){
					$(this).next().text( user[ options[ $(this).prop("id") ].title ] );
				});

				console.dir( user );

			},
			// ログイン失敗
			function( error ) {

				error["メッセージ"] = "ログインに失敗しました";

				$(".error").each(function(){
					$(this).next().text( error[ options[ $(this).prop("id") ].title ] );
				});

				console.dir( error );
			}
		);
	} );

	// **************************************
	// mmenu
	// **************************************
	$("#mmenu_left").mmenu({
		navbar: {
			title: "メニュー"
		},
		offCanvas: {
			position  : "left",
			zposition : "next"
		}
	});


});

</script>
</head>
<body>

<div id="wrapper">

	<div id="head">
		
<a id="hamburger" href="#mmenu_left">
	<span class="top-bar"></span>
	<span class="middle-bar"></span>
	<span class="bottom-bar"></span>
</a>
		<div id="title">1会話・テンプレート(ログイン)</div>
	</div>

	<div id="body">
		<form class="form-inline">

			<fieldset>
				<legend>ログイン</legend>
				<table class="table table-condensed">
			
					<tr>
						<td class="fields" id="row1"></td>
						<td>
							<input type="text" id="row1_fld" name="row1_fld" value="abc@test.jp">
						</td>
					</tr>
					<tr>
						<td class="fields" id="row2"></td>
						<td>
							<input type="text" id="row2_fld" name="row2_fld" value="20160828">
						</td>
					</tr>

					<tr>
						<td class="fields" id="row3"></td>
						<td>
							<input id="login" type="button" class="btn btn-primary btn-sm" value="送信">
						</td>
					</tr>

					<tr>
						<td class="fields error" id="row_last"></td>
						<td></td>
					</tr>

				</table>

			</fieldset>

			<fieldset>
				<legend>結果</legend>
				<table class="table table-condensed">

					<tr><td class="fields result" id="rrow1"></td><td></td></tr>
					<tr><td class="fields result" id="rrow2"></td><td></td></tr>
					<tr><td class="fields result" id="rrow3"></td><td></td></tr>
					<tr><td class="fields result" id="rrow4"></td><td></td></tr>
					<tr><td class="fields result" id="rrow5"></td><td></td></tr>

				</table>

			</fieldset>

			<fieldset>
				<legend>Firebase エラー</legend>
				<table class="table table-condensed">

					<tr><td class="fields result error" id="erow1"></td><td></td></tr>
					<tr><td class="fields result error" id="erow2"></td><td></td></tr>

				</table>

			</fieldset>

		</form>
	</div>

	<div id="comment">
	ようこそ jQuery + Bootstrap(css) + mmenu + Firebase	</div>

</div>


<div id="mmenu_left">
<ul>
	<li class="mm_user_title">ページ選択</li>
	<li><a class="mm_link_left" href="#" onclick="location='index.php';void(0)">リセット</a></li>
	<li><a class="mm_link_left" 
			href="http://getbootstrap.com/css/"
			onclick="location='entry.php';void(0)"
			target="_blank"
		>Bootstrap(css)</a></li>
	<li><a class="mm_link_left"
			href="http://api.jquery.com/"
			onclick="location='entry.php';void(0)"
			target="_blank"
		>jQuery ドキュメント</a></li>
</ul>
</div>


</body>
</html>



mmenu と hamburger アイコン設定
( mmenu.css )
#hamburger {
	vertical-align: bottom;
	border: 1px solid #999;
	display: inline-block;
	width: 50px;
	padding: 5px 10px;
	margin: 0 20px 0 8px;
}
#hamburger span {
	background: #999;
	display: block;
	height: 3px;
	margin: 5px 0;
}

html.mm-opened #hamburger span.top-bar {
	transform: rotate( 45deg );
	top: 8px;
}
html.mm-opened #hamburger span.middle-bar {
	opacity: 0;
	left: -40px;
}
html.mm-opened #hamburger span.bottom-bar {
	transform: rotate( -45deg );
	top: -8px;
}

#hamburger {
	overflow: hidden;
}
#hamburger span {
	position: relative;
	transform: rotate( 0 );
	top: 0;
	left: 0;
	opacity: 1;

	transition: none 0.5s ease;
	transition-property: transform, top, left, opacity;
}


.mm-menu {
	background-color: #DAEEF2;
	color: #444444;
}
.mm-title {
	color: #222222!important;
	font-size: 16px;
	font-weight: bold;
}
.mm_user_title {
	padding: 20px!important;
}


テンプレート用 CSS
( basic.css )
@charset "UTF-8";

* {
	font-family: Arial, Helvetica, Verdana, "ヒラギノ角ゴPro W3", "Hiragino Kaku Gothic Pro", Osaka, "メイリオ", Meiryo, "MS Pゴシック", sans-serif!important;
}

#head {
	background-color: #404040;
}
#title {
	color: white;
	display: inline-block;
	line-height:40px;
}

#body {
	margin: 20px 0 0 0;
}

td {
	word-break: break-all;
}

.error {
	background-color: #FFE8EC;
}

#comment {
	padding: 20px;
	border: solid 1px #ccc;
	margin: 40px;
	border-radius: 10px;
}

@-ms-viewport {
	width: auto;
}

関連する記事

jQuery + Bootstrap(css) + mmenu : Firebase Database 新規登録テンプレート



posted by lightbox at 2016-10-01 16:38 | Comment(0) | Google | このブログの読者になる | 更新情報をチェックする

2016年08月21日


Google ドライブの WEBホスティングが無くなったので、Google の Firebase をとりあえず使う方法

もう、【2016/8/31で廃止】であることは解っていたのですが、Google からメールが届きました。

IMPORTANT: Drive web hosting is shutting down

We announced last year that we're deprecating web hosting in Google Drive for users and developers. Our records show that you might have used this feature to publish a webpage or serve other web assets.

On Aug 31, 2016, we will discontinue serving content via googledrive.com/host/[id] and the webpages will not be accessible anymore.

As an alternative to web hosting in Drive, we recommend:

Blogger−An easy and free way to host websites.
Firebase Hosting− An alternative if you're using the web-hosting feature to serve static webpages with items on Drive.
で、試してみました。確かに普通に使えます。インターネットの情報はそれなりにありますが、無料プランの説明はちょっと古いものしか見つかりませんでした。結論から言って、『無料プランで独自ドメインが使用できます』 技術者が使用するのであれば、DB や Android でPush 通知などがすぐいろいろ試してみれると思うので、特に問題は無いですが(ドキュメントが英語というのはいつものことですが)、一般の人にはちょっとハードルが高いです。ただ、ホスティングのみをする目的で、Node.js をインストールしてコマンドプロンプトを使ってデプロイするという事は、FTP クライアント使うのとそう違わないのかなぁ・・という気もします。それどころか、ローカルに http://localhost:5000 のウェブサーバを使用して表示を確かめる事ができるので、そんなに悪くも無いのかなぁとも思いました。 インストール等手順 二つのアカウントと、3つのPC から試しました。これでいけると思います。画像がやたらと多くなるので、NAVER のシステムを使ってまとめました。 Firebase の使い方 / Google の 1 GB まで無料のホスティングサービス プロジェクトの作成もコマンドプロンプトからできるようですが、プロジェクトはブラウザから作成したほうがいいでしょう。そして、ブラウザであらかじめログインしておく事になるので、そのブラウザは規定のブラウザである必要があると思います。ログイン時にたぶん、規定のブラウザを使っていると思われるからです。 カスタムドメインは、自分の管理するドメイン側で、二つ TXT レコードを書き込む必要があります。これは、以前から Google が使用していた方法のようです。ただ、説明としてはサブドメインが使えるとあるのですが、自分がゾーン編集できるのはメインのドメインのみなので、試してはいません。 入力したとたん、TXT レコード が表示されて、そのエントリをすぐに削除できませんでした。仕方ないので一晩明けて見に行ったら『削除可能』になっていました。 コマンドプロンプトについて コマンドプロンプトに慣れている人にはいまさらですが、『簡易編集モード』に変更しておくと、コピーペーストが楽になります。ただ、インストール場所をデフォルトの Program Files にした場合、昨今変更できないので、『簡易編集モード』へ変更する為にデスクトップにショートカットを作成してから『簡易編集モード』に変更する事になります。 ▼ Windows10 の設定画面 また、Node.js 用にインストール時に Path 環境変数の先頭に文字列が追加されるので、これも知ってる人はいいですが、知らない場合は後で『あれ?』と思うかもしれません。 デプロイ エラーが出る可能性があるので、その場合はしばらくしてから再度実行が必要です。
posted by lightbox at 2016-08-21 23:01 | Comment(0) | Google | このブログの読者になる | 更新情報をチェックする

2016年08月06日


【2016/8/31で廃止】Google ドライブに HTML を置いて WEBページが作れる詳細 / Drive Notepad / Neutron Drive

Google ドライブにおけるウェブ ホスティング機能の廃止について

この機能は、Google の方針により、2016 年 8 月 31 日 で利用ができなくなります



▼ 以下古い記録になります
-----------------------------------------------------------------------------
こちらで利用方法を説明しています
SDK 的には、『webViewLink』という仮想ディレクトリによる公開
( access-control-allow-origin:* を返してくれるので ajax で取得できます )

https://googledrive.com/host/0B9Jymqpro6gSVlB5Wm52U29wTlE/base.htm
( https://googledrive.com/host/0B9Jymqpro6gSVlB5Wm52U29wTlE 部分が webViewLink )

関連する記事

Google ドライブの公開ページと管理ページを行ったり来たりする為のブックマークレット

▼ 昔は無かったのですが、現在ページ下に広告が出てしまいます。

Google+ のコメントを読んでいたら、Google ドライブの仮想ディレクトリの別名を作ってくれるサービスがある事が解りました。どの程度の信頼性があるか解りませんが、とりあえず作ってみました。

http://gdriv.es/winofsql/base.htm
( https://googledrive.com/host/0B9Jymqpro6gSVlB5Wm52U29wTlE/base.htm と同じ )

別名は早い者勝ち。こちらからです。

からくりは、ただのフレームです。ですから、アイコンの表示は gdriv.es のものになります。
正直言って、Google ドライブそのものがそれほど使いやすいものでは無いので、『できる』という事は間違い無いんですが、実際運用しようとなるといろいろあるので『面倒』な部分もあります。 例えば、同名ファイルのアップロードでは、同じファイルがもう一つ作成されますが、HTML 内よりそのファイルを参照していた場合参照できなくなります。 ですから、テキストデータの更新はオンラインで直接行う必要があるのですが、そのような事を実現するには、Google Chrome 拡張の Drive Notepad が必要になります( 現在他に選択肢がありません ) (重要) 新規作成時の拡張子でファイルの意味( MIME ) が決定してしまうようなので、注意して下さい( 拡張子変更しても変わりません )
追記 : ※ Google+ のコメントより、Neutron Drive という高性能なエディタがある事を知りました(但し、3週間の無料のトライアルで本来は年間3ドルの有料です。( フリーになっていました ) しかし、ツリーで管理できて、さらにテキスト毎にタブになるのでその価値はあります。)

It's free! However, if you would like to fund further development feel free to donate.
また、ファイルを右クリックしてホスティングされている URL で開いてくれるのが便利です 今回再確認したら、2013年の夏に FTP の対応を済ましていたようです。ただ、高性能のわりにユーザ数が少ないのは、当初有料にしていた影響なのか、内容が開発者向きなのかどちらかが理由では無いかと思っています。 ※ FTP は、有償のプロアカウントで使えるようです(詳しく調べて無いので詳細は不明です) ちょっと使ってみると自動保存である事が解るので、むやみにネットワークを混雑させない為に Auto Save のチェックは外しておいたほうがいいと思います。 以上はどこからでも使えるという運用ですが、自宅のみで使うのならば 『PC 用 Google ドライブ』をインストールすればほんの少しのタイムラグで普通に編集できます ただ、同期する為に PC のディスク容量とネットのトラフィックを多少犠牲にしなくてはいけません。また、個人 PC 以外でインストールするのは良くありません。
( Drive Notepad / ユーティリティカテゴリにあります ) しかし、この拡張アプリ(Drive Notepad)はかなり前から使っていますが、PC上で使う一般的なテキストエディタに比べるとまだまだ問題を抱えています。少なくとも現時点では、『作成されたファイルがルートにしか保存されない』という問題を確認しています。ですから、後から目的のフォルダへ移動処理を行わないといけません( ドラッグによる移動は可能です ) 現在そのような不具合はありません 以上を前提に、『Drive Notepad』を使って運用するという手順が以下のようになります。 ファイルのアップロード オンラインで更新を行うのは、仕方の無い場合のみという方向で、最初に HTML、CSS、画像等を用意してローカルの PC で動作確認を終えておきます。そして、ある程度公開可能になってからそのセットを Google ドライブのフォルダにアップロードします。 フォルダは、共有機能で『ウェブ上で一般公開』にする必要があります フォルダの作成 ウェブ上で一般公開 ※ フォルダを共有しないと公開できません 公開 URL の取得
※ 現在さらに長いサブドメインにリダイレクトされます

https://googledrive.com/host/xxxxxxxxxxxxxxxxxxxxxxx
▲ xxxxxxxxxxxxxxxxxxxxxxx の位置に、自分のアカウントで開いた時にアドレスバーに表示される id を設定してアドレスバーにセットして表示すると、WEB ページの仮想ディレクトリが表示されます。

https://drive.google.com/?authuser=0#folders/長いid文字列


もうちょっと具体的に 少し前は、Google ドライブビュアーというアプリが標準であって、HTML から使えたのですが、今はブックマークレットを使用するか、Neutron Drive を使用して『View File』を実行するといいと思います。 フォルダの中のファイル https://googledrive.com/host/0B9Jymqpro6gSVlB5Wm52U29wTlE/base.htm と言う URL になっている場合、0B9Jymqpro6gSVlB5Wm52U29wTlE 部分がこのフォルダにあたるので、同じフォルダの中にあるファイルを直接参照する場合は、例えばこのようにします。 さらに、フォルダ内のフォルダは階層で参照できますが、フォルダには全て ID があるので、それで直接参照しなおすと、URL は短くなります。 このようにして、必要なファイルをフォルダ内にアップロードして、HTML 内では直接参照すれば良いのですが、同名ファイルが複数あると参照できなくなるので注意して下さい。 tool.css と img.jpg は同じフォルダにあります。http://winofsql.jp/WinOfSql.ico は、アイコンの指定を外部ファイルで行っていますが、正しく動作しています。 Drive Notepad は、UTF-8 しか対応していないので、HTML 内の charset 指定は UTF-8 で行います。 別ドメインの JavaScript 最初にテストしたのですが、動きませんでした。画像を外部から参照は可能でしたが、開発者ツールでは警告のようなものが表示されていました。 『The page at https://googledrive.com/host/0B9Jymqpro6gSVlB5Wm52U29wTlE/base.htm displayed insecure content from http://別ドメイン/ファイル名.』 これは、https から http でアクセスした為ブロックされてしまっています。こんな経験は https のサイトを運用していないので解りませんよね・・・ 最後に Google なんで、突然(こっそり)仕様変更があったりや拡張アプリが動かなくなったり( 実際ありました )するので、Google ドライブはあまり一般ユーザ向けのサービスではありません。 実際問題、Google ドライブ向けの拡張アプリは使えるものは数少なく、日本語のものは当分手に入らないものと思います。仕様を調べてもさっぱり解らなかったりするのですが、現状使えているものが使えなくなる事は考えにくいので、このホスティング機能とはうまく付き合って有意義に利用すべきだと思います。 Google+ のコメントの前半は、PHP や MySQL が使いたいとか結構好きな事を言ってる人が居ました。後半は、いくつかの問題点やバグのような報告ですが、だいたいにおいてここに書いてある事で包括していると思います。 開発者向けのドキュメント Publish Website Conten : Google Drive SDK 正式発表は、Google+ のこのエントリ( 2/6 )。SDK の更新日付は 1/31 でした。 ▼ 英文のあちらの記事 Google Drive to support simple website publishing
posted by lightbox at 2016-08-06 14:43 | Google | このブログの読者になる | 更新情報をチェックする

2016年07月30日


Google サイト内検索の FORM 要素による設置

このブログの PC バージョンのページナビの右上にある検索入力です。この方法を使えば、他の特殊なキーワード文字を使った Google 検索フィールドも設置可能です。

Google の検索は現在では、『https://www.google.co.jp/search』に QueryString を渡す事で容易に実現できます。これは、当然 FORM 要素で行う一般的な WEBアプリケーションの機能です。FORM に対して method を指定しないこの呼び出しは、GET コマンドとなるので、通常のリンクの呼び出しと同じになります。

accept-charset は、無くても shift_jis では正しく動作しますが、euc-jp では化けるようです。また、utf-8 にすると、Google での アドレスバーで日本語部分が日本語として表示されます

複雑な検索文字列に対応する為に、検索文字列の入力は name 属性の無い送信されないフィールドで行い、本来必要な文字列作成を onsubmit イベントの中で行って、仕様に必要な name="q" のフィールドにセットして送信します。(name="q" のフィールドは type="hidden" で非表示です)

キャラクタセット指定
<script>
function callSearch() {

	var query = document.getElementById("q").value;
	if ( query.trim() != "" ) {
		query = query + " site:logicalerror.seesaa.net";
		document.getElementById("q_submit").value = query;
		return true;
	}

	return false;
}
</script>
<form
	accept-charset="utf-8"
	action="https://www.google.co.jp/search"
	target="_blank"
	onsubmit="return callSearch()">
<input
	type="text"
	id="q"
	size="31"
	maxlength="255"> 
<input
	type="hidden"
	id="q_submit"
	name="q"> 
<input
	type="submit"
	value="検索"> 
</form>



posted by lightbox at 2016-07-30 17:19 | Comment(0) | Google | このブログの読者になる | 更新情報をチェックする

2016年06月20日


ブラウザの geolocation で Google MAP に現在地を表示。ライブラリでさらに詳細情報。API の geocoder で名称・住所から Google MAP を表示して、ライブラリでさらに詳細情報を取得。

緯度・経度関連で、4つの機能を実装したデモページです


※ この デモは https でアクセスしますが、http でもアクセスできるので注意して下さい
※ http でアクセスした場合、Google Chrome では現在地を取得できません

1) navigator.geolocation.getCurrentPosition でブラウザの現在位置を取得
2) ライブラリ(DmGeocorder) を使用して緯度・経度から場所情報を取得
3) Google の API の geocoder.geocode で 住所・名前から緯度・経度を取得

4) Google Maps JavaScript API で MAP 表示

制限事項

Google Chrome ては、PC でも スマホでも、現在地取得には https を使うか localhost でないと動作しません。( 他のブラウザでは今のところ動作しているようですが、将来的には同じになる可能性があります )
事実、現在 Yahoo の雨雲ズームレーダでは、Chrome では現在位置が取れません。
通常のサイトで使用して、PC の開発者ツールで表示すると、以下のようにメッセージが出ます


getCurrentPosition() and watchPosition() are deprecated on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.
DmGeocorder は、自分でサーバに準備して使うものです。ですが、とりあえずデモ内で使用しているものに関して外部からの使用制限は設けていません。 Google Maps JavaScript API は、API コンソールで登録した APIKEY を使用し、使用するドメインを登録しているので他所では使用できません。 もし、他所で使用しようとすると以下のようになります デモのソースコード
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">

<style>
body,input {
	font-family: "ヒラギノ角ゴPro W3","Hiragino Kaku Gothic Pro","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif;
	font-size: 16px;
}

a {
	color: navy;
}

#target_area {
	width: 600px; 
	height: 480px; 
}
#address {
	margin-bottom: 10px;
	width: 450px;
}


@media screen and (max-width:774px) {

	#target_area {
		width: 100%; 
	}

	#address {
		width: 250px;
	}

}
</style>

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
// *************************************
// 初期位置
// *************************************
var lat = 34.7013233;
var lng = 135.4966954;

var geo = null;


$(function(){

	// *************************************
	// 現在位置を取得してマップに反映する
	// *************************************
	$("#getcur").on("click",function(){

		// *************************************
		// Chrome では、この実行には https か 
		// localhost である必要があります
		// *************************************
		navigator.geolocation.getCurrentPosition(function(target){
			geo = target;
			console.dir(target);

			var obj = {};

			for( value in target.coords ) {
				obj[value] = target.coords[value];
			}

			// ブラウザの geolocation で取得した内容
			$("#latlng").text( JSON.stringify(obj,null,"    ") );

			lat = geo.coords.latitude;
			lng = geo.coords.longitude;

			// Google MAP の再表示
			loadMap(document,"target_area",lat,lng,15);

			// サーバーのライブラリから場所情報を取得
			$.get("https://lightbox.sakura.ne.jp/toolbox/g_ken.php?lat="
				+geo.coords.latitude
				+"&lng="
				+geo.coords.longitude,
				function(data){
					console.dir(data);
					$("#latlng2").text( JSON.stringify(data,null,"  ") );
			
				}
			);
				
		});

	});

});

</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCQq2Yaz_ue8jVhf2LAQBlE73RJ17jd0tM"></script>
<script>
var geocoder = new google.maps.Geocoder();
var map;

$(function(){
	// *************************************
	// 住所・名前から位置情報を取得
	// *************************************
	$("#geo_action").on("click",function(){
		geocoder.geocode( {'address': $("#address").val()}, function(results, status) {
			if (status == google.maps.GeocoderStatus.OK) {
				map.setCenter(results[0].geometry.location);
				var marker = new google.maps.Marker({
					map: map,
					position: results[0].geometry.location
				});
				// lat と lng
				console.log(results[0].geometry.location.lat(),results[0].geometry.location.lng());

				// *************************************
				// サーバーのライブラリから場所情報を取得
				// *************************************
				$.get("https://lightbox.sakura.ne.jp/toolbox/g_ken.php?lat="
					+results[0].geometry.location.lat()
					+"&lng="
					+results[0].geometry.location.lng(),
					function(data){
						console.dir(data);
						$("#latlng2").text( JSON.stringify(data,null,"  ") );
				
					}
				);

			}
			else {
				alert("Geocode が失敗しました : " + status);
			}
		});
	});
});

// *************************************
// Google MAP の表示
// *************************************
function loadMap(doc,obj_str,a,b,c) {
	var latlng = new google.maps.LatLng(a,b);
	var myOptions = {
		zoom: c,
		center: latlng,
		mapTypeControlOptions: {
			mapTypeIds: [
				google.maps.MapTypeId.HYBRID,
				google.maps.MapTypeId.ROADMAP,
				google.maps.MapTypeId.SATELLITE
			],
			style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
		},
		mapTypeId: google.maps.MapTypeId.HYBRID,
		scaleControl: true
	};
	map = new google.maps.Map(doc.getElementById(obj_str),myOptions);
}

// *************************************
// 最初の Google MAP の表示
// *************************************
google.maps.event.addDomListener(window, 'load', function () {
	loadMap(document,"target_area",lat,lng,15);
}); 
</script>
</head>
<body>

住所 <input type="text" id="address"> <input type="button" id="geo_action" value="実行">
<div id='target_area'></div>
<br><br>
<input type="button" id="getcur" value="現在位置を取得してマップに反映する">

<br>
▼ ブラウザの geolocation で取得した内容
<pre id="latlng"></pre>
▼ <a target="_blank" href="https://github.com/demouth/DmGeocoder">ライブラリ</a>より取得した場所情報
<pre id="latlng2"></pre>


</body>
</html>


以下のツールで、スマホで簡単に URL を送る事ができます。



posted by lightbox at 2016-06-20 15:01 | Comment(0) | Google | このブログの読者になる | 更新情報をチェックする

2016年02月27日


Picasa が終了するので、Google フォトで登録した画像の URL を Picasa の API で取得する手順


※ この画像は Google フォトで登録して Picasa API で取り出した URL を使用しています

Picasa Web Albums Data API の【重要】を読む限り、読み込みはサポート続きそうなので、以下の方法でしばらく対応できると思います。内容は簡単なので、JavaScript でもアルバムとか作れそうですし。( access-control-allow-origin: * である事は確認しました )

自分の ユーザID

Picasa の設定ページでもいいですが、アルバムや画像を表示した時にドメインの次に表示される数字です。これを使うとまずアルバムの一覧を取得できます。

https://picasaweb.google.com/data/feed/api/user/101280392108947207617?alt=json

アルバムの IDとプロパティの絞込み

ほぼこれで目的は達成されます

https://picasaweb.google.com/data/feed/api/user/101280392108947207617/albumid/6125016770423395377?alt=json&fields=entry%28content%29&imgmax=1600

imgmax=1600 は、適当でいいです。s1600 となるだけなので後で調整しますし。最初から s500 が欲しいのならば、imgmax=500 とするだけです。fields パラメータは、省略すると全てのデータを取得できます(正直必要無いです)

これだけでは該当する画像から URL を取り出すのがたいへんなので、JavaScript で 1時間くらい格闘すれば自分専用の URL 取得アプリは簡単に作れそうです。


関連する記事

Picasa が終了するので、Picasa ブログの英文を解りやすく翻訳して整形しました

jQuery Columns を使って、Picasa API より アルバム一覧を表示する



タグ:google
posted by lightbox at 2016-02-27 14:19 | Comment(0) | Google | このブログの読者になる | 更新情報をチェックする

2016年02月25日


Picasa が終了するので、Picasa ブログの英文を解りやすく翻訳して整形しました

▼ オリジナル
Moving on from Picasa

※ 冗長部分は省いています

Googleフォトの発売以来、私たちは、これはPicasaの将来のために何を意味するのか多くの疑問を持っていました。多くを考慮した後、我々は、Googleフォトで写真サービスに完全に集中するために、今後数カ月でPicasaを終了することを決定しました。我々は二つの異なる製品間での努力を分けるのではなく、より多くの機能を提供し、モバイルとデスクトップ全体に働く一つのサービスに着目する事によってはるかに優れた体験を作成することができると信じています。

私たちは、あなたのコンテンツにアクセスする簡単な方法を提供します。私たちは、あなたが期待できる変更のいくつかを以下に概説しました。

Picasaウェブアルバム
あなたがPicasaウェブアルバム内の写真やビデオを持っている場合、アクセスするための最も簡単な方法は、Googleフォトにログインすることであり、すべてのあなたの写真や動画がすでに存在することになります。 Googleフォトを使用して、アップロードし、あなたの思い出を整理するだけでなく、あなたのイメージを検索し、共有する事ができます。

しかし、Googleフォトを使用したくない人々のために、私たちは、あなたがあなたのPicasaウェブアルバムにアクセスするための新しい場所を作成します。そうすれば、あなたはまだあなただけの(あなたが今Googleフォトでこれを行うことになる)、作成、整理、編集アルバムすることができなくなり、Picasaウェブアルバムを、ダウンロードを表示、または削除することができます。

明確にするべき事の一つは、今は Picasaウェブアルバムを持っているあなたは、通常のようにそれを使用し続けることができます。(当社は2016年5月1日にこれらの変更をロールアウト開始します)

デスクトップアプリケーション
2016年3月15日の時点で、我々はもはやPicasaデスクトップアプリケーションをサポートすることはありません。すでにこれを利用している人のために動作し続けますが、我々はそれを更に発展させず、将来のアップデートはありません。あなたがGoogleフォトに切り替えることを選択した場合、あなたはphotos.google.com/appsでデスクトップアップローダを使用して写真や動画をアップロードし続けることができます。

最後に、開発者のために、我々はまた、Picasa APIの一部の機能を終了します。

この移行がご迷惑をおかけして申し訳ございませんが、我々は、最高の可能な体験を提供することを目的にこれをやっていることを保証します。 Googleフォトは、私たちは将来的にあなたのための素晴らしい経験と機能を構築するための優れたプラットフォームを提供する新しい製品です。


関連する記事

Picasa が終了するので、Google フォトで登録した画像の URL を Picasa の API で取得する手順

jQuery Columns を使って、Picasa API より アルバム一覧を表示する

Picasa のサムネイルの使い方



タグ:google Picasa
posted by lightbox at 2016-02-25 11:34 | Comment(0) | Google | このブログの読者になる | 更新情報をチェックする

2016年02月19日


Picasa のサムネイルの使い方

Google が、Picasaを終わらせるようですが、以前よりGoogle フォトやGoogle+で同様のURLが使えていました。Google+ はすでにGoogle フォトに切り替わっていますので、今後はGoogle フォトの画像を右クリック等で取得する事になります。

但しこの方法では、Google の公式なものではないので、突然画像が表示出来なくなる可能性は覚悟する必要があります

▼ 古い仕様
画像 URL の基本仕様

1) 保存の画像形式(png、jpg等)はオリジナルの形式で保存される
2) s999 形式のサイズは長辺に適用される
3) s999 を省略すると適当な大きさになる
4) s999 は、実際の大きさを越えても実際の大きさにしかならない
( 実際のサイズは、Chrome ならばタイトルに表示されます )

現在では、s999 の後ろに -Ic42 が付加されていますが、当時に取得した URL は有効のままです(但し今の URL から -Ic42 を省く事はできません )。
また、Google+ では w999-rw-no と h999-rw-no が使えているので、w999-Ic42 と h999-Ic42 も使えます。これは、幅かあるいは高さを優先させてサムネイルを取得できます。但し、w と h を使う方法は公式ではありません。s999-Ic42 も公式のドキュメントはありませんが、Picasa のサービスの一つとして取得できる埋め込み URL 内で使用されているので、余程の仕様変更が無いかぎり使えるものと思います。
※ オリジナルサイズは、右サイドに表示されています ※ URL は、画像の情報から取得します( 顔部分は避けて下さい )
Picasa では、画像をアップロードすると、URL がパラメータとなってその大きい画像内の大きさの画像であれば自由な大きさの画像を供給してくれます。その場合のURL が QueryString ではなく URL そのもので構成されています。

例えば以下は、幅 128px ですが、オリジナル画像のは、1600×1200 なので、s1600 以内であれば自由自在です。
画像表示サンプル
<img src="http://lh6.ggpht.com/_IzfbcNjqGuE/S1jkKM952HI/AAAAAAAAAPU/CheJ6YkRGPM/s128/b15architecture_exteriors014.jpg" style='border:solid 1px #000000' />

▼ s200


▼ s400


▼ s555


関連する記事

jQuery Columns を使って、Picasa API より アルバム一覧を表示する

Picasa が終了するので、Picasa ブログの英文を解りやすく翻訳して整形しました

Picasa を使った、一枚の画像でサムネイルも兼ねる画像ウインドウの表示コード

コード取得ツール : 誰でも簡単に 画像を使った Shadowbox が使えます



タグ:google
posted by lightbox at 2016-02-19 13:11 | Google | このブログの読者になる | 更新情報をチェックする

2015年09月11日


Google+ に投稿するテキスト内の文字列を太字(ボールド)にしたりイタリックにしたりする方法







アスタリスクで文字列を挟むと*太字*になりますが、
アスタリスクの両端は *スペース* が必要です

イタリックには、アンダーバーを使用しますが、
日本語は _italic にならない_ ようです

どちらが外側でもいいですが、 _*italicと太字*_ は同時に利用可能です

取り消し線はハイフンを使用します
あああ -あああ- あああ

ボールドにしたい文字列を *(アスタリスク) で挟み、イタリックにしたい文字列を _(アンダーバー)で挟み、取り消し線を設定したて文字列を-(ハイフン)で挟みます。

※ * と _ と - の両外側にはスペースが必要なようです

公式での表記( 『投稿文の書式を設定する』を開いて下さい )



posted by lightbox at 2015-09-11 14:08 | Google | このブログの読者になる | 更新情報をチェックする

2015年01月23日


Google の Plus API を使って Google+ 投稿データを jQuery UI のアコーディオン(accordion)で表示する

アプリケーションを認証すると、以下のようになります。



一番上のブルーのメニューは、ログアウトや関連リンクをセットしてあります。下の黒いバーが jQuery UI のアコーディオンを使用して Google Plus の投稿データを表示しています。


▼ 実際のデモページです。
http://winofsql.jp/gapi/examples/page2.htm

page2.htm に IFRAME 内で接続用のリンクを用意しています。こうしておくと、どんなページにも簡単に接続リンクを追加できます。IFRAME 内は普通のリンクで、target="_top" になっています。

リンクには QueryString として初期ページと処理ページを渡して標準化しています。

page2.htm
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>

<iframe
	src="start.php?start=page2&action=main_action2"
	name="myframe"
	frameborder="0"
	scrolling="no"
	width="200"
	height="100"
></iframe>

</body>
</html>

▼ 接続リンクのあるページ
start.php
<?php
require_once("user_client.php");

$_SESSION['start'] = $_GET['start'];
$_SESSION['action'] = $_GET['action'];

$authUrl = $client->createAuthUrl();

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
</head>
<body style='background-color:#e0e0e0;'>
<a href="<?= $authUrl ?>" target="_top">接続</a>
<br><br><br>
ここは IFREAME です
</body>
</html>


▼ Google Plus の投稿情報を jQuery UI のアコーディオンとして
main_action2.php
<?php
require_once("user_client.php");

/************************************************
  アクセストークンがある場合
  但し、期限が切れている場合は再度取得する必要
  があるので、認証用の URL を作成する
 ************************************************/
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  if ($client->isAccessTokenExpired()) {
    unset($_SESSION['access_token']);
    header("Location: {$_SESSION['start']}htm");
    exit();
  }
}
/************************************************
  アクセストークンが無い場合
  認証用の URL を作成する
 ************************************************/
else {
    header("Location: {$_SESSION['start']}.htm");
    exit();
}

/************************************************
  目的 API の処理
 ************************************************/
$service = new Google_Service_Plus($client);

// タスクリストの一覧
try {
	$obj_activities = $service->activities->listActivities("me", "public");
}
catch(Exception $ex) {
	header('Location: logout.php');
	exit();
}

// タスクリストの配列として取得
$activities = $obj_activities->getItems();
?>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<link href="http://winofsql.jp/jquery/plugins/smartmenus/sm-core-css.css" rel="stylesheet" type="text/css" />
<link href="http://winofsql.jp/jquery/plugins/smartmenus/sm-blue.css" rel="stylesheet" type="text/css" />

<style type="text/css">
#main-menu {
	margin-top: -3px;
	position:relative;
	z-index:9999;
	width:400px;
}
pre {
	white-space: pre;
	white-space: pre-wrap;
	white-space: -pre-wrap;
	white-space: -o-pre-wrap;
	white-space: -moz-pre-wrap;
	white-space: -hp-pre-wrap;
	word-wrap: break-word;
	width: 700px;
}
</style>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="http://winofsql.jp/jquery/plugins/smartmenus/jquery.smartmenus.min.js"></script>

<link type="text/css" href="http://winofsql.jp/jquery/jqcss/black-tie/jquery-ui-1.10.1.custom.css" rel="stylesheet" />
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>

</head>
<body>

<ul id="main-menu" class="sm sm-vertical sm-blue sm-blue-vertical">
	<li><a href="#">処理</a>
		<ul>
			<li><a href="page1.htm">HOME</a></li>
			<li><a href="logout.php">ログアウト</a></li>
			<li><a href="https://security.google.com/settings/security/permissions" target="_blank">Google のアカウント権限</a></li>
			<li><a href="http://code.google.com/apis/console/" target="_blank">APIs Console</a></li>
		</ul>
	</li>
</ul>

<script>
$('#main-menu').smartmenus();
</script>


<div id="google-plus">
<?php

for( $i = 0; $i < count($activities); $i++ ) {


	$obj = $activities[$i]->getObject();


	$main_text = $obj->getContent();

	$attachments = $obj->getAttachments();

	$attachments_displayName = $attachments[0]->displayName;

	// アコーディオンタイトル
	print "<h3>投稿" . ($i+1) . " : " . mb_substr($main_text,0,20,"UTF-8") . " / " . mb_substr($attachments_displayName,0,20,"UTF-8") . "</h3>";

	// アコーディオンコンテンツ
	print "<pre>";

	print "投稿部分 : " . $main_text . "<br>";

	print "▼--- 添付部分----<br>";

	print $attachments[0]->displayName . "<br>";
	print $attachments[0]->content . "<br>";
	print $attachments[0]->url . "<br>";
	print $attachments[0]->image['url'] . "<br>";
	if ( $attachments[0]->image['url'] != "" ) {
		print "   <img src=\"" . $attachments[0]->image['url'] . "\"><br>";
		print "   " . $attachments[0]->image['type'] . "<br>";
		print "   " . $attachments[0]->image['width'] . "<br>";
		print "   " . $attachments[0]->image['height'] . "<br>";
	}
	print "<br>";

	print "</pre>";

}
?>
</div>

<script>
$('#google-plus').accordion({
		heightStyle: "content",
		header: "h3"
	});
</script>


</bodyy>
</html>


Google Plus の投稿データは多くの階層内にいろいろなクラスが使われており、仕様上メソッドで呼び出す内容も多い為、一つ一つ階層を print_r で表示して取り出し方を Goolge のクラスのソースと照らし合わせながら確認する必要があります。

APIs Explorer

APIs Explorer ページの右上で認証後、me と public をセットして内容を確認できます


▼ 使用する API によって、スコープを変えれるよう標準化しています
user_client.php( 共通 )
<?php
session_start();

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" );

require_once realpath(dirname(__FILE__) . '/../autoload.php');

$client_id = '';
$client_secret = '';
$redirect_uri = 'http://winofsql.jp/gapi/examples/idtoken.php';

$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
if ( $_GET['start'] == 'page1' || $_SESSION['start'] == 'page1' ) {
	$client->addScope('https://www.googleapis.com/auth/tasks');
}
if ( $_GET['start'] == 'page2' || $_SESSION['start'] == 'page2' ) {
	$client->addScope('https://www.googleapis.com/auth/plus.login');
	$client->addScope('https://www.googleapis.com/auth/plus.me');
}

?>


▼ API から呼び出されるページ
idtoken.php
<?php
session_start();

require_once("user_client.php");

if (isset($_GET['code'])) {

  $client->authenticate($_GET['code']);
  $_SESSION['access_token'] = $client->getAccessToken();
  header("Location: {$_SESSION['action']}.php");

}
else {
  header("Location: {$_SESSION['start']}.htm");
}

?>

関連する記事

Google API の中でも単純な Task API を使って、アクセストークン取得のテンプレートを整備しました



タグ:google API
posted by lightbox at 2015-01-23 20:44 | Google | このブログの読者になる | 更新情報をチェックする

2015年01月22日


C# : Picasa の指定したアルバム内に OpenFileDialog を使って複数の画像を一気にアップロードするコンソールアプリケーション

クライアントライブラリについては、以下を参照して下さい

VB.net(C#) : Picasa より指定したアルバム内の画像の URL 一覧を取得する

▼ 正式英文ドキュメントとサンプルコード
Developer's Guide: Protocol
Google.GData.Client Namespace
PhotoBrowser.cs

using System;
using System.Windows.Forms;
using Google.GData.Client;
using Google.GData.Photos;

class Module1 {

	// OpenFileDialog を使う為
	[STAThread]
	static void Main() {

		// 引数のチェック( user password アルバムタイトル )
		string[] arguments = Environment.GetCommandLineArgs();
		if ((arguments.Length != 4)) {
			return;
		}

		// 複数画像を選択する
		OpenFileDialog openFileDialog = new OpenFileDialog();
		openFileDialog.Filter = "JPeg Files|*.jpg";
		openFileDialog.Multiselect = true;

		DialogResult result = openFileDialog.ShowDialog();
 
		if( result == DialogResult.OK ) {
			// 選んだファイルのパス一覧
			string[] files = openFileDialog.FileNames;

			// companyName-applicationName-versionID で適当に設定
			PicasaService picasaService = new PicasaService("mymymy-photos-v1");
			picasaService.setUserCredentials(arguments[1], arguments[2]);

			AlbumQuery query = new AlbumQuery();
			query.Uri = new Uri(PicasaQuery.CreatePicasaUri(arguments[1]));
			PicasaFeed picasaFeed = picasaService.Query(query);

			if ((!(picasaFeed == null) && (picasaFeed.Entries.Count > 0))) {
				foreach (PicasaEntry entry in picasaFeed.Entries) {
					if ((arguments[3] == entry.Title.Text)) {
						Console.WriteLine( entry.Title.Text );
						// パスの最後の アルバムID を取得
						String[] pathArrayData = (entry.Id.AbsoluteUri).Split('/');
						Console.WriteLine( pathArrayData[pathArrayData.Length-1] );

						Uri postUri = new Uri(PicasaQuery.CreatePicasaUri(arguments[1],pathArrayData[pathArrayData.Length-1]));

						foreach ( string file in files ) {
							System.IO.FileInfo fileInfo = new System.IO.FileInfo(file);
							System.IO.FileStream fileStream = fileInfo.OpenRead();
							// アップロード
							picasaService.Insert(postUri, fileStream, "image/jpeg", file);
							fileStream.Close();
						}
					}
				}
			}
		}
	}
}




タグ:google API
posted by lightbox at 2015-01-22 01:16 | Google | このブログの読者になる | 更新情報をチェックする

2015年01月20日


Google の タスク API(ToDoリスト) を使ってタスクリストとタスクのタイトルを jQuery のプラグインでメニュー化する

アプリケーションを認証すると、以下のようになります。



一番上は、最初から設定済みのメニューで、ログアウトや関連リンクをセットしてあります。下の3つが実際にタスクリストに登録した内容をタイトルだけ設定しています。

Google のタスクリストの管理

Google にログインしていない状態で認証プロセスを実行すると、ログイン画面が表示されるのですが、このログイン画面でログインしてしまうと、ログインを保持してしまうので注意して下さい。これを避けるには、あらかじめ Google にログインしてから認証すると OK です。

▼ 認証プロセス中のログイン


▼ 通常のログイン(ログイン状態を保持する為のチェックボックスがあります )


▼ 認証画面


▼ 実際のデモページです。
http://winofsql.jp/gapi/examples/page1.htm

page1.htm に IFRAME 内で接続用のリンクを用意しています。こうしておくと、どんなページにも簡単に接続リンクを追加できます。IFRAME 内は普通のリンクで、target="_top" になっています。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>

<iframe
	src="start.php?start=page1&action=main_action"
	name="myframe"
	frameborder="0"
	scrolling="no"
	width="200"
	height="100"
></iframe>

</body>
</html>

▼ 接続リンクのあるページ
start.php
<?php
require_once("user_client.php");

$_SESSION['start'] = $_GET['start'];
$_SESSION['action'] = $_GET['action'];

$authUrl = $client->createAuthUrl();

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
</head>
<body style='background-color:#e0e0e0;'>
<a href="<?= $authUrl ?>" target="_top">接続</a>
<br><br><br>
ここは IFREAME です
</body>
</html>


▼ タスクリストのメニュー作成
main_action.php
<?php
require_once("user_client.php");

/************************************************
  アクセストークンがある場合
  但し、期限が切れている場合は再度取得する必要
  があるので、認証用の URL を作成する
 ************************************************/
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  if ($client->isAccessTokenExpired()) {
    unset($_SESSION['access_token']);
    header("Location: {$_SESSION['start']}htm");
    exit();
  }
}
/************************************************
  アクセストークンが無い場合
  認証用の URL を作成するページへのリンクがある
  ページに移動する
 ************************************************/
else {
    header("Location: {$_SESSION['start']}htm");
    exit();
}

/************************************************
  目的 API の処理
 ************************************************/
$service = new Google_Service_Tasks($client);

// タスクリストの一覧
try {
	$obj_tasklists = $service->tasklists->listTasklists();
}
catch(Exception $ex) {
	// セッションの継続中に、アプリケーションの
	// 認証登録が削除された場合
	header('Location: logout.php');
	exit();
}

// タスクリストの配列として取得
$tasklists = $obj_tasklists->getItems();

for( $i = 0; $i < count($tasklists); $i++ ) {

	$obj_tasks = $service->tasks->listTasks($tasklists[$i]->id);
	// タスクリストの数にに同期したタスクの配列の配列を作成
	$tasks[] = $obj_tasks->getItems();

}

/************************************************
  目的の処理
 ************************************************/

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<link href="http://winofsql.jp/jquery/plugins/smartmenus/sm-core-css.css" rel="stylesheet" type="text/css" />
<link href="http://winofsql.jp/jquery/plugins/smartmenus/sm-blue.css" rel="stylesheet" type="text/css" />

<style type="text/css">
#main-menu {
	margin-top: -3px;
	position:relative;
	z-index:9999;
	width:400px;
}
</style>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="http://winofsql.jp/jquery/plugins/smartmenus/jquery.smartmenus.min.js"></script>
</head>
<body>

<ul id="main-menu" class="sm sm-vertical sm-blue sm-blue-vertical">
	<li><a href="#">処理</a>
		<ul>
			<li><a href="page1.htm">HOME</a></li>
			<li><a href="logout.php">ログアウト</a></li>
			<li><a href="https://security.google.com/settings/security/permissions" target="_blank">Google のアカウント権限</a></li>
			<li><a href="http://code.google.com/apis/console/" target="_blank">APIs Console</a></li>
			<li><a href="https://mail.google.com/tasks/canvas" target="_blank">Google のタスク管理ページ</a></li>
 
		</ul>
	</li>
</ul>

<div>
  <pre class="data" style='padding:20px;'>

<?php 
// 主処理

$obj = json_decode($_SESSION['access_token']);
print_r($obj);

print "期限 :" . ($obj->{'created'}+$obj->{'expires_in'}) . "\n";
print "現在 :" . time() . "\n";

print "\n";


?>
  </pre>
</div>

<script type="text/javascript">
// PHP の タスクリストを JavaScript のオブジェクトとして埋め込む
var taskLists = <?php print json_encode( $tasklists ) ?>;
// PHP の タスクの配列の配列を JavaScript のオブジェクトとして埋め込む
var tasks = <?php print json_encode( $tasks ) ?>;
var ul_unit;

for( i = 0; i < taskLists.length; i++ ) {
	// main-menu に最上位メニューとしてタスクリストを追加
	$( "<li id='"+ taskLists[i].id +"'><a href='#'>" + taskLists[i].title + "</a></li>" ).appendTo( $("#main-menu") )
	if ( tasks[i].length != 0 ) {
		// サブメニューのユニットを追加
		ul_unit = $("<ul></ul>").appendTo( $("#"+ taskLists[i].id) );
		// サブメニューの項目としてタスクを全て追加
		for( j = 0; j < tasks[i].length; j++ ) {
			if ( tasks[i][j].title != "" ) {
				$( "<li><a href='#'>" + tasks[i][j].title + "</a></li>" ).appendTo( $(ul_unit) );
			}
		}
	}
}

$('#main-menu').smartmenus({});

</script>


</body>
</html>

jQuery のプラグインである SmartMenus を使用しています。SmartMenus のデモページはこちらになります。

▼ user_client.php( 共通 )
<?php
session_start();

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" );

require_once realpath(dirname(__FILE__) . '/../autoload.php');

$client_id = '';
$client_secret = '';
$redirect_uri = 'http://winofsql.jp/gapi/examples/idtoken.php';

$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
if ( $_GET['start'] == 'page1' || $_SESSION['start'] == 'page1' ) {
	$client->addScope('https://www.googleapis.com/auth/tasks');
}
if ( $_GET['start'] == 'page2' || $_SESSION['start'] == 'page2' ) {
	$client->addScope('https://www.googleapis.com/auth/plus.login');
	$client->addScope('https://www.googleapis.com/auth/plus.me');
}

?>


▼ API から呼び出されるページ( idtoken.php )
<?php
session_start();

require_once("user_client.php");

if (isset($_GET['code'])) {

  $client->authenticate($_GET['code']);
  $_SESSION['access_token'] = $client->getAccessToken();
  header("Location: {$_SESSION['action']}.php");

}
else {
  header("Location: {$_SESSION['start']}.htm");
}

?>



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

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

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

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

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


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

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

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

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

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


Windows
container 終わり

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

Android SDK ポケットリファレンス
改訂版 Webデザイナーのための jQuery入門
今すぐ使えるかんたん ホームページ HTML&CSS入門
CSS ドロップシャドウの参考デモ
PHP正規表現チェッカー
Google Hosted Libraries
cdnjs
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり