Ok, this func doesn't make sense, but I'm just using it as an example:
<cffunction name="blah">
<cfset var myFoo = 123>
<cfset var varNamePrefix = "my">
<cfset var bar = Evaluate("#varNamePrefix#Foo")>
<cfreturn bar>
</cffunction>
With CF9, I can use local["#varNamePrefix#Foo"]. Is there a way for CF7/8 to get rid of the Evaluate() without refactoring the whole thing with var local = structNew()?
Not by documented means. Pre-CF9 there is only getPageContext().getActiveFunctionLocalScope()
<cffunction name="blah">
<cfset var myFoo = 123>
<cfset var varNamePrefix = "my">
<!--- ie object.method()[keyName] syntax does not seem to be supported --->
<cfset var localScope = getPageContext().getActiveFunctionLocalScope()>
<cfset var bar = localScope["#varNamePrefix#Foo"]>
<cfreturn bar>
</cffunction>
Related
There's a method in one of my components componentValitation.cfc:
<cffunction name="getValidationTypeRegExpByID" access="public"
returntype="string" output="false">
<cfargument name="componentValidationTypeID" type="numeric" required="true">
<cfscript>
if (structKeyExists(variables.componentValidationTypes, arguments.componentValidationTypeID))
{
return variables.componentValidationTypes[arguments.componentValidationTypeID].RegExp;
}
return '';
</cfscript>
</cffunction>
I want to call the above mentioned method from another component. I tried calling it from common.cfc like this
var advertisement = getComponentValidation('component','sys.jo.core.fe.componentValidation');
<cfset testttt = advertisement.getValidationTypeRegExpByID(componentValidationTypeID) />
<cfset errorMessage = "#componentShortLabel# #Lib.showCaption('message_Decimal2dpValidation', UserIdentity)#" />
<cfset arguments.Message.addValidationError( keyName=QuestionID, errorMessage=errorMessage, componentKey=ComponentID, componentErrorMessage=errorMessage, tupleIndex=arguments.tupleIndex, QuestionDisplayNumber=errorDisplaySequenceNumber ) />
But I'm getting an error like Elementcomponent is not defined in variable in componentValidation.cfc (which was already defined in my init() function). Any ideas?
This is probably a mistake:
var advertisement = getComponentValidation('component','sys.jo.core.fe.componentValidation');
Shouldn't it be:
var advertisement = createobject('component','sys.jo.core.fe.componentValidation');
I am trying to create the client to client chat application by using cfwebsocket. I referenced the adobe example. In that example we pass an extra argument on to the publish function. So I passed the receiver id to the publish function, but cannot get that value in the msgHandler function.
<cfoutput>
<cfif !structkeyexists(session,'userName')>
<cflocation url="index.cfm?msg=Please login first" addtoken="false">
</cfif>
<cfdump var="i am chat.cfm" />
Logout
<cfwebsocket name="myworld" onMessage="msgHandler" onOpen="openHandler"/>
<script>
var msgHandler = function(message){
// Get data from the recieved message token
var data = message.data;
console.log(message.data.to);
if(data){
// If data is present write it to the div
var txt=document.getElementById("myDiv");
txt.innerHTML+= data + "<br>";
}
}
var sayHello = function(){
uname = document.getElementById("username").value;
receiver = document.getElementById("selectUser").value;
//var myData = {publishedBy: ''+uname, receiver:''+receiver}
// Calling authenticate from client side. Calling this
//function will invoke onWSAuthenticate from Application.cfc
myworld.authenticate(uname,"password");
myworld.subscribe("chat");
// Client says Hello World
myworld.publish("chat","Hello World! WebSocket is here !!",{to:receiver});
}
var openHandler = function(){
// do nothing
}
</script>
<input type="hidden" name="userName" id="username" value="#session.userName#">
<input id="hello" type="button" value="Say Hello!" onclick="sayHello();">
<div id="myDiv"></div>
<cfset users = Application.usersDAO.read()>
<select name="user" id="selectUser">
<option value="0">Select User</option>
<cfloop query="users">
<option value="#id#">#username#</option>
</cfloop>
</select>
</cfoutput>
You should pass your message and extra argument like a json object.
var sayHello = function()
{
uname = document.getElementById("username").value;
userID = document.getElementById("userID").value;
receiverID = document.getElementById("ToUser").value;
receiverName = document.getElementById("ToUserName").value;
// Calling authenticate from client side. Calling this function will invoke onWSAuthenticate from Application.cfc
myworld.authenticate(uname,"password");
// Client says Hello World
// console.log($('#input').val())
msg = {'username': uname, 'userID' : userID, 'chat': $('#input').val().trim(), 'to':receiverID, 'receiverName' : receiverName };
myworld.publish("world",msg);
$('#input').val('');
}
In msgHandler function you will get message.data.to and message.data.userId. You will store the userId on session scope inside the msgHandler you will compare the session userID and message.data.to. If both are same you will appeand your message on your chat window.
I am trying to resolve an issue on CFWheels, where I am have trouble extending my parent Application.cfc which also extends another Application.cfc. In order to understand the problem better and really single out what's going wrong, I have created a directory structure as follows:
/mainapp/index.cfm
-------------------------------------------------
<cfoutput>
<cfdump var="#session#">
</cfoutput>
/mainapp/Application.cfc
-------------------------------------------------
<cfscript>
component
{
this.name = "Main App";
this.applicationTimeout = createTimeSpan(0, 1, 0, 0);
this.sessionManagement = true;
this.sessionTimeout = createTimeSpan(0, 0, 30, 0);
public function intMainApp(name, value){
session[name] = value;
}
public boolean function OnApplicationStart(){
//Handle OnApplicationStart Callback
return true;
}
public void function OnApplicationEnd(struct ApplicationScope=structNew()){
//Handle OnApplicationEnd Callback
}
public void function OnRequest(required string TargetPage){
//Handle OnRequest Callback
}
public boolean function OnRequestStart(required string TargetPage){
//Handle OnRequestStart Callback
include arguments.TargetPage;
intMainApp("mainappv1", "something session");
return true;
}
public void function OnSessionStart(){
//Handle OnSessionStart Callback
}
public void function OnSessionEnd(required struct SessionScope, struct ApplicationScope=structNew()){
//Handle OnSessionEnd Callback
}
}
</cfscript>
/mainapp/submainapp/index.cfm
-------------------------------------------------
<cfoutput>
<cfdump var="#session#">
</cfoutput>
/mainapp/submainapp/Application.cfc
-------------------------------------------------
<cfscript>
component extends="mainapp.Application"
{
this.name = "Main App";
this.applicationTimeout = createTimeSpan(0, 1, 0, 0);
this.sessionManagement = true;
this.sessionTimeout = createTimeSpan(0, 0, 30, 0);
public function intSubMainApp(name, value){
session[name] = value;
}
public boolean function OnApplicationStart(){
//Handle OnApplicationStart Callback
return true;
}
public void function OnApplicationEnd(struct ApplicationScope=structNew()){
//Handle OnApplicationEnd Callback
}
public void function OnRequest(required string TargetPage){
//Handle OnRequest Callback
}
public boolean function OnRequestStart(required string TargetPage){
//Handle OnRequestStart Callback
include arguments.TargetPage;
intSubMainApp("submainapp2", "var var 2");
intMainApp("v3", "var 3");
return true;
}
public void function OnSessionStart(){
//Handle OnSessionStart Callback
}
public void function OnSessionEnd(required struct SessionScope, struct ApplicationScope=structNew()){
//Handle OnSessionEnd Callback
}
}
</cfscript>
/mainapp/submainapp/childapp/index.cfm
-------------------------------------------------
<cfoutput>
<p>Testing Child App</p>
</cfoutput>
/mainapp/submainapp/childapp/Application.cfc
-------------------------------------------------
<cfcomponent output="false">
<cfinclude template="../Application.cfc">
</cfcomponent>
If I execute the childapp/index.cfm I get the error.
Variable INTMAINAPP is undefined.
This problem is similar to the issue that I facing with cfwheels when trying to extend my parent Application.cfc. Why is it that InitMainApp method not being included in submainapp/Application.cfc when it used via cfinclude tag and Is there a workaround or fix for this problem.
Just as a clarification, childapp/Application.cfc is trying to include submainapp/Application.cfc
Moreover there is a issue created on this in the cfwheels community forums.
https://groups.google.com/forum/#!topic/cfwheels/1eMGLGSrbBY
This exact function does not work on Node Js, even though it work fine on a regular browser. How can I make it work on NodeJS?
Example: http://jsfiddle.net/wC53N/
var MyHereDoc = function() {
var bodyEmail = function(){
var test = 1;
/*HEREDOC
<div>
Hola1
<p>
hola2
</p>
</div>
HEREDOC*/
};
var here = "HEREDOC";
var reobj = new RegExp("/\\*"+here+"\\n[\\s\\S]*?\\n"+here+"\\*/", "m");
str = reobj.exec(bodyEmail).toString();
str = str.replace(new RegExp("/\\*"+here+"\\n",'m'),'').toString();
toPrint = str.replace(new RegExp("\\n"+here+"\\*/",'m'),'').toString();
document.getElementById("demo").innerHTML = toPrint;
}
MyHereDoc();
If you try to run this same code on NodeJS u will get this error:
Cannot call method 'toString' of null
But Why? any idea how to make it works, or what am I doing wrong?
Thanks
I get this error when posting a form. The strangest thing, though, is that this error only occurs in Chrome and Safari. FF, IE and Opera all post the form without a problem.
The Stack Trace does not point to a file to where this error occurs. A cfdump of cfcatch gives me some insight as to what the problem is, but I can't find any instance of where the problem actually exists. Here's the partial dump:
Column 1
Detail The variable attributes. ends with a "." character. You must supply an additional structure key or delete the "." character.
KnownColumn -1
KnownLine -1
KnownText "unknown"
Line 1
Message A CFML variable name cannot end with a "." character.
Here's the code handling the posted data. Everything is wrapped inside cftransaction and there's a loop, not sure why it's not being displayed. (thanks Peter Boughton for clearing that up)
<!--- Delete out the old category ties --->
<cfquery name="deleteCategory" datasource="#request.dsnWrite#">
DELETE FROM
ProductListings_categories
WHERE
listingID = <cfqueryparam value="#attributes.listingID#">
</cfquery>
<!--- Loop through the list --->
<cfloop list="#attributes.taginput#" index="idx" delimiters=".">
<!--- check to see if tag exists --->
<cfquery name="checkTag" datasource="#request.dsnWrite#">
SELECT
categoryID
FROM
categories
WHERE
CategoryName = <cfqueryparam value="#idx#" cfsqltype="cf_sql_varchar">
</cfquery>
<!--- If it does not then add the tag --->
<cfif not(checkTag.recordCount)>
<cfquery name="insertTag" datasource="#request.dsnWrite#">
INSERT into Categories
(
categoryname,
dateCreated
)
VALUES
(
<cfqueryparam value="#idx#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">
)
</cfquery>
<cfquery name="insertTag" datasource="#request.dsnWrite#">
SELECT
LAST_INSERT_ID() as newID
FROM
Categories
</cfquery>
<cfset variables.categoryID = insertTag.newID>
<cfelse>
<cfset variables.categoryID = checkTag.categoryID>
</cfif>
<cftry>
<!--- Tie the tag to the listing --->
<cfquery name="insertCategory" datasource="#request.dsnWrite#">
INSERT into ProductListings_categories
(
listingID,
CategoryID
)
VALUES
(
<cfqueryparam value="#attributes.listingID#" cfsqltype="cf_sql_bigint">,
<cfqueryparam value="#variables.categoryID#" cfsqltype="cf_sql_bigint">
)
</cfquery>
<cfcatch></cfcatch>
</cftry>
</cfloop>
<cflocation url="/sell/add_listing/step/3/listingID/#attributes.listingID#" addtoken="false">
Any insight would be great. Thanks!
Here's the form and the Javascript. I haven't had a chance to rewrite the code by the previous developer (up until this point, it was working, so there was no need to visit the code in the first place), but CFFORM isn't used, nor are other CF form items. Various JS functions are used for AJAX calls and are included as well.
<form action="/sell/add_listing/step/2/listingID/#attributes.listingId#" method="post">
<div id="formFields"><input name="tagInput" id="tagInput" value="#variables.tagInput#" type="hidden"/></div>
<h3>Step 2: <span id="instructions">First, choose a top-level category</span></h3>
<p id="instructions2">This category will show up as the first tag on your listing.</p>
<div id="tagLand">
<div>
1. <select onchange="mainCategorySelector(this.value)">
<cfloop query="getTopCats">
<option value="#getTopCats.categoryName#" <cfif ListFirst(variables.tagInput,".") EQ getTopCats.categoryName>selected="selected"</cfif>>#capFirstTitle(ReplaceNoCase(getTopCats.categoryName, "_"," ", "all"))#</option>
</cfloop>
</select>
</div>
<div id="inputDiv" style="visibility: hidden;">
<div>Add a tag</div>
<div>2.
<input type="text" onkeypress="return disableEnterKey(event)" name="newTag" id="newTag" maxlength="18"/>
<input type="button" value="add" onclick="addTag(document.getElementById('newTag').value)" class="small_button" />
</div>
<div class="error"></div>
</div>
</div>
<img src="/resources/img/layoutV3/button_prev.gif" alt="prev"/>
<input type="image" name="btnSubmit" src="/resources/img/layoutV3/button_next.gif" />
</form>
<script src="/resources/js/listing_2.js" type="text/javascript"></script>
//some variables
var listCount=1;
var tagLimit=14;
var maxSuggestions=100;
var allTags=new Array();
var allTags=new Array();
var allTagPointers=new Array();
var currentTags=0;
// XML document
var xmlDoc;
var req;
//this function will run anything upon page load
function addLoadEvent(func)
{
var oldonload = window.onload;
if (typeof window.onload != 'function')
{
if(func)window.onload = func;
}
else
{
window.onload = function()
{
oldonload();
func();
}
}
}
//let's rebuild the page!
addLoadEvent(rebuildTags());
function rebuildTags()
{
//grab the tag tree left for us by PHP
var passedTags=document.getElementById('tagInput').value;
//only run if we got a value
if(passedTags.replace(/^\s+|\s+$/g, ""))
{
//split the string into an array
passedTags=passedTags.split(".");
//run functions to rebuild the world
mainCategorySelector(passedTags[0]);
for(var i=1;i<passedTags.length;i++)
{
addTag(passedTags[i]);
}
}
}
function addTag(tagName)
{
tagName=trim(tagName);
tagName=tagName.toLowerCase();
if(tagName)
{
//remove underscores from tags, replace with spaces so we can validate
tagName=tagName.replace(/_/g," ");
//clear out error message if it's there
var errorDiv=document.getElementById('errorDiv');
errorDiv.innerHTML="";
//only run if we're not at the limit and tag has not been used already
if(currentTags<=tagLimit && !getArrayIndex(allTags,tagName))
{
//if not alphanumeric, error
var myRegxp = /^[0-9a-zA-Z\s]*$/;
if(myRegxp.test(tagName)==false)
{
var errorDiv=document.getElementById('errorDiv');
errorDiv.innerHTML="You may only use letters and numbers in your tags.";
}
//if it error checks fine, move on
else
{
//let's replace all spaces with underscores for DB storage
//tagName=tagName.replace(/ /g,"_");
//query server and get list of related tags
//random number to kill the cache
var cacheKiller=Math.random();
//get all children tags
xmlDoc=ajaxRequest("/sell/get_categories_xml/tag/"+tagName.replace(/ /g,"_")+"/random/"+cacheKiller);
relatedTags=new Array;
var root=xmlDoc.getElementsByTagName('root')[0];
var tags=root.getElementsByTagName('tag');
//now get all sibling tags
xmlDoc=ajaxRequest("/sell/get_categories_siblings_xml/tag/"+tagName.replace(/ /g,"_")+"/random/"+cacheKiller);
root=xmlDoc.getElementsByTagName('root')[0];
var siblingTags=root.getElementsByTagName('tag');
//first compile child tags into an array
for(var i=0;(i<tags.length && i<maxSuggestions);i++)
{
relatedTags[i]=tags[i].firstChild.nodeValue;
}
//now add sibling tags to the same array
tags=root.getElementsByTagName('tag');
for(i;(i<tags.length && i<maxSuggestions);i++)
{
relatedTags[i]=tags[i].firstChild.nodeValue;
}
var tagLand=document.getElementById('tagLand');
var newNumberDiv=document.createElement('div');
var newDiv=document.createElement('div');
//add to counter and master tag array
listCount++;
allTags[allTags.length]=tagName.replace(/ /g,"_");
allTagPointers[allTagPointers.length]=listCount;
updateForm();
newNumberDiv.setAttribute('id','number_'+listCount);
newNumberDiv.className='listing_number';
newNumberDiv.innerHTML=listCount+".";
newDiv.innerHTML=tagName+' <span onclick="removeTag(\''+listCount+'\');" class="list_dynamic_link">x</span>';
newDiv.className='list_tag';
var newReccomendDiv=makeRelatedDiv(relatedTags);
//let's give IDs to all of the new divs so we can't kill 'em later
newDiv.setAttribute('id','tagDiv'+listCount);
newReccomendDiv.setAttribute('id','reccomendDiv'+listCount);
//add new divs to the master list
tagLand.appendChild(newNumberDiv);
tagLand.appendChild(newDiv);
tagLand.appendChild(newReccomendDiv);
//remove and re-append the input div to keep it at the end
var inputDiv=document.getElementById('inputDiv');
tagLand.removeChild(inputDiv);
tagLand.appendChild(inputDiv);
//make the inputDiv visible if it is not already
inputDiv.style.visibility='visible';
//run the reorderizer
reorderizer();
//clear input field
document.getElementById('newTag').value="";
document.getElementById('newTag').focus();
}
}
}
}
//removes a tag from the list -- called through the "x" link on each tag
function removeTag(tagNumber)
{
//get master div
var tagLand=document.getElementById('tagLand');
//get reference to all three divs that make up a tag listing
var deathRowNumberDiv=document.getElementById('number_'+tagNumber);
var deathRowTagDiv=document.getElementById('tagDiv'+tagNumber);
var deathRowReccomendDiv=document.getElementById('reccomendDiv'+tagNumber);
//any last words, boys?
tagLand.removeChild(deathRowNumberDiv);
tagLand.removeChild(deathRowTagDiv);
tagLand.removeChild(deathRowReccomendDiv);
//find where we are in the master array
var tagIndex=getArrayIndex(allTagPointers,tagNumber);
//splice this tag out of master tag array
allTags.splice(tagIndex,1);
allTagPointers.splice(tagIndex,1);
updateForm();
//alert(allTags.join("."));
//since we just changed the page structure, let's run reorderizer
//run the reorderizer
reorderizer();
//make the inputDiv visible if we're below the tag limit
var inputDiv=document.getElementById('inputDiv');
if(currentTags<=tagLimit)
{
inputDiv.style.visibility='visible';
}
}
//this function displays the formatted div for related tags
function makeRelatedDiv(relatedTags)
{
//let's prepare the recommended tags div
var newReccomendDiv=document.createElement('div');
newReccomendDiv.className='list_suggested_tags';
newReccomendDiv.innerHTML='<span>Add related tags: </span> ';
var numTags=0;
//loop through suggested tag array
for ( keyVar in relatedTags )
{
//add comma if necessary
if(numTags)
{
newReccomendDiv.innerHTML+=", ";
}
newReccomendDiv.innerHTML+='<span onclick="addTag(\''+relatedTags[keyVar]+'\');" class="list_dynamic_link">'+relatedTags[keyVar]+'</span>';
numTags++;
}
return newReccomendDiv;
}
function mainCategorySelector(tag)
{
//only run if we're not the dead selection
if(tag!="- - -")
{
//query server and get list of related tags
//random number to kill the cache
var cacheKiller=Math.random();
xmlDoc=ajaxRequest("/sell/get_categories_xml/tag/"+tag+"/random/"+cacheKiller);
relatedTags=new Array;
var root=xmlDoc.getElementsByTagName('root')[0];
var tags=root.getElementsByTagName('tag');
for(var i=0;(i<tags.length && i<maxSuggestions);i++)
{
relatedTags[i]=tags[i].firstChild.nodeValue;
}
var tagLand=document.getElementById('tagLand');
var newReccomendDiv=makeRelatedDiv(relatedTags);
//replace old reccomend list if it exists
if(document.getElementById('mainCategoryReccomendations'))
{
var mainCategoryReccomendations=document.getElementById('mainCategoryReccomendations');
tagLand.appendChild(newReccomendDiv);
tagLand.insertBefore(newReccomendDiv , mainCategoryReccomendations);
tagLand.removeChild(mainCategoryReccomendations);
}
else
{
tagLand.appendChild(newReccomendDiv);
//add to counter if we added a new tag
listCount++;
}
newReccomendDiv.setAttribute('id' , 'mainCategoryReccomendations');
//alert(allTags.join("."));
//add master tag array
allTags[0]=tag;
allTagPointers[0]=1;
updateForm()
//alert(allTags.join("."));
//remove and re-append the input div to keep it at the end
var inputDiv=document.getElementById('inputDiv');
tagLand.removeChild(inputDiv);
tagLand.appendChild(inputDiv);
//make the inputDiv visible if we're below the tag limit
if(currentTags<=tagLimit)
{
inputDiv.style.visibility='visible';
//focus on the new field
document.getElementById('newTag').focus();
}
//change up the instructions
changeInstructions("Now, add other tags to sort your listing","You can either click the related tags or enter your own")
}
}
//this function changes the content of the instructional div
function changeInstructions(top, bottom)
{
var instructions=document.getElementById('instructions');
var instructions2=document.getElementById('instructions2');
instructions.innerHTML=top;
instructions2.innerHTML=bottom;
}
//this function reassigns all list numbers to their proper value
function reorderizer()
{
/*
Here we run through all number div IDs...
remember, the div ID number may not match the display number, due to
additions/removals. That's why we have a separate variable for displayNumber!
*/
var tagLand=document.getElementById('tagLand');
//another counting var, for the actual display number
var displayNumber=1;
for(var i=1; i <= listCount; i++)
{
if(document.getElementById('number_'+i))
{
var b=document.getElementById('number_'+i);
b.innerHTML=displayNumber+".";
//ony increment displayNumber if we've actually printed a number
displayNumber++;
}
}
//update global tag count to most current and accurate number
currentTags=displayNumber;
//have we hit the tag limit? If so, hidezorz input
if(displayNumber>tagLimit)
{
var inputDiv=document.getElementById('inputDiv');
inputDiv.style.visibility='hidden';
}
else
{
//after looping through dynamic list entries, let's change the submit field's number too
var number_last=document.getElementById('number_last');
if(number_last)
{
number_last.innerHTML=displayNumber+".";
}
}
}
function pausecomp(millis)
{
date = new Date();
var curDate = null;
do { var curDate = new Date(); }
while(curDate-date < millis);
}
function ajaxRequest(requestURL)
{
var req;
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
req.open("GET", requestURL, false);
req.send(null);
var xmlDocument = req.responseXML;
return(xmlDocument);
}
function disableEnterKey(e)
{
var key;
if(window.event)
key = window.event.keyCode; //IE
else
key = e.which; //firefox
if(key == 13)
{
addTag(document.getElementById('newTag').value);
return false;
}
else
{
return true;
}
}
function getArrayIndex(arr, val)
{
for (i = 0; i < arr.length; i++)
{
if (arr[i] == val) { return i; }
}
}
function updateForm()
{
//this function updates the hidden field that will actually send the tag data upon form submission
document.getElementById('tagInput').value=allTags.join(".");
}
Problem solved: select list did not have the name attribute defined, and as a result, the attributes variable did have a null field name, causing the error. In my case, the select list is not used in CF, but only in JS. Chrome and Safari will pass a field's value even if the field lacks a name, while IE, FF and Opera do not. Thanks for guiding me in the right direction.
From your description it sounds like that the error is thrown by the form itself in the client, and not the handling code that you've posted above. If you have a cfform/cfgrid on the calling page, you may want to look at the Javascript that's generated by CF and test it against Chrome/Safari.