この記事では、 Edge Delivery ServicesとDocument Authoringの機能を活用して、DAに保存されているスプレッドシートから動的なアイテムリストを作成する方法について詳しく解説します。
リンクのリストをページに羅列することと、実際に使えるコンテンツを厳選することの間には大きな違いがある。このプロジェクトは「URLと説明文のリストが必要なだけだ」というところから始まったが、すぐにいくつかの現実的な問題を解決することに発展した。具体的には、コンテンツの保守性を維持すること、DOMの肥大化を避けること、そして過剰な設計をせずにフィルタリングを高速に感じさせることである。
その結果生まれたのが 「参照リスト」 ブロックです。これは、Adobe Edge Delivery Services(EDS)向けのデータ駆動型でフィルタリング可能なカードグリッドであり、スプレッドシートを基盤としたJSONフィードからコンテンツを取得し、カテゴリとタグによるフィルタリングをサポートし、洗練されたアニメーションで結果を段階的に読み込みます。このページは、皆さんが既にブックマークしているはずのエッジデリバリーサービスのリファレンスページを宣伝するために特別に作成しました!
スプレッドシートにすべてを任せる
このブロックは完全にデータ駆動型です。/en/reference-links.jsonにある EDS シートによって生成された JSON ファイルを取得します。私たちは複数シート形式を採用することにしました。1枚は参考資料用、もう1枚はカテゴリー用です。
{
"data": {
"data": [
{
"url": "https://developer.adobe.com/",
"image-url": "https://example.com/thumb.png",
"title": "Adobe Developer Documentation",
"description": "Official docs for building on Adobe platforms.",
"tag": "Documentation|Official",
"category": "Development"
}
]
},
"categories": {
"data": [{ "Category": "Development", "Description": "Dev tools and references" }]
}
}
タグはセル内でパイプ記号(Tag1 | Tag2)を使用するため、作成が簡単で予測可能になります。
このブロックを作成する際には、本番環境に公開する前に必ずテストを行いたいと思うでしょう。DA内に入力済みのリストしかない場合、ローカルでテストを行う際に、クロスオリジンリソース共有(CORS)の問題に遭遇する可能性が高くなります。この問題を解決するには、DAシートと同じ要件を満たすテストエントリを含む独自のJSONファイルを作成し、ローカルJSONの使用を有効にするだけです。
const USE_LOCAL_JSON = false;
const LOCAL_JSON_PATH = '/tools/json/reference-list.json';
const LIVE_JSON_URL = '/en/reference-links.json';
壊れない建築カード
各参照項目は、以下のDOM構造を持つカードになります。
.reference-card
└── a.reference-link
├── div.reference-image-wrapper (optional)
│ └── img.reference-image
└── div.reference-content
├── h3.reference-title
├── p.reference-description (optional)
└── div.reference-tags
└── span.reference-tag (one per tag)
ブロックを作成する際に考慮すべき最も重要なことの一つは、著者がそれをどれだけ簡単に使用できるかということです。そのため、リストがさまざまな量の情報を処理しても、同じように機能するようにする必要がありました。説明文やタグが付いているものもあれば、どちらも付いていないものもある。ルールは、存在するものだけをレンダリングすることだが、レイアウトが特定の要素の存在に依存しないようにすることだ。具体的な決定事項をいくつか挙げます。
-
画像はオプションです。画像URLフィールド(画像へのフォールバックあり)は、空でない場合にのみ表示されます。
-
画像はloading="lazy"を使用しているため、画面外のサムネイルが初期レンダリングを妨げません。
-
すべてのリンクは、外部URLでのタブの不正アクセスを防ぐためにrel="noopener noreferrer"を使用しています。
- これは通常、最新のブラウザでは自動的に行われますが、念のため確認しておいた方が良いでしょう!
世界を再構築せずにリストをフィルタリングする
フィルタリングの方法を検討する際、特に操作のたびに再レンダリングを行う場合は、物事が複雑になることがあります。これを避けるため、各カードの属性を最初から設定するようにしました。そうすることで、表示/非表示を切り替えるような操作感になります。
card.setAttribute('data-category', ref.category);
card.setAttribute('data-tags', JSON.stringify(cardTags));
また、あらゆるインタラクションにおける表示状態を再評価する関数、updateReferenceDisplay を追加しました。
const categoryMatch = selectedCategory === 'all' || cardCategory === selectedCategory;
const tagMatch = cardTags.length === 0 || cardTags.some((tag) => activeTags.has(tag));
タグのマッチングには ORロジック が使用され、選択されたタグのいずれかがカードの条件を満たします。アクティブなタグはセット内に存在するため、追加/削除およびメンバーシップチェックはすべてO(1)です。一つ微妙な例外ケース:タグ付けされていないアイテム。タグフィルターを常に通過させることで、それらが予期せず消えてしまうことがなくなった。
CSSが期待以上の働きをする
これは必ずしもスタイリングに関するブログではありませんが、その点に関して私たちが下したいくつかの決定について触れないわけにはいきません。特に、カードにカーソルを合わせたときに表示される「スポットライト」効果に関して。
.reference-grid:has(.reference-card:hover) .reference-card:not(:hover) {
transform: scale(0.9);
opacity: 0.6;
}
フェードインアニメーションも同様のアプローチを採用しているため、JavaScriptとスタイル間の調整オーバーヘッドは発生しません。
.reference-card { opacity: 0; }
.reference-card.fade-in {
opacity: 1;
animation: fade-in-up 0.5s ease-out forwards;
}
@keyframes fade-in-up {
from { transform: translateY(20px); }
to { transform: translateY(0); }
}
最後に
このプロジェクトは、思慮深い設計によって、ありふれたパターンを真に拡張可能なものへと変えることができるという好例である。参照リストブロックは、責任を構造化データに押し付け、フロントエンドを効率的なレンダリングと状態管理に集中させることで、肥大化したDOMやコストのかかる再レンダリングといった一般的な落とし穴を回避します。
真の価値は、フィルタリングや表示方法だけではなく、システムそのものにある。著者は、予測可能で手間のかからない方法でコンテンツを管理できる一方、実装は高いパフォーマンスを維持し、拡張も容易です。これはコンテンツが増えても通用するパターンであり、コンテンツが増えるたびに見直す必要はない。
リファレンスページの動作をご覧ください!
著者について
聞いた内容は気に入りましたか?自分にとって何が最適なのか、疑問がありますか?ぜひお話させてください!お問い合わせはこちら