一昔前まではサイトそのものをフレーム構造にしたり iframe を使って新着情報などを埋め込むサイトを良く見かけましたが、HTML5 と Ajax が定着してからはあまり見なくなりました。frameset や frame タグ自体廃止され、唯一残った iframe も iPhone や android の登場により使いにくいものとなってしまったことが理由の一つかと思います。
今回は jQuery の load() を使って他のページを GET, POST の二つの方式を用いて読み込むサンプルを作ってみようと思います。
GET
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Ajax Load</title> <script src="//code.jquery.com/jquery-1.12.0.min.js"></script> <script> function loadPage(page){ $("#content-frame").load("pages.php?page=" + page); } </script> </head> <body> <ul> <li><a href="javascript:loadPage(0);">Page 1</a></li> <li><a href="javascript:loadPage(1);">Page 2</a></li> <li><a href="javascript:loadPage(2);">Page 3</a></li> </ul> <div id="content-frame" style="width: 300px;height:200px;overflow:scroll;border:1px solid #DDD;"> Sample </div> </body> </html>
pages.php
<?php $content1 = <<<EOD <h1>Hello, World!</h1> <p>page 1</p> EOD; $content2 = <<<EOD <h1>Foo Bar</h1> <p>page 2</p> EOD; $content3 = <<<EOD <h1>Lorem Ipsum</h1> <p>page 3</p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> EOD; $pages = array($content1, $content2, $content3); $page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT); $page = ($page !== false) ? (int)$page : 0; if(isset($pages[$page])){ echo $pages[$page]; } else { echo 'Not Found.'; }
GET パラメータ「page」を pages.php を渡し、そのページ番号に応じて HTML を返すという単純なものです。
$("#表示先ID").load(読み込むページのURL); という形で指定します。
iframe と違い要素内に直接読み込まれるので <html> や<body> などのタグは使いません。
また、CSS などは読み込み元のページのスタイルが適用されます。
POST
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Ajax Load</title> <script src="//code.jquery.com/jquery-1.12.0.min.js"></script> <script> function submitMessage(page){ var params = {message: $('#message').val()}; $("#content-frame").load("hello.php", params); } </script> </head> <body> <p> <input id="message" type="text"> <input type="button" onclick="submitMessage()" value="Submit"> </p> <div id="content-frame" style="width: 300px;height:200px;overflow:scroll;border:1px solid #DDD;"> Sample </div> </body> </html>
hello.php
<?php $message = (string)filter_input(INPUT_POST, 'message'); echo '<p>Hello, ' . htmlspecialchars($message, ENT_QUOTES, 'UTF-8') . '!</p>';
load() の第二引数にオブジェクトを指定した場合 POST メソッドが使用されます。
サンプルではテキストボックスの文字列を post.php に送信し、post.php は送られてきた文字に「Hello, 」をつけて返します。
POST の際にCSRF(クロスサイトリクエストフォージェリ)対策としてトークンを送信する必要がある場合、ajaxSetup() を使って拡張ヘッダに埋め込んでしまうのが良いと思います。
<meta name="csrf-token" content="<?php echo $token;?>"> <script> $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); </script>
送信されたヘッダのトークンは PHP では $_SERVER["HTTP_X_CSRF_TOKEN"]; として受け取ることができます。
また、より複雑な通信を行う必要がある場合は load() の代わりに ajax() を使うことになります。
以下は同じ動作を ajax() を使う形に変更したものです。
function submitMessage(page){ var params = {message: $('#message').val()}; $("#content-frame").load('hello.php', params); $.ajax({ url: "hello.php", data: params, type: "POST", success: function(html) { $("#content-frame").html(html); } }); }