Coldfusion - How to prevent multiple clicks? - coldfusion

I have a button (anchor tag) that send a confirm message if you press it.
The problem is that for example if you press it 5 times very quickly it will send 5 confirm messages, if you press it 2 times it will send 2 messages.
This can occur when the user has low connection speed and while the page is refreshing he presses again the button.
How can I manage this situation? I though of disabling the button but for other reasons this is not possible.
<a class="msg" href="/manage/conversations.cfm?destination=#destination#">
#ucase(request.l('Send'))#
</a>
Thank you for your time

Ultimately, you need to have code on your server to prevent processing the link multiple times from the same user.
However, to solve the UI issue, have you link call a function instead of the cf file directly.
<a class="msg" href="javascript: processLink(#destination#);">
#ucase(request.l('Send'))#
</a>
<script>
runCount = 0;
function processLink(destination){
runCount++;
if (runCount == 1){
window.location.href = "/manage/conversations.cfm?destination=" + destination;
}
}
</script>

As mentioned in the previous answer it's nice to have some client side javascript to stop duplicate submissions from trigger happy users however you should also do this checking server side.
One approach would be to create a hidden formfield with a GUID that coldfusion generates when coldfusion renders your form.
So something like:
<cfset GUID = createUUID()>
<cfoutput>
<form id="frm" action="/target.cfm" method="post">
<input type="hidden" name="guid" value="#GUID#">
<!-- all your formfields go here -->
<input type="submit">
</form>
</cfoutput>
On the server side the target page then checks if it has already previously received the GUID. There are lots of ways to do, here are two of many ways.
a) Use Session Scope.
This is probably the quickest way if you are not running in a clustered environment and just need something quick for a tiny application.
<cfif isDefined("session.MYPAGE_GUID") AND session.MYPAGE_GUID EQ form.guid>
<cfoutput>Duplicate Form Submission</cfoutput>
<cfabort>
<cfelse>
<cfset session.MYPAGE_GUID = form.guid>
<!-- Do Business Logic Here -->
</cfif>
b) Use a Database Table.
Create a database table with a column called GUID. Make sure that GUID is the primary key or has a unique constraint.
Before you run your business logic insert the form.GUID into the database table. If you can do the insert process your business logic, if not the database query will throw an error that the record exists. You can then catch this error and take the appropriate action for a duplicate submission.
I prefer the database option as it works across clustered environments and database server are solid protecting against race conditions to ensure that a GUID is only set once.
Please be aware that this is just demonstrating the basic concepts and is not a drop in solution. There is a bit of more work to get these concepts into an e-commerce solution.

The best way is to disable the link once it's selected. If you don't want to do that, an alternative is to structure conversations.cfm like this.
<div id="pageContent">
small amount of text
</div>
<cfflush>
</body>
</html>
<cfsavecontent variable = "actualPageContent">
code
</cfsavecontent>
<cfoutput>
<script>
var #toScript(actualPageContent, "newPageContent")#;
document.getElementById("pageContent").innerHTML = "newPageContent";
</script>
</cfoutput>

Related

How to add and save entry in dropdown listbox using coldfusion

Id like to make a drop down list box where in at the end of the list, an option "Enter New housing", that if selected there will be a message box then it will automatically saves on the database and refreshes the object.
Im a beginner and this is what ive started:
<cfquery name="housingsel" datasource=" " dbtype=" ">
select rtrim(housing_name) as housing, housingid as housingid from housing order by housing
</cfquery>
<!---<cfquery name="housingins" datasource=" " dbtype=" ">
insert into housing (housingid,housing_name) values (1,'Tierra Pura Housing')
</cfquery>--->
<body>
<div class="container">
<div class="content">
<h1>Housing</h1>
<table width="300" bgcolor="#FFFFFF" cellpadding="2" cellspacing="0" border="0">
<cfform action="de_housing.cfm" method="POST">
<tr><td height="20" class="lbl" align="right">Housing</td><td>
<select name="housingcat">
<CFOUTPUT QUERY="housingsel">
<OPTION VALUE="#housingid#">#housing#</OPTION>
</CFOUTPUT>
<option value="new">Enter New Housing</option>
</select>
</td></tr>
<tr><td height="20" class="lbl"></td><td align="left">
</td></tr>
</cfform>
</table>
Please help!
Thanks!
First off, avoid cfform at all costs. It will not help you. See https://github.com/cfjedimaster/ColdFusion-UI-the-Right-Way for reasons why and examples of how to do stuff the right way.
That being said, what you want to do isn't difficult. Let's break it down.
> "Id like to make a drop down list box where in at the end of the list, an option "Enter New housing", that if selected "
Using jQuery, you would add a change handler to your dropdown. In that change handler, you can get the selected index of the drop down. If that index is equal to the length of the options, then the user has picked the last one.
> "there will be a message box"
You have a few choices here. One simple, but not pretty way, is to use the built in confirm option. It has a simple modal box API that the user can type in. There are pretty options, like jQuery UI dialogs, but the confirm option is super simple. I'd recommend starting there.
> "automatically saves on the database"
So, you will know when a user enters a value into the confirm. Take that and use jQuery to do an XHR (Ajax) hit to your code. You will need to write CF code to respond to this request and insert it into the db. Not too difficult and it has been shown many places elsewhere. I'd also add logic to check for dupes.
> "refreshes the object"
When you do a XHR in jQuery, you know when the server is done doing crap, so in the response handler, you can add a new option to the drop down. This too has been done many times before, just Google for adding an option to a drop down. (You will probably end up back here.)

Field giving error after CF9 to CF10 Upgrade

We have a form which has some mandatory fields and 2 buttons(One is Submit, second is Search).
Search buttton code is like :
<input name="btnSearch" type="submit" id="Search" value="Search">
This code redirects to action form and then further to a new screen. Finally it reverts back to the main form and has code to restore the selected values.
One of the mandatory fields has the following code:
<td align="right">Class Id:<font color="red">*</font></td>
<td><cfselect name="YY_CLASS_ID" size="1" query="XX_Class_List"
value="XX_CLASS_ID" display="XX_DESCRIPTION"
required="yes"selected="#variables.XX_CLASS_ID#">
<cfif variables.XX_CLASS_ID eq "">
<option value="" selected></option>
</cfif>
</cfselect></td>
When user clicks on the search button and this Class ID dropdown is blank, they get an error that "Error in YY_CLASS_ID text".
yy_class_id field has required attribute as ‘yes’ and message attribute is not set. As per our understanding, this means error should always come if the user tries to navigate away from the screen without populating the CLASS ID.
However, as per our user ,they were not getting this error in CF9 and started coming after the CF10 upgrade. They are frequent users of the screen and could have not missed this in past if this was happening during CF9 days.
Can anyone please confirm if something has changed in CF10 which was not earlier in CF9 and causing this issue. Or we missing something here.
Let me know if any more information is needed.

Execute cfquery after button press or behind the scenes action page?

My page creates a few random variables to pick prizes and winners for a drawing, and I want to write the prize winners and their prizes to a table after the winner clicks a button to claim the prize.
The problem is I want them to stay on the page so that a prize can be picked again if it isn't claimed.
The best solution I can come up with is an action page that the cfinput button references, but I don't want the action page to open up, I just want the cfquery on that page to run behind the scenes.
Here's an example of my query:
<cfquery name="updateQuantity" datasource="christmas">
UPDATE PRIZES
SET QUANTITY = QUANTITY - 1
WHERE prize_ID = #prizeID#
</cfquery>
I tried making my button a "submit" button and using cfif isDefined("form.Submit") to run the cfquery on the same page, but the submit button refreshes the page (which I don't want) and writes the next picked winner instead of the prizeID of the current session:
<cfform>
<cfinput name="submit" type="submit" value="Claim Your Prize!" onClick="">
</cfform>
<cfif isDefined("form.Submit")>
<cfquery name="updateQuantity" datasource="christmas">
UPDATE PRIZES
SET QUANTITY = QUANTITY - 1
WHERE prize_ID = #prizeID# </cfquery>
</cfif>
prizeID is determined by the randomly selected prize.
Adam is correct.
While AJAX is what you're after, ColdFusion's AJAX related tags are not the way to go.
Take the time to learn JQuery and AJAX (it isn't too hard, and the CF community has some great examples and guides) and do it properly; with your example requirements, you should be up and running in no time.
That way you can properly manage any logging and error handling that you may need to as well. Good luck!
It sounds like ColdFusion.Ajax.submitForm would work for you.
In general, I think an AJAX request is what you are looking for.

Django: How can I invisibly pass a variable to another template?

I have three templates in my project—we'll call them first.html, second.html, third.html.
first.html gets a string from the user, using an <input> tag:
<input type="radio" name="selection" value="example_string" />
second.html displays this string using {{selection}}. (In my views.py, I got the value using request.POST.get and render_to_response().)
The question is: how do I send this value from second.html to third.html? One of my attempts—using a <span> tag to save the information in a variable—is illustrated below, but it doesn't seem to work.
<span name="selection" value={{selection}}>{{selection}}</span>
Edit: The following line works by creating a dummy single radio button. I don't know why it shouldn't be possible to create a variable without an <input> tag [visible to the user].
<input type="radio" name="selected" value={{selected}} checked="checked" />
You need to understand how the web works: each page is entirely separate, and is requested using a separate request.
Your basic options are: save data on the client side, or post it back to the server.
Both options can be performed with javascript, or posting back can also be performed by posting the form back to the server.
If you want to send it back to the server, it will have to be stored in the current session, or in a model.
There are many javascript libraries. If you want to use them, I suggest you google around the subject.
Answering my own question, now that I've found the answer on Django's documentation.
There's a special kind of <input> tag precisely for this: "hidden". The following line accomplishes the same as was asked in the question, but without a dummy element visible to the user:
<input type="hidden" name="selected" value={{selected}} />

Many to Many relationship with cfwheels without composite keys

I've been following the information from here:
cfwheels.org/docs/1-1/chapter/nested-properties
I've ended up downloading a sample application which breaks down at the same place
code executes fine, in the sense that I get no errors, but the many-many table does not get the new entries, and when I add the entries manually in the database, they are not reflected with the checkboxes and sometimes they are removed when the model is updated.
EDIT
I found out the issue... just not how to solve it. There's a small detail there that is very easy to miss. The application seems to rely on composite keys and the order of the keys matters. But I'm not using composite keys.
(following https://github.com/mhenke/cfwheels-training/blob/develop/03-tags.md as an example...)
How do I get a table with cols: id,tagsid, and commentsid to work?
the problems I see is that cfwheels keeps trying to use the id tag when creating the taggings model
As much as I love about CFWheels, I have to admit that I am not a fan of the form helper functions or the "shortcut" feature. In this example case, I'd just "revert" to the more straightforward/simple CFML to construct the checkboxes (if not the whole form) and looping logic to save the values in the join table. For example:
<fieldset>
<legend>PropertyLanguages</legend>
<cfloop query="Languages">
<label>
#Languages.language#
<input type="checkbox" name="Property[PropertyLanguages]" value="#Languages.id#">
</label>
</cfloop>
</fieldset>
Then change the update controller logic like so:
<!--- CONTROLLER - update.cfm - updateProperty --->
<cffunction name="updateProperty">
<cfscript>
Property = model("Property").findByKey(key=params.Property.id);
Property.update(params.Property);
if (IsDefined("params.Property.PropertyLanguages"))
{
model("PropertyLanguages").deleteAll(where="propertyid=#params.Property.id# AND languageid NOT IN (#params.Property.PropertyLanguages#)");
for (var i = 1; i<=ListLen(params.Property.PropertyLanguages); i++)
{
languageid = ListGetAt(params.Property.PropertyLanguages, i);
if (! IsObject(model("PropertyLanguages").findOne(where="propertyid=#params.Property.id# AND languageid=#languageid#")))
{
pl = model("PropertyLanguages").new();
pl.langugageid = languageid;
pl.propertyid = params.Property.id;
pl.save();
}
}
}
else
{
model("PropertyLanguages").deleteAll(where="propertyid=#params.Property.id#");
}
</cfscript>
</cffunction>
I haven't tested this, but it should work, more or less. It's not as simple as it could (should?) be using the wheels helpers, but it doesn't seem too bad.