CF Component Doesn't Reset Variables - coldfusion

I have some forms and there is a table with "instructions" for each question, for each form. I am trying to add a button which pops a modal displaying each question's instruction. The problem is every button links to the instruction for the first question. The later instructions exist - If I start w/question 2, everything after that shows Q2's instruction. It's as if it gets locked onto the first field and can't discard it.
Here is the component code:
<cfcomponent displayname="QxQ" output="false" hint="Gets QxQ information for display on data entry screen">
<cfparam name="qxq_instruct" default="">
<cfparam name="qxq_fieldGUID" default="">
<cffunction name="getFieldInstructions" hint="Gets the QxQ Instructions for the requesting field">
<cfargument name="qxq_versionGUID" type="string" required="yes">
<cfargument name="qxq_fieldName" type="string" required="yes">
<!--- Get FieldGUID based on form VersionGUID and field name --->
<cfquery name="qryGetqxqfieldGUID" datasource="#application.DSN#">
SELECT
FieldGUID
FROM
_sysformFields
WHERE
VersionGUID = <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#qxq_versionGUID#">
AND
FieldName = <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#qxq_fieldName#">
</cfquery>
<cfset qxq_fieldGUID = #qryGetqxqfieldGUID.FieldGUID#>
<!--- Get instructions based on fieldGUID --->
<cfquery name="qryGetFieldInstructions" datasource="#application.DSN#">
SELECT
instruct
FROM
_sysFormFieldInstructions
WHERE
fieldGUID = <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#qxq_fieldGUID#">
</cfquery>
<cfif qryGetFieldInstructions.recordcount eq 1>
<cfset qxq_instruct = #qryGetFieldInstructions.instruct#>
</cfif>
<cfset modalButton = '
<!--- Modal Button --->
<button type="button" class="btn btn-small" style="background-color: transparent; border: none" data-toggle="modal" data-target="##exampleModal">
<i class="fa fa-question-circle-o fa-2x" style="color: ##8a0d25"></i>
</button>
<!--- Modal --->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<span style="text-align: left">
#qxq_versionGUID#<br>
#qxq_fieldName#<br>
#qxq_fieldGUID#<br><br>
#qxq_instruct#
</span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
'>
<cfreturn modalButton>
</cffunction>
And here is how I am trying to implement it. This is 2 questions, and should display the instructions for each question. Instead, both buttons display the information for Q1.
<div class="form-group">
<label class="col-sm-1 control-label">1.</label>
<label for="oftndrink" class="col-sm-10 control-label" style="text-align:left">
How often do you have a drink containing alcohol?
</label>
<br>
<cfset form.qxq=createobject("component","#application.componentspath#.cfc_QxQ")>
<label class="col-sm-1">
#form.qxq.getFieldInstructions(qxq_versionGUID="#formInfo.versionGUID#",qxq_fieldName="oftndrink")#
</label>
</div>
(Q2)
<div class="form-group">
<label class="col-sm-1 control-label">2.</label>
<label for="numdrinks" class="col-sm-10 control-label" style="text-align:left">
How many drinks containing alcohol do you have on a typical day when you are drinking?
</label>
<br>
<cfset form.qxq=createobject("component","#application.componentspath#.cfc_QxQ")>
<label class="col-sm-1">
#form.qxq.getFieldInstructions(qxq_versionGUID="#formInfo.versionGUID#",qxq_fieldName="numdrinks")#
</label>
</div>
Thanks for pointing out the answer, which turned out to be really easy!
I am now initializing the component in a pre-process that runs once:
<cfset form.qxq=createobject("component","#application.componentspath#.cfc_QxQ")>
And can add the modal with the correct instructions by inserting just one line. (This part is a big deal because I have to add it to every question on about 150 forms)
<span style="text-align: left">#form.qxq.getFieldInstructions(qxq_versionGUID="#formInfo.versionGUID#",qxq_fieldName="varName")#</span>

The issue here is that both modals are created with the same ID exampleModal.
So, when you try to open using #exampleModal it will open the first element in the document. What you need to do is to make the modals have different ID. Something like this.
<div class="modal fade" id="exampleModal#qxq_fieldGUID#">
and the button arguments like data-target="##exampleModal#qxq_fieldGUID#".
That being said creating this much html for each question will increase your page size and in the cases where there are a lot of questions that might even crash the browser. You should try to make the modal dynamic by using AJAX or JS Objects containing the instructions.

Related

Bootstrap Modal INSIDE Coldfusion <cfoutput query> tags fails with "Invalid CFML construct"

The Bootstrap button and modal code below fails when the code is placed inside ColdFusion CFOUTPUT QUERY tags.
If I move the code outside of the cfoutput query then it works well.
Obviously, the problem is with the BootStrap modal single hashtag requirement: target="#staticBackdrop" for the button.
Inside the cfoutput, coldfusion expects two hashtags. The modal does not function without the single hashtag.
Is there a work-around?
<cfoutput query="q_GetPrinters">
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
DELETE
</button>
<!-- Modal -->
<div class="modal fade" name="staticBackdrop" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Delete Printer?</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<!--- <div class="modal-body">
...
</div>--->
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Confirm</button>
</div>
</div>
</div>
</div>
</cfoutput>
You have to use double hashes for mentioning ids in ColdFusion like,
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="##staticBackdrop">
Reason for this double hash is, in CF hash is used for outputting as it can be enclosed with variable name. While you writing target as #staticBackDrop, it will consider it as a variable name & hashes are not enclosed properly. So you re getting error like this.

CFML reCAPTCHA v3 Issue

Im trying to use the code I have found and its not working properly it is always saying that I am a robot do you have any idea why this will not work?
The Application.cfc has the site and secret key in it.
<script src="https://www.google.com/recaptcha/api.js?render=<cfoutput>#application.SiteKey#</cfoutput>"></script>
<cfif ISDEFINED('FORM.FirstName')> <!--- check if form was submitted and if so run code below --->
<cfhttp url="https://www.google.com/recaptcha/api/siteverify?secret=#application.SecretKey#&response=#FORM['g-recaptcha-response']#" result="Response" />
<cfset Return = deserializeJSON(Response.FileContent) />
<cfif Return.success IS 'true' AND Return.score GT 0.0> <!--- check if true and if score is greater than 0.5. Run code below if all good. --->
<cfoutput>Human: #FORM.FirstName# #FORM.LastName#</cfoutput>
<!--- you can do database entry and/or email results here --->
<cfelse> <!--- if not a human, do this. I usually remove the else part completely, but if you need to do something with the robot, do it here. --->
Most likely a robot.
</cfif>
<cfelse> <!--- show form --->
<form method="post" action="/contact.cfm"> <!--- submit form back to itself --->
First Name: <input name="FirstName" type="text"><br>
Last Name: <input name="LastName" type="text"><br>
<input name="submit" type="submit">
<input name="g-recaptcha-response" id="g-recaptcha-response" type="hidden" /> <!--- javascript below gives this a value from google. --->
</form>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('<cfoutput>#application.SiteKey#</cfoutput>', {action: 'homepage'})
.then(function(token) {
document.getElementById('g-recaptcha-response').value=token;
});
});
</script>
</cfif>
This is how I was able to get the form working properly.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://www.google.com/recaptcha/api.js?render=YOUR SITE KEY"></script>
<!-- contact form demo container -->
<cfif ISDEFINED('FORM.name')> <!--- check if form was submitted and if so run code below --->
<cfhttp url="https://www.google.com/recaptcha/api/siteverify?secret=#application.SecretKey#&response=#FORM['token']#" result="Response" />
<cfset Return = deserializeJSON(Response.FileContent) />
<cfif Return.success IS 'true' AND Return.score GT 0.5> <!--- check if true and if score is greater than 0.5. Run code below if all good. --->
<cfelse> <!--- if not a human, do this. I usually remove the else part completely, but if you need to do something with the robot, do it here. --->
</cfif>
<cfelse>
<section style="margin: 50px 20px;">
<div style="max-width: 768px; margin: auto;">
<!-- contact form -->
<div class="card">
<h2 class="card-header">Contact Form</h2>
<div class="card-body">
<form class="contact_form" method="post" action="contact.cfm">
<!-- form fields -->
<div class="row">
<div class="col-md-6 form-group">
<input name="name" type="text" class="form-control" placeholder="Name" required>
</div>
<div class="col-md-6 form-group">
<input name="email" type="email" class="form-control" placeholder="Email" required>
</div>
<div class="col-md-6 form-group">
<input name="phone" type="text" class="form-control" placeholder="Phone" required>
</div>
<div class="col-md-6 form-group">
<input name="subject" type="text" class="form-control" placeholder="Subject" required>
</div>
<div class="col-12 form-group">
<textarea name="message" class="form-control" rows="5" placeholder="Message" required></textarea>
</div>
<!-- form message prompt -->
<div class="row">
<div class="col-12">
<div class="contact_msg" style="display: none">
<p>Your message was sent.</p>
</div>
</div>
</div>
<div class="col-12">
<input type="submit" value="Submit Form" class="btn btn-success" name="post">
</div>
<!-- hidden reCaptcha token input -->
<input type="hidden" id="token" name="token">
</div>
</form>
</div>
</div>
</div>
</section>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('YOUR SITE KEY', {action: 'homepage'}).then(function(token) {
// console.log(token);
document.getElementById("token").value = token;
});
// refresh token every minute to prevent expiration
setInterval(function(){
grecaptcha.execute('YOUR SITE KEY', {action: 'homepage'}).then(function(token) {
console.log( 'refreshed token:', token );
document.getElementById("token").value = token;
});
}, 60000);
});
</script>
</cfif>
<!-- References for the optional jQuery function to enhance end-user prompts -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
This is how I passed the values to the API. Again, just passing along code that worked, not saying this is the only way
<cfhttp method="post" url="https://www.google.com/recaptcha/api/siteverify" result="Response">
<cfhttpparam name="secret" type="formField" value="#application.SecretKey#">
<cfhttpparam name="response" type="formField" value="#form["g-recaptcha-response"]#">
</cfhttp>

Picture submit to database blob and control size

I have a registration page that will submit all the registration values into MS SQL database. I am trying to control the size of the image that is updated to the database to be width=125 height=125. Is there a way to control that before it is submitted into the database?
Also is this the most recent way to submit it into the database?(The most recent I could find was 2011)
FORM
<form class="m-t" role="form" action="cfm/register_process.cfm" method="post" enctype="multipart/form-data">
<div class="form-group">
<input type="text" name="employee_number" class="form-control" placeholder="Employee Number" required="">
</div>
<div class="form-group">
<input type="text" name="firstname" class="form-control" placeholder="First Name" required="">
</div>
<div class="form-group">
<input type="text" name="lastname" class="form-control" placeholder="Last Name" required="">
</div>
<div class="form-group">
<input type="text" name="department" class="form-control" placeholder="Department" required="">
</div>
<div class="form-group">
<input type="text" name="position" class="form-control" placeholder="Position" required="">
</div>
<div class="form-group">
<input type="email" name="email" class="form-control" placeholder="Email" required="">
</div>
<div class="form-group">
<input type="text" name="phone_extension" class="form-control" placeholder="Extension" required="">
</div>
<div class="form-group">
<input type="text" name="user_name" class="form-control" placeholder="User ID" required="">
</div>
<div class="form-group">
<input type="password" name="user_pass" class="form-control" placeholder="Password" required="">
</div>
<div class="input-group">
<span class="input-group-btn">
<span class="btn btn-primary btn-file">
Select image
<input type="file" name="filefieldname" id="filefieldname" multiple />
</span>
</span>
<input id="filename" class="form-control" type="text"/>
<span class="input-group-btn">
<span class="btn btn-primary cleared">Reset</span>
</span>
</div>
<div class="form-group">
<div class="checkbox i-checks"><label> <input type="checkbox"><i></i> Agree the terms and policy </label></div>
</div>
<button type="submit" class="btn btn-primary block full-width m-b">Register</button>
<p class="text-muted text-center"><small>Already have an account?</small></p>
<a class="btn btn-sm btn-white btn-block" href="login.html">Login</a>
</form>
Then the form calls register_process.cfm and submits to database
<cffile action="readbinary" file="#form.filefieldname#" variable="bin_filedata">
<cfquery datasource="test" name="UserRegistration">
INSERT INTO dbo.Users (employee_number, user_name, user_pass, firstname, lastname, position, email, phone_extension, department, picture)
VALUES (
, <cfqueryparam value='#form.employee_number#' cfsqltype='cf_sql_varchar' />
, <cfqueryparam value='#form.user_name#' cfsqltype='cf_sql_varchar' />
, <cfqueryparam value='#form.user_pass#' cfsqltype='cf_sql_varchar' />
, <cfqueryparam value='#form.firstname#' cfsqltype='cf_sql_varchar' />
, <cfqueryparam value='#form.lastname#' cfsqltype='cf_sql_varchar' />
, <cfqueryparam value='#form.position#' cfsqltype='cf_sql_varchar' />
, <cfqueryparam value='#form.email#' cfsqltype='cf_sql_varchar' />
, <cfqueryparam value='#form.phone_extension#' cfsqltype='cf_sql_varchar' />
, <cfqueryparam value='#form.department#' cfsqltype='cf_sql_varchar' />
, <cfqueryparam value='#bin_filedata#' cfsqltype='cf_sql_blob' />
)
</cfquery>
<script>
self.location="../login.html";
</script>
Unfortunately when I try to submit this I just get an all white screen and it does not update the database. I am assuming I am doing something wrong with the picture.

How to set the width of the input element using Foundation 5 Zurb

Below is the html JSFiddle - Problem
<div class="row">
<div class="small-3 medium-3 large-3 columns">
<label for="firstName" class="inline">* First Name:</label>
</div>
<div class="small-9 medium-9 large-9 columns">
<input type="text" name="firstName" id="firstName" placeholder="First Name" />
</div>
</div>
The input element spans the entire page width by default. I want to limit the width of the element.
One way to achieve this is by using incomplete rows and adding class end.
See below: JSFiddle - Solution
<div class="row">
<div class="small-3 medium-3 large-3 columns">
<label for="firstName" class="inline">* First Name:</label>
</div>
<div class="small-3 medium-3 large-3 end columns">
<input type="text" name="firstName" id="firstName" placeholder="First Name" />
</div>
Is this the correct way? Or is there any other method to do it.
I am aware that I can use css/modify css but wanted to see if there is any other way to do it using Foundation.
This is the correct way to size input elements.
While there are many ways to do it, wrapping form elements in column classes is the recommended method. For example, to produce an input with 50% width, wrap the input in a large-6 columns end class.
<form>
<div class="row">
<div class="large-6 columns end">
<label>Input Label
<input type="text" placeholder="large-12.columns" />
</label>
</div>
</div>
</form>

Element Undefined Error In ColdFusion. cfparam does not work

I am having problems with my ColdFusion code returning "Element AUTHOR is undefined in FORM." whenever I submit my form. I've tried using <cfparam> to set comment.author but it didn't work either. I'm fairly new to ColdFusion so any reasoning comments would be great too!
<cfparam name="form.submitted" default="0" />
<cfset blogPost = EntityLoad('BlogPost',url.id,true) />
<cfif form.submitted>
<cfset comment = EntityNew('BlogComment') />
<cfset comment.author = form.author />
<cfset comment.comment = form.comment />
<cfset comment.createdDateTime = now() />
<cfset blogPost.addComment(comment) />
<cfset EntitySave(blogPost) />
</cfif>
<cfimport taglib="customTags/" prefix="layout" />
<layout:page section="blog">
<!-- Content Start -->
<!--Card -->
<div id="content">
<div class="card-pattern">
<!-- blog -->
<div id="blog">
<div class="clr">
<div class="top-bg1">
<div class="top-left">
<div><h1>Blog</h1></div>
</div>
</div>
<div class="clr">
<div class="pat-bottomleft"> </div>
<div class="pat-bottomright"> </div>
</div>
</div>
<div class="blog-top">
<div class="clr">
<cfoutput>
<div class="left">
<!-- Blog Title -->
<h2 class="big">
#blogPost.title#
</h2>
<!-- Date Published -->
<h5>
<strong>Date Posted</strong>: #dateformat(blogPost.dateposted,'mm/dd/yyyy')#
</h5>
<!-- Blog Body -->
#blogPost.body#
<!-- Blog Export -->
<p>
<img src="assets/images/export_pdf.png" border="0"/>
</p>
<!-- Blog Comments Section -->
<h3>
Comments #arrayLen(blogPost.getComments())#
</h3>
<div class="clr hline"> </div>
<div class="clr comments">
<ul>
<!-- Start Comment -->
<cfloop array="#blogPost.getComments()#" index="comment">
<li>
<p>
<strong>Posted On:</strong> #dateFormat(comment.createdDateTime,'mm/dd/yyyy')# at #timeformat(comment.createdDateTime,'short')# By #comment.author#
</p>
<p>
#comment.comment#
</p>
<div class="clr hline"> </div>
</li>
</cfloop>
<!-- End Comment -->
</ul>
</div>
<h3>
Post Comment
</h3>
<div class="clr hline"> </div>
<div class="clr postComment">
<form action="BlogPost.cfm?id=#blogPost.id#" method="post" id="form">
<div>
<label>Name <span class="font-11">(required)</span></label>
<input name="contactname" type="text" class="required" />
</div>
<div class="textarea">
<label>Comment <span class="font-11">(required)</span></label>
<textarea name="comment" rows="6" cols="60" class="required"></textarea>
</div>
<div>
<input id="submitBtn" value="Submit" name="submit" type="submit" class="submitBtn" />
</div>
<input type="hidden" name="submitted" value="1" />
</form>
</div>
</div>
</cfoutput>
<div class="right" >
<h2>Categories</h2>
<!-- Blog Specific Categories -->
<div id="categories" align="center">
<ul>
<li>ColdFusion</li>
<li>Development</li>
</ul>
</div>
</div>
</div>
</div>
<div class="clr"></div>
</div> <!--blog end -->
</layout:page>
The error is telling you what is wrong. There is no author element in your form OR there is no form scope at all. Here is the form code that you posted:
<form action="BlogPost.cfm?id=#blogPost.id#" method="post" id="form">
<div>
<label>Name <span class="font-11">(required)</span></label>
<input name="contactname" type="text" class="required" />
</div>
<div class="textarea">
<label>Comment <span class="font-11">(required)</span></label>
<textarea name="comment" rows="6" cols="60" class="required"></textarea>
</div>
<div>
<input id="submitBtn" value="Submit" name="submit" type="submit" class="submitBtn" />
</div>
<input type="hidden" name="submitted" value="1" />
</form>
It only contains 4 elements: contactname, comment, submit and submitted. This means that after the form is submitted ColdFusion will have access to: form.contactname, form.comment, form.submit and form.submitted. I presume that you are trying to set your comment.author variable to the contactname form field.
You could either change your code where you are setting the variable, like this:
<cfset comment.author = form.contactname />
Or you could change your code where the form field is defined, like this:
<input name="author" type="text" class="required" />
Either way, the references to the form scope must match the names that you give them in your HTML form. For what it's worth, you can always dump the form scope after it is submitted to see what is available, like this:
<cfdump var="#form#">
Also remember to sanitize all data that you receive from the client.
How can I sanitize user input but keep the content of <pre> tags?
Agreed, undefined because it doesn't exist in the form.
And definitely sanitize all form and url data. One example below:
<cfset myVar = ReReplaceNoCase(#FORM.formfield#,"<[^>]*>","","ALL")/>