Google Chromeでは javascript の window.close() で自分自身を消すことができない?効かない?


表題の件、javascriptのwindow.close()について、いろいろとテストをしてみた。

結論から言うと、Google Chromeでは javascript の window.close() で自分自身を消すことができないです。効かないです、ハイ。

忙しい人や、とりあえず結果だけ知りたい人は別に以下読まなくてもいいんじゃね?以下は「できない」ことを検証しただけだから。

さてさて、
以下のような簡単なコードを書いてみてテストしてみる。

sample1.htm

<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<script>
$(function(){
    $(document).on("click","#close_window",function(){
        //自分自身を閉じる
        window.close();
    });
});
</script>
<button id="close_window">Close Window</button>
</body>
</html>

↑のHTMLファイルを作りChromeブラウザの「お気に入り」から(URLアドレス欄にパスを張り付けてもおなじ)「sample1.htm」を表示させてボタン「Close Window」を押すと、

Scripts may close only the windows that were opened by it.

というエラーが出て画面を閉じることができない。
一方で、「sample1.htm」のファイルを「ファイルの右クリック→プログラムから開く→Google Chrome」とすると
あら不思議、さっきまでウンともスンとも言わなかったのに見事にタブが消えるじゃありませんか。

もうちょっとツッコんでテストしてみる。

以下の2つのファイルを作ってみる。

sample2.htm

<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<script>
$(function(){
    var childWindow;
    $(document).on("click","#open_child_window",function(){
        //別窓でsample3.htmを開く
        childWindow = window.open("./sample3.htm","window_close_2","_blank");
    });
    $(document).on("click","#close_child_window",function(){
        //別窓で開いたsample3.htmを閉じる
        childWindow.close();
    });
});
</script>
<button id="open_child_window">Open Child Window</button>
<button id="close_child_window">Close Child Window</button>
</body>
</html>

sample3.htm

<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<script>
$(function(){
    $(document).on("click","#im_close",function(){
        //自分自身を閉じる
        window.close();
    });
    $(document).on("click","#close_parent",function(){
        //自分自身開いた親を閉じる
        window.opener.close();
    });
});
</script>
<button id="im_close">Im Close</button>
<button id="close_parent">Close Parent Window</button>
</body>
</html>

例ごとく、Chromeの「お気に入り」から「sample2.htm」を開く。
ボタン「Open Child Window」を押すと普通に別窓で「sample3.htm」が開く。
別窓「sample3.htm」のボタン「Im Close」を押すと、別窓「sample3.htm」が普通に消えてくれる。
これは問題ないようだ。

もう一つのボタン「Close Parent Window」を押すと、これは効かない。
案の定、「Scripts may close only the windows that were opened by it.」だ。
さて、前の実験と同じく、「sample2.htm」を「ファイルの右クリック→プログラムから開く→Google Chrome」とすると
あら不思議、「Close Parent Window」も動作して「sample2.htm」が表示されているタブもスコッと消える。

最後にもう一つテスト。
以下の二つのファイルをつくる。

sample4.htm

<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<script>
$(function(){
    $(document).on("click","#move_next",function(){
        //sample4.htmに画面移動する
        location.href="sample5.htm";
    });
});
</script>
<button id="move_next">Move Next</button>
</body>
</html>

sample5.htm

<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
$(function(){
    //即座に自分自身を閉じる
    window.close();
});
</script>
<span>ほげほげ!!</span>
</body>
</html>

これも同じように「お気に入り」からと「右クリック→プログラムから開く」で試してみると、
「お気に入り」のほうは「sample5.htm」が表示されたまま止まり、
「Scripts may close only the windows that were opened by it.」となるが、
「右クリック」のほうは「sample5.htm」が表示された瞬間に消える。

結論としては・・・・

  • Google Chromeでは親タブ、親ウィンドウをJavascriptから(window.close()で)閉じることはできない。
  • ただし、window.openで開いた子ウィンドであれば自分自身からでも親からでも閉じることができる。
  • もちろん子ウィンドウから親ウィンドウは消すことはできない。

WEBサイトやWEBサービスを作るうえで、
「ファイルの右クリック→プログラムから開く→Google Chrome」なんてやるわけないから、
実質のところGoogle Chromeでは親画面(=初期表示ウィンドウや初期表示タブ)はスクリプトから消すことはできないようだ。
まぁ考えてみればセキュリティ的にもUI的にもいきなり画面が消えるなんてことはNGだからっちゅうことかしらね。
ってことで、この記事を書くきっかけとなった「URL直打ちされてタブ画面として開かれてしまった画面を別ウィンドウに移動させる」という課題は頓挫いたしましたとさ、チャンチャン。

ちなみにIEでは自分自身をWindow.close()で消すことができます。ただ、「消していいですか?」的なダイアログがでるので、どっちみにユーザのクリック動作が必要になるけど。自動的にスコっとウィンドウやタブを落とすのはできないのね。

jQueryでcheckboxにチェックを入れる/外すにはporp()を使え!!


ん?

checkboxにチェックを入れる → $("***").attr("checked",true);
checkboxにチェックを外す → $("***").attr("checked",false);

じゃねぇの?

やってみたら、一度チェックを入れるとチェックが入らない・・・

どうやら jQuery 1.6 のあたりからporp()というメソッドが実装されたそうで、attr()ではなくporp()を使う方がよいとのこと。

使い方やそもそもどういうメソッドなのかは↓やらを参考のこと。

jQueryにおけるattrとpropの違いと使いドコロまとめ
http://qiita.com/kbyay_/items/7a7ce9547f29b34a63b1

checkboxにチェックを入れる → $("***").prop("checked",true);
checkboxにチェックを外す → $("***").prop("checked",false);

ってするほうがいいようで。

GoogleMapで地図描画前に描画要素をdisplay:none;すると表示がおかしくなる(中心がズレて表示される)


GoogleMapAPI とか GoogleMap埋め込み などを利用している場合、MAP描画前にiFrame要素や、APIで描画仕様としているボックス要素を display: none; で表示を消してしまうと表示がおかしくなる。

べつに表示されないわけではないのだけど、地図の中心がずれたりする。この問題の回避策はJavascriptなどを利用してロード開始時には表示しておき、ロード後に非表示にするしかない。

試してみたところ、

<div style="height: 0px; overflow: hidden;">

としても地図は問題なく表示されたので、初期設定は左記ほのとおりスタイルを設定しておき、ロード後にjQueryなどで

$("div").css("height","").css("overflow","")

として初期設定を消してやればいいだろう。

IE8 + jqueryでselect要素を複製(clone)した後にoption要素を編集するとエラーが生じる


jQueryでselect要素をまるっと複製(clone)して、その後に$(this).append(“~~”)$(this).empty().html(“~~”)などでoption要素を編集すると、IEでのみ、かな~りヘンな挙動になり、問題が生じる(Firefox、Chromeでは無問題)。

option要素は正しく追加されているのに、プルダウンを出してみると変更前の表示が残っていて、選択すると新しいデータが反映される・・とか意味わからん現象になる。

↓初期表示は「<option>ほげほげ</option>」としとく。

$(this).empty().append(“<option>うがうが</option>”);としてoption要素を入れ替える。

↓あれ?プルダウンしてみると、変更前の「ほげほげ」になったままで変わってない・・・

↓「ほげほげ」を選択してみると・・・「うがうが」になる・・・いみわからん・・・

ちなみにこの現象はjQuery ver 1.8.1(2012/9/21現在の最新版)でも発生している。原因はわからないんだけど、悪いとしたらjQueryかIEのバグになるんだけど、動きをている限り、たぶんjQueryのバグじゃなくてIEバグっぽいニホイが・・・

ネット上で色々と情報を探ると「jQueryオブジェクトとselect要素(もしくはoption要素)の相性が悪い」という記事が散見されるんだけど「select要素をイジルと必ず~」というもので、どうやらIE6でのバグが原因らしい。

IE8と最新のjQueryではここらへんは解消されている様子。ただし、今回の現象はIE8で「クローンしたselect要素のみ」おかしな現象が起きている。

結論を言うと「select要素から作り直す」と問題が解消された。

いろいろと先達の対策を試してみたのだけど、ダメで、$(this).remove() してからselect要素とoption要素をぜ~~んぶ作り直す。このときはjQueryをフル活用しても問題ない。そうするとIEでも問題なく動作した。

まぁ、原因は今でもさ~~っぱりわからないんだけど、「IE + jQueryオブジェクト + select要素(oprion要素)」は今でも相性が悪いらしい。

ってか、くたばれIE。テメェのせいでどんんだけイラン時間つこうてるかわからん!!

jQueryをつかってHTML文字列を表示させるときにIEで文字化けする


以下の処理を行うときになぜかIEでのみ文字化けする現象にぶち当たった。

A.phpにイベントを仕掛けて

jQueryのAjaxメソッド発動

B.phpにAJAXリクエストをなげて

B.phpでHTMLテキストを生成して

A.phpのAjaxメソッドに戻して

A.php内のボックスに$(~).html(~)でHTMLテキストを描画

なぜかIEでのみ文字化け!! (´;ω;`)

なぜかIEの「ページ→エンコード→自動選択」をONにすると文字化けがおこらない。

ChromeやFirefoxでは文字化けは一切おこらない。

さらに、自分のテスト環境ではおこらず、本番環境でのみ発生する。

おそらく、ApacheかPHPの設定が異なるために起こっているのだと思う。

(詳細はしらべてないのでシラネ)

ってことで早速Google先生をシバキ倒してみたら、↓に答えのヒントを書いてくれているエロいひとを発見。

感謝感謝。

ズバリ以下のコードをHTMLテキストを吐く直前に書いてやればいい。

header(“Content-type: text/html; charset=UTF-8”);

前述のヒトはJSONデータでお困りだったようだけど、今回は「text/html」なので、そこらへんを修正ってことね。

以上、めでたし、めでたし。

JavaScriptのsubstrメソッド第1引数はIEでは負数を指定できない。


Javascriptの文字列抽出メソッドであるsubstrメソッドやsubstringメソッドでは第1引数に負の値(負数)を指定すると、文字列の後ろからカウントする仕様になっている。しかし、IEでは、第1引数に負数を指定しても「0」とされてしまい、他のブラウザと挙動が異なり、エラーとなってしまう。

結論を言えばこれを回避するためにはsliceメソッドを使う。もしくはsliceメソッドをメソッドチェーンして複数回を組み合わせる。

“ABCDEFGH”.substr(-4.2)

の場合、IE以外では”EF”となるがIEでは”AB”となってしまう。

そこで、IEでも”EF”を得たい場合には、

“ABCDEFGH”.slice(-4).slice(-2)

とするとIEでも”EF”を得ることができる。

詳しい事は↓で紹介してくれているので見てほしい。

「戻る」ボタン(もしくは history.back() )で前ページで入力していたフォーム内容が消えてしまう問題の対処法


Formでとある内容を次ページにPOSTで送った後に、

「戻る」ボタン、もしくは history.back() で前ページ(入力フォーム画面)に戻ったら、

フォーム内容が消える問題に遭遇。

んで、色々と実験しながら調べていたんだけど、現状だと

  • IE8 => NG
  • FireFox5.0 => NG
  • Chrome12.0 => OK

というな~ぜかChromeだけちゃんと動いてくれている様子。

さてどうしたもんか、と。

submitで前ページに入力内容を戻して~

$_POSTで受け取って~

セキュリティチェックかけて~

htmlspecialcharsでサイニタイズして~

Formに書き出す?

=゚ロ゚)ノ ⌒┫:・’.::ヤッテラレルカァァァァァ!!!!

そんなこと繰り返すからセキュリティホールが増えるんじゃぼけぇ~

(ノ ̄皿 ̄)ノヤッテラレルカァァァァァ!┫:・’.::

そこで、色々調べていたら、

と。

しかし、「session.cache_limiter」を調べてみたら、ブラウザもしくはプロキシサーバにキャッシュ保存可否を伝えるスイッチで、考えなしに「public !!」とはしたくない。

が、しかし、phpではうまいこと抜け道を用意してくれていました!!エライ!!

実はPHPは「session_cache_limiter()」ちゅう便利な関数を用意してくれているので、当該個所にこれを置いてやればおk。

そのページだけキャッシュするようにできます。

ただし、この session_cache_limiter() は session_start() がコールされる前に実行しなければダメ。

まぁ、根本解決ではないけど、これでとりあえずの回避はできるはず。

「これじゃやだ」ってヒトはシコシコと「戻る」処理を書くしかないんじゃないの?

がんばれば?おれはやんねぇけど。




LightBoxライクの画像ギャラリー「piroBox」をWordPressに実装してみた


う~ん

すご~く簡単。

しかもスライドショーとかできちゃって結構イイ感じ。

まず一式をここからダウンロード

以下のファイルを読み込んで(サーバにUPして)、

  • pirobox.min.js
  • style.css(※内部に記載されている画像パスに注意)
  • 画像一式
  • (ひつようであればjQuery本体)
<script type="text/javascript">
$(document).ready(function() {
	$().piroBox({
		my_speed: 400,
		bg_alpha: 0.1,
		slideShow : true,
		slideSpeed : 4,
		close_all : '.piro_close,.piro_overlay'
	});
});
</script>

と書いて(ここらへんのパラメータは本家サイトのドキュメントを適当にみてくれ)、

<a href="images/1.jpg" class="pirobox_gall" title="Spain 2009">
<img src="images/1s.jpg" />
</a>

とimgタグをクラス指定したaタグで囲むだけ。

簡単簡単。

でも

jQueryの1.4.4で動かなかったから注意。

なぜかpiroBoxについてる1.4.2では動くんだよね。

ちなみに俺はwordpressに別途jQuery Ver1.6を読み込ませて使いました。

1.6でも問題なく動いてる(ここで)。

jQuery.getJSON( url, data, callback )の第2引数([data])について


jQueryのJSONを取得するgetJSONメソッドの第二引数である[data]についてなんだけど、

data
------------------------------
	Map
	キーと値の組み合わせ

とか

[data] : サーバに送信するパラメータ。キーと値のペア(ハッシュ)。(オプション)

とか書かれてもサル並みの脳みそしかない俺にはわからんのですよ。

これなんだろうなぁ~とGoogle先生と格闘していたら、カスにもわかるように明確に書いているところを見つけたましたよ。

ズバリ↓です。

jQuery | お勉強の軌跡

http://extra.pxt.jp/studylog/ja/javascript/jquery/index.html


第二引数の data にオブジェクトを渡すと、URLの後ろにGETパラメータとして付加されます。上記の例の {a:12,b:14} を指定した場合、?a=12&b=14が付加されます。

つまり、PHPならJSON生成ファイル側で↓のようにうけとればよろし。

$hogehoge = $_get["a"];
$piyopiyo = $_get["b"];

ってか↓とかさ、もちっと丁寧に書けよ。わかんね~よ

jQuery.getJSON( url, data, callback ) – jQuery 日本語リファレンス

http://semooh.jp/jquery/api/ajax/jQuery.getJSON/+url,+data,+callback+/

jQuery プラグインの jquery.validate.js を使って入力チェック機能を仕込んでみた。


このエントリでは、私が WordPress + Contact Form 7 + jquery.validate.js という環境を構築中にハマったところがあったので備忘録を兼ねて書いておく。

なお、私が参考にしたサイトを張っておく。基本的なところは先達者が詳しく書いてくれているので先に一読されることをお勧めする。

jquery.validate.js 公式:

http://bassistance.de/jquery-plugins/jquery-plugin-validation/

jQueryでフォームの入力チェックする、jquery.validate.js とエラーの日本語化:Goodpic:

http://www.goodpic.com/mt/archives2/2008/06/jqueryjqueryval.html

まず、重要なところから書くと

jquery.validate.js の バージョン1.8.0「jquery-validation-1.8.0」はIEでまともに動かない!!

ということで、

すぐに最新版のバージョン1.8.1「jquery-validation-1.8.1」にバージョンアップしよう。

また、Contact Form 7 ではformタグにid属性が付与されないが、class属性がデフォルトで付与されているので、class属性値を指定することで問題なく動作する。

なお、Contact Form 7 タグでjquery.validate.jsを使用する際には、[text* name 15/15 id:name class:required]というように記述するのが一般的だが、私は以下のようなjsファイルを別途作成、ロードさせた。