Displaying "no records found" alert from inside a CFC - coldfusion

In CF9 with IE8 I have a cfgrid that is bound to a text (search) field as well as a cfc function. The text field value is used as a query filter within the cfc function. If any results are found, the grid gets populated. Otherwise, I would like to send an alert to user like "No records found"
I couldn't find anything able to do this, as both javascript and CF tags seem to be simply ignored inside a cfc, i.e.
<cfif myQry.recordCount eq 0> No records found <cfabort></cfif>
or
<cfif myQry.recordCount eq 0>
<script>
alert("No records found");
</script>
</cfif>
Thanks for any suggestions

It actually proved to be more complicated than I thought. I've tried a couple of things I discovered, like the ajaxOnLoad statement or the onLoad event of the grid, but they didn't work as expected. Finally I solved it with a js function like:
getTotalRows = function() {
var isGrid = ColdFusion.Grid.getGridObject('myGrid');
var isData = isGrid.getStore();
isData.addListener("load", function() {
if(isData.totalLength == 0)
{
alert("No records found");
return false;
}
});
}
ColdFusion.Event.registerOnLoad(getTotalRows,null,false,true);

Related

Hide Tooltip for HTML5 validation defined in ASP.NET/MVC

When the input does not match the pattern specified by the pattern attribute, the browser displays "You must use this format:" in a tooltip on the field.
I cannot hide this tooltip message at all, can I? 'Cause even when I write
#Html.TextBoxFor(model => model.tbMyNumber, new { #pattern = "[0-9]{6,}", title="" })
it stills brings "You must use this format:" in the tooltip for this field.
How can I avoid this?
I don't think there is a way to do what you want without adding javascript. A simple alternative would be to verify with javascript (example below shown using jQuery) instead...
$('#myform').submit(function() {
if(!/^[0-9]{6,}$/.test($('#mytext').val())) {
return false;
}
});
This would prevent the form from submitting if the value doesn't match the pattern... without displaying the tooltip... just make sure you have an alternative so the user doesn't wonder why they can't submit the form.
I guess that is not what you expect as answer, but you can probably work the problem around with javascript
HTML:
* The string must be at least 6 digits
<br/>
<input type="text" onkeyup="isNumber(this)" onblur="lengthValidation(this)">
Javascript:
function isNumber(textbox)
{
textbox.value = textbox.value.replace(/[\D]+/, '');
}
function lengthValidation(textbox)
{
if (textbox.value.length < 6) {
document.getElementById("error").style.display = 'block';
} else {
document.getElementById("error").style.display = 'none';
}
}
Test it here: https://jsfiddle.net/mvxeous4/1/

JavaScript client side (user input) find-and-replace Hyperlinks

I want a clientside user to be able to insert text in text input box, click 'replace' and have a list of hyperlinks replaced accordingly. Anchor text will stay the same, but the hyperlink will change.
My problem: I am only getting the first hyperlink to change. I have a fiddle set up with two links, and you can see only the first changes. I want a list of, say, 20 links to change at once.
jsfiddle.net/TKxuf/
HTML:
<input id="replace" type="text" value="newphrase" />
<input onclick="doReplace()" type="button" value="Replace!" />
<br/>
<p id="list">Google Keyword Search</p>
<p id="list">Yahoo Keyword Search</p>
JavaScript:
function doReplace() {
var s = "keyword";
var r = document.getElementById('replace').value;
var oldtext = document.getElementById('list').innerHTML;
var newtext = oldtext.replace( s, r );
console.log(s);
console.log(r);
console.log(document.getElementById('list'));
document.getElementById('list').innerHTML = newtext;
}
I can't work out why you'd want the original strings in the HTML page code to begin with, so I'd suggest that you may have a problem with your approach. Note also that it's illegal in HTML to have more than one element with the same Id, which mostly explains why getElementById only returns one item. Also external urls must be preceded by http:// too.
I usually use jQuery these days - in jQuery you could simply swap id="list" to class="list" and use $('.list') to get a list of them all. $('.list').each(function() { var item = this; /* manipulation code here */ }); would allow you to change them all, but you may have to do some reading.
In any case, I still think that your approach is wrong.
What I'd do is have a normal javascript array of Urls, with replacable keys that are difficult to confuse as part of the url, e.g.
var addresses = [
{ text: "Google Keyword Search", url: "http://google.com?q=%keyword%" },
{ text: "Yahoo Keyword Search", url: "http://yahoo.com?q=%keyword%" }
];
When your user searches, you then build up your new html code into a string by iterating through the array:
var output = '';
for (var i = 0; i<addresses.length; i++) {
var item = addresses[i];
output += '<p>'+item.text+'</p>';
}
Note: I haven't checked this code, but you should be able to get the idea. You'd actually write out all the entire list by using innerHTML on the list container.
Hope that this helps.
Best Regards,
Mark Rabjohn
Integrated Arts Limited

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.

How To I Replace New Elements Added To A Page With Jquery

Here is the scenario... I have a a checkbox next to each field that I am replacing on page load with jquery with "Delete" text that enables me to delete the field via jquery, which is working fine. Like so...
$(".profile-status-box").each(function(){ $(this).replaceWith('<span class="delete">' + 'Delete' + '</span>') });
The problem comes in however is that after page load, I am also giving the user the option to dynamically add new fields. The new added fields though have the checkbox and not the delete link because they are not being replaced by jquery since they are being added after the initial page load.
Is't possible to replace the content of new elements added to the page without doing a page refresh? If not, I can always have two templates with different markup depending one for js and one for non js, but I was trying to avoind taht.
Thanks in advance.
You can use the .livequery() plugin, like this:
$(".profile-status-box").livequery(function(){
$(this).replaceWith('<span class="delete">Delete</span>')
});
The anonymous function is run against every element found, and each new element matching the selector as they're added.
Have a look at this kool demo. It removes and adds elements like a charm.
http://www.dustindiaz.com/basement/addRemoveChild.html
Here's how:
First of all, the (x)html is real simple.
xHTML Snippet
<input type="hidden" value="0" id="theValue" />
<p>Add Some Elements</p>
<div id="myDiv"> </div>
The hidden input element simply gives you a chance to dynamically call a number you could start with. This, for instance could be set with PHP or ASP. The onclick event handler is used to call the function. Lastly, the div element is set and ready to receive some children appended unto itself (gosh that sounds wierd).
Mkay, so far so easy. Now the JS functions.
addElement JavaScript Function
function addElement() {
var ni = document.getElementById('myDiv');
var numi = document.getElementById('theValue');
var num = (document.getElementById('theValue').value -1)+ 2;
numi.value = num;
var newdiv = document.createElement('div');
var divIdName = 'my'+num+'Div';
newdiv.setAttribute('id',divIdName);
newdiv.innerHTML = 'Element Number '+num+' has been added! <a href=\'#\' onclick=\'removeElement('+divIdName+')\'>Remove the div "'+divIdName+'"</a>';
ni.appendChild(newdiv);
}
And if you want to,
removeElement JavaScript Function
function removeElement(divNum) {
var d = document.getElementById('myDiv');
var olddiv = document.getElementById(divNum);
d.removeChild(olddiv);
}
and thats that. bobs your uncle.
This is taken from this article/tutorial: http://www.dustindiaz.com/add-and-remove-html-elements-dynamically-with-javascript/
I've just learnt this myself. thank you for the question
Hope that helps.
PK

cfgrid boolean column as Yes/No

I have a boolean type column in an html cfgrid. The data is stored in the database as 1/0 and is returned from CF as such. I want the user to see Yes/No instead of 1/0. I tried QuerySetCell, and couldn't get it to work.
The form is editable, when you double click the cell, the checkboxes show and it updates as it should. The only issue is the display.
<cfform>
<cfgrid name="blah" format="html" bind="mycfccall" selectmode="edit">
<cfgridcolumn name="bitCol" header="Is it" width="75" type="boolean">
</cfgrid>
</cfform>
Thanks in advance...
You'll need to apply a custom field renderer. You'll need to add an init() js function to your page, along with a renderer method. I have the basic process of applying a custom renderer on my blog:
CF8 Ajax Grid: Renderers and Events
Basically, you'll call your init() method after the grid has initially rendered, by using the ajaxOnLoad() method:
<cfset ajaxOnLoad("init") />
Within your init() method, you would get a reference to the grid and it's ColumnModel:
init = function() {
var myGrid = ColdFusion.Grid.getGridObject('myGridID');
var gridCM = myGrid.getColumnModel();
// The rest goes here
}
You'll also need your renderer method, that you can apply to any column:
yesNoRenderer = function(value,meta,record,row,column,store) {
if (value === 1){
return "Yes";
} else {
return "No";
}
}
After which, you'll need to apply the renderer to the column of your choice:
gridCM.setRenderer(cm.getIndexById('myColumnName'), yesNoRenderer);
The setRenderer method takes the column index (starting from 0) and the function to apply as a renderer. The getIndexById() method should work here, but you should test it first to be sure, and remember that casing is important in JavaScript.
Most of the CF Ajax components use Ext 1.1 under the hood. Carefully read through The Adobe documentation on the ColdFusion JavaScript Functions, and remember that you can tap into the underlying Ext 1.1 API.
I think it will be easier to use Decode in your database query:
Decode(bitCol,1,'Yes','No') bitCol