1. Create a Coldfusion Component (cfc) to gather and package your data (See File 1)
2. Create a page to call the cfc and display the returned data. (See File 2)
--------------------------------------------
File 1. (/components/remote.cfc)
--------------------------------------------
<cfcomponent output="false">
<cffunction name="get" access="private" returntype="query" output="yes">
<cfset var q = "">
<cfquery name="q" datasource="#REQUEST.mysqldsn#">
SELECT *
FROM departments
</cfquery>
<cfreturn q>
</cffunction>
<cffunction name="queryToArray" access="private" returntype="array" output="No">
<cfargument name="queryIn" required="Yes" type="query">
<cfset var aResult = arrayNew(1)>
<cfset var q = ARGUMENTS.queryIn>
<cfset var stData = structNew()>
<cfloop query="q">
<cfset stData = structNew()>
<cfloop list="#q.columnList#" index="col">
<cfset stData["#col#"] = Evaluate('q.' & col)>
</cfloop>
<cfset arrayAppend(aResult,stData)>
</cfloop>
<cfreturn aResult>
</cffunction>
<cffunction name="getJSON" access="remote" output="yes" returntype="void">
<cfheader name="Cache-Control" value= "no-cache">
<cfheader name="Expires" value="0">
<cfheader name="Pragma" value="no-cache">
<!--- Get department data --->
<cfset departments = get()>
<!--- SPRY likes to work with an array of structures rather than a query object since those are unique to Coldfusion. --->
<cfoutput>#serializeJSON(queryToArray(departments))#</cfoutput>
</cffunction>
</cfcomponent>
--------------------------------------------
--------------------------------------------
File 2. (mySpryExample.cfm)
--------------------------------------------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<cfheader name="Cache-Control" value= "no-cache">
<cfheader name="Expires" value="0">
<cfheader name="Pragma" value="no-cache">
<html>
<head>
<title>SPRY At Work</title>
<script src="/SpryAssets/SpryData.js" type="text/javascript"></script>
<script src="/SpryAssets/SpryJSONDataSet.js" type="text/javascript"></script>
<script language="JavaScript">
var ds1 = new Spry.Data.JSONDataSet("/components/remote.cfc?method=getJSON",{useCache:false});
</script>
</head>
<body>
<div spry:region="ds1">
<table>
<tr>
<th spry:sort="DEPARTMENTID" style="cursor:pointer;">Dept ID</th>
<th spry:sort="DEPARTMENT" style="cursor:pointer;">Department</th>
</tr>
<tr spry:repeat="ds1" spry:even="altColor">
<td>{ds1::DEPARTMENTID}</td>
<td>{ds1::DEPARTMENT}</td>
</tr>
</table>
</div>
</body>
</html>
--------------------------------------------
--------------------------------------------
MySQL Table Construct
--------------------------------------------
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for departments
-- ----------------------------
CREATE TABLE `departments` (
`departmentid` int(11) NOT NULL auto_increment,
`department` varchar(45) default NULL,
PRIMARY KEY (`departmentid`),
UNIQUE KEY `deptid` (`departmentid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records
-- ----------------------------
INSERT INTO `departments` VALUES ('1', 'Sales');
INSERT INTO `departments` VALUES ('2', 'Accounting');
INSERT INTO `departments` VALUES ('3', 'Customer Service');
--------------------------------------------
This code has been tested on Firefox and I.E.
Fusecast Web Application Development and Web Hosting Services
www.fusecast.com
Wednesday, May 14, 2008
Tuesday, May 13, 2008
Getting Internet Explorer to Release Dataset Cache
Getting I.E. to STOP caching Spry datasets.
This help can be applied to all languages (PHP, ASP, Coldfusion) but since I am primarily a Coldfusion developer, I'll demonstrate how I solved this issue using CFML and JavaScript.
--------------------------------------------------------------------------
File 1. remote.cfc
This file basically returns the XML I will call from Spry
--------------------------------------------------------------------------
<cfcomponent>
<cffunction name="qGetData" access="remote" output="No" returntype="any">
<cfargument name="chatid" required="Yes">
<cfquery name="qGetData" datasource="#DSN#">
SELECT *
FROM chat
WHERE chatid = #ARGUMENTS.chatid#
</cfquery>
<!--- !!!!! IMPORTANT !!!!! --->
<!--- START :: THIS BLOCK OF CODE IS REQUIRED!!! THIS IS WHAT TELLS SPRY TO NOT CACHE THE INCOMING DATA --->
<cfcontent type="text/xml"><!--- I.E. NEEDS THIS --->
<cfheader name="Cache-Control" value= "no-cache">
<cfheader name="Expires" value="0">
<cfheader name="Pragma" value="no-cache">
<!--- END :: THIS BLOCK OF CODE IS REQUIRED!!! THIS IS WHAT TELLS SPRY TO NOT CACHE THE INCOMING DATA --->
<!--- !!!!! IMPORTANT !!!!! --->
<cfset rtrn = "">
<cfxml variable="rtrn">
<chat>
<topic><cfoutput>#qGetData.topic#</cfoutput></topic>
<cfoutput query="qGetData">
<thread>
<date>#DateFormat(qGetData.dtCreated,"m/d/yyyy")#</date>
<time>#TimeFormat(qGetData.dtCreated,"h:mm:ss tt")#</time>
<firstName>#qGetData.first_name#</firstName>
<lastName>#qGetData.last_name#</lastName>
<content><![CDATA[#qGetData.content#]]></content>
</thread>
</cfoutput>
</chat>
</cfxml>
<cfreturn rtrn>
</cffunction>
</cfcomponent>
--------------------------------------------------------------------------
--------------------------------------------------------------------------
File 2. Calling page (chat.cfm)
This file uses Spry to get my dataset from File 1.
--------------------------------------------------------------------------
<cfheader name="Cache-Control" value= "no-cache">
<cfheader name="Expires" value="0">
<cfheader name="Pragma" value="no-cache">
<html>
<head><title>My Chat</title></head>
<script src="/SpryAssets/xpath.js" type="text/javascript"></script>
<script src="/SpryAssets/SpryData.js" type="text/javascript"></script>
<body>
<cfoutput><script language="JavaScript">
//!!!!! IMPORTANT !!!!!
//This variable is appended to the query string to ensure that a cached dataset isn't returned.
var d = new Date().valueOf();
//!!!!! IMPORTANT !!!!!
threads = new Spry.Data.XMLDataSet("/components/remote.cfc?method=qGetData&chatid=#URL.chatid#&cacheBuster=" + d.toString(), //!!!!! IMPORTANT !!!!!
"chat/thread",
{
distinctOnLoad:true,
loadInterval:2000,
useCache:false //this ONLY works in Firefox.
}
);
//The content column needs to be defined as HTML. What a bugger this was to figure out!
threads.setColumnType("content", "html");
</script></cfoutput>
<!--- Output your data! --->
<div spry:region="threads">
<div spry:repeat="threads">
{threads::firstName} says: {threads::time}<br>
<div>{threads::content}</div>
</div>
</div>
</body>
</html>
--------------------------------------------------------------------------
That should do it. EVERYWHERE you see !!!!! IMPORTANT !!!!! you must be sure to do.
Good luck!
Steve Holland
Fusecast
This help can be applied to all languages (PHP, ASP, Coldfusion) but since I am primarily a Coldfusion developer, I'll demonstrate how I solved this issue using CFML and JavaScript.
--------------------------------------------------------------------------
File 1. remote.cfc
This file basically returns the XML I will call from Spry
--------------------------------------------------------------------------
<cfcomponent>
<cffunction name="qGetData" access="remote" output="No" returntype="any">
<cfargument name="chatid" required="Yes">
<cfquery name="qGetData" datasource="#DSN#">
SELECT *
FROM chat
WHERE chatid = #ARGUMENTS.chatid#
</cfquery>
<!--- !!!!! IMPORTANT !!!!! --->
<!--- START :: THIS BLOCK OF CODE IS REQUIRED!!! THIS IS WHAT TELLS SPRY TO NOT CACHE THE INCOMING DATA --->
<cfcontent type="text/xml"><!--- I.E. NEEDS THIS --->
<cfheader name="Cache-Control" value= "no-cache">
<cfheader name="Expires" value="0">
<cfheader name="Pragma" value="no-cache">
<!--- END :: THIS BLOCK OF CODE IS REQUIRED!!! THIS IS WHAT TELLS SPRY TO NOT CACHE THE INCOMING DATA --->
<!--- !!!!! IMPORTANT !!!!! --->
<cfset rtrn = "">
<cfxml variable="rtrn">
<chat>
<topic><cfoutput>#qGetData.topic#</cfoutput></topic>
<cfoutput query="qGetData">
<thread>
<date>#DateFormat(qGetData.dtCreated,"m/d/yyyy")#</date>
<time>#TimeFormat(qGetData.dtCreated,"h:mm:ss tt")#</time>
<firstName>#qGetData.first_name#</firstName>
<lastName>#qGetData.last_name#</lastName>
<content><![CDATA[#qGetData.content#]]></content>
</thread>
</cfoutput>
</chat>
</cfxml>
<cfreturn rtrn>
</cffunction>
</cfcomponent>
--------------------------------------------------------------------------
--------------------------------------------------------------------------
File 2. Calling page (chat.cfm)
This file uses Spry to get my dataset from File 1.
--------------------------------------------------------------------------
<cfheader name="Cache-Control" value= "no-cache">
<cfheader name="Expires" value="0">
<cfheader name="Pragma" value="no-cache">
<html>
<head><title>My Chat</title></head>
<script src="/SpryAssets/xpath.js" type="text/javascript"></script>
<script src="/SpryAssets/SpryData.js" type="text/javascript"></script>
<body>
<cfoutput><script language="JavaScript">
//!!!!! IMPORTANT !!!!!
//This variable is appended to the query string to ensure that a cached dataset isn't returned.
var d = new Date().valueOf();
//!!!!! IMPORTANT !!!!!
threads = new Spry.Data.XMLDataSet("/components/remote.cfc?method=qGetData&chatid=#URL.chatid#&cacheBuster=" + d.toString(), //!!!!! IMPORTANT !!!!!
"chat/thread",
{
distinctOnLoad:true,
loadInterval:2000,
useCache:false //this ONLY works in Firefox.
}
);
//The content column needs to be defined as HTML. What a bugger this was to figure out!
threads.setColumnType("content", "html");
</script></cfoutput>
<!--- Output your data! --->
<div spry:region="threads">
<div spry:repeat="threads">
{threads::firstName} says: {threads::time}<br>
<div>{threads::content}</div>
</div>
</div>
</body>
</html>
--------------------------------------------------------------------------
That should do it. EVERYWHERE you see !!!!! IMPORTANT !!!!! you must be sure to do.
Good luck!
Steve Holland
Fusecast
Tuesday, March 25, 2008
Set All Form Fields In All Forms To Disabled
/*----------------------------------------------------
This code disables ALL fields in all forms on a screen.
USAGE:
<script language="JavaScript">
disableForms()
</script>
----------------------------------------------------*/
function disableForms(){
//Loop over the forms
for(i=0;i<document.forms.length;i++){
//Loop over the form elements
for(j=0;j>document.forms[i].elements.length;j++){
//alert(document.forms[i].elements[j].name);
document.forms[i].elements[j].disabled = "true";
}
}
}
This code disables ALL fields in all forms on a screen.
USAGE:
<script language="JavaScript">
disableForms()
</script>
----------------------------------------------------*/
function disableForms(){
//Loop over the forms
for(i=0;i<document.forms.length;i++){
//Loop over the form elements
for(j=0;j>document.forms[i].elements.length;j++){
//alert(document.forms[i].elements[j].name);
document.forms[i].elements[j].disabled = "true";
}
}
}
Friday, February 8, 2008
FCKEditor and Stylesheets
Getting FCKEditor to work with your stylesheets is a trick because documentation on how to do it is not very good. You get the basics here and there but finding docs that tell you how from A-Z just doesn't exists.... till now. Here's how I did it.
This is what I figured out for FCKEditor to get it to use custom stylesheets...
1. Open up /fckeditor/fckconfig.js
1a. Edit the following variable:
FCKConfig.BaseHref = 'http://www.yourDomain.com/';
FCKConfig.EditorAreaCSS = '/style.css' ;
Save and close
2. Open up /fckeditor/fckstyles.xml
2a. Define your styles:
E.g.
<Style name="heading1" element="span">
<Attribute name="class" value="heading1" />
</Style>
<Style name="heading2" element="span">
<Attribute name="class" value="heading2" />
</Style>
<Style name="heading3" element="span">
<Attribute name="class" value="heading3" />
</Style>
(Note: this XML must coincide with your CSS. If you have a Style called "myHeader", then you would have XML that would look like this)
<Style name="myHeader" element="span">
<Attribute name="class" value="myHeader" />
</Style>
Save and close.
The Jist.
The first operation pulls in the entire CSS stylesheet your using.
The second operation allows you to show in the style drop down what styles to be used by the user. Not all of the styles in the CSS file are seen or needed by the user normally. This is a great way to separate them but allow them to use their defined styles.
This is what I figured out for FCKEditor to get it to use custom stylesheets...
1. Open up /fckeditor/fckconfig.js
1a. Edit the following variable:
FCKConfig.BaseHref = 'http://www.yourDomain.com/';
FCKConfig.EditorAreaCSS = '/style.css' ;
Save and close
2. Open up /fckeditor/fckstyles.xml
2a. Define your styles:
E.g.
<Style name="heading1" element="span">
<Attribute name="class" value="heading1" />
</Style>
<Style name="heading2" element="span">
<Attribute name="class" value="heading2" />
</Style>
<Style name="heading3" element="span">
<Attribute name="class" value="heading3" />
</Style>
(Note: this XML must coincide with your CSS. If you have a Style called "myHeader", then you would have XML that would look like this)
<Style name="myHeader" element="span">
<Attribute name="class" value="myHeader" />
</Style>
Save and close.
The Jist.
The first operation pulls in the entire CSS stylesheet your using.
The second operation allows you to show in the style drop down what styles to be used by the user. Not all of the styles in the CSS file are seen or needed by the user normally. This is a great way to separate them but allow them to use their defined styles.
Tuesday, December 4, 2007
Time Machine Hangs
I have found an issue with Time Machine on Mac Leopard 10.5.1 where it hangs and causes all sorts of grief. I found that it does this when I have Parallels open.
Here is how I fixed it. (Before we start, be sure Parallels is off)
1. Turn off Time Machine.
2. Open up Time Machine Preferences.
3. Click the "Options" button.
4. At the bottom left is a button with a "+" sign. Click it. (We're going to add an exception to TM)
5. Navigate to /users/[user]/Documents
6. Select the "Parallels" directory and click the "Exclude" button.
(You have just excluded Time Machine from backing up your parallels directory. When Parallels is open, the contents of this directory are constantly changing. This drives Time Machine crazy for some reason.)
7. Turn on Time Machine.
You're done. Good luck.
Here is how I fixed it. (Before we start, be sure Parallels is off)
1. Turn off Time Machine.
2. Open up Time Machine Preferences.
3. Click the "Options" button.
4. At the bottom left is a button with a "+" sign. Click it. (We're going to add an exception to TM)
5. Navigate to /users/[user]/Documents
6. Select the "Parallels" directory and click the "Exclude" button.
(You have just excluded Time Machine from backing up your parallels directory. When Parallels is open, the contents of this directory are constantly changing. This drives Time Machine crazy for some reason.)
7. Turn on Time Machine.
You're done. Good luck.
Tuesday, August 21, 2007
Verity Collection Creation Error
When creating Verity collections, you may get this error from time to time.
ERROR
An error occurred while performing an operation in the Search Engine library.
Error opening the collection: com.verity.organize.WorkSpaceException: Path not found [VdkError_PathNotFound]. (-104)
ANOTHER RELATED ERROR
If you go into your CFADMIN and click on Verity, you may get the following message.
I found that the problem was in the creation of the "bookclub" collection on new CF installs. However, if you have a collection gone wild, this is how you can fix it.
FIX TO BOTH ERRORS
1. Delete the collection(s) definition(s) via code or from the verity admin in CFADMIN if you can. If you can't see the collections do it via the code below.
VERITY COLLECTIONS BEFORE PURGE
<cfdirectory action="LIST" directory="[CFINSTALL]/verity/collections" name="GetCols">
<cfdump var="#GetCols#">
<br>
DELETE ALL COLLECTIONS
<cfoutput query="GetCols">
<cfif GetCols.name DOES NOT CONTAIN ".">
<cfcollection action="DELETE" collection="#GetCols.name#" path="[ CFINSTALL]/verity/collections/#GetCols.name#">
"#GetCols.name#" collection removed<br><br>
</cfif>
</cfoutput>
VERITY COLLECTIONS AFTERPURGE
<cfdirectory action="LIST" directory="[CFINSTALL]/verity/collections" name="GetCols">
<cfdump var="#GetCols#">
2. Go to:
[CFINSTALL]/verity/Data/services/ColdFusionK2_indexserver1/ws
(The "ws" directory acts as a work space during collection creation)
3. Run: [rm –rf *] to remove everything in the ws directory.
4. Run: [CFINSTALL]/bin/cfmxsearch restart
5. Re-create the collection in the CFADMIN or using CFCOLLECTION.
ERROR
An error occurred while performing an operation in the Search Engine library.
Error opening the collection: com.verity.organize.WorkSpaceException: Path not found [VdkError_PathNotFound]. (-104)
ANOTHER RELATED ERROR
If you go into your CFADMIN and click on Verity, you may get the following message.
Unable to retrieve collections from the Search Service.
Please verify that the ColdFusion Search Server is installed and running.
Please verify that the ColdFusion Search Server is installed and running.
I found that the problem was in the creation of the "bookclub" collection on new CF installs. However, if you have a collection gone wild, this is how you can fix it.
FIX TO BOTH ERRORS
1. Delete the collection(s) definition(s) via code or from the verity admin in CFADMIN if you can. If you can't see the collections do it via the code below.
VERITY COLLECTIONS BEFORE PURGE
<cfdump var="#GetCols#">
<br>
DELETE ALL COLLECTIONS
<cfoutput query="GetCols">
<cfif GetCols.name DOES NOT CONTAIN ".">
<cfcollection action="DELETE" collection="#GetCols.name#" path="[
"#GetCols.name#" collection removed<br><br>
</cfif>
</cfoutput>
<cfdump var="#GetCols#">
2. Go to:
[CFINSTALL]/verity/Data/services/ColdFusionK2_indexserver1/ws
(The "ws" directory acts as a work space during collection creation)
3. Run: [rm –rf *] to remove everything in the ws directory.
4. Run: [CFINSTALL]/bin/cfmxsearch restart
5. Re-create the collection in the CFADMIN or using CFCOLLECTION.
Tuesday, April 3, 2007
MySQL and Coldfusion Isolation Types
I was working a locking and speed problem with our MySQL Servers today and found something interesting you may want to have a look at.
MySQL defaults its tables to MyISAM. In order to create Foreign Key relationships, the tables must be changed to InnoDB. The problem with InnoDB is that by default the isolation level for the tables are "REPEATABLE-READ".
In reading the documentation for CF on cftransaction tags, adobe says that "REPEATABLE-READ" is the same as read-committed, except that rows in the recordset are exclusively locked until the transaction completes. Due to high overhead, Macromedia does not recommend this isolation level for normal database access..
The recommended isolation level is "READ-COMMITTED".
Now you can go through ever query statement and encase each with a cftransaction tag specifying the isolation type OR you can set it as the general isolation type for MySQL.
This is how to change the default isolation level for MySQL. It's simple and fast and requires a quick MySQL restart.
1. Run the following SQL to see what the default Isolation level was for the DB.
SELECT @@global.tx_isolation;
SELECT @@tx_isolation;
If you got back anything but "READ-COMMITTED", continue on to step 2.
2. I created a text file called my.cnf.
------------------------------
File contents
=====================
[mysqld]
transaction-isolation = READ-COMMITTED
=====================
Note: Do not use the dashes or "File contents". Just the portion between the "=" signs. If you have a my.cnf, just add "transaction-isolation = READ-COMMITTED" to it.
3. Uploaded the file (my.cnf) to /etc/ on the server (Linux)
4. Restart MySQL /etc/init.d/mysql restart
5. Re-run the following SQL
SELECT @@global.tx_isolation ;
SELECT @@tx_isolation;
You should get back "READ-COMMITTED"
Boom! Game on! Now your servers will be running what Adobe recommends for CF.
When I did this, immediately I saw huge performance gains from my production box!
Hope this helps!
Steve H.
www.fusecast.com
Web hosting, design and development services.
MySQL defaults its tables to MyISAM. In order to create Foreign Key relationships, the tables must be changed to InnoDB. The problem with InnoDB is that by default the isolation level for the tables are "REPEATABLE-READ".
In reading the documentation for CF on cftransaction tags, adobe says that "REPEATABLE-READ" is the same as read-committed, except that rows in the recordset are exclusively locked until the transaction completes. Due to high overhead, Macromedia does not recommend this isolation level for normal database access..
The recommended isolation level is "READ-COMMITTED".
Now you can go through ever query statement and encase each with a cftransaction tag specifying the isolation type OR you can set it as the general isolation type for MySQL.
This is how to change the default isolation level for MySQL. It's simple and fast and requires a quick MySQL restart.
1. Run the following SQL to see what the default Isolation level was for the DB.
SELECT @@global.tx_isolation;
SELECT @@tx_isolation;
If you got back anything but "READ-COMMITTED", continue on to step 2.
2. I created a text file called my.cnf.
------------------------------
File contents
=====================
[mysqld]
transaction-isolation = READ-COMMITTED
=====================
Note: Do not use the dashes or "File contents". Just the portion between the "=" signs. If you have a my.cnf, just add "transaction-isolation = READ-COMMITTED" to it.
3. Uploaded the file (my.cnf) to /etc/ on the server (Linux)
4. Restart MySQL /etc/init.d/mysql restart
5. Re-run the following SQL
SELECT @@global.tx_isolation ;
SELECT @@tx_isolation;
You should get back "READ-COMMITTED"
Boom! Game on! Now your servers will be running what Adobe recommends for CF.
When I did this, immediately I saw huge performance gains from my production box!
Hope this helps!
Steve H.
www.fusecast.com
Web hosting, design and development services.
Subscribe to:
Posts (Atom)
