Sample Three: URL Title Search

This sample script searches for specific words in the Title field of all items the user has privileges to view within the Issues table. This sample can only be used in the URL context. The URL Title Search Results dialog box displays the results of this script.

image

Note: To use this script, you must add it to SBM using the Scripts editor in SBM Composer. Make sure that you remove any arrows that are used to indicate line breaks first.

Title Search Script Contents

' SBM ModScript Example: SearchTitle.tscm

/*  ModScript Example: SearchTitle.tscm
    -----------------------------------
    Perform a search specified by the URL,
    display hyperlinked list of resulting
    items.
  
    Requirements:
    This script is designed for URL context, in which
    the user enters a URL specifying the desired search.
    Note that a user-friendly HTML form could generate
    the URL from a user-supplied search string.
  
    Sample URL:
    To search for Issues whose titles contain "monkey",
      "http://...tmtrack.dll?ScriptPage&scriptName=SearchTitle&find=monkey"
      (where "..." is replaced by your system's path to the SBM IIS DLL) */

//  MODIFY THESE CONSTANTS FOR YOUR DATABASE
//  ----------------------------------------
add_global_const( "Issues", "TBL_NAME" ); // add a global constant called "TBL_NAME" 
with the value "Issues". The keyword "global" could also be used, but then the 
value is not constant
add_global_const( "TS_TITLE", "COL_NAME" ); // add a global constant called "COL_NAME" 
with the value "TS_TITLE".


//  Use SQL to find findMe in title column of Issues table
//  Resulting list goes into global itemList
//  Return true for successful SQL operation, false for failure
def getItemList() {
  itemList = Ext.CreateAppRecordList( tableID );
  sqlWhereClause = COL_NAME &&& " like '%" &&& findMe &&& "%'";
  return itemList.ReadWithWhere( sqlWhereClause );
}

//  Generate HTML for entire body of result page
def resultHTML() {
  var numItems = itemList.Length();

  //  Heading shows search string and # items found
  Ext.WriteStream( "<h1>Search Results</h1>" &&& "<p>Found " &&& numItems &&& " " &&& 
(numItems == 1 ? "item" : "items") &&& " containing <b>" &&& 
 Ext.EncodeHTML( findMe ) &&& "</b></p>" );

  //  HTML "definition list" (<dl>) containing an entry for each found item
  Ext.WriteStream( "<dl>" );
  for ( item : itemList ) {
    itemHTML ( item );
  }
  Ext.WriteStream( "</dl>" );
}

def itemHTML( item ) {
  //  Generate <dt> element as the title of this list entry
  Ext.WriteStream( "<dt><a href='tmtrack.dll?View&T=" &&& tableID &&& "&I=" &&&
item.GetId() &&& "' target='srch_detail'>" &&& 
Ext.EncodeHTML( item.GetDisplayIssueId() ) &&& "</a></dt>" );

  //  Generate <dd> element for each field to be listed for this entry
  textFldHTML ( item, "Title" );
  selFldHTML ( item, "State" );
  textFldHTML ( item, "Description" );
  Ext.WriteStream( "<p></p>" );
}

def textFldHTML( item, fldName ) {
  var fldVal = Variant(); // since fields can have lots of different data types, we can only 
get their value as a Variant. When passing a var as an output-parameter to a function 
that takes a Variant, we need to ensure we create a Variant to pass in.
  if ( !( item.GetFieldValue( fldName, fldVal )  )) { fldVal = "[none]"; }
  Ext.WriteStream( "<dd>" &&& Ext.EncodeHTML( fldName ) &&& ": " &&&
Ext.EncodeHTML( fldVal ) &&& "</dd>" );
}

//  Generate HTML for a selection field's name and value
def selFldHTML( item, fldName ) {
  var fldObj = item.Fields().FindField( fldName );
  var fldVal = Variant(); // since fields can have lots of different data types, we can only 
get their value as a Variant. When passing a var as an output-parameter to a function that 
takes a Variant, we need to ensure we create a Variant to pass in.
  if ( fldObj.is_var_null() ) {
    fldVal = "[none]";
  } else {
    fldObj.GetDisplayValue( fldVal );
  }
  Ext.WriteStream( "<dd>" &&& Ext.EncodeHTML( fldName ) &&& ": " &&& 
Ext.EncodeHTML( fldVal ) &&& "</dd>" );
}

//  Generate HTML for an error page (search did not execute)
def errorHTML() {
  Ext.WriteStream( "<h1>SQL Error</h1><p>Unable to search for <b>" &&&
Ext.EncodeHTML( findMe ) &&& "</b></p>" 
&&& "<p>SQL \"where\" clause:<br><b>" &&& 
Ext.EncodeHTML( sqlWhereClause ) &&& "</b></p>" );
}

//  Start the HTML, take care of entire <head>, open the <body>
def openHTML() {
  Ext.WriteStream( "<html><head><title>Title Search for \"" &&&
Ext.EncodeHTML( findMe ) &&& "\" in " 
&&& TBL_NAME &&& " table</title></head><body>" );
}

//  End the <body> and the page
def closeHTML() {
  Ext.WriteStream( "</body></html>" );
}

//  Declare all vars
//  Several subroutines below will use these global vars
global findMe;
global tableID;
global itemList;
global sqlWhereClause;

if ( Shell.Context() == "URL" ) {
  //  Get params
  findMe = Shell.Params().Item( "find" );
  tableID = Ext.TableId( TBL_NAME, "display" );
  //  Build the HTML page
  openHTML();
  if ( getItemList() ) {
    resultHTML();
  } else {
    errorHTML();
  }
  closeHTML();
}
else {
  //  They are running this in the wrong context (e.g., post-transition)
  Ext.LogErrorMsg( "ModScript error: this script must run in URL context." );
}