面包屑生成工具






4.29/5 (7投票s)
本文介绍了一种方法,使开发人员能够动态生成遍历历史面包屑。
目录
1. 简介
根据所需的格式,面包屑导航
- 跟踪并按查看顺序显示网站访问者查看的每个页面
- 显示当前页面相对于网站结构的层次结构
本文仅讨论第一种形式。
对于面包屑导航中的每个面包屑,它由两部分组成:标签和路径。在网页上显示的面包屑字符串中,面包屑之间有一个分隔符(当前页面标签后面没有)。此分隔符通常是大于号(>)。最后一个面包屑的路径将被省略。
本文将介绍一种动态生成面包屑的方法。
1.1. 开发目录结构
在我为该项目编写 JavaScript 代码时,我逐渐得出结论,需要有两个独立的模块:一个用于独立情况,另一个用于母版页情况。因此,我创建了两个目录结构(均包含在下载文件中)用于测试面包屑生成工具。
StandAloneBreadcrumbs MasterPageBreadcrumbs
CSS CSS
breadcrumbs.css master_page.css
Scripts Images
breadcrumbs.js favicon.ico
index.html green_dot.png
link_1.html ocean2.gif
link_2.html printer.png
link_3.html printer_hover.png
link_4.html site_logo.png
under_construction.png
Scripts
master_page.js
contact_webmaster.html
index.html
link_1.html
link_2.html
link_3.html
link_4.html
privacy_policy.html
使用 MasterPageBreadcrumbs 目录,假设读者已按照以下路径访问了 link_4.html 页面
index.html → link_1.html → link_3.html → link_4.html
并且开发人员已选择“Home”、“Journeys”、“Programming”和“Ethics”作为面包屑组件的标签,那么将在 link_4.html 页面上显示的面包屑字符串将是
Home > Journeys > Programming > Ethics
由于页面路径中不存在固有的遍历历史,因此在访问每个页面时,都需要记录访问以及遍历顺序。本项目的遍历历史字符串,记录了到 ethics.html 页面的遍历是
Home>index.html|Journeys>link_1.html|Programming>link_3.html
其中 > 分隔标签与其路径,| 分隔标签-路径对。
1.2. 保存遍历历史字符串
遍历历史字符串是短暂的;它会随着每个页面的遍历而改变,记录到最后一个访问页面的历史。但除了记录网页遍历之外,遍历历史字符串还必须在浏览器刷新和标签操作时保留,但在浏览器会话结束时消失。
有多种方法可以保存遍历历史字符串
- document.cookie
- window.localStorage
- window.sessionStorage
对遍历历史字符串的要求只能通过 document.cookie 属性来满足,特别是会话 cookie。
1.3. 被屏蔽的 Cookies
如果访问者不允许 cookie,则 JavaScript 必须以非侵入性的方式失败,即不提供面包屑。
1.4. 欧盟“Cookie 政策”
欧盟 Cookie 政策 [ ^ ] 禁止在事先未获得知情同意的情况下使用 cookie。但是,此限制不适用于用于网站技术目的的 cookie。因此,面包屑中使用的 cookie 不受欧盟限制的约束。
2. 使用代码
借鉴 《使用 HTML、CSS 和 JavaScript 的母版页》[ ^ ] 的经验,我决定面包屑的生成应由每个页面(需要显示面包屑的页面)的 <head> 部分声明的 JSON 参数内容来控制,然后将其传递给 build_breadcrumbs,这是 <body> 元素的 onload 事件的处理程序。
在本文中,
- 术语“当前页面”是指即将显示的 HTML 页面。
- 符号 < 和 >(注意粗体)包围用户提供的信息。
2.1. 母版页面包屑
以下是生成母版页面包屑的先决条件
- master_page.js 必须包含在当前页面中,如下所示:
<script src="<scripts-directory>/master_page.js"></script>
- build_page 方法必须作为表单加载事件的一部分被调用,如下所示:
<body onload="MasterPage.build_page ( PAGE_COMPONENTS );">
2.2. 独立面包屑
以下是生成独立面包屑的先决条件
- breadcrumbs.js 必须包含在当前页面中,如下所示:
<script src="<scripts-directory>/breadcrumbs.js"></script>
- build_breadcrumbs 方法必须作为表单加载事件的一部分被调用,如下所示:
<body onload="BreadCrumbs.build_breadcrumbs ( PAGE_COMPONENTS );">
2.3. PAGE_COMPONENTS
如果需要默认的面包屑处理,则不需要将 PAGE_COMPONENTS 参数传递给 build_page 或 build_breadcrumbs 方法。在这种情况下,页面的面包屑标签将是页面的 URL(document.URL)的文件名,并且标签的大小写将是标题式(title case)。
如果需要特殊处理,JSON 对象中有四个已识别的名称/值对,它们控制着独立和母版页面包屑生成的处理:
- breadcrumbs_desired - 可识别的值为 true 和 false
- breadcrumb_label_source - 可识别的值为:
- given - 标签在 breadcrumb_label 中给出
- filename - 标签从页面 URL 的文件名中提取
- title - 标签从页面 <title> 的文本中获取
- breadcrumb_label - 一个包含所需页面标签的字符串;如果省略,将使用页面 URL 的文件名
- breadcrumb_label_casing - 可识别的值为:
- lower - 面包屑标签将显示为小写
- title - 面包屑标签将显示为标题式
- upper - 面包屑标签将显示为大写
例如
<head>
<title>Home</title>
<meta http-equiv="Content-type"
content="text/html; charset=UTF-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1.0" />
<script type="text/javascript">
var PAGE_COMPONENTS =
{
"breadcrumbs_desired":true,
"breadcrumb_label_source":"given",
"breadcrumb_label":"home",
"breadcrumb_label_casing":"title",
};
</script>
</head>
对于母版页,PAGE_COMPONENTS 参数仅包含这四个名称/值对;对于独立页面,PAGE_COMPONENTS 参数仅包含这四个名称/值对(可能包含 debug_json)。
2.4. 网站顶部页面
网站的顶部页面很可能来自网站外部(例如,来自 Google 等)。发生这种情况时,可能存在一个现有的面包屑 cookie。为了防止该 cookie 干扰面包屑的生成,应将其删除。
- 对于母版页网站:
<script type="text/javascript"> if ( MasterPage.cookie_exists ( MasterPage.BREADCRUMB_COOKIE_NAME ) ) { MasterPage.erase_cookie ( MasterPage.BREADCRUMB_COOKIE_NAME ); } </script>
- 对于独立网站:
<script type="text/javascript"> if ( BreadCrumbs.cookie_exists ( BreadCrumbs.BREADCRUMB_COOKIE_NAME ) ) { BreadCrumbs.erase_cookie ( BreadCrumbs.BREADCRUMB_COOKIE_NAME ); } </script>
3. 实现
面包屑生成器的实现包含在 bread_crumbs.js 和 master_page.js JavaScript 文件中。逻辑基本相同,但由于 master_page.js 稍显复杂,我们将在此处进行讨论。
- 如果当前页面不是引荐页面的子页面,则必须消除面包屑 cookie。这意味着我们从网站外部的某个网络位置(例如,从 Google)到达当前页面,因此我们必须删除面包屑 cookie。
: var document_path = ""; // path of current page var referrer_path = ""; // path of referrer : document_path = retrieved_path ( document.URL ); referrer_path = retrieved_path ( document.referrer ); if ( document_path !== referrer_path ) { if ( cookie_exists ( BREADCRUMB_COOKIE_NAME ) ) { erase_cookie ( BREADCRUMB_COOKIE_NAME ); } }
retrieved_path 返回一个 URL,其中已去除文件名和扩展名。 - 当前页面必须支持某些方法和属性;如果不支持,请以非侵入性的方式失败(不生成面包屑即返回)。
: if ( !document.createElement || !document.getElementById || !document.title || !document.URL || !window.navigator.cookieEnabled ) { return; // fail unobtrusively }
- 如果文档包含 breadcrumbs_div <div> 元素,请确保它是一个 <div>;否则将其设置为 null。
: var breadcrumbs_div; // target div in the document : breadcrumbs_div = document.getElementById ( BREADCRUMB_DIV_NAME ); if ( breadcrumbs_div ) { if ( typeof breadcrumbs_div !== "div" ) { breadcrumbs_div = null; } }
- 母版页和独立版本之间存在细微差别。
- 对于母版页面包屑,如果文档包含 breadcrumbs_div 元素,则使用它;否则,如果需要面包屑,则在标题之后创建一个 breadcrumbs_div 元素,如果不存在 <header> div,则在文档主体开头创建一个 breadcrumbs_div 元素。
if ( breadcrumbs_div ) { // no action needed - use it } else if ( components.breadcrumbs_desired ) { var header_div = document.getElementById ( 'header' ); breadcrumbs_div = document.createElement ( "div" ); breadcrumbs_div.id = BREADCRUMB_DIV_NAME; if ( header_div ) { header_div.appendChild ( breadcrumbs_div ); } else { document.body.insertBefore ( breadcrumbs_div, document.body. firstElementChild. nextSibling); } } else { return; // fail unobtrusively }
- 对于独立面包屑,如果文档包含 breadcrumbs_div 元素,则使用它;否则,在文档主体开头创建一个 breadcrumbs_div 元素。请注意,breadcrumbs_desired 是通过调用 build_breadcrumbs 暗示的。
if ( breadcrumbs_div ) { // no action needed - use it } else { breadcrumbs_div = document.createElement ( "div" ); breadcrumbs_div.id = BREADCRUMB_DIV_NAME; document.body.insertBefore ( breadcrumbs_div, document.body. firstElementChild. nextSibling); }
- 对于母版页面包屑,如果文档包含 breadcrumbs_div 元素,则使用它;否则,如果需要面包屑,则在标题之后创建一个 breadcrumbs_div 元素,如果不存在 <header> div,则在文档主体开头创建一个 breadcrumbs_div 元素。
- 创建将替换文档中 breadcrumbs_div 的 <div>,
: var breadcrumbs; // breadcrumbs to appear : breadcrumbs = document.createElement ( "div" ); breadcrumbs.id = BREADCRUMB_DIV_NAME;
- 确定从何处检索 cookie:从 document.URL 中的文件名?从 document.title 的文本?从首选项的 breadcrumb_label 中的用户给定值?- 默认为 document.URL 中的文件名;检索并修剪标签。
: var breadcrumb_label = ""; // this page's breadcrumb label : breadcrumb_label = extract_filename ( document.URL ); if ( preferences.breadcrumb_label_source ) { // defaults to filename in the // document.URL switch ( preferences.breadcrumb_label_source.toLowerCase ( ) ) { case "title": breadcrumb_label = document.title; break; case "given": if ( preferences.breadcrumb_label ) { breadcrumb_label = preferences.breadcrumb_label; } break; case "filename": default: break; } } breadcrumb_label = trim ( breadcrumb_label );
- 设置标签的大小写;默认为标题式。
: if ( preferences.breadcrumb_label_casing ) { switch ( preferences.breadcrumb_label_casing.toLowerCase ( ) ) { case "lower": breadcrumb_label = breadcrumb_label.toLowerCase ( ); break; case "upper": breadcrumb_label = breadcrumb_label.toUpperCase ( ); break; case "title": default: breadcrumb_label = to_titlecase ( breadcrumb_label ); break; } }
- 生成当前页面的面包屑。
: var LABEL_URL_SEPARATOR = ">"; : var page_label_URL = ""; // current page's label/URL : page_label_URL = breadcrumb_label + LABEL_URL_SEPARATOR + document.URL;
- 检索现有的面包屑 cookie 字符串。
: var cookie_string = ""; // existing breadcrumb cookies : cookie_string = read_cookie ( "breadcrumb" );
- 根据需要修改 cookie_string。
: var LABEL_URL_PAIR_SEPARATOR = "|"; : var index = -1; // general purpose index : if ( IsNullOrEmpty ( cookie_string ) ) { cookie_string = page_label_URL; } else { // determine if the current // page URL is already in the // cookie string; required if // visitor backs up through // the breadcrumbs index = cookie_string.indexOf ( document.URL ); if ( index >= 0 ) { // URL is already in the // cookie string; make it the // last entry index = cookie_string.indexOf ( LABEL_URL_PAIR_SEPARATOR, index ); // index < 0 implies URL is at // the end of the cookie // string; no action necessary if ( index < 0 ) { } else { // index >= 0 implies cookie // string must be truncated // at the pair separator // following the current page // URL cookie_string = cookie_string.slice ( 0, index ); } } else { cookie_string += LABEL_URL_PAIR_SEPARATOR + page_label_URL; } }
- 根据 cookie 字符串构建当前页面的面包屑。
: var label_URLs; // array of labels and URLs : label_URLs = cookie_string.split ( LABEL_URL_PAIR_SEPARATOR ); for ( var i = 0; ( i < label_URLs.length ); i++ ) { var label_URL; var span; label_URL = label_URLs [ i ].split ( LABEL_URL_SEPARATOR ); if ( IsNullOrEmpty ( label_URL [ 0 ] ) || IsNullOrEmpty ( label_URL [ 1 ] ) ) { continue; } span = document.createElement ( "span" ); if ( i < ( label_URLs.length - 1 ) ) { var a = document.createElement ( "a" ); a.href = label_URL [ 1 ]; a.innerText = label_URL [ 0 ]; bread_crumbs.appendChild ( a ); span.innerHTML = " > "; bread_crumbs.appendChild ( span ); } else { span.innerHTML = label_URL [ 0 ]; bread_crumbs.appendChild ( span ); } }
- 用新的面包屑 <div> 替换当前页面的面包屑 <div>。
: breadcrumbs_div.parentNode.replaceChild ( bread_crumbs, breadcrumbs_div );
- 用新的面包屑 cookie 字符串替换旧的面包屑 cookie 字符串。
: erase_cookie ( "breadcrumb" ); create_cookie ( "breadcrumb", cookie_string, 0 ); // make a session cookie
辅助函数
- cookie_exists
- create_cookie
- erase_cookie
- extract_filename
- IsNullOrEmpty
- read_cookie
- to_titlecase
都包含在相应的 JavaScript 文件中。
4. 参考文献
- 欧盟 Cookie 法规终极指南 [ ^ ]
5. 下载
下载包含两个开发目录。在相应的 Scripts/ 目录中可以找到 master_page.js 和 breadcrumbs.js。
在两个开发目录中,CSS/ 目录中都包含 CSS 文件,这些文件包含
#breadcrumbs
{
padding-left:15px;
font-size:smaller;
}
此样式使面包屑显示为缩进且字体较小。
master-page.js 文件位于 MasterPageBreadcrumbs/ 目录的 Scripts/ 子目录中;breadcrumbs.js 文件位于 StandAloneBreadcrumbs/ 目录的 Scripts/ 子目录中。
6. 实践与经验
独立面包屑是最早开发的。直到开发后期才认识到需要一个独立的母版页版本。
6.1. 将 breadcrumbs.js 整合到 master_page.js
第一步是将 breadcrumbs.js 整合到 master_page.js 中。很明显,breadcrumbs.js 的大部分内容已经存在于 master_page.js 中。因此,只需要进行以下修改:
- build_breadcrumbs 调用被添加到 build_page 中。
- 常量 BREADCRUMB_COOKIE_NAME、BREADCRUMB_DIV_NAME、BREADCRUMB_LABEL_URL_PAIR_SEPARATOR 和 BREADCRUMB_LABEL_URL_SEPARATOR 被添加。
- 函数 to_titlecase、trim、IsNullOrEmpty、extract_filename、parse_URL、retrieved_path 和 build_breadcrumbs 被添加。
- 入口点 build_breadcrumbs 被添加到命名空间 MasterPage 的公共属性中。
6.2. 将面包屑整合到现有网站
我选择将面包屑整合到我自己的网站[ ^ ]。由于网站的菜单结构,我认为面包屑不是必需的(除了教学目的以支持本文)。
整合需要在我的本地计算机上执行以下步骤。
- 将网站上的 master-page.js 替换为 MasterPageBreadcrumbs 目录中的 master_page.js。
- 在网站的每个网页中,将“breadcrumbs_desired”、“breadcrumb_label_source”、“breadcrumb_label”和“breadcrumb_label_casing”添加到 PAGE_COMPONENTS 中。
- 在 index.html 的末尾添加所需的 <script>。
除了向 PAGE_COMPONENTS 添加面包屑参数外,这项任务并不算太繁重,只是有些重复。
7. 结论
我介绍了一种方法,该方法使开发人员能够动态生成遍历历史面包屑。
8. 开发环境
面包屑生成工具是在以下环境中开发的:
Microsoft Windows 7 专业版 SP 1 |
Microsoft Visual Studio 2008 专业版 SP1 |
Microsoft Visual C# 2008 |
Microsoft .Net Framework Version 3.5 SP1 |
9. 历史
01/27/2020 | 原文 |