home *** CD-ROM | disk | FTP | other *** search
/ Practical Internet Web Designer 86 / PIWD86.iso / pc / contents / dreamweaver / software / dwmx2004.exe / Disk1 / data1.cab / Configuration_En / Commands / ServerObject-MasterDetail.js < prev    next >
Encoding:
JavaScript  |  2003-09-05  |  19.6 KB  |  703 lines

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