ColdFusion shopping cart - coldfusion

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.

Related

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>

creating dynamic drop down menu in 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>

Creating valid XML with ColdFusion XMLParse

I am attempting to use XMLParse against content that is not valid xhtml. In the html code, the tags are not properly terminated. In order to terminate them, I am using the replace function to find the invalid code and replace it with properly terminated code. In doing so, my application errors out and tells me that the meta tag is invalid:
An error occured while Parsing an XML document.
The element type "meta" must be terminated by the matching end-tag "".
The code I'm trying to validate is:
<html>
<head>
<title>Impart Client Interface</title>
<link href="side_panel.css" rel="stylesheet" type="text/css">
<link href="default.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
<link href="data_tables.css" rel="stylesheet" type="text/css">
<link href="xp_button.css" rel="stylesheet" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
What I've created in CF to attempt to handle this is:
<cfset xml = objResponse.FileContent>
<cfset page.content = '<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">'>
<cfset page.updatedcontent = replace('#page.content#','8859-1','8859-1" />"','')>
<Cfset page.link = 'type="text/css">'>
<cfset page.updatedLink = replace('#page.link#', 'css">', 'css" />', 'all')>
<cfset validXML = replace(#xml#, "#page.content#", "#page.updatedContent#", "")>
<cfset validXML = replace(#xml#, "#page.link#", "#page.UpdatedLink#", "all")>
<cfoutput>#validXML#</cfoutput>
<cfset parsethis = xmlparse(validXML)>
<cfdump var="#parsethis#">
How can I resolve this error?
Looks to me like you are missing part of the substring in your replace call:
<cfset page.updatedcontent = replace(page.content,'8859-1">','8859-1" />')>
Note the addition of ">
So, the above will address your specific technical question. I'd like to suggest a better approach to your general task, however. Doing string manipulation on HTML to try to mash it into proper XHTML is tricky at best (as you have seen). Instead, consider abandoning XMLParse in favor of an actual HTML parser, such as JSOUP. After you download the jar and add it to your CF classpath, you can do things like this:
<cfset jsoup = CreateObject("java", "org.jsoup.Jsoup")>
<cfsavecontent variable="html">
<html>
<body>
<hr>
<pre id="blah">Foo<br>bar1</pre>
<hr>
<pre id="blah2">Foo<br>bar2</pre>
</body>
</html>
</cfsavecontent>
<cfdump var="#jsoup.parse(html).select('pre').first().html()#">
Which will output :
Foo<br />bar1
Pretty spiffy, eh? And no need to pull out your hair over getting exact details right with XML.

How do I write text in ColdFusion?

I'm trying to understand ColdFusion, as I am coming from ASP.NET. I've put together a sample page to piggy-back off some already finished code -- but I can't seem to get the actual data from the object I am creating:
<cfset objProduct = createObject("component", "com.MyObj.Product")>
<cfset prodExists = objProduct.getProduct(10)>
<html>
<head/>
<body>
<h2>#objProduct.ProductName#</h2>
</body>
... It simply prints the literal #objProduct.ProductName# text, and not the data from within the object. Any idea where I'm going astray?
Thanks!
Don't forget the <cfoutput>!
<cfoutput>
<html>
<head>
<title>Test</title>
</head>
<body>
<h2>#HtmlEditFormat(objProduct.ProductName)#</h2>
</body>
</html>
</cfoutput>
You forgot the CFOUTPUT tags.
You're trying to output the wrong variable.
#objProduct.getProduct(10)#
or
<cfoutput>#prodExists#</cfoutput>