65.9K
CodeProject 正在变化。 阅读更多。
Home

面包屑生成工具

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.29/5 (7投票s)

2020年1月29日

CPOL

9分钟阅读

viewsIcon

10052

downloadIcon

101

本文介绍了一种方法,使开发人员能够动态生成遍历历史面包屑。

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_pagebuild_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.jsmaster_page.js JavaScript 文件中。逻辑基本相同,但由于 master_page.js 稍显复杂,我们将在此处进行讨论。

  1. 如果当前页面不是引荐页面的子页面,则必须消除面包屑 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,其中已去除文件名和扩展名。
  2. 当前页面必须支持某些方法和属性;如果不支持,请以非侵入性的方式失败(不生成面包屑即返回)。
        :
        if ( !document.createElement || 
             !document.getElementById || 
             !document.title ||
             !document.URL || 
             !window.navigator.cookieEnabled )
          {
          return;                   // fail unobtrusively
          }
    
  3. 如果文档包含 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;
            }
          }
    
  4. 母版页和独立版本之间存在细微差别。
    • 对于母版页面包屑,如果文档包含 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);
            }
      
  5. 创建将替换文档中 breadcrumbs_div 的 <div>,
        :
        var breadcrumbs;            // breadcrumbs to appear
        :
        breadcrumbs = document.createElement ( "div" );
        breadcrumbs.id = BREADCRUMB_DIV_NAME;
    
  6. 确定从何处检索 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 );
    
  7. 设置标签的大小写;默认为标题式。
        :
        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;
            }
          }
    
  8. 生成当前页面的面包屑。
      :
      var LABEL_URL_SEPARATOR = ">";
        :
        var page_label_URL = "";    // current page's label/URL
    
        :
        page_label_URL = breadcrumb_label + 
                         LABEL_URL_SEPARATOR + 
                         document.URL;
    
    
  9. 检索现有的面包屑 cookie 字符串。
        :
        var cookie_string = "";     // existing breadcrumb cookies
        :
        cookie_string = read_cookie ( "breadcrumb" );
    
  10. 根据需要修改 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;
            }
          }
    
  11. 根据 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 );
            }
          }
    
  12. 用新的面包屑 <div> 替换当前页面的面包屑 <div>。
        :
        breadcrumbs_div.parentNode.replaceChild ( bread_crumbs, 
                                                  breadcrumbs_div );
    
  13. 用新的面包屑 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. 参考文献 目录

5. 下载 目录

下载包含两个开发目录。在相应的 Scripts/ 目录中可以找到 master_page.jsbreadcrumbs.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_NAMEBREADCRUMB_DIV_NAMEBREADCRUMB_LABEL_URL_PAIR_SEPARATORBREADCRUMB_LABEL_URL_SEPARATOR 被添加。
  • 函数 to_titlecasetrimIsNullOrEmptyextract_filenameparse_URLretrieved_pathbuild_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 原文
© . All rights reserved.