creating dynamic drop down menu in ColdFusion - coldfusion

I am trying to create a dynamic database-driven drop down menu in a ColdFusion page.
I have written ul and li tags in a cfoutput tag, but nothing is displaying in the page.
<cfset dbsource="ndev9">
<cfset dbschema="security">
<cfset dbuserid="security">
<cfset dbpw="sec">
<html>
<link rel="stylesheet" href="menubar_new.css">
<link rel="stylesheet" href="bannerstyle.css">
<cfquery name="main_menu" datasource="#dbsource#" username="#dbuserid#" password="#dbpw#">
select * from #dbschema#.main_menu order by MAIN_MENU_ORDER
</cfquery>
<body>
<cfoutput>
<ul id="menu_new">
<cfloop query="main_menu">
<li>#main_menu.main_menu_name#</li>
</cfloop>
</ul>
</cfoutput>
</body>
</html>

Related

ColdFusion - CFDOCUMENT Title in URL

I am creating a PDF document using ColdFusion cfdocument tag. Works fine, however instead of showing the document name in browser Title - it shows the .cfc file that I call to create the PDF.
Here is how I'm calling it.
<cfdocument format="pdf" marginbottom=".5" margintop=".25" marginright=".5" marginleft=".5" saveAsName="#filename#.pdf">
<cfdocumentitem type="footer">
<p style="font-size:11px; text-align:right; font-style:italic;">Page #cfdocument.currentpagenumber# of #cfdocument.totalpagecount#</p>
</cfdocumentitem>
<html>
<head><title>#filename#.pdf</title></head>
<body><img src="file:///#application.tempFolder#\#thisFilename#" /></body>
</html>
</cfdocument>
What the heck am I missing? Why does it still show the filename.cfc file that I'm calling in the browser title instead of the filename I give to the PDF???
Figured it out. Had to create the document using CFDOCUMENT, then add a "Title" attribute to it using the CFPDF tag. Then output it to the browser.
<!--- Create the PDF --->
<cfdocument format="pdf" marginbottom=".5" margintop=".25" marginright=".5" marginleft=".5" filename="#application.tempFolder#\#thisSaveAsFilename#" overwrite="yes">
<cfdocumentitem type="footer">
<p style="font-size:11px; text-align:right; font-style:italic;">Page #cfdocument.currentpagenumber# of #cfdocument.totalpagecount#</p>
</cfdocumentitem>
<html>
<head><title>#thisSaveAsFilename#</title></head>
<body><img src="file:///#application.tempFolder#\#thisFilename#" /></body>
</html>
</cfdocument>
<!--- Use CFPDF to add attributes to it --->
<cfset thisInfo = StructNew()>
<cfset thisInfo.Title = "pdf title goes here...">
<cfpdf action="setinfo" info="#thisInfo#" source="#application.tempFolder#\#thisSaveAsFilename#" />
<!--- Send it to the browser --->
<cfcontent file="#application.tempFolder#\#thisSaveAsFilename#" type="application/pdf" />A

Styling a cfcontent which produced an excel sheet with an external stylesheet

I am trying to incorporate a stylesheet to a cfcontent tag that will produce an Excel spreadsheet as shown below. However, the stylesheet is always ignored even when it is linked with an explicit reference. What would ensure that the Excel spreadsheet would incorporate the stylesheet?
<cfsetting enablecfoutputonly="Yes">
<cfsavecontent variable="sTest">
<cfoutput>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="www.somesite.com/bootstrap/another.css" media="all">
<link rel="stylesheet" type="text/css" href="../cssBootstrap/css/another.css" media="all">
</head>
<body>
<cfinclude template="../Reports/reportexportedasEXcel.cfm">
</body>
</cfoutput>
</cfsavecontent>
<cfcontent type="application/vnd.ms-excel">
<cfheader name="Content-Disposition" value="attachment; filename=filename#DateFormat(now(),"mmdd")#-#TimeFormat(Now(),"HHMMSS")#.xls">
<cfoutput>
<html>
</head>
<body>
#sTest#
</body>
</html>
</cfoutput>
</cfcontent>
Include the protocol in the link to the style sheet. <link rel="stylesheet" type="text/css" href="http://www.somesite.com/bootstrap/another.css" media="all">
Another option would be to include the style sheet content into the xls file.
<cfset cssFilePath = getDirectoryFromPath(gettemplatePath()) & "../cssBootstrap/css/another.css" />
<cfset cssContent = fileRead(cssFilePath) />
</cfscript>
<html>
<cfoutput>
<head>
<style>#cssContent#</style>
</head>
</cfoutput>

Why is CFHTMLHEAD not working in ColdFusion 11?

I've tested several pages so far, and it seems that wherever I am attempting to use <CFHTMLHEAD> to add CSS or JavaScript to a CFM page in ColdFusion 11, it will not add it (works fine in CF8).
I read on SO about increasing the "Maximum Output Buffer size" in the Administrator > Server Setttings > Settings from the default valut of 1024KB, but every value I've tried (2048KB, 4096KB, and even the max allowed 999999KB) I get the same result - the content is not included in the <HEAD> tag when the page loads.
Has anyone else run into this and found a solution yet?
Code Sample:
htmlhead.cfm:
<cfif NOT ThisTag.HasEndTag>
<cfthrow message="Missing end tag for custom tag htmlhead." type="HeadWrap" />
</cfif>
<cfif ThisTag.ExecutionMode is "End">
<cfhtmlhead text="#ThisTag.GeneratedContent#" />
<cfset ThisTag.GeneratedContent = "" />
</cfif>
index.cfm:
<cfsilent>
<!---
Data Retrieval, validation, etc. here
--->
<cf_htmlhead>
<style type="text/css">
tr.status-RETIRED td {
color: #800000;
}
tr.status-PENDING td {
color: #008000;
}
</style>
<script type="text/javascript">
$(function(){
$(".options-menu").mouseleave(function(e){
$(this).hide("fast");
})
$(".options-menu-link").mouseover(function(){
$(".options-menu").hide("fast");
$(".options-menu[data-sku='" + $(this).data("sku") + "']").show("fast");
}).click(function(e){
e.preventDefault();
});
});
</script>
</cf_htmlhead>
</cfsilent>
<!---
Custom Tag layout.cfm contains the DOCTYPE declaration, html, head (loads jquery, jquery-ui, css, etc.), and body tags with a header and footer for each page.
--->
<cf_layout>
<!--- Page Content Here (a form, a table, some divs, etc.) --->
</cf_layout>
I've found that in CF11 anything added using a cfhtmlhead call that comes before a cfcontent reset="true" does not get added to the resulting document. Does the cf_layout tag you are calling after your cf_htmlhead contain a content reset?
For example,
<!--- This will not be added under CF11. --->
<cfhtmlhead text="<!-- I'm some content that will only be included in CF10 or lower. -->">
<cfcontent reset="true">
<!--- This will be added under CF11 and lower. --->
<cfhtmlhead text="<!-- I'm some content that will be added in CF11 and lower. -->">
... the rest of your view code ...
<!--- This is a sample of the content you will get under CF11 --->
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Head Testing</title>
<!-- I'm some content that will be added in CF11 and lower. -->
</head>
<body>
<h1>Page content</h1>
</body>
</html>

ColdFusion shopping cart

Update: I'm rewriting with all my code for each page as well as my error message... keep in mind I am very new and honestly don't know some of this code...
productlist.cfm 1st page: (hard coded product list code built from select statement)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/style.css" type="text/css" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/style.css" type="text/css" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/bootstrap-theme.min.css" type="text/css" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/bootstrap.min.css" type="text/css" />
<script type = "text/javascript" src="http://students.uwf.edu/jeb48/week8/assignments/scripts/jbrown.js"></script>
<script type = "text/javascript" src="http://students.uwf.edu/jeb48/week8/assignments/scripts/jbrown2.js"></script>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type = "text/javascript" src = "http://code.jquery.com/jquery-latest.js" ></script>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<title>Scuba Diving is Fun!</title>
</head>
<body>
<div class="container">
<cfquery name = "getlist" datasource="jeb48_shoppingcart">
SELECT ProductID, ProductName, ProductQty, ProductPrice, ProductDescription, ProductPhoto
FROM Products;
</cfquery>
<div class="row">
<div class="col-md-2"><b>Product Photo</b></div>
<div class="col-md-2"><b>Product ID</b></div>
<div class="col-md-2"><b>Product Name</b></div>
<div class="col-md-2"><b>Quantity in Inventory</b></div>
<div class="col-md-2"><b>Product Description</b></div>
<div class="col-md-2"><b>Unit Price</b></div>
</div !--row>
<cfoutput query ="getlist">
<div class="row equallist">
<div class="col-md-2">#getlist.ProductPhoto#</div>
<div class="col-md-2">#getlist.ProductID#</div>
<div class="col-md-2">#getlist.ProductName#</div>
<div class="col-md-2"><div style="text-align:center">#getlist.ProductQty#</div></div>
<div class="col-md-2"><div style="text-align:left">#getlist.ProductDescription#</div></div>
<div class="col-md-2"><div style="text-align:left">#DollarFormat(getlist.ProductPrice)#
<cfif #getlist.ProductQty# gt 0>
<br>Add to Cart
<cfelse>
<br>Out of Stock!
</cfif>
</div></div>
</div !--row>
</cfoutput>
</div !--container>
</body>
</html>
scart.cfm Page 2: This is the page I'm having trouble with... I know my code is messed up but I do not know how to fix it... the error I'm getting is on this page... the error is "Parameter validation error for the ARRAYAPPEND function." I'm trying to build a cart based on the link in the previous page.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/style.css" type="text/css" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/bootstrap-theme.min.css" type="text/css" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="http://students.uwf.edu/jeb48/css/style.css" type="text/css" />
<script type = "text/javascript" src="http://students.uwf.edu/jeb48/week8/assignments/scripts/jbrown.js"></script>
<script type = "text/javascript" src="http://students.uwf.edu/jeb48/week8/assignments/scripts/jbrown2.js"></script>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type = "text/javascript" src = "http://code.jquery.com/jquery-latest.js" ></script>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<title>Scuba Diving is Fun!</title>
</head>
<body>
<div class="container">
<h3><center>Your Shopping Cart</center></h3>
<cfparam name="url.productid" default="">
<cfparam name="url.qty" default="">
<cfquery name = "getCartItem" datasource="jeb48_shoppingcart">
SELECT ProductID, ProductName, ProductQty, ProductPrice, ProductDescription, ProductPhoto
FROM Products
WHERE ProductID = #url.productid#;
</cfquery>
<cfset arrShoppingCart = arrayNew(1) />
<cfparam name="session.cart" default="arrayNew()">
<cfset arrayAppend( "session.cart", structNew() )>
< cfset session.cart = arrayNew(1) >
< cfset thisCartItem = arraylen( session.cart )>
<cfset arrayAppend( session.cart, structNew() )>
< cfset thisCartItem = arraylen( session.cart )>
< cfset session.cart[thisCartItem].itemID = url.productid>
< cfset session.cart[thisCartItem].quantity = url.qty>
</body>
</html>
application.cfc
<cfcomponent>
<cfset this.name = "jeb48SC">
<cfset this.datasource = "jeb48_shoppingcart">
<cfset this.loginstorage="Session">
<cfset this.sessionmanagement="Yes">
<cfset this.sessiontimeout="#createtimespan(0,0,45,0)#">
</cfcomponent>
Once I get this working I can begin working on getting the output built... thanks for taking a look.
The details of the question have significantly changed, so editing my answer.
1: <cfset arrShoppingCart = arrayNew(1) />
2: <cfparam name="session.cart" default="arrayNew()">
3: <cfset arrayAppend( "session.cart", structNew() )>
4: < cfset session.cart = arrayNew(1) >
5: < cfset thisCartItem = arraylen( session.cart )>
6: <cfset arrayAppend( session.cart, structNew() )>
7: < cfset thisCartItem = arraylen( session.cart )>
8: < cfset session.cart[thisCartItem].itemID = url.productid>
9: < cfset session.cart[thisCartItem].quantity = url.qty>
There are a few problems with this code. I'll ignore the spaces after some opening brackets, you're clearly experimenting and canceling out some experiments.
On line 2, you're not creating an array, you're creating a string with the default value of "ArrayNew()". You need to add hashes around each end. "#ArrayNew()#".
On line 3, you have the array name quoted, which is invalid. Most cold fusion functions that require a variable name, want it unquoted. Some exceptions are StructkeyExists() and isDefined(), which serve similar purposes. They check if a variable exists so they ask for the variable name as a string, rather than raw.
Line 4, this is how you properly set an array. Good Job. The only thing is every time someone visits this page, this happens. This line should be when a session is first initiated and it should go something like this <cfif not isDefined("session.cart")><cfset session.cart=ArrayNew(1)></cfif>.
As I said before, you need to maintain data types across your application. One quick fix is to address your code problems and then create a page that has nothing but this <Cfset structclear(session)>. That gets rid of all your old session data.
You're on the right track after this. It can be tough when you're trying to debug something that you don't (yet!) understand several aspects of, but you'll get it.
Okay something else we need to talk about. You're new to CF? That's great, time to start an important habit early.
Any Time you're using a #variable# in a query, use a tag called <cfqueryparam. There's a mischievious thing called SQL injection, where a user can modify a url to cause havoc on the website. This tag is your primary defense against this
(There are occasions where some people don't feel it's necessary but you really cannot over-param your variables and as you're new, it's better to be safe than sorry).
Suppose I'm on scart.cfm?productID=7. If I change the url to scart.cfm?productID=7; DROP TABLE Products, your products table disappears. Or maybe I just want cheap goodies. scart.cfm?productID=7; UPDATE Products SET PRICE = 1 (I'd have to guess at column names here), but I could reset all your product prices.
Further CFQueryParam makes your queries slightly faster, and one of my favorite parts, is that when you provide the type, it handles the quoting for you.
Adobe was a bit silly when designing the tag and it's a little long-winded, but you get used to it.
You query above should look like this:
<cfquery name = "getCartItem" datasource="jeb48_shoppingcart">
SELECT ProductID, ProductName, ProductQty, ProductPrice, ProductDescription, ProductPhoto
FROM Products
WHERE ProductID = <cfqueryparam cfsqltype="cf_sql_integer" value="#url.productID#">
</cfquery>
Oh, because you're using this.datasource in application.cfc, providing a datasource here is not necessary. so your queries can just look like, which makaes your application more mobile.
<cfquery name="..."> or <cfquery> for queries where name isn't useful.
If you ever find yourself using additional datasources, you can store their names in the request scope, and then you can reference them like datasource="#request.db1#" or #request.db2#', etc. There are some applications people have designed that might have particular users using different databases so they have setups like #session.db#.
If I was searching for something by say a string value, the where could look like this WHERE ProductID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#form.productName#'>
See, the tag takes care of the quoting, and it lets other developers know your data types at a glance.
In the future, please provide more of the error.
From what you've shown, it looks like either:
A cfparam declares session.sCartItems somewhere, probably as a basic string. (<cfparam name="session.sCartItems" default=""> which basically just says, "If not defined, define it". In other words, a cfparam on a variable will make an isDefined() check pass.
In development, you've formerly declared session.sCartItems as a string, and that action is still alive. If that is the case, the not-isDefined() check fails, and the variable is not re-set as an array.
You should resolve the source of this problem. Data types of variables should remain consistent across your application, otherwise you will always constantly be trying to check data types.
However, changing this should bandaid-fix your problem.
<cfif not isDefined("session.scartItems")>
to:
<cfif not isDefined("session.scartItems") or not isArray(session.sCartItems)>
The way this is works is if your variable is not defined, the check stops there. If you variable is defined, the check continues to verify that it is an array.

Cfdocumentitem pagebreak during loop gives extra blank page

I am using CF9, and ColdBox. What I am doing is looping through a query, and assigning a page break at the end using cfdocumentitem pagebreak. However, it always gives me an extra blank page at the end. It's pretty much driving me crazy, so I defer to expert advice.
<cfdocument format="PDF" overwrite="Yes" localUrl="yes" pageType = "letter">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<cfquery name="Receipts" dbtype="query">
SELECT distinct id_number
FROM rc.RC1
</cfquery>
<cfoutput>
<cfloop query="Receipts">
<!--- removed for brevity --->
<cfdocumentitem type="pagebreak" />
</cfloop>
</cfoutput>
</body>
</html>
</cfdocument>
If you don't want to display the pagebreak after the last item in the loop then you have to explicitly say that. If the current row of the query is not the last row in the query then display the page break.
<cfloop query="Receipts">
<cfif Receipts.currentRow NEQ Receipts.recordCount>
<cfdocumentitem type="pagebreak" />
</cfif>
</cfloop>