Creating A Thdl Template Page For Off-site Use

THL Toolbox > Developers' Zone > Web Development > Creating a Template for Off-Site Use

Creating a THL Template for Off-Site Use with Ruby on Rails

Ruby on Rails apps run on a separate port than the standard HTML port 80. They are also sometimes developed on other servers such as Jefferson. Because Ruby on Rails apps are integrated systems, they cannot be used to output HTML which is then inserted in a THL page using AJAX and JQuery. Instead, a mechanism has been devised where the Ruby On Rails app reads a THL page template and uses the different parts of the template (header, side-column, etc.) to create the applications view.

Two things needs to be done to achieve this. First, a THL page that serves as a template much be created. This page has the appropriate banner, side-menu, etc. Second, the view rhtml pages of the app need to be configured to use this template.

Creating the Template Page

The template page, which resides in the appropriate place within the THL folder structure, needs to have a header and side menu with all the links in the navigation bar, side-menu, and site-map made absolute so that the Ruby on Rails app page can link to them. However, most of this is automated. What one needs to do is to create a special shell of a page in the appropriate part of the site.

An example is at: external link: http://staging.thdl.org/reference/dictionaries/tibetan-dictionary/dictionary-offsite.php

The template needs to be configured in the following ways:

1. Add a PHP $server Variable

At the top of the PHP template page, a variable needs to be set to the present server. The code is:

< ?php
    $droot = $_SERVER['DOCUMENT_ROOT']; 
    $server = $_SERVER['SERVER_NAME'];
? >;

This is used to insert the server name, whether it be "staging.thdl.org", "www.thlib.org", etc., into the page as a JavaScript variable.

2. Declare a JS variable called 'pgserv' in the $add_header

The PHP $server variable is then used in the $add_header section to declare a JS variable called 'pgserv' to be used by the Javascript in the page. This is coded as:

$add_header = … '< script type="text/javascript">var pgserv = "http://' . $server . '"< /script>' …;

The ellipses (…) above indicate that this may be only part of the $add_header declaration as is the case in the example page above.

Note: in the dictionary site, further JS was needed to ensure the proper functioning of the nav-bar buttons and the like. This was included in a separate script called external link: tibdictionarytemplate.js. The call to extra scripts also needs to be added to the header so that the full header definition becomes something like:

$add_header = … '< script type="text/javascript" src="/reference/dictionaries/tibetan-dictionary/js/tibdictionarytemplate.js">var pgserv = "http://' . $server . '"< /script>';&#xd;
$add_header .= … '< script type="text/javascript">var pgserv = "http://' . $server . '"< /script>';

3. Include a Modified Masthead in the Template File

In order to make the THL sitemap work a special version of the masthead-utility.php file needs to be used. This requires a separate version of the masthead for the template page. Rather than creating a separate masthead just for the template. It is more concise to copy the masthead used by other pages of that portal and paste it into the template in place of the include. That is, right after the open <body> tag.

In this masthead section, the masthead-utility include needs to be changed to the following:

< ? include_once "$droot/global/php/masthead-utility-offsite.php" ; ? >

Note: With the dictionary template, there were some irresolvable problems with the automatic side-column include parts of the PHP template page, which were only solved by actually pasting the side-column code into the template.

Using the Template in Ruby on Rails

The Ruby on Rails app uses parts of the template to build its view pages, through the THL Integration plug-in developed by Andres Montano.

The thdl_integration_plugin is well documented in the README file located at external link: http://ndlb.svn.sourceforge.net/svnroot/ndlb/portal/ror/plugins/thdl_integration/trunk/README

The suggested way of installing it is as an svn external:

script/plugin install -x external link: https://ndlb.svn.sourceforge.net/svnroot/ndlb/portal/ror/plugins/thdl_integration/trunk

since it is expected to change as the thl template gets refined, and that way you will always get the latest changes. For your case it is a bit different because you want to point to a different template. Not designed great, the URL is simply hardcoded in the external link: https://ndlb.svn.sourceforge.net/svnroot/ndlb/portal/ror/plugins/thdl_integration/trunk/lib/helpers/thdl_integration_helper.rb file under the load_attributes method. One cannot change svn externals.

One thing I can do to keep the design clean is for the plugin expect a method in application_helper.rb such as template_url (just as it expects there to be there the side_column_links, stylesheets and javascripts methods).

Remember that the custom side_column_links, stylesheets and javascripts are set dynamically. Especially with the side_column_links they were designed like that to display different links depending on the state of the application (user logged in or not, etc). So are the attributes to body (to highlight the correct tab through the html class attribute). I guess the only reason you would need a separate template is for banner. Or is there something else different about the template? Maybe we can simply just load the banner dynamically too to eliminate the need to have different templates.

The plug-in is installed by executing the following command in the Ruby on Rails app:

Once the plug-in is installed the URL is simply hardcoded in the external link: helpers/thdl_integration_helper.rb file under the load_attributes method. However, the plug-in does not make a URL call directly to the template location. The template needs to be "fed through" a PHP script that absolutizes all the URLs. An example of the call that plug-in would use is:

The documentation for the plug-in is at external link: external link: http://ndlb.svn.sourceforge.net/svnroot/ndlb/portal/ror/plugins/thdl_integration/trunk/README.

How to Use the Template within Ruby on Rails

From the Ruby on Rails side, the programmer has to use the gem "hpricot". Using the hpricot gem, one creates helper functions that target parts of the template page and return it to the layout in Ruby on Rails. An example of this is:

&#x20;&#x20;def get_content(url)&#xd;
&#x20;&#x20;&#x20;&#x20;begin&#xd;
&#x20;&#x20;&#x20;&#x20;doc = Hpricot(open(url))&#xd;
&#x20;&#x20;&#x20;&#x20;yield doc&#xd;
&#x20;&#x20;&#x20;&#x20;rescue Errno::EHOSTUNREACH&#xd;
&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;"Can't connect to #{url}"&#xd;
&#x20;&#x20;&#x20;&#x20;rescue Errno::ETIMEDOUT&#xd;
&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;"Can't connect to #{url}"&#xd;
&#x20;&#x20;&#x20;&#x20;rescue SocketError&#xd;
&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;"Can't connect to #{url}"     &#xd; 
&#x20;&#x20;&#x20;&#x20;end&#xd;
&#x20;&#x20;end&#xd;&#xd;

&#x20;&#x20;def menu1&#xd;
&#x20;&#x20;&#x20;&#x20;get_content('http://staging.thdl.org/global/php/offsite.php?url=/reference/dictionaries/tibetan-dictionary/dictionary-template.php') do |document|&#xd;
&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;content = document.at("//div[@id=thdlmenu-link-1]")&#xd;
&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;content.to_html&#xd;
&#x20;&#x20;&#x20;&#x20;end&#xd;
&#x20;&#x20;end&#xd;&#xd;
  
&#x20;&#x20;def menu1content&#xd;
&#x20;&#x20;&#x20;&#x20;get_content('http://staging.thdl.org/global/php/offsite.php?url=/reference/dictionaries/tibetan-dictionary/dictionary-template.php') do |document|&#xd;
&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;content = document.at("//div[@id=highslide-html-1]")&#xd;
&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;content.to_html&#xd;
&#x20;&#x20;&#x20;&#x20;end&#xd;
&#x20;&#x20;end&#xd;

This is included in the layout for the Ruby on Rails app in the following way:

<!-- THDL Sitemap -->&#xd;
<%= menu1 %>&#xd;
<%= menu1content %>&#xd;

Note: When this was done for the Tibetan Dictionary, the HTML <head> has to be fully coded within Ruby on Rails so that it can include the Javascript include necessary for the app, i.e. <%= javascript_include_tag :defaults %> .

Issues with Ruby on Rails Apps

Side-Column

With Ruby on Rails apps, one wants the side-column to be hidden by default. To do so, one has to include specific JS code within the app to hide the side-column upon loading the page. This code is:

document.observe("dom:loaded", function(){&#xd;
&#x20;&#x20;$('fxSideMenu').hide();&#xd;
});

Wikis

Wiki links in side-columns etc for Ruby on Rails apps will only load when the root domain for the app and the rest of the site is the same. This is because the Ajax call to load the wiki page calls upon a PHP page on the THL site (www.thlib.org). The root domain is the last portion of the URL (thlib.org). For instance, the knowledge maps app URL is external link: http://tmb.thlib.org. It's root domain is thus "thlib.org", which matches the site, and the wikis will load. On the staging version of the app (external link: http://staging.tmb.thdl.org), the root domain does not match the rest of the site and the Ajax calls to wikis will fail. For the Ajax calls to be actually triggered, the class_external.js file needs to be included in the web-pages for the app, which, if the THL template is being used, happens automatically.

Alternative Method for Implementing Ruby On Rails With a New THL Template

This method was proposed by Matt Mitchell and has not been evaluated for effectiveness.

I did find a way to wrap the contents of any Rails page into the THL layout. I’ve posted the code below - really didn’t spend too much time on it. And I’m not even sure how the remote php template is supposed to work. What kinds of problems are you guys having?

One solution would be to provide a very simple re-usable template that would just provide the basic THL, look-and-feel. No java-script, but basic CSS/images. That way each of the applications that are using the template could still have the THL look, but the method of building the page wouldn’t have to be so complicated and fragile. Also, there may be times when the template’s java-script (and even css) could cause problems within the applications. Just a basic shell seems ideal?

For this code to work… You need to specify a layout in your application controller:

ApplicationController < ActionController::Base&#xd;
&#x20;&#x20;layout ‘main’ # for example&#xd;
end&#xd;

Put this in your helpers/application.rb helper:

require 'net/http'&#xd;
require 'uri'&#xd;&#xd;

def thdl_wrap(content)&#xd;
&#x20;&#x20;Net::HTTP.get(&#xd;
&#x20;&#x20;&#x20;&#x20;URI.parse(&#xd;
&#x20;&#x20;&#x20;&#x20;&#x20;&#x20;'http://staging.thdl.org/global/php/offsite.php?url=/reference/dictionaries/tibetan-dictionary/dictionary-template.php'&#xd;
&#x20;&#x20;&#x20;&#x20;)&#xd;
&#x20;&#x20;).sub(/&lt;p&gt;Content here&lt;/p&gt;/, content)&#xd;
end&#xd;

And finally, in your layouts/main.rhtml file:

<%= thdl_wrap(yield) %>

Provided for unrestricted use by the external link: Tibetan and Himalayan Library