coldfusion

Static content is so yesterday. Websites, whether internal or external, are all about staying current.

昨天的静态内容是如此 内部或外部网站都是与时俱进的。

To that end, on a recent internal project I created a new intranet site and opted to develop a dynamically populated menu in ColdFusion. I went this route so that managing the links didn’t require us to open up the HTML files each time new content was added. This made updating the menu much less trouble for me as well as the content owners.

为此,在最近的内部项目中,我创建了一个新的Intranet站点,并选择在ColdFusion中开发一个动态填充的菜单。 我走了这条路,以便管理链接不需要每次添加新内容时都打开HTML文件。 这使得更新菜单对我和内容所有者而言都没有那么麻烦。

Why go through the trouble of building a dynamic menu in ColdFusion when an HTML/JavaScript menu could be written and maintained with relative ease? Sure, we could have built the menu in HTML and JavaScript and just modified the code as needed, but where’s the fun in that? More importantly, project maintenance wasn’t what I was looking for. I didn’t want to be tied to the project in perpetuity; the team I was on was too small and had too many new projects to be spending time on the maintenance of old projects.

当可以相对轻松地编写和维护HTML / JavaScript菜单时,为什么还要在ColdFusion中构建动态菜单呢? 当然,我们可以用HTML和JavaScript构建菜单,然后根据需要修改代码,但是这样做的乐趣何在? 更重要的是,项目维护不是我想要的。 我不想永远被这个项目所束缚; 我所在的团队规模太小,有太多新项目,无法花时间维护旧项目。

The end users and I came up with a menu that could be managed easily, and took up very little space on the site. The reason why space was an issue was that the site had several embedded sections, each of which had several embedded sections, which had… you see where I’m going.

最终用户和我想出了一个易于管理的菜单,并且只占用了很少的网站空间。 空间之所以成为问题,是因为该站点有几个嵌入式部分,每个部分都有几个嵌入式部分,这些部分有……您知道我要去的地方。

在守则之前… (Before the Code…)

We’ll start by designing the database — we can’t write code to access a database until we know how the database is designed. The database for our dynamic menu is straightforward. To accomplish our menu we only need two tables — no stored procedures or anything else (though a stored procedure would be the easiest way to manage the data in the menu), so you can use any database system you’d like.

我们将从设计数据库开始-在知道数据库的设计方式之前,我们无法编写代码来访问数据库。 动态菜单的数据库非常简单。 要完成菜单,我们只需要两个表-不需要存储过程或其他任何表(尽管存储过程是管理菜单中数据的最简单方法),因此您可以使用任何数据库系统。

1224_image1

Image 1

图片1

Image 1 shows the database tables we’ll use for our menu. The MENU_ITEMS table is where all the actual menu tree items will live. Name (menu_item_name) and HREF (menu_item_url) are stored along with the primary key (menu_item_id). The table MENU_ITEMS_XREF holds the structure of the tree itself. Both menu_item_id and child_id refer to the menu_item_id from the MENU_ITEMS table. IDs that appear in the child_id column indicate that that ID will be nested under the item in the menu_item_id column. Image 2 illustrates this concept.

图1显示了我们将用于菜单的数据库表。 MENU_ITEMS表是所有实际菜单树项所在的位置。 Name ( menu_item_name )和HREF ( menu_item_url )与主键( menu_item_id )一起存储。 表MENU_ITEMS_XREF包含树本身的结构。 无论menu_item_idchild_idmenu_item_idMENU_ITEMS表。 出现在的ID child_id列指示该ID将项目下嵌套在menu_item_id柱。 图2说明了此概念。

1224_image2

Image 2

图片2

The last column in the MENU_ITEMS_XREF table is the sort_order field. Initially, I just let the menu query that generates the menu handle the sorting (alphabetically). Wouldn’t you know it, though — the business unit had other ideas. So now there is a sort_order field, which allows the content owner to place more important or popular topics closer to the top of the page.

MENU_ITEMS_XREF表的最后一列是sort_order字段。 最初,我只是让生成菜单的菜单查询处理排序(按字母顺序)。 但是,您不知道吗–业务部门有其他想法。 因此,现在有一个sort_order字段,该字段使内容所有者可以将更重要或受欢迎的主题放在页面顶部附近。

That’s it for the database. Let’s code!

数据库就是这样。 让我们编码吧!

代码 (The Code)

The code we use to create the menu is pretty easy to follow. Basically, we’ll create a custom ColdFusion tag that recurses over a database structure and builds the appropriate menu structure as it goes. We’ll break down the pieces of create_menu.cfm, which you can download here, and discuss each section. The end result will be a completely de-mystified, dynamically built tree menu.

我们用来创建菜单的代码非常容易遵循。 基本上,我们将创建一个自定义ColdFusion标记,该标记在数据库结构上递归并随其构建适当的菜单结构。 我们将分解create_menu.cfm的片段,您可以在此处下载这些片段,并讨论每个部分。 最终结果将是一个完全不神秘的,动态构建的树菜单。

The code in Section A defines some initial parameters we’ll need as default. You may or may not need these, depending on whether your site has pages in sub folders and such. Our site did, so we needed a way to get up the folder tree to the images directory.

A节中的代码定义了一些默认需要的初始参数。 您可能需要也可能不需要这些,这取决于您的站点是否在子文件夹等中有页面。 我们的网站做了,所以我们需要一种将文件夹树移到images目录的方法。

Section A

A节

<CFPARAM DEFAULT="1" NAME="ATTRIBUTES.Level">
<CFPARAM DEFAULT="" NAME="ATTRIBUTES.divID"> 
<CFIF ATTRIBUTES.Level EQ 1> <CFSET VARIABLES.RootLevel = ""> 
<CFELSEIF ATTRIBUTES.Level EQ 2>  <CFSET VARIABLES.RootLevel = "../"> 
<CFELSEIF ATTRIBUTES.Level EQ 3>  <CFSET VARIABLES.RootLevel = "../../"> 
</CFIF>

The following sections of code all combine into a single JavaScript block, but for the sake of making it easier to explain, I’ve broken it into smaller, more digestible pieces. This is the JavaScript that will handle the menu, collapsing and expanding the appropriate branches, and changing the image states of those branches as required.

以下各节代码全部合并为一个JavaScript块,但是为了使解释更容易,我将其分为更小,更易理解的部分。 这是JavaScript,它将处理菜单,折叠和展开适当的分支,并根据需要更改这些分支的图像状态。

Section B

B区

<CFOUTPUT><script type="text/javascript">   function ShowMenu(n)  {  var menu, arrowImg;  menu = document.getElementById("d" + n);

Section C

C区

// Determine if the menu is currently showing.if (menu.style.display == 'block')  {  // If it is showing, hide the menu and update the twisty image.  menu.style.display = 'none';  arrowImg = document.images['i' + n];  arrowImg.src = "#VARIABLES.RootLevel#images/right_arrow.gif";  }

Section C handles the event of clicking on an already-expanded menu branch. Doing this triggers the branch to collapse. The menu doesn’t have to function this way, but why require your users to select a different level just to collapse a section? Instead, we simply take the section the user clicked on and see if it’s expanded; if it is, we collapse it. If it is not expanded, move right along to Section D.

C节处理单击已展开的菜单分支的事件。 这样做会触发分支崩溃。 菜单不必以这种方式运行,但是为什么要让用户选择其他级别只是为了折叠部分? 取而代之的是,我们只需要查看用户单击的部分,看看它是否已展开; 如果是,我们将其折叠。 如果未展开,请向右移至D节。

Section D

D区

else{  // Hide all layers first.  var divs = document.getElementsByTagName("div");  for (var i = 0; i < divs.length; i++)  if (divs[i].id.indexOf("d0") >= 0)  divs[i].style.display = 'none';  // Reset the images.  for (var j = 0; j < document.images.length; j++)  if (document.images[j].src.indexOf("down_arrow") > 0)  document.images[j].src = "#VARIABLES.RootLevel#images/right_arrow.gif";  // Show the menus and update their twisty images.  i = 2;  while (n.length >= i)  {  menu = document.getElementById("d" + n.substring(0, i));  arrowImg = document.images["i" + n.substring(0, i)];  menu.style.display = "block";  arrowImg.src = "#VARIABLES.RootLevel#images/down_arrow.gif";  i += 2;  }  }  }  </script>  
</CFOUTPUT>

Section D is pretty long — it’s the remainder of the JavaScript function ShowMenu(). If the branch that the user selected was not already expanded, the first order of business is to collapse all branches. We essentially want to start with a fresh menu each time. To accomplish this, we loop over the structure of the image tags (all named in series), resetting each image. We repeat the process on the menu structure itself (each <div> tag that makes up the menu is named in series like the images, so looping over the entire menu is very easy).

D部分相当长-这是JavaScript函数ShowMenu()的其余部分。 如果用户选择的分支尚未扩展,则首要任务是折叠所有分支。 我们本质上希望每次都从一个新菜单开始。 为此,我们遍历了图像标签的结构(全部序列化),重置每个图像。 我们在菜单结构本身上重复此过程(组成菜单的每个<div>标签像图像一样依次命名,因此遍历整个菜单非常容易)。

Once the entire menu has been collapsed, we have to expand the chosen menu branch. Since each branch can have its own sub-branches, the JavaScript has to not only expand the main branch, but, if the user clicks a sub-branch, that branch must be expanded also (see Image 3). Once the appropriate branches are expanded, the corresponding images need to be changed. Our menu uses two images: a blue arrow pointing to the right and a gold arrow that points down. These serve as an additional visual cue for the user.

折叠完整个菜单后,我们必须展开所选菜单分支。 由于每个分支都可以有自己的子分支,因此JavaScript不仅必须扩展主分支,而且,如果用户单击一个子分支,则还必须扩展该分支(参见图3)。 适当的分支一旦展开,就需要更改相应的图像。 我们的菜单使用两张图片:指向右边的蓝色箭头和指向下方的金色箭头。 这些为用户提供了额外的视觉提示。

1224_image3

Image 3

图片3

Once the images are adjusted, we’re done – in terms of the JavaScript, that is. We covered the JavaScript first, even though the ColdFusion part of our custom tag will execute first, because I wanted to establish the flow of the code and how it should work before we cover the set up. The JavaScript is the work horse of this menu, so it’s important to know what’s going on there and how everything works. Now, time to face the CF!

调整图像后,就完成了JavaScript。 尽管自定义标签的ColdFusion部分将首先执行,但我们还是先介绍了JavaScript,因为在我们进行介绍之前,我想确定代码流程以及代码的工作方式。 JavaScript是此菜单的主力军,因此了解发生的事情以及一切工作原理非常重要。 现在,该面对CF!

设置 (The Set Up)

This menu is the product of a ColdFusion custom tag. Wherever you need the menu to appear (keeping in mind that this menu is vertical), you simply include the tag. To set up the menu on a page, you’ll require two lines of code. Sample 1 shows the <body> tag as well as the actual custom tag call. The ColdFusion code in the body tag expands the menu to reflect the user’s location within the site. Without this logic the menu collapses on load by default.

此菜单是ColdFusion自定义标签的产品。 无论您需要菜单出现在何处(请记住该菜单是垂直菜单),只需添加标签即可。 要在页面上设置菜单,您需要两行代码。 示例1显示了<body>标签以及实际的自定义标签调用。 body标签中的ColdFusion代码可展开菜单以反映用户在站点中的位置。 没有这种逻辑,默认情况下菜单会在加载时折叠。

Sample 1

样品1

<body <CFIF IsDefined('URL.Div')>
onload="ShowMenu('<CFOUTPUT>#URL.Div#</CFOUTPUT>')"</CFIF>>   
<CFINCLUDE TEMPLATE="modules/menu/create_menu.cfm">

We don’t call the custom tag in the standard <CF_> syntax; instead we call it using <CFINCLUDE>. The tag’s designed to call itself as it builds the tree, so we just need to include the code.

我们不会以标准<CF_>语法调用自定义标签; 相反,我们使用<CFINCLUDE>来称呼它。 标签的设计目的是在构建树时调用自身,因此我们只需要包含代码即可。

Now, back to the custom tag — we’ll continue with the ColdFusion code. Section E establishes our variables and queries the database. You’ll notice the query is actually a query of a variable. You can execute this section in whichever way you are most comfortable. I chose to store my initial query as an APPLICATION scoped variable, as the menu data doesn’t change very frequently. Also, because the menu is located on each page of the site, I wanted to spare my database the extra traffic. The last query in Section E creates the application variable.

现在,回到自定义标签-我们将继续使用ColdFusion代码。 E节建立我们的变量并查询数据库。 您会注意到查询实际上是一个变量查询。 您可以按照自己喜欢的任何方式执行此部分。 我选择将初始查询存储为APPLICATION范围的变量,因为菜单数据不会经常更改。 另外,因为菜单位于站点的每个页面上,所以我想为数据库节省额外的流量。 E节中的最后一个查询创建应用程序变量。

Section E

E节

<CFPARAM DEFAULT="0" NAME="ATTRIBUTES.MenuID">
<CFPARAM DEFAULT="" NAME="ATTRIBUTES.DivID">   
<CFPARAM DEFAULT="0" NAME="VARIABLES.LoopCount">   
<CFPARAM DEFAULT="0" NAME="VARIABLES.IncreNum">   
<CFLOCK SCOPE="APPLICATION" TIMEOUT="10" TYPE="READONLY">   <CFSET VARIABLES.qGrabMenu = APPLICATION.qGrabMenu>   <CFSET VARIABLES.DataSource = APPLICATION.DataSource>   
</CFLOCK>   
<CFQUERY DBTYPE="query" NAME="qGetMenuElement">   SELECT *    FROM VARIABLES.qGrabMenu   WHERE Menu_item_ID = #ATTRIBUTES.MenuID#   ORDER BY sort_order   
</CFQUERY>   
<CFQUERY DATASOURCE="#APPLICATION.DataSource#" NAME="APPLICATION.qGrabMenu" CACHEDWITHIN="#APPLICATION.QueryTimeOut#">   
SELECT    menu_item_id,   (SELECT menu_item_name FROM MENU_ITEMS WHERE MENU_ITEMS.menu_item_id = menu_items_xref.menu_item_id) AS Parent,   (SELECT menu_item_url FROM MENU_ITEMS WHERE MENU_ITEMS.menu_item_id = menu_items_xref.menu_item_id) AS Parentlink,   child_id,   (SELECT menu_item_name FROM MENU_ITEMS WHERE MENU_ITEMS.menu_item_id = menu_items_xref.child_id) AS Child,   (SELECT menu_item_url FROM MENU_ITEMS WHERE MENU_ITEMS.menu_item_id = menu_items_xref.child_id) AS Childlink,   sort_order   FROM menu_items_xref   
</CFQUERY>

Section F rounds out our code; it’s the final piece of our create_menu.cfm custom tag. Using recursion, we’re able to build and populate the menu tree with a single custom tag. Create_menu.cfm uses recursion to call itself as a custom tag in order to build sub-branches off the main root menu as needed. When a sub-branch is required, the code calls <CF_create_menu>, which processes the data for the new branch. Should additional sub-branches be needed for an existing sub-branch, the code is called again and recurses another level (or as many levels as required) to create the branch(es). As each level completes, the one above continues on. After all the recursions have run, we’re left with the menu tree.

F节完善了我们的代码; 这是我们的create_menu.cfm自定义标记的最后一部分。 使用递归,我们可以使用单个自定义标签构建并填充菜单树。 Create_menu.cfm使用递归将其称为自定义标签,以便根据需要在主根菜单上构建子分支。 当需要一个子分支时,代码调用<CF_create_menu> ,它处理新分支的数据。 如果现有子分支需要其他子分支,则再次调用该代码并递归另一个级别(或所需的多个级别)以创建分支。 完成每个级别后,上面的一个继续。 运行完所有递归后,我们将剩下菜单树。

Section F

F节

<!--- Build menu --->
<CFLOOP QUERY="qGetMenuElement">   <!--- Increment the loop counter --->   <CFSET VARIABLES.LoopCount = VARIABLES.LoopCount + 1>   <CFIF (qGetMenuElement.childlink NEQ '')>   <!--- Last element on a branch --->   <CFOUTPUT>   <a href="#VARIABLES.RootLevel##childlink#" class="menu"><img src="#VARIABLES.RootLevel#images/transparent.gif" width="9" height="9" border="0" hspace="4">#child#<!--- -#ATTRIBUTES.divID# ---></a><CFIF ATTRIBUTES.divID NEQ ""><CFIF FindNoCase(qGetMenuElement.ChildLink, CGI.PATH_INFO)><script type="text/javascript">ShowMenu('#ATTRIBUTES.divID#');</script></CFIF></CFIF>   </CFOUTPUT>   <!--- build out branches --->   <CFELSE>    <CFOUTPUT>   <CFSET VARIABLES.IncreNum = "0" & VARIABLES.LoopCount>   <CFSET VARIABLES.Num = ATTRIBUTES.DivID & VARIABLES.IncreNum>    <a href="##" class="menu" onclick="ShowMenu('#VARIABLES.Num#'); this.blur(); return false"><img src="#VARIABLES.RootLevel#images/right_arrow.gif" name="i#VARIABLES.Num#" width="9" height="9" border="0" hspace="4 /">#child#<!--- -#ATTRIBUTES.divID# ---></a>   <div id="d#VARIABLES.Num#" class="expand">   <CF_create_menu menuID = "#child_id#" divID = "#VARIABLES.Num#" level = "#ATTRIBUTES.Level#">   </div>   </CFOUTPUT>   </CFIF>     
</CFLOOP>   
<!--- Reset the loop counter --->   
<CFSET VARIABLES.LoopCount = 0>

That’s all there is to it! We’ve created a dynamic collapsible tree menu using a database and ColdFusion.

这里的所有都是它的! 我们使用数据库和ColdFusion创建了动态可折叠树菜单。

翻译自: https://www.sitepoint.com/dynamic-menu-coldfusion/

coldfusion

coldfusion_在ColdFusion中建立动态菜单相关推荐

  1. coldfusion_在ColdFusion中建立旋转画廊

    coldfusion They came, they bought- but did they come back? An ecommerce site's most important visito ...

  2. Microbiome:在人工肠道中建立动态线性模型指导设计和分析微生物组研究

    文章目录 在人工肠道中建立动态线性模型指导设计和分析微生物组研究 导读 摘要 主要结果 图1. 技术变异掩盖了微生物动态的模型 图2. 10个最高丰度细菌科随时间变化 图3. 生物和技术变异的结构和幅 ...

  3. Vue3 中如何加载动态菜单?

    松哥之前写了两篇文章和大家分享了 TienChin 项目中的菜单数据问题,还没看过的小伙伴请戳这里: Vue 里,多级菜单要如何设计才显得专业? TienChin 项目动态菜单接口分析 这两篇文章主要 ...

  4. 在(CListView)列表视图中添加右键菜单的方法

    使用弹出式菜单(PopMenu) 弹 出式菜单(PopMenu)大家都熟悉,在WIN98的桌面上单击鼠标右键弹出的菜单就是弹出式菜单.通常情况下,弹出式菜单在鼠标右键单击时弹出,当 然,也可以根据需要 ...

  5. Django Vue实现动态菜单、动态权限

    随着前后端分离架构的流行,在 web 应用中,RESTful API 几乎已经成为了开发者主要选择,它使得客户端和服务端不需要保存对方的详细信息,也就是无状态性,但是这样在项目中需要动态菜单和动态权限 ...

  6. 如何做DVD动态菜单

    前几天在音像超市看到有最近热播的电视剧DVD光盘买,便兴冲冲的买了一套回家看.没想到吸引小美的不是曲折离奇的剧情,而是极具个性的动态DVD菜单.于是小美找到老哥我,叫我帮她把以前用DV拍摄的视频做成有 ...

  7. 在delphi中如何动态建立类的实例

    在面向对象语言中,用两种方法建立类的实例:静态建立和动态建立.静态建立就是在程序中显式地建立类的实例,如c1 = TClass1.Create().而动态建立是在只知道类名的前题下建立类的实例.动态建 ...

  8. 怎么把dll库写成MATLAB接口,如何在Matlab中应用动态连接库接口技术

    1 引言 Matlab是当前应用最为广泛的数学软件,具有强大的数值计算.数据分析处理.系统 分析.图形显示甚至符号运算等功能.利用这一完整的数学平台,用户可以快速实现十分 复杂的功能,极大地提高工程分 ...

  9. java工具栏的工具提示,动态菜单项、状态条提示、工具条提示问题

    问题的提出: 一个应用程序想要动态改变菜单项.使用CCmdUI::SetText("Menu Text")可以改变菜单文本,但是如何动态改变工具条和状态条的文本呢? 有几种策略,避 ...

  10. 网络营销中的动态定价策略

    生活中常会碰到这种尴尬的情景:去平素最喜欢的一家服装店逛一逛,结果惊讶地发现,155美元刚买的西装正在打折,现价仅为79.99美元.有人的遭遇或许比这更惨,6个星期前刚买了一台最新配置的手提电脑,正暗 ...

最新文章

  1. 求3*4数组的全部元素之和
  2. Shell-/bin/bash和/bin/sh解释器的误用引起的脚本语法错误
  3. ASP.NET MVC 3 Razor基础语法
  4. ubuntu-10.04硬盘安装挫折略记
  5. 非刚性人脸跟踪 —— 人脸跟踪
  6. 辽宁学业水平测试 计算机考试,辽宁高中学业水平考试报名系统
  7. linux ns级定时器_预热 | 万众期待的单片机、Linux二合一的STM32MP157开发板亮相
  8. hibernate访问效率相关
  9. 苹果秋季新品发布会终于官宣:然而并不会发布新iPhone?
  10. java链表的用法_数据结构(java语言描述)链表的使用
  11. oracle 回收站
  12. 牛腩学ASP.NET CORE做博客(视频)
  13. ActiveX控件的注册方法
  14. LncRNA与代谢组联合分析
  15. hadoop错误org.apache.hadoop.yarn.exceptions.YarnException Unauthorized request to start container
  16. python中offset_python pandas tseries.offsets.DateOffset用法及代码示例
  17. python 素数库_使用Python判断质数(素数)的简单方法讲解
  18. Bacterial seed endophyte shapes disease resistance in rice种子内生菌与水稻抗病性的关系
  19. mapreduce 论文(中文翻译)
  20. uniapp 使用canvas 画图连线

热门文章

  1. Java面向对象编程(OOP)
  2. Photoshop抠图(色彩范围命令扣人物/动物毛发图)
  3. c++ vector容器emplace_back
  4. 2021.3.8-第一次MD作业
  5. el表达试中三元用法
  6. 致远OA-A8系统的0day远程命令执行的实战
  7. Android 长按3Dtouch快捷方式
  8. 简单做(ZTD)的十个好习惯总结--转
  9. 详解vue中数据传递(父传子、子传父、兄弟之间以及vuex)代码附上
  10. 计算机考试科目一模拟试题,学车科目一模拟考试,最全答题知识点,送给准备考驾照的你...