home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 July / 07_02.iso / software / mdmx / files / DreamweaverMXInstaller.exe / Disk1 / data1.cab / Configuration_En / Commands / ServerObject-MasterDetail.js < prev    next >
Encoding:
JavaScript  |  2002-05-01  |  19.5 KB  |  695 lines

  1. // Copyright 2001-2002 Macromedia, Inc. All rights reserved.
  2.  
  3. var _RecordsetName = new RecordsetMenu("","RecordsetName");
  4. var _MasterPageFields = new RecordsetFieldsOrderedList("MasterDetail.htm", "MasterPageFields", "");
  5. var _LinkField = new RecordsetFieldMenu("MasterDetail.htm", "LinkField", "");
  6. var _UniqueKeyField = new RecordsetFieldMenu("MasterDetail.htm", "UniqueKeyField", "");
  7. var _NumRecs = new NumRecButtons("MasterDetail.htm", "NumRecs", "");
  8. var _DetailPageName = new URLTextField("MasterDetail.htm", "DetailPageName", "");
  9. var _DetailPageFields = new RecordsetFieldsOrderedList("MasterDetail.htm", "DetailPageFields", "");
  10. var _Numeric = new CheckBox("MasterDetail.htm","Numeric","");
  11.  
  12. var _documentTypeID = "";
  13.  
  14. //--------------------------------------------------------------------
  15. // FUNCTION:
  16. //   commandButtons
  17. //
  18. // DESCRIPTION:
  19. //   API function for commands. Controls dialog buttons.
  20. //
  21. // ARGUMENTS:
  22. //   none
  23. //
  24. // RETURNS:
  25. //   an array of button names and function calls
  26. //--------------------------------------------------------------------
  27. function commandButtons()
  28. {
  29.   return new Array(MM.BTN_OK,      "clickedOK()",
  30.                    MM.BTN_Cancel,  "window.close()",
  31.                    MM.BTN_Help,    "displayHelp()");
  32. }
  33.  
  34.  
  35.  
  36. //--------------------------------------------------------------------
  37. // FUNCTION:
  38. //   createMasterDetailSet
  39. //
  40. // DESCRIPTION:
  41. //   Inserts the content into the master and detail pages.
  42. //
  43. //   In this implementation, this function is responsible for all
  44. //   insertion work.
  45. //
  46. // ARGUMENTS:
  47. //   paramObj. Contains properties:
  48. //     RecordsetName -- string
  49. //     MasterPageFields -- array
  50. //     DetailPageFields -- array
  51. //     LinkToField -- string
  52. //     UniqueIDField -- string
  53. //     DetailPagePath -- string, relative path from master page
  54. //     DetailPageName -- string, file name only
  55. //     PageSize -- string or number, "all" or positive integer
  56. //
  57. // RETURNS:
  58. //   string - empty upon success, or an error message
  59. //--------------------------------------------------------------------
  60. function createMasterDetailSet(paramObj)
  61. {
  62.   var docURL = dw.getDocumentPath('document');
  63.   var siteURL = dw.getSiteRoot();
  64.   var detailPageName = paramObj.DetailPageName;
  65.   var detailPageAbsURL = dwscripts.getAbsoluteURL(detailPageName,docURL,siteURL);
  66.   var uniqueIDField = paramObj.UniqueIDField;
  67.   _documentTypeID = dw.getDocumentDOM().documentType;
  68.  
  69.   // add recordset parameters. Looks for the recordset paramObj.RecordsetName,
  70.   // and adds its parameters to paramObj
  71.   getRecordsetParameters(paramObj);
  72.   
  73.   paramObj.AddQueryString = "QueryString";
  74.  
  75.   // hava: genericize this so that it is not platform-specific...
  76.   var urlVar = (paramObj.Numeric)?"#URL.recordID#":"'" + "#URL.recordID#" + "'";
  77.   var conditionStr = paramObj.UniqueIDField + " = " + urlVar;
  78.  
  79.   // new SQL statement used in detail page recordset
  80.   paramObj.SQLStatement = editWhereClause(paramObj.SQLStatement,conditionStr);
  81.  
  82.   // add navigation bar parameters
  83.   paramObj.FirstLinkText = MM.LABEL_NewMoveToFirstLinkLabel;
  84.   paramObj.PrevLinkText  = MM.LABEL_NewMoveToPrevLinkLabel;
  85.   paramObj.NextLinkText  = MM.LABEL_NewMoveToNextLinkLabel;
  86.   paramObj.LastLinkText  = MM.LABEL_NewMoveToLastLinkLabel;
  87.  
  88.   // add navigation statistic parameters
  89.   paramObj.beforeFirst = MM.LABEL_RSNavBeforeFirst;
  90.   paramObj.beforeLast  = MM.LABEL_RSNavBeforeLast;
  91.   paramObj.beforeTotal = MM.LABEL_RSNavBeforeTotal;
  92.   paramObj.afterTotal  = MM.LABEL_RSNavAfterTotal;
  93.   paramObj.total = MM.LABEL_RSNavTotal;
  94.  
  95.   // insert content into master page, which is the currently open page
  96.   if (paramObj.PageSize)
  97.     extGroup.queueDocEdits("MasterPageNumRecs",paramObj,null);
  98.   else
  99.     extGroup.queueDocEdits("MasterPageAllRecs",paramObj,null);
  100.   dwscripts.applyDocEdits();
  101.  
  102.  
  103.   // create new or open existing detail page, and prep for insertion
  104.   createAndPrepDetailPage(detailPageName,detailPageAbsURL);
  105.  
  106.   // create unique name for the detail page recordset
  107.   // Note: the below line of code  *must* be placed at a point
  108.   // in the workflow where the Detail Page already has the focus.
  109.   paramObj.RecordsetName = getUniqueRecordsetName();
  110.  
  111.   // insert detail page content into detail page, which is currently open
  112.   extGroup.queueDocEdits("DetailPage",paramObj,null);
  113.   dwscripts.applyDocEdits();
  114.   createLiveDataSettings(); // allow detail page to be viewed with Live Data
  115.  
  116.   // switch focus back to Master Page
  117.   dw.openDocument(docURL);
  118.  
  119.  
  120.   return "";
  121.  
  122. }
  123.  
  124. //--------------------------------------------------------------------
  125. // FUNCTION:
  126. //   createLiveDataSettings
  127. //
  128. // DESCRIPTION:
  129. //   sets the recordID variable to 1 so that page can be previewed
  130. //   from within the application
  131. //
  132. // ARGUMENTS:
  133. //   none
  134. //
  135. // RETURNS:
  136. //   nothing
  137. //--------------------------------------------------------------------
  138. function createLiveDataSettings(detailPageObj)
  139. {
  140.   // NOTE: This is currently Cold Fusion specific
  141.   var str =  "#URL.recordID# = 1";
  142.   dw.setLiveDataParameters(str);
  143. }
  144.  
  145. //--------------------------------------------------------------------
  146. // FUNCTION:
  147. //   clickedOK
  148. //
  149. // DESCRIPTION:
  150. //   verifies data and alerts err msg if invalid.
  151. //   if valid, sets value of MM.cmdReturnValue to parameters and
  152. //   closes dialog
  153. //
  154. // ARGUMENTS:
  155. //   none
  156. //
  157. // RETURNS:
  158. //   an array of button names and function calls
  159. //--------------------------------------------------------------------
  160. function clickedOK()
  161. {
  162.  
  163.   var errMsg = "";
  164.   var detailPageName = _DetailPageName.getValue();
  165.   var masterPageName = dwscripts.getFileName(dw.getDocumentPath("document"));
  166.   var rsName = _RecordsetName.getValue();
  167.   var numRecs = _NumRecs.getValue();
  168.  
  169.   // check that all parameter values are valid
  170.  
  171.   // check detail page name
  172.   if (   !detailPageName || detailPageName.charAt(0) == " "
  173.       || detailPageName.indexOf("/") != -1 
  174.       || (detailPageName.indexOf(".") == 0) 
  175.       || (detailPageName.indexOf(".") == detailPageName.length - 1)
  176.      )
  177.   {
  178.     errMsg = MM.MSG_invalidDetailPageName;
  179.   }
  180.   
  181.   if (!errMsg)
  182.   {
  183.     if (   (detailPageName == masterPageName) 
  184.         || (masterPageName.indexOf(detailPageName + ".") == 0)
  185.        )
  186.     {
  187.       errMsg = MM.MSG_NeedUniqueDetailPageName;
  188.     }
  189.   }
  190.  
  191.   if (!errMsg) // check number of records validity
  192.   {
  193.     errMsg = _NumRecs.applyServerBehavior();
  194.   }
  195.   
  196.   if (!errMsg)
  197.   {
  198.     if (numRecs != "all")
  199.     {
  200.       var sbObj = sbUtils.getRepeatRegionWithPageNav(rsName, true);
  201.       if (sbObj != null)
  202.       {
  203.         errMsg = MM.MSG_RepeatRegionWithPageNavExists;
  204.       }
  205.     }
  206.   }
  207.  
  208.   if (!errMsg) // check that valid columns exist
  209.   {
  210.     var masterFields = _MasterPageFields.getValue();
  211.  
  212.     if((masterFields.length == 0) ||
  213.        (masterFields.length == 1 && masterFields[0].indexOf("MM_ERROR")!=-1))
  214.     {
  215.       errMsg = MM.MSG_columnsEmpty;
  216.     }
  217.   }
  218.  
  219.  
  220.   if (errMsg)
  221.   {
  222.     alert(errMsg);
  223.   }
  224.   else
  225.   {
  226.     paramObj = new Object();
  227.     paramObj.RecordsetName = _RecordsetName.getValue();
  228.     paramObj.MasterPageFields = _MasterPageFields.getValue();
  229.     paramObj.DetailPageFields = _DetailPageFields.getValue();
  230.     paramObj.LinkToField = _LinkField.getValue();
  231.     paramObj.UniqueIDField = _UniqueKeyField.getValue();
  232.     paramObj.DetailPageName = addExtensionToFileName(detailPageName);
  233.     paramObj.PageSize = (_NumRecs.getValue() =="all") ? "":_NumRecs.getValue();
  234.     paramObj.Numeric = _Numeric.getCheckedState();
  235.  
  236.     MM.cmdReturnValue.push(paramObj);
  237.  
  238.     window.close();
  239.   }
  240. }
  241.  
  242.  
  243.  
  244. //--------------------------------------------------------------------
  245. // FUNCTION:
  246. //   initializeUI
  247. //
  248. // DESCRIPTION:
  249. //   Prepare the dialog and controls for user input
  250. //
  251. // ARGUMENTS:
  252. //   none
  253. //
  254. // RETURNS:
  255. //   nothing
  256. //--------------------------------------------------------------------
  257. function initializeUI()
  258. {
  259.   var elts;
  260.  
  261.   _RecordsetName.initializeUI();
  262.   _MasterPageFields.initializeUI();
  263.   _LinkField.initializeUI();
  264.   _UniqueKeyField.initializeUI();
  265.   _NumRecs.initializeUI();
  266.   _DetailPageName.initializeUI();
  267.   _DetailPageFields.initializeUI();
  268.   _Numeric.initializeUI();
  269.  
  270.   elts = document.forms[0].elements;
  271.   if (elts && elts.length)
  272.     elts[0].focus();
  273. }
  274.  
  275.  
  276.  
  277. //-------------------------------------------------------------------
  278. // FUNCTION:
  279. //   displayHelp
  280. //
  281. // DESCRIPTION:
  282. //   displays appropriate help file
  283. //
  284. // ARGUMENTS:
  285. //   none
  286. //
  287. // RETURNS:
  288. //   nothing
  289. //--------------------------------------------------------------------
  290. function displayHelp()
  291. {
  292.   dwscripts.displayDWHelp();
  293. }
  294.  
  295.  
  296.  
  297. //--------------------------------------------------------------------
  298. // FUNCTION:
  299. //   updateUI
  300. //
  301. // DESCRIPTION:
  302. //   Called from controls to update the dialog based on user input
  303. //
  304. // ARGUMENTS:
  305. //   whatChanged -- string -- key for which UI element has been updated
  306. //
  307. // RETURNS:
  308. //   nothing
  309. //--------------------------------------------------------------------
  310. function updateUI(whatChanged)
  311. {
  312.   switch (whatChanged)
  313.   {
  314.  
  315.     case "masterFieldsLength":
  316.       var masterFieldsArr = _MasterPageFields.getValue();
  317.       var linkFieldsArr = _LinkField.listControl.list;
  318.  
  319.       if (masterFieldsArr.length != linkFieldsArr.length)
  320.       {
  321.         _LinkField.listControl.setAll(masterFieldsArr,masterFieldsArr);
  322.       }
  323.       break;
  324.  
  325.     default:
  326.       break;
  327.   }
  328. }
  329.  
  330.  
  331. //--------------------------------------------------------------------
  332. // FUNCTION:
  333. //   getUniqueRecordsetName
  334. //
  335. // DESCRIPTION:
  336. //   Returns a unique recordset name for the current document
  337. //
  338. // ARGUMENTS:
  339. //   none
  340. //
  341. // RETURNS:
  342. //   unique recordset name
  343. //--------------------------------------------------------------------
  344. function getUniqueRecordsetName()
  345. {
  346.   var dsNames = dwscripts.getRecordsetNames();
  347.   var nNames = dsNames.length;
  348.   var num = 0;
  349.   var uniqueName = false;
  350.   var rsName = ""
  351.  
  352.   while(!uniqueName)
  353.   {
  354.     num++;
  355.     rsName = "Recordset" + num;
  356.     uniqueName = true;
  357.     for (var i=0;i<nNames;i++)
  358.     {
  359.       if (dsNames.toLowerCase() == rsName.toLowerCase())
  360.       {
  361.         uniqueName = false;
  362.         break;
  363.       }
  364.     }
  365.   }
  366.  
  367.   return rsName;
  368. }
  369.  
  370.  
  371.  
  372. //-------------------------------------------------------------------
  373. // FUNCTION:
  374. //   addExtensionToFileName
  375. //
  376. // DESCRIPTION:
  377. //   Given a file name, check for a file extension, and add a
  378. //   file extension (server-specific) if one does not exist
  379. //
  380. // ARGUMENTS:
  381. //   fileName -- string, file name
  382. //
  383. // RETURNS:
  384. //   file name
  385. //--------------------------------------------------------------------
  386. function addExtensionToFileName(fileName)
  387. {
  388.   var retVal = fileName;
  389.   var hasExtension = (fileName.search(/\.\w+$/) != -1);
  390.  
  391.   if (!hasExtension)
  392.   {
  393.     var fileExtension = dwscripts.getFileExtension(dw.getDocumentDOM().URL)
  394.     retVal = fileName +"." + fileExtension;
  395.   }
  396.  
  397.   return retVal;
  398. }
  399.  
  400. // HE Note: This is modified from the original in Sam's file because I'm passing
  401. // in the entire filter; this makes it generic and easier to copy for multiple users.
  402. // function: editWhereClause -- would better be part of the SQL class
  403.  
  404. // SQL RELATED FUNCTIONS BELOW, should be moved
  405. // They belong in the main SQL function
  406.  
  407. var CONST_where = "WHERE";
  408. var CONST_and = "AND";
  409. var CONST_orderBy = "ORDER BY";
  410. var CONST_groupBy = "GROUP BY";
  411.  
  412. function buildNewSQLSource(sourceStr, index, clause, filter)
  413. {
  414.   var newSource;
  415.  
  416.   newSource = sourceStr.substr(0, index - 1) + " " + clause + " " + filter + " " + sourceStr.substr(index, sourceStr.length - index);
  417.  
  418.   return newSource;
  419.  
  420. }
  421.  
  422. function editWhereClause(SQLStatement,newFilter)
  423. {
  424.  
  425.    //var part = new Participant("recordset_sqlVar");
  426.    var sourceStr = SQLStatement
  427.    var filter = "";
  428.    var newSource = "";
  429.  
  430.    var paramObj = new Object();
  431.    // paramObj.rsName = rsName;
  432.    // paramObj.varName = varName;
  433.  
  434.    // filter = part.getInsertString(paramObj);
  435.  
  436.    // filter = colId + " = " + enclosingToken + filter + enclosingToken;
  437.  
  438.    filter = newFilter;
  439.    var re = new RegExp("\\bwhere\\b","gi");
  440.  
  441.    var index = sourceStr.search(re);
  442.  
  443.    if (index == -1) {
  444.      //The where clause was not found in the sql
  445.  
  446.        var reOrderBy = new RegExp("\\border\\sby\\b","gi");
  447.      var reGroupBy = new RegExp("\\bgroup\\sby\\b","gi");
  448.      var orderIndex = sourceStr.search(reOrderBy);
  449.      var groupIndex = sourceStr.search(reGroupBy);
  450.      if(groupIndex == orderIndex)
  451.      {
  452.          //This can only mean that the group by and order by clause both don't exist (index returns -1).
  453.          newSource = sourceStr + " " + CONST_where + " " + filter;
  454.      } else {
  455.  
  456.          var groupBoolean = new Boolean(false);
  457.  
  458.          // Either group by or order by or both clauses exist in the sql.
  459.        if((groupIndex > -1) && (orderIndex > -1)) {
  460.            // both clause's exist. Check which one has the least index value and insert the filter before it.
  461.          groupBoolean = (groupIndex < orderIndex);
  462.        } else {
  463.            //only one clause exists. Check which one has the greater index value and insert the filter before it.
  464.              groupBoolean = (groupIndex > orderIndex);
  465.        }
  466.        if(groupBoolean)
  467.           newSource = buildNewSQLSource(sourceStr, groupIndex, CONST_where, filter);
  468.        else
  469.           newSource = buildNewSQLSource(sourceStr, orderIndex, CONST_where, filter);
  470.      }
  471.    } else {
  472.        //The sql contains a where clause. We need to find out where it is and insert our filter just after it.
  473.      //The clause generated here will be the only where clause that is used.
  474.      newSource = sourceStr.substr(0, index) + " " + CONST_where + " " + filter;
  475.    }
  476.  
  477.    return newSource;
  478. }
  479.  
  480. //--------------------------------------------------------------------
  481. // FUNCTION:
  482. //   getUniqueRecordsetName
  483. //
  484. // DESCRIPTION:
  485. //   Returns a unique recordset name for the current document
  486. //
  487. // ARGUMENTS:
  488. //   none
  489. //
  490. // RETURNS:
  491. //   unique recordset name
  492. //--------------------------------------------------------------------
  493. function getUniqueRecordsetName()
  494. {
  495.   var dsNames = dwscripts.getRecordsetNames();
  496.   var nNames = dsNames.length;
  497.   var num = 0;
  498.   var uniqueName = false;
  499.   var rsName = ""
  500.  
  501.   while(!uniqueName)
  502.   {
  503.     num++;
  504.     rsName = "Recordset" + num;
  505.     uniqueName = true;
  506.     for (var i=0;i<nNames;i++)
  507.     {
  508.       if (dsNames[i].toLowerCase() == rsName.toLowerCase())
  509.       {
  510.         uniqueName = false;
  511.         break;
  512.       }
  513.     }
  514.   }
  515.  
  516.   return rsName;
  517. }
  518.  
  519. //--------------------------------------------------------------------
  520. // FUNCTION:
  521. //   getSQLStringForURLVariable
  522. //
  523. // DESCRIPTION:
  524. //   Returns url variable surrounded by appropriate delimiters
  525. //
  526. // ARGUMENTS:
  527. //   connName -- string, name of connection. Note: in CF, this is the data source name
  528. //   tableName -- string, name of table
  529. //   colName -- string, name of column
  530. //   varStr -- string, url variable for sql statement, e.g.: #URL.recordID#
  531. //
  532. //
  533. //
  534. // RETURNS:
  535. //   unique recordset name
  536. //--------------------------------------------------------------------
  537. function getSQLStringForURLVariable(connName,tableName,colName,varStr)
  538. {
  539.     var colAndTypes = MMDB.getColumnAndTypeOfTable(connectionName, tableName);
  540.     var nItems = colAndTypes.length;
  541.     var i;
  542.     var colType = "";
  543.     var retVal = colName;
  544.  
  545.     // find colName in colAndTypesArr
  546.     // note that colAndTypes is single dimensional array in form of
  547.     // column name, column type, etc.
  548.  
  549.     for (i=0;i<nItems;i+=2)
  550.     {
  551.       if (colAndTypes[i] == colName)
  552.       {
  553.         colType = colAndTypes[i+1];
  554.       }
  555.     }
  556.  
  557.     // hava: is colType number or string type? Will next clause work?
  558.     if (colType)
  559.     {
  560.       retVal = dwscripts.getSQLStringForDBColumnType(varStr,colType);
  561.     }
  562.     else
  563.     {
  564.       // this case should not be hit, but if it is, use no delimiters
  565.       retVal = varStr;
  566.     }
  567.  
  568.     return retVal;
  569.  
  570.  
  571. }
  572.  
  573. //--------------------------------------------------------------------
  574. // FUNCTION:
  575. //   getRecordsetParameters
  576. //
  577. // DESCRIPTION:
  578. //   Finds paramObj.RecordsetName in the current document, and adds all
  579. //   recordset related parameters to paramObj
  580. //   NOTE: Another way to do this would be use an explicit recordset
  581. //   copying method. hava: is one way preferable over another?
  582. //
  583. // ARGUMENTS:
  584. //   paramObj -- object to store parameters. Must include a property
  585. //   named "RecordsetName" with a valid recordset name.
  586. //   The recordset properties are added to paramObj. Note: this
  587. //   function will override existing paramObj properties of the same
  588. //   name.
  589. //
  590. // RETURNS:
  591. //   nothing. paramObj is passed by reference; return value not needed.
  592. //--------------------------------------------------------------------
  593. function getRecordsetParameters(paramObj)
  594. {
  595.   var sbRecs = dw.sbi.getServerBehaviors();
  596.   var nRecs = sbRecs.length;
  597.   var rsName = paramObj.RecordsetName;
  598.   var i;
  599.   var currRec = "";
  600.  
  601.   for (i=0;i<nRecs;i++)
  602.   {
  603.     currRec = sbRecs[i];
  604.     if (currRec.getName() == "Recordset" && currRec.getParameter("RecordsetName") == rsName)
  605.     {
  606.       rsParamObj = currRec.getParameters();
  607.       break;
  608.     }
  609.   }
  610.  
  611.   // add recordset parameters to paramObj
  612.   for (var i in rsParamObj)
  613.   {
  614.     paramObj[i] = rsParamObj[i];
  615.   }
  616. }
  617.  
  618.  
  619.  
  620.  
  621. // shamelessly copied -- only temporary to focus on major issues first
  622. // add to common dwscripts file? or at least to server behavior file
  623. // in any case, move it!
  624.  
  625. //Invokes dialog to allow user to select filename. Puts value in text input.
  626. // The optional flag stripParameters will remove anything after a question
  627. // mark if it is set to true
  628.  
  629. function browseFile(fieldToStoreURL, stripParameters)
  630. {
  631.   var fileName = "";
  632.   fileName = browseForFileURL();  //returns a local filename
  633.   if (stripParameters) {
  634.     var index = fileName.indexOf("?");
  635.     if (index != -1) {
  636.       fileName = fileName.substring(0,index);
  637.     }
  638.   }
  639.   if (fileName) fieldToStoreURL.value = fileName;
  640. }
  641.  
  642.  
  643. //--------------------------------------------------------------------
  644. // FUNCTION:
  645. //   createAndPrepDetailPage
  646. //
  647. // DESCRIPTION:
  648. //   Looks at detail page name to determine if it exists. Creates
  649. //   file for detail page if it does not already exist. Preps file
  650. //   in either case to ensure that future html insertion will not
  651. //   cause invalid html markup.
  652. //
  653. //
  654. // ARGUMENTS:
  655. //   detailPageName -- string
  656. //   detailPageAbsURL -- string -- detail page absolute path
  657. //   dom (optional) -- document object model for current document
  658. //
  659. //
  660. // RETURNS:
  661. //   nothing
  662. //--------------------------------------------------------------------
  663. function createAndPrepDetailPage(detailPageName,detailPageAbsURL,theDom)
  664. {
  665.   var detailPageExists = dwscripts.fileExists(detailPageAbsURL);
  666.   var detailPageIsOpen = detailPageExists && dwscripts.fileIsCurrentlyOpen(detailPageAbsURL);
  667.   var detailPageIsOpen = false;
  668.   var dom = (theDom)?theDom:dw.getDocumentDOM();
  669.  
  670.   if (detailPageExists)
  671.   {
  672.     dw.openDocument(detailPageAbsURL);
  673.     dom = dw.getDocumentDOM();
  674.  
  675.     if (detailPageIsOpen)
  676.     {
  677.       // move cursor from head, move outside of block tags
  678.       dwscripts.fixUpSelection(dom,false,false);
  679.     }
  680.       else
  681.     {
  682.       // if it was closed, move cursor to the end of the just-opened document
  683.       dwscripts.setCursorToEndOfBody(dom);
  684.     }
  685.   }
  686.  
  687.   else // create a new page to use as the detail page
  688.   {
  689.     dw.createDocument(false, _documentTypeID);
  690.     dom = dw.getDocumentDOM();
  691.     dw.saveDocument(dom,detailPageAbsURL);
  692.   }
  693. }
  694.  
  695.