SQLの窓

2018年02月08日


jQuery の ajax でアクセス可能なデータをボタンをクリックした後 window.open で開いたウインドウの中にテキストエリアを作成して表示する方法

デモページ

利用目的

ウェブアプリで、デバッグデータをファイルに書き込んで残しているような場合、すくに内容を確認できるように作成しました。なので、dataType に text を使用していますが、一般的な json や QueryString の作成は 『jQuery + bootstrap.js で ajax の GET と POST を使用した DB テーブルを更新する UI テンプレート』を参照して下さい。

位置、サイズ指定の window.open

window.open の処理は、他でも転用できるように関数化しています。元々は SyntaxHighlighter 2.0.296 で使用されていたものを転用しています。特別な内容はありませんが、文字列の引数を作成する場合に常に前にカンマを置いておいて、最終的に出来上がった文字列の先頭のカンマを正規表現で取り除いていたのが印象的でした。

やはり、IE11 が障害でした

document.write を使用しているのは、IE11 がそれでしか動作しなかったからです。Chrome や Firefox ですと、Owner ウインドウ側の jQuery で、新しいウインドウ内の動的処理やイベントを定義できました(その場合でも、新しい window 内に jQuery を組み込む事はできます)。しかし、IE11 では動作しなかったのでこのような実装になっています。

ただ、メンテナンス性や作りやすさで言えば、document.write が勝ります。唯一、文字列のコードを作るのがやっかいですが、自作のテキスト変換サービス を使用しているので特に困った事はありません。
(プログラム用文字列作成 の JavaScript ボタン)

Access-Control-Allow-Origin: *

通常、別ドメインのデータを ajax で取得できないので、自サイトに Access-Control-Allow-Origin: * を返すデータを用意して使用しています。同じドメインで完結するアプリでしたら、特に気にする必要はありません

ポップアップブロック対策

$.get のイベントの中で window.open をしてしまうと、ポップアップブロックにひっかかるので、先に window.open をして window を開いておいてから、$.get のイベント内で動的にコンテンツを書き込んでいます。

補足

css 設定に関しては、見栄えを優先するのであれば、style 記述そのものを document.write すべきです。ですが、ここではあくまでデバッグが目的なので、メンテナンス性に基づいて、一か所に集約しています。

css に calc を指定しているのは、テキストエリアがウインドウのサイズ変更と同期するためです。但し、複雑な階層を持つ HTML 構造の場合は、height の指定は注意が必要です( html や body や 親要素が height:100% である必要があったような... )

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>

$(function(){

	$("#debug1").on("click", function(){

		var win = win_open("","_blank",750, 400, "location=0,resizable=1,menubar=0,scrollbars=1");

		$.get({
			url: "https://lightbox.sakura.ne.jp/toolbox/data/syain.json",
			cache: false,
			dataType : "text"
		})
		.done( function( result, textStatus, jqXHR ) {
			console.dir( jqXHR );
			console.log( textStatus );	// success
			console.log( jqXHR.status );	// 通常 200
			console.log( jqXHR.statusText );	// OK
		
			var headers = jqXHR.getAllResponseHeaders();
			console.dir( headers );
		
			// 成功した結果 : jqXHR.responseText
			console.log( result );

var str="";
str+="<"+"script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js\"></"+"script> \n";
			win.document.write(str);

str="";
str+="<t"+ "extarea readonly style=\"width:100%;height:350px\">" + result + "</" + "textarea>\n";
str+="<"+"script> \n";
str+="$(function() { \n";
str+="	$(\"textarea\").css({\"width\":\"calc(100% - 10px)\", \"padding\":\"10px\"}); \n";
str+="	$(\"textarea\").css({\"height\":\"calc(100% - 20px)\"}); \n";
str+="	$(\"textarea\").css({\"font-size\":\"14px\"}); \n";
str+=" $(\"textarea\").css({\"font-family\": '\"ヒラギノ角ゴPro W3\",\"Hiragino Kaku Gothic Pro\",\"メイリオ\",Meiryo,\"MS Pゴシック\",Verdana,Arial,Helvetica,sans-serif'}); \n";
str+="	$(\"head\").append($(\"<title>\").text(\"前回の入力値\")); \n";
str+="	$(\"textarea\").focus(); \n";
str+="}); \n";
str+="</"+"script> ";

			win.document.write(str);
			win.document.close();
		
		})
		.fail(function( jqXHR, textStatus ) {
			console.dir( jqXHR );
			console.log( textStatus );	// error
			
		});

	});

});

function win_open(url, name, width, height, options)	{
	var x = (screen.width - width) / 2;
	var y = (screen.height - height) / 2;
	options +=
		', left=' + x + 
		', top=' + y +
		', width=' + width +
		', height=' + height
	;
	// 先頭のカンマを取り除く
	options = options.replace(/^,/, '');

	var win = window.open(url, name, options);
	win.focus();
	return win;
}
</script>
<input id="debug1" class="debug" type="button" value="Access-Control-Allow-Origin: * データの表示">





タグ:jquery javascript
posted by lightbox at 2018-02-08 15:46 | JavaScript コンテンツ | このブログの読者になる | 更新情報をチェックする

2015年08月19日


IFRAME を ブラウザのサイズ変更時のイベントでコントロールして、HTML5で廃止された FRAME と同様に使うサンプル

デモページ

※ 下の灰色の部分は全て IFRAME で、ブラウザのサイズ変更と同期します

結論から言いますと、IFRAME と FRAME の大きな違いは、上の画像のように jQuery の DatePicker のカレンダーが、IFRAME の上に展開されるというところです。FRAME の場合ですと、ブラウザが用意するコンボボックス等は FRAME の境界を越えて表示されますが、HTML で作成されるコンテンツは FRAME の境界の下に潜り込んでしまいます。

しかし、FRAME の便利な点は、WEB ページのデータ送信の結果を一方通行で別の FRAME に表示できるので、WEB アプリが元のページの内容を書き換える必要が無いところです。当然その特性は IFRAME も持っていますが、IFRAME は固定のウインドウとして表示されるものなので、ブラウザの大きさに同期して表示部分いっぱいいっぱいで利用するには( FRAME のように )、JavaScript でリアルタイムでサイズを変更する必要があります。

にもかかわらず、実際実装しようとすると、ページの縦のサイズを取得しようとすると、IFRAME が表示されているとうまく取得できない仕様になっていて、たいていは失敗する事になります。これを避けるには、IFRAME のサイズ変更は、IFRAME を非表示にして行う事で解決できました。
古い IE のシステムを想定して、IE8 で動作させる為に、header 関数で『x-ua-compatible: IE=8』 を送っています。

IE8 前提なので、jQuery のバージョンは低く設定しています
IE8 では、IFRAME の境界を CSS で消せませんので frameborder を使用しています

IE、Firefox、Google Chronme で正しく動作する為に、縦の補正値を使用しています

shift_jis を使用しているのは、SQLServer を ODBC 関数でアクセスする予定だからです

FORM の送り先は、accept-charset="utf-8" を使用して utf-8 を利用しています( 但しこの機能は IE8 コンパチブルでは動作しないので、受け取り側で対処する必要があります )

デモページのコード
<?php
header( "Content-Type: text/html; Charset=shift_jis" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "x-ua-compatible: IE=8" );

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=shift_jis">

<!-- jQuery のバージョンが 1.9 なのは、IE 用 -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<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.10.1/jquery-ui.min.js"></script>

<style>
body {
	margin: 0;
}
#wrapper {
	background-color: #ffffff;
}
#head_unit {
	height: 50px;
	padding: 15px 0 10px 15px;
}
#target {
	/* IFRAME の横調整は、ブラウザに任せます */
	width: 100%;
}
</style>
<script>
// IFRAME フィット
function control_page_iframe(iframe_id) {
	var height = Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);
	var head_height = document.getElementById("head_unit").clientHeight;

	// -6 は、IE と Firefox 用。Google Chrome は 0 で正しくフィットするが、
	// IE と Firefox では、BODY のスクロールバーが表示されてしまう( バグレベルの動作 )
	document.getElementById(iframe_id).style.height = (height - parseInt(head_height)-6) + "px"
}

// 日付フォーマット用の文字列処理3つ
String.prototype.right = function(n){
	var str = this.valueOf();
	str = str.substr(str.length-n,n);
	return str;
}
String.prototype.zero = function(n){
	var strzero = "0000000000000000000";
	var str = this.valueOf();
	str = strzero + str;
	return str.right(n);
}
Date.prototype.datestr = function(sep){
	str = this.getFullYear() + sep + (this.getMonth()+1).toString().zero(2) + sep + (this.getDate()).toString().zero(2);
	return str;
}

// jQuery 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'
}
var datepicker;

// jQuery 初期処理
$(function() {
	// jQuery DatePicker プラグイン 
	// ※ 通常フィールド
	datepicker = $("#datepicker")
		.datepicker(datepicker_option)
		.val( (new Date()).datestr("/") )
		.css( "width", "100px" );

	// この処理は、IE のみで動作します
	$("#target").on("focus",function(){
		datepicker.datepicker( "hide" );
	});

	// jQuery DatePicker プラグイン 
	// ※ ダイアログ表示
	$("#datetDialog").click(
		function() {
			$( "#datepicker" ).datepicker(
				"dialog",
				$("#datepicker").val(),
				function(sdate) {
					$("#datepicker").val( sdate );
				},
				datepicker_option
			);
		}
	);

	// Google Chrome 用
	$("#targetDate").val((new Date()).datestr("-"));

	// IFRAME フィット用
	$(window).on("resize", function(){

		var iframe_id = "target";

		document.getElementById(iframe_id).style.display = "none";
		control_page_iframe(iframe_id);
		document.getElementById(iframe_id).style.display = "";

	});

	// 初期 IFRAME フィット
	control_page_iframe("target");

});
</script>
</head>
<body>
<div id="wrapper">
	<div id="head_unit">
		<form target="target_iframe" action="iframe_test.php" accept-charset="utf-8">
			<input id="targetDate" name="date" type="date">
			<input type="submit" name="send" value="送信">
			<input type="submit" name="send" value="リセット">
			jQuery DatePicker: <input name="date2" type="text" id="datepicker">
			<input
				id="datetDialog"
				type="button"
				value="dialog">
		</form>
	</div>
	<!-- frameborder はサイズ調整させるので境界は無しで設定 -->
	<!-- ここでは IE8 コンパチブルなので CSS では消せません -->
	<iframe
		id="target"
		name="target_iframe"
		frameborder="0"
		src="iframe_test2.php"
	></iframe>
</div>

</body>
</html>

▼ IFRAME 内のコード
<?php
header( "Content-Type: text/html; Charset=shift_jis" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
// IE 用
header( "x-ua-compatible: IE=8" );

?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=shift_jis">

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<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.10.1/jquery-ui.min.js"></script>
<script>
$(function() {

	// この処理は、一般的なブラウザと最新の IE( IE11で確認 )で動作します
	$(window).on("focus",function(){
		parent.datepicker.datepicker( "hide" );
	});

});
</script>
<style>
body {
	background-color: #c0c0c0;
}
</style>
</head>
<body>

<img src="https://lh6.googleusercontent.com/-ShzpKMxTsDU/VJ6mrePilbI/AAAAAAAAYA8/YNag5FGr5Qg/s402/freefont_logo_kana003.png" style="border: solid 0px #000000">

<br><br>
あいうえおかきくけこさしすせそたちつてとあいうえおかきくけこさしすせそたちつてとあいうえおかきくけこさしすせそたちつてとあいうえおかきくけこさしすせそたちつてとあいうえおかきくけこさしすせそたちつてとあいうえおかきくけこさしすせそたちつてとあいうえおかきくけこさしすせそたちつてと

</body>
</html>

このページのコードは、INPUT 要素の type="date" の利用のテストも兼ねています。jQuery を使ってしまったほうが簡単ではありますが、既存の FRAME 仕様のページでカレンダーを使うとなると、現在 Google Chrome と Opera でしか動作しません。この二つのブラウザはほぼ同じ仕様でカレンダーが表示されますが、FRAME の境界を越える事ができるので、IE の ActiveX の DatePicker の代替えとして利用可能です。

ですが一つ問題があって・・・

このデモページでは対応済ですが、初期値のセット方法として日付フォーマットが -(ハイフン) 区切りである必要がある上に、月と日は2ケタの前ゼロでなければダメです。さらに、表示は /(スラッシュ)区切りで、かつサーバーに送信されると -(ハイフン)区切り になります。



サーバーサイドはそちらで対応すれば良いですが、もともと JavaScript で日付文字列の操作が面倒なので、String オブジェクトと Date オブジェクトに メソッドを追加して使っています。
String.prototype.right = function(n){
	var str = this.valueOf();
	str = str.substr(str.length-n,n);
	return str;
}
String.prototype.zero = function(n){
	var strzero = "0000000000000000000";
	var str = this.valueOf();
	str = strzero + str;
	return str.right(n);
}
Date.prototype.datestr = function(sep){
	str = this.getFullYear() + sep + (this.getMonth()+1).toString().zero(2) + sep + (this.getDate()).toString().zero(2);
	return str;
}

jQuery もチューニングしています

blur イベントを処理しないと、カレンダーを表示した後、IFRAME 内に移動した時にカレンダーが閉じませんでした。
blur イベントを処理してしまうと、カレンダー内部のコントロールをクリックすると閉じてしまったので、IFRAME 側のイベントで対応しました。しかし、IE8 では、IFRAME 側(内部から window)の focus イベントで動作しなかったので、IFRAME を表示しているほうからの focus イベントで対処しています

関連する記事

Google Chrome 専用 jQuery プラグイン : DatePicker( type=date ) の個別機能の設定を行います / 当日セット、キーイベントキャンセル、専用ボタン非表示




posted by lightbox at 2015-08-19 11:29 | JavaScript コンテンツ | このブログの読者になる | 更新情報をチェックする

2014年11月03日


bitly.com へ URL を渡してページを開く方法

2011年に記事を書いた時より、URL が変わっていましたので修正します

やってみたら「できた」というレベルなので、仕様とかを調べたわけではありません

( あまりに長い URL はエラーになるかもしれません / 2011年当時の事なので )
function jumpBitly(strUrl) {

	strUrl = encodeURIComponent( strUrl );
	strUrl = strUrl.replace("%20", "+");
	window.open( "http://bitly.com/shorten/?url="+strUrl );

}






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

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

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

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

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


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

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

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

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

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

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

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