SQLの窓

2017年03月13日


jQuery UI の Datepicker Widget のオプション


デモページ

デモページでは、いろいろなオプションを設定した Datepicker のフィールドの動きを確認できます。これらのフィールドは、デフォルトのオプションとして以下のようなものを設定済みです。
var datepicker_option = {
	dateFormat: 'yy/mm/dd',
	dayNamesMin: ['日', '月', '火', '水', '木', '金', '土'],
	monthNames:  ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
	showMonthAfterYear: true,
	yearSuffix: '年',
	changeYear: true,
	showAnim: 'fadeIn',
	yearRange: "c-70:c"
}

このオプションは、日本語としてカレンダーを利用する為に最低限必要なものです。


※ ▼ コンボボックスの幅を以下で最適化しています
.ui-datepicker-month, .ui-datepicker-year {
	width: 70px!important;
}
yearRange: "c-70:c" のオプションは、c が現在の年を示す相対範囲指定です。デモページでは、2) cは当年 c-3:c+3 にあたります。そして、1) dateRangeなし は、そのオプションを削除したもので、その場合は "c-10:c+10" を指定したのと同じ事になります。 ▼ "c-3:c+3" ▼ jQuery を使用して、JSON オブジェクトのクローンを作成
	var datepicker_option1 = $.extend(true, {}, datepicker_option);
	delete datepicker_option1.yearRange;

	$("#date_picker1_fld").datepicker( datepicker_option1 );
※ デモで複数のオプション作成の為、$.extend を使用しています

altField, altFormat, appentText, autoSize

altField と altFormat は、alternate(代わりの) フィールドの定義です。altField で右横にあるフィールドを id で参照します。altFormat では、そのフィールドで表示するフォーマットを指定します(ここでは日本語を使用しています。)

さらに、appentText で、DatePicker フィールドの後ろにテキストを追加し、autoSize で jQuery UI にDatePicker フィールドの幅を調整させます。
	var datepicker_option3 = $.extend(true, {}, datepicker_option);
	datepicker_option3.altField  = "#date_picker3_fld_alt";
	datepicker_option3.altFormat  = "yy年mm月dd日";
	datepicker_option3.appendText  = " altFormat で日本語表現 ";
	datepicker_option3.autoSize = true;

	$("#date_picker3_fld").datepicker( datepicker_option3 );

※ 二番目のフィールドは固定で 120px を指定しており、3番目のフィールドが autoSize です。

ボタンでカレンダーを表示させる

通常では、フィールドにカーソルが移動するとカレンダーが表示されますが、それでは他の画面部分が隠されてしまって、エンドユーザが操作しづらい場合があります。そういう場合にボタンを追加してその操作を行う方法です。ここでは、その目的のために showOn = "button" と buttonText = "開く" を指定しています。(showOn では、both というオプションがありますが、それでは意味が無いので button のみの動作、また、buttonText では無く buttonImage で画像ボタンにする事もできます)

月を変更可

★重要 : 表示したい月表現を monthNamesShort = ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"] のように設定する必要がありました

誕生日の指定等、連続していない年月の指定の為、月をコンボボックスに変更します。



※ ▼ コンボボックスの幅を以下で最適化しています
.ui-datepicker-month, .ui-datepicker-year {
	width: 70px!important;
}
※ 月を変更可にした場合、これをしておかないと、年と月が入りきらずに二段になってしまいます。 前後の月を表示して選択可能にする これは、現実のカレンダーのように、表示できる場合は前月の最後と次月の最初を表示して選択できるようにするものです。そのために showOtherMonths = true と selectOtherMonths = true を両方設定しています。 jQuery.ajax による送信処理
	// *************************************
	// 送信 <input type="submit">
	// *************************************
	$("#frm").submit( function(event){
		// 本来の送信処理はキャンセル
		event.preventDefault();

		// 入力部分をプロテクト
		$("fieldset").eq(0).prop("disabled", true);

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

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


		// 新規送信用オブジェクト
		var formData = new FormData();

		formData.append("datepicker1", $("#date_picker1_fld").val() );
		formData.append("datepicker2", $("#date_picker2_fld").val() );
		formData.append("datepicker3", $("#date_picker3_fld").val() );
		formData.append("datepicker3_alt", $("#date_picker3_fld_alt").val() );
		formData.append("datepicker4", $("#date_picker4_fld").val() );
		formData.append("datepicker5", $("#date_picker5_fld").val() );
		formData.append("datepicker6", $("#date_picker6_fld").val() );

		// **************************************
		// サーバ呼び出し
		// **************************************
		$.ajax({
			url: "./post_action.php",
			type: "POST",
			data: formData,
			processData: false,  // jQuery がデータを処理しないよう指定
			contentType: false   // jQuery が contentType を設定しないよう指定
		})
		.done(function( data, textStatus ){
			console.log( "status:" + textStatus );
			console.log( "data:" + JSON.stringify(data, null, "    ") );
			options.info("送信処理が完了しました");

		})
		.fail(function(jqXHR, textStatus, errorThrown ){
			console.log( "status:" + textStatus );
			console.log( "errorThrown:" + errorThrown );
			options.info("送信処理を失敗しました");
		})
		.always(function() {

			// 入力部分のプロテクトを解除
			$("fieldset").eq(0).prop("disabled", false);
		})
		;


	} );



タグ:datepicker jquery
【jQueryの最新記事】
posted by lightbox at 2017-03-13 14:27 | Comment(0) | jQuery | このブログの読者になる | 更新情報をチェックする

2017年03月10日


FormData を使用して、jQuery で配列として PHP に送る

必要なデータを隠しリストボックス( multiple ) に jQuery で追加して配列として PHP に送る では、select 要素を使用しましたが、jQuery の ajax と FormData を使用すれば、もっと単純に送る事ができます。

送信用データ作成部分は結局4行です
		// 新規送信用オブジェクト
		var formData = new FormData();

		// 送信フィールド作成
		$("#row1_fld option").each( function(){
			formData.append("ybp[]", $(this).val());
		});

		// **************************************
		// サーバ呼び出し
		// **************************************
		$.ajax({
			url: "./post_action.php",
			type: "POST",
			data: formData,
			processData: false,
			contentType: false
		})
		.done(function( data, textStatus ){
			console.log( "status:" + textStatus );
			console.log( "data:" + JSON.stringify(data, null, "    ") );
			options.info("処理が完了しました");

		})
		.fail(function(jqXHR, textStatus, errorThrown ){
			console.log( "status:" + textStatus );
			console.log( "errorThrown:" + errorThrown );
			options.info("アップロードに失敗しました");
		})
		.always(function() {

		})
		;


デモページ



ソースコードセットダウンロード

メインソースコード(view_main.php)
<?php
// *************************************
// 表示コントロール
// *************************************
$GLOBALS['title'] = "jQuery Ajax POST : 配列";
$GLOBALS['comment'] = 'ようこそ jQuery + Bootstrap(css) + mmenu + FormData + PHP';

?>
<!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">

<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 = {
	row1 : { title : "複数データ<br>(Yahoo!テレビ番組表地域コード)", pcss : { width: "400px" }, attr: { size : 6 } },
	row_last : { title :"メッセージ" },
	error : function(message){
		$("#row_last").next().text( message );
		toastr.error(message);
	},
	info : function(message){
		$("#row_last").next().text( message );
		toastr.success(message);
	}
};

$(function(){

	$("#wrapper").css({"visibility":"visible", "margin-bottom": "0px"}); 
	// -------------------------------------
	// 固定テンプレート
	// -------------------------------------
	// 1) options による行とフィールドの設定
	// 2) Bootstrap 用 form-control クラスの追加
	$(".fields").each(function(){
		if ( options[ $(this).prop("id") ] ) {
			$(this).html( options[ $(this).prop("id") ].title );
			// 個別 css
			if ( options[ $(this).prop("id") ].css ) {
				$(this).next().find("input,select,textarea").css( options[ $(this).prop("id") ].css );
			}
			// 入力チェック用属性
			if ( options[ $(this).prop("id") ].attr ) {
				$(this).next().find("input,select,textarea").attr( options[ $(this).prop("id") ].attr );
			}
			// pc のみの css
			if ( options[ $(this).prop("id") ].pcss ) {
				if ( !$.isMobile ) {
					$(this).next().find("input,select,textarea").css( options[ $(this).prop("id") ].pcss );
				}
			}

		}
		$(this).next().find("input,select,textarea").addClass("form-control");
	});

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

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

		$("#post_check").modal();

	} );


	// **************************************
	// Bootstrap OK ボタン
	// **************************************
	$("#data_post").on("click", function(){

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

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

		// **************************************
		// サーバへ送信
		// **************************************

		// 新規送信用オブジェクト
		var formData = new FormData();

		// 送信フィールド作成
		$("#row1_fld option").each( function(){
			formData.append("ybp[]", $(this).val());
		});

		// **************************************
		// サーバ呼び出し
		// **************************************
		$.ajax({
			url: "./post_action.php",
			type: "POST",
			data: formData,
			processData: false,
			contentType: false
		})
		.done(function( data, textStatus ){
			console.log( "status:" + textStatus );
			console.log( "data:" + JSON.stringify(data, null, "    ") );
			options.info("処理が完了しました");

		})
		.fail(function(jqXHR, textStatus, errorThrown ){
			console.log( "status:" + textStatus );
			console.log( "errorThrown:" + errorThrown );
			options.info("アップロードに失敗しました");
		})
		.always(function() {

		})
		;

	});

	// -------------------------------------
	// 固定テンプレート
	// -------------------------------------
	$("#mmenu_left").mmenu({
		navbar: {
			title: "メニュー"
		},
		offCanvas: {
			position  : "left",
			zposition : "next"
		}
	});
	// -------------------------------------


});

</script>
</head>
<body>

<div id="wrapper">
<script>
$("#wrapper").css( {"visibility": "hidden", "margin-bottom" : "1000px" } );
</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>
				<legend></legend>
				<table class="table table-condensed">
			
					<tr>
						<td class="fields" id="row1"></td>
						<td>
							<select name="row1_fld" id="row1_fld">
								<option value="43">和歌山</option>
								<option value="44">奈良</option>
								<option value="45">滋賀</option>
								<option value="41">京都</option>
								<option value="40">大阪</option>
								<option value="42">兵庫</option>
							</select>
						</td>
					</tr>

					<tr>
						<td class="fields" id="row2"></td>
						<td>
							<input id="action" type="submit" 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 id="result" class="table table-condensed">


				</table>

			</fieldset>

		</form>
	</div>

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

	<div class="modal fade" id="post_check" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
		<div class="modal-dialog" role="document">
			<div class="modal-content">

				<div class="modal-header">
					<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
					<h4 class="modal-title" id="myModalLabel">確認</h4>
				</div>

				<div class="modal-body">
				送信しますか?
				</div>

				<div class="modal-footer">
					<button id="data_post" type="button" class="btn btn-default" data-dismiss="modal">OK</button>
					<button type="button" class="btn btn-primary" data-dismiss="modal">キャンセル</button>
				</div>

			</div>
		</div>
	</div>

</div>


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


</body>
</html>

※ jQuery + Bootstrap(css) + mmenu + FormData + PHP の総合テンプレートです


post_action.php
<?php
// *************************************
// キャラクタセット
// *************************************
header( "Content-Type: application/json; charset=utf-8" );
// *************************************
// キャッシュ無効
// *************************************
session_cache_limiter('nocache');
session_start();


// *************************************
// 処理
// *************************************


// *************************************
// PHP の結果を result キーで
// JSON としてブラウザに返す
// *************************************
print json_encode($_POST , JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT );

?>

※ 処理の結果は、開発者ツールのコンソールで確認して下さい。








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

2017年03月09日


必要なデータを隠しリストボックス( multiple ) に jQuery で追加して配列として PHP に送る

送信直前に onsubmit="return check_form();" で追加して、PHP がページを再表示したら元の状態に戻るというデータの送信方法です。

jQuery は、最初に option 要素を作って、その属性を設定して最後に appendTo で select に追加して行きます。PHP 対象なので、name="target[]" となっていますが、ASP(いまだに運用してるので) だと name="target" で Request.Form("target")(n) とかで参照できます。


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>

function check_form() {

	if ( !confirm("送信しますか?") ) {

		return false;

	}

	$("#target option").each( function(){

		$("<option></option>")
			.prop("selected", true)
			.val( $(this).val() )
			.appendTo( $("#send_target") )

	});

	return true;

}
</script>
</head>
<body>

<form method="post" onsubmit="return check_form();">

<input id="send" name="send" type="submit" value="send">

<select multiple id="send_target" name="target[]" style='display:none'>
</select>
<select id="target" size="3">
<option value="A001">テキスト1</option>
<option value="A002">テキスト2</option>
<option value="B001">テキスト3</option>
</select>


</form>

<pre>
<?php

print_r($_POST)

?>
</pre>
</body>
</html>




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

2017年02月28日


cp932 の SQLServer に対して、PHP の ODBC 関数に対して UTF8 変換で地道に対応し、特殊なUncode文字は、HTML 数値エンティティで保存する。

Microsoft のドライバで自動的に対応させる方法もありますが、かつて切り替え時期に Microsoft 純正を使ってえらい目にあった経緯があり、全て SHIFT_JIS で現在も運用していますが、jQuery の ajax を使用するに当たってどうしても通信部分は UTF-8 になるため、以下のようにしています。

また、国際化のためどうしても SHIFT_JIS に無い文字に対応する必要も出てきました。

まず、以下のソースは SHIFT_JIS で書かれており、mb_convert_encoding が不可欠なので、先頭で内部コードを UTF-8 に設定しています。
<?php
mb_internal_encoding("UTF-8");
require_once( "../db.php" );

// *************************************
// キャラクタセット
// *************************************
header( "Content-Type: application/json; charset=utf-8" );
// *************************************
// キャッシュ無効
// *************************************
session_cache_limiter('nocache');
session_start();

// ajax の為、入力値は UTF-8
foreach( $_POST as $Key => $Value ) {

	if ( $Key == "name" || $Key == "name2" ) {
		$_POST[$Key] = mb_encode_numericentity( $Value, array(0x0, 0x2FFFF, 0, 0xFFFFF) );
	}
	else {
		$_POST[$Key] = mb_convert_encoding( $Value, "cp932", "UTF-8" );
	}
}

// *************************************
// 処理
// *************************************
$SQL = new DBSS( $COMMON_DB, "sa" );

$query = "update SQLServerのテーブル set";
$query .= " 姓 = '{$_POST["name"]}'";
$query .= " ,名 = '{$_POST["name2"]}'";

$query .= " where 番号 = {$_POST["no"]}";


$_POST['query'] = $query;

$ret = $SQL->Execute( $query );

if ( $ret === false ) {
	$_POST['status'] = 0;
}
else {
	$_POST['status'] = 1;
}


// *************************************
// PHP の結果を result キーで
// JSON としてブラウザに返す
// *************************************
foreach( $_POST as $Key => $Value ) {
	$_POST[$Key] = mb_convert_encoding( $Value, "UTF-8", "cp932" );
}
print json_encode($_POST);

?>

この処理は、jQuery から呼び出された更新処理です。name と name2 に、HTML 数値エンティティに変換すべき文字列が入っています。全て変換する必要は無いのですが、SHIFT_JIS と Unicode の云々の詳細を省く為に array(0x0, 0x2FFFF, 0, 0xFFFFF) となっています。

0x0 〜 0x2FFFF : オフセット 0、マスク 0xFFFFF

ここでは、サンプルとしてのコードなので、入力文字列が name と name2 しかないので、mb_convert_encoding( $Value, "cp932", "UTF-8" ) が実行されませんが、一般的な SHIFT_JIS の文字列のデータに対して必要です。

print する場合は、jQuery の中に戻るので、再度 UTF-8 に変換する必要があります。

以下は同様の処理で、読み出すだけのコードです。
<?php
mb_internal_encoding("UTF-8");
require_once( "../db.php" );

// *************************************
// キャラクタセット
// *************************************
header( "Content-Type: application/json; charset=utf-8" );
// *************************************
// キャッシュ無効
// *************************************
session_cache_limiter('nocache');
session_start();

// ajax の為、入力値は UTF-8
foreach( $_POST as $Key => $Value ) {
	$_POST[$Key] = mb_convert_encoding( $Value, "cp932", "UTF-8" );
}

// *************************************
// 処理
// *************************************
$SQL = new DBSS( $COMMON_DB, "sa" );

$query = "select * from SQLServerのテーブル where 番号 = {$_POST["no"]}";
$column = $SQL->QueryEx( $query );

if ( $column ) {

	foreach( $column as $Key => $Value ) {
		$fld = mb_convert_encoding( $Key, "UTF-8", "cp932" );

		if ( $Key == "姓" || $Key == "名" ) {
			$column2[$fld] = mb_decode_numericentity( $Value, array(0x0, 0x2FFFF, 0, 0xFFFFF) );
		}
		else {
			$column2[$fld] = mb_convert_encoding( $Value, "UTF-8", "cp932" );
		}

	}


	$_POST['exist'] = 1;
}
else {
	$_POST['exist'] = 0;
}


// *************************************
// PHP の結果を result キーで
// JSON としてブラウザに返す
// *************************************
foreach( $_POST as $Key => $Value ) {
	$_POST[$Key] = mb_convert_encoding( $Value, "UTF-8", "cp932" );
}
$_POST['data'] = $column2;
print json_encode($_POST);

file_put_contents("debug.log", print_r($_POST, true));

?>

ここで、一番重要なのは、HTML 数値エンティティ を mb_decode_numericentity で元の文字列に戻す事です。これでブラウザから貼り付けれる文字であれば、DB には HTML 数値エンティティ で保存されて、表示すると元に戻るはずです。

※ ただ、DB 側の列の文字列サイズがかなり大きくなります。

ちなみに、Excel への変換は、IE を使用してブラウザからの Excel オフジェクト呼び出しでまかなっています。
▼ 
IE11 で VBScript を使う場合の注意事項 ( 古い社内アプリ移行時必見 )


posted by lightbox at 2017-02-28 22:03 | Comment(0) | PHP + 特記事項 | このブログの読者になる | 更新情報をチェックする

2017年02月06日


WebRTC による WEBカメラ表示を canvas にコピーして画像に変換し、サーバへアップロードする

資料ページ

Taking still photos with WebRTC
2016/3末時点のWebRTCブラウザ対応状況まとめ

※ デモページは、WEBアプリ用のテンプレートを Bootstrap を使用してスマホ対応で作成しています

▼ デモページ

※ この画像では、カメラが無い場合の代替の動画を使用しています

MediaDevices - Web API インターフェイス | MDN
Taking still photos with WebRTC - Web APIs | MDN



▼ 初回( Google Chrome )


ソースコード

カメラを使うにしても、動画を使うにしても VIDEO 要素が使用されます。そこから、いったん canvas へコピーして、base64 で表現された画像に変換します。

アップロード時は、FormData を使い、データはバイナリに変換してアップロードします。(最大3枚までアップロード可能にしています)

アップロードは ajax で行われるので、ページが書き換わる事はありません。結果として返される json は、$_FILES の内容をそのまま返しています(メッセージを追加しています)

<!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>カメラ撮影とアップロード</title>

<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<!-- jQuery UI -->
<link id="link" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.css">
<!-- jQuery.mmenu -->
<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">
<!-- toastr -->
<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">

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

legend {
	font-size: 18px;
	padding-left: 6px;
}

/* 画像表示用 */
#row2 {
	vertical-align: top!important;
}

/* カメラ用 */
#camera {
	width: 400px;
	height: 300px;
	object-fit: fill;
}
#canvas {
	/* display: none; */
}
</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 datepicker_option = {
	dateFormat: 'yy/mm/dd',
	dayNamesMin: ['日', '月', '火', '水', '木', '金', '土'],
	monthNames:  ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
	showMonthAfterYear: true,
	yearSuffix: '年',
	changeYear: true,
	showAnim: 'fadeIn',
	yearRange: "c-70:c"
}
$(function(){
	var curlink = $("#title").text();
	$("#title").html("<a href=\"./\" style=\"color:#fff\">" + curlink + "</a>");
});
var options = {
	row1 : { title : "カメラ" },
	row2 : { title : ""  },
	row3 : { title : "画像一覧<br>(ロード順)"  },
	row4 : { title : ""  },
	row_last : { title :"メッセージ" },
	error : function(message){
		$("#row_last").next().text( message );
		toastr.error(message);
	},
	info : function(message){
		$("#row_last").next().text( message );
		toastr.success(message);
	},
	cerror : function( message ){
		message =  message + "<br>代替として動画を表示します"
		$("#row_last").next().html( message );
		toastr.error( message );
		$("#camera")
		.prop({ 
			"loop" : true, "muted" : true, "controls" : true,
			"src" : "mp4/freebies_018_win.mp4"
		})
		.css("border", "solid 1px #000");
	}
};

// *************************************
// カメラ用データ
// *************************************
var camera;
var canvas;
var copy_count = 0;

$(function(){

	// 1) options による行とフィールドの設定
	// 2) Bootstrap 用 form-control クラスの追加
	$(".fields").each(function(){
		if ( options[ $(this).prop("id") ] ) {
			$(this).html( 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", "margin-bottom" : "0px" }); 

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

	// video 内 camera
	camera = $("#camera").get(0);

	// *************************************
	// 最新 API
	// *************************************
	if ( navigator.mediaDevices ) {
		console.log("navigator.mediaDevices");

		if ( $.isMobile ) {
			$("#camera").css("width","100%");
		}
		navigator.mediaDevices.getUserMedia({video: true})
		.then(function(stream){
			camera.src = window.URL.createObjectURL(stream);
		})
		.catch(function(err){
			// ブラウザで使用を拒否した場合等( 動画で代替 )
			options.cerror(err.name);
		});

	}
	// *************************************
	// 旧 API
	// *************************************
	else {
		console.log("navigator.getUserMedia");

		// 旧 WebRTCチェック用
		var api = [
			"webkitGetUserMedia", "mozGetUserMedia","msGetUserMedia"
		]
		$.each(api,function(idx){
			if (navigator.getUserMedia = navigator.getUserMedia || navigator[api[idx]]) {
				return false;
			}
		});
		// WebRTC 使用可能
		if ( navigator.getUserMedia ) {
			if ( $.isMobile ) {
				$("#camera").css("width","100%");
			}
			// カメラの表示
			navigator.getUserMedia({video: true}, 
				function(stream) {
					camera.src = window.URL.createObjectURL(stream);
				},
				function(err){
					// ブラウザで使用を拒否した場合等( 動画で代替 )
					options.cerror(err.name);
				}
			);	
		}
		else {
			// WebRTC 使用不可( 動画で代替 )
			options.cerror("WebRTC を使用できません");
		}
	}

	// *************************************
	// canvas にコピーして画像に変換
	// *************************************
	$("#copy").on( "click", function(){

		copy_count++;
		if ( copy_count > 3 ) {
			options.error("撮影は3枚までです");
			return false;
		}

		canvas = $("#canvas").get(0);
		var ctx = canvas.getContext('2d');

		ctx.drawImage(camera, 0, 0, canvas.width, canvas.height);

		$("<img>").appendTo("#images")
		.prop( {"src": canvas.toDataURL("image/jpeg"), "id": "image"+ copy_count } )
		.css( {"width": "100px", "margin": "10px" } );


	});

	// *************************************
	// アップロード処理
	// *************************************
	$("#frm").submit( function(event){
		// 本来の送信処理はキャンセル
		event.preventDefault();

		if ( $("#images").html() == "" ) {
			options.error("アップロードする画像ファイルを作成して下さい");
			return;
		}

		$("fieldset").eq(0).prop("disabled", true);

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

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


		// **************************************
		// ファイルのアップロード
		// **************************************
		console.log("アップロード処理開始");

		var formData = new FormData();

		// テストの為、約100K の制限
		formData.append("MAX_FILE_SIZE", 100000);

		var file_cnt = 0;

		$("#images img").each( function() {

			var base64 = $(this).prop("src");
			var bin = atob(base64.split(',')[1]);
			var buffer = new Uint8Array(bin.length);
			for (var i = 0; i < bin.length; i++) {
				buffer[i] = bin.charCodeAt(i);
			}
			var blob = new Blob([buffer.buffer], {type: "image/jpeg"});

			file_cnt++;
			var file_name = (new Date()).getTime();
			formData.append("image"+file_cnt, blob, file_name +"_"+file_cnt+".jpg");

		});

		formData.append("FILE_COUNT", file_cnt );

		$.ajax({
			url: "./upload.php",
			type: "POST",
			data: formData,
			processData: false,  // jQuery がデータを処理しないよう指定
			contentType: false   // jQuery が contentType を設定しないよう指定
		})
		.done(function( data, textStatus ){
			console.log( "status:" + textStatus );
			console.log( "data:" + JSON.stringify(data, null, "    ") );
			options.info("アップロード処理が完了しました");

			// アップロード結果の表示
			$.each(data, function(idx,image){

				if ( image.error != 0 ) {
					$("#result").append("<tr><td><span id=\"result" +idx+"\"></span><b style='color:red'>" + image.name+ " : " + image.result +"</b></td></tr>");
				}
				else {
					$("#result").append("<tr><td><span id=\"result" +idx+"\"></span>" + image.name + " : " + image.result +"</td></tr>");
				}

				$( "#result"+idx ).append($("#"+idx).clone());

			});

			$("#images").html("");
			copy_count = 0;
		})
		.fail(function(jqXHR, textStatus, errorThrown ){
			console.log( "status:" + textStatus );
			console.log( "errorThrown:" + errorThrown );
			options.info("アップロードに失敗しました");
		})
		.always(function() {

			// 操作不可を解除
			$("fieldset").eq(0).prop("disabled", false);
		})
		;

	} );

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


});

</script>
</head>
<body>

<div id="wrapper">
<script>
// スマホでロード時等の処理のチラつき防止用
$("#wrapper").css( {"visibility": "hidden", "margin-bottom" : "1000px" } );
</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">カメラ撮影とアップロード</div>
	</div>

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

			<fieldset>
				<legend>アップロード</legend>
				<table class="table table-condensed">
			
					<tr>
						<td class="fields" id="row1"></td>
						<td>
							<video
								id="camera"
								autoplay></video>
							<canvas
								id="canvas"
								width="400"
								height="300"></canvas>								
						</td>
					</tr>

					<tr>
						<td class="fields" id="row2"></td>
						<td>
							<input id="copy" type="button" class="btn btn-primary btn-sm" value="撮影">
						</td>
					</tr>

					<tr>
						<td class="fields" id="row3"></td>
						<td>
							<div id="images"></div>
						</td>
					</tr>

					<tr>
						<td class="fields" id="row4"></td>
						<td>
							<input id="action" type="submit" 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 id="result" class="table table-condensed">


				</table>

			</fieldset>

		</form>
	</div>

	<div id="comment">
	ようこそ jQuery + Bootstrap(css) + mmenu + WebRTC(カメラ) + FormData + PHP<br><a href="https://www.studio-lab01.com/freebies.html" target="_blank">素材提供:らぼわん</a> / カメラが無い場合の動画素材	</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='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>

	<li><a class="mm_link_left"
			href="https://developer.mozilla.org/ja/docs/Web/Guide/Using_FormData_Objects"
			onclick="location='index.php';void(0)"
			target="_blank"
		>FormData オブジェクトの利用 / MDN</a></li>

	<li><a class="mm_link_left"
			href="https://developer.mozilla.org/ja/docs/Web/API/MediaDevices"
			onclick="location='index.php';void(0)"
			target="_blank"
		>MediaDevices (MDN)</a></li>

	<li><a class="mm_link_left"
			href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Taking_still_photos"
			onclick="location='index.php';void(0)"
			target="_blank"
		>Taking still photos with WebRTC(英文)</a></li>


</ul>
</div>


</body>
</html>



upload.php

※ アップロードした画像の保存部分はコメントにしています
<?php
// キャラクタセット
// *************************************
header( "Content-Type: application/json; charset=utf-8" );
// *************************************
// キャッシュ無効
// *************************************
session_cache_limiter('nocache');
session_start();

// ファイルを移動するフォルダ
$target_folder = "./images/";


$cnt = $_POST["FILE_COUNT"] + 0;

for( $i = 0; $i < $cnt; $i++ ) {

	$image_target = "image".($i+1);

	if ( $_FILES[$image_target]["error"] == 0 ) {

		// *************************************
		// 1) 画像フォーマットの取得
		// *************************************
		$type_string = image_type_to_mime_type( exif_imagetype( $_FILES[$image_target]['tmp_name'] ) );

		// *************************************
		// 2) オリジナルファイル名の取得
		// *************************************
		$file = explode(".", $_FILES[$image_target]['name']);

		// *************************************
		// 3) 日本語ファイル名対応
		// *************************************
		$file_name = urlencode( $file[0] );

		// *************************************
		// 4) 保存ファイル名を作成
		//   a) 拡張子決定
		//   b) uniqid() でファイル目をユニーク
		// *************************************
		$target = "";
		if ( $type_string == "image/jpeg" ) {
			$target = uniqid() . "_{$file_name}.jpg";
		}
		if ( $type_string == "image/gif" ) {
			$target = uniqid() . "_{$file_name}.gif";
		}
		if ( $type_string == "image/png" ) {
			$target = uniqid() . "_{$file_name}.png";
		}
		if ( $target == "" ) {
			$_FILES["image"]["result"][] = "アップロードできないフォーマットです";
		}
		else {
			// *************************************
			// アップロードファイルの保存
			// *************************************
//			if ( @move_uploaded_file( $_FILES[$image_target]['tmp_name'], $target_folder . $target ) ) {
				$_FILES[$image_target]["result"] = "アップロードに成功しました";
//			}
//			else {
				// なんらかの環境エラー
//				$_FILES[$image_target]["result"] = "アップロードに失敗しました";
//			}
			
		}
	}
	else {
		switch($_FILES[$image_target]["error"]){
			case 1:
				$_FILES[$image_target]["result"] = "php.ini の upload_max_filesize ディレクティブの値を超えています";
				break;
			case 2:
				$_FILES[$image_target]["result"] = "HTML フォームで指定された MAX_FILE_SIZE を超えています";
				break;
			case 3:
				$_FILES[$image_target]["result"] = "一部のみしかアップロードされていません";
				break;
			case 4:
				$_FILES[$image_target]["result"] = "アップロードされませんでした";
				break;
			case 6:
				$_FILES[$image_target]["result"] = "テンポラリフォルダがありません";
				break;
			case 7:
				$_FILES[$image_target]["result"] = "ディスクへの書き込みに失敗しました";
				break;
			case 8:
				$_FILES[$image_target]["result"] = "PHP の拡張モジュールがファイルのアップロードを中止しました";
				break;
			default:
				$_FILES[$image_target]["result"] = "不明なエラーです";
		}
		
	}

}


print json_encode($_FILES)


?>


関連する記事

WebRTC による WEBカメラ表示



posted by lightbox at 2017-02-06 18:18 | Comment(0) | API | このブログの読者になる | 更新情報をチェックする
container 終わり

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

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