Is there something built into Coldfusion that would let me know the browser and version number surfing my site? Are there existant libraries that would enable me to do this?
My google-fu hasn't shown many things other than simple if statements detecting IE.
I did do a dump of the cgi.http_user_agent variable in Chrome:
Mozilla/5.0 (Windows NT 5.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.77 Safari/534.24
There's three different browsers mentionned in there! Doing an if statement looking for either would return true. There's got to be a more formal approach?
This is much easier than the complicated function submitted earlier...
<CFIF FindNoCase('Chrome','#CGI.HTTP_USER_AGENT#') GREATER THAN 0>
<CFSET browser = 'Chrome'>
</CFIF>
credit: http://www.paulsilver.co.uk/code/coldfusion_detect_browser.php
Could you not use javascript instead? http://cssuseragent.org/
CSSUA is awesome, adds simple classes to the tag and allows you to target content in CSS/Javascript using classes like ua-ie-6 etc
There is a User-Defined Function which can parse out the user_agent string.
browserDetect
<cfscript>
/**
* Detects 130+ browsers.
* v2 by Daniel Harvey, adds Flock/Chrome and Safari fix.
*
* #param UserAgent User agent string to parse. Defaults to cgi.http_user_agent. (Optional)
* #return Returns a string.
* #author John Bartlett (jbartlett#strangejourney.net)
* #version 4, June 28, 2009
*/
function browserDetect() {
// Default User Agent to the CGI browser string
var UserAgent=CGI.HTTP_USER_AGENT;
// Regex to parse out version numbers
var VerNo="/?v?_? ?v?[\(?]?([A-Z0-9]*\.){0,9}[A-Z0-9\-.]*(?=[^A-Z0-9])";
// List of browser names
var BrowserList="";
// Identified browser info
var BrowserName="";
var BrowserVer="";
// Working variables
var Browser="";
var tmp="";
var tmp2="";
var x=0;
// If a value was passed to the function, use it as the User Agent
if (ArrayLen(Arguments) EQ 1) UserAgent=Arguments[1];
// Allow regex to match on EOL and instring
UserAgent=UserAgent & " ";
// Browser List (Allows regex - see BlackBerry for example)
BrowserList="1X|Amaya|Ubuntu APT-HTTP|AmigaVoyager|Android|Arachne|Amiga-AWeb|Arora|Bison|Bluefish|Browsex|Camino|Check&Get|Chimera|Chrome|Contiki|cURL|Democracy|" &
"Dillo|DocZilla|edbrowse|ELinks|Emacs-W3|Epiphany|Galeon|Minefield|Firebird|Phoenix|Flock|IceApe|IceWeasel|IceCat|Gnuzilla|" &
"Google|Google-Sitemaps|HTTPClient|HP Web PrintSmart|IBrowse|iCab|ICE Browser|Kazehakase|KKman|K-Meleon|Konqueror|Links|Lobo|Lynx|Mosaic|SeaMonkey|" &
"muCommander|NetPositive|Navigator|NetSurf|OmniWeb|Acorn Browse|Oregano|Prism|retawq|Shiira Safari|Shiretoko|Sleipnir|Songbird|Strata|Sylera|" &
"ThunderBrowse|W3CLineMode|WebCapture|WebTV|w3m|Wget|Xenu_Link_Sleuth|Oregano|xChaos_Arachne|WDG_Validator|W3C_Validator|" &
"Jigsaw|PLAYSTATION 3|PlayStation Portable|IPD|" &
"AvantGo|DoCoMo|UP.Browser|Vodafone|J-PHONE|PDXGW|ASTEL|EudoraWeb|Minimo|PLink|NetFront|Xiino|";
// Mobile strings
BrowserList=BrowserList & "iPhone|Vodafone|J-PHONE|DDIPocket|EudoraWeb|Minimo|PLink|Plucker|NetFront|PIE|Xiino|" &
"Opera Mini|IEMobile|portalmmm|OpVer|MobileExplorer|Blazer|MobileExplorer|Opera Mobi|BlackBerry\d*[A-Za-z]?|" &
"PPC|PalmOS|Smartphone|Netscape|Opera|Safari|Firefox|MSIE|HP iPAQ|LGE|MOT-[A-Z0-9\-]*|Nokia|";
// No browser version given
BrowserList=BrowserList & "AlphaServer|Charon|Fetch|Hv3|IIgs|Mothra|Netmath|OffByOne|pango-text|Avant Browser|midori|Smart Bro|Swiftfox";
// Identify browser and version
Browser=REMatchNoCase("(#BrowserList#)/?#VerNo#",UserAgent);
if (ArrayLen(Browser) GT 0) {
if (ArrayLen(Browser) GT 1) {
// If multiple browsers detected, delete the common "spoofed" browsers
if (Browser[1] EQ "MSIE 6.0" AND Browser[2] EQ "MSIE 7.0") ArrayDeleteAt(Browser,1);
if (Browser[1] EQ "MSIE 7.0" AND Browser[2] EQ "MSIE 6.0") ArrayDeleteAt(Browser,2);
tmp2=Browser[ArrayLen(Browser)];
for (x=ArrayLen(Browser); x GTE 1; x=x-1) {
tmp=Rematchnocase("[A-Za-z0-9.]*",Browser[x]);
if (ListFindNoCase("Navigator,Netscape,Opera,Safari,Firefox,MSIE,PalmOS,PPC",tmp[1]) GT 0) ArrayDeleteAt(Browser,x);
}
if (ArrayLen(Browser) EQ 0) Browser[1]=tmp2;
}
// Seperate out browser name and version number
tmp=Rematchnocase("[A-Za-z0-9. _\-&]*",Browser[1]);
Browser=tmp[1];
if (ArrayLen(tmp) EQ 2) BrowserVer=tmp[2];
// Handle "Version" in browser string
tmp=REMatchNoCase("Version/?#VerNo#",UserAgent);
if (ArrayLen(tmp) EQ 1) {
tmp=Rematchnocase("[A-Za-z0-9.]*",tmp[1]);
BrowserVer=tmp[2];
}
// Handle multiple BlackBerry browser strings
if (Left(Browser,10) EQ "BlackBerry") Browser="BlackBerry";
// Return result
return Browser & " " & BrowserVer;
}
// Unable to identify browser
return "Unknown";
}
</cfscript>
I created BrowscapCFC powered by http://browscap.org/. It may fit your needs
There's nothing built into ColdFusion that will allow you to do this. Capturing the user_agent string and parsing it manually is about the best you can do.
There are third party apps like Browserhawk (http://www.cyscape.com/Default.aspx) that will do this... and while I've not used Browserhawk myself, I understand that it does the job well.
Googling also turns up http://www.andrewdixon.co.uk/aebrowser/, but that is 6 years old. Might still work... but depending on how bulletproof you need the solution to be, you might want to consider something like Browserhawk. You could google for a list of user agent strings and handle it yourself... but given the sheer number of browsers (and versions) across OS's, I think that'd be a full time job in and of itself.
The user defined function above worked great, but I had to add the following code to get the version number to work correctly with IE (MSIE):
// Handle MSIE Version issue
IF (Left(Browser,4) EQ "MSIE") {
tmpBrowser = Browser;
IF (listLen("#tmpBrowser#", " ") EQ 2) {
Browser = listGetAt("#tmpBrowser#", 1, " ");
BrowserVer = listGetAt("#tmpBrowser#", 2, " ");
}
}
With a user_agent like this:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)
It was returning a blank version and a browser name of "MSIE 8.0"
Here is a recent build of the browser name and version
Tested on Opra / IE 8 / IE 9 / IE 10 / IE 11 / Edge / Chrome / Firefox
<cffunction name="GetBrowser" access="public">
<cfset var l = {}>
<cfset l.UserInfo = cgi.HTTP_USER_AGENT>
<cfset l.Browser = {}>
<cfif FindNoCase ( "Opera", l.UserInfo ) >
<cfset l.Browser.type = "Opera">
<cfset l.Browser.Name = "Opera">
<cfelseif FindNoCase ( "OPR", l.UserInfo )>
<cfset l.Browser.type = "OPR">
<cfset l.Browser.Name = "Opera">
<cfelseif FindNoCase ( "Edge", l.UserInfo )>
<cfset l.Browser.type = "Edge">
<cfset l.Browser.Name = "Edge">
<cfelseif FindNoCase ( "Chrome", l.UserInfo )>
<cfset l.Browser.type = "Chrome">
<cfset l.Browser.Name = "Chrome">
<cfelseif FindNoCase ( "Safari", l.UserInfo )>
<cfset l.Browser.type = "Safari">
<cfset l.Browser.Name = "Safari">
<cfelseif FindNoCase ( "FireFox", l.UserInfo )>
<cfset l.Browser.type = "FireFox">
<cfset l.Browser.Name = "FireFox">
<cfelseif FindNoCase ( "MSIE", l.UserInfo ) >
<cfset l.Browser.type = "MSIE">
<cfset l.Browser.Name = "Internet Explorer">
<cfelseif FindNoCase ( "Trident", l.UserInfo ) >
<cfset l.Browser.type = "Trident">
<cfset l.Browser.Name = "Internet Explorer">
<cfelse>
<cfset l.Browser.type = "Unknown">
<cfset l.Browser.Name = "Unknown">
<cfset l.Browser.Version = "Unknown">
</cfif>
<cfif FindNoCase ( "rv:" , l.UserInfo ) NEQ 0>
<cfset l.Params = REFindNoCase ( "rv:[0-9.]+", l.UserInfo, Find ( "rv:", l.UserInfo ), true )>
<cfset l.FirstOccurrence = l.Params.POS[1]>
<cfset l.ParamLength = l.Params.LEN[1]>
<cfset l.BrowserNameLength = Len ( "rv:" )>
<cfset l.Browser.Version = Mid ( l.UserInfo, ( l.FirstOccurrence + l.BrowserNameLength ), ( l.ParamLength - l.BrowserNameLength ) )>
<cfelse>
<cfset l.Params = REFindNoCase ( #l.Browser.type# & "/?[ 0-9.]+", l.UserInfo, Find ( "#l.Browser.type#", l.UserInfo ), true )>
<cfset l.FirstOccurrence = l.Params.POS[1]>
<cfset l.ParamLength = l.Params.LEN[1]>
<cfset l.BrowserNameLength = Len ( l.Browser.type ) + 1>
<cfset l.Browser.Version = Mid ( l.UserInfo, ( l.FirstOccurrence + l.BrowserNameLength ), ( l.ParamLength - l.BrowserNameLength ) )>
</cfif>
<cfreturn l.Browser>
</cffunction>
<cfdump var="#GetBrowser()#">
Here is refactored (from above) cfscript version for just browser name
function GetBrowserName() {
var rs = "Unknown";
var uag = cgi.HTTP_USER_AGENT;
if (FindNoCase("Opera",uag))
rs = "Opera";
else if (FindNoCase("OPR",uag))
rs = "Opera";
else if (FindNoCase("Edge",uag))
rs = "Edge";
else if (FindNoCase("Chrome",uag))
rs = "Chrome";
else if (FindNoCase("Safari",uag))
rs = "Safari";
else if (FindNoCase("Firefox",uag))
rs = "Firefox";
else if (FindNoCase("MSIE",uag))
rs = "IExplore";
else if (FindNoCase("Trident",uag))
rs = "IExplore";
else
rs = "Unknown";
return rs;
}
Related
i see this code in one of the pages, seems annoying, it can be shorted, if i am on Coldfusion 11
https://trycf.com/gist/701515844d5e41549a7b6e61dfafeaa0/lucee5?theme=monokai
Here is the code how its looks like
<cfloop list="#mqry.columnList#" index="col">
<cfset ColRow ="#mqry.columnList#," >
</cfloop>
<cfset x = replace(ColRow,"CONDITION1","CONDITION") & chr(13) & chr(10)>
<cfloop query="mqry">
<cfloop list="#mqry.columnList#" index="colN">
<cfset f = Replace("#mqry[colN][currentRow]#" ,"""","","All")>
<cfset f = REReplaceNoCase("#mqry[colN][currentRow]#" , "<[^>]*(?:>|$)", "", "ALL")>
<cfset x = x & """#_f#"",">
</cfloop>
<cfset x = x & chr(13) & chr(10)>
</cfloop>
the first value i think i can do as:
mquery.columnlist - no need to loop over
There's nothing wrong with the nested loop. You iterate over all rows and then iterate over each cell per row using the column name. I rewrote your code to be easier understandable:
<cfset NEWLINE = (chr(13) & chr(10))>
<cfset DELIM = ",">
<cfset QUOTE = '"'>
<!--- column headers --->
<cfset x = mqry.columnList>
<!--- replace column names as desired --->
<cfset x = replace(x, "CONDITION1", "CONDITION")>
<!--- next line --->
<cfset x &= NEWLINE>
<cfloop query="mqry">
<cfset row = []>
<cfloop list="#mqry.columnList#" index="colN">
<cfset cellValue = mqry[colN][mqry.currentRow]>
<!--- remove all quotes --->
<cfset cellValue = replace(cellValue, QUOTE, "", "ALL")>
<!--- remove tags --->
<cfset cellValue = reReplaceNoCase(cellValue, "<[^>]*(?:>|$)", "", "ALL")>
<!--- prefix with underscore --->
<cfset cellValue = ("_" & cellValue)>
<!--- wrap in quotes --->
<cfset cellValue = (QUOTE & cellValue & QUOTE)>
<cfset row.add(cellValue)>
</cfloop>
<!--- combine cell values into a row --->
<cfset x &= arrayToList(row, DELIM)>
<!--- next line --->
<cfset x &= NEWLINE>
</cfloop>
<cfoutput>#x#</cfoutput>
I'm trying to add the serialized data in a request to third party API which needs a specific order of the data to be maintained, but SerializeJSON orders in alphabetical order which breaks the format required by the third party API. Could someone help me to figure it out
INPUT:
<cfset data ={
"Booking": {
"ActionCode":"DI",
"AgencyNumber":"23",
"Touroperator":"TVR",
"BookingNumber":"323",
},
"Payment": {
"__type":"paymenttype",
"PaymentProfile": {
"Value": 4,
"Manual": false
},
"PaymentType": 4,
"PaymentAction":2,
"Details": {
"IBAN": "DE02120300000000202051",
"BIC": "BYLADEM1001"
}
},
"Login":{
"UserCode": "usercode",
"Password": "password"
}
}>
When this method SerializeJSON() is used on my data:
SerializeJSON(data)
Current Output
"{"Booking":{"Touroperator":"TVR","ActionCode":"DI","BookingNumber":"323","AgencyNumber":"23"},"Login":{"UserCode":"usercode","Password":"password"},"Payment":{"PaymentProfile":{"Manual":false,"Value":4},"PaymentType":4,"PaymentAction":2,"__type":"paymenttype","Details":{"BIC":"BYLADEM1001","IBAN":"DE02120300000000202051"}}}"
Expected Output:
"{"Booking":{"ActionCode":"DI","AgencyNumber":"23","Touroperator":"TVR","BookingNumber":"323",},"Payment":{"__type":"paymenttype","PaymentProfile":{"Value":4,"Manual":false},"PaymentType":4,"PaymentAction":2,"Details":{"IBAN":"DE02120300000000202051","BIC":"BYLADEM1001"}},"Login":{"UserCode":"usercode","Password":"password"}}"
Structs in ColdFusion are unordered HashMaps, so there is no order at all. You can keep insertion order by using structNew("Ordered") (introduced with ColdFusion 2016). Unfortunately you can no longer use the literal syntax anymore, but I assume you are generating the data dynamically anyway.
<cfset data = structNew("Ordered")>
<cfset data["Booking"] = structNew("Ordered")>
<cfset data["Booking"]["ActionCode"] = "DI">
<cfset data["Booking"]["AgencyNumber"] = "TVR">
<cfset data["Booking"]["BookingNumber"] = "323">
<cfset data["Payment"] = structNew("Ordered")>
<cfset data["Payment"]["__type"] = "paymenttype">
<cfset data["Payment"]["PaymentProfile"] = structNew("Ordered")>
<cfset data["Payment"]["PaymentProfile"]["Value"] = 4>
<cfset data["Payment"]["PaymentProfile"]["Manual"] = false>
etc.
If you are stuck on an older ColdFusion version, you will have to use Java's LinkedHashMap.
<cfset data = createObject("java", "java.util.LinkedHashMap")>
<cfset data["Booking"] = createObject("java", "java.util.LinkedHashMap")>
<cfset data["Booking"]["ActionCode"] = "DI">
<cfset data["Booking"]["AgencyNumber"] = "TVR">
<cfset data["Booking"]["BookingNumber"] = "323">
<cfset data["Payment"] = createObject("java", "java.util.LinkedHashMap")>
<cfset data["Payment"]["__type"] = "paymenttype">
<cfset data["Payment"]["PaymentProfile"] = createObject("java", "java.util.LinkedHashMap")>
<cfset data["Payment"]["PaymentProfile"]["Value"] = 4>
<cfset data["Payment"]["PaymentProfile"]["Manual"] = false>
etc.
But be aware: LinkedHashMap is case-sensitive (and also type-sensitive: in case your keys are numbers, it does matter!).
<cfset data = createObject("java", "java.util.LinkedHashMap")>
<cfset data["Test"] = "">
<!---
accessing data["Test"] = works
accessing data["test"] = doesn't work
accessing data.Test = doesn't work
--->
Another issue you might encounter: Due to ColdFusion's internal type casting, serializeJSON() might stringify numbers and booleans in an unintended way. Something like:
<cfset data = structNew("Ordered")>
<cfset data["myBoolean"] = true>
<cfset data["myInteger"] = 123>
could easily end up like:
{
"myBoolean": "YES",
"myInteger": 123.0
}
(Note: The above literal syntax would work perefectly fine, but if you are passing the values around as variables/arguments, casting eventually happens.)
The easiest workaround is explicitly casting the value before serializing:
<cfset data = structNew("Ordered")>
<cfset data["myBoolean"] = javaCast("boolean", true)>
<cfset data["myInteger"] = javaCast("int", 123)>
I'm building a new application using Coldfusion as the business logic layer or controller in an MVC pattern and wanting to setup a binary search algorithm to handle username lookup on a registration function. Are there any documented instances of implementing a binary search algorithm in Coldfusion/sql?
Code Below. Note this is far from perfect.
Just a rough attempt at trying to translate the syntax into CFML
<cffunction name="binarySearchFunc" access="public" returntype="boolean">
<!--- Define array collection variable and target --->
<cfargument name="collection" type="array">
<cfargument name="target">
<!--- If the target is empty, return false --->
<cfif not isDefined(#argument.target#) or is Null>
<cfset returnValue = "false">
<cfreturn returnValue >
<!--- Else set the high, mid and low params for binary search --->
<cfelse>
<cfparam name="low" type="integer" default="0">
<cfparam name="high" type="integer" default="#ArrayLen(collection)#-1" >
<cfparam name="ix" type="integer" default="">
<cfscript>
While( low LTE high){
<!--- set the mid variable equal to the mean value between the low and
high --->
ix = (#low# + #high#)/2
<!--- set a variable equal to compareTo method of the target below --->
intVar = #target#.compareTo(collection[xi] <!--- equivalent CF syntax
??? --->
if (intVar LTE 0 ) {
//target value less than collection[i]
high = ix - 1;
}
else if (intVar GT 0 ){
low = ix ++ 1 ; }
else {
var returnValue = "true";
return returnValue;
}
}
</cfscript>
</cfif>
</cffunction>
I have been tasked with shortening a sequence of numbers by replacing internal sequences of 3 or more with a dash for the internal numbers (as in, 3,5,6,7,8,10 would be 3,5-8,10)
Pretty similar to the above, just using lists.
<cfscript>
a = listToArray('3,5,6,7,8,10,11,15,16,17,18');
writeOutput( fNumSeries(a) );
string function fNumSeries( array a) output="false" {
var tempList = '';
var outputList = '';
for ( var i in a ) {
if( listLen(tempList) == 0 ) {
// Nothing in the list
tempList = i;
} else if ( listLen(tempList) ) {
if ( listLast(tempList)+1 == i) {
// i is next in order from the previous list item. Just add to temp list.
tempList = listAppend(tempList, i);
} else if (listLen(tempList) >= 3) {
// current item is not the next item, and the tempList is more than 2 items long, so abbreviate and set templist to the current item.
outputList = listAppend(outputList, listFirst(tempList) & '-' & listLast(tempList));
tempList = i;
} else {
// tempList is less than 3 items long, just append to output and set tempList to the current item.
outputList = listAppend(outputList, tempList);
tempList = i;
}
}
}
// Clean up the remaining item(s) in tempList. If 3 or more, abbreviate, else just append to output.
outputList = listLen(tempList) >= 3 ? listAppend(outputList, listFirst(tempList) & '-' & listLast(tempList)) : listAppend(outputList, templist);
return outputList;
}
</cfscript>
I put the following function together, plus some demo output. It assumes the numbers are in an ordered, non-repeating array. (CF list functions help get to this point.) Is there a more elegant way of doing this?
<cffunction name="fNumSeries" output="1" hint="parses array of numbers for display: 1|2|3|6|7|9|10|11|12 would be 1-3, 6, 7, 9-12 ">
<cfargument name="raNums" required="1" type="array">
<cfset raLen=arraylen(raNums)>
<cfif raLen eq 0><CFRETURN "">
<cfelseif raLen eq 1><CFRETURN raNums[1]>
<cfelseif raLen eq 2><CFRETURN raNums[1] & "," & raNums[2]>
</cfif>
<cfset numSeries="">
<cfset numHold=raNums[1]>
<cfset seqHold=raNums[1]>
<cfset numSeries=raNums[1]><!--- raNums[1]always output the first number --->
<cfloop from="1" to="#raLen#" index="idxItem">
<cfif idxItem gt 1><!--- wait for 2nd element to decide output --->
<cfif numHold+1 neq raNums[idxItem]><!--- reason to output and seqHold+1 neq numHold--->
<cfif seqHold eq numHold>
<cfset numSeries=numSeries & ",#raNums[idxItem]#">
<cfelse>
<cfif seqHold+1 eq numHold><cfset numSeries=numSeries & ","><!--- and numHold+1 neq raNums[1] and seqHold+1 eq numHold --->
<cfelse><cfset numSeries=numSeries & "-">
</cfif>
<cfset numSeries=numSeries & "#numHold#,#raNums[idxItem]#">
</cfif>
<cfset seqHold=raNums[idxItem]>
</cfif>
</cfif>
<cfset numHold=raNums[idxItem]>
</cfloop>
<cfif seqHold neq numHold><!--- display the last element --->
<cfif seqHold+1 eq numHold or raLen eq 2><cfset numSeries=numSeries & ",">
<cfelse><cfset numSeries=numSeries & "-">
</cfif>
<cfset numSeries=numSeries & "#numHold#">
</cfif>
<CFRETURN numSeries>
</cffunction>
<cfset raRa=[
[2,12],
[2,3,12],
[2,4,12],
[2,3,4,12],
[2,8,9,11,12],
[2,9,11,12],
[2,3,8,10,11,12]
]>
<cfoutput>
<cfloop array="#raRa#" index="ra">
#arrayToList(ra)#<br />
#fNumSeries(ra)#<hr>
</cfloop>
</cfoutput>
I would like to handle a row from a query by a function, where I pass the row as a structure.
ideally...
<cfloop query="myquery">
#myfunction(#row#)#
</cfloop>
I could set it up like this too...
<cfloop query="myquery">
#myfunction(#col1#,#col2#,#col3#,#col4#)#
</cfloop>
but I don't want to. I haven't been able to finda simple way of extracting a row, But I thought I'd ask.
found a little more elegant looking solution, for single row
<cfscript>
function GetQueryRow(query, rowNumber) {
var i = 0;
var rowData = StructNew();
var cols = ListToArray(query.columnList);
for (i = 1; i lte ArrayLen(cols); i = i + 1) {
rowData[cols[i]] = query[cols[i]][rowNumber];
}
return rowData;
}
</cfscript>
Adobe ColdFusion 11 introduced QueryGetRow which converts a row from a query into a struct.
Ben Nadel has posted a blog post about this where he gives an example UDF that converts a query to a struct, and it accepts an optional row argument that allows you to turn an single row in that query to a struct. Take a look here.
This is the Class from Ben's site without the comments
<--- --------------------------------------------------------------------------------------- ----
Blog Entry:
Ask Ben: Converting A Query To A Struct
Author:
Ben Nadel / Kinky Solutions
Link:
http://www.bennadel.com/index.cfm?event=blog.view&id=149
Date Posted:
Jul 19, 2006 at 7:32 AM
---- --------------------------------------------------------------------------------------- --->
<cffunction name="QueryToStruct" access="public" returntype="any" output="false"
hint="Converts an entire query or the given record to a struct. This might return a structure (single record) or an array of structures.">
<cfargument name="Query" type="query" required="true" />
<cfargument name="Row" type="numeric" required="false" default="0" />
<cfscript>
var LOCAL = StructNew();
if (ARGUMENTS.Row){
LOCAL.FromIndex = ARGUMENTS.Row;
LOCAL.ToIndex = ARGUMENTS.Row;
} else {
LOCAL.FromIndex = 1;
LOCAL.ToIndex = ARGUMENTS.Query.RecordCount;
}
LOCAL.Columns = ListToArray( ARGUMENTS.Query.ColumnList );
LOCAL.ColumnCount = ArrayLen( LOCAL.Columns );
LOCAL.DataArray = ArrayNew( 1 );
for (LOCAL.RowIndex = LOCAL.FromIndex ; LOCAL.RowIndex LTE LOCAL.ToIndex ; LOCAL.RowIndex = (LOCAL.RowIndex + 1)){
ArrayAppend( LOCAL.DataArray, StructNew() );
LOCAL.DataArrayIndex = ArrayLen( LOCAL.DataArray );
for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE LOCAL.ColumnCount ; LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){
LOCAL.ColumnName = LOCAL.Columns[ LOCAL.ColumnIndex ];
LOCAL.DataArray[ LOCAL.DataArrayIndex ][ LOCAL.ColumnName ] = ARGUMENTS.Query[ LOCAL.ColumnName ][ LOCAL.RowIndex ];
}
}
if (ARGUMENTS.Row){
return( LOCAL.DataArray[ 1 ] );
} else {
return( LOCAL.DataArray );
}
</cfscript>
</cffunction>
usage...
<!--- Convert the entire query to an array of structures. --->
<cfset arrGirls = QueryToStruct( qGirls ) />
<!--- Convert the second record to a structure. --->
<cfset objGirl = QueryToStruct( qGirls, 2 ) />
Another solution would be:
function QueryToStruct(query){
var cols = ListToArray(query.columnList);
var salida = query.map(function(v=0,i,a){
return {'#cols[1]#':v};
});
return ValueArray(salida,'#cols[1]#');
}