Template Examples

(as of 27 February 2006)

Search Results Page

Here is an example template that could be used to format a Google search results page:


{{>HEADER}}
<body bgcolor=white>

{{>PAGE_HEADING}}{{!The following div must be on the same line}}<div>

{{!The ONE_RESULT section displays a single search item}}
{{#ONE_RESULT}}
    {{! Note: there are two SUBITEM_SECTIONs. They both show or hide together}}
    {{#SUBITEM_SECTION}}<blockquote>{{/SUBITEM_SECTION}}
    <p><a href={{JUMP_TO_URL:html_escape}}  target=nw>{{LEAD_LINE}}</a><font size=-1>

    {{#SNIPPET1_SECTION}}
        <br>{{SNIPPET1}}
    {{/SNIPPET1_SECTION}}

    {{#SNIPPET2_SECTION}}
        <br>{{SNIPPET2}}
    {{/SNIPPET2_SECTION}}

    {{#DESCRIPTION_SECTION}}
        <br><span class=f>Description:</span> {{DESC}}
    {{/DESCRIPTION_SECTION}}

    {{#CATEGORY_SECTION}}
        <br><span class=f>Category:</span> <a href={{CAT_URL:html_escape}} class=f>
	{{CATEGORY}}</a>
    {{/CATEGORY_SECTION}}

    {{#LASTLINE_SECTION}}
        <br><font color={{ALT_TEXT_COLOR}}>{{URL}}
        {{#KS_SECTION}}} - {{KSIZE}}{{/KS_SECTION}}}
        {{#CACHE_SECTION}}} - <a href={{CACHE_URL:html_escape}} class=f>Cached</A>
	{{/CACHE_SECTION}}}
        {{#SIM_SECTION}}} - <a href={{SIM_PAGES_URL:html_escape}} class=f>Similar pages</A>
	{{/SIM_SECTION}}}

        {{#STOCK_SECTION}}
             -  <a href={{STOCK_URL:html_escape}} class=f>Stock quotes: {{STOCK_SYMBOL}}</a>
        {{/STOCK_SECTION}}
        </font>
    {{/LASTLINE_SECTION}}           

    {{#MORE_SECTION}}
        <br>[ <a href={{MORE_URL:html_escape}} class=f>More results from {{MORE_LABEL}}</a> ]
    {{/MORE_SECTION}}

    </font><br>
    {{! Note: there are two SUBITEM_SECTIONs. They both show or hide together}}
    {{#SUBITEM_SECTION}}</blockquote>{{/SUBITEM_SECTION}}
{{/ONE_RESULT}}
</div> {{! this /div closes the div at the top of this file}}
{{>PAGE_FOOTING}}

Here is a sample procedure that could populate a dictionary for expanding that template. The "one procedure" entry point is fill_search_results_dictionary. The SetTemplateValues function is a separate entry point for initializing each top-level template with some standard values.

#include "template.h"

RegisterTemplateFilename(SEARCH_RESULTS_FN, "search_results.tpl");
#include "search_results.tpl.varnames.h"  // defines ksr_HEADER, etc.

using google::Template;
using google::TemplateDictionary;
using google::STRIP_WHITESPACE;

// IsEmpty
//    A simple utility function
static bool IsEmpty(const string &str) {
  return str.empty();
}

// SetTemplateValues
//   Use the TemplateDictionary object to set template-wide values that
//   may be used in the top-level template and all its sub-sections
//   and included templates. The template-wide values are all
//   colors from the Palette object
void SetTemplateValues(TemplateDictionary *dictionary, const Palette* colors) {
  // better would be to use ksr_LINK_COLOR, etc, assuming those are
  // defined in search_results.tpl.varnames.h.  But using literal
  // text, as here, is legal as well.
  dictionary->SetValue("LINK_COLOR", colors->link_color);
  dictionary->SetValue("BAR_TEXT_COLOR", colors->bar_text_color);
  dictionary->SetValue("TEXT_COLOR", colors->text_color);
  dictionary->SetValue("FAINT_COLOR", colors->faint_color);
  dictionary->SetValue("IMPORTANT_COLOR", colors->important_color);
  dictionary->SetValue("BAR_COLOR", colors->bar_color);
  dictionary->SetValue("ALT_TEXT_COLOR", colors->alt_text_color);
  dictionary->SetValue("ALINK_COLOR", colors->alink_color);
  dictionary->SetValue("VLINK_COLOR", colors->vlink_color);
}

// fill_search_results_dictionary
//   Iterates through all the QueryResults contained in the Query object.
//   For each one, it sets corresponding template dictionary values
//   (or hides sections containing their variables, if appropriate) in
//   a sub-dictionary and then adds that dictionary to the parent
void fill_search_results_dictionary(TemplateDictionary *dictionary,
                                    const Query *query) {
  dictionary->SetFilename(SEARCH_RESULTS_FN);

  // These two functions are defined elsewhere
  fill_header_dictionary(dictionary->AddIncludeDictionary(ksr_HEADER));
  fill_page_heading_dictionary(dictionary->AddIncludeDictionary(ksr_PAGE_HEADING),
                               query);

  ResultsList *results = query->GetResults();
  int resCount = 0;

  for (ResultsList::const_iterator iter = results->begin();
       iter != results->end();
       ++iter) {
    QueryResult *qr = (*iter);

    // Create a new sub-dictionary named "Result Dict " for this entry

    ++resCount;

    TemplateDictionary *result_dictionary =
      dictionary->AddSectionDictionary(ksr_ONE_RESULT);

    result_dictionary->SetValue(ksr_JUMP_TO_URL, qr->GetUrl());

    if (qr->IsSubItem()) {
      result_dictionary->ShowSection(ksr_SUBITEM_SECTION);
    }

    result_dictionary->SetValue(ksr_LEAD_LINE, qr->GetLeadLine());

    result_dictionary->SetValueAndShowSection(ksr_SNIPPET1, qr->GetSnippet1(),
                                              ksr_SNIPPET1_SECTION);
    
    result_dictionary->SetValueAndShowSection(ksr_SNIPPET2, qr->GetSnippet2(),
                                              ksr_SNIPPET2_SECTION);
    
    result_dictionary->SetValueAndShowSection(ksr_DESC, qr->GetDescription(),
                                              ksr_DESCRIPTION_SECTION);

    result_dictionary->SetValueAndShowSection(ksr_CAT_URL, qr->GetCategoryUrl(),
                                              ksr_CATEGORY_SECTION);

    result_dictionary->SetValueAndShowSection("CATEGORY", qr->GetCategoryName(),
                                              "CATEGORY_SECTION");


    if (IsEmpty(qr->GetDisplayUrl()) &&
        IsEmpty(qr->GetPageSize()) &&
        IsEmpty(qr->GetCachedUrl()) &&
        IsEmpty(qr->GetSimilarPagesUrl()) &&
        (IsEmpty(qr->GetStockUrl()) ||
         IsEmpty(qr->GetStockSymbol())) ) {
      // there is nothing on the last line, so hide it altogether
    } else {
      result_dictionary->ShowSection("LASTLINE_SECTION");

      result_dictionary->SetValue(ksr_URL, qr->GetDisplayUrl());

      result_dictionary->SetValueAndShowSection(ksr_KSIZE, qr->GetPageSize(),
                                                ksr_KS_SECTION);

      result_dictionary->SetValueAndShowSection(ksr_CACHE_URL, qr->GetCachedUrl(),
                                                ksr_CACHE_SECTION);

      result_dictionary->SetValueAndShowSection(ksr_SIM_PAGES_URL,
                                                qr->GetSimilarPagesUrl(),
                                                ksr_SIM_SECTION);

      result_dictionary->SetValueAndShowSection(ksr_STOCK_URL, qr->GetStockUrl(),
                                                ksr_STOCK_SECTION);

      result_dictionary->SetValueAndShowSection(ksr_STOCK_SYMBOL,
                                                qr->GetStockSymbol(),
                                                ksr_STOCK_SECTION);
    }

    result_dictionary->SetValueAndShowSection(ksr_MORE_URL, qr->GetMoreUrl(),
                                              ksr_MORE_SECTION);

    result_dictionary->SetValueAndShowSection(ksr_MORE_LABEL, qr->GetMoreLabel(),
                                              ksr_MORE_SECTION);

  }    

  fill_page_footing_dictionary(dictionary->AddIncludeDictionary(ksr_PAGE_FOOTING),
                               query);
}        

void output_page(const Query* query) {
  Template* tpl = Template::GetTemplate(SEARCH_RESULTS_FN, STRIP_WHITESPACE);
  TemplateDictionary dict("search-results dict");
  string output;
  fill_search_results_dictionary(&dict, query);
  tpl->Expand(&output, &dict);
  // output now holds the expanded template
}



Craig Silverstein
27 February 2006