Link to home
Start Free TrialLog in
Avatar of joezizzo
joezizzoFlag for United States of America

asked on

Running a ColdFusion page in the background

I'm having a surprising amount of trouble finding out how I can have a user action fire off a background coldfusion process. I know this can be done with cfschedule, but i need to pass specific parameters to the template before proceeding.

I'm looking for a way to pass parameters to a CFM and run it, but not hang the user up in the process.  Basically, I want to initiate a rather large FTP upload with what the user has entered into the html form.  

Is there a way to allow the user to write the file to the server and locate away, while in the process, firing off a template that will run a rather long process for moving the file to where it needs to be?
Avatar of kyle1830
kyle1830

when the form submits, open a small window that says "Processing file" running the upload process.  when the small window loads have an onload event that send the focus back to the opener window.  You can even send the opener to another page.

small window:
<body onload="opener.focus();opener.location.href='/index.cfm';">

Kyle
here is what you would do on the form to get it to send the fields to the popup
<form action="processpage.cfm" method="post" target="mywin" onsubmit="window.open('','mywin','resizable,height=200,width=200,scrollBars=yes');">
    <input type="Text" name="test" value="Test">
    <input type="Submit" name="submit" value="submit">
</form>


then when the process window finishes the upload code add a window close function.

<script>
alert("Finished processing");
window.close;
</script>
If it is just a page that you want running then yes.

One method to do this is to have the page work in the background.

You can do this using an iframe (or a better XML method if you exclude certain older browsers like IE 5 for Mac)

THe way to do this is to have the button call a function in your page that looks like this:

<script type="text/javascript" language="JavaScript">
function CallPage()
{      
     callToServer("MyProcessPage.cfm?Var1=" + #var1# + "&var2=" + #var2#);
}
</script>

Or have javascript get the values instead of being coded in  like so:

function CallPage()
{      
     callToServer("MyProcessPage.cfm?Var1=" + document.getElementById("var1").value + "&var2=" +  document.getElementById("var2").value);
}


Then if you want to display a message to the user whenthe process is done add a function like the following


function Complete()
{    
     document.GetElementById("completemessage").innerHtml = "Process Complete";
}

The MyProcessPage.cfm would be a cold fusion page with your code to run the process on it - and it would accept all parameters via URL.

It would look like:

<cfquery datasource="myDSN" name="myquery">
whatever here
</cfquery>

<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<cfoutput>
<body onLoad="window.parent.Complete();">
</body>
</cfoutput>
</html>


SO then the onyly thing you need is to include the following javascript file to make the callToServer function work:

save as iFrameRPC.js

// ****************BEGIN FILE******************************************
var IFrameObj; // our IFrame object

function callToServer(backgroundURL) {
     if (!document.createElement)
     {// todo :: implement some kind of redirection if browser doesn't support creating of dom object
          return true;
     }
       
     var IFrameDoc;
     var URL =  backgroundURL;
     if (!IFrameObj && document.createElement)
     {// create the IFrame and assign a reference to the object to our global variable IFrameObj.
          // this will only happen the first time callToServer() is called
          try
          {
               var tempIFrame=document.createElement('iframe');
               tempIFrame.setAttribute('id','RSIFrame');
               tempIFrame.style.border='0px';
               tempIFrame.style.width='0px';
               tempIFrame.style.height='0px';
               IFrameObj = document.body.appendChild(tempIFrame);
               
               if (document.frames)
               {// this is for IE5 Mac, because it will only allow access to the document object
               // of the IFrame if we access it through the document.frames array
                    IFrameObj = document.frames['RSIFrame'];
               }
          }
          catch(exception)
          {// This is for IE5 PC, which doesn't allow dynamic creation/manipulation of iframe object.
               // Instead, we'll fake it up by creating our own objects.
               iframeHTML='\<iframe id="RSIFrame" style="';
               iframeHTML+='border:0px;';
               iframeHTML+='width:0px;';
               iframeHTML+='height:0px;';
               iframeHTML+='"><\/iframe>';
               document.body.innerHTML+=iframeHTML;
               IFrameObj = new Object();
               IFrameObj.document = new Object();
               IFrameObj.document.location = new Object();
               IFrameObj.document.location.iframe = document.getElementById('RSIFrame');
               IFrameObj.document.location.replace = function(location) {this.iframe.src = location;}
          }
     }          
 
     if (navigator.userAgent.indexOf('Gecko') !=-1 && !IFrameObj.contentDocument)
     {     // we have to give NS6 a fraction of a second
           // to recognize the new IFrame
           setTimeout('callToServer()',10);
           return false;
     }
 
     if (IFrameObj.contentDocument)
     {     // For NS6
          IFrameDoc = IFrameObj.contentDocument;
     }
     else if (IFrameObj.contentWindow)
     {     // For IE5.5 and IE6
          IFrameDoc = IFrameObj.contentWindow.document;
     }
     else if (IFrameObj.document)
     {     // For IE5
           IFrameDoc = IFrameObj.document;
     }
     else
     {
          return true;
     }
 
     IFrameDoc.location.replace(URL);
     return false;
}
//*****************END FILE***********************


(Watch out for some wrapping (due to forum) of above that should be on one line....)

ANd include in your project as <script type="text/javascript" language="JavaScript" src="iframeRPC.js"></script>
I see kyle was positng while I was typing.

His method works too, but I am not sure what happens if they close the pop-up or have pop-up blockers on...

THe background method I decscribed doesn't use pop-ups so you don't have to worry about it being blocked, but the action is transparent to the user.....
mrichmon, good solution to "bypass" blockers.  I like it!.

My Intranet uses the "popup" method and since I control the blockers, my site is always allowed to "pop".   It's nice making the rules, but I lose out on having to think outside the box sometimes.

One ?..... since this is running in the background, what happens if the user clicks another link on the page before the process is finished?  I assume it would go to the new page and end processing.  How would you prevent this?

OK that was two questions?
No it actually is a separate page so the processing *should* complete, but you won't get the complete message.

I say *should* since I don't kow what will happen with Really Long processes.....
ASKER CERTIFIED SOLUTION
Avatar of INSDivision6
INSDivision6

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial