I came across problem today in that a client has a menu tree that I built in Farcry. Works perfectly, except for the fact that one of the menu items does not correspond with a page that would be displayed in the content area. This single menu item was to be a pop-up window. So, I had 2 options. Do it the easy way:
In navigation file:
if (qNav.objectName[i] eq "Video Testimonial") {
// Write Javascript popup instead of a normal link
}
Or do it the Right way.
It took 3 hours of time but I did it the right way *pats himself on the back.
The way to accomplish this is to extend the dmNavigation class and I did so in such a way that you might want to copy it because it makes a lot of sense. I’m even considering submitting this to Daemon’s wiki.
If you search my blog I wrote about this before but that project required adding navigation node specific CSS code. This is much more applicable.
First, I created a new file called dmNavigation.cfc in /project_name/packages/types/. I created a sub directory there called _dmNavigation and copied edit.cfm from /farcry_core/packages/types/_dmnavigation/.
I created a bunch of new properties in my dmNavigation.cfc file and, of course, I extended farcry.farcry_core.packages.types.dmNavigation. (I’ll copy the entire code from that file shortly). Then I added the new form fields and some validation for submission in the edit.cfm file. Then I overwrote the edit function by writing a new edit function in my custom dmNavigation.cfc file. Finally, I changed the nav.cfm file that actually writes out the menu structure. (more on that later)
Here’s the dmNavigation.cfc file:
<cfcomponent extends="farcry.farcry_core.packages.types.dmNavigation">
<cfproperty name="popup" type="boolean" hint="Whether or not the navigation node is a popup link or normal page" required="no" default="false">
<cfproperty name="statusBar" type="boolean" hint="Whether or not the status bar should be shown" required="no" default="false">
<cfproperty name="toolbar" type="boolean" hint="Whether or not the toolbar should be shown" required="no" default="false">
<cfproperty name="menubar" type="boolean" hint="Whether or not the menu bar should be shown" required="no" default="false">
<cfproperty name="scrollbars" type="boolean" hint="Whether or not scroll bars should be shown" required="no" default="false">
<cfproperty name="height" type="numeric" hint="Height of the window that will be opened" required="no" default="500">
<cfproperty name="width" type="numeric" hint="Width of the window that will be opened" required="no" default="500">
<cffunction name="edit" access="public" hint="edit dmNavigation nodes">
<cfscript>
// getData for object edit
stObj = this.getData(arguments.objectID);
</cfscript>
<cfinclude template="_dmNavigation/edit.cfm">
</cffunction>
</cfcomponent>
The edit.cfm file (now in /project_name/packages/types/_dmNavigation/edit.cfm is 228 lines long after I made my changes. I’ll put the whole file here but I strongly recommend copying it and pasting it into your editor of choice. In a related note, I just started using CFEclipse and I would definitely recommend it
The basics of the changes are:
- Lines 151-189: Added new form fields
- Lines 106-117: Set up local variables for use
- Lines 57-63: Set up stProperties variables for use in DB Update
- Lines 71-73: Added a quick if statement for error handling
- Lines 32-37: cfparamed necessary variables in form scope
- Lines 206-225: Added a javascript function just to make the display of this edit page work nicely.
And here’s the file:
<cfsetting enablecfoutputonly="yes">
<!---
|| LEGAL ||
$Copyright: Daemon Pty Limited 1995-2003, http://www.daemon.com.au $
$License: Released Under the "Common Public License 1.0", http://www.opensource.org/licenses/cpl.php$
|| VERSION CONTROL ||
$Header: /cvs/farcry/farcry_core/packages/types/_dmnavigation/edit.cfm,v 1.46.2.1 2006/03/21 05:03:26 jason Exp $
$Author: jason $
$Date: 2006/03/21 05:03:26 $
$Name: p300_b113 $
$Revision: 1.46.2.1 $
|| DESCRIPTION ||
$Description: Navigation node edit method. Displays edit form and updates object on submission. $
$TODO: Needs to be refactored.. definitely must remove direct SQL calls from the method 20050802 GB$
|| DEVELOPER ||
$Developer: Brendan Sisson (brendan@daemon.com.au)$
|| ATTRIBUTES ||
$in: $
$out:$
--->
<cfparam name="errormessage" default="">
<cfparam name="bFormSubmitted" default="no">
<cfparam name="title" default="">
<cfparam name="externalLink" default="">
<cfparam name="lNavIDAlias" default="">
<cfparam name="fu" default="">
<cfparam name="form.statusBar" default="false">
<cfparam name="form.menuBar" default="false">
<cfparam name="form.toolbar" default="false">
<cfparam name="form.scrollbars" default="false">
<cfparam name="form.theHeight" default="500">
<cfparam name="form.theWidth" default="500">
<cfimport taglib="/farcry/fourq/tags" prefix="q4">
<cfimport taglib="/farcry/farcry_core/tags/navajo/" prefix="nj">
<cfimport taglib="/farcry/farcry_core/tags/display/" prefix="display">
<!--- editing from site tree --->
<cfset cancelCompleteURL = "#application.url.farcry#/edittabOverview.cfm?objectid=#stObj.ObjectID#">
<cfif bFormSubmitted EQ "yes">
<cfif isDefined("form.cancel")> <!--- cancel --->
<cflocation url="#cancelCompleteURL#" addtoken="no">
<cfabort>
<cfelse> <!--- submit --->
<cfset stProperties = structNew()>
<cfset stProperties.objectid=stObj.objectId>
<cfset stProperties.title = form.title>
<cfset stProperties.label = form.title>
<cfset stProperties.externalLink = form.externalLink>
<cfset stProperties.lNavIDAlias = form.lNavIDAlias>
<cfset stProperties.popup = form.popup>
<cfset stProperties.statusBar = form.statusBar>
<cfset stProperties.toolbar = form.toolbar>
<cfset stProperties.menuBar = form.menuBar>
<cfset stProperties.scrollbars = form.scrollbars>
<cfset stProperties.height = form.theHeight>
<cfset stProperties.width = form.theWidth>
<cfset stProperties.datetimelastupdated = Now()>
<cfset stProperties.lastupdatedby = session.dmSec.authentication.userlogin>
<cfset stProperties.fu = form.fu>
<!--- unlock object --->
<cfset stProperties.locked = 0>
<cfset stProperties.lockedBy = "">
<cfif NOT isNumeric(form.theHeight) OR NOT isNumeric(form.theWidth)>
<cfset errormessage = "The height and width must be integer values.">
</cfif>
<cfif Trim(errormessage) EQ "">
<!--- update the OBJECT --->
<cfset oType = createobject("component", application.types.dmNavigation.typePath)>
<cfset oType.setData(stProperties=stProperties)>
<cfif NOT (isdefined("url.ref") AND url.ref eq "typeadmin")> <!--- if not typeadmin edit (from site tree edit) --->
<!--- get parent to update tree --->
<nj:treeGetRelations typename="#stObj.typename#" objectId="#stObj.ObjectID#" get="parents" r_lObjectIds="ParentID" bInclusive="1">
<!--- update tree --->
<nj:updateTree objectId="#parentID#">
</cfif>
<cfquery datasource="#application.dsn#">
UPDATE #application.dbowner#nested_tree_objects
SET objectName = <cfqueryparam cfsqltype="cf_sql_varchar" value="#title#">
WHERE objectID = '#stObj.ObjectID#'
</cfquery>
<cfset application.navid = getNavAlias()>
<cfoutput><script type="text/javascript">
if(parent['sidebar'].frames['sideTree'])
parent['sidebar'].frames['sideTree'].location= parent['sidebar'].frames['sideTree'].location;
parent['content'].location.href = "#cancelCompleteURL#"
</script></cfoutput>
<cfabort>
</cfif>
</cfif>
<cfelse>
<cfset title = stObj.title>
<cfset externalLink = stObj.externalLink>
<cfset lNavIDAlias = stObj.lNavIDAlias>
<cfset fu = stObj.fu>
<cfset popup = stObj.popup>
<cfif len(trim(popup)) eq 0><cfset popup = "No">></cfif>
<cfset statusBar = stObj.statusBar>
<cfif len(trim(statusBar)) eq 0><cfset statusBar = "No">></cfif>
<cfset toolbar = stObj.toolbar>
<cfif len(trim(toolbar)) eq 0><cfset toolbar = "No">></cfif>
<cfset menubar = stObj.menubar>
<cfif len(trim(menubar)) eq 0><cfset menubar = "No">></cfif>
<cfset scrollbars = stObj.scrollbars>
<cfif len(trim(scrollbars)) eq 0><cfset scrollbars = "No">></cfif>
<cfset height = stObj.height>
<cfset width = stObj.width>
</cfif>
<cfset aNavalias = listToArray(listSort(structKeyList(application.navid),'textnocase'))>
<cfsetting enablecfoutputonly="no"><cfoutput>
<!--- Show the form --->
<form action="#cgi.script_name#?#cgi.query_string#" class="f-wrap-1 wider f-bg-medium" name="editform" method="post">
<fieldset>
<div class="req"><b>*</b>Required</div>
<h3>#application.adminBundle[session.dmProfile.locale].navigationNodeDetails#: <span class="highlight">#stObj.title#</span></h3>
<cfif errormessage NEQ "">
<p id="fading1" class="fade"><span class="error">#errormessage#</span></p><br />
</cfif>
<label for="title"><b>#application.adminBundle[session.dmProfile.locale].titleLabel#<span class="req">*</span></b>
<input type="text" name="title" id="title" value="#title#" maxlength="255" size="45" /><br />
</label>
<display:OpenLayer title="#application.adminBundle[session.dmProfile.locale].advancedOptions#" isClosed="Yes" border="no">
<label for="externalLink"><b>#application.adminBundle[session.dmProfile.locale].symbolicLinkLabel#</b>
<select name="externalLink">
<option value=""<cfif externalLink EQ "">selected="selected"</cfif>>#application.adminBundle[session.dmProfile.locale].noneForSelect#</option><cfloop from="1" to="#arraylen(aNavalias)#" index="i">
<option value="#application.navid[aNavalias[i]]#"<cfif externalLink EQ application.navid[aNavalias[i]]>selected="selected"</cfif>>#aNavalias[i]#</option></cfloop>
</select>
</label><br />
<label for="lNavIDAlias"><b>#application.adminBundle[session.dmProfile.locale].navAliases#</b>
<input type="text" name="lNavIDAlias" id="lNavIDAlias" value="#lNavIDAlias#" maxlength="255" size="45" /><br />
</label><br />
<label for="fu"><b>Friendly URL:</b>
<input type="text" name="fu" id="fu" value="#fu#" maxlength="255" size="45" /><br />
</label><br />
<label for="popup"><b>Open New Window?</b>
<select name="popup" onchange="showWindowOptions()">
<option value="Yes" <cfif popup>selected</cfif>>Yes</option>
<option value="No" <cfif NOT popup>selected</cfif>>No</option>
</select><br>
</label><br />
<div id="windowOptionsLabel" style="<cfif popup>display:block;<cfelse>display:none;</cfif>font-weight:bold;">New Window Options:<br><br></div>
<div id="windowOptions" style="<cfif popup>display:block;<cfelse>display:none;</cfif>font-weight:bold; margin-left:50px;">
<label for="statusBar"><b>Show Status Bar?</b>
<select name="statusBar">
<option value="Yes" <cfif statusBar>selected</cfif>>Yes</option>
<option value="No" <cfif NOT statusBar>selected</cfif>>No</option>
</select><br>
</label>
<label for="toolbar"><b>Show Toolbar?</b>
<select name="toolbar">
<option value="Yes" <cfif toolbar>selected</cfif>>Yes</option>
<option value="No" <cfif NOT toolbar>selected</cfif>>No</option>
</select><br>
</label>
<label for="menuBar"><b>Show Menu Bar?</b>
<select name="menuBar">
<option value="Yes" <cfif menuBar>selected</cfif>>Yes</option>
<option value="No" <cfif NOT menuBar>selected</cfif>>No</option>
</select><br>
</label>
<label for="scrollbars"><b>Show Scrollbars?</b>
<select name="scrollbars">
<option value="Yes" <cfif scrollbars>selected</cfif>>Yes</option>
<option value="No" <cfif NOT scrollbars>selected</cfif>>No</option>
</select><br>
</label>
<label for="height"><b>Height:</b>
<input type="text" name="theHeight" id="theHeight" value="#height#" style="width:50px;"><br>
</label>
<label for="Width"><b>Width:</b>
<input type="text" name="theWidth" id="theWidth" value="#width#" style="width:50px;"><br>
</label>
</div>
</display:OpenLayer>
</fieldset>
<div class="f-submit-wrap">
<input type="submit" name="submit" value="OK" class="f-submit" />
<input type="submit" name="cancel" value="Cancel" class="f-submit" />
</div>
<input type="hidden" name="bFormSubmitted" value="yes">
</form>
<script type="text/javascript">
//bring focus to title
document.editform.title.focus();
qFormAPI.errorColor="##cc6633";
objForm = new qForm("editform");
objForm.title.validateNotNull("#application.adminBundle[session.dmProfile.locale].pleaseEnterTitle#");
function showWindowOptions() {
if (document.editform.popup.options[document.editform.popup.selectedIndex].value == "Yes"){
document.getElementById("windowOptionsLabel").style.display = "block";
document.getElementById("windowOptions").style.display = "block";
popupValue = "on";
}
else {
document.getElementById("windowOptionsLabel").style.display = "none";
document.getElementById("windowOptions").style.display = "none";
document.editform.statusBar.options[1].selected = true;
document.editform.toolbar.options[1].selected = true;
document.editform.menuBar.options[1].selected = true;
document.editform.scrollbars.options[1].selected = true;
document.getElementById("theHeight").value = "";
document.getElementById("theWidth").value = "";
popupValue = "off";
}
}
</script>
</cfoutput>
Finally, I made a change in the nav.cfm file that builds the menu. In the _genericNav.cfm file it’s at line 169 where you see this code:
// write the link
writeOutput("><a href="""&href&""">"&trim(qNav.ObjectName[i])&"</a>");
I changed that to this:
// write the link
if (qNav.popup[i] eq 1) {
windowOptions = "menuBar=" & qNav.menuBar[i] & ",statusBar=" & qNav.statusBar[i] & ",toolbar=" & qNav.toolbar[i] & ",height=" & qNav.height[i] & ",width=" & qNav.width[i];
jsString = "javascript:window.open('" & href & "', '" & replaceNoCase(qNav.objectName[i], " ", "_", "ALL");
jsString = jsString & "', '" & windowOptions & "')";
writeOutput("><a onClick="""&jsString&"""><span id=""shadow"">"&trim(qNav.ObjectName[i])&"</span><span id=""text"">"&trim(qNav.ObjectName[i])&"</span></a>");
}
else {
writeOutput("><a href="""&href&"""><span id=""shadow"">"&trim(qNav.ObjectName[i])&"</span><span id=""text"">"&trim(qNav.ObjectName[i])&"</span></a>");
}
I should note that you also have to change how the qNav object is built. This is line 60 in _genericNav.cfm. Look for “lColumns=’externallink’”. What lColumns does is tells the function being called (getDescendents in our case) which additional columns to return. Make it look like this: “lColumns=’externallink,popup,statusBar,toolbar,menuBar,scrollbars,height,width’” So you are adding popup, statusBar, toolbar, menuBar, scrollbars, height and width in a standard comma-delimited list.
After this there is just one final step. In the farcry webtop you need to go to the Admin tab, select COAPI Management from the dropdown, click “Type Classes” and it will display a bunch of dependency conflicts. There will be a dropdown next to each and a “Go” button. Select the 2nd option from the dropdown for ach saying “deploy change” and click “Go.” Now go try and edit a navigation node.
And voila! Hopefully I didn’t miss anything and this just works but if I did, just leave me a comment and I’ll help you work it out.

Related Articles
No user responded in this post
Leave A Reply