Tuesday, October 21, 2008

Simple Dojo Example for R&D (ripoff and duplicate) and/or Critiquing

Originally posted on www.dojotoolkit.org/forum

I put the following example together back in August as part of my ongoing effort to experiment with dojo. The example includes a loading page, followed by a login page which if the correct username and password are entered brings up a mock application page.

The work is in no way original as I made healthy use of the dojo forums and other examples that I found on the web. I hope by posting a working example here others may learn from what I learned from others.

If you have comments or suggestions I would be very interested in hearing them. If you have questions I will do my best to answer them.

<html>
  <head>
    <title>User Interface</title>
    <!--Look for dojo on local server-->
    <script type="text/javascript">
      var dojoroot= 'http://' + window.location.hostname + '/dojo/js/dojo';
      var ext='.js';

      document.write('<link href="'+dojoroot+'/dojo/resources/dojo.css" type="text/css" rel="stylesheet">');
      document.write('<link href="'+dojoroot+'/dijit/themes/soria/soria.css" type="text/css" rel="stylesheet">');
      document.write('<script type="text/javascript" src="'+dojoroot+'/dojo/dojo'+ext+'" djConfig="debug: true, parseOnLoad: false"><\/script>');
    </script>
   
    <!--Check if dojo is loaded if not load from aol.-->
    <script type="text/javascript">
      if(typeof dojo == "undefined"){
        dojoroot='http://o.aolcdn.com/dojo/1.1.1';
        ext='.xd.js';

        document.write('<link href="'+dojoroot+'/dojo/resources/dojo.css" type="text/css" rel="stylesheet">');
        document.write('<link href="'+dojoroot+'/dijit/themes/soria/soria.css" type="text/css" rel="stylesheet">');
        document.write('<script type="text/javascript" src="'+dojoroot+'/dojo/dojo'+ext+'" djConfig="debug: true, parseOnLoad: false"><\/script>');
      }
    </script>
   
    <style>
      html, body, #uigMainCnt, #uigAppPge, #loader{ 
        width: 100%;  /* make the body expand to fill the visible window */
        height: 100%;
        overflow: hidden;  /* erase window level scrollbars */
        padding: 0 0 0 0;
        margin: 0 0 0 0;
        top:0; left:0;
        font: 10pt Arial,Myriad,Tahoma,Verdana,sans-serif;
        position: absolute;
      }

    /* Start Loading Page */
      #loader {
        background:#ffffff;
        z-index:999;
      }
      #loaderInner {
        padding:5px;
        position:relative;
        left:0; top:40%;
        width:100%;
        background:#ffffff;
        color:#fff;      
      }
      /* End Loading Page */
     
      /* Start Login Form */
      #uigLoginFrm label,input {
        display: block;
        float: left;
        margin-bottom: 10px;
      }
      #uigLoginFrm label {
        text-align: left;
        width: 50px;
        padding-right: 20px;
      }
      #uigLoginFrm button {
        margin-left: 50px;
      }
      #uigLoginFrm br {
        clear: left;
      }
      #uigLoginMsg {
        text-align: left;
        padding-top: 5px;
        color: red;
      }
      /*End Login Form */
     
      /*Start App Main Page */
      #uigAppPge{
        visibility: hidden;
      }
      /*End App Main Page */
    </style>
   
    <script type="text/javascript">
      dojo.require("dojo.fx");
      dojo.require("dojo.parser");

      dojo.require("dijit.layout.BorderContainer");

      dojo.require("dijit.Dialog");
      dojo.require("dijit.form.ValidationTextBox");
      dojo.require("dijit.form.Button");
      dojo.require("dijit.form.Form");

      dojo.require("dijit.layout.ContentPane");
      dojo.require("dijit.form.Button");
      dojo.require("dijit.Toolbar");
      dojo.require("dijit.Menu");
      dojo.require("dijit.Tooltip");
     
      //Using this function along with the dojo.connect in the dojo.addOnLoad allows the submit event to be stopped
      //so that when the function completes it will not try and submit the form.  There are a number of ways that
      //this can be done but this appears to be the most common.
      function uigLoginAuth(e){
        //Stop the default action from happening when the function completes. 
        dojo.stopEvent(e);
        console.log ('In uigLoginAuth...');
        if(!dijit.byId('uigLoginFrm').validate()){
          dojo.byId('uigLoginMsg').innerHTML='Invalid data, please correct';
          return;
        }
       
        //Normally you would call a routine on the server to validate but for the example we will just simulate that.
        //dojo.xhrPost ({
        //  url: 'uigLoginAuth.pl',
        //  form: 'uigLoginFrm',
        //  load: uigFireApp,
        //  error: function(response, ioArgs) {
        //    dojo.byId('uigLoginMsg').innerHTML='System error: '+ ioArgs.xhr.status;
        //    return;
        //  }
        //});
       
        //Emulate call to server
        var user = dijit.byId('uiguser').getValue();
        var pwd = dijit.byId('uigpwd').getValue();

        if ((user=='test') && (pwd=='test')) {
          uigFireApp('uigsuccess', 0);
          return;
        }
       
        uigFireApp('uigLoginAuth-Fail, Login failed, try again!', 0);
      }
     
      function uigFireApp(response, ioArgs) {
        if (response!='uigsuccess') {
          dojo.byId('uigLoginMsg').innerHTML=response;
          return;
        }

        //Hiding the dialog allows the page "below" it to become active and accept input and respond to the mouse.
        dijit.byId('uigLoginDlg').hide();

        //Clear the login form so the username and password are not stored after a successful authentication
        uigLoginReset();
           
        //To get the main application screen to fade in the CSS sets the uigAppPge to visibility: hidden.
        //This function uses dojo to correctly set the opacity of the div based on browser independent logic
        //and then makes the div visible and does the fade.  This works for both IE and FF.
        dojo.style(dojo.byId('uigAppPge'), "opacity", "0");
        dojo.style(dojo.byId('uigAppPge'), "visibility", "visible");
        dojo.fadeIn({
          node: 'uigAppPge'
        }).play();
      }
     
      function uigLoginReset () {
        dojo.byId('uigLoginMsg').innerHTML=" ";
        dojo.byId('uigLoginFrm').reset();
        return false;
      }
     
      function uigLoginCancel () {
        dojo.byId('uigLoginMsg').innerHTML=" ";
        dojo.byId('uigLoginFrm').reset();
        dijit.byId('uigLoginDlg').show();
        return false;
      }
     
      //The logout function will need to make a call to the server to log the user out.
      function uigLogout () {
        dojo.fadeOut({
          node: 'uigAppPge'
        }).play();
        dijit.byId('uigLoginDlg').show();
       
        //Call to server to login the session out
      }
       
      dojo.addOnLoad(function(){
        //Start Loading Page
         dojo.parser.parse();
        dojo.fadeOut({
          node: 'loader',
          onEnd: function(){
            dojo.style(dojo.byId('loader'), "display", "none");
          }
        }).play();
        //End Loading Page
       
        //Start Login Form
        dijit.byId('uigLoginDlg').show();
        dojo.connect(dijit.byId('uigLoginDlg'), 'onCancel', uigLoginCancel);
        //End Login Form
      });
      </script>
  </head>
 
  <body class="soria">
    <!-- Start Loading Page -->
    <div id="loader"><div id="loaderInner" align=center>
      <img src="loading.gif"/>
      <p style="color: #BCD5F0"><font face="Arial"><b>Loading</b></font></p>
    </div></div>
    <!-- End Loading Page -->
   
    <div id="uigMainCnt" >
      <!-- Start Login Form -->
      <div id="uigLoginDlg" dojoType="dijit.Dialog" title="Login">
        <form id="uigLoginFrm" dojoType="dijit.form.Form" action="" method="">
          <label for="uiguser">Username</label>
          <input id="uiguser" type="text" trim="true" required="true" invalidMessage="Username is Required!" dojoType="dijit.form.ValidationTextBox" value="" name="uiguser"/><br>
          <label for="uigpwd">Password</label>
          <input id="uigpwd" type="password" trim="true" required="true" invalidMessage="Password is Required!" dojoType="dijit.form.ValidationTextBox" value="" name="uigpwd"/><br>
          <button dojoType="dijit.form.Button" onClick="uigLoginAuth">Login</button>
          <button dojoType="dijit.form.Button" onClick="uigLoginReset">Reset</button>
          <div id="uigLoginMsg"> </div>
        </form>
      </div>
      <!--End Login Form -->
     
      <!--Start App Main Page-->
      <div id="uigAppPge" dojoType="dijit.layout.BorderContainer">
        <div id="uigAppMenuBar" dojoType="dijit.Toolbar" region="top" class="menuBar">
          <button dojoType="dijit.form.Button">
            Logout
            <script type="dojo/method" event="onClick">
              uigLogout();
            </script>
          </button>
        </div>
          
        <div id="uigCenterCnt" dojoType="dijit.layout.ContentPane" region="center">
          uigCenterCnt
        </div>

        <div id="uigBottomCnt" dojoType="dijit.layout.ContentPane" region="bottom"
             style="height:100px;" splitter="true">
          uigBottomCnt
        </div>

        <div id="uigSideCnt" dojoType="dijit.layout.ContentPane" region="left"
             style="width:100px;" splitter="true">
          uigSideCnt
        </div>
      </div>
      <!--End App Main Page-->
    </div>
  </body>
</html>

Wednesday, September 10, 2008

IIS 5.1 and IIS 6.0 Fastcgi and Perl Install in a Test Configuration

Originally posted on forums.iis.net

After spending a good bit of time with Google and through trial and error I have found a configuration that appears to support perl using FastCGI on IIS 5.1 and IIS 6.0 using MS's FastCGI Extension for IIS6.0. I have tested it out on a limited basis using both IIS 5.1 on WinXp and IIS 6.0 on a virtual machine copy of Windows 2003 Server running on top of WinXP.

With this setup you setup a specific perl routine to run every time a URL with a specific extension is entered. What use this is I will leave up to you to decide.

A good description of how to configure FastCGI that focuses on PHP:

http://learn.iis.net/page.aspx/248/configuring-FastCGI-extension-for-iis60/

Here are the steps that I took to make it work with perl.

  1. Configure IIS on both platforms using the default choices.
  2. Download and install ActivePerl 5.8.8.824 using the msi installer and the default choices. Downloaded from: http://www.activestate.com/store/download_file.aspx?binGUID=45107672-7d2c-4529-85be-4aad89bcd59c
  3. Using the ppm utility from ActivePerl install the FCGI module from the ActiveState PPM repository.
  4. Download and install FastCGI using default options. Downloaded from: http://www.microsoft.com/downloads/details.aspx?FamilyID=2d481579-9a7c-4632-b6e6-dee9097f9dc5&displaylang=en and check to make sure fcgiconfig.js, fcgiext.dll and fcgiext.ini were all present in c:\windows\system32\inetsrv.
  5. In "Local Security Settings" under "User Rights Assignment" add the "Network Service" to "Access this computer from the network". This took me a while to figure out. Now I need to think about potential side effects.
  6. Using the Internet Information Services manager program:
    1. Select properties for the "Default Web Site" and then go to the "Home Directory" tab and select "Configuration..." to get "Application Configuration" window.
    2. Select "Add" to get the "Add/Edit Application Mapping" window.
    3. Under "Executable:" browse to c:\windows\ststem32\inetsrv\fcgiext.dll and select it.
    4. Once back at the "Add/Edit Application Mapping" select the value in the "Executable:" window. If you don't do this you will never be able to select "OK". See http://support.microsoft.com/kb/317948 for further details.
    5. Type in .fcgi into the "Extension" field.
    6. Check to make sure the "Script Engine" box is checked
    7. The documentation says that "File Exists" must be checked but based on initial tests this is not the case.
    8. Press OK.
  7. Using the Services I restart the "World Wide Web Publishing" service.
  8. Edit fcgiext.ini to include the lines below at the bottom. Note that what this is going to do is run the perl routine in printenv.fcgi every time you enter anything with an ".fcgi" extension. If you have not selected the checked the "File Exists" above then there will be no checking to make sure the file even exists.

    [Types]
    
      fcgi=fcgi
    
    [fcgi]
    
      ExePath=c:\perl\bin\perl.exe
      Arguments=c:\inetpub\wwwroot\printenv.fcgi
  9. Placed printenv.fgci into the c:\inetpub\wwwroot directory.
    use FCGI;
    
    while (FCGI::accept() == 0) {
      print "Content-type: text/html\r\n\r\n";
      while (($key, $val) = each %ENV) {
        print "$key = $val\n";
       }
    } 

At this point printenv.fcgi will run every time you enter the following URL http://yourserver.domain.com/printenv.fcgi. Again note if you have not selected "File Exits" when you setup the application mapping no checking to see if the file on the URL actually exists. In this case http://yourserver.domain.com/mydir/test.fcgi will also run printenv.fcgi.

Tuesday, September 9, 2008

Welcome

Welcome to digitalhack's blog. I am in the process of setting this up. Please check back later.