jQueryのAjaxを使って外部HTMLの一部を抜き出し挿入する

皆様こんにちは。普段はC++やってます。

本題に。

# jQueryを用いて単にhtmlを読み込み表示する

これは簡単です。
http://yokano-jp.blogspot.jp/2013/10/jquery-html_10.html
より引用します

```html:index.html
<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>jQuery load() sample</title>
 </head>
 <body>
  <h1>ここに外部 HTML ファイルを表示します</h1>
  <div id="page"></div>
  
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  <script src="load.js"></script>
 </body>
</html>
```

```html:external.html
<h2>外部ファイル</h2>
<p>この文章は external.html に記載された外部 HTML の文章です</p>
```

```js:load.js
$(function() {
 $('#page').load('external.html');
});
```

簡単ですよね

# jQueryのAjaxを使って外部HTMLの一部を抜き出し挿入する

ええ、違うんです、やりたいのはそうじゃない。そもそも、その``external.html``、HTMLとして成立してねーだろ。

じゃあどうするか？こうじゃ。

```html:index.html
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>jQueryのAjaxを使って外部HTMLの一部を抜き出し挿入する</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
		<script src="load.js"></script>
	</head>
	<body>
		<h1>ここに外部 HTML ファイルを表示します</h1>
		<div id="page">dst</div>
		<div id="page2">dst</div>
	</body>
</html>
```

```html:external.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>external-ありきたりとは</title>
</head>
<body>
	<div id="sub">
		<h2>外部ファイル</h2>
		<p>この文章は external.html に記載された外部 HTML の文章です</p>
	</div>
	<div id="sub2">
		<h2>外部ファイル</h2>
		<p>これはありきたりな文章です</p>
	</div>
</body>
</html>
```

```js:load.js
$(function() {
	$.ajax('external.html', {
		timeout : 1000, // 1000 ms
		datatype:'html'
	}).then(function(data){
        var out_html = $($.parseHTML(data));//parse
        $('#page').empty().append(out_html.filter('#sub')[0].innerHTML);//insert
        $('#page2').empty().append(out_html.filter('#sub2')[0].innerHTML);//insert
        //var sub_html = out_html.filter(function(index) {
        //    return $(this).attr("id") === "sub";
        //})[0].innerHTML;//extract
        //var sub2_html = out_html.filter(function(index) {
        //    return $(this).attr("id") === "sub2";
        //})[0].innerHTML;//extract
        //$('#page').empty().append(sub_html);//insert
        //$('#page2').empty().append(sub2_html);//insert
	},function(jqXHR, textStatus) {
        if(textStatus!=="success") {
            var txt = "<p>textStatus:"+ textStatus + "</p>" +
                "<p>status:"+ jqXHR.status + "</p>" +
                "<p>responseText : </p><div>" + jqXHR.responseText +
                "</div>";
        	$('#page').html(txt);
            $('#page2').html(txt);
        }
    });
	// $('#page').load('external.html');
});
```

jQueryは楽でいいですね・・・。それに引き換え、C++のboost.asioは(ry。

ajaxに渡すパラメータは最低限``timeout``と``datatype``だけあれば十分です。
ajaxのcallbackは``done()/error()``を使う方法もありますが、他言語との共通性の観点から``then()``を使います。C++にも標準にfuture/thenとかpromiseとか入るらしいね、やっと。
``then()``の第1引数が成功した時、第2引数が失敗した時に呼ばれる関数を登録するところです。

thenの第一引数に登録した関数の第一引数``data``にはhtmlが**文字列として**入ってきます。[どういうわけかlocalでテストすると``XMLDocumet``型になるんですが](https://twitter.com/yumetodo/status/706071299508973568)。

でそれを取り出すのに

```js
var h = $("#sub", $(data));
var h = $("#sub", $(data)).html();
var h = $("#sub", $($.parseHTML(data)));
var h = $($.parseHTML(data)).find('#sub').text()
```

とかとかいろいろやりましたが**全部ダメです**

じゃあどうするかというと、``$.filter()``関数をつかえばいいです。~~こいつは条件を満たした(引数に指定する関数が``true``を返す)ものだけを~~第一引数にidとかで指定かければ、それに合うものだけjQuery特有のあのarrayもどきなobjectに入れて返します。

**まともなhtmlを書いていればidは重複しないので**0番目の要素がほしい部分になります。

あとはその``innerHtml``を挿入すればいいです。

# GitHubに上げた

https://github.com/yumetodo/jQuery_Ajax_get_html_test

はい。デモページは

http://yumetodo.github.io/jQuery_Ajax_get_html_test/index.html

# 余談

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/yumetodo">@yumetodo</a> それ、jQuery使わないで自分でXHR生で使った方が早かったんじゃね？</p>&mdash; Chikuzen (@mtfmk) <a href="https://twitter.com/mtfmk/status/707873470382641153">2016, 3月 10</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

いいんですよ！私はthenって書きたかったんだ！

# 参考リンク

- [jQuery.ajax()で取得したHTMLの一部を抜き出す方法: 小粋空間](http://www.koikikukan.com/archives/2013/12/05-012345.php) (さっぱり動かなかった)
- [javascript - Setting timeout jQuery.load() - Stack Overflow](http://stackoverflow.com/questions/12734444/setting-timeout-jquery-load)
- [jquery - ajax timeout callback function - Stack Overflow](http://stackoverflow.com/questions/16533360/ajax-timeout-callback-function)
- [javascript - jQuery() not finding elements inside of results from jQuery.parseHTML() - Stack Overflow](http://stackoverflow.com/questions/15403600/jquery-not-finding-elements-inside-of-results-from-jquery-parsehtml)(質問者自ら書いている回答に``$.filter()``使えとあります。これのおかげで救われました)
- [filter(fn) - jQuery 日本語リファレンス](http://semooh.jp/jquery/api/traversing/filter/fn/)