// initial feature tests
    // Check that the library loaded
if (typeof LIB == 'object' &&
    LIB &&
    // Test for library functions I use directly
    LIB.isHostObject &&
    LIB.isHostMethod &&
    LIB.isHostCollection &&
    LIB.getAnElement &&
    LIB.getDocumentElement &&
    LIB.addListener &&
    LIB.preventDefault &&
    LIB.hasClass &&
    LIB.addClass &&
    LIB.removeClass &&
    LIB.querySelector &&
    LIB.filter &&
    LIB.forEach &&
    // Test for host objects and methods I use directly
    LIB.isHostObject(this, 'document') &&
    LIB.isHostMethod(this.document, 'write') &&
    LIB.isHostMethod(this.document, 'createTextNode') &&
    LIB.isHostMethod(this.document, 'createElement') &&
    (function() {
      var el = LIB.getAnElement();
      return LIB.isHostObject(el, 'style') &&
             typeof el.style.display == 'string' &&
             LIB.isHostMethod(el, 'appendChild') &&
             LIB.isHostMethod(el, 'insertBefore') &&
             LIB.isHostObject(el, 'firstChild') &&
             LIB.isHostCollection(el, 'childNodes') &&
             typeof el.innerHTML == 'string';
    })()) {

  (function() {
    
    var doc = this.document;
    
    // configuration
    var tabbedPaneCssUrl = 'tabbedPane.css',
        // optional depending on content of tabbed pane and 
        // desired printing effect.
        // tabbedPanePrintCssUrl = 'tabbedPanePrint.css',
        enabledTabbedPaneClassName = 'enabledTabbedPane',
        disabledTabbedPaneClassName = 'disabledTabbedPane',
        currentClassName = 'current',
        tabGroupTagName = 'ul',
        tabGroupClassName = 'tabs',
        tabTagName = 'li',
        defaultTabText = 'tab',
        paneTagName = 'div',
        tabbedPaneGroupClassName = 'sections',
        paneGroupTagName = 'div',
        tabbedPaneClassName = 'section',
        showPaneDisplay = 'block',
        hidePaneDisplay = 'none';

    var showPane = function(pane) {
      pane.style.display = showPaneDisplay;
      LIB.addClass(pane, currentClassName);
    };
    var hidePane = function(pane) {
      pane.style.display = hidePaneDisplay;
      LIB.removeClass(pane, currentClassName);
    };
    var makeTabCurrent = function(tab) {
      LIB.addClass(tab, currentClassName);
    };
    var makeTabNotCurrent = function(tab) {
      LIB.removeClass(tab, currentClassName);
    };
    
    var enliven = function(current, tab, pane) {
      LIB.addListener(tab, 'click', function(e) {
        LIB.preventDefault(e);
        
        // avoid potential flicker if user clicks the current tab
        if (tab == current.tab) {
          return;
        }
        makeTabNotCurrent(current.tab);
        hidePane(current.pane);
        current.tab = tab;
        current.pane = pane;
        makeTabCurrent(tab);
        showPane(pane);
      });
    };

    var init = function(widgetEl) {
      LIB.addClass(widgetEl, enabledTabbedPaneClassName);
      var tabs = doc.createElement(tabGroupTagName),
          first = true,
          current,
          tab,
          heading;
      LIB.addClass(tabs, tabGroupClassName);
      LIB.forEach(
        LIB.filter(
               widgetEl.childNodes,
               function(node) {
                 return LIB.hasClass(node, tabbedPaneClassName);
               }),
        function(pane) {
          tab = doc.createElement(tabTagName);
          if (first) {
            current = {tab:tab, pane:pane};
            makeTabCurrent(tab);
            showPane(pane);
            first = false;
          }
          else {
            hidePane(pane);
          }
          enliven(current, tab, pane);
          heading = LIB.querySelector('h2', pane)[0];
          tab.innerHTML = '<a href="#">' +
                          (heading ?
                            heading.innerHTML :
                            defaultTabText) +
                          '</a>';
          tabs.appendChild(tab);
        });
      widgetEl.insertBefore(tabs, widgetEl.firstChild);
    };

    // Test that a pane really appears and disappears.
    // This test uses a dummy tabbed pane temporarily 
    // inserted into the page. It is one of 
    // the largest granularity test possible to determine
    // the tabbed pane will work.
    // 
    // Tests that CSS is enabled, the necessary
    // CSS is supported and that there are no !important rules
    // that will interfere.
    var supportsDisplayCss = function() {
      var outer = doc.createElement(paneGroupTagName),
          inner = doc.createElement(paneTagName);

      if (LIB.isHostObject(doc, 'body') &&
          LIB.isHostMethod(doc.body, 'removeChild')) {

        LIB.addClass(outer, enabledTabbedPaneClassName);
        LIB.addClass(inner, tabbedPaneClassName);
        inner.innerHTML = '.';
        outer.appendChild(inner);
        doc.body.appendChild(outer);
        showPane(inner);
        var doesSupport;
        // wait until elements are attached
        // to the DOM before examining them.
        if (typeof outer.offsetHeight == 'number') {
          var height = outer.offsetHeight;
          hidePane(inner);
          doesSupport = (height > 0 && outer.offsetHeight == 0);
        }
        doc.body.removeChild(outer);
        return doesSupport;
      }
      return false;
    };

    // We don't know for sure at this point that the tabbed pane
    // will work. We have to wait for the DOM is ready to finish
    // the tests. We do know we can give the pages some style to use
    // during the page load because we can "get out of trouble"
    // when window.onload fires. This is
    // because the functions used to get out of trouble
    // have been feature tested.
    doc.write('<link href="'+tabbedPaneCssUrl+'"' +
              ' rel="stylesheet" type="text/css">');

    // optional depending on content of tabbed pane and 
    // desired printing effect.
    // doc.write('<link href="'+tabbedPanePrintCssUrl+'" media="print"' +
    //           ' rel="stylesheet" type="text/css">');

    // "this" refers to the window object.
    LIB.addListener(this, 'load', function() {
      // Cannot test that CSS support works until the DOM is ready.
      var widgetEls = LIB.querySelector('.'+tabbedPaneGroupClassName);
      if (supportsDisplayCss()) {
        LIB.forEach(widgetEls, init);
      }
      else {
        // "get out of trouble"
        LIB.forEach(widgetEls,
          function(el) {
            LIB.addClass(el, disabledTabbedPaneClassName);
          });
      }
    });

  })();
  
}
