「テンプレート:駅名 飲食店ページ」の版間の差分
提供: 川西図鑑
その他の操作
ページの作成:「<noinclude> {{#template_params:}} </noinclude><includeonly> {{#template_display:_format=table}}</includeonly>」 |
編集の要約なし |
||
| 1行目: | 1行目: | ||
< | <html> | ||
{{# | <nav class="breadcrumb"> | ||
</ | <a href="/">ホーム</a> | ||
{{# | › <a href="/wiki/飲食店検索">飲食店検索</a> | ||
<span id='navText'></span> | |||
</nav> | |||
<style> | |||
.breadcrumb { | |||
font-size: 14px; | |||
color: #555; | |||
margin-bottom: 12px; | |||
} | |||
.breadcrumb a { | |||
color: #3366cc; | |||
text-decoration: none; | |||
} | |||
.breadcrumb span { | |||
color: #333; | |||
font-weight: bold; | |||
} | |||
.search-intro p { | |||
margin: 4px 0; | |||
} | |||
/* --- 検索説明文(ライトテーマ) --- */ | |||
html.skin-theme-clientpref-day .search-intro { | |||
background: #f7f9fc; | |||
padding: 12px 16px; | |||
border-radius: 8px; | |||
margin-bottom: 20px; | |||
font-size: 0.95rem; | |||
line-height: 1.6; | |||
} | |||
/* --- 検索説明文(ダークテーマ) --- */ | |||
html.skin-theme-clientpref-night .search-intro { | |||
background: #1f2430; | |||
color: #e5e7eb; | |||
padding: 12px 16px; | |||
border-radius: 8px; | |||
margin-bottom: 20px; | |||
font-size: 0.95rem; | |||
line-height: 1.6; | |||
} | |||
</style> | |||
</html> | |||
<div class="search-intro"> | |||
<p> | |||
川西市で人気の<strong>{{{genre}}}</strong>のお店を一覧でご紹介しています。 | |||
</p> | |||
<p> | |||
下の検索フォームを使えば、さらに条件を絞り込んで探すこともできます。 | |||
</p> | |||
</div> | |||
== 検索条件 == | |||
<!-- 検索ボックス --> | |||
<html> | |||
<form method="get" action="/wiki/飲食店検索" id="searchForm"> | |||
<div style="padding: 10px;"> | |||
<div class="form-row"> | |||
<div class="clear-btn">クリア</div> | |||
<input type="submit" value="検索" class="search-btn" /> | |||
</div> | |||
<!-- 予約可 --> | |||
<div class="form-row"> | |||
<span>予約できる店だけ</span> | |||
<label class="toggle"> | |||
<input type="checkbox" name="reservable" value="1"> | |||
<span class="slider"></span> | |||
</label> | |||
</div> | |||
<!-- 店名 --> | |||
<input class="form-row inputbox" type="text" name="searchText" placeholder="店名" id="searchText"/> | |||
<!-- ジャンル --> | |||
<div class="form-row"> | |||
<select name="genre" id="genre" class="inputbox"> | |||
<option value="">すべてのジャンル</option> | |||
<option value="居酒屋">居酒屋</option> | |||
<option value="ダイニングバー・バル">ダイニングバー・バル</option> | |||
<option value="創作料理">創作料理</option> | |||
<option value="和食">和食</option> | |||
<option value="洋食">洋食</option> | |||
<option value="イタリアン・フレンチ">イタリアン・フレンチ</option> | |||
<option value="中華">中華</option> | |||
<option value="焼肉・ホルモン">焼肉・ホルモン</option> | |||
<option value="韓国料理">韓国料理</option> | |||
<option value="アジア・エスニック料理">アジア・エスニック料理</option> | |||
<option value="各国料理">各国料理</option> | |||
<option value="カラオケ・パーティ">カラオケ・パーティ</option> | |||
<option value="バー・カクテル">バー・カクテル</option> | |||
<option value="ラーメン">ラーメン</option> | |||
<option value="お好み焼き・もんじゃ"> お好み焼き・もんじゃ</option> | |||
<option value="カフェ・スイーツ">カフェ・スイーツ</option> | |||
<option value="その他グルメ">その他グルメ</option> | |||
</select> | |||
</div> | |||
<!-- 最寄り --> | |||
<div class="form-row"> | |||
<select name="station" class="inputbox" id="station"> | |||
<option value="">最寄り駅:指定なし</option> | |||
<option value="川西能勢口駅">川西能勢口</option> | |||
<option value="雲雀丘花屋敷駅">雲雀丘花屋敷</option> | |||
<option value="川西池田駅">川西池田</option> | |||
<option value="北伊丹駅">北伊丹</option> | |||
<option value="絹延橋駅">絹延橋</option> | |||
<option value="滝山駅">滝山</option> | |||
<option value="鴬の森駅">鴬の森</option> | |||
<option value="鼓滝駅">鼓滝</option> | |||
<option value="多田駅">多田</option> | |||
<option value="平野駅">平野</option> | |||
<option value="一の鳥居駅">一の鳥居</option> | |||
<option value="畦野駅">畦野</option> | |||
<option value="山下駅">山下</option> | |||
<option value="笹部駅">笹部</option> | |||
</select> | |||
</div> | |||
<!-- 予算 --> | |||
<div class="budget-box"> | |||
<label>予算</label> | |||
<div> | |||
<label><input type="radio" name="lanch-dinner" value="lanch">昼</label> | |||
<label><input type="radio" name="lanch-dinner" value="dinner">夜</label> | |||
</div> | |||
<div> | |||
<label>下限</label> | |||
<select name="budget_min" id="budget_min"> | |||
<option value="">指定なし</option> | |||
<option value="1000">1,000円</option> | |||
<option value="2000">2,000円</option> | |||
<option value="3000">3,000円</option> | |||
</select> | |||
<span>〜</span> | |||
<label>上限</label> | |||
<select name="budget_max" id="budget_max"> | |||
<option value="">指定なし</option> | |||
<option value="2000">2,000円</option> | |||
<option value="3000">3,000円</option> | |||
<option value="5000">5,000円</option> | |||
</select> | |||
</div> | |||
</div> | |||
</div> | |||
<!-- こだわり(アコーディオン) --> | |||
<details class="accordion"> | |||
<summary>こだわり条件</summary> | |||
<!-- 支払い --> | |||
<fieldset> | |||
<legend>支払い方法</legend> | |||
<label><input type="checkbox" name="credit"> カード</label> | |||
<label><input type="checkbox" name="emoney"> 電子マネー</label> | |||
<label><input type="checkbox" name="qr"> QRコード決済</label> | |||
</fieldset> | |||
<!-- 禁煙 / 喫煙 --> | |||
<fieldset> | |||
<legend>禁煙 / 喫煙</legend> | |||
<label style="width: 33%;"><input type="radio" name="smoking" value="" > 指定なし</label> | |||
<label style="width: 33%;"><input type="radio" name="smoking" value="non"> 禁煙のみ</label> | |||
<label style="width: 33%;"><input type="radio" name="smoking" value="allow"> 喫煙可</label> | |||
</fieldset> | |||
<!-- メニュー --> | |||
<fieldset> | |||
<legend>メニュー</legend> | |||
<label><input type="checkbox" name="tabehodai"> 食べ放題</label> | |||
<label><input type="checkbox" name="nomihodai"> 飲み放題</label> | |||
<label><input type="checkbox" name="takeout"> テイクアウト</label> | |||
</fieldset> | |||
<!-- 設備 --> | |||
<fieldset> | |||
<legend>設備・サービス</legend> | |||
<label><input type="checkbox" name="parking"> 駐車場</label> | |||
<label><input type="checkbox" name="privateroom"> 個室</label> | |||
<label><input type="checkbox" name="wifi"> Wi-Fi</label> | |||
<label><input type="checkbox" name="barrierfree"> バリアフリー</label> | |||
<label><input type="checkbox" name="kids"> お子様連れOK</label> | |||
<label><input type="checkbox" name="reserve"> 貸切</label> | |||
</fieldset> | |||
<div class="form-row"> | |||
<div class="clear-btn">クリア</div> | |||
<input type="submit" value="検索" class="search-btn" /> | |||
</div> | |||
</details> | |||
</form> | |||
<style> | |||
.clear-btn { | |||
margin-left: auto; | |||
padding: 8px 16px; | |||
background: #ccc; | |||
border-radius: 6px; | |||
cursor: pointer; | |||
user-select: none; | |||
font-size: 14px; | |||
color: black; | |||
} | |||
.clear-btn:active { | |||
opacity: 0.7; | |||
} | |||
.search-btn { | |||
margin-left: 10px; | |||
display: block; | |||
width: 75px; | |||
padding: 14px 0; | |||
background: #0078ff; | |||
color: #fff; | |||
font-size: 18px; | |||
font-weight: 600; | |||
text-align: center; | |||
border: none; | |||
border-radius: 8px; | |||
cursor: pointer; | |||
transition: all 0.25s ease; | |||
} | |||
#searchText, | |||
#searchForm select{ | |||
height: 35px; | |||
font-size: 1em; | |||
background-color: Canvas; | |||
color: CanvasText; | |||
} | |||
.inputbox { | |||
width: 100%; | |||
max-width: 450px; | |||
} | |||
#searchForm input[type="radio"], | |||
#searchForm input[type="checkbox"] { | |||
transform: scale(1.5); | |||
transform-origin: left center; | |||
margin-right: 15px; | |||
} | |||
#searchForm fieldset label { | |||
display: flex; | |||
align-items: center; | |||
width: 50%; | |||
box-sizing: border-box; | |||
margin-bottom: 8px; | |||
} | |||
#searchForm fieldset { | |||
display: flex; | |||
flex-wrap: wrap; | |||
} | |||
.search-form { | |||
max-width: 700px; | |||
margin: 1em auto; | |||
font-size: 14px; | |||
} | |||
.form-row { | |||
display: flex; | |||
align-items: center; | |||
margin: 0.5em 0; | |||
gap: 1em; | |||
} | |||
/* トグルスイッチ */ | |||
.toggle { | |||
position: relative; | |||
width: 40px; | |||
height: 22px; | |||
display: inline-block; | |||
} | |||
.toggle input { | |||
display: none; | |||
} | |||
.slider { | |||
position: absolute; | |||
cursor: pointer; | |||
inset: 0; | |||
background: #ccc; | |||
border-radius: 22px; | |||
} | |||
.slider::before { | |||
content: ""; | |||
position: absolute; | |||
height: 18px; | |||
width: 18px; | |||
left: 2px; | |||
top: 2px; | |||
background: white; | |||
border-radius: 50%; | |||
transition: .3s; | |||
} | |||
.toggle input:checked+.slider { | |||
background: #4caf50; | |||
} | |||
.toggle input:checked+.slider::before { | |||
transform: translateX(18px); | |||
} | |||
/* アコーディオン */ | |||
html.skin-theme-clientpref-day .accordion { | |||
margin-top: 1em; | |||
border: 1px solid #ccc; | |||
padding: 1em; | |||
border-radius: 6px; | |||
background-color: #f7f9fc; | |||
} | |||
html.skin-theme-clientpref-night .accordion { | |||
margin-top: 1em; | |||
border: 1px solid #ccc; | |||
padding: 1em; | |||
border-radius: 6px; | |||
background: #1f2430; | |||
color: #e5e7eb; | |||
} | |||
.accordion summary { | |||
cursor: pointer; | |||
font-weight: bold; | |||
} | |||
fieldset { | |||
border: none; | |||
margin: 1em 0; | |||
} | |||
legend { | |||
font-weight: bold; | |||
} | |||
.search-card { | |||
border: 1px solid #ddd; | |||
border-radius: 8px; | |||
padding: 10px; | |||
margin-bottom: 12px; | |||
max-width: 600px; | |||
transition: box-shadow 0.2s; | |||
max-height: 332px; | |||
} | |||
.search-card:hover { | |||
box-shadow: 0 2px 8px rgba(0,0,0,0.2); | |||
} | |||
.card-header { | |||
margin-bottom: 5px; | |||
} | |||
.card-title { | |||
margin: 0; | |||
} | |||
.card-genre { | |||
margin: 0; | |||
font-size: calc(1em - 3px); | |||
} | |||
.img-crop { | |||
height: 200px; | |||
overflow-x: auto; | |||
overflow-y: hidden; | |||
white-space: nowrap; | |||
} | |||
.img-crop p, | |||
.img-crop > div { | |||
height: 100%; | |||
margin: 0; | |||
display: flex; | |||
flex-direction: row; | |||
width: max-content; | |||
} | |||
.crop-img img { | |||
width: 200px; | |||
height: 200px; | |||
object-fit: cover; | |||
border-radius: 4px; | |||
display: inline-block; | |||
margin-right: 2px; | |||
} | |||
.card-info { | |||
margin-top: 10px; | |||
} | |||
.card-cost, .card-address { | |||
margin: 0; | |||
font-size: calc(1em - 3px); | |||
} | |||
</style> | |||
<script> | |||
document.getElementById('searchForm').addEventListener('submit', function (e) { | |||
const searchText = document.getElementById('searchText'); | |||
const genre = document.getElementById('genre'); | |||
const station = document.getElementById('station'); | |||
const budget_min = document.getElementById('budget_min'); | |||
const budget_max = document.getElementById('budget_max'); | |||
if (searchText.value === '') { | |||
searchText.removeAttribute('name'); // 空のとき name属性を削除 | |||
} | |||
if (genre.value === '') { | |||
genre.removeAttribute('name'); // 空のとき name属性を削除 | |||
} | |||
if (station.value === '') { | |||
station.removeAttribute('name'); // 空のとき name属性を削除 | |||
} | |||
if (budget_min.value === '') { | |||
budget_min.removeAttribute('name'); // 空のとき name属性を削除 | |||
} | |||
if (budget_max.value === '') { | |||
budget_max.removeAttribute('name'); // 空のとき name属性を削除 | |||
} | |||
}); | |||
document.addEventListener('DOMContentLoaded', function () { | |||
const clearBtn = document.querySelector('.clear-btn'); | |||
const form = document.getElementById('searchForm'); | |||
clearBtn.addEventListener('click', function () { | |||
form.reset(); | |||
}); | |||
const titleEl = document.querySelector('.mw-page-title-main'); | |||
const genre = titleEl ? titleEl.textContent.trim() : 'グルメ'; | |||
// タイトル生成 | |||
let title = `川西市でおすすめのおいしい${genre}をご紹介! | 川西図鑑`; | |||
// タイトル更新 | |||
document.title = title; | |||
// パンくず用テキスト生成 | |||
let nav = titleEl ? titleEl.textContent.trim() : ''; | |||
if (nav != '') { | |||
nav = ` › ${nav}`; | |||
} | |||
// パンくず更新 | |||
document.getElementById('navText').textContent = nav; | |||
// セレクトボックス制御 | |||
const el = document.querySelector(`[name="genre"]`); | |||
if (el) el.value = genre;; | |||
var count = document.getElementById("count"); | |||
count = count.dataset.total.toString(); | |||
if (count) { | |||
count = count + "件"; | |||
} else { | |||
count = ""; | |||
} | |||
// description生成 | |||
let desc = `「川西図鑑」では、兵庫県川西市で人気の${genre}のお店を ${count}掲載中。営業時間、アクセス、写真、地図などの詳細情報をまとめています。ランチやディナー、テイクアウトなど条件で絞り込みができ、地元でおすすめのお店が見つかります。`; | |||
let meta = document.querySelector("meta[name='description']"); | |||
if (!meta) { | |||
meta = document.createElement("meta"); | |||
meta.name = "description"; | |||
document.head.appendChild(meta); | |||
} | |||
meta.content = desc; | |||
// 現在のURL取得 | |||
let url = window.location.href; | |||
// ページネーション | |||
const fullurl = new URL(location.href); | |||
const page = parseInt(fullurl.searchParams.get('page') || '1', 10); | |||
// 最終ページ制御 | |||
const countMeta = document.getElementById('count'); | |||
if (!countMeta) return; | |||
const total = parseInt(countMeta.dataset.total, 10); | |||
const limit = parseInt(countMeta.dataset.limit, 10); | |||
if (isNaN(total) || isNaN(limit) || limit <= 0) return; | |||
const lastPage = Math.ceil(total / limit); | |||
if (lastPage <= 1) { | |||
const pagination = document.querySelector('.pagination'); | |||
if (pagination) pagination.style.display = 'none'; | |||
return; | |||
} | |||
if (page > lastPage) { | |||
fullurl.searchParams.set('page', lastPage); | |||
location.replace(fullurl.toString()); | |||
} | |||
if (page < 1) { | |||
fullurl.searchParams.set('page', 1); | |||
location.replace(fullurl.toString()); | |||
} | |||
function makeLink(targetPage) { | |||
fullurl.searchParams.set('page', targetPage); | |||
return fullurl.toString(); | |||
} | |||
// 各ボタン | |||
const first = document.querySelector('[data-role="first-page"]'); | |||
const prev = document.querySelector('[data-role="prev-page"]'); | |||
const next = document.querySelector('[data-role="next-page"]'); | |||
const last = document.querySelector('[data-role="last-page"]'); | |||
if (page <= 1) { | |||
first.classList.add('disabled'); | |||
prev.classList.add('disabled'); | |||
} else { | |||
first.href = makeLink(1); | |||
prev.href = makeLink(page - 1); | |||
} | |||
if (page >= lastPage) { | |||
next.classList.add('disabled'); | |||
last.classList.add('disabled'); | |||
} else { | |||
next.href = makeLink(page + 1); | |||
last.href = makeLink(lastPage); | |||
} | |||
// 数字ボタン | |||
const pageNumbers = document.querySelector('[data-role="page-numbers"]'); | |||
if (!pageNumbers) return; | |||
const start = Math.max(1, page - 2); | |||
const end = Math.min(lastPage, page + 2); | |||
for (let i = start; i <= end; i++) { | |||
const link = document.createElement('a'); | |||
link.textContent = i; | |||
const newUrl = new URL(url); | |||
newUrl.searchParams.set('page', i); | |||
link.href = newUrl.toString(); | |||
if (i === page) { | |||
link.classList.add('current'); | |||
} | |||
pageNumbers.appendChild(link); | |||
} | |||
});//# sourceURL=foobar.js | |||
</script> | |||
</html> | |||
{{#vardefine:hitCount | | |||
{{#cargo_query: | |||
tables=飲食店情報 | |||
|fields=COUNT(*) | |||
|where=( | |||
飲食店情報.ジャンル LIKE CONCAT('%{{{genre}}}%') | |||
) | |||
}} | |||
}} | |||
{{#vardefine:page|{{#urlget:page|1}}}} | |||
{{#vardefine:limit|30}} | |||
{{#vardefine:offset| | |||
{{#expr: ({{#var:page}} - 1) * {{#var:limit}} }} | |||
}} | |||
{{#vardefine:from| | |||
{{#expr: | |||
({{#var:page}} - 1) * {{#var:limit}} + 1 | |||
}} | |||
}} | |||
<h1 style="font-size: 1.2em;"> | |||
<strong>{{#if: {{#urlget:station}} | {{#urlget:station}} |川西市}}</strong>の<strong>{{#if: {{#urlget:genre}} | {{#urlget:genre}} |グルメ}}</strong></h1><strong style="float: right;" id="count" data-total="{{#var:hitCount}}" data-limit="{{#var:limit}}">{{#var:hitCount}} 件の結果があります({{#var:from}} 件目~) | |||
</strong> | |||
== 検索結果 == | |||
<!-- 検索実行 --> | |||
{{#cargo_query: | |||
tables=飲食店情報 | |||
|fields=飲食店情報._pageName,飲食店情報.店名,飲食店情報.画像,飲食店情報.ジャンル,飲食店情報.郵便番号,飲食店情報.住所,飲食店情報.最寄り,飲食店情報.営業時間月,飲食店情報.定休日,飲食店情報.電話番号,飲食店情報.予算昼下限,飲食店情報.予算昼上限,飲食店情報.予算夜下限,飲食店情報.予算夜上限,飲食店情報.ストリートビューURL,飲食店情報.座標 | |||
|where=( | |||
飲食店情報.ジャンル LIKE CONCAT('%{{{genre}}}%') | |||
) | |||
|format=template | |||
|template=検索結果カード | |||
|named args=yes | |||
|default=該当する店舗はありません。 | |||
|limit={{#var:limit}} | |||
|offset={{#var:offset}} | |||
|order by=score DESC | |||
|more results text= | |||
}} | |||
<html> | |||
<div class="pagination"> | |||
<a data-role="first-page" href="#"><<</a> | |||
<a data-role="prev-page" href="#"><</a> | |||
<div class="page-numbers" data-role="page-numbers"></div> | |||
<a data-role="next-page" href="#">></a> | |||
<a data-role="last-page" href="#">>></a> | |||
</div> | |||
<style> | |||
.pagination { | |||
display: flex; | |||
justify-content: center; | |||
gap: 12px; | |||
margin: 24px 0; | |||
font-size: 14px; | |||
} | |||
.pagination a { | |||
display: inline-flex; | |||
align-items: center; | |||
justify-content: center; | |||
padding: 8px 14px; | |||
min-width: 40px; | |||
text-decoration: none; | |||
border-radius: 6px; | |||
border: 1px solid; | |||
transition: background-color 0.15s ease, | |||
color 0.15s ease, | |||
box-shadow 0.15s ease; | |||
} | |||
.page-numbers { | |||
display: flex; | |||
gap: 6px; | |||
} | |||
.page-numbers a { | |||
min-width: 36px; | |||
padding: 8px 0; | |||
} | |||
/* ライト・通常 */ | |||
.pagination a { | |||
background: #f9fafb; | |||
color: #1f2937; | |||
border-color: #d1d5db; | |||
} | |||
.pagination a:hover { | |||
background: #eef2f7; | |||
box-shadow: 0 1px 4px rgba(0,0,0,0.08); | |||
} | |||
/* 非活性 */ | |||
.pagination a.disabled { | |||
background: #f1f5f9; | |||
color: #94a3b8; | |||
border-color: #e2e8f0; | |||
pointer-events: none; | |||
box-shadow: none; | |||
} | |||
/* 現在ページ(数字) */ | |||
.pagination .page-numbers a.current { | |||
background: #1f2937; | |||
color: #fff; | |||
border-color: #1f2937; | |||
font-weight: 600; | |||
pointer-events: none; | |||
} | |||
/* ダーク・通常 */ | |||
.skin-theme-clientpref-night .pagination a { | |||
background: #374151; | |||
color: #f9fafb; | |||
border-color: #4b5563; | |||
} | |||
.skin-theme-clientpref-night .pagination a:hover { | |||
background: #4b5563; | |||
} | |||
/* ダーク・非活性 */ | |||
.skin-theme-clientpref-night .pagination a.disabled { | |||
background: #1f2937; | |||
color: #6b7280; | |||
border-color: #374151; | |||
} | |||
/* ダーク・現在ページ */ | |||
.skin-theme-clientpref-night .pagination .page-numbers a.current { | |||
background: #f9fafb; | |||
color: #1f2937; | |||
border-color: #f9fafb; | |||
} | |||
</style> | |||
</html> | |||
__目次非表示__ | |||